AlliedModders

AlliedModders (https://forums.alliedmods.net/index.php)
-   Scripting Help (https://forums.alliedmods.net/forumdisplay.php?f=43)
-   -   Superheromod.sma need help (https://forums.alliedmods.net/showthread.php?t=255148)

aaa131 01-11-2015 08:22

Superheromod.sma need help
 
I want to compile this source. But .inc files must imported in the Superheromod.sma source code but couldn't do it. Can someone help me?

I need combine all include files in one source

Can someone help me?
Thank you. (and sorry for my bad english)


This is Superheromod.sma:
Code:

// XP Saving Method
// **Make sure only ONE is uncommented**
//#define SAVE_METHOD 1                //Saves XP to vault.ini (Note: Use also for non-save xp to avoid loading extra modules)
#define SAVE_METHOD 2                //Saves XP to superhero nVault (default)
//#define SAVE_METHOD 3                //Saves XP to a MySQL database


//By default, plugins have 4KB of stack space.
//This gives the plugin a little more memory to work with (6144 or 24KB is sh default)
#pragma dynamic 6144

//Sets the size of the memory table to hold data until the next save
#define gMemoryTableSize 64

//Amount of heroes at a time to display in the amx_help style console listing
#define HEROAMOUNT 10

//Lets includes detect if the core is loading them or a hero
#define SHCORE

#include <amxmodx>
#include <amxmisc>
#include <superheromod>

new const SH_CORE_STR[] =  "SuperHero Core"

// Parms Are: Hero, Power Description, Help Info, Needs A Bind?, Level Available At
enum enumHeros { hero[25], superpower[50], help[128], requiresKeys, availableLevel }

// The Big Array that holds all of the heroes, superpowers, help, and other important info
new gSuperHeros[SH_MAXHEROS][enumHeros]
new gSuperHeroCount = 0

// Changed these from CVARS to straight numbers...
new gHeroMaxSpeed[SH_MAXHEROS]
new gHeroSpeedWeapons[SH_MAXHEROS][31] // array weapons of weapon's i.e. {4,30} Note:{0}=all
new gHeroMaxHealth[SH_MAXHEROS]
new gHeroMinGravity[SH_MAXHEROS]
new gHeroMaxArmor[SH_MAXHEROS]
new bool:gHeroShieldRest[SH_MAXHEROS]
new gHeroLevelCVAR[SH_MAXHEROS]
new gHeroMaxDamageMult[SH_MAXHEROS][31]

//CVARS to be loaded into variables
new bool:gAutoBalance
new bool:gLongTermXP = true
new bool:gObjectiveXP = true
new gCMDProj = 0

// Player Variables Used by Various Functions
// Player IDS are base 1 (i.e. 1-32 so we have to diminsion for 33)
new gPlayerPowers[SH_MAXSLOTS+1][SH_MAXLEVELS+1]      // List of all Powers - Slot 0 is the superpower count
new gPlayerBinds[SH_MAXSLOTS+1][SH_MAXBINDPOWERS+1]  // What superpowers are the bind keys bound
new gPlayerFlags[SH_MAXSLOTS+1]
new gPlayerMenuOffset[SH_MAXSLOTS+1]
new gPlayerMenuChoices[SH_MAXSLOTS+1][SH_MAXHEROS+1]  // This will be filled in with # of heroes available
new gMaxPowersLeft[SH_MAXSLOTS+1][SH_MAXLEVELS+1]
new gCurrentWeapon[SH_MAXSLOTS+1]
new gCurrentFOV[SH_MAXSLOTS+1]
new gPlayerStunTimer[SH_MAXSLOTS+1]
new Float:gPlayerStunSpeed[SH_MAXSLOTS+1]
new gPlayerGodTimer[SH_MAXSLOTS+1]
new gPlayerStartXP[SH_MAXSLOTS+1]
new gPlayerLevel[SH_MAXSLOTS+1]
new gPlayerXP[SH_MAXSLOTS+1]
new gXPLevel[SH_MAXLEVELS+1]
new gXPGiven[SH_MAXLEVELS+1]
new bool:gNewRoundSpawn[SH_MAXSLOTS+1]
new bool:gIsPowerBanned[SH_MAXSLOTS+1]
new bool:gInMenu[SH_MAXSLOTS+1]
new bool:gReadXPNextRound[SH_MAXSLOTS+1]
new bool:gFirstRound[SH_MAXSLOTS+1]
new bool:gShieldRestrict[SH_MAXSLOTS+1]
new bool:gBlockMercyXp[SH_MAXSLOTS+1]
new Float:gReloadTime[SH_MAXSLOTS+1]
new gInPowerDown[SH_MAXSLOTS+1][SH_MAXBINDPOWERS+1]
new bool:gChangedHeroes[SH_MAXSLOTS+1]
new gMaxHealth[SH_MAXSLOTS+1]
new gMaxArmor[SH_MAXSLOTS+1]
new bool:gPlayerPutInServer[SH_MAXSLOTS+1]
new gXpBounsVIP
//new Float:gLastKeydown[SH_MAXSLOTS+1]

// Other miscellaneous global variables
new gHelpHudMsg[340]
new gmsgStatusText, gmsgScoreInfo, gmsgDeathMsg, gmsgDamage
new gmsgSayText, gmsgTeamInfo
new bool:gRoundFreeze
new bool:gRoundStarted
new bool:gBetweenRounds
new bool:gGiveMercyXP = true
new gNumLevels = 0
new gMaxPowers = 0
new gMenuID = 0
new gNumHostages = 0
new gXpBounsC4ID = -1
new gHelpHudSync, gHeroHudSync
new bool:gMapBlockWeapons[31]        //1-30 CSW_ constants
new bool:gXrtaDmgClientKill
new gServersMaxPlayers
new gXrtaDmgWpnName[32]
new gXrtaDmgAttacker
new gXrtaDmgHeadshot
new bool:gIsCzero
new bool:gCZBotRegisterHam
new bool:gMonsterModRunning

//Memory Table Variables
new gMemoryTableCount = 33
new gMemoryTableKeys[gMemoryTableSize][32]                                // Table for storing xp lines that need to be flushed to file...
new gMemoryTableNames[gMemoryTableSize][32]                                // Stores players name for a key
new gMemoryTableXP[gMemoryTableSize]                                        // How much XP does a player have?
new gMemoryTableFlags[gMemoryTableSize]                                        // User flags for other settings (see below)
new gMemoryTablePowers[gMemoryTableSize][SH_MAXLEVELS+1]                // 0=# of powers, 1=hero index, etc...

//Config Files
new gSHConfigDir[128], gBanFile[128], gSHConfig[128], gHelpMotd[128]

//PCVARs
new sv_superheros, sh_adminaccess, sh_alivedrop, sh_autobalance, sh_objectivexp
new sh_cmdprojector, sh_debug_messages, sh_endroundsave, sh_hsmult, sh_loadimmediate, sh_lvllimit
new sh_maxbinds, sh_maxpowers, sh_menumode, sh_mercyxp, sh_mercyxpmode, sh_minlevel
new sh_savexp, sh_saveby, sh_xpsavedays, sh_minplrsbhxp, sh_reloadmode, sh_blockvip, sh_ffa
new mp_friendlyfire, sv_maxspeed, sv_lan, bot_quota

//Forwards
new fwdReturn
new fwd_HeroInit, fwd_HeroKey, fwd_Spawn, fwd_Death
new fwd_RoundStart, fwd_RoundEnd, fwd_NewRound

#if defined SH_BACKCOMPAT
//Old global variables, required for backward compat
new gEventInit[SH_MAXHEROS][20]
new gEventKeyDown[SH_MAXHEROS][20]
new gEventKeyUp[SH_MAXHEROS][20]
new gEventMaxHealth[SH_MAXHEROS][20]
new gEventLevels[SH_MAXHEROS][20]  // Holds server functions to call when a person levels...
#endif

//Level up sound
new const gSoundLevel[] = "plats/elevbell1.wav"

//Used to reset players team for colored text
new const gTeamName[4][] =  {
        "",
        "TERRORIST",
        "CT",
        "SPECTATOR"
}

//==============================================================================================
// XP Saving Method, do not modify this here, please see the top of the file.
#if SAVE_METHOD == 1
        #include <superherovault>        //Saves XP to vault.ini
#endif

#if SAVE_METHOD == 2
        #include <superheronvault>        //Saves XP to superhero nVault (default)
#endif

#if SAVE_METHOD == 3
        #include <superheromysql>        //Saves XP to a MySQL database
#endif
//==============================================================================================

//----------------------------------------------------------------------------------------------
public plugin_init()
{
        // Check to make sure this plugin isn't loaded already
        if ( is_plugin_loaded(SH_CORE_STR) > 0 ) {
                set_fail_state("You can only load the ^"SuperHero Core^" once, please check your plugins-shero.ini")
        }

        // Plugin Info
        register_plugin(SH_CORE_STR, SH_VERSION_STR, "JTP10181/{HOJ}Batman/vittu/AssKicR")
        register_cvar("SuperHeroMod_Version", SH_VERSION_STR, FCVAR_SERVER|FCVAR_SPONLY)
        set_cvar_string("SuperHeroMod_Version", SH_VERSION_STR)        // Update incase new version loaded while still running

        debugMsg(0, 1, "plugin_init - Version: %s", SH_VERSION_STR)

        // Menus
        gMenuID = register_menuid("Select Super Power")
        new menukeys = MENU_KEY_1|MENU_KEY_2|MENU_KEY_3|MENU_KEY_4|MENU_KEY_5|MENU_KEY_6|MENU_KEY_7|MENU_KEY_8|MENU_KEY_9|MENU_KEY_0
        register_menucmd(gMenuID, menukeys, "selectedSuperPower")

        // CVARS
        // DO NOT EDIT THIS FILE TO CHANGE CVARS, USE THE SHCONFIG.CFG
        sv_superheros = register_cvar("sv_superheros", "1")
        sh_adminaccess = register_cvar("sh_adminaccess", "m")
        sh_alivedrop = register_cvar("sh_alivedrop", "0")
        sh_autobalance = register_cvar("sh_autobalance", "0")
        sh_objectivexp = register_cvar("sh_objectivexp", "8")
        sh_cmdprojector = register_cvar("sh_cmdprojector", "1")
        sh_endroundsave = register_cvar("sh_endroundsave", "1")
        sh_hsmult = register_cvar("sh_hsmult", "1.0")
        sh_loadimmediate = register_cvar("sh_loadimmediate", "0")
        sh_lvllimit = register_cvar("sh_lvllimit", "1")
        sh_maxbinds = register_cvar("sh_maxbinds", "3")
        sh_maxpowers = register_cvar("sh_maxpowers", "20")
        sh_menumode = register_cvar("sh_menumode", "1")
        sh_mercyxp = register_cvar("sh_mercyxp", "0")
        sh_mercyxpmode = register_cvar("sh_mercyxpmode", "1")
        sh_minlevel = register_cvar("sh_minlevel", "0")
        sh_savexp = register_cvar("sh_savexp", "1")
        sh_saveby = register_cvar("sh_saveby", "1")
        sh_xpsavedays = register_cvar("sh_xpsavedays", "14")
        sh_reloadmode = register_cvar("sh_reloadmode", "1")
        sh_minplrsbhxp = register_cvar("sh_minplayersxp", "2")
        sh_blockvip = register_cvar("sh_blockvip", "abcdef")
        sh_ffa = register_cvar("sh_ffa", "0")

        // Server cvars checked by core
        mp_friendlyfire = get_cvar_pointer("mp_friendlyfire")
        sv_maxspeed = get_cvar_pointer("sv_maxspeed")
        sv_lan = get_cvar_pointer("sv_lan")
        bot_quota = get_cvar_pointer("bot_quota")        // For cz bots to register spawn hook


        // API - Register a bunch of forwards that heroes can use
        fwd_HeroInit = CreateMultiForward("sh_hero_init", ET_IGNORE, FP_CELL, FP_CELL, FP_CELL)        // id, heroID, mode
        fwd_HeroKey = CreateMultiForward("sh_hero_key", ET_IGNORE, FP_CELL, FP_CELL, FP_CELL)        // id, heroID, key
        fwd_Spawn = CreateMultiForward("sh_client_spawn", ET_IGNORE, FP_CELL, FP_CELL)                // id, newSpawn
        fwd_Death = CreateMultiForward("sh_client_death", ET_IGNORE, FP_CELL, FP_CELL, FP_CELL, FP_STRING)        //killer, victim, wpnindex, hitplace, TK
        fwd_NewRound = CreateMultiForward("sh_round_new", ET_IGNORE)
        fwd_RoundStart = CreateMultiForward("sh_round_start", ET_IGNORE)
        fwd_RoundEnd = CreateMultiForward("sh_round_end", ET_IGNORE)


#if defined SH_BACKCOMPAT
        // API - Register a bunch of Server Command so that the Heroes can Call them
        register_srvcmd("sh_regKeyUp", "regKeyUp")                // Hero can register a keyup event to fire
        register_srvcmd("sh_regKeyDown", "regKeyDown")                // Hero can register a keydown event to fire
        register_srvcmd("sh_regLevels", "regLevels")                // Hero may want to what levels people are at...
        register_srvcmd("sh_regMaxHealth", "regMaxHealth")        // Hero may want to know what max health of a person is... doing this to cut down on server messages (woverine, dracula)
        register_srvcmd("sh_regInit", "regInit")                // Hero may need to init player gains or looses superpowers! 2 parms passed to script - id and hassuperpowers
#endif

        // Init saving method commands/cvars/variables
        saving_init()

        // Setup config file paths
        setupConfig()

        // Events to Capture
        register_event("CurWeapon", "event_CurWeapon", "be", "1=1")
        register_event("SetFOV", "event_SetFOV", "be")
        register_event("DeathMsg", "event_DeathMsg", "a")
        register_event("HLTV", "event_HLTV", "a", "1=0", "2=0")        // New Round
        register_logevent("round_Start", 2, "1=Round_Start")
        register_logevent("round_End", 2, "1=Round_End")
        register_logevent("round_Restart", 2, "1&Restart_Round_")
        register_logevent("bomb_HolderSpawned", 3, "2=Spawned_With_The_Bomb")
        register_logevent("host_Killed", 3, "2=Killed_A_Hostage")
        register_logevent("host_Rescued", 3, "2=Rescued_A_Hostage")
        register_logevent("host_AllRescued", 6, "3=All_Hostages_Rescued")
        register_logevent("vip_UserSpawned", 3, "2=Became_VIP")
        register_logevent("vip_UserEscape", 3, "2=Escaped_As_VIP")
        register_logevent("vip_Assassinated", 3, "2=Assassinated_The_VIP")
        register_logevent("vip_Escaped", 6, "3=VIP_Escaped")

        // Must use post or else is_user_alive will return false when dead player respawns
        // cz bots won't hook here must RegisterHamFromEntity
        RegisterHam(Ham_Spawn, "player", "ham_PlayerSpawn_Post", 1)
        RegisterHam(Ham_TakeDamage, "player", "ham_TakeDamage_Pre")

        // Events to catch shield buying
        // Old Style Menus
        register_menucmd(register_menuid("BuyItem", 1), MENU_KEY_8, "shieldbuy")
        // VGUI Menus
        register_menucmd(-34, MENU_KEY_9, "shieldbuy")
        // Steam console QuickBuys
        register_clcmd("shield", "shieldqbuy")
        // Steam Autobuying
        register_clcmd("cl_setautobuy", "fn_autobuy")
        register_clcmd("cl_autobuy", "fn_autobuy")
        register_clcmd("cl_setrebuy", "fn_autobuy")
        register_clcmd("cl_rebuy", "fn_autobuy")
        // Touch Forward
        register_forward(FM_Touch, "fm_Touch")

        // Player choosing a team (t, ct, auto, spec)
        register_menucmd(register_menuid("IG_Team_Select", 1), 511, "team_chosen")
        register_menucmd(register_menuid("Team_Select", 1), 511, "team_chosen")
        register_menucmd(register_menuid("Team_Select_Spect", 1), 511, "team_chosen")
        register_clcmd("jointeam", "team_chosen")

        // Client Commands
        register_clcmd("superpowermenu", "cl_superpowermenu", ADMIN_ALL, "superpowermenu")
        register_clcmd("clearpowers", "cl_clearpowers", ADMIN_ALL, "clearpowers")
        register_clcmd("say", "cl_say")
        register_clcmd("fullupdate", "cl_fullupdate")

        // Power Commands, using a loop so it adjusts with SH_MAXBINDPOWERS
        for (new x = 1; x <= SH_MAXBINDPOWERS; x++) {
                new powerDown[10], powerUp[10]
                formatex(powerDown, charsmax(powerDown), "+power%d", x)
                formatex(powerUp, charsmax(powerUp), "-power%d", x)

                register_clcmd(powerDown, "powerKeyDown")
                register_clcmd(powerUp, "powerKeyUp")
        }

        // Console commands for client or from server console
        register_concmd("playerlevels", "showLevelsCon", ADMIN_ALL, "<nick | @team | @ALL | #userid>")
        register_concmd("playerskills", "showSkillsCon", ADMIN_ALL, "<nick | @team | @ALL | #userid>")
        register_concmd("herolist", "showHeroListCon", ADMIN_ALL, "[search] [start] - Lists/Searches available heroes in console")

        // Hud Syncs for help and hero info, need 2 since help can be on at same time
        gHelpHudSync = CreateHudSyncObj()
        gHeroHudSync = CreateHudSyncObj()

        // Count number of hostages for sh_objectivexp
        // This should have a better method of counting, maybe check when keyvalue is set
        new ent = -1
        while( (ent = engfunc(EngFunc_FindEntityByString, ent, "classname", "hostage_entity")) > 0 ) {
                gNumHostages++
        }

        // Global Variables...
        gmsgStatusText = get_user_msgid("StatusText")
        gmsgScoreInfo = get_user_msgid("ScoreInfo")
        gmsgDeathMsg = get_user_msgid("DeathMsg")
        gmsgDamage = get_user_msgid("Damage")
        gmsgSayText = get_user_msgid("SayText")
        gmsgTeamInfo = get_user_msgid("TeamInfo")
        gServersMaxPlayers = get_maxplayers()

        // Set the game description
        register_forward(FM_GetGameDescription, "fm_GetGameDesc")

        // Block committed suicide hl log messages caused by extradamage
        register_forward(FM_AlertMessage, "fm_AlertMessage")
        register_message(gmsgDeathMsg, "msg_DeathMsg")

        // Block player names from overwriting StatusText sent by core
        register_message(gmsgStatusText, "msg_StatusText")

        // Fixes bug with HUD showing 0 health and reversing keys
        register_message(get_user_msgid("Health"), "msg_Health")

        // Load the config file here and again later
        // Initial load for core configs
        loadConfig()
}
//----------------------------------------------------------------------------------------------
public plugin_precache()
{
        // Default Sounds
        precache_sound("common/wpn_denyselect.wav")
        precache_sound(gSoundLevel)

        // Create this cvar in precache incase a hero wants to create a debug msg during precache
        sh_debug_messages = register_cvar("sh_debug_messages", "0")
}
//----------------------------------------------------------------------------------------------
public plugin_natives()
{
        register_library(SH_CORE_STR)

        register_native("sh_create_hero", "_sh_create_hero")
        register_native("sh_set_hero_info", "_sh_set_hero_info")
        register_native("sh_set_hero_bind", "_sh_set_hero_bind")
        register_native("sh_set_hero_shield", "_sh_set_hero_shield")
        register_native("sh_set_hero_hpap", "_sh_set_hero_hpap")
        register_native("sh_set_hero_speed", "_sh_set_hero_speed")
        register_native("sh_set_hero_grav", "_sh_set_hero_grav")
        register_native("sh_set_hero_dmgmult", "_sh_set_hero_dmgmult")
        register_native("sh_get_max_ap", "_sh_get_max_ap")
        register_native("sh_get_max_hp", "_sh_get_max_hp")
        register_native("sh_get_num_lvls", "_sh_get_num_lvls")
        register_native("sh_get_lvl_xp", "_sh_get_lvl_xp")
        register_native("sh_get_user_lvl", "_sh_get_user_lvl")
        register_native("sh_set_user_lvl", "_sh_set_user_lvl")
        register_native("sh_get_user_xp", "_sh_get_user_xp")
        register_native("sh_set_user_xp", "_sh_set_user_xp")
        register_native("sh_add_kill_xp", "_sh_add_kill_xp")
        register_native("sh_get_hero_id", "_sh_get_hero_id")
        register_native("sh_user_has_hero", "_sh_user_has_hero")
        register_native("sh_chat_message", "_sh_chat_message")
        register_native("sh_debug_message", "_sh_debug_message")
        register_native("sh_extra_damage", "_sh_extra_damage")
        register_native("sh_set_stun", "_sh_set_stun")
        register_native("sh_get_stun", "_sh_get_stun")
        register_native("sh_set_godmode", "_sh_set_godmode")
        register_native("sh_is_freezetime", "_sh_is_freezetime")
        register_native("sh_is_inround", "_sh_is_inround")
        register_native("sh_reload_ammo", "_sh_reload_ammo")
        register_native("sh_drop_weapon", "_sh_drop_weapon")
        register_native("sh_give_weapon", "_sh_give_weapon")
        register_native("sh_give_item", "_sh_give_item")
        register_native("sh_reset_max_speed", "_sh_reset_max_speed")
        register_native("sh_reset_min_gravity", "_sh_reset_min_gravity")
}
//----------------------------------------------------------------------------------------------
public fm_GetGameDesc()
{
        if ( !get_pcvar_num(sv_superheros) ) return FMRES_IGNORED

        new mod_name[9]
        get_modname(mod_name, charsmax(mod_name))
        if ( equal(mod_name, "cstrike") ) {
                forward_return(FMV_STRING, "CS - SuperHero Mod")
        }
        else {
                gIsCzero = true
                forward_return(FMV_STRING, "CZ - SuperHero Mod")
        }

        return FMRES_SUPERCEDE
}
//----------------------------------------------------------------------------------------------
public plugin_cfg()
{
        // GIVES TIME FOR SERVER.CFG AND LISTENSERVER.CFG TO LOAD UP THEIR VARIABLES
        // AMX COMMANDS AND CONSOLE COMMAND

        debugMsg(0, 1, "Starting plugin_cfg() function")

        // Load the Config file, secondary load for heroes
        loadConfig()

        // Setup the Admin Commands
        new accessLevel[10]
        get_pcvar_string(sh_adminaccess, accessLevel, charsmax(accessLevel))
        new aLevel = read_flags(accessLevel)

        //This can all be set with cmdaccess.ini now, do we really need a sh_adminaccess cvar?
        register_concmd("amx_shsetlevel", "adminSetLevel", aLevel, "<name|^"steamid^"|#userid|@TEAM|@ALL> <level> - Sets SuperHero level on Players")
        register_concmd("amx_shsetxp", "adminSetXP", aLevel, "<name|^"steamid^"|#userid|@TEAM|@ALL> <xp> - Sets Players XP")
        register_concmd("amx_shaddxp", "adminSetXP", aLevel, "<name|^"steamid^"|#userid|@TEAM|@ALL> <xp> - Adds XP to Players")
        register_concmd("amx_shban", "adminBanXP", aLevel, "<name|^"steamid^"|#userid> - Bans a player from using Powers")
        register_concmd("amx_shunban", "adminUnbanXP", aLevel, "<name|^"steamid^"|#userid|^"ip^"> - Unbans a player from using Powers")
#if SAVE_METHOD != 2
        register_concmd("amx_shimmunexp", "adminImmuneXP", aLevel, "<name|^"steamid^"|#userid> <0=OFF|1=ON> - Sets/Unsets player immune from sh_savedays XP prune only")
#endif

        register_concmd("amx_shresetxp", "adminEraseXP", ADMIN_RCON, "- Erases ALL saved XP (may take some time with a large vault file)")

        // Check to see if we need to block weapon giving heroes
        giveWeaponConfig()

        // Setup XPGiven and XP
        readINI()

        // Check the CVARs
        cvarCheck()

        // Clean out old XP data
        cleanXP(false)

        // Setup the Help MOTD
        setupHelpMotd()

        // Init CMD_PROJECTOR
        buildHelpHud()

        // Tasks
        set_task(1.0, "loopMain", _, _, _, "b")
        set_task(3.0, "setHeroLevels")
        set_task(5.0, "setSvMaxspeed")
        set_task(5.0, "cvarCheck")

        if ( cvar_exists("monster_spawn") ) {
                gMonsterModRunning = true
        }
}
//----------------------------------------------------------------------------------------------
setupConfig()
{
        // Set Up Config Files
        get_configsdir(gSHConfigDir, charsmax(gSHConfigDir))
        add(gSHConfigDir, charsmax(gSHConfigDir), "/shero", 6)

        // Attempt to create directory if it does not exist
        if ( !dir_exists(gSHConfigDir) ) {
                mkdir(gSHConfigDir)
        }

        formatex(gBanFile, charsmax(gBanFile), "%s/nopowers.cfg", gSHConfigDir)
        formatex(gSHConfig, charsmax(gSHConfig), "%s/shconfig.cfg", gSHConfigDir)
}
//----------------------------------------------------------------------------------------------
setupHelpMotd()
{
        formatex(gHelpMotd, charsmax(gHelpMotd), "%s/shmotd.txt", gSHConfigDir)

        if ( !file_exists(gHelpMotd) ) {
                //Create the file if it doesn't exist
                createHelpMotdFile(gHelpMotd)
        }
}
//----------------------------------------------------------------------------------------------
loadConfig()
{
        //Load SH Config File
        if ( file_exists(gSHConfig) ) {
                //Message Not run thru debug system since people are morons and think it's an error cause it says "DEBUG"
                static count
                ++count
                log_amx("Exec: (%d) Loading shconfig.cfg (message should be seen twice)", count)

                server_cmd("exec %s", gSHConfig)

                //Force the server to flush the exec buffer
                server_exec()

                //Note: I do not believe this is an issue anymore disabling until known otherwise - vittu
                //Exec the config again due to issues with it not loading all the time
                //server_cmd("exec %s", gSHConfig)
        }
        else {
                debugMsg(0, 0, "**DIKKAT** SuperHero Config Dosyasi bulunamadi, dogru yol: %s", gSHConfig)
        }
}
//----------------------------------------------------------------------------------------------
// This will set the sh_give_weapon blocks for the map
giveWeaponConfig()
{
        new wpnBlockFile[128]
        formatex(wpnBlockFile, charsmax(wpnBlockFile), "%s/shweapon.cfg", gSHConfigDir)

        if ( !file_exists(wpnBlockFile) ) {
                //Create the file if it doesn't exist
                createGiveWeaponConfig(wpnBlockFile)
                return
        }

        new blockWpnFile = fopen(wpnBlockFile, "rt")

        if ( !blockWpnFile ) {
                debugMsg(0, 0, "Failed to open shweapon.cfg, please verify file/folder permissions")
                return
        }

        new data[512], mapName[32], blockMapName[32]
        new blockWeapons[512], weapon[16], weaponName[32]
        new checkLength, x, weaponID

        get_mapname(mapName, charsmax(mapName))

        while(!feof(blockWpnFile)) {
                fgets(blockWpnFile, data, charsmax(data))
                trim(data)

                //Comments or blank skip it
                switch(data[0]) {
                        case '^0', '^n', ';', '/', '\', '#': continue
                }

                strbreak(data, blockMapName, charsmax(blockMapName), blockWeapons, charsmax(blockWeapons))

                //all maps or check for something more specific?
                if ( blockMapName[0] != '*' ) {

                        //How much of the map name do we check?
                        checkLength = strlen(blockMapName)

                        if ( blockMapName[checkLength-1] == '*' ) {
                                --checkLength
                        }
                        else {
                                //Largest length between the 2, do this because of above check
                                checkLength = max(checkLength, strlen(mapName))
                        }

                        //Keep checking or did we find the map?
                        if ( !equali(mapName, blockMapName, checkLength) )  continue
                }

                //If gotten this far a map has been found
                remove_quotes(blockWeapons)

                //Idiot check, make sure weapon names are lowercase before going further
                strtolower(blockWeapons)

                while ( blockWeapons[0] != '^0' ) {
                        //trim any spaces left over especially from strtok
                        trim(blockWeapons)
                        strtok(blockWeapons, weapon, charsmax(weapon), blockWeapons, 415, ',', 1)

                        if ( equal(weapon, "all") ) {
                                //Set all 1-30 CSW_ constants
                                for(x = 1; x < 31; x++) {
                                        gMapBlockWeapons[x] = gMapBlockWeapons[x] ? false : true
                                }
                        }
                        else {
                                //Set named weapon
                                formatex(weaponName, charsmax(weaponName), "weapon_%s", weapon)
                                weaponID = get_weaponid(weaponName)

                                if ( !weaponID ) {
                                        debugMsg(0, 0, "Invalid block weapon name ^"%s^" for entry ^"%s^" check shweapon.cfg", weapon, blockMapName)
                                        continue
                                }

                                gMapBlockWeapons[weaponID] = gMapBlockWeapons[weaponID] ? false : true
                        }
                }

                // Map found stop looking for more
                break;
        }
        fclose(blockWpnFile)
}
//----------------------------------------------------------------------------------------------
public cvarCheck()
{
        //Check variables for invalid settings
        new XPSaveDays = get_pcvar_num(sh_xpsavedays)
        if ( XPSaveDays > 365 ) set_pcvar_num(sh_xpsavedays, 365)
        else if ( XPSaveDays < 0 ) set_pcvar_num(sh_xpsavedays, 0)

        new minLevel = get_pcvar_num(sh_minlevel)
        if ( minLevel > gNumLevels ) set_pcvar_num(sh_minlevel, gNumLevels)
        else if ( minLevel < 0 ) set_pcvar_num(sh_minlevel, 0)

        if ( get_pcvar_num(sh_mercyxpmode) == 2 ) {
                new mercyXP = get_pcvar_num(sh_mercyxp)
                if ( mercyXP > gNumLevels ) set_pcvar_num(sh_mercyxp, gNumLevels)
                else if ( mercyXP < 0 ) set_pcvar_num(sh_mercyxp, 0)
        }

        //Load Global Variables from frequently used CVARS...
        gLongTermXP = get_pcvar_num(sh_savexp) ? true : false
        gMaxPowers = get_pcvar_num(sh_maxpowers)
        gObjectiveXP = (get_pcvar_num(sh_objectivexp) <= 0) ? false : true
        if ( !gLongTermXP ) gAutoBalance = get_pcvar_num(sh_autobalance) ? true : false
        gCMDProj = get_pcvar_num(sh_cmdprojector)
}
//----------------------------------------------------------------------------------------------
public loopMain()
{
        //Might be better to create an ent think loop
        if ( !get_pcvar_num(sv_superheros) ) return

        //Unstun Timer & GodMode Timer
        timerAll()

        //Show the CMD Projector
        showHelpHud()
}
//----------------------------------------------------------------------------------------------
public setHeroLevels()
{
        debugMsg(0, 1, " %d Herolari icin leveller yeniden yukleniyor", gSuperHeroCount)

        for ( new x = 0; x < gSuperHeroCount && x <= SH_MAXHEROS; x++ ) {
                gSuperHeros[x][availableLevel] = get_pcvar_num(gHeroLevelCVAR[x])
        }
}
//----------------------------------------------------------------------------------------------
public setSvMaxspeed()
{
        new maxspeed = 320 // Server Default
        for ( new x = 0; x < gSuperHeroCount; x++ ) {
                if ( gHeroMaxSpeed[x] != 0 ) {
                        maxspeed = max(maxspeed, get_pcvar_num(gHeroMaxSpeed[x]))
                }
        }

        // Only set if below required speed to avoid setting lower then server op may want
        if ( get_pcvar_num(sv_maxspeed) < maxspeed )
        {
                debugMsg(0, 1, "Setting server CVAR sv_maxspeed to: %d", maxspeed)
                set_pcvar_num(sv_maxspeed, maxspeed)
        }
}
//----------------------------------------------------------------------------------------------
public bool:_sh_is_inround()
{
        return gBetweenRounds ? false : true
}
//----------------------------------------------------------------------------------------------
public bool:_sh_is_freezetime()
{
        return gRoundStarted ? false : true
}
//----------------------------------------------------------------------------------------------
public _sh_get_num_lvls()
{
        return gNumLevels
}
//----------------------------------------------------------------------------------------------
public _sh_get_lvl_xp()
{
        new level = get_param(1)

        //stupid check - but checking prevents crashes
        if ( level < 0 || level > gNumLevels ) return -1

        return gXPLevel[level]
}
//----------------------------------------------------------------------------------------------
//native sh_get_user_lvl(id)
public _sh_get_user_lvl()
{
        new id = get_param(1)

        //stupid check - but checking prevents crashes
        if ( id < 1 || id > gServersMaxPlayers ) return -1

        //Check if data has loaded yet
        //if ( gReadXPNextRound[id] ) return -1

        return gPlayerLevel[id]
}
//----------------------------------------------------------------------------------------------
//sh_get_max_hp(id)
public _sh_get_max_hp()
{
        new id = get_param(1)

        //stupid check - but checking prevents crashes
        if ( id < 1 || id > gServersMaxPlayers ) return 0

        return gMaxHealth[id]
}
//----------------------------------------------------------------------------------------------
//sh_get_max_ap(id)
public _sh_get_max_ap()
{
        new id = get_param(1)

        //stupid check - but checking prevents crashes
        if ( id < 1 || id > gServersMaxPlayers ) return 0

        return gMaxArmor[id]
}
//----------------------------------------------------------------------------------------------
//native sh_set_user_lvl(id, setlevel)
public _sh_set_user_lvl()
{
        new id = get_param(1)

        //stupid check - but checking prevents crashes
        if ( id < 1 || id > gServersMaxPlayers ) return -1

        new setlevel = get_param(2)

        if ( setlevel < 0 || setlevel > gNumLevels ) return -1

        gPlayerXP[id] = gXPLevel[setlevel]
        displayPowers(id, false)

        return setlevel
}
//----------------------------------------------------------------------------------------------
//native sh_get_user_xp(id)
public _sh_get_user_xp()
{
        new id = get_param(1)

        //stupid check - but checking prevents crashes
        if ( id < 1 || id > gServersMaxPlayers ) return -1

        return gPlayerXP[id]
}
//----------------------------------------------------------------------------------------------
//native sh_set_user_xp(id, xp, bool:addtoxp = false)
public _sh_set_user_xp()
{
        new id = get_param(1)

        //stupid check - but checking prevents crashes
        if ( id < 1 || id > gServersMaxPlayers ) return -1

        new xp = get_param(2)

        // Add to XP or set a value
        if ( get_param(3) ) {
                localAddXP(id, xp)
        }
        else {
                //Set to xp, by finding what must be added to users current xp
                localAddXP(id, (xp - gPlayerXP[id]))
        }

        displayPowers(id, false)

        return 1
}
//----------------------------------------------------------------------------------------------
//native sh_chat_message(id, heroID = -1, const msg[], any:...)
public _sh_chat_message()
{
        new id = get_param(1)

        if ( id < 0 || id > gServersMaxPlayers ) return
        if ( is_user_bot(id) ) return

        // Chat max is 191(w/null) to pass into it, "[SH] " is 5 char min added to message
        new output[186]
        vdformat(output, charsmax(output), 3, 4)

        if ( output[0] == '^0' ) return

        chatMessage(id, get_param(2), output)
}
//----------------------------------------------------------------------------------------------
// Thanks to teame06's ColorChat method which this is based on
chatMessage(id, heroIndex = -1, const msg[], any:...)
{
        if ( id < 0 || id > gServersMaxPlayers ) return
        if ( is_user_bot(id) ) return

        // Make sure we have a valid index
        new msgType, index
        if ( !id ) {
                new i
                while ( i < gServersMaxPlayers ) {
                        if ( gPlayerPutInServer[++i] ) {
                                index = i
                                break
                        }
                }

                if ( !index ) return

                msgType = MSG_BROADCAST
        }
        else {
                // Make sure this id is actually in the server
                if ( !gPlayerPutInServer[id] ) return

                msgType = MSG_ONE_UNRELIABLE
                index = id
        }

        // Now we build our message
        static message[191], heroName[27]
        new len
        message[0] = '^0'
        heroName[0] = '^0'

        // Set first bit
        message[0] = 0x03 //Team colored
        ++len

        // Do we need to set a hero name to the message
        if ( -1 < heroIndex < gSuperHeroCount ) {
                // Set hero name in parentheses
                formatex(heroName, charsmax(heroName), "(%s)",  gSuperHeros[heroIndex][hero])
        }

        len += formatex(message[len], charsmax(message)-len, "[SH]%s^x01 ", (heroName[0] == '^0') ? "" : heroName)

        vformat(message[len], charsmax(message)-len, msg, 4)

        // Temporarily set teaminfo of player to send message from that player as if on the set team
        // index is in server at this point
        new indexTeam = _:cs_get_user_team(index)
        chatSetTeamInfo(index, msgType, gTeamName[3])

        // Send message
        message_begin(msgType, gmsgSayText, _, index)
        write_byte(index)
        write_string(message)
        message_end()

        // Reset player's teaminfo
        chatSetTeamInfo(index, msgType, gTeamName[indexTeam])
}
//----------------------------------------------------------------------------------------------
chatSetTeamInfo(id, type, const team[])
{
        message_begin(type, gmsgTeamInfo, _, id)
        write_byte(id)
        write_string(team)
        message_end()
}
//----------------------------------------------------------------------------------------------
//native sh_debug_message(id, level, const message[], any:...)
public _sh_debug_message()
{
        new level = get_param(2)

        if ( get_pcvar_num(sh_debug_messages) < level && level != 0 ) return

        new id = get_param(1)

        new output[512]
        vdformat(output, charsmax(output), 3, 4)

        if ( output[0] == '^0' ) return

        debugMsg(id, level, output)
}
//----------------------------------------------------------------------------------------------
debugMsg(id, level, const message[], any:...)
{
        if ( get_pcvar_num(sh_debug_messages) < level && level != 0 ) return

        new output[512]
        vformat(output, charsmax(output), message, 4)

        if ( output[0] == '^0' ) return

        if ( 0 < id <= gServersMaxPlayers ) {
                new name[32], userid, authid[32], team[32]
                get_user_name(id, name,  charsmax(name))
                userid = get_user_userid(id)
                get_user_authid(id, authid,  charsmax(authid))
                get_user_team(id, team,  charsmax(team))
                if ( equal(team, "UNASSIGNED") ) copy(team, charsmax(team), "")
                if ( userid > 0 ) format(output, charsmax(output), "^"%s<%d><%s><%s>^" %s", name, userid, authid, team, output)
        }

        log_amx("DEBUG: %s", output)
}
//----------------------------------------------------------------------------------------------
//native sh_get_hero_id(const heroName[])
public _sh_get_hero_id()
{
        new pHero[25]
        get_string(1, pHero, charsmax(pHero))

        return getHeroID(pHero)
}
//----------------------------------------------------------------------------------------------
getHeroID(const heroName[])
{
        for ( new x = 0; x < gSuperHeroCount; x++ ) {
                if ( equali(heroName, gSuperHeros[x][hero]) ) {
                        return x
                }
        }
        return -1
}
//----------------------------------------------------------------------------------------------
//native sh_user_has_hero(id, heroIndex)
public _sh_user_has_hero()
{
        new id = get_param(1)

        //stupid check - but checking prevents crashes
        if ( id < 1 || id > gServersMaxPlayers ) return 0

        new heroIndex = get_param(2)

        if ( -1 < heroIndex < gSuperHeroCount ) {
                return playerHasPower(id, heroIndex)
        }

        return 0
}
//----------------------------------------------------------------------------------------------
bool:playerHasPower(id, heroIndex)
{
        new playerpowercount = getPowerCount(id)
        for ( new x = 1; x <= playerpowercount && x <= SH_MAXLEVELS; x++ ) {
                if ( gPlayerPowers[id][x] == heroIndex ) return true
        }
        return false
}
//----------------------------------------------------------------------------------------------
//native sh_drop_weapon(id, weaponID, bool:remove = false)
public _sh_drop_weapon()
{
        if ( !get_pcvar_num(sv_superheros) ) return

        new id = get_param(1)

        if ( !is_user_alive(id) ) return

        //If VIPs are not allowed other weapons, protect them from losing what they have
        if ( id == gXpBounsVIP && getVipFlags() & VIP_BLOCK_WEAPONS ) return

        new weaponID = get_param(2)

        if ( !user_has_weapon(id, weaponID) ) return

        new slot = sh_get_weapon_slot(weaponID)

        if ( slot == 1 || slot == 2 || slot == 5 ) {

                //Don't drop/remove the main c4
                if ( weaponID == CSW_C4 && pev_valid(gXpBounsC4ID) && id == pev(gXpBounsC4ID, pev_owner) ) return
       
                dropWeapon(id, weaponID, get_param(3) ? true : false)
        }
}
//---------------------------------------------------------------------------------------------
dropWeapon(id, weaponID, bool:remove)
{
        if ( !get_pcvar_num(sv_superheros) ) return
        if ( !is_user_alive(id) ) return
        // If VIPs are not allowed other weapons protect them from losing what they have
        if ( id == gXpBounsVIP && getVipFlags() & VIP_BLOCK_WEAPONS ) return
        if ( !user_has_weapon(id, weaponID) ) return

        new slot = sh_get_weapon_slot(weaponID)

        if ( slot == 1 || slot == 2 || slot == 5 ) {

                //Don't drop/remove the main c4
                if ( weaponID == CSW_C4 && pev_valid(gXpBounsC4ID) && id == pev(gXpBounsC4ID, pev_owner) ) return

                static weaponName[32]

                get_weaponname(weaponID, weaponName, charsmax(weaponName))

                engclient_cmd(id, "drop", weaponName)

                if ( !remove ) return

                new Float:weaponVel[3]
                new weaponBox = -1

                while( (weaponBox = engfunc(EngFunc_FindEntityByString, weaponBox, "classname", "weaponbox")) > 0 ) {

                        // Skip anything not owned by this client
                        if ( pev_valid(weaponBox) && pev(weaponBox, pev_owner) == id ) {

                                // If Velocities are all Zero its on the ground already and should stay there
                                pev(weaponBox, pev_velocity, weaponVel)
                                if ( weaponVel[0] == 0.0 && weaponVel[1] == 0.0 && weaponVel[2] == 0.0 ) continue

                                // Forcing a think cleanly removes weaponbox and it's contents
                                dllfunc(DLLFunc_Think, weaponBox)
                        }
                }
        }
}
//---------------------------------------------------------------------------------------------
//native sh_give_weapon(id, weaponID, bool:switchTo = false)
public _sh_give_weapon()
{
        if ( !get_pcvar_num(sv_superheros) ) return 0

        new id = get_param(1)

        if ( !is_user_alive(id) ) return 0

        if ( id == gXpBounsVIP && getVipFlags() & VIP_BLOCK_WEAPONS ) return 0

        new weaponID = get_param(2)

        if ( weaponID < CSW_P228 || weaponID > CSW_P90 )  return 0

        if ( gMapBlockWeapons[weaponID] )  return 0

        if ( !user_has_weapon(id, weaponID) ) {
                return giveWeapon(id, weaponID, get_param(3) ? true : false)
        }

        return 0
}
//---------------------------------------------------------------------------------------------
giveWeapon(id, weaponID, bool:switchTo)
{
        if ( !get_pcvar_num(sv_superheros) ) return 0
        if ( !is_user_alive(id) ) return 0
        if ( id == gXpBounsVIP && getVipFlags() & VIP_BLOCK_WEAPONS ) return 0
        if ( weaponID < CSW_P228 || weaponID > CSW_P90 )  return 0
        if ( gMapBlockWeapons[weaponID] )  return 0

        if ( !user_has_weapon(id, weaponID) ) {
                static weaponName[32]
                get_weaponname(weaponID, weaponName, charsmax(weaponName))

                new itemID = give_item(id, weaponName)

                // Switch to the given weapon?
                if ( switchTo ) engclient_cmd(id, weaponName)

                return itemID
        }

        return 0
}
//---------------------------------------------------------------------------------------------
//native sh_give_item(id, const itemName[], bool:switchTo = false)
public _sh_give_item()
{
        if ( !get_pcvar_num(sv_superheros) ) return 0

        new id = get_param(1)

        if ( !is_user_alive(id) ) return 0

        new itemName[32], itemID
        get_array(2, itemName, charsmax(itemName))

        if ( equal(itemName, "weapon", 6) )
        {
                if ( id == gXpBounsVIP && getVipFlags() & VIP_BLOCK_WEAPONS ) return 0

                new weaponID = get_weaponid(itemName)
                if (weaponID)
                {
                        //It's a weapon see if it is blocked or user already has it
                        if ( gMapBlockWeapons[weaponID] || user_has_weapon(id, weaponID) ) return 0
                }

                itemID = give_item(id, itemName)

                if ( get_param(3) ) engclient_cmd(id, itemName)
        }
        else {
                itemID = give_item(id, itemName)
        }

        return itemID
}
//---------------------------------------------------------------------------------------------
//native sh_create_hero(const heroName[], pcvarMinLevel)
public _sh_create_hero()
{
        //Heroes Name
        new pHero[25]
        get_string(1, pHero, charsmax(pHero))       

        // Add Hero to Big Array!
        if ( gSuperHeroCount >= SH_MAXHEROS ) {
                debugMsg(0, 1, "Hero ^"%s^" Is Being Rejected, Exceeded SH_MAXHEROS", pHero)
                return -1
        }

        new idx = gSuperHeroCount

        new pcvarMinLevel = get_param(2)
        new heroLevel = get_pcvar_num(pcvarMinLevel)

        debugMsg(0, 3, "Create Hero-> HeroID: %d - %s - %d", gSuperHeroCount, pHero, heroLevel)

        copy(gSuperHeros[idx][hero], 24, pHero)
        gHeroLevelCVAR[idx] = pcvarMinLevel
        gSuperHeros[idx][availableLevel] = heroLevel

        ++gSuperHeroCount

        return idx
}
//----------------------------------------------------------------------------------------------
public _sh_set_hero_info()
{
        new heroIndex = get_param(1)

        if ( heroIndex < 0 || heroIndex >= gSuperHeroCount ) return

        new pPower[50], pHelp[128]
        get_string(2, pPower, charsmax(pPower))                //Short Power Description
        get_string(3, pHelp, charsmax(pHelp))                //Help Info

        debugMsg(0, 3, "Create Hero-> HeroID: %d - %s - %s", heroIndex, pPower, pHelp)

        copy(gSuperHeros[heroIndex][superpower], 49, pPower)
        copy(gSuperHeros[heroIndex][help], 127, pHelp)
}
//----------------------------------------------------------------------------------------------
public _sh_set_hero_bind()
{
        new heroIndex = get_param(1)

        if ( heroIndex < 0 || heroIndex >= gSuperHeroCount ) return

        debugMsg(0, 3, "Create Hero-> HeroID: %d - Bindable: ^"TRUE^"", heroIndex)

        gSuperHeros[heroIndex][requiresKeys] = true
}
//----------------------------------------------------------------------------------------------
public _sh_set_hero_shield()
{
        new heroIndex = get_param(1)

        if ( heroIndex < 0 || heroIndex >= gSuperHeroCount ) return

        new pRestricted = get_param(2)        //Shield Restricted?

        debugMsg(0, 3, "Create Hero-> HeroID: %d - Shield Restricted: %s", heroIndex, pRestricted ? "TRUE" : "FALSE")

        gHeroShieldRest[heroIndex] = pRestricted ? true : false
}
//----------------------------------------------------------------------------------------------
initHero(id, heroIndex, mode)
{
        // OK to pass this through when mod off... Let's heroes cleanup after themselves
        // init event is used to let hero know when a player has selected OR deselected a hero's power

        // Reset Shield Restriction if needed for this hero
        if ( gHeroShieldRest[heroIndex] ) {
                //If this is called by an added hero they must be restricted
                if ( mode == SH_HERO_ADD ) {
                        gShieldRestrict[id] = true
                }
                else {
                        new heroIndex, bool:restricted = false
                        new powerCount = getPowerCount(id)
                        for (new x = 1; x <= powerCount; x++ ) {
                                heroIndex = gPlayerPowers[id][x]
                                // Test crash gaurd
                                if ( heroIndex < 0 || heroIndex >= gSuperHeroCount ) continue

                                if ( gHeroShieldRest[heroIndex] ) {
                                        restricted = true
                                        break
                                }
                        }
                        gShieldRestrict[id] = restricted
                }

                //If they are alive make sure they don't have a shield already
                if ( gShieldRestrict[id] && is_user_alive(id) ) {
                        if ( cs_get_user_shield(id) ) {
                                engclient_cmd(id, "drop", "weapon_shield")
                        }
                }
        }

        // Reset Hero hp/ap/speed/grav if needed
        if ( mode == SH_HERO_DROP && is_user_alive(id) ) {
                //reset all values
                if ( gHeroMaxHealth[heroIndex] != 0 ) {
                        new newHealth = getMaxHealth(id)

                        if ( get_user_health(id) > newHealth ) {
                                // Assume some damage for doing this?
                                // Don't want players picking Superman let's say then removing his power - and trying to keep the HPs
                                // If they do that - feel free to lose some hps
                                // Also - Superman starts with around 150 Person could take some damage (i.e. reduced to 110 )
                                // but then clear powers and start at 100 - like 40 free hps for doing that, trying to avoid exploits
                                set_user_health(id, newHealth - (newHealth / 4) )
                        }
                }

                if ( gHeroMaxArmor[heroIndex] != 0 ) {
                        new newArmor = getMaxArmor(id)
                        new CsArmorType:armorType
                        if ( cs_get_user_armor(id, armorType) > newArmor ) {
                                // Remove Armor for doing this
                                cs_set_user_armor(id, newArmor, armorType)
                        }
                }

                if ( gHeroMaxSpeed[heroIndex] != 0 ) {
                        setSpeedPowers(id, true)
                }

                if ( gHeroMinGravity[heroIndex] != 0 ) {
                        resetMinGravity(id)
                }
        }

        //Init the hero
#if defined SH_BACKCOMPAT
        if ( gEventInit[heroIndex][0] != '^0' ) {
                server_cmd("%s %d %d", gEventInit[heroIndex], id, mode)
        }
        else {
#endif
                ExecuteForward(fwd_HeroInit, fwdReturn, id, heroIndex, mode)

#if defined SH_BACKCOMPAT
        }
#endif

        gChangedHeroes[id] = true
}
//----------------------------------------------------------------------------------------------
//native sh_set_hero_hpap(heroID, pcvarHealth, pcvarArmor)
public _sh_set_hero_hpap()
{
        new heroIndex = get_param(1)

        if ( heroIndex < 0 || heroIndex >= gSuperHeroCount ) return

        new pcvarMaxHealth = get_param(2)
        new pcvarMaxArmor = get_param(3)

        debugMsg(0, 3, "Set Max HP/AP -> HeroID: %d - %d - %d", heroIndex, pcvarMaxHealth ? get_pcvar_num(pcvarMaxHealth) : 0, pcvarMaxArmor ? get_pcvar_num(pcvarMaxArmor) : 0)

        // Avoid setting if 0 because backward compatibility method would overwrite value
        if ( pcvarMaxHealth != 0 ) gHeroMaxHealth[heroIndex] = pcvarMaxHealth // pCVAR expected!
        if ( pcvarMaxArmor != 0 ) gHeroMaxArmor[heroIndex] = pcvarMaxArmor // pCVAR expected!
}
//----------------------------------------------------------------------------------------------
//native sh_set_hero_speed(heroID, pcvarSpeed, const weapons[] = {0}, numofwpns = 1)
public _sh_set_hero_speed()
{
        new heroIndex = get_param(1)

        if ( heroIndex < 0 || heroIndex >= gSuperHeroCount ) return

        new pcvarSpeed = get_param(2)
        new numWpns = get_param(4)

        new pWeapons[31]
        get_array(3, pWeapons, numWpns)

        //Avoid running this unless debug is high enough
        if ( get_pcvar_num(sh_debug_messages) > 2 ) {
                //Set up the weapon string for the debug message
                new weapons[32], number[3], x
                for ( x = 0; x < numWpns; x++ ) {
                        formatex(number, charsmax(number), "%d", pWeapons[x])
                        add(weapons, charsmax(weapons), number)
                        if ( pWeapons[x+1] != '^0' ) {
                                add(weapons, charsmax(weapons), ",")
                        }
                        else break
                }

                debugMsg(0, 3, "Set Max Speed -> HeroID: %d - Speed: %d - Weapon(s): %s", heroIndex, get_pcvar_num(pcvarSpeed), weapons)
        }

        gHeroMaxSpeed[heroIndex] = pcvarSpeed // pCVAR expected!
        copy(gHeroSpeedWeapons[heroIndex], charsmax(gHeroSpeedWeapons[]), pWeapons) // Array expected!
}
//----------------------------------------------------------------------------------------------
//native sh_set_hero_grav(heroID, pcvarGravity, const weapons[] = {0}, numofwpns = 1)
public _sh_set_hero_grav()
{
        new heroIndex = get_param(1)

        if ( heroIndex < 0 || heroIndex >= gSuperHeroCount ) return

        new pcvarGravity = get_param(2)
        new numWpns = get_param(4)

        new pWeapons[40]
        get_array(3, pWeapons, numWpns)

        //Avoid running this unless debug is high enough
        if ( get_pcvar_num(sh_debug_messages) > 2 ) {
                //Set up the weapon string for the debug message
                new weapons[32], number[3], x
                for ( x = 0; x < numWpns; x++ ) {
                        formatex(number, charsmax(number), "%d", pWeapons[x])
                        add(weapons, charsmax(weapons), number)
                        if ( pWeapons[x+1] != '^0' ) {
                                add(weapons, charsmax(weapons), ",")
                        }
                        else break
                }

                debugMsg(0, 3, "Set Min Gravity -> HeroID: %d - Gravity: %.3f - Weapon(s): %s", heroIndex, get_pcvar_float(pcvarGravity), weapons)
        }

        gHeroMinGravity[heroIndex] = pcvarGravity // pCVAR expected!
        //copy(gHeroGravityWeapons[heroIndex], charsmax(gHeroGravityWeapons[]), pWeapons) // Array expected!
}
//----------------------------------------------------------------------------------------------
Float:getMaxSpeed(id, weapon)
{
        if ( id == gXpBounsVIP && getVipFlags() & VIP_BLOCK_SPEED ) return 227.0

        switch(weapon) {
                // If weapon is a zoomed sniper rifle set default speeds
                case  CSW_SCOUT, CSW_SG550, CSW_AWP, CSW_G3SG1: {
                        if ( gCurrentFOV[id] <= 45 ) {
                                return sh_get_weapon_speed(weapon, true)
                        }
                }
        }

        static Float:returnSpeed, Float:heroSpeed, x, i
        static playerpowercount, heroIndex, heroWeapon, heroSpeedPointer
        returnSpeed = -1.0
        playerpowercount = getPowerCount(id)

        for ( x = 1; x <= playerpowercount; x++ ) {
                heroIndex = gPlayerPowers[id][x]
                if ( -1 < heroIndex < gSuperHeroCount ) {
                        heroSpeedPointer = gHeroMaxSpeed[heroIndex]
                        if ( !heroSpeedPointer ) continue
                        heroSpeed = get_pcvar_float(heroSpeedPointer)
                        if ( heroSpeed > 0.0 ) {
                                for ( i = 0; i < 31; i++ ) {
                                        heroWeapon = gHeroSpeedWeapons[heroIndex][i]

                                        //Stop checking, end of list
                                        if ( i != 0 && heroWeapon == 0 ) break

                                        debugMsg(id, 5, "Looking for Speed Functions - %s, %d, %d", gSuperHeros[heroIndex][hero], heroWeapon, weapon)

                                        //if 0 or current weapon check max
                                        if ( heroWeapon == 0 || heroWeapon == weapon ) {
                                                returnSpeed = floatmax(returnSpeed, heroSpeed)
                                                break
                                        }
                                }
                        }
                }
        }

        return returnSpeed
}
//----------------------------------------------------------------------------------------------
getMaxHealth(id)
{
        static returnHealth, x
        returnHealth = 100

        if ( !(id == gXpBounsVIP && getVipFlags() & VIP_BLOCK_HEALTH) ) {
                static heroIndex, playerpowercount, heroHealthPointer
                playerpowercount = getPowerCount(id)

                for ( x = 1; x <= playerpowercount; x++ ) {
                        heroIndex = gPlayerPowers[id][x]
                        // Test crash gaurd
                        if ( -1 < heroIndex < gSuperHeroCount ) {
                                heroHealthPointer = gHeroMaxHealth[heroIndex]
                                if ( !heroHealthPointer ) continue
                                returnHealth = max(returnHealth, get_pcvar_num(heroHealthPointer))
                        }
                }
        }

        // Other plugins might use this, even maps
        set_pev(id, pev_max_health, returnHealth)

#if defined SH_BACKCOMPAT
        // Ok let any heroes know that need to know...
        for ( x = 0; x < gSuperHeroCount; x++ ) {
                if ( gEventMaxHealth[x][0] != '^0' ) {
                        server_cmd("%s %d %d", gEventMaxHealth[x], id, returnHealth)
                }
        }
#endif

        return gMaxHealth[id] = returnHealth
}
//----------------------------------------------------------------------------------------------
getMaxArmor(id)
{
        if ( id == gXpBounsVIP && getVipFlags() & VIP_BLOCK_ARMOR ) {
                return gMaxArmor[id] = 200
        }

        static heroIndex, returnArmor, x, playerpowercount, heroArmorPointer
        returnArmor = 0
        playerpowercount = getPowerCount(id)

        for ( x = 1; x <= playerpowercount; x++ ) {
                heroIndex = gPlayerPowers[id][x]
                if ( -1 < heroIndex < gSuperHeroCount ) {
                        heroArmorPointer = gHeroMaxArmor[heroIndex]
                        if ( !heroArmorPointer ) continue
                        returnArmor = max(returnArmor, get_pcvar_num(heroArmorPointer))
                }
        }

        return gMaxArmor[id] = returnArmor
}
//----------------------------------------------------------------------------------------------
Float:getMinGravity(id)
{
        if ( id == gXpBounsVIP && getVipFlags() & VIP_BLOCK_GRAVITY ) return 1.0

        static Float:returnGravity, Float:heroMinGravity
        static x, heroIndex, playerpowercount, heroGravityPointer
        returnGravity = 1.0
        playerpowercount = getPowerCount(id)

        for ( x = 1; x <= playerpowercount; x++ ) {
                heroIndex = gPlayerPowers[id][x]
                if ( -1 < heroIndex < gSuperHeroCount ) {
                        heroGravityPointer = gHeroMinGravity[heroIndex]
                        if ( !heroGravityPointer ) continue
                        heroMinGravity = get_pcvar_float(heroGravityPointer)
                        if ( heroMinGravity > 0.0 ) {
                                returnGravity = floatmin(returnGravity, heroMinGravity)
                        }
                }
        }

        return returnGravity
}
//----------------------------------------------------------------------------------------------
getPowerCount(id)
{
        // I'll make this a function for now in case I want to change power mapping strategy
        // i.e. drop a power menu
        return max(gPlayerPowers[id][0], 0)
}
//----------------------------------------------------------------------------------------------
getBindNumber(id, heroIndex)
{
        new MaxBinds = min(get_pcvar_num(sh_maxbinds), SH_MAXBINDPOWERS)
        for (new x = 1; x <= MaxBinds; x++) {
                if (gPlayerBinds[id][x] == heroIndex) return x
        }
        return 0
}
//----------------------------------------------------------------------------------------------
menuSuperPowers(id, menuOffset)
{
        // Don't show menu if mod off or they're not connected
        if ( !get_pcvar_num(sv_superheros) || !is_user_connected(id) || gReadXPNextRound[id] ) return PLUGIN_HANDLED

        gInMenu[id] = false
        gPlayerMenuOffset[id] = 0

        new bool:isBot = is_user_bot(id) ? true : false

        if ( gIsPowerBanned[id] ) {
                if ( !isBot ) client_print(id, print_center, "Super guc kullanmaniz yasaklandi")
                return PLUGIN_HANDLED // Just don't show the gui menu
        }

        new playerpowercount = getPowerCount(id)
        new playerLevel = gPlayerLevel[id]

        // Don't show menu if they already have enough powers
        if ( playerpowercount >= playerLevel || playerpowercount >= gMaxPowers ) return PLUGIN_HANDLED

        // Figure out how many powers a person should be able to have
        // Example: At level 10 a person can pick a max of 1 lvl 10 hero
        //                and a max of 2 lvl 9 heroes, and a max of 3 lvl 8 heors, etc...
        new LvlLimit = get_pcvar_num(sh_lvllimit)
        if ( LvlLimit == 0 ) LvlLimit = SH_MAXLEVELS

        for ( new x = 0; x <= gNumLevels; x++ ) {
                if ( playerLevel >= x ) {
                        gMaxPowersLeft[id][x] = playerLevel - x + LvlLimit
                }
                else {
                        gMaxPowersLeft[id][x] = 0
                }
        }

        // Now decrement the level powers that they've picked
        new heroIndex, heroLevel

        for ( new x = 1; x <= playerpowercount && x <= SH_MAXLEVELS; x++ ) {
                heroIndex = gPlayerPowers[id][x]
                if ( heroIndex < 0 || heroIndex >= gSuperHeroCount) continue
                heroLevel = getHeroLevel(heroIndex)
                // Decrement all gMaxPowersLeft by 1 for the level hero they have and below
                for ( new y = heroLevel; y >= 0; y-- ) {
                        if ( --gMaxPowersLeft[id][y] < 0 ) gMaxPowersLeft[id][y] = 0
                        //If none left on this level, there should be none left on any higher levels
                        if ( gMaxPowersLeft[id][y] <= 0 && y < SH_MAXLEVELS ) {
                                if ( gMaxPowersLeft[id][y+1] != 0 ) {
                                        for ( new z = y; z <= gNumLevels; z++ ) {
                                                gMaxPowersLeft[id][z] = 0
                                        }
                                }
                        }
                }
        }

        // OK BUILD A LIST OF HEROES THIS PERSON CAN PICK FROM
        gPlayerMenuChoices[id][0] = 0  // <- 0 choices so far
        new count = 0, enabled = 0
        new MaxBinds = min(get_pcvar_num(sh_maxbinds), SH_MAXBINDPOWERS)
        new menuMode = get_pcvar_num(sh_menumode)
        new bool:thisEnabled

        for ( new x = 0; x < gSuperHeroCount; x++ )  {
                heroIndex = x
                heroLevel = getHeroLevel(heroIndex)
                thisEnabled = false
                if ( playerLevel >= heroLevel ) {
                        if (gMaxPowersLeft[id][heroLevel] > 0 && !(gPlayerBinds[id][0] >= MaxBinds && gSuperHeros[heroIndex][requiresKeys])) {
                                thisEnabled = true
                        }
                        // Don't want to present this power if the player already has it!
                        if ( !playerHasPower(id, heroIndex) && (thisEnabled || (!isBot && menuMode > 0)) ) {
                                gPlayerMenuChoices[id][0] = ++count
                                gPlayerMenuChoices[id][count] = heroIndex
                                if ( thisEnabled ) enabled++
                        }
                }
        }

        // Choose and give a random power to a bot
        if ( isBot && count ) {
                // Select a random power
                heroIndex = gPlayerMenuChoices[id][random_num(1, count)]

                // Bind Keys / Set Powers
                gPlayerPowers[id][0] = playerpowercount + 1
                gPlayerPowers[id][playerpowercount + 1] = heroIndex

                //Init This Hero!
                initHero(id, heroIndex, SH_HERO_ADD)
                displayPowers(id, true)

                //Don't show menu to bots and wait for next menu call before giving another power
                return PLUGIN_HANDLED
        }

        // show menu super power
        new message[800]
        new temp[90]
        new keys = 0

        //menuOffset Stuff
        if ( menuOffset <= 0 || menuOffset > gPlayerMenuChoices[id][0] ) menuOffset = 1
        gPlayerMenuOffset[id] = menuOffset

        new total = min(gMaxPowers, playerLevel)
        formatex(message, 68, "\ySelect Super Power:%-16s\r(Siz %d/%d sectiniz)^n^n", " ", playerpowercount, total)

        // OK Display the Menu
        for ( new x = menuOffset; x < menuOffset + 8; x++ ) {
                // Only allow a selection from powers the player doesn't have
                if ( x > gPlayerMenuChoices[id][0] ) {
                        add(message, charsmax(message), "^n")
                        continue
                }
                heroIndex = gPlayerMenuChoices[id][x]
                heroLevel = getHeroLevel(heroIndex)
                if ( gMaxPowersLeft[id][heroLevel] <= 0 || (gPlayerBinds[id][0] >= MaxBinds && gSuperHeros[heroIndex][requiresKeys]) ) {
                        add(message,charsmax(message),"\d")
                }
                else {
                        add(message,charsmax(message),"\w")
                }
                keys |= (1<<x-menuOffset) // enable this option
                formatex(temp, charsmax(temp), "%s (%d%s)", gSuperHeros[heroIndex][hero], heroLevel, gSuperHeros[heroIndex][requiresKeys] ? "b" : "")
                format(temp, charsmax(temp), "%d. %-20s- %s^n", x - menuOffset + 1, temp, gSuperHeros[heroIndex][superpower])
                add(message, charsmax(message), temp)
        }

        if ( gPlayerMenuChoices[id][0] > 8 ) {
                // Can only Display 8 heroes at a time
                add(message, charsmax(message), "\w^n9. Daha Fazla Hero")
                keys |= MENU_KEY_9
        }
        else {
                add(message, charsmax(message), "^n")
        }

        // Cancel
        add(message, charsmax(message), "\w^n0. Iptal")
        keys |= MENU_KEY_0

        if ( (count > 0 && enabled > 0) || gInMenu[id] ) {
                debugMsg(id, 8, "Displaying Menu - offset: %d - count: %d - enabled: %d", menuOffset, count, enabled)
                gInMenu[id] = true
                show_menu(id, keys, message)
        }

        return PLUGIN_HANDLED
}
//----------------------------------------------------------------------------------------------
public selectedSuperPower(id, key)
{
        if ( !gInMenu[id] || !get_pcvar_num(sv_superheros) ) return PLUGIN_HANDLED

        gInMenu[id] = false

        if ( gIsPowerBanned[id] ) {
                client_print(id, print_center, "Super guc kullanmaniz yasaklandi")
                return PLUGIN_HANDLED
        }

        switch(key) {
                case 8: {
                        // Next and Previous Super Hero Menus
                        menuSuperPowers(id, gPlayerMenuOffset[id] + 8)
                        return PLUGIN_HANDLED
                }
                case 9: {
                        // Cancel
                        gPlayerMenuOffset[id] = 0
                        return PLUGIN_HANDLED
                }
        }

        // Hero was Picked!
        new playerpowercount = getPowerCount(id)
        if ( playerpowercount >= gNumLevels || playerpowercount >= gMaxPowers ) return PLUGIN_HANDLED

        new heroIndex = gPlayerMenuChoices[id][key + gPlayerMenuOffset[id]]

        // Just a crash check
        if ( heroIndex < 0 || heroIndex >= gSuperHeroCount ) return PLUGIN_HANDLED

        new heroLevel = getHeroLevel(heroIndex)
        new MaxBinds = get_pcvar_num(sh_maxbinds)
        if ((gPlayerBinds[id][0] >= MaxBinds && gSuperHeros[heroIndex][requiresKeys])) {
                chatMessage(id, _, "Ozel gucu olan %d 'den fazla hero secemezsiniz", MaxBinds)
                menuSuperPowers(id, gPlayerMenuOffset[id])
                return PLUGIN_HANDLED
        }
        else if ( gMaxPowersLeft[id][heroLevel] <= 0 ) {
                chatMessage(id, _, "Bu levelde daha fazla hero secemezsiniz.")
                menuSuperPowers(id, gPlayerMenuOffset[id])
                return PLUGIN_HANDLED
        }

        new message[256]
        if ( !gSuperHeros[heroIndex][requiresKeys] ) {
                formatex(message, charsmax(message), "OTOMATIK GUC: %s^n%s", gSuperHeros[heroIndex][superpower], gSuperHeros[heroIndex][help])
        }
        else {
                formatex(message, charsmax(message), "BIND EDILMIS GUC ^"+POWER%d^": %s^n%s", gPlayerBinds[id][0]+1, gSuperHeros[heroIndex][superpower], gSuperHeros[heroIndex][help])
        }

        // Show the Hero Picked
        set_hudmessage(100, 100, 0, -1.0, 0.2, 0, 1.0, 5.0, 0.1, 0.2, -1)
        ShowSyncHudMsg(id, gHeroHudSync, "%s", message)

        // Bind Keys / Set Powers
        gPlayerPowers[id][0] = playerpowercount + 1
        gPlayerPowers[id][playerpowercount + 1] = heroIndex

        //Init This Hero!
        initHero(id, heroIndex, SH_HERO_ADD)
        displayPowers(id, true)

        // Show the Menu Again if they don't have enough skills yet!
        menuSuperPowers(id, gPlayerMenuOffset[id])

        return PLUGIN_HANDLED
}
//----------------------------------------------------------------------------------------------
clearPower(id, level)
{
        new heroIndex = gPlayerPowers[id][level]

        if ( heroIndex < 0 || heroIndex >= gSuperHeroCount ) return

        // Ok shift over any levels higher
        new playerpowercount = getPowerCount(id)
        for ( new x = level; x <= playerpowercount && x <= SH_MAXLEVELS; x++ ) {
                if ( x != SH_MAXLEVELS ) gPlayerPowers[id][x] = gPlayerPowers[id][x + 1]
        }

        new powers = gPlayerPowers[id][0]--
        if ( powers < 0 ) gPlayerPowers[id][0] = 0

        //Clear out powers higher than powercount
        for ( new x = powers + 1; x <= gNumLevels && x <= SH_MAXLEVELS; x++ ) {
                gPlayerPowers[id][x] = -1
        }

        // Disable this power
        initHero(id, heroIndex, SH_HERO_DROP)

        // Display Levels will have to rebind this heroes powers...
        gPlayerBinds[id][0] = 0
}
//----------------------------------------------------------------------------------------------
public cl_clearpowers(id)
{
        if ( !get_pcvar_num(sv_superheros) ) {
                console_print(id, "[SH] Superhero mod kapali")
                return PLUGIN_HANDLED
        }

        if ( !get_pcvar_num(sh_alivedrop) && is_user_alive(id) ) {
                console_print(id, "[SH] Canliyken herolari atamazsiniz.")
                chatMessage(id, _, "Canliyken herolari atamazsiniz.")
                return PLUGIN_HANDLED
        }

        // When Client Fires, there won't be a 2nd parm (dispStatusText), so let's just make it true
        clearAllPowers(id, true)
        console_print(id, "[SH] Herolariniz sifirlandi bastan secebilirsiniz.")

        return PLUGIN_HANDLED
}
//----------------------------------------------------------------------------------------------
clearAllPowers(id, bool:dispStatusText)
{
        // OK to fire if mod is off since we want heroes to clean themselves up
        gPlayerPowers[id][0] = 0
        gPlayerBinds[id][0] = 0

        new heroIndex
        new bool:userConnected = is_user_connected(id) ? true : false

        // Clear the power before sending the drop init
        for ( new x = 1; x <= gNumLevels && x <= SH_MAXLEVELS; x++ ) {

                // Save heroid for init forward
                heroIndex = gPlayerPowers[id][x]

                // Clear All Power slots for player
                gPlayerPowers[id][x] = -1

                // Only send drop on heroes user has
                if ( heroIndex != -1 && userConnected ) {
                        initHero(id, heroIndex, SH_HERO_DROP)  // Disable this power
                }
        }

        if ( dispStatusText && userConnected ) {
                displayPowers(id, true)
                menuSuperPowers(id, gPlayerMenuOffset[id])
        }
}
//----------------------------------------------------------------------------------------------
public cl_superpowermenu(id)
{
        menuSuperPowers(id, 0)
}
//----------------------------------------------------------------------------------------------
public ham_PlayerSpawn_Post(id)
{
        if ( !get_pcvar_num(sv_superheros) ) return HAM_IGNORED

        // The very first Ham_Spawn on a user will happen when he is
        // created, this user is not spawned alive into the game.
        // Alive check will block first Ham_Spawn call for clients.
        // Team check will block first Ham_Spawn call for bots. (bots pass alive check)
        if ( !is_user_alive(id) ) return HAM_IGNORED
        if ( cs_get_user_team(id) == CS_TEAM_UNASSIGNED ) return HAM_IGNORED

        //Prevents non-saved XP servers from having loading issues
        if ( !gLongTermXP ) gReadXPNextRound[id] = false

        //Cancel the ultimate timer task on any new spawn
        //It is up to the hero to set the variable back to false
        remove_task(id+SH_COOLDOWN_TASKID, 1)                // 1 = look outside this plugin

        //Sets the stun and god timers back to normal
        gPlayerStunTimer[id] = -1
        gPlayerGodTimer[id] = -1
        set_user_godmode(id, 0)

        //These must be checked here to set the max variables correctly
        getMaxHealth(id)
        getMaxArmor(id)

        //Prevents this whole function from being called if its not a new round
        if ( !gNewRoundSpawn[id] ) {
                displayPowers(id, true)

                //Let heroes know someone just spawned mid-round
                ExecuteForward(fwd_Spawn, fwdReturn, id, 0)

                return HAM_IGNORED
        }

        if ( !gBetweenRounds ) setSpeedPowers(id, false)

        // Read the XP!
        if ( gFirstRound[id] ) {
                gFirstRound[id] = false
        }
        else if ( gReadXPNextRound[id] ) {
                readXP(id)
        }

        //MercyXP system
        if ( gGiveMercyXP && !gReadXPNextRound[id] && !gBlockMercyXp[id] ) {
                new mercyxpmode = get_pcvar_num(sh_mercyxpmode)

                if ( mercyxpmode != 0 && gPlayerStartXP[id] >= gPlayerXP[id] && get_playersnum() > get_pcvar_num(sh_minplrsbhxp) ) {
                        new XPtoGive = 0
                        new mercyxp = get_pcvar_num(sh_mercyxp)

                        if ( mercyxpmode == 1 ) {
                                XPtoGive = mercyxp
                        }
                        else if ( mercyxpmode == 2 && gPlayerLevel[id] <= mercyxp ) {
                                new giveLvl = mercyxp - gPlayerLevel[id]
                                XPtoGive = gXPGiven[giveLvl] / 2
                        }

                        if ( XPtoGive != 0 ) {
                                localAddXP(id, XPtoGive)
                                chatMessage(id, _, "Size %d MerhametXp verildi", XPtoGive)
                        }
                }
                gPlayerStartXP[id] = gPlayerXP[id]
        }

        //Display the XP and bind powers to their screen
        displayPowers(id, true)

        //Shows menu if the person is not in it already, always show for bots to choose powers
        if ( !gInMenu[id] && (is_user_bot(id) || !(gPlayerFlags[id] & SH_FLAG_NOAUTOMENU)) ) {
                menuSuperPowers(id, gPlayerMenuOffset[id])
        }

        //Prevents resetHUD from getting called twice in a round
        gNewRoundSpawn[id] = false

        //Reset this check for the mercyxp system
        gBlockMercyXp[id] = false

        //Prevents People from going invisible randomly
        set_user_rendering(id)

        //Makes armor system more reliable, also forces armor to reset if survived round
        //Note: might need to call this after forward is sent
        if ( getMaxArmor(id) != 0 && !(id == gXpBounsVIP && (getVipFlags()&VIP_BLOCK_ARMOR)) ) {
                cs_set_user_armor(id, 0, CS_ARMOR_NONE)
        }

        //Let heroes know someone just spawned from a new round
        ExecuteForward(fwd_Spawn, fwdReturn, id, 1)

        return HAM_IGNORED
}
//----------------------------------------------------------------------------------------------
//New Round
public event_HLTV()
{
        gRoundFreeze = true
        gRoundStarted = false

        //Remove all Monster Mod monsters, stops them from attacking during freezetime
        if ( gMonsterModRunning ) {
                new flags, monster = -1
                while ( (monster = engfunc(EngFunc_FindEntityByString, monster, "classname", "func_wall")) != 0 ) {
                        flags = pev(monster, pev_flags)
                        if ( flags & FL_MONSTER ) {
                                    set_pev(monster, pev_flags, flags | FL_KILLME)
                        }
                }
        }

        //Lets let all the heroes know
        ExecuteForward(fwd_NewRound, fwdReturn)
}
//----------------------------------------------------------------------------------------------
public round_Start()
{
        if ( !get_pcvar_num(sv_superheros) ) return

        gRoundFreeze = false
        gBetweenRounds = false

        set_task(0.1, "roundStartDelay")
}
//----------------------------------------------------------------------------------------------
public roundStartDelay()
{
        for ( new x = 1; x <= gServersMaxPlayers; x++ ) {
                displayPowers(x, true)
                //Prevents People from going invisible randomly
                if ( is_user_alive(x) ) set_user_rendering(x)
        }

        gRoundStarted = true

        //Lets let all the heroes know
        ExecuteForward(fwd_RoundStart, fwdReturn)
}
//----------------------------------------------------------------------------------------------
public round_Restart()
{
        // Round end is not called when round is set to restart, so lets just force it right away.
        round_End()
        gGiveMercyXP = false
}
//----------------------------------------------------------------------------------------------
public round_End()
{
        gBetweenRounds = true

        gGiveMercyXP = false

        new CsTeams:idTeam

        for (new id = 1; id <= gServersMaxPlayers; id++) {
                gNewRoundSpawn[id] = true

                if ( !is_user_connected(id) ) continue

                idTeam = cs_get_user_team(id)

                if ( idTeam == CS_TEAM_UNASSIGNED ) continue

                gFirstRound[id] = false

                // Player must be on a team beyond this point
                // Find if anyone needs mercy xp to avoid the more expenisve check during spawn
                if ( idTeam == CS_TEAM_SPECTATOR ) continue

                if ( !gBlockMercyXp[id] ) {
                        gGiveMercyXP = true
                }
        }

        //Check CVARS for invalid settings
        cvarCheck()

        //Save XP Data
        if ( get_pcvar_num(sh_endroundsave) ) set_task(2.0, "memoryTableWrite")

        //Lets let all the heroes know
        ExecuteForward(fwd_RoundEnd, fwdReturn)
}
//----------------------------------------------------------------------------------------------
public cl_fullupdate(id)
{
        // This blocks "fullupdate" from resetting the HUD and doing bad things to heroes
        if ( is_user_alive(id) ) return PLUGIN_HANDLED

        return PLUGIN_CONTINUE
}
//----------------------------------------------------------------------------------------------
public powerKeyDown(id)
{
        if ( !get_pcvar_num(sv_superheros) || !is_user_connected(id) ) return PLUGIN_HANDLED

        // re-entrency check to prevent aliasing muliple powerkeys - currently untested
        //new Float:gametime = get_gametime()
        //if ( gametime - gLastKeydown[id] < 0.2 ) return PLUGIN_HANDLED
        //gLastKeydown[id] = gametime

        new cmd[12], whichKey
        read_argv(0, cmd, charsmax(cmd))
        whichKey = str_to_num(cmd[6])

        if ( whichKey > SH_MAXBINDPOWERS || whichKey <= 0 ) return PLUGIN_CONTINUE

        debugMsg(id, 5, "power%d Pressed", whichKey)

        // Check if player is a VIP
        if ( id == gXpBounsVIP && getVipFlags() & VIP_BLOCK_POWERKEYS ) {
                sh_sound_deny(id)
                chatMessage(id, _, "VIP'ler super guc kullanamaz!")
                return PLUGIN_HANDLED
        }

        // Make sure player isn't stunned
        if ( gPlayerStunTimer[id] > 0 ) {
                sh_sound_deny(id)
                return PLUGIN_HANDLED
        }

        // Make sure there is a power bound to this key!
        if ( whichKey > gPlayerBinds[id][0] ) {
                sh_sound_deny(id)
                return PLUGIN_HANDLED
        }

        new heroIndex = gPlayerBinds[id][whichKey]
        if ( heroIndex < 0 || heroIndex >= gSuperHeroCount ) return PLUGIN_HANDLED

        //Make sure they are not already using this keydown
        if (gInPowerDown[id][whichKey]) return PLUGIN_HANDLED
        gInPowerDown[id][whichKey] = true

        if ( playerHasPower(id, heroIndex) ) {
#if defined SH_BACKCOMPAT
                if ( gEventKeyDown[heroIndex][0] != '^0' ) {
                        server_cmd("%s %d", gEventKeyDown[heroIndex], id )
                }
                else {
#endif
                        ExecuteForward(fwd_HeroKey, fwdReturn, id, heroIndex, SH_KEYDOWN)
#if defined SH_BACKCOMPAT
                }
#endif
        }

        return PLUGIN_HANDLED
}
//----------------------------------------------------------------------------------------------
public powerKeyUp(id)
{
        if ( !get_pcvar_num(sv_superheros) || !is_user_connected(id) ) return PLUGIN_HANDLED

        new cmd[12], whichKey
        read_argv(0, cmd, charsmax(cmd))
        whichKey = str_to_num(cmd[6])

        if ( whichKey > SH_MAXBINDPOWERS || whichKey <= 0 ) return PLUGIN_CONTINUE

        if ( id == gXpBounsVIP && getVipFlags() & VIP_BLOCK_POWERKEYS ) return PLUGIN_HANDLED

        // Make sure player isn't stunned (unless they were in keydown when stunned)
        if ( gPlayerStunTimer[id] > 0 && !gInPowerDown[id][whichKey] )  return PLUGIN_HANDLED

        //Set this key as NOT in use anymore
        gInPowerDown[id][whichKey] = false

        debugMsg(id, 5, "power%d Released", whichKey)

        // Make sure there is a power bound to this key!
        if ( whichKey > gPlayerBinds[id][0] ) return PLUGIN_HANDLED

        new heroIndex = gPlayerBinds[id][whichKey]
        if ( heroIndex < 0 || heroIndex >= gSuperHeroCount ) return PLUGIN_HANDLED

        if ( playerHasPower(id, heroIndex) ) {
#if defined SH_BACKCOMPAT
                if ( gEventKeyUp[heroIndex][0] != '^0' ) {
                        server_cmd("%s %d", gEventKeyUp[heroIndex], id )
                }
                else {
#endif
                        ExecuteForward(fwd_HeroKey, fwdReturn, id, heroIndex, SH_KEYUP)
#if defined SH_BACKCOMPAT
                }
#endif
        }

        return PLUGIN_HANDLED
}
//----------------------------------------------------------------------------------------------
public event_CurWeapon(id)
{
        // Change Weapon gets called  even when a player fires a weapon
        // To avoid spamming - set speed only when weapon is not the current weapon
        // Changing Weapons Resets the User speed!

        if ( !get_pcvar_num(sv_superheros) || !is_user_alive(id) ) return

        new weaponid = read_data(2)

        if ( gCurrentWeapon[id] != weaponid ) {
                gCurrentWeapon[id] = weaponid
                setSpeedPowers(id, false)
                //setGravityPowers(id)
        }
}
//----------------------------------------------------------------------------------------------
public event_SetFOV(id)
{
        // Sniper rifle scoping can reset user speed lets fix that

        if ( !get_pcvar_num(sv_superheros) || !is_user_alive(id) ) return

        new fov = read_data(1)

        if ( gCurrentFOV[id] != fov ) {
                gCurrentFOV[id] = fov

                switch(gCurrentWeapon[id]) {
                        // Only need to check speed for sniper rifles
                        case  CSW_SCOUT, CSW_SG550, CSW_AWP, CSW_G3SG1: {
                                setSpeedPowers(id, false)
                        }
                }
        }
}
//----------------------------------------------------------------------------------------------
public setPowers(id)
{
        if ( !is_user_alive(id) ) return

        setSpeedPowers(id, false)
        setArmorPowers(id)
        setGravityPowers(id)
        setHealthPowers(id)
}
//----------------------------------------------------------------------------------------------
//native sh_reset_max_speed(id)
public _sh_reset_max_speed()
{
        if ( !get_pcvar_num(sv_superheros) ) return

        new id = get_param(1)

        if ( !is_user_alive(id) ) return

        setSpeedPowers(id, true)
}
//----------------------------------------------------------------------------------------------
setSpeedPowers(id, bool:checkDefault)
{
        if ( !get_pcvar_num(sv_superheros) ) return
        if ( !is_user_alive(id) || gRoundFreeze || gReadXPNextRound[id] ) return

        if ( gPlayerStunTimer[id] > 0 ) {
                new Float:stunSpeed = gPlayerStunSpeed[id]
                set_user_maxspeed(id, stunSpeed)
                debugMsg(id, 5, "Sersemletme hız ayari %f", stunSpeed)
                return
        }

        new currentWeapon = gCurrentWeapon[id]
        new Float:oldSpeed = get_user_maxspeed(id)
        new Float:newSpeed = getMaxSpeed(id, currentWeapon)

        debugMsg(id, 10, "Hiz Denetlemesi - Eski: %f - Yeni: %f", oldSpeed, newSpeed)

        // OK SET THE SPEED
        if ( newSpeed != oldSpeed ) {
                switch(newSpeed) {
                        case -1.0: {
                                if ( checkDefault ) {
                                        if ( id == gXpBounsVIP ) {
                                                //Still need to check this because vip speed may not be blocked
                                                //and user may not have a hero with current weapon speed
                                                set_user_maxspeed(id, 227.0)
                                        }
                                        else {
                                                // Set default weapon speed
                                                // Do not need to check for scoped sniper rifles as getMaxSpeed will
                                                // return that value since heroes can not effect scoped sniper rifles.
                                                set_user_maxspeed(id, sh_get_weapon_speed(currentWeapon))
                                        }
                                }
                        }
                        default: {
                                set_user_maxspeed(id, newSpeed)
                                debugMsg(id, 5, "Hiz ayarlamasi %f", newSpeed)
                        }
                }
        }
}
//----------------------------------------------------------------------------------------------
setHealthPowers(id)
{
        if ( !get_pcvar_num(sv_superheros) ) return
        if ( !is_user_alive(id) || gReadXPNextRound[id] ) return

        new oldHealth = get_user_health(id)
        new newHealth = getMaxHealth(id)

        // Can't get health in the middle of a round UNLESS you didn't get shot...
        if ( oldHealth < newHealth && oldHealth >= 100 ) {
                debugMsg(id, 5, "Health ayarlamasi %d", newHealth)
                set_user_health(id, newHealth)
        }
}
//----------------------------------------------------------------------------------------------
public msg_Health(msgid, dest, id)
{
        // Run even when mod is off, not a big deal
        if ( !is_user_alive(id) ) return

        // Fixes bug with health multiples of 256 showing 0 HP on HUD causes keys to be reversed
        static hp
        hp = get_msg_arg_int(1)

        if ( hp % 256 == 0 ) {
                set_msg_arg_int(1, ARG_BYTE, ++hp)
        }
}
//----------------------------------------------------------------------------------------------
setArmorPowers(id)
{
        if ( !get_pcvar_num(sv_superheros) ) return
        if ( !is_user_alive(id) || gReadXPNextRound[id] ) return

        new CsArmorType:armorType
        new oldArmor = cs_get_user_armor(id, armorType)
        new newArmor = getMaxArmor(id)

        // Little check for armor system
        if ( oldArmor != 0 || oldArmor >= newArmor ) return

        // Set the armor to the correct value
        cs_set_user_armor(id, newArmor, CS_ARMOR_VESTHELM)

        debugMsg(id, 5, "Armor ayarlamasi %d", newArmor)
}
//----------------------------------------------------------------------------------------------
//native sh_reset_min_gravity(id)
public _sh_reset_min_gravity()
{
        if ( !get_pcvar_num(sv_superheros) ) return

        new id = get_param(1)

        if ( !is_user_alive(id) ) return

        resetMinGravity(id)
}
//----------------------------------------------------------------------------------------------
resetMinGravity(id)
{
        if ( !get_pcvar_num(sv_superheros) ) return

        if ( !is_user_alive(id) ) return

        new Float:newGravity = getMinGravity(id)
        if ( get_user_gravity(id) != newGravity ) {
                // Set to 1.0 or the next lowest Gravity
                set_user_gravity(id, newGravity)
        }
}
//----------------------------------------------------------------------------------------------
setGravityPowers(id)
{
        if ( !get_pcvar_num(sv_superheros) ) return
        if ( !is_user_alive(id) || gRoundFreeze || gReadXPNextRound[id] ) return

        new Float:oldGravity = 1.0
        new Float:newGravity = getMinGravity(id)

        if ( oldGravity != newGravity ) {
                debugMsg(id, 5, "Yercekimi ayarlamasi %f", newGravity)
                set_user_gravity(id, newGravity)
        }
}
//----------------------------------------------------------------------------------------------
public msg_StatusText()
{
        if ( !get_pcvar_num(sv_superheros) ) return PLUGIN_CONTINUE

        // Block sending StatusText sent by engine
        // Stops name from overwriting StatusText set by plugin
        // Will not block StatusText sent by plugin
        return PLUGIN_HANDLED
}
//----------------------------------------------------------------------------------------------
writeStatusMessage(id, const message[64])
{
        // Crash Check, bots will crash server is message sent to them
        if ( !is_user_connected(id) || is_user_bot(id) ) return

        // Message is a max of 64 characters including null terminator
        // Place in unreliable stream, not a necessary message
        message_begin(MSG_ONE_UNRELIABLE, gmsgStatusText, _, id)
        write_byte(0)
        write_string(message)
        message_end()
}
//----------------------------------------------------------------------------------------------
displayPowers(id, bool:setThePowers)
{
        if ( !get_pcvar_num(sv_superheros) || !is_user_connected(id) ) return

        // To avoid recursion - displayPowers will call clearPowers<->Display Power Loop if we don't check for player powers
        if ( gIsPowerBanned[id] ) {
                clearAllPowers(id, false) // Avoids Recursion with false
                writeStatusMessage(id, "[SH] Super guc kullanmaniz yasaklandi")
                return
        }
        else if ( gReadXPNextRound[id] ) {
                debugMsg(id, 5, "XP will load next round")
                writeStatusMessage(id, "[SH] Leveliniz sonraki roundda yuklenecek")
                return
        }

        debugMsg(id, 5, "Goruntuleme ve Guc ayarlamalari")

        // OK Test What Level this Fool is
        testLevel(id)

        new message[64], temp[64]
        new heroIndex, MaxBinds, count, playerLevel, playerpowercount
        new menuid, mkeys

        count = 0
        playerLevel = gPlayerLevel[id]

        if ( playerLevel < gNumLevels ) {
                formatex(message, charsmax(message), "LVL:%d/%d XP:(%d/%d)", playerLevel, gNumLevels, gPlayerXP[id], gXPLevel[playerLevel+1])
        }
        else {
                formatex(message, charsmax(message), "LVL:%d/%d XP:(%d)", playerLevel, gNumLevels, gPlayerXP[id])
        }

        //Resets All Bind assignments
        MaxBinds = min(get_pcvar_num(sh_maxbinds), SH_MAXBINDPOWERS)
        for ( new x = 1; x <= MaxBinds; x++ ) {
                gPlayerBinds[id][x] = -1
        }

        playerpowercount = getPowerCount(id)

        for ( new x = 1; x <= gNumLevels && x <= playerpowercount; x++ ) {
                heroIndex = gPlayerPowers[id][x]
                if ( -1 < heroIndex < gSuperHeroCount ) {
                        // 2 types of heroes - auto heroes and bound heroes...
                        // Bound Heroes require special work...
                        if ( gSuperHeros[heroIndex][requiresKeys] ) {
                                count++
                                if (count <= 3) {
                                        if ( message[0] != '^0') add(message, charsmax(message), " ")
                                        formatex(temp, charsmax(temp), "%d=%s", count, gSuperHeros[heroIndex])
                                        add(message, charsmax(message), temp)
                                }
                                // Make sure this players keys are bound correctly
                                if ( count <= get_pcvar_num(sh_maxbinds) && count <= SH_MAXBINDPOWERS ) {
                                        gPlayerBinds[id][count] = heroIndex
                                        gPlayerBinds[id][0] = count
                                }
                                else {
                                        clearPower(id, x)
                                }
                        }
                }
        }

        if ( is_user_alive(id) ) {
                writeStatusMessage(id, message)
                if ( setThePowers ) set_task(0.6, "setPowers", id)
        }

        // Update menu incase already in menu and levels changed
        // or user is no longer in menu
        get_user_menu(id, menuid, mkeys)
        if ( menuid != gMenuID ) {
                gInMenu[id] = false
        }
        else {
                menuSuperPowers(id, gPlayerMenuOffset[id])
        }
}
//----------------------------------------------------------------------------------------------
//This function is the ONLY way this plugin should add/subtract XP to a player
//There are checks to prevent overflowing
//To take XP away just send the function a negative (-) number
localAddXP(id, xp)
{
        new playerXP = gPlayerXP[id]
        new newTotal = playerXP + xp

        if ( xp > 0 && newTotal < playerXP ) {
                // Max possible signed 32bit int
                gPlayerXP[id] = 2147483647
        }
        else if ( xp < 0 && (newTotal < -1000000 || newTotal > playerXP) ) {
                gPlayerXP[id] = -1000000
        }
        else {
                gPlayerXP[id] = newTotal
        }
}
//----------------------------------------------------------------------------------------------
//native sh_add_kill_xp(id, victim, Float:multiplier = 1.0)
public _sh_add_kill_xp()
{
        new id = get_param(1)
        new victim = get_param(2)

        // Stupid check - but checking prevents crashes
        if ( id < 1 || id > gServersMaxPlayers || victim < 1 || victim > gServersMaxPlayers ) return

        //new Float:mult = get_param_f(3)
        localAddXP(id, floatround(get_param_f(3) * gXPGiven[gPlayerLevel[victim]]))
        displayPowers(id, false)
}
//----------------------------------------------------------------------------------------------
//native sh_set_hero_dmgmult(heroID, pcvarDamage, const weaponID = 0)
public _sh_set_hero_dmgmult()
{
        new heroIndex = get_param(1)

        if ( heroIndex < 0 || heroIndex >= gSuperHeroCount ) return

        new pcvarDamageMult = get_param(2)
        new weaponID = get_param(3)

        debugMsg(0, 3, "Set Damage Multiplier -> HeroID: %d - Multiplier: %d - Weapon: %d", heroIndex, get_pcvar_num(pcvarDamageMult), weaponID)

        gHeroMaxDamageMult[heroIndex][weaponID] = pcvarDamageMult // pCVAR expected!
}
//----------------------------------------------------------------------------------------------
Float:getMaxDamageMult(id, weaponID)
{
        if ( id == gXpBounsVIP && getVipFlags() & VIP_BLOCK_EXTRADMG ) return 1.0

        static Float:returnDmgMult, x
        static playerpowercount, heroIndex, heroDmgMultPointer
        returnDmgMult = 1.0
        playerpowercount = getPowerCount(id)

        for ( x = 1; x <= playerpowercount; x++ ) {
                heroIndex = gPlayerPowers[id][x]
                if ( -1 < heroIndex < gSuperHeroCount ) {
                        // Check hero for All weapons wildcard first
                        heroDmgMultPointer = gHeroMaxDamageMult[heroIndex][0]
                        if ( !heroDmgMultPointer ) {
                                // Check hero for weapon that was passed in
                                heroDmgMultPointer = gHeroMaxDamageMult[heroIndex][weaponID]

                                if ( !heroDmgMultPointer ) continue
                        }

                        returnDmgMult = floatmax(returnDmgMult, get_pcvar_float(heroDmgMultPointer))
                }
        }

        return returnDmgMult
}
//----------------------------------------------------------------------------------------------
public ham_TakeDamage_Pre(victim, inflictor, attacker, Float:damage, damagebits)
{
        if ( damage <= 0.0 ) return HAM_IGNORED
        if ( !is_user_connected(attacker) || !is_user_alive(victim) ) return HAM_IGNORED
        //if ( victim != attacker && cs_get_user_team(victim) == cs_get_user_team(attacker) && !get_pcvar_num(sh_ffa) ) return HAM_IGNORED
        if ( attacker == gXpBounsVIP && getVipFlags() & VIP_BLOCK_EXTRADMG ) return HAM_IGNORED

        new weaponID
        if ( damagebits & (1<<24) )
        {
                weaponID = CSW_HEGRENADE
        }
        else if ( damagebits & DMG_BULLET && inflictor == attacker )
        {
                //includes knife and any other weapon
                weaponID = get_user_weapon(attacker)
        }

        //Damage not from a CS weapon
        if ( !weaponID ) return HAM_IGNORED

        new Float:dmgmult = getMaxDamageMult(attacker, weaponID)

        //Damage is not increased damage
        if ( dmgmult <= 1.0 ) return HAM_IGNORED

        SetHamParamFloat(4, (damage * dmgmult))

        return HAM_HANDLED
}
//----------------------------------------------------------------------------------------------
//native sh_extra_damage(victim, attacker, damage, const wpnDescription[], headshot = 0, dmgMode = SH_DMG_MULT, bool:dmgStun = false, bool:dmgFFmsg = true, const dmgOrigin[3] = {0,0,0});
public _sh_extra_damage()
{
        new victim = get_param(1)

        if ( !is_user_alive(victim) || get_user_godmode(victim) ) return

        new attacker = get_param(2)

        if ( !is_user_connected(attacker) ) return

        if ( attacker == gXpBounsVIP && getVipFlags() & VIP_BLOCK_EXTRADMG ) return

        new damage = get_param(3)

        new mode = get_param(6)

        new health = get_user_health(victim)
        new CsArmorType:armorType
        new plrArmor = cs_get_user_armor(victim, armorType)

        if ( mode == SH_DMG_KILL ) {
                damage = health
        }
        else {
                if ( damage <= 0 ) return

                // *** Damage calculation due to armor from: multiplayer/dlls/player.cpp ***
                // *** Note: this is not exactly CS damage method because we do not have that sdk ***
                new Float:flDamage = float(damage)
                new Float:flNewDamage = flDamage * SH_ARMOR_RATIO
                new Float:flArmor = (flDamage - flNewDamage) * SH_ARMOR_BONUS

                // Does this use more armor than we have figured for?
                if ( flArmor > float(plrArmor) ) {
                        flArmor = float(plrArmor) * ( 1 / SH_ARMOR_BONUS )
                        flNewDamage = flDamage - flArmor
                        plrArmor = 0
                }
                else {
                        plrArmor = floatround(plrArmor - flArmor)
                }

                if ( mode == SH_DMG_NORM ) damage = floatround(flNewDamage)
                //*** End of damage-armor calculations ***
        }

        new newHealth = health - damage
        new FFon = get_pcvar_num(mp_friendlyfire)
        new freeforall = get_pcvar_num(sh_ffa)
        new CsTeams:victimTeam = cs_get_user_team(victim)
        new CsTeams:attackerTeam = cs_get_user_team(attacker)

        if ( newHealth < 1 ) {
                new bool:kill
                new headshot = get_param(5)
                new attackerFrags = get_user_frags(attacker)
                new attackerMoney = cs_get_user_money(attacker)

                if ( victim == attacker ) {
                        kill = true
                }
                else if ( victimTeam != attackerTeam || ( FFon && freeforall ) ) {
                        kill = true

                        new Float:hsmult = get_pcvar_float(sh_hsmult)
                        if ( headshot && hsmult > 1.0 ) {
                                localAddXP(attacker, floatround(gXPGiven[gPlayerLevel[victim]] * hsmult))
                        }
                        else {
                                localAddXP(attacker, gXPGiven[gPlayerLevel[victim]])
                        }

                        set_user_frags(attacker, ++attackerFrags)

                        // Frag gives $300, make sure not to go over max
                        if ( attackerMoney < 16000 ) {
                                new money = min((attackerMoney + 300), 16000)
                                cs_set_user_money(attacker, money, 1)
                        }
                }
                else if ( FFon ) {
                        kill = true

                        localAddXP(attacker, -gXPGiven[gPlayerLevel[attacker]])

                        gBlockMercyXp[attacker] = true

                        set_user_frags(attacker, --attackerFrags)

                        client_print(attacker, print_center, "Bir takim arkadasinizi oldurdunuz")

                        // Teamkill removes $3300, make sure not to go under min
                        if ( attackerMoney > 0 ) {
                                new money = max((attackerMoney - 3300), 0)
                                cs_set_user_money(attacker, money, 1)
                        }
                }

                if ( !kill ) return

                new wpnDescription[32]
                get_string(4, wpnDescription, charsmax(wpnDescription))

                // Kill the victim and block the message
                set_msg_block(gmsgScoreInfo, BLOCK_ONCE)

                gXrtaDmgClientKill = true
                // Save info to change HUD death message and send forward with correct info
                copy(gXrtaDmgWpnName, charsmax(gXrtaDmgWpnName), wpnDescription)
                gXrtaDmgAttacker = attacker
                gXrtaDmgHeadshot = headshot
                // Kill the victim
                // pev_dmg_inflictor not set becase this will be self even if we did set it
                dllfunc(DLLFunc_ClientKill, victim)
                gXrtaDmgClientKill = false

                // Log the Kill
                logKill(attacker, victim, wpnDescription)

                // Make camera turn toward attacker on death, thx Emp`
                set_pev(victim, pev_iuser3, attacker)

                // ClientKill removes a frag, give it back if not self inflicted
                new victimFrags = get_user_frags(victim)
                if ( victim != attacker ) {
                        set_user_frags(victim, ++victimFrags)

                        // Update attacker's statustext since his xp changed
                        displayPowers(attacker, false)

                        // Update victims scoreboard with correct info
                        message_begin(MSG_ALL, gmsgScoreInfo)
                        write_byte(victim)
                        write_short(victimFrags)
                        write_short(cs_get_user_deaths(victim))
                        write_short(0)
                        write_short(_:victimTeam)
                        message_end()
                }

                // Update killers scoreboard with new info
                message_begin(MSG_ALL, gmsgScoreInfo)
                write_byte(attacker)
                write_short(attackerFrags)
                write_short(cs_get_user_deaths(attacker))
                write_short(0)
                write_short(_:attackerTeam)
                message_end()
        }
        else {
                new bool:hurt = false
                if ( victimTeam != attackerTeam || victim == attacker || ( FFon && freeforall ) ) {
                        hurt = true
                }
                else if ( FFon ) {
                        hurt = true
                        //new bool:dmgFFmsg = get_param(6) ? true : false
                        if ( get_param(8) ) {
                                new name[32]
                                get_user_name(attacker, name, charsmax(name))
                                client_print(0, print_chat, "%s takim arkadasina saldirdi", name)
                        }
                }

                if ( !hurt ) return

                // External plugins might use this
                // This should be set to the entity that caused the
                // damage, but lets just set it to attacker for now
                set_pev(victim, pev_dmg_inflictor, attacker)

                set_user_health(victim, newHealth)

                cs_set_user_armor(victim, plrArmor, armorType)

                // Slow down from damage, does not effect z vector
                // new bool:dmgStun = get_param(7) ? true : false
                if ( get_param(7) && pev(victim, pev_movetype) & MOVETYPE_WALK ) {

                        // Fake a slowdown from damage
                        // Method needs improvement can not find how cs does it
                        // possibly use a sh_get_velocity type of method adding to current velocity
                        new Float:velocity[3]
                        pev(victim, pev_velocity, velocity)
                        velocity[0] = 0.0
                        velocity[1] = 0.0
                        // Keep [2] the same as current velocity
                        set_pev(victim, pev_velocity, velocity)
                }

                if ( is_user_bot(victim) ) return

                new Float:dmgOrigin[3]
                get_array_f(9, dmgOrigin, 3)

                if ( dmgOrigin[0] == 0.0 && dmgOrigin[1] == 0.0 && dmgOrigin[2] == 0.0 ) {
                        // Damage origin is attacker
                        pev(attacker, pev_origin, dmgOrigin)
                }

                // Damage message for showing damage bits only
                message_begin(MSG_ONE_UNRELIABLE, gmsgDamage, _, victim)
                write_byte(0)                // dmg_save
                write_byte(damage)        // dmg_take
                write_long(DMG_GENERIC)        // visibleDamageBits
                engfunc(EngFunc_WriteCoord, dmgOrigin[0])        // damageOrigin.x
                engfunc(EngFunc_WriteCoord, dmgOrigin[1])        // damageOrigin.y
                engfunc(EngFunc_WriteCoord, dmgOrigin[2])        // damageOrigin.z
                message_end()
        }
}
//---------------------------------------------------------------------------------------------
public fm_AlertMessage(atype, const msg[])
{
        // Keeps hl logs clean of commited suicide with world, caused by sh_extra_damage
        return gXrtaDmgClientKill ? FMRES_SUPERCEDE : FMRES_IGNORED
}
//---------------------------------------------------------------------------------------------
logKill(id, victim, const weaponDescription[32])
{
        new namea[32], namev[32], authida[32], authidv[32], teama[16], teamv[16]

        // Info On Attacker
        get_user_name(id, namea, charsmax(namea))
        get_user_team(id, teama, charsmax(teama))
        get_user_authid(id, authida, charsmax(authida))
        new auserid = get_user_userid(id)

        // Info On Victim
        get_user_name(victim, namev, charsmax(namev))
        get_user_team(victim, teamv, charsmax(teamv))
        get_user_authid(victim, authidv, charsmax(authidv))

        // Log This Kill
        if ( id != victim ) {
                log_message("^"%s<%d><%s><%s>^" killed ^"%s<%d><%s><%s>^" with ^"%s^"",
                        namea, auserid, authida, teama, namev, get_user_userid(victim), authidv, teamv, weaponDescription)
        }
        else {
                log_message("^"%s<%d><%s><%s>^" committed suicide with ^"%s^"",
                        namea, auserid, authida, teama, weaponDescription)
        }
}
//----------------------------------------------------------------------------------------------
public msg_DeathMsg()
{
        // Send out the sh death forwards and change the hud death message for sh_extra_damage kill
        // Run this even with sh off so forward can still run and clean up what it needs to
        new attacker, headshot
        static wpnDescription[32]

        if ( !gXrtaDmgClientKill ) {
                attacker = get_msg_arg_int(1)
                headshot = get_msg_arg_int(3)
                get_msg_arg_string(4, wpnDescription, charsmax(wpnDescription))
        }
        else {
                attacker = gXrtaDmgAttacker
                headshot = gXrtaDmgHeadshot
                copy(wpnDescription, charsmax(wpnDescription), gXrtaDmgWpnName)

                // Change HUD death message to show extradamage kill correctly
                set_msg_arg_int(1, ARG_BYTE, attacker)
                set_msg_arg_int(3, ARG_BYTE, headshot)
                set_msg_arg_string(4, wpnDescription)
        }

        // Send the sh_client_death forward
        ExecuteForward(fwd_Death, fwdReturn, get_msg_arg_int(2), attacker, headshot, wpnDescription)
}
//---------------------------------------------------------------------------------------------
// Must use death event since csx client_death does not catch worldspawn or suicides
public event_DeathMsg()
{
        if ( !get_pcvar_num(sv_superheros) ) return

        new killer = read_data(1)
        new victim = read_data(2)

        // Kill by extra damage will be skipped here since killer is self
        if ( killer && killer != victim && victim ) {

                if ( cs_get_user_team(killer) == cs_get_user_team(victim) && !get_pcvar_num(sh_ffa) ) {
                        // Killed teammate
                        gBlockMercyXp[killer] = true
                        localAddXP(killer, -gXPGiven[gPlayerLevel[killer]])
                }
                else {
                        new Float:hsmult = get_pcvar_float(sh_hsmult)
                        //new headshot = read_data(3)
                        if ( read_data(3) && hsmult > 1.0 ) {
                                localAddXP(killer, floatround(gXPGiven[gPlayerLevel[victim]] * hsmult))
                        }
                        else {
                                localAddXP(killer, gXPGiven[gPlayerLevel[victim]])
                        }
                }

                displayPowers(killer, false)
        }

        gCurrentWeapon[victim] = 0
        displayPowers(victim, false)
}
//----------------------------------------------------------------------------------------------
//native sh_reload_ammo(id, mode = 0)
public _sh_reload_ammo()
{
        new id = get_param(1)

        if ( !is_user_alive(id) ) return

        // re-entrency check
        new Float:gametime = get_gametime()
        if ( gametime - gReloadTime[id] < 0.5 ) return
        gReloadTime[id] = gametime

        new clip, ammo
        new wpnid = get_user_weapon(id, clip, ammo)
        new wpnslot = sh_get_weapon_slot(wpnid)

        if ( wpnslot != 1 && wpnslot != 2 ) return

        new mode = get_param(2)

        if ( mode == 0 ) {
                // Server decides what mode to use
                mode = get_pcvar_num(sh_reloadmode)
                if ( !mode ) return
        }

        switch(mode)
        {
                // No reload, reset max clip (most common)
                case 1: {
                        if ( clip != 0 ) return

                        new iWPNidx = -1
                        new wpn[32]
                        get_weaponname(wpnid, wpn, charsmax(wpn))

                        while ( (iWPNidx = engfunc(EngFunc_FindEntityByString, iWPNidx, "classname", wpn)) != 0 ) {
                                if (id == pev(iWPNidx, pev_owner)) {
                                        cs_set_weapon_ammo(iWPNidx, sh_get_max_clipammo(wpnid))
                                        break
                                }
                        }
                }

                // Requires reload, but reset max backpack ammo
                case 2: {
                        new maxbpammo = sh_get_max_bpammo(wpnid)
                        if ( ammo < maxbpammo ) {
                                cs_set_user_bpammo(id, wpnid, maxbpammo)
                        }
                }

                // Drop weapon and get a new one with full clip
                case 3: {
                        if ( clip != 0 ) return

                        new idSilence, idBurst
                        if ( wpnid == CSW_M4A1 || wpnid == CSW_USP ) {
                                new iWPNidx = -1
                                new wpn[32]
                                get_weaponname(wpnid, wpn, charsmax(wpn))
                                while ( (iWPNidx = engfunc(EngFunc_FindEntityByString, iWPNidx, "classname", wpn)) != 0 ) {
                                        if (id == pev(iWPNidx, pev_owner)) {
                                                idSilence = cs_get_weapon_silen(iWPNidx)
                                                break
                                        }
                                }
                        }
                        else if ( wpnid == CSW_FAMAS || wpnid == CSW_GLOCK18 ) {
                                new iWPNidx = -1
                                new wpn[32]
                                get_weaponname(wpnid, wpn, charsmax(wpn))
                                while ( (iWPNidx = engfunc(EngFunc_FindEntityByString, iWPNidx, "classname", wpn)) != 0 ) {
                                        if (id == pev(iWPNidx, pev_owner)) {
                                                idBurst = cs_get_weapon_burst(iWPNidx)
                                                break
                                        }
                                }
                        }

                        dropWeapon(id, wpnid, true)

                        new entityID = giveWeapon(id, wpnid, true)

                        if ( idSilence ) {
                                cs_set_weapon_silen(entityID, idSilence, 0)
                        }
                        else if ( idBurst ) {
                                cs_set_weapon_burst(entityID, idBurst)
                        }

                        // Recheck speed just in case above not caught by CurWeapon
                        setSpeedPowers(id, false)
                }
        }
}
//----------------------------------------------------------------------------------------------
timerAll()
{
        static id
        for ( id = 1; id <= gServersMaxPlayers; id++ ) {
                if ( is_user_alive(id) ) {
                        // Switches are faster but we don't want to do anything with -1
                        switch(gPlayerStunTimer[id]) {
                                case -1: {/*Do nothing*/}
                                case 0: {
                                        gPlayerStunTimer[id] = -1
                                        setSpeedPowers(id, true)
                                }
                                default: {
                                        gPlayerStunTimer[id]--
                                        gPlayerStunSpeed[id] = get_user_maxspeed(id) //is this really needed?
                                }
                        }

                        switch(gPlayerGodTimer[id]) {
                                case -1: {/*Do nothing*/}
                                case 0: {
                                        gPlayerGodTimer[id] = -1
                                        set_user_godmode(id, 0)
                                        sh_set_rendering(id)
                                }
                                default: {
                                        gPlayerGodTimer[id]--
                                }
                        }
                }
                else {
                        gPlayerStunTimer[id] = -1
                        gPlayerGodTimer[id] = -1
                }
        }
}
//----------------------------------------------------------------------------------------------
//native sh_set_stun(id, Float:howLong, Float:speed = 0.0)
public _sh_set_stun()
{
        if ( !get_pcvar_num(sv_superheros) ) return

        new id = get_param(1)

        if ( !is_user_alive(id) ) return

        new Float:howLong = get_param_f(2)

        if ( howLong > gPlayerStunTimer[id] ) {
                new Float:speed = get_param_f(3)
                debugMsg(id, 5, "Stunning for %f seconds at %f speed", howLong, speed)
                gPlayerStunTimer[id] = floatround(howLong)
                gPlayerStunSpeed[id] = speed
                set_user_maxspeed(id, speed)
        }
}
//----------------------------------------------------------------------------------------------
//native sh_get_stun(id)
public _sh_get_stun()
{
        if ( !get_pcvar_num(sv_superheros) ) return 0

        new id = get_param(1)

        if ( !is_user_alive(id) ) return 0

        return gPlayerStunTimer[id] > 0 ? 1 : 0
}
//----------------------------------------------------------------------------------------------
//native sh_set_godmode(id, Float:howLong)
public _sh_set_godmode()
{
        if ( !get_pcvar_num(sv_superheros) ) return

        new id = get_param(1)

        if ( !is_user_alive(id) ) return

        new Float:howLong = get_param_f(2)

        if ( howLong > gPlayerGodTimer[id] ) {
                debugMsg(id, 5, " %f saniye God mode var", howLong)
                sh_set_rendering(id, 0, 0, 128, 16, kRenderFxGlowShell)        // Remove the godmode glow, make heroes set it??
                set_user_godmode(id, 1)
                gPlayerGodTimer[id] = floatround(howLong)
        }
}
//----------------------------------------------------------------------------------------------
public cl_say(id)
{
        static said[192]
        read_args(said, charsmax(said))
        remove_quotes(said)

        if ( !get_pcvar_num(sv_superheros) ) {
                if ( containi(said, "powers") != -1 || containi(said, "superhero") != -1 ) {
                        chatMessage(id, _, "Superhero mod kapatildi.")
                }
                return PLUGIN_CONTINUE
        }

        // If first character is "/" start command check after that character
        new pos
        if ( said[pos] == '/' ) pos++

        if ( equali(said[pos], "superherohelp") || equali(said[pos], "help") ) {
                showHelp(id)
                return PLUGIN_CONTINUE
        }
        else if ( equali(said[pos], "herolist") ) {
                showHeroList(id)
                return PLUGIN_HANDLED
        }
        else if ( equali(said[pos], "playerskills", 12) ) {
                showPlayerSkills(id, 1, said[pos+13])
                return PLUGIN_HANDLED
        }
        else if ( equali(said[pos], "playerlevels", 12) ) {
                showPlayerLevels(id, 1, said[pos+13])
                return PLUGIN_HANDLED
        }
        else if ( equali(said[pos], "whohas", 6) ) {
                if ( said[pos+7] == '^0' ) {
                        chatMessage(id, _, "Bu komutu kullanmak icin mutlaka bir heronun adi gerekli")
                        return PLUGIN_HANDLED
                }
                showWhoHas(id, 1, said[pos+7])
                return PLUGIN_HANDLED
        }
        else if ( equali(said[pos], "myheroes") ) {
                showHeroes(id)
                return PLUGIN_HANDLED
        }
        else if ( equali(said[pos], "clearpowers") ) {
                if ( !get_pcvar_num(sh_alivedrop) && is_user_alive(id) ) {
                        chatMessage(id, _, "Canliyken herolarinizi atamazsiniz")
                        return PLUGIN_HANDLED
                }
                clearAllPowers(id, true)
                chatMessage(id, _, "Herolariniz sifirlandi bastan secebilirsiniz")
                return PLUGIN_HANDLED
        }
        else if ( equali(said[pos], "showmenu") ) {
                menuSuperPowers(id, 0)
                return PLUGIN_HANDLED
        }
        else if ( equali(said[pos], "automenu") ) {
                chatMessage(id, _, "Super guc menusunu otomatik goster %s", (gPlayerFlags[id] & SH_FLAG_NOAUTOMENU) ? "ENABLED" : "DISABLED")
                gPlayerFlags[id] ^= SH_FLAG_NOAUTOMENU
                return PLUGIN_HANDLED
        }
        else if ( equali(said[pos], "drop", 4) ) {
                dropPower(id, said)
                return PLUGIN_HANDLED
        }
        else if ( equali(said[pos], "helpon") ) {
                if ( gCMDProj > 0 ) {
                        chatMessage(id, _, "Yardim menusu aktif")
                }
                gPlayerFlags[id] |= SH_FLAG_HUDHELP
                return PLUGIN_HANDLED
        }
        else if ( equali(said[pos], "helpoff") ) {
                if ( gCMDProj > 0 ) {
                        chatMessage(id, _, "Yardim menusu kapali")
                }
                gPlayerFlags[id] &= ~SH_FLAG_HUDHELP
                return PLUGIN_HANDLED
        }
        else if ( containi(said, "powers") != -1 || containi(said, "superhero") != -1 ) {
                chatMessage(id, _, "Superhero yardimi icin, /help  yaziniz")
                return PLUGIN_CONTINUE
        }

        return PLUGIN_CONTINUE
}

//----------------------------------------------------------------------------------------------
dropPower(id, const said[])
{
        if ( !get_pcvar_num(sh_alivedrop) && is_user_alive(id) ) {
                chatMessage(id, _, "Canliyken herolarinizi atamazsiniz")
                return
        }

        new heroName[32]
        new heroIndex
        new bool:found = false

        new spaceIdx = contain(said, " ")
        if ( spaceIdx > 0 && strlen(said) > spaceIdx+2 ) {
                copy(heroName, charsmax(heroName), said[spaceIdx+1] )
        }
        else {
                chatMessage(id, _, "Lutfen atmak istediginiz heronun en az 2 harfini yaziniz")
                return
        }

        debugMsg(id, 5, "Atilan hero: %s", heroName)

        new playerpowercount = getPowerCount(id)
        for ( new x = 1; x <= playerpowercount && x <= SH_MAXLEVELS; x++ ) {
                heroIndex = gPlayerPowers[id][x]
                if ( -1 < heroIndex < gSuperHeroCount ) {
                        if ( containi( gSuperHeros[heroIndex][hero], heroName ) != -1 ) {
                                debugMsg(id, 1, "Atiliyor hero: %s", gSuperHeros[heroIndex][hero])
                                clearPower(id, x)
                                chatMessage(id, _, "Atilan hero: %s", gSuperHeros[heroIndex][hero])
                                found = true
                                break
                        }
                }
        }

        // Show the menu and the loss of power... or a message...
        if ( found ) {
                displayPowers(id, true)
                menuSuperPowers(id, gPlayerMenuOffset[id])
        }
        else {
                chatMessage(id, _, "Bu isimde bir hero yok duzgun yaziniz: %s", heroName)
        }
}
//----------------------------------------------------------------------------------------------
showHelp(id)
{
        if ( !get_pcvar_num(sv_superheros) ) return

        show_motd(id, gHelpMotd, "SuperHero Mod Yardimi")
}
//----------------------------------------------------------------------------------------------
showHeroList(id)
{
        if ( !get_pcvar_num(sv_superheros) ) return

        new buffer[1501]
        new n = 0

        n += copy(buffer[n], charsmax(buffer)-n, "<html><head><style type=^"text/css^">pre{color:#FFB000;}body{background:#000000;margin-left:8px;margin-top:0px;}</style></head><body><pre>^n")

        n += copy(buffer[n], charsmax(buffer)-n, "Tavsiye: ^"herolist^" komutunu kullanarak butun herolari goruntuleyebilirsiniz.^n^n")
        n += copy(buffer[n], charsmax(buffer)-n, "Yuklenmis Herolar (By Kakarott):^n^n")

        for (new x = 0; x < gSuperHeroCount; x++ ) {
                n += formatex(buffer[n], charsmax(buffer)-n, "%s (%d%s) - %s^n", gSuperHeros[x][hero], getHeroLevel(x), gSuperHeros[x][requiresKeys] ? "b" : "", gSuperHeros[x][superpower])
        }

        copy(buffer[n], charsmax(buffer)-n, "</pre></body></html>")

        show_motd(id, buffer, "SuperHero Listesi")
}
//----------------------------------------------------------------------------------------------
showPlayerLevels(id, say, said[])
{
        if ( !get_pcvar_num(sv_superheros) ) return

        new playerCount
        new players[SH_MAXSLOTS]

        if ( equal(said, "") ) copy(said, 30, "@ALL")

        new buffer[1501]
        new n = 0

        if ( say == 1 ) {
                n += copy(buffer[n], charsmax(buffer)-n,"<html><head><style type=^"text/css^">pre{color:#FFB000;}body{background:#000000;margin-left:8px;margin-top:0px;}</style></head><body><pre>^n")
                n += copy(buffer[n], charsmax(buffer)-n,"Player Levels:^n^n")
        }
        else {
                console_print(id, "Oyuncu Levelleri:^n")
        }

        if ( said[0] == '@' ) {
                if ( equali("T", said[1]) ) {
                        copy(said[1], 31, "TERRORIST")
                }

                if ( equali("ALL", said[1]) ) {
                        get_players(players, playerCount)
                }
                else {
                        get_players(players, playerCount, "eg", said[1])
                }
                if ( playerCount == 0 ) {
                        console_print(id, "No clients in such team")
                        return
                }
        }
        else {
                players[0] = cmd_target(id, said, CMDTARGET_ALLOW_SELF)
                if ( !players[0] ) return
                playerCount = 1
        }

        new pid, teamName[5], name[32]
        for ( new team = 2; team >= 0; team-- ) {
                for ( new x = 0; x < playerCount; x++ ) {
                        pid = players[x]
                        if ( get_user_team(pid) != team ) continue
                        get_user_name(pid, name, charsmax(name))

                        teamName[0] = '^0'
                        if ( get_user_team(pid) == 1 ) copy(teamName, charsmax(teamName), "T :")
                        else if ( get_user_team(pid) == 2 ) copy(teamName, charsmax(teamName), "CT:")
                        else copy(teamName, charsmax(teamName), "S :")

                        if ( say == 1 ) {
                                n += formatex(buffer[n], charsmax(buffer)-n, "%s%-24s (Level %d)(XP = %d)^n", teamName, name, gPlayerLevel[pid], gPlayerXP[pid])
                        }
                        else {
                                console_print(id, "%s%-24s (Level %d)(XP = %d)", teamName, name, gPlayerLevel[pid], gPlayerXP[pid])
                        }
                }
        }

        if ( say == 1 ) {
                copy(buffer[n], charsmax(buffer)-n, "</pre></body></html>")

                show_motd(id, buffer, "Oyuncularin Superhero Levelleri")
        }
        else {
                console_print(id, "")
        }
}
//----------------------------------------------------------------------------------------------
showPlayerSkills(id, say, said[])
{
        if ( !get_pcvar_num(sv_superheros) ) return

        new playerCount
        new players[SH_MAXSLOTS]
        new name[32]

        if ( equal(said,"") ) copy(said, 31, "@ALL")

        new buffer[1501]
        new n = 0
        new tn = 0
        new temp[512]

        if ( say == 1 ) {
                n += copy(buffer[n], charsmax(buffer)-n,"<html><head><style type=^"text/css^">pre{color:#FFB000;}body{background:#000000;margin-left:8px;margin-top:0px;}</style></head><body><pre>^n")

                n += copy(buffer[n], charsmax(buffer)-n,"Oyuncu Skilleri:^n^n")
        }
        else {
                console_print(id, "Player Skills:^n")
        }

        if ( said[0] == '@' ) {
                if (equali("T",said[1])) {
                        copy(said[1], 31,"TERRORIST")
                }
                if ( equali("ALL", said[1]) ) {
                        get_players(players, playerCount)
                }
                else {
                        get_players(players, playerCount, "eg", said[1] )
                }
                if ( playerCount == 0 ) {
                        console_print(id, "No clients in such team")
                        return
                }
        }
        else {
                players[0] = cmd_target(id, said, CMDTARGET_ALLOW_SELF)
                if ( !players[0] ) return
                playerCount = 1
        }

        new pid, teamName[5], idx, heroIndex, playerpowercount
        for ( new team = 2; team >= 0; team-- ) {
                for ( new x = 0; x < playerCount; x++) {
                        tn = 0
                        pid = players[x]
                        if ( get_user_team(pid) != team) continue
                        get_user_name(pid, name, charsmax(name))
                        teamName[0] = '^0'
                        if ( get_user_team(pid) == 1 ) copy(teamName, charsmax(teamName), "T :")
                        else if ( get_user_team(pid) == 2 ) copy(teamName, charsmax(teamName), "CT:")
                        else copy(teamName, charsmax(teamName), "S: ")
                        tn += formatex(temp[tn], charsmax(temp)-tn, "%s%-24s (Level %d)(XP = %d)", teamName, name, gPlayerLevel[pid], gPlayerXP[pid])
                        if (say == 0) {
                                console_print(id, "%s", temp)
                                tn = 0
                                tn += copy(temp[tn], charsmax(temp)-tn, "  ")
                        }
                        playerpowercount = getPowerCount(pid)
                        for ( idx = 1; idx <= playerpowercount; idx++ ) {
                                heroIndex = gPlayerPowers[pid][idx]
                                tn += formatex(temp[tn], charsmax(temp)-tn, "| %s ", gSuperHeros[heroIndex][hero])
                                if ( idx % 6 == 0 ) {
                                        if (say == 1) {
                                                tn += copy(temp[tn], charsmax(temp)-tn, "|^n  ")
                                        }
                                        else {
                                                tn += copy(temp[tn], charsmax(temp)-tn, "|")
                                                console_print(id, "%s", temp)
                                                tn = 0
                                                tn += copy(temp[tn], charsmax(temp)-tn, "  ")
                                        }
                                }
                        }

                        if (say == 1) {
                                copy(temp[tn], charsmax(temp)-tn, "^n^n")
                                n += copy(buffer[n], charsmax(buffer)-n, temp)
                        }
                        else {
                                if ( gPlayerPowers[pid][0] > 0 ) {
                                        copy(temp[tn], charsmax(temp)-tn, "|")
                                }
                                console_print(id, "%s", temp)
                        }
                }
        }

        if ( say == 1 ) {
                copy(buffer[n], charsmax(buffer)-n,"</pre></body></html>")

                show_motd(id, buffer, "Oyuncularin Superhero Skilleri")
        }
        else {
                console_print(id, "")
        }
}
//----------------------------------------------------------------------------------------------
showWhoHas(id, say, said[])
{
        if ( !get_pcvar_num(sv_superheros) ) return

        new who[25]
        copy(who, charsmax(who), said)

        new heroIndex = -1

        for ( new i = 0; i < gSuperHeroCount; i++ ) {
                if ( containi(gSuperHeros[i][hero], who) != -1 ) {
                        heroIndex = i
                        break
                }
        }

        if ( heroIndex < 0 ) {
                if ( say == 1 ) {
                        chatMessage(id, _, "Bu isimde bir hero bulunamadi: %s", who)
                }
                else {
                        console_print(id, "[SH] Bu isimde bir hero bulunamadi: %s", who)
                }
                return
        }

        new buffer[1501], n

        if ( say == 1 ) {
                n += copy(buffer[n], charsmax(buffer)-n,"<html><head><style type=^"text/css^">pre{color:#FFB000;}body{background:#000000;margin-left:8px;margin-top:0px;}</style></head><body><pre>^n")
        }

        n += formatex(buffer[n], charsmax(buffer)-n, "Bu Hero Kimde var?: %s^n^n", gSuperHeros[heroIndex][hero])

        // Get a List of Players
        new players[SH_MAXSLOTS], playerCount
        get_players(players, playerCount)

        new pid, teamName[5], name[32]
        for ( new team = 2; team >= 0; team-- ) {
                for (new x = 0; x < playerCount; x++) {
                        pid = players[x]
                        if ( get_user_team(pid) != team) continue
                        get_user_name(pid, name, charsmax(name))
                        teamName[0] = '^0'
                        if (!playerHasPower(pid, heroIndex)) continue
                        if ( get_user_team(pid) == 1 ) copy(teamName, charsmax(teamName), "T :")
                        else if ( get_user_team(pid) == 2 ) copy(teamName, charsmax(teamName), "CT:")
                        else copy(teamName, charsmax(teamName), "S: ")
                        n += formatex(buffer[n], charsmax(buffer)-n, "%s%-24s (Level %d)(XP = %d)^n", teamName, name, gPlayerLevel[pid], gPlayerXP[pid])
                }
        }

        if ( say == 1 ) {
                copy(buffer[n], charsmax(buffer)-n,"</pre></body></html>")

                new title[32]
                formatex(title, charsmax(title), "SuperHero bu hero kimde var?: %s", who)
                show_motd(id, buffer, title)
        }
        else {
                console_print(id, "%s", buffer)
        }
}
//----------------------------------------------------------------------------------------------
public adminSetLevel(id, level, cid)
{
        if ( !cmd_access(id, level, cid, 3) ) return PLUGIN_HANDLED

        if ( !get_pcvar_num(sv_superheros) ) {
                console_print(id, "[SH] Superhero mod kapatildi")
                return PLUGIN_HANDLED
        }

        if ( read_argc() > 3 ) {
                console_print(id, "[SH] Hata. Isim arasinda bosluk birakmayiniz")
                console_print(id, "[SH] Bu komutu kullanmak icin ismin bir kismini girmek zorundasiniz")
                return PLUGIN_HANDLED
        }

        new arg2[4]
        read_argv(2, arg2, charsmax(arg2))

        if ( !isdigit(arg2[0]) ) {
                console_print(id, "[SH] Ikinci kisim bir level olmak zorundadir.")
                console_print(id, "Usage:  amx_shsetlevel <nick | @team | @ALL | #userid> <level> - Sets SuperHero level on players")
                return PLUGIN_HANDLED
        }

        new setlevel = str_to_num(arg2)

        if ( setlevel < 0 || setlevel > gNumLevels ) {
                console_print(id, "[SH] Geçersiz Level - Geçerli Leveller = 0 - %d", gNumLevels)
                return PLUGIN_HANDLED
        }

        new arg[32]
        read_argv(1, arg, charsmax(arg))

        new authid2[32], name2[32]
        get_user_name(id, name2, charsmax(name2))
        get_user_authid(id, authid2, charsmax(authid2))

        if ( arg[0] == '@' ) {
                new players[SH_MAXSLOTS], inum
                if ( equali("T", arg[1]) ) {
                        copy(arg[1], charsmax(arg)-1, "TERRORIST")
                }

                if ( equali("ALL", arg[1]) ) {
                        get_players(players, inum)
                }
                else {
                        get_players(players, inum, "eg", arg[1])
                }

                if ( !inum ) {
                        console_print(id, "No clients in such team")
                        return PLUGIN_HANDLED
                }

                new user
                for ( new a = 0; a < inum; a++ ) {
                        user = players[a]
                        gPlayerXP[user] = gXPLevel[setlevel]
                        displayPowers(user, false)
                }

                show_activity(id, name2, "set level %d on %s players", setlevel, arg[1])

                console_print(id, "[SH] Set level %d on %s players", setlevel, arg[1])

                log_amx("[SH] ^"%s<%d><%s><>^" set level %d on %s players", name2, get_user_userid(id), authid2, setlevel, arg[1])
        }
        else {
                new player = cmd_target(id, arg, CMDTARGET_ALLOW_SELF)
                if ( !player ) return PLUGIN_HANDLED

                gPlayerXP[player] = gXPLevel[setlevel]
                displayPowers(player, false)

                new name[32], authid[32]
                get_user_name(player, name, charsmax(name))
                get_user_authid(player, authid, charsmax(authid))

                show_activity(id, name2, "set level %d on %s", setlevel, name)

                console_print(id, "[SH] Client ^"%s^" has been set to level %d", name, setlevel)

                log_amx("[SH] ^"%s<%d><%s><>^" set level %d on ^"%s<%d><%s><>^"", name2, get_user_userid(id), authid2, setlevel, name, get_user_userid(player), authid)
        }

        return PLUGIN_HANDLED
}
//----------------------------------------------------------------------------------------------
public adminSetXP(id, level, cid)
{
        if ( !cmd_access(id, level, cid, 3) ) return PLUGIN_HANDLED

        if ( !get_pcvar_num(sv_superheros) ) {
                console_print(id, "[SH] Superhero mod kapatildi")
                return PLUGIN_HANDLED
        }

        if ( read_argc() > 3 ) {
                console_print(id, "[SH] Hata. Isim arasinda bosluk birakmayiniz")
                console_print(id, "[SH] Bu komutu kullanmak icin ismin bir kismini girmek zorundasiniz")
                return PLUGIN_HANDLED
        }

        new arg2[12]
        read_argv(2, arg2, charsmax(arg2))

        if ( !(isdigit(arg2[0]) || (equal(arg2[0], "-", 1) && isdigit(arg2[1]))) ) {
                console_print(id, "[SH]  Ikinci kisim bir exp degeri olmak zorundadir.")
                return PLUGIN_HANDLED
        }

        new xp = str_to_num(arg2)

        new cmd[32], arg[32]
        new bool:giveXP = false
        read_argv(0, cmd, charsmax(cmd))
        read_argv(1, arg, charsmax(arg))

        if ( equali(cmd, "amx_shaddxp") ) giveXP = true

        new name2[32], authid2[32]
        get_user_name(id, name2, charsmax(name2))
        get_user_authid(id, authid2, charsmax(authid2))

        if ( arg[0] == '@' ) {
                new players[32], inum
                if ( equali("T", arg[1]) ) {
                        copy(arg[1], charsmax(arg)-1, "TERRORIST")
                }

                if ( equali("ALL", arg[1]) ) {
                        get_players(players, inum)
                }
                else {
                        get_players(players, inum, "eg", arg[1])
                }

                if ( !inum ) {
                        console_print(id, "No clients in such team")
                        return PLUGIN_HANDLED
                }

                new user
                for ( new a = 0; a < inum; a++ ) {
                        user = players[a]
                        if ( giveXP ) localAddXP(user, xp)
                        else gPlayerXP[user] = xp
                        displayPowers(user, false)
                }

                show_activity(id, name2, "%s %d XP on %s players", giveXP ? "added" : "set", xp, arg[1])

                console_print(id, "[SH] %s %d XP on %s players", giveXP ? "Added" : "Set", xp, arg[1])

                log_amx("[SH] ^"%s<%d><%s><>^" %s %d XP on %s players", name2, get_user_userid(id), authid2, giveXP ? "added" : "set", xp, arg[1])
        }
        else {
                new player = cmd_target(id, arg, CMDTARGET_ALLOW_SELF)
                if ( !player ) return PLUGIN_HANDLED

                if ( giveXP ) localAddXP(player, xp)
                else gPlayerXP[player] = xp
                displayPowers(player, false)

                new name[32], authid[32]
                get_user_name(player, name, charsmax(name))
                get_user_authid(player, authid, charsmax(authid))

                show_activity(id, name2, "%s %d XP on %s", giveXP ? "added" : "set", xp, name)

                console_print(id, "[SH] Client ^"%s^" has been %s %d XP", name, giveXP ? "given" : "set to", xp)

                log_amx("[SH] ^"%s<%d><%s><>^" %s %d XP on ^"%s<%d><%s><>^"", name2, get_user_userid(id), authid2, giveXP ? "added" : "set", xp, name, get_user_userid(player), authid)
        }

        return PLUGIN_HANDLED
}
//----------------------------------------------------------------------------------------------
public adminBanXP(id, level, cid)
{
        if ( !cmd_access(id, level, cid, 2) ) return PLUGIN_HANDLED

        if ( read_argc() > 2 ) {
                console_print(id, "[SH] Hata. Isim arasinda bosluk birakmayiniz")
                console_print(id, "[SH] Bu komutu kullanmak icin ismin bir kismini girmek zorundasiniz")
                return PLUGIN_HANDLED
        }

        new arg[32]
        read_argv(1, arg, charsmax(arg))

        new player = cmd_target(id, arg, CMDTARGET_OBEY_IMMUNITY)
        if ( !player ) return PLUGIN_HANDLED

        new name[32], authid[32], bankey[32]
        new userid = get_user_userid(player)
        get_user_name(player, name, charsmax(name))
        get_user_authid(player, authid, charsmax(authid))

        if ( gIsPowerBanned[player] ) {
                console_print(id, "[SH] Client is already SuperHero banned: ^"%s<%d><%s>^"", name, userid, authid)
                return PLUGIN_HANDLED
        }

        if ( !getSaveKey(player, bankey) ) {
                console_print(id, "[SH] Unable to find valid Ban Key to write to file for client: ^"%s<%d><%s>^"", name, userid, authid)
                return PLUGIN_HANDLED
        }

        // "a" will create a file if it does not exist but not overwrite it if it does
        new banFile = fopen(gBanFile, "at")

        if ( !banFile ) {
                debugMsg(0, 0, "Failed to open nopowers.cfg, please verify file/folder permissions")
                console_print(id, "[SH] Failed to open/create nopowers.cfg to save ban")
                return PLUGIN_HANDLED
        }

        // Add a first line of description if file was just created
        if (  -1 < file_size(gBanFile, 1) < 2 ) fputs(banFile, "//List of SteamIDs / IPs Banned from using powers^n")

        fprintf(banFile, "%s^n", bankey)

        fclose(banFile)

        new name2[32], authid2[32]
        get_user_name(id, name2, charsmax(name2))
        get_user_authid(id, authid2, charsmax(authid2))

        gIsPowerBanned[player] = true
        clearAllPowers(player, false)        // Avoids Recursion with false
        writeStatusMessage(player, "Super guclerden banlandiniz")

        show_activity(id, name2, " %s 'nin super guc kullanmasi yasaklandi", name)

        chatMessage(player, _, "Super guclerden banlandiniz")

        log_amx("[SH] ^"%s<%d><%s><>^" banned ^"%s<%d><%s><>^" from using superhero powers", name2, get_user_userid(id), authid2, name, userid, authid)

        console_print(id, "[SH] Successfully SuperHero banned ^"%s<%d><%s><>^"", name, userid, authid)

        return PLUGIN_HANDLED
}

//----------------------------------------------------------------------------------------------
public adminUnbanXP(id, level, cid)
{
        if ( !cmd_access(id, level, cid, 2) ) return PLUGIN_HANDLED

        if ( read_argc() > 2 ) {
                console_print(id, "[SH] Hata. Isim arasinda bosluk birakmayiniz")
                console_print(id, "[SH] Bu komutu kullanmak icin ismin bir kismini girmek zorundasiniz")
                return PLUGIN_HANDLED
        }

        if( !file_exists(gBanFile) ) {
                console_print(id, "[SH] Degistirilebilecek ban dosyasi yok")
                return PLUGIN_HANDLED
        }

        new arg[32]
        read_argv(1, arg, charsmax(arg))

        new player = cmd_target(id, arg, CMDTARGET_ALLOW_SELF)

        new name2[32], authid2[32], bankey[32]
        get_user_name(id, name2, charsmax(name2))
        get_user_authid(id, authid2, charsmax(authid2))

        if ( player ) {
                new name[32], authid[32]
                get_user_name(player, name, charsmax(name))
                get_user_authid(player, authid, charsmax(authid))
                new userid = get_user_userid(player)

                if ( !gIsPowerBanned[player] ) {
                        console_print(id, "[SH] Client is not SuperHero banned: ^"%s<%d><%s><>^"", name, userid, authid)
                        return PLUGIN_HANDLED
                }

                if ( !getSaveKey(player, bankey) ) {
                        console_print(id, "[SH] Unable to find valid Ban Key to remove from file for client: ^"%s<%d><%s>^"", name, userid, authid)
                        return PLUGIN_HANDLED
                }

                if ( !removeBanFromFile(id, bankey) ) return PLUGIN_HANDLED

                gIsPowerBanned[player] = false
                displayPowers(player, false)

                show_activity(id, name2, "unbanned %s from using superhero powers", name)

                console_print(id, "[SH] Successfully SuperHero unbanned ^"%s<%d><%s><>^"", name, userid, authid)

                log_amx("[SH] ^"%s<%d><%s><>^" un-banned ^"%s<%d><%s><>^" from using superhero powers", name2, get_user_userid(id), authid2,name, userid, authid)
        }
        else {
                // Assume attempting to unban by steamid or IP
                copy(bankey, charsmax(bankey), arg)
                console_print(id, "[SH] Attemping to unban using argument: %s", bankey)

                if ( !removeBanFromFile(id, bankey) ) return PLUGIN_HANDLED

                console_print(id, "[SH] Successfully SuperHero unbanned: %s", bankey)
                console_print(id, "[SH] WARNING: If this user is connected they need to reconnect to use powers")

                log_amx("[SH] ^"%s<%d><%s><>^" un-banned ^"%s^" from using superhero powers", name2, get_user_userid(id), authid2, bankey)
        }

        return PLUGIN_HANDLED
}
//----------------------------------------------------------------------------------------------
removeBanFromFile(adminID, const bankey[32])
{
        new tempFile[128]
        formatex(tempFile, charsmax(tempFile), "%s~", gBanFile)

        new banFile = fopen(gBanFile, "rt")
        new tempBanFile = fopen(tempFile, "wt")

        if ( !banFile || !tempBanFile ) {
                debugMsg(0, 0, "Failed to open nopowers.cfg, please verify file/folder permissions")
                console_print(adminID, "[SH] Unable to edit nopowers.cfg ban file")
                return 0
        }

        new bool:found
        new data[128]

        while ( !feof(banFile) ) {
                fgets(banFile, data, charsmax(data))
                trim(data)

                // Blank line skip copying it
                if ( data[0] == '^0' ) continue

                if ( equali(data, bankey) ) {
                        found = true
                        continue
                }

                fprintf(tempBanFile, "%s^n", data)
        }

        fclose(banFile)
        fclose(tempBanFile)

        delete_file(gBanFile)

        if ( !rename_file(tempFile, gBanFile, 1) ) {
                debugMsg(0, 0, "Error renaming file: %s -> %s", tempFile, gBanFile)
                console_print(adminID, "[SH] Unable to rename ban file")
                return 0
        }

        if ( !found ) {
                console_print(adminID, "[SH] ^"%s^" not found in nopowers.cfg", bankey)
                return 0
        }

        return 1
}
//----------------------------------------------------------------------------------------------
#if SAVE_METHOD != 2
public adminImmuneXP(id, level, cid)
{
        if ( !cmd_access(id, level, cid, 2) ) return PLUGIN_HANDLED

        if ( !gLongTermXP ) {
                console_print(id, "[SH] Xp dokunulmazligi kayitsiz Xp modunda ayarlanamaz")
                return PLUGIN_HANDLED
        }

        new numOfArg = read_argc()

        if ( numOfArg > 3 ) {
                console_print(id, "[SH] Hata. Isim arasinda bosluk birakmayiniz")
                console_print(id, "[SH] Bu komutu kullanmak icin ismin bir kismini girmek zorundasiniz")
                return PLUGIN_HANDLED
        }

        new arg[32]
        read_argv(1, arg, charsmax(arg))

        new player = cmd_target(id, arg, CMDTARGET_ALLOW_SELF)
        if ( !player ) return PLUGIN_HANDLED

        new name[32], authid[32], bankey[32]
        new userid = get_user_userid(player)
        get_user_name(player, name, charsmax(name))
        get_user_authid(player, authid, charsmax(authid))

        if ( !getSaveKey(player, bankey) ) {
                console_print(id, "[SH] Unable to find valid Save Key for client: ^"%s<%d><%s>^"", name, userid, authid)
                return PLUGIN_HANDLED
        }

        if ( numOfArg == 2 ) {
                // No on/off just supply what setting is at
                console_print(id, "[SH] Immunity from sh_savedays XP prune is %s on client: ^"%s<%d><%s><>^"", (gPlayerFlags[player] & SH_FLAG_XPIMMUNE) ? "ENABLED" : "DISABLED", name, userid, authid)
                return PLUGIN_HANDLED
        }

        new arg2[4], mode
        read_argv(2, arg2, charsmax(arg2))

        if ( equali(arg2, "on") ) mode = 1
        else if  ( equali(arg2, "off") ) mode = 0
        else mode = str_to_num(arg2)

        switch(mode) {
                case 0: {
                        if ( !(gPlayerFlags[player] & SH_FLAG_XPIMMUNE) ) {
                                console_print(id, "[SH] Client is already nonimmune to sh_savedays XP prune: ^"%s<%d><%s>^"", name, userid, authid)
                                return PLUGIN_HANDLED
                        }
                        gPlayerFlags[player] &= ~SH_FLAG_XPIMMUNE
                        chatMessage(player, _, "Your immunity from inactive user XP deletion has been removed")
                }
                case 1: {
                        if ( gPlayerFlags[player] & SH_FLAG_XPIMMUNE ) {
                                console_print(id, "[SH] Client is already immune from sh_savedays XP prune: ^"%s<%d><%s>^"", name, userid, authid)
                                return PLUGIN_HANDLED
                        }
                        gPlayerFlags[player] |= SH_FLAG_XPIMMUNE

                        chatMessage(player, _, "You have been given immunity from inactive user XP deletion")
                }
                default: {
                        console_print(id, "[SH] Invalid 3rd parameter: %s", arg2)
                        return PLUGIN_HANDLED
                }
        }

        // Update saved data now for safety
        memoryTableUpdate(player)

        new name2[32], authid2[32]
        get_user_name(id, name2, charsmax(name2))
        get_user_authid(id, authid2, charsmax(authid2))

        show_activity(id, name2, "%s %s immune from inactive user XP deletion", mode ? "Set" : "Unset", name)

        log_amx("[SH] ^"%s<%d><%s><>^" %s immunity ^"%s<%d><%s><>^" from sh_savedays XP prune", name2, get_user_userid(id), authid2, mode ? "set" : "unset", name, userid, authid)

        console_print(id, "[SH] Successfully %s immunity from sh_savedays XP prune on client ^"%s<%d><%s><>^"", mode ? "set" : "unset", name, userid, authid)

        return PLUGIN_HANDLED
}
#endif
//----------------------------------------------------------------------------------------------
public adminEraseXP(id, level, cid)
{
        if ( !cmd_access(id, level, cid, 1) ) return PLUGIN_HANDLED

        console_print(id, "[SH] Xp silinirken lutfen bekleyiniz")

        for ( new x = 1; x <= gServersMaxPlayers; x++ ) {
                gPlayerXP[x] = 0
                gPlayerLevel[x] = 0
                writeStatusMessage(x, "Butun XP'ler Silindi")
                clearAllPowers(x, true)
        }

        cleanXP(true)

        new name[32], authid[32]
        get_user_name(id, name, charsmax(name))
        get_user_authid(id, authid, charsmax(authid))

        show_activity(id, name, "Butun XP'ler Silindi")

        console_print(id, "[SH] Butun XP'ler Basariyla Silindi")

        log_amx("[SH] ^"%s<%d><%s><>^" butun XP'leri sildi", name, get_user_userid(id), authid)

        return PLUGIN_HANDLED
}
//----------------------------------------------------------------------------------------------
showHeroes(id)
{
        if ( !get_pcvar_num(sv_superheros) ) return PLUGIN_CONTINUE

        new buffer[1501]
        new n = 0
        new heroIndex, bindNum, x
        new bindNumtxt[128], name_lvl[128]

        n += copy(buffer[n], charsmax(buffer)-n, "<html><head><style type=^"text/css^">pre{color:#FFB000;}body{background:#000000;margin-left:8px;margin-top:0px;}</style></head><body><pre>^n")

        n += copy(buffer[n], charsmax(buffer)-n, "Sizin Herolariniz:^n^n")
        new playerpowercount = getPowerCount(id)
        for ( x = 1; x <= playerpowercount; x++ ) {
                heroIndex = gPlayerPowers[id][x]
                bindNum = getBindNumber(id, heroIndex)
                bindNumtxt[0] = '^0'

                if ( bindNum > 0 ) {
                        formatex(bindNumtxt, charsmax(bindNumtxt), "- POWER #%d", bindNum)
                }

                formatex(name_lvl, charsmax(name_lvl), "%s (%d)", gSuperHeros[heroIndex][hero], getHeroLevel(heroIndex))
                n += formatex(buffer[n], charsmax(buffer)-n, "%d) %-18s- %s %s^n", x, name_lvl, gSuperHeros[heroIndex][superpower], bindNumtxt)
        }

        copy(buffer[n], charsmax(buffer)-n, "</pre></body></html>")

        show_motd(id, buffer, "Sizin SuperHero Kahramanlariniz")
        return PLUGIN_HANDLED
}
//----------------------------------------------------------------------------------------------
public showSkillsCon(id, level, cid)
{
        if ( !cmd_access(id,level,cid,1) ) return PLUGIN_HANDLED

        if ( !get_pcvar_num(sv_superheros) ) {
                console_print(id, "[SH] SuperHero Mod Kapatildi")
                return PLUGIN_HANDLED
        }

        new arg1[32]
        read_argv(1, arg1, charsmax(arg1))

        showPlayerSkills(id, 0, arg1)
        return PLUGIN_HANDLED
}
//----------------------------------------------------------------------------------------------
public showLevelsCon(id,level,cid)
{
        if ( !cmd_access(id, level, cid, 1) ) return PLUGIN_HANDLED

        if ( !get_pcvar_num(sv_superheros) ) {
                console_print(id, "[SH] SuperHero Mod Kapatildi")
                return PLUGIN_HANDLED
        }

        new arg1[32]
        read_argv(1, arg1, charsmax(arg1))

        showPlayerLevels(id, 0, arg1)
        return PLUGIN_HANDLED
}

//----------------------------------------------------------------------------------------------
public showHeroListCon(id)
{
        if ( !get_pcvar_num(sv_superheros) ) {
                console_print(id, "[SH] SuperHero Mod kapatildi")
                return PLUGIN_HANDLED
        }

        console_print(id, "^n----- Hero Listesi (By Kakarott) -----")
        new argx[20]
        read_argv(1, argx, charsmax(argx))
        new start, end
        if ( !isdigit(argx[0]) && !equal("", argx) ) {
                new tmp[8], n=1
                read_argv(2, tmp, charsmax(tmp))
                start = str_to_num(tmp)
                if ( start < 0 ) start = 0
                if ( start != 0 ) start--
                end = start + HEROAMOUNT
                for( new x = 0; x < gSuperHeroCount; x++ ) {
                        if ( (containi(gSuperHeros[x][hero], argx) != -1) || (containi(gSuperHeros[x][help], argx) != -1) ) {
                                if ( n > start && n <= end ) {
                                        console_print(id, "%3d: %s (%d%s) - %s", n, gSuperHeros[x][hero], getHeroLevel(x), gSuperHeros[x][requiresKeys] ? "b" : "", gSuperHeros[x][help])
                                }
                                n++
                        }
                }
                if ( start+1 > n-1 ) {
                        console_print(id, "----- Highest Entry: %d -----", n-1)
                }
                else if ( n-1 == 0 ) {
                        console_print(id, "----- No Matches for Your Search -----")
                }
                else if ( n-1 < end ) {
                        console_print(id, "----- Entries %d - %d of %d -----", start+1, n-1, n-1)
                }
                else {
                        console_print(id, "----- Entries %d - %d of %d -----", start+1, end, n-1)
                }

                if ( end < n-1 ) {
                        console_print(id, "----- Use 'herolist %s %d' for more -----", argx, end+1)
                }
        }
        else {
                new arg1[8]
                start = read_argv(1, arg1, charsmax(arg1)) ? str_to_num(arg1) : 1
                if ( --start < 0 ) start = 0
                if ( start >= gSuperHeroCount ) start = gSuperHeroCount - 1
                end = start + HEROAMOUNT
                if ( end > gSuperHeroCount ) end = gSuperHeroCount
                for ( new i = start; i < end; i++ ) {
                        console_print(id, "%3d: %s (%d%s) - %s", i+1, gSuperHeros[i][hero], getHeroLevel(i), gSuperHeros[i][requiresKeys] ? "b" : "", gSuperHeros[i][help])
                }
                console_print(id, "----- Entries %d - %d of %d -----", start+1, end, gSuperHeroCount)
                if ( end < gSuperHeroCount ) {
                        console_print(id, "----- Use 'herolist %d' for more -----", end+1)
                }
        }
        return PLUGIN_HANDLED
}
//----------------------------------------------------------------------------------------------
showHelpHud()
{
        if ( !get_pcvar_num(sv_superheros) ) return

        static flags[4]
        switch(gCMDProj)
        {
                case 1: copy(flags, charsmax(flags), "bch")        // show to dead non-bots only
                case 2: copy(flags, charsmax(flags), "ch")        // show to live or dead non-bots
                default: return                        // off
        }

        set_hudmessage(230, 100, 10, 0.80, 0.28, 0, 1.0, 1.0, 0.9, 0.9, -1)

        static players[SH_MAXSLOTS], numplayers, id, i
        get_players(players, numplayers, flags)

        for ( i = 0; i < numplayers; i++ ) {
                id = players[i]
                if ( gPlayerFlags[id] & SH_FLAG_HUDHELP ) {
                        ShowSyncHudMsg(id, gHelpHudSync, "%s", gHelpHudMsg)
                }
        }
}
//----------------------------------------------------------------------------------------------
//Called when a client chooses a "team", not a "class type" (could be used to self kill)
public team_chosen(id)
{
        gBlockMercyXp[id] = true
}
//----------------------------------------------------------------------------------------------
//Called when a client types "kill" in the console
public client_kill(id)
{
        gBlockMercyXp[id] = true
}
//----------------------------------------------------------------------------------------------
public client_connect(id)
{
        // Don't want any left over residuals
        initPlayer(id)
}
//----------------------------------------------------------------------------------------------
public client_disconnect(id)
{
        // Don't want any left over residuals
        initPlayer(id)
        gPlayerPutInServer[id] = false
}
//----------------------------------------------------------------------------------------------
public client_putinserver(id)
{
        if ( id < 1 || id > gServersMaxPlayers ) return

        gPlayerPutInServer[id] = true

        // Find a czero bot to register Ham_Spawn
        if ( gIsCzero && pev(id, pev_flags) & FL_FAKECLIENT && get_pcvar_num(bot_quota) > 0 && !gCZBotRegisterHam ) {

                // Delay for private data to initialize
                set_task(0.1, "czbotHookHam", id)
        }

        // Don't want to mess up already loaded XP
        if ( !gReadXPNextRound[id] && gLongTermXP ) return

        // Load up XP if LongTerm is enabled
        if ( gLongTermXP ) {
                // Mid-round loads allowed?
                if ( get_pcvar_num(sh_loadimmediate) ) {
                        readXP(id)
                }
                else {
                        gReadXPNextRound[id] = true
                }
        }
        // If autobalance is on - promote this player by avg XP
        else if ( gAutoBalance ) {
                gPlayerXP[id] = getAverageXP()
        }
}
//----------------------------------------------------------------------------------------------
public czbotHookHam(id)
{
        // Thx to Avalanche and GunGame for which this method is based on.
        if ( gCZBotRegisterHam || !is_user_connected(id) ) return

        // Make sure it's a bot and if quota greater than 0 it's a cz bot.
        if ( pev(id, pev_flags) & FL_FAKECLIENT && get_pcvar_num(bot_quota) > 0) {
                // Post-spawn fix for cz bots, since RegisterHam does not work for them.
                RegisterHamFromEntity(Ham_Spawn, id, "ham_PlayerSpawn_Post", 1)
                RegisterHamFromEntity(Ham_TakeDamage, id, "ham_TakeDamage_Pre")

                gCZBotRegisterHam = true

                // Incase this CZ bot was spawned alive during a round, call the Ham_Spawn
                // because it would have happned before the RegisterHam.
                if ( is_user_alive(id) ) ham_PlayerSpawn_Post(id)
        }
}

//----------------------------------------------------------------------------------------------
getAverageXP()
{
        new count = 0
        new Float:sum = 0.0

        for ( new x = 1; x <= gServersMaxPlayers; x++) {
                if ( is_user_connected(x) && gPlayerXP[x] > 0 ) {
                        count++
                        sum += gPlayerXP[x]
                }
        }

        if ( count > 0 ) {
                return floatround(sum / count)
        }

        return 0
}
//----------------------------------------------------------------------------------------------
initPlayer(id)
{
        if ( id < 1 || id > gServersMaxPlayers ) return

        gPlayerXP[id] = 0
        gPlayerPowers[id][0] = 0
        gPlayerBinds[id][0] = 0
        gCurrentWeapon[id] = 0
        gPlayerStunTimer[id] = -1
        gPlayerGodTimer[id] = -1
        setLevel(id, 0)
        gShieldRestrict[id] = false
        gPlayerFlags[id] = SH_FLAG_HUDHELP
        gFirstRound[id] = true
        gNewRoundSpawn[id] = true
        gIsPowerBanned[id] = false
        gReadXPNextRound[id] = gLongTermXP

        clearAllPowers(id, false)
}
//----------------------------------------------------------------------------------------------
public fm_Touch(ptr, ptd)
{
        if ( !get_pcvar_num(sv_superheros) ) return FMRES_IGNORED
        if ( !pev_valid(ptr) || !pev_valid(ptd) ) return FMRES_IGNORED
        if ( ptd < 1 || ptd > gServersMaxPlayers ) return FMRES_IGNORED
        if ( !gShieldRestrict[ptd] ) return FMRES_IGNORED

        static entclass[32]
        entclass[0] = '^0'
        pev(ptr, pev_classname, entclass, charsmax(entclass))

        // Lets block the picking up of a shield
        if ( equal(entclass, "weapon_shield") ) {
                return FMRES_SUPERCEDE
        }

        return FMRES_IGNORED
}
//----------------------------------------------------------------------------------------------
// This is called when a user tries to buy a shield via a menu
public shieldbuy(id)
{
        if ( !get_pcvar_num(sv_superheros) ) return PLUGIN_CONTINUE
        if ( id < 1 || id > gServersMaxPlayers ) return PLUGIN_CONTINUE

        if ( gShieldRestrict[id] ) {
                engclient_cmd(id, "menuselect", "10")
                client_print(id, print_center, "Yaptiginiz bir hero secimi nedeniyle kalkan alamazsiniz.")
                return PLUGIN_HANDLED
        }

        return PLUGIN_CONTINUE
}
//----------------------------------------------------------------------------------------------
// This gets called when a user tries to buy a shield with the console command
public shieldqbuy(id)
{
        if ( !get_pcvar_num(sv_superheros) ) return PLUGIN_CONTINUE
        if ( id < 1 || id > gServersMaxPlayers ) return PLUGIN_CONTINUE

        if ( gShieldRestrict[id] && cs_get_user_team(id) == CS_TEAM_CT ) {
                console_print(id, "[SH] Yaptiginiz bir hero secimi nedeniyle kalkan alamazsiniz.")
                client_print(id, print_center, "Yaptiginiz bir hero secimi nedeniyle kalkan alamazsiniz.")
                return PLUGIN_HANDLED
        }

        return PLUGIN_CONTINUE
}



//----------------------------------------------------------------------------------------------
// This gets called when a user tries to use the autobuy feature
// Just block autobuying all together because they should have weapons already
public fn_autobuy(id)
{
        if ( !get_pcvar_num(sv_superheros) ) return PLUGIN_CONTINUE
        if ( id < 1 || id > gServersMaxPlayers ) return PLUGIN_CONTINUE

        if ( gShieldRestrict[id] ) {
                console_print(id, "[SH] Yaptiginiz bir hero secimi nedeniyle otomatik satin alamazsiniz.")
                client_print(id, print_center, "Yaptiginiz bir hero secimi nedeniyle otomatik satin alamazsiniz.")
                return PLUGIN_HANDLED
        }

        return PLUGIN_CONTINUE
}
//----------------------------------------------------------------------------------------------
getVipFlags()
{
        static temp[8]
        get_pcvar_string(sh_blockvip, temp, charsmax(temp))

        return read_flags(temp)
}
//----------------------------------------------------------------------------------------------
getLoguserIndex()
{
        static loguser[80], name[32]
        read_logargv(0, loguser, charsmax(loguser))
        parse_loguser(loguser, name, charsmax(name))

        return get_user_index(name)
}
//----------------------------------------------------------------------------------------------
public vip_UserSpawned()
{
        // Save if user is a vip here instead of checking cs_get_user_vip all thru the code
        gXpBounsVIP = getLoguserIndex()
}
//----------------------------------------------------------------------------------------------
public vip_UserEscape()
{
        if ( !get_pcvar_num(sv_superheros) || !gObjectiveXP ) return

        new id = getLoguserIndex()

        if ( !is_user_connected(id) ) return
        if ( id != gXpBounsVIP ) return
        if ( cs_get_user_team(id) != CS_TEAM_CT ) return
        if ( get_playersnum() <= get_pcvar_num(sh_minplrsbhxp) ) return

        new XPtoGive = get_pcvar_num(sh_objectivexp)
        localAddXP(id, XPtoGive)
        chatMessage(id, _, "VIP kactigi icin %d XP Kazandiniz!", XPtoGive)
        displayPowers(id, false)
}
//----------------------------------------------------------------------------------------------
public vip_Assassinated()
{
        if ( !get_pcvar_num(sv_superheros) || !gObjectiveXP ) return

        new attacker = getLoguserIndex()

        if ( !is_user_connected(attacker) ) return
        if ( cs_get_user_team(attacker) != CS_TEAM_T ) return
        if ( get_playersnum() <= get_pcvar_num(sh_minplrsbhxp) ) return

        new XPtoGive = get_pcvar_num(sh_objectivexp)
        localAddXP(attacker, XPtoGive)
        chatMessage(attacker, _, "VIP'i oldurdugunuz icin %d XP kazandiniz!", XPtoGive)
        displayPowers(attacker, false)
}
//----------------------------------------------------------------------------------------------
public vip_Escaped()
{
        if ( !get_pcvar_num(sv_superheros) || !gObjectiveXP ) return
        if ( get_playersnum() <= get_pcvar_num(sh_minplrsbhxp) ) return

        new players[32], numplayers, ct
        new XPtoGive = get_pcvar_num(sh_objectivexp)

        get_players(players, numplayers, "h")

        // VIP is considered dead at this point, so we have to check dead players to find him
        for (new i = 0; i < numplayers; i++) {
                ct = players[i]
                if ( ct == gXpBounsVIP || (is_user_alive(ct) && cs_get_user_team(ct) == CS_TEAM_CT) ) {
                        localAddXP(ct, XPtoGive)
                        chatMessage(ct, _, "Takiminiz VIP'i korumada basarili oldugu icin %d XP kazandiniz!", XPtoGive)
                        displayPowers(ct, false)
                }
        }
}
//----------------------------------------------------------------------------------------------
public host_Killed()
{
        if ( !get_pcvar_num(sv_superheros) || !gObjectiveXP) return

        new id = getLoguserIndex()

        if ( id < 1 || id > gServersMaxPlayers ) return

        new XPtoTake = get_pcvar_num(sh_objectivexp)
        localAddXP(id, -XPtoTake)
        chatMessage(id, _, "Rehinelerden birini oldurdugunuz icin %d XP kaybettiniz", XPtoTake)
        displayPowers(id, false)
}
//----------------------------------------------------------------------------------------------
public host_Rescued()
{
        if ( !get_pcvar_num(sv_superheros) || !gObjectiveXP) return

        new id = getLoguserIndex()

        if ( !is_user_connected(id) ) return
        if ( cs_get_user_team(id) != CS_TEAM_CT ) return
        if ( get_playersnum() < get_pcvar_num(sh_minplrsbhxp) ) return

        // Give at least 1 xp per hostage even if sh_objectivexp is really low
        // gNumHostages should never be 0 if this is called so no need to check for div by 0
        new XPtoGive = max(1, floatround(get_pcvar_float(sh_objectivexp) / gNumHostages))

        localAddXP(id, XPtoGive)
        chatMessage(id, _, "Rehinelerden birini kurtardiniz %d XP kazandiniz!", XPtoGive)
        displayPowers(id, false)
}
//----------------------------------------------------------------------------------------------
public host_AllRescued()
{
        if ( !get_pcvar_num(sv_superheros) || !gObjectiveXP ) return
        if ( get_playersnum() <= get_pcvar_num(sh_minplrsbhxp) ) return

        new players[32], numplayers, ct
        new XPtoGive = get_pcvar_num(sh_objectivexp)

        get_players(players, numplayers, "ah")

        for (new i = 0; i < numplayers; i++) {
                ct = players[i]
                if ( cs_get_user_team(ct) != CS_TEAM_CT ) continue
                localAddXP(ct, XPtoGive)
                chatMessage(ct, _, "Takiminiz tum rehineleri kurtardigi icin %d XP kazandiniz!", XPtoGive)
                displayPowers(ct, false)
        }
}
//----------------------------------------------------------------------------------------------
public bomb_HolderSpawned()
{
        new id = getLoguserIndex()

        if ( id < 1 || id > gServersMaxPlayers ) return

        // Find the Index of the bomb entity and save to be used as the one that gives xp
        new iWPNidx = -1
        while ((iWPNidx = engfunc(EngFunc_FindEntityByString, iWPNidx, "classname", "weapon_c4")) != 0) {
                if ( id == pev(iWPNidx, pev_owner) ) {
                        // set iWPNidx to XP bomb
                        gXpBounsC4ID = iWPNidx
                        break
                }
        }
}
//----------------------------------------------------------------------------------------------
public bomb_planted(planter)
{
        if ( !get_pcvar_num(sv_superheros) || !gObjectiveXP ) return
        if ( !is_user_connected(planter) || !pev_valid(gXpBounsC4ID) ) return
        if ( planter != pev(gXpBounsC4ID, pev_owner) ) return
        if ( cs_get_user_team(planter) != CS_TEAM_T ) return
        if ( get_playersnum() <= get_pcvar_num(sh_minplrsbhxp) ) return

        // Only give this out once per round
        gXpBounsC4ID = -1

        new XPtoGive = get_pcvar_num(sh_objectivexp)
        localAddXP(planter, XPtoGive)
        chatMessage(planter, _, "C4'u yerlestirdiniz %d XP kazandiniz!", XPtoGive)
        displayPowers(planter, false)
}
//----------------------------------------------------------------------------------------------
public bomb_defused(defuser)
{
        // Need to make sure gXpBounsC4ID was the bomb defused?
        if ( !get_pcvar_num(sv_superheros) || !gObjectiveXP ) return
        if ( !is_user_connected(defuser) ) return
        if ( cs_get_user_team(defuser) != CS_TEAM_CT ) return
        if ( get_playersnum() <= get_pcvar_num(sh_minplrsbhxp) ) return

        new XPtoGive = get_pcvar_num(sh_objectivexp)
        localAddXP(defuser, XPtoGive)
        chatMessage(defuser, _, "C4'u imha ettiniz %d XP kazandiniz!", XPtoGive)
        displayPowers(defuser, false)
}
//----------------------------------------------------------------------------------------------
public bomb_explode(planter, defuser)
{
        if ( !get_pcvar_num(sv_superheros) || !gObjectiveXP ) return PLUGIN_CONTINUE
        if ( get_playersnum() <= get_pcvar_num(sh_minplrsbhxp) ) return PLUGIN_CONTINUE

        new players[32], numplayers, terrorist
        new XPtoGive = get_pcvar_num(sh_objectivexp)

        get_players(players, numplayers, "ah")

        for (new i = 0; i < numplayers; i++) {
                terrorist = players[i]
                if ( cs_get_user_team(terrorist) != CS_TEAM_T ) continue
                localAddXP(terrorist, XPtoGive)
                chatMessage(terrorist, _, "C4 basariyla patlatildigi icin %d XP kazandiniz!", XPtoGive)
                displayPowers(terrorist, false)
        }
        return PLUGIN_CONTINUE
}
//----------------------------------------------------------------------------------------------
getHeroLevel(heroIndex)
{
        return gSuperHeros[heroIndex][availableLevel]
}
//----------------------------------------------------------------------------------------------
getPlayerLevel(id)
{
        new newLevel = 0

        for ( new i = gNumLevels; i >= 0 ; i-- ) {
                if ( gXPLevel[i] <= gPlayerXP[id] ) {
                        newLevel = i
                        break
                }
        }

        // Now make sure this level is between the ranges
        new minLevel = clamp(get_pcvar_num(sh_minlevel), 0, gNumLevels)

        if ( newLevel < minLevel && !gReadXPNextRound[id] ) {
                newLevel = minLevel
                gPlayerXP[id] = gXPLevel[newLevel]
        }

        if ( newLevel > gNumLevels ) newLevel = gNumLevels

        return newLevel
}
//----------------------------------------------------------------------------------------------
// Use to set CVAR Variable to the proper level - If a Hero needs to know a level at least it's possible
setLevel(id, newLevel)
{
        // MAKE SURE THE VAR IS SET CORRECTLY...
        gPlayerLevel[id] = newLevel

#if defined SH_BACKCOMPAT
        // Let any hero that wants to know about this level event
        for ( new x = 0; x < gSuperHeroCount; x++ ) {
                if ( gEventLevels[x][0] != '^0' ) {
                        server_cmd("%s %d %d", gEventLevels[x], id, newLevel)
                }
        }
#endif
}
//----------------------------------------------------------------------------------------------
testLevel(id)
{
        new newLevel, oldLevel, playerpowercount
        oldLevel = gPlayerLevel[id]
        newLevel = getPlayerLevel(id)

        // Play a Sound on Level Change!
        if ( oldLevel != newLevel ) {
                setLevel(id, newLevel)
                if ( newLevel != 0 ) client_cmd(id, "spk %s", gSoundLevel)
        }

        // Make sure player is allowed to have the heroes in their list
        if ( newLevel < oldLevel ) {
                new heroIndex
                playerpowercount = getPowerCount(id)
                for ( new x = 1; x <= gNumLevels && x <= playerpowercount; x++ ) {
                        heroIndex = gPlayerPowers[id][x]
                        if ( -1 < heroIndex < gSuperHeroCount ) {
                                if ( getHeroLevel(heroIndex) > gPlayerLevel[id] ) {
                                        clearPower(id, x)
                                        x--
                                }
                        }
                }
        }

        // Uh oh - Rip away a level from powers if they loose a level
        playerpowercount = getPowerCount(id)
        if ( playerpowercount > newLevel ) {
                for ( new x = newLevel + 1; x <= playerpowercount && x <= SH_MAXLEVELS; x++ ) {
                        clearPower(id, x) // Keep clearing level above cuz levels shift!
                }
                gPlayerPowers[id][0] = newLevel
        }

        // Go ahead and write this so it's not lost - hopefully no server crash!
        memoryTableUpdate(id)
}
//----------------------------------------------------------------------------------------------
public readXP(id)
{
        if ( !gLongTermXP ) return

        // Players XP already loaded, no need to do this again
        if ( !gReadXPNextRound[id] ) return

        static savekey[32]

        // Get Key
        if ( !getSaveKey(id, savekey) ) {
                debugMsg(id, 1, "Gecersiz anahtar bulundu, Xp yuklemesi tekrar denenecek: ^"%s^"", savekey)
                set_task(5.0, "readXP", id)
                return
        }

        // Set if player is banned from powers or not
        checkBan(id, savekey)

        debugMsg(id, 1, "XP kullanma anahtari yukleniyor: ^"%s^"", savekey)

        // Check Memory Table First
        if ( memoryTableRead(id, savekey) ) {
                debugMsg(id, 8, "XP verisi bellek tablosundan yuklendi")
        }
        else if ( loadXP(id, savekey) ) {
                debugMsg(id, 8, "XP verisi Vault'tan , nVault'tan, veya MySQL save'den yuklendi")
        }
        else {
                // XP Not able to load, will try again next round
                return
        }

        gReadXPNextRound[id] = false
        memoryTableUpdate(id)
        displayPowers(id, false)
}
//----------------------------------------------------------------------------------------------
getSaveKey(id, savekey[32])
{
        if ( is_user_bot(id) ) {
                static botname[32]
                get_user_name(id, botname, charsmax(botname))

                // Get Rid of BOT Tag

                // PODBot
                replace(botname, charsmax(botname), "[POD]", "")
                replace(botname, charsmax(botname), "[P*D]", "")
                replace(botname, charsmax(botname), "[P0D]", "")

                // CZ Bots
                replace(botname, charsmax(botname), "[BOT] ", "")

                // Attempt to get rid of the skill tag so we save with bots true name
                new lastchar = strlen(botname) - 1
                if ( botname[lastchar] == ')' ) {
                        for ( new x = lastchar - 1; x > 0; x-- ) {
                                if ( botname[x] == '(' ) {
                                        botname[x - 1] = 0
                                        break
                                }
                                if ( !isdigit(botname[x]) ) break
                        }
                }
                if ( botname[0] != '^0' ) {
                        replace_all(botname, charsmax(botname), " ", "_")
                        formatex(savekey, charsmax(savekey), "[BOT]%s", botname)
                }
        }
        else {       
                switch( get_pcvar_num(sh_saveby) )
                {
                        //Forced save XP by name
                        case 0: {
                                get_user_name(id, savekey, charsmax(savekey))
                        }

                        //Auto Detect, save XP by SteamID or IP if LAN (default)
                        case 1: {
                                // Hack for STEAM's retardedness with listen servers
                                if ( id == 1 && !is_dedicated_server() ) {
                                        copy(savekey, charsmax(savekey), "loopback")
                                }
                                else if ( get_pcvar_num(sv_lan) ) {
                                        get_user_ip(id, savekey, charsmax(savekey), 1)                // by ip without port
                                }
                                else {
                                        get_user_authid(id, savekey, charsmax(savekey))                // by steamid

                                        //Check both STEAM_ID_ and VALVE_ID_
                                        if ( equal(savekey[9], "LAN") ) {
                                                get_user_ip(id, savekey, charsmax(savekey), 1)        // by ip without port
                                        }
                                        else if ( equal(savekey[9], "PENDING") ) {
                                                // steamid not loaded yet, try again
                                                return false
                                        }
                                }
                        }

                        //Forced save XP by IP
                        case 2: {
                                get_user_ip(id, savekey, charsmax(savekey), 1)
                        }
                }
        }

        // Check to make sure we got something useable
        if ( savekey[0] == '^0' ) return false

        return true
}

//----------------------------------------------------------------------------------------------
checkBan(id, const bankey[32])
{
        if ( !file_exists(gBanFile) || gIsPowerBanned[id] ) return

        new bool:idBanned, data[32]

        debugMsg(id, 4, "Checking for ban using key: ^"%s^"", bankey)

        new banFile = fopen(gBanFile, "rt")

        if ( !banFile ) {
                debugMsg(0, 0, "Failed to open nopowers.cfg, please verify file/folder permissions")
                return
        }

        while ( !feof(banFile) && !idBanned ) {
                fgets(banFile, data, charsmax(data))
                trim(data)

                switch(data[0]) {
                        case '^0', '^n', ';', '/', '\', '#': continue
                }

                if ( equali(data, bankey) ) {
                        gIsPowerBanned[id] = idBanned = true
                        debugMsg(id, 1, "Ban loaded from banlist for this player")
                }
        }

        fclose(banFile)
}
//----------------------------------------------------------------------------------------------
memoryTableUpdate(id)
{
        if ( !get_pcvar_num(sv_superheros) || !gLongTermXP ) return
        if ( gIsPowerBanned[id] || gReadXPNextRound[id] ) return

        // Update this XP line in Memory Table
        static savekey[32], x, powerCount

        if ( !getSaveKey(id, savekey) ) return

        // Check to see if there's already another id in that slot... (disconnected etc.)
        if ( gMemoryTableKeys[id][0] != '^0' && !equali(gMemoryTableKeys[id], savekey) ) {
                if ( gMemoryTableCount < gMemoryTableSize ) {
                        copy(gMemoryTableKeys[gMemoryTableCount], charsmax(gMemoryTableKeys[]), gMemoryTableKeys[id])
                        copy(gMemoryTableNames[gMemoryTableCount], charsmax(gMemoryTableNames[]), gMemoryTableNames[id])
                        gMemoryTableXP[gMemoryTableCount] = gMemoryTableXP[id]
                        gMemoryTableFlags[gMemoryTableCount] = gMemoryTableFlags[id]
                        powerCount = gMemoryTablePowers[id][0]
                        for ( x = 0; x <= powerCount && x <= SH_MAXLEVELS; x++ ) {
                                gMemoryTablePowers[gMemoryTableCount][x] = gMemoryTablePowers[id][x]
                        }
                        gMemoryTableCount++  // started with position 33
                }
        }

        // OK copy to table now - might have had to write 1 record...
        copy(gMemoryTableKeys[id], charsmax(gMemoryTableKeys[]), savekey)
        get_user_name(id, gMemoryTableNames[id], charsmax(gMemoryTableNames[]))
        gMemoryTableXP[id] = gPlayerXP[id]
        gMemoryTableFlags[id] = gPlayerFlags[id]

        powerCount = getPowerCount(id)
        for ( x = 0; x <= powerCount && x <= SH_MAXLEVELS; x++ ) {
                gMemoryTablePowers[id][x] = gPlayerPowers[id][x]
        }
}
//----------------------------------------------------------------------------------------------
memoryTableRead(id, const savekey[])
{
        if ( !get_pcvar_num(sv_superheros) ) return false

        static x, p, idLevel, powerCount, heroIndex

        for ( x = 1; x < gMemoryTableCount; x++ ) {
                if ( gMemoryTableKeys[x][0] != '^0' && equal(gMemoryTableKeys[x], savekey) ) {
                        gPlayerXP[id] = gMemoryTableXP[x]
                        idLevel = gPlayerLevel[id] = getPlayerLevel(id)
                        setLevel(id, idLevel)
                        gPlayerFlags[id] = gMemoryTableFlags[id]

                        // Load the Powers
                        gPlayerPowers[id][0] = 0
                        powerCount = gPlayerPowers[id][0] = gMemoryTablePowers[x][0]
                        for ( p = 1; p <= idLevel && p <= powerCount; p++ ) {
                                heroIndex = gPlayerPowers[id][p] = gMemoryTablePowers[x][p]
                                initHero(id, heroIndex, SH_HERO_ADD)
                        }

                        // Null this out so if the id changed - there won't be multiple copies of this guy in memory
                        if ( id != x ) {
                                gMemoryTableKeys[x][0] = '^0'
                                memoryTableUpdate(id)
                        }

                        // Notify that this was found in memory...
                        return true
                }
        }
        return false // If not found in memory table...
}
//----------------------------------------------------------------------------------------------
public plugin_end()
{
        // SAVE EVERYTHING...
        log_message("[SH] Making final XP save before plugin unloads")
        memoryTableWrite()

        // Final cleanup in the saving include
        saving_end()
}
//----------------------------------------------------------------------------------------------
readINI()
{
        new levelINIFile[128]
        formatex(levelINIFile, charsmax(levelINIFile), "%s/superhero.ini", gSHConfigDir)

        if ( !file_exists(levelINIFile) ) createINIFile(levelINIFile)

        new levelsFile = fopen(levelINIFile, "rt")

        if ( !levelsFile ) {
                debugMsg(0, 0, " superhero.ini Dosyasi bulunamadi, lutfen yolu dogru belirtiniz")
                return
        }

        // Only called once no need for static
        new data[1501], tag[20]
        new numLevels[6], loadCount = -1
        new XP[1501], XPG[1501]
        new LeftXP[32], LeftXPG[32]

        while (!feof(levelsFile)) {
                fgets(levelsFile, data, charsmax(data))
                trim(data)

                if ( data[0] == '^0' || equal(data, "##", 2) ) continue

                if ( equali(data, "NUMLEVELS", 9) ) {
                        parse(data, tag, charsmax(tag), numLevels, charsmax(numLevels))
                }
                else if ( (equal(data, "XPLEVELS", 8) && !gLongTermXP) || (equal(data, "LTXPLEVELS", 10) && gLongTermXP) ) {
                        copy(XP, charsmax(XP), data)
                }
                else if ( (equal(data, "XPGIVEN", 7) && !gLongTermXP) || (equal(data, "LTXPGIVEN", 9) && gLongTermXP) ) {
                        copy(XPG, charsmax(XPG), data)
                }
        }
        fclose(levelsFile)

        if ( numLevels[0] == '^0' ) {
                debugMsg(0, 0, "No NUMLEVELS Data was found, aborting INI Loading")
                return
        }
        else if ( XP[0] == '^0' ) {
                debugMsg(0, 0, "No XP LEVELS Data was found, aborting INI Loading")
                return
        }
        else if ( XPG[0] == '^0' ) {
                debugMsg(0, 0, "No XP GIVEN Data was found, aborting INI Loading")
                return
        }

        debugMsg(0, 1, "Loading %s XP Levels", gLongTermXP ? "Long Term" : "Short Term")

        gNumLevels = str_to_num(numLevels)

        //This prevents variables from getting overflown
        if (gNumLevels > SH_MAXLEVELS) {
                debugMsg(0, 0, "NUMLEVELS in superhero.ini is defined higher than MAXLEVELS in the include file. Adjusting NUMLEVELS to %d", SH_MAXLEVELS)
                gNumLevels = SH_MAXLEVELS
        }

        //Get the data tag out of the way
        strbrkqt(XP, LeftXP, charsmax(LeftXP), XP, charsmax(XP))
        strbrkqt(XPG, LeftXPG, charsmax(LeftXPG), XPG, charsmax(XPG))

        while ( XP[0] != '^0' && XPG[0] != '^0' && loadCount < gNumLevels ) {
                loadCount++

                strbrkqt(XP, LeftXP, charsmax(LeftXP), XP, charsmax(XP))
                strbrkqt(XPG, LeftXPG, charsmax(LeftXPG), XPG, charsmax(XPG))

                gXPLevel[loadCount] = str_to_num(LeftXP)
                gXPGiven[loadCount] = str_to_num(LeftXPG)

                switch(loadCount) {
                        case 0: {
                                if ( gXPLevel[loadCount] != 0 ) {
                                        debugMsg(0, 0, "Level 0 must have an XP setting of 0, adjusting automatically")
                                        gXPLevel[loadCount] = 0
                                }
                        }
                        default: {
                                if ( gXPLevel[loadCount] < gXPLevel[loadCount - 1] ) {
                                        debugMsg(0, 0, "Level %d is less XP than the level before it (%d < %d), adjusting NUMLEVELS to %d", loadCount, gXPLevel[loadCount], gXPLevel[loadCount - 1], loadCount - 1)
                                        gNumLevels = loadCount - 1
                                        break
                                }
                        }
                }

                debugMsg(0, 3, "XP Loaded - Level: %d  -  XP Required: %d  -  XP Given: %d", loadCount, gXPLevel[loadCount], gXPGiven[loadCount])
        }

        if ( loadCount < gNumLevels ) {
                debugMsg(0, 0, "Ran out of levels to load, check your superhero.ini for errors. Adjusting NUMLEVELS to %d", loadCount)
                gNumLevels = loadCount
        }
}
//----------------------------------------------------------------------------------------------
createINIFile(const levelINIFile[])
{
        new levelsFile = fopen(levelINIFile, "wt")
        if (!levelsFile) {
                debugMsg(0, 0, "Failed to create superhero.ini, please verify file/folder permissions")
                return
        }

        fputs(levelsFile, "## NUMLEVELS  - The total Number of levels to award players^n")
        fputs(levelsFile, "## XPLEVELS  - How much XP does it take to earn each level (0..NUMLEVELS)^n")
        fputs(levelsFile, "## XPGIVEN    - How much XP is given when a Level(N) player is killed (0..NUMLEVELS)^n")
        fputs(levelsFile, "## LTXPLEVELS - Same as XPLEVELS but for Long-Term mode (sh_savexp 1)^n")
        fputs(levelsFile, "## LTXPGIVEN  - Same as XPGIVEN but for Long-Term mode (sh_savexp 1)^n")

        // Straight from WC3 - but feel free to change it in the INI file...
        fputs(levelsFile, "NUMLEVELS  10^n")
        fputs(levelsFile, "XPLEVELS  0 100 300 600 1000 1500 2100 2800 3600 4500 5500^n")
        fputs(levelsFile, "XPGIVEN    60 80 100 120 140 160 180 200 220 240 260^n")
        fputs(levelsFile, "LTXPLEVELS 0 100 200 400 800 1600 3200 6400 12800 25600 51200^n")
        fputs(levelsFile, "LTXPGIVEN  6 8 10 12 14 16 20 24 28 32 40")

        fclose(levelsFile)
}
//----------------------------------------------------------------------------------------------
createGiveWeaponConfig(const wpnBlockFile[])
{
        new blockWpnFile = fopen(wpnBlockFile, "wt")
        if ( !blockWpnFile ) {
                debugMsg(0, 0, "Failed to create shweapon.cfg, please verify file/folder permissions")
                return
        }

        fputs(blockWpnFile, "// Use this file to block SuperHero from giving weapons by map. This only blocks shmod from giving weapons.^n")
        fputs(blockWpnFile, "// For example you can block all heroes from giving any weapon on all ka_ maps instead of disabling the hero.^n")
        fputs(blockWpnFile, "// You can even force people to buy weapons for all maps by blocking all weapons on all maps.^n")
        fputs(blockWpnFile, "//^n")
        fputs(blockWpnFile, "// Usage for maps:^n")
        fputs(blockWpnFile, "// - The asterisk * symbol will act as wildcard or by itself will be all maps, ie de_* is all maps that start with de_^n")
        fputs(blockWpnFile, "// - If setting a map prefix with wildcard and setting a map that has the same prefix, place map name before the^n")
        fputs(blockWpnFile, "//    prefix is used to use it over the prefix. ie set de_dust before de_* to use de_dust over the de_* config.^n")
        fputs(blockWpnFile, "// Usage for weapon:^n")
        fputs(blockWpnFile, "// - Place available weapon shorthand names from list below inside quotes and separate by commas.^n")
        fputs(blockWpnFile, "// - Works like an on/off switch so if you set a weapon twice it will block then unblock it.^n")
        fputs(blockWpnFile, "// - A special ^"all^" shorthand name can be used to toggle all weapons at once.^n")
        fputs(blockWpnFile, "// Valid shorthand weapon names:^n")
        fputs(blockWpnFile, "// - all, p228, scout, hegrenade, xm1014, c4, mac10, aug, smokegrenade, elite, fiveseven, ump45, sg550, galil,^n")
        fputs(blockWpnFile, "// - famas, usp, glock18, awp, mp5navy, m249, m3, m4a1, tmp, g3sg1, flashbang, deagle, sg552, ak47, knife, p90^n")
        fputs(blockWpnFile, "//^n")
        fputs(blockWpnFile, "// Examples of proper usage are as follows (these can be used by removing the // from the line):^n")
        fputs(blockWpnFile, "// - below blocks sh from giving the awp and p90 on de_dust.^n")
        fputs(blockWpnFile, "//de_dust ^"awp, p90^"^n")
        fputs(blockWpnFile, "// - below blocks sh from giving all weapons on all ka_ maps.^n")
        fputs(blockWpnFile, "//ka_* ^"all^"^n")
        fputs(blockWpnFile, "// - below blocks sh from giving all weapons then unblocks hegrenade on all he_ maps.^n")
        fputs(blockWpnFile, "//he_* ^"all, hegrenade^"^n")

        fclose(blockWpnFile)
}
//----------------------------------------------------------------------------------------------
createHelpMotdFile(const helpMotdFile[])
{
        // Write as binary so if created on windows server the motd won't display double spaced
        new helpFile = fopen(helpMotdFile, "wb")
        if ( !helpFile ) {
                debugMsg(0, 0, "Failed to create sh_helpmotd.txt, please verify file/folder permissions")
                return
        }

        fputs(helpFile, "<html><head><style type=^"text/css^">pre{color:#FFB000;}body{background:#000000;margin-left:8px;margin-top:0px;}</style></head><body><pre>^n")

        fputs(helpFile, "<b>Nasil Hero Alinir?:</b>^n")
        fputs(helpFile, "Dusman oldururseniz exp kazanirsiniz^n")
        fputs(helpFile, "Eger yeteri kadar xp toplarsaniz yeni hero secebilirsiniz.^n")
        fputs(helpFile, "Leveli yuksek kisileri oldururseniz daha fazla exp alirsiniz.^n")
        fputs(helpFile, "Baslangic leveli adminler tarafindan belirlenir...^n^n")

        fputs(helpFile, "<b>Nasil Hero Kullanilir?:</b>^n")
        fputs(helpFile, "Superhero gucleri kullanmak icin konsola ornegin:^n")
        fputs(helpFile, "        bind f +power1  --> 1.guc^n^n")
        fputs(helpFile, "Bunu kullanmak icin konsola yazmalisiniz.^n")
        fputs(helpFile, "        bind ^"tus^" ^"komut^"^n^n")
        fputs(helpFile, "Asagida bazi ornekler vardir. Inceleyebilirsiniz:^n")
        fputs(helpFile, "        bind f +power1                bind v +power2^n^n")

        fputs(helpFile, "<b>Kullanilabilecek komutlar:</b>^n")
        fputs(helpFile, "say /superherohelp        - Yardim menusunu acar^n")
        fputs(helpFile, "say /showmenu                - Hero secme menusunu acar^n")
        fputs(helpFile, "say /herolist                - Servara yuklenmis herolarin listesini acar^n")
        fputs(helpFile, "say /myheroes                - Kendi herolarinizi listeler^n")
        fputs(helpFile, "say /clearpowers        - Guclerinizi sifirlar bastan secebilirsiniz.^n")
        fputs(helpFile, "say /drop <hero_adi>                - Bu komutla tek hero atabilirsiniz.^n")
        fputs(helpFile, "say /whohas <hero_adi>                - Bu heronun kimlerde oldugunu gosterir^n")
        fputs(helpFile, "say /playerskills [@ALL|@CT|@T|name] - Butun oyuncularin herolarini listeler^n")
        fputs(helpFile, "say /playerlevels [@ALL|@CT|@T|name] - Butun oyuncularin levellerini listeler^n^n")

        fputs(helpFile, "say /automenu        - Super guc menusu aktiflestirme/devre disi birakma^n")
        fputs(helpFile, "say /helpon        - Yardim menusu acik kalir^n")
        fputs(helpFile, "say /helpoff        - Yardim menusu kapanir^n^n")

        fputs(helpFile, "Turkcelestiren: DragonballZ Kakarott, emege saygi...")

        fputs(helpFile, "</pre></body></html>")

        fclose(helpFile)
}
//----------------------------------------------------------------------------------------------
buildHelpHud()
{
        // Max characters hud messages can be is 479
        // Message is 338 characters currently
        new n
        n += copy(gHelpHudMsg[n], charsmax(gHelpHudMsg)-n, "SuperHero Mod Yardim^n^n")

        n += copy(gHelpHudMsg[n], charsmax(gHelpHudMsg)-n, "Guc Nasil Kullanilir?:^n")
        n += copy(gHelpHudMsg[n], charsmax(gHelpHudMsg)-n, "--------------------^n")
        n += copy(gHelpHudMsg[n], charsmax(gHelpHudMsg)-n, "Konsolu Acin^n")
        n += copy(gHelpHudMsg[n], charsmax(gHelpHudMsg)-n, "Ornegin:^n")
        n += copy(gHelpHudMsg[n], charsmax(gHelpHudMsg)-n, "bind f +power1^n^n")

        n += copy(gHelpHudMsg[n], charsmax(gHelpHudMsg)-n, "Yardim Komutlari:^n")
        n += copy(gHelpHudMsg[n], charsmax(gHelpHudMsg)-n, "--------------------^n")
        n += copy(gHelpHudMsg[n], charsmax(gHelpHudMsg)-n, "/help^n")
        n += copy(gHelpHudMsg[n], charsmax(gHelpHudMsg)-n, "/clearpowers^n")
        n += copy(gHelpHudMsg[n], charsmax(gHelpHudMsg)-n, "/showmenu^n")
        n += copy(gHelpHudMsg[n], charsmax(gHelpHudMsg)-n, "/drop <heronun_adi>^n")
        n += copy(gHelpHudMsg[n], charsmax(gHelpHudMsg)-n, "/herolist^n")
        n += copy(gHelpHudMsg[n], charsmax(gHelpHudMsg)-n, "/playerskills^n")
        n += copy(gHelpHudMsg[n], charsmax(gHelpHudMsg)-n, "/playerlevels^n")
        n += copy(gHelpHudMsg[n], charsmax(gHelpHudMsg)-n, "/myheroes^n")
        n += copy(gHelpHudMsg[n], charsmax(gHelpHudMsg)-n, "/automenu^n")
        n += copy(gHelpHudMsg[n], charsmax(gHelpHudMsg)-n, "--------------------^n")
        n += copy(gHelpHudMsg[n], charsmax(gHelpHudMsg)-n, "Yardim menusu acik:  /helpon^n")
        copy(gHelpHudMsg[n], charsmax(gHelpHudMsg)-n, "Yardim menusu kapali: /helpoff")
}
//----------------------------------------------------------------------------------------------



#if defined SH_BACKCOMPAT
// Old server message commands for backward compatibility only
//----------------------------------------------------------------------------------------------
public regKeyUp()
{
        new pHero[25]
        new pFunction[20]

        // What's the Heroes Name
        read_argv(1, pHero, charsmax(pHero))

        //Get the function being registered
        read_argv(2, pFunction, charsmax(pFunction))

        debugMsg(0, 3, "Register KeyUP -> Name: %s  - Function: %s", pHero, pFunction)

        // Get Hero Index
        new idx = getHeroID(pHero)
        if ( idx >= 0 && idx < gSuperHeroCount ) {
                copy(gEventKeyUp[idx], charsmax(gEventKeyUp[]), pFunction)
        }
}
//----------------------------------------------------------------------------------------------
public regKeyDown()
{
        new pHero[25]
        new pFunction[20]

        // What's the Heroes Name
        read_argv(1, pHero, charsmax(pHero))

        //Get the function being registered
        read_argv(2, pFunction, charsmax(pFunction))

        debugMsg(0, 3, "Register KeyDOWN -> Name: %s  - Function: %s", pHero, pFunction)

        // Get Hero Index
        new idx = getHeroID(pHero)
        if ( idx >= 0 && idx < gSuperHeroCount) {
                copy(gEventKeyDown[idx], charsmax(gEventKeyDown[]), pFunction)
        }
}
//----------------------------------------------------------------------------------------------
public regLevels()
{
        new pHero[25]
        new pFunction[20]

        // What's the Heroes Name
        read_argv(1, pHero, charsmax(pHero))

        read_argv(2, pFunction, charsmax(pFunction))

        debugMsg(0, 3, "Register Levels -> Name: %s  - Function: %s", pHero, pFunction)

        // Get Hero Index
        new idx = getHeroID(pHero)
        if ( idx >= 0 && idx < gSuperHeroCount) {
                copy(gEventLevels[idx], charsmax(gEventLevels[]), pFunction)
        }
}
//----------------------------------------------------------------------------------------------
public regMaxHealth()
{
        new pHero[25]
        new pFunction[20]

        // What's the Heroes Name
        read_argv(1, pHero, charsmax(pHero))

        read_argv(2, pFunction, charsmax(pFunction))

        debugMsg(0, 3, "Register MaxHealth -> Name: %s  - Function: %s", pHero, pFunction)

        // Get Hero Index
        new idx = getHeroID(pHero)
        if ( idx >= 0 && idx < gSuperHeroCount) {
                copy(gEventMaxHealth[idx], charsmax(gEventMaxHealth[]), pFunction)
        }
}
//----------------------------------------------------------------------------------------------
public regInit()
{
        new pHero[25]
        new pFunction[20]

        // What's the Heroes Name
        read_argv(1, pHero, charsmax(pHero))

        read_argv(2, pFunction, charsmax(pFunction))

        debugMsg(0, 3, "Register Init -> Name: %s  - Function: %s", pHero, pFunction)

        // Get Hero Index
        new idx = getHeroID(pHero)
        if ( idx >= 0 && idx < gSuperHeroCount) {
                copy(gEventInit[idx], charsmax(gEventInit[]), pFunction)
        }
}
//----------------------------------------------------------------------------------------------
#endif


This is superheromod.inc & superheroconst.inc combined source:

PHP Code:

// SuperHero Constants Include File
// Version 1.2.0

//----------------------------------------------------------------------------------------------
// Changeable DEFINE Settings, must recompile SuperHero plugins if changed
//----------------------------------------------------------------------------------------------

// Max levels that can be loaded from the superhero.ini
#define SH_MAXLEVELS 100

// Max Amount of heros that can be loaded
#define SH_MAXHEROS 100

// Potential of power1-power9 but limited by sh_maxbinds (3 default)
#define SH_MAXBINDPOWERS 9

// Comment out for new optimized coding only, old coded heroes will break
#define SH_BACKCOMPAT

//----------------------------------------------------------------------------------------------
// DO NOT EDIT BELOW HERE
//----------------------------------------------------------------------------------------------

#define SH_VERSION        1.20
stock const SH_VERSION_STR[] =    "1.2.0.14";

// Cooldown task id, required to allow core to stop task
#define SH_COOLDOWN_TASKID    572910

// Max player slots
#define SH_MAXSLOTS        32

// sh_hero_init(id, heroID, mode) modes
#define SH_HERO_DROP        0    //Hero is dropped
#define SH_HERO_ADD        1    //Hero is added

// sh_hero_key(id, heroID, key) keys
#define SH_KEYUP        0    //Power Key is released
#define SH_KEYDOWN        1    //Power Key is pressed

// sh_extra_damage() damage types
#define SH_DMG_MULT        0    // Multipiler damage, armor will not reduce damage hit points (armor is still reduced)
#define SH_DMG_NORM        1    // Normal damage, armor will reduce damage hit points
#define SH_DMG_KILL        2    // Kill damage, instantly kills if damage is possible (Note: godmode can block this)

// From HLSDK for sh_screenfade
#define SH_FFADE_IN        0x0000    // Just here so we don't pass 0 into the function
#define SH_FFADE_OUT        0x0001    // Fade out (not in)
#define SH_FFADE_MODULATE    0x0002    // Modulate (don't blend)
#define SH_FFADE_STAYOUT    0x0004    // Ignores the duration, stays faded out until new ScreenFade message received

// User Flags, saved with XP data
#define SH_FLAG_HUDHELP        (1<<0)    /* flag "a" */    // Enable the Help HUD
#define SH_FLAG_NOAUTOMENU    (1<<1)    /* flag "b" */    // Do not show menu automatically on spawn
#define SH_FLAG_XPIMMUNE    (1<<2)    /* flag "c" */    // Immue to xp reset from savedays. (Not available for nVault)
#define SH_FLAG_BANNED        (1<<3)    /* flag "d" */    // Flag user banned from having hereos (not used, if used would have to keep info stored and will not work with nVault)

// VIP Flags, set with sh_blockvip CVAR
#define VIP_BLOCK_POWERKEYS    (1<<0)    /* flag "a" */    // VIP blocked from using power keys
#define VIP_BLOCK_WEAPONS    (1<<1)    /* flag "b" */    // VIP blocked from receiving weapons thru sh
#define VIP_BLOCK_HEALTH    (1<<2)    /* flag "c" */    // VIP blocked from receiving health thru sh
#define VIP_BLOCK_ARMOR        (1<<3)    /* flag "d" */    // VIP blocked from receiving armor thru sh
#define VIP_BLOCK_SPEED        (1<<4)    /* flag "e" */    // VIP blocked from receiving speed thru sh
#define VIP_BLOCK_GRAVITY    (1<<5)    /* flag "f" */    // VIP blocked from receiving gravity thru sh
#define VIP_BLOCK_EXTRADMG    (1<<6)    /* flag "g" */    // VIP blocked from using sh_extra_damage
#define VIP_BLOCK_CUSTOM    (1<<7)    /* flag "h" */    // Custom VIP block, heroes can use for whatever they want

// From multiplayer/dlls/player.cpp (Note: Actual CS calculation is unknown)
#define SH_ARMOR_RATIO        0.5    // Armor Takes 50% of the damage (0.2 in the HL SDK)
#define SH_ARMOR_BONUS        0.5    // Each Point of Armor is worth 1/x points of health (0.5 in the HL SDK)

// Common sound for denying power use, precached by core
stock const gSoundDeny[] =     "common/wpn_denyselect.wav";

//------------
// Weapon look up tables
//------------
// usage: sh_get_max_bpammo(weaponID)
#define sh_get_max_bpammo(%1) gMaxBPAmmo[%1]
stock gMaxBPAmmo[] = {
    
0,
    
52,    //CSW_P228
    
0,
    
90,    //CSW_SCOUT
    
1,    //CSW_HEGRENADE
    
32,    //CSW_XM1014
    
1,    //CSW_C4
    
100,    //CSW_MAC10
    
90,    //CSW_AUG
    
1,    //CSW_SMOKEGRENADE
    
120,    //CSW_ELITE
    
100,    //CSW_FIVESEVEN
    
100,    //CSW_UMP45
    
90,    //CSW_SG550
    
90,    //CSW_GALIL
    
90,    //CSW_FAMAS
    
100,    //CSW_USP
    
120,    //CSW_GLOCK18
    
30,    //CSW_AWP
    
120,    //CSW_MP5NAVY
    
200,    //CSW_M249
    
32,    //CSW_M3
    
90,    //CSW_M4A1
    
120,    //CSW_TMP
    
90,    //CSW_G3SG1
    
2,    //CSW_FLASHBANG
    
35,    //CSW_DEAGLE
    
90,    //CSW_SG552
    
90,    //CSW_AK47
    
0,    //CSW_KNIFE
    
100    //CSW_P90
};
// usage: sh_get_max_clipammo(weaponID)
#define sh_get_max_clipammo(%1) gMaxClipAmmo[%1]
stock gMaxClipAmmo[] = {
    
0,
    
13,    //CSW_P228
    
0,
    
10,    //CSW_SCOUT
    
0,    //CSW_HEGRENADE
    
7,    //CSW_XM1014
    
0,    //CSW_C4
    
30,    //CSW_MAC10
    
30,    //CSW_AUG
    
0,    //CSW_SMOKEGRENADE
    
30,    //CSW_ELITE
    
20,    //CSW_FIVESEVEN
    
25,    //CSW_UMP45
    
30,    //CSW_SG550
    
35,    //CSW_GALIL
    
25,    //CSW_FAMAS
    
12,    //CSW_USP
    
20,    //CSW_GLOCK18
    
10,    //CSW_AWP
    
30,    //CSW_MP5NAVY
    
100,    //CSW_M249
    
8,    //CSW_M3
    
30,    //CSW_M4A1
    
30,    //CSW_TMP
    
20,    //CSW_G3SG1
    
0,    //CSW_FLASHBANG
    
7,    //CSW_DEAGLE
    
30,    //CSW_SG552
    
30,    //CSW_AK47
    
0,    //CSW_KNIFE
    
50    //CSW_P90
};
// usage: sh_get_weapon_slot(weaponID)
#define sh_get_weapon_slot(%1) gWeaponSlot[%1]
stock gWeaponSlot[] = {
    
0,
    
2,    //CSW_P228
    
0,
    
1,    //CSW_SCOUT
    
4,    //CSW_HEGRENADE
    
1,    //CSW_XM1014
    
5,    //CSW_C4
    
1,    //CSW_MAC10
    
1,    //CSW_AUG
    
4,    //CSW_SMOKEGRENADE
    
2,    //CSW_ELITE
    
2,    //CSW_FIVESEVEN
    
1,    //CSW_UMP45
    
1,    //CSW_SG550
    
1,    //CSW_GALIL
    
1,    //CSW_FAMAS
    
2,    //CSW_USP
    
2,    //CSW_GLOCK18
    
1,    //CSW_AWP
    
1,    //CSW_MP5NAVY
    
1,    //CSW_M249
    
1,    //CSW_M3
    
1,    //CSW_M4A1
    
1,    //CSW_TMP
    
1,    //CSW_G3SG1
    
4,    //CSW_FLASHBANG
    
2,    //CSW_DEAGLE
    
1,    //CSW_SG552
    
1,    //CSW_AK47
    
3,    //CSW_KNIFE
    
1    //CSW_P90
};
// usage: check sh_get_weapon_speed stock in superheromod.inc
// Thanks WC3:FT for weapon speeds so I didn't have to check them
stock Float:gWeaponSpeed[] = {
    
0.0,
    
250.0,    // CSW_P228
    
0.0,
    
260.0,    // CSW_SCOUT
    
250.0,    // CSW_HEGRENADE
    
240.0,    // CSW_XM1014
    
250.0,    // CSW_C4
    
250.0,    // CSW_MAC10
    
240.0,    // CSW_AUG
    
250.0,    // CSW_SMOKEGRENADE
    
250.0,    // CSW_ELITE
    
250.0,    // CSW_FIVESEVEN
    
250.0,    // CSW_UMP45
    
210.0,    // CSW_SG550
    
240.0,    // CSW_GALI
    
240.0,    // CSW_FAMAS
    
250.0,    // CSW_USP
    
250.0,    // CSW_GLOCK18
    
210.0,    // CSW_AWP
    
250.0,    // CSW_MP5NAVY
    
220.0,    // CSW_M249
    
230.0,    // CSW_M3
    
230.0,    // CSW_M4A1
    
250.0,    // CSW_TMP
    
210.0,    // CSW_G3SG1
    
250.0,    // CSW_FLASHBANG
    
250.0,    // CSW_DEAGLE
    
235.0,    // CSW_SG552
    
221.0,    // CSW_AK47
    
250.0,    // CSW_KNIFE
    
245.0    // CSW_P90
};


// SuperHero Main Include File
// Version 1.2.0


#pragma reqlib "SuperHero Core"
#if !defined AMXMODX_NOAUTOLOAD
  #pragma loadlib "SuperHero Core"
#endif

//Default includes used for shero
#include <amxmodx>
#include <fakemeta>
#include <hamsandwich>
#include <fun>
#include <csx>
#include <cstrike>

#if defined SH_BACKCOMPAT
  #include <engine>
#endif

//----------------------------------------------------------------------------------------------
// IMPORTANT FUNCTIONS - WHAT EVENTS CAN THE SUPERHEROES REGISTER FOR?
//----------------------------------------------------------------------------------------------


/**************************
 *        FORWARDS        *
 **************************/

/**
 * Called when a hero is added or dropped.
 * See superheroconst.inc for mode types.
 *
 * @param id            The index of the client.
 * @param heroID        The index of the hero.
 * @param mode            The heroID is being added or dropped.
 * @noreturn
 */
forward sh_hero_init(idheroIDmode);

/**
 * Called when a +/-power is executed.
 * See superheroconst.inc for key types.
 *
 * @param id            The index of the client.
 * @param heroID        The index of the hero.
 * @param key            The heroID power key function, key down or key up.
 * @noreturn
 */
forward sh_hero_key(idheroIDkey);

/**
 * Called post player spawn.
 *
 * @param id            The index of the client.
 * @param bool:newRound        True if client spawned because of a new round, else false.
 * @noreturn
 */
forward sh_client_spawn(idbool:newRound);

/**
 * Called whenever a client dies.
 * Death from sh_extra_damage will send correct info into this forward.
 *
 * @param victim        The index of the victim.
 * @param attacker        The index of the attacker.
 * @param headshot        Equals 1 if death is by a headshot else 0.
 * @param wpnDescription    Name of the weapon that killed the victim.
 * @noreturn
 */
forward sh_client_death(victimattackerheadshot, const wpnDescription[]);

/**
 * Called every new round (start of freezetime).
 *
 * @noreturn
 */
forward sh_round_new();

/**
 * Called at the approximate time that a round is started.
 * (0.1 seconds after the end of freezetime).
 *
 * @noreturn
 */
forward sh_round_start();

/**
 * Called at the end of every round (and on sv_restart).
 *
 * @noreturn
 */
forward sh_round_end();


/**************************
 *        NATIVES         *
 **************************/

/**
 * Whether or not there is a game in progress.
 * In round is between end of freezetime and end of round.
 *
 * @return        True if game is in round, false otherwise.
 */
native bool:sh_is_inround();

/**
 * Returns current freezetime status (new round to round start).
 * Freezetime is between the start and end mp_freezetime time.
 *
 * @return        True if game is in freezetime, false otherwise.
 */
native bool:sh_is_freezetime();

/**
 * Returns server's max level.
 *
 * @note        The earliest this is guaranteed to be accurate is during plugin_cfg(). It needs
 *                the max level to be properly set or it will return 0.
 *
 * @return        The max number of levels of the server.
 */
native sh_get_num_lvls();

/**
 * Gets the XP required for the level.
 *
 * @param level        The level number to check.
 * @return        The XP needed for the level, else -1 if not a valid level.
 */
native sh_get_lvl_xp(level);

/**
 * Gets the client's current level.
 *
 * @param id        The index of the client.
 * @return        The current level of the client, else -1 if not a valid id.
 */
native sh_get_user_lvl(id);

/**
 * Sets the client's current level.
 *
 * @param id        The index of the client.
 * @param level        The level to set on the client.
 * @return        The level set on the client, else -1 if not a valid level.
 */
native sh_set_user_lvl(idlevel);

/**
 * Gets the client's current XP.
 *
 * @param id        The index of the client.
 * @return        The current XP of the client.
 */
native sh_get_user_xp(id);

/**
 * Sets or Adds to the client's current XP.
 *
 * @param id        The index of the client.
 * @param xp        The xp to set/add on the client.
 * @param addtoxp    False to set client xp to the xp specified, true to add xp to client's current xp.
 * @return        1 if success, -1 if invalid client.
 */
native sh_set_user_xp(idxpbool:addtoxp false);

/**
 * Adds to the client's current XP in the amount equal to if client killed victim.
 * As if client killed victim with sh_extra_damage, client recives the xp for that kill.
 *
 * @param id        The index of the client.
 * @param victim    The index of the client to calculate kill xp amount to add to id.
 * @param multiplier    Amount to multiply the kill xp by.
 * @noreturn
 */
native sh_add_kill_xp(idvictimFloat:multiplier 1.0);

/**
 * Gets the client's max Health based on heroes client has.
 *
 * @param id        The index of the client.
 * @return        The max hero HP of the client, else 0 if invalid client.
 */
native sh_get_max_hp(id);

/**
 * Gets the client's max SuperHero Armor.
 *
 * @param id        The index of the client.
 * @return        The max hero AP of the client, else 0 if invalid client.
 */
native sh_get_max_ap(id);

//------------
// Hero Creation/Property Natives
//------------
// IMPORTANT: Make sure these are set AFTER cvars are registered

/**
 * Creates the hero and returns the heroID. (Required)
 *
 * @note    This must be the first property set as it returns the hero index to be used for the rest.
 *
 * @param heroName    The name of the Hero. (max 24 characters)
 * @param pcvarMinLevel    The pcvar value for minmum Level required CVAR for the hero.
 * @return        The hero's index, -1 on failure.
 */
native sh_create_hero(const heroName[], pcvarMinLevel);

/**
 * Sets the hero's power description and help info. (Required)
 *
 * @param heroID    The index of the hero.
 * @param powerInfo    The short info for the heroes power, used in the power select menu. (max 49 characters)
 * @param powerHelp    The long description for the heroes power, hud message displayed when users chooses the hero. (max 127 characters)
 * @noreturn
 */
native sh_set_hero_info(heroID, const powerInfo[] = "", const powerHelp[] = "");

/**
 * Sets the hero to use a +power bind key. (Optional)
 * Use only if hero requires a bound key.
 *
 * @param heroID    The index of the hero.
 * @noreturn
 */
native sh_set_hero_bind(heroID);

/**
 * Sets hero's shield restriction status. (Optional)
 *
 * @note        Set this on heroes that give weapons to avoid invisible shield bug.
 *
 * @param heroID    The index of the hero.
 * @param restricted    Set true to restict hero from allowing shield use, otherwise false.
 * @noreturn
 */
native sh_set_hero_shield(heroIDbool:restricted false);

/**
 * Sets hero's max Health and Armor. (Optional)
 * Health and Armor do not stack, values from heroes are compared and greatest is applied.
 *
 * @note        If you only want to set one of the values, set the other to 0 or underscore "_" to use the default set value of 0.
 *
 * @param heroID    The index of the hero.
 * @param pcvarHealth    The pcvar value for maximum Health CVAR for the hero, CVAR values below 100 are ignored.
 * @param pcvarArmor    The pcvar value for maximum Armor CVAR for the hero.
 * @noreturn
 */
native sh_set_hero_hpap(heroIDpcvarHealth 0pcvarArmor 0);

/**
 * Sets hero's max speed dependent on currently held weapon. (Optional)
 * Speeds do not stack, values from heroes are compared and greatest is applied.
 * weapons[] is an array of weapons this speed is good for, check CSW_ constants for weapon values.
 * {29, 30} would equal the CSW_ weapon constants corresponding to {CSW_KNIFE, CSW_P90}, etc... (see amxconst.inc)
 *
 * @note        This setting does not effect speed of sniper rifles when scoped.
 *                Max possible running speed is 2000, limited by half-life.
 *                Clients are also limited by cl_***speed client cvars defaulted to 400.
 *                Scout is the fastest default weapon at 260 and the other 3 snipers slowest at 150 when scoped.
 *
 * @param heroID    The index of the hero.
 * @param pcvarSpeed    The pcvar value for maximum Speed CVAR for the hero.
 * @param weapons    Array of weapon CSW_ constant values to set speed for, 0 is for all weapons.
 * @param numofwpns    The size of the weapons array, this MUST be passed in CORRECTLY!
 * @noreturn
 */
native sh_set_hero_speed(heroIDpcvarSpeed, const weapons[] = {0}, numofwpns 1);

/**
 * Sets hero's min gravity dependent on currently held weapon. (Optional)
 * Gravities do not stack, values from heroes are compared and lowest is applied.
 * weapons[] is an array of weapons this gravity is good for, check CSW_ constants for weapon values.
 * {29, 30} would equal the CSW_ weapon constants corresponding to {CSW_KNIFE, CSW_P90}, etc... (see amxconst.inc)
 *
 * @note        A Gravity value 0.0 or below is ignored, 1.0 is normal gravity (800).
 *                ***Weapon based gravity is not implemented yet. Maybe in next version, undecided.***
 *
 * @param heroID    The index of the hero.
 * @param pcvarGravity    The pcvar value for minimum Gravity CVAR for the hero.
 * @param weapons    Array of weapon CSW_ constant values to set gravity for, 0 is for all weapons.
 * @param numofwpns    The size of the weapons array, this MUST be passed in CORRECTLY!
 * @noreturn
 */
native sh_set_hero_grav(heroIDpcvarGravity, const weapons[] = {0}, numofwpns 1);


/**
 * Sets hero's damage multiplier for the specified cs/cz weapon. (Optional)
 * Multipliers do not stack, values from user's heroes are compared and greatest is applied.
 * If multiple weapons required, native must be called separately for each weapon.
 *
 * @note        A Multiplier value of 1.0 or below is ignored.
 *                Multiplier is applied before armor reduces damage.
 *
 * @param heroID    The index of the hero.
 * @param pcvarSpeed    The pcvar value of the damage multiplier CVAR for the specified weaponID.
 * @param weaponID    The CSW_ constant of the weapon to set damage multiplier for, 0 is for all weapons. (see amxconst.inc)
 * @noreturn
 */
native sh_set_hero_dmgmult(heroIDpcvarWpnMult, const weaponID 0);

//------------

/**
 * Forces client to drop weapon if they have it in inventory.
 *
 * @param id        The index of the client.
 * @param weaponID    The CSW_ index of the weapon. (see amxconst.inc)
 * @param remove    Set True to remove the weapon from world on drop, otherwise False to drop it like normal.
 * @noreturn
 */
native sh_drop_weapon(idweaponIDbool:remove false);

/**
 * Gives client a weapon.
 *
 * @note        This can be overridden by server using shweapon.cfg.
 *                If giving a primary weapon set sh_set_hero_shield() in hero to avoid invisible shield bug.
 *
 * @param id        The index of the client.
 * @param weaponID    The CSW_ index of the weapon. (see amxconst.inc)
 * @param switchTo    Set True to force client to switch to given weapon, otherwise False.
 * @noreturn
 */
native sh_give_weapon(idweaponIDbool:switchTo false);

/**
 * Gives client an item. (Use sh_give_weapon for better weapon_ handling)
 *
 * @note        Weapons can be overridden by server using shweapon.cfg.
 *                If giving a primary weapon set sh_set_hero_shield() in hero to avoid invisible shield bug.
 *
 * @param id        The index of the client.
 * @param itemName    The "item_*", "ammo_*", or "weapon_*" name of the desired item.
 * @param switchTo    Set True to force client to switch to given item if it's a weapon, otherwise False.
 * @noreturn
 */
native sh_give_item(id, const itemName[], bool:switchTo false);

/**
 * Sets ammo reload method.
 *
 * @note        You are responsible for when this is called, usually when clip is empty.
 *
 * @param id        The index of the client.
 * @param mode        The mode    0 - follow server sh_reloadmode CVAR
 *                    1 - continuous shooting, no reload
 *                    2 - fill the backpack (must reload)
 *                    3 - drop the gun and get a new one with full clip
 * @noreturn
 */
native sh_reload_ammo(idmode 0);

/**
 * Cause non-default extra damage.
 * Use this for non-default damage to correctly send damage messages and handle XP.
 *
 * @note        Set dmgFFmsg to false for looping extra damage, to avoid team attack chat spam.
 *                The default dmgOrigin of {0,0,0} will use attacker as the damage direction.
 *                Victim is unaffected if victim has godmode (this includes insta kill dmgMode).
 *
 * @param victim        The index of the victim.
 * @param attacker        The index of the attacker.
 * @param damage        Value of damage to cause, see dmgMode for effect on victim.
 * @param wpnDescription    Name of the weapon that causes the damage.
 * @param headshot        Set 1 if damage is a headshot else 0.
 * @param dmgMode        Type of damage, how victim is effected by damage value. See superheroconst.inc for types and explanations.
 * @param dmgStun        Set True to emulate damage stun on victim, otherwise False. (currently only sets horizontal velocity to 0)
 * @param dmgFFmsg        Set True to show friendly fire chat message "John Doe attacked a teammate", otherwise False.
 * @param dmgOrigin        Origin of damage bits direction (red flash indicators).
 * @noreturn
 */
native sh_extra_damage(victimattackerdamage, const wpnDescription[], headshot 0dmgMode SH_DMG_MULTbool:dmgStun falsebool:dmgFFmsg true, const Float:dmgOrigin[3] = {0.0,0.0,0.0});

/**
 * Speed stuns client for time specified. Bind powers are not usable when stunned.
 *
 * @note        Does not combine time, the highest time will override.
 *
 * @param id        The index of the client.
 * @param howLong    The length of time in seconds the stun lasts.
 * @param speed        The speed of the client when stunned.
 * @noreturn
 */
native sh_set_stun(idFloat:howLongFloat:speed 1.0);

/**
 * Returns a clients speed stun status.
 *
 * @param id        The index of the client.
 * @return        Returns 1 if client is in a stun, otherwise 0.
 */
native sh_get_stun(id);

/**
 * Sets godmode on client for time specified.
 *
 * @note        Does not combine time, the highest time will override.
 *                Client will sh glow blue {0,0,128} to indicate godmode. (This may be removed in a future version)
 *
 * @param id        The index of the client.
 * @param howLong    The length of time in seconds godmode lasts.
 * @noreturn
 */
native sh_set_godmode(idFloat:howLong);

/**
 * Gets hero's index.
 *
 * @param heroName    The name of the hero. (name must be exact spelling and case tense)
 * @return        Returns hero's index, -1 on failure
 */
native sh_get_hero_id(const heroName[]);

/**
 * Checks if the client has the hero.
 *
 * @param id        The index of the client.
 * @param heroID    The index of the hero.
 * @return        Returns 1 if client has hero, otherwise 0.
 */
native sh_user_has_hero(idheroID);

/**
 * Reset client's max speed according to heroes they have.
 * Useful incase a temporary value was set.
 *
 * @param id        The index of the client.
 * @noreturn
 */
native sh_reset_max_speed(id);

/**
 * Reset client's min gravity according to heroes they have.
 * Useful incase a temporary value was set.
 *
 * @param id        The index of the client.
 * @noreturn
 */
native sh_reset_min_gravity(id);

/**
 * Sends a chat message thru core to append colored [SH] to front of message.
 * If heroID is supplied hero's name will be colored in parentheses ie "[SH](Batman) message displayed here"
 *
 * @note        Max characters for message without heroID supplied is 186.
 *                 Max characters for message with heroID supplied is
 *                 between 183 and 160 depending on size of hero's name.
 *
 * @param id        The index of the client.
 * @param heroID    The index of the hero, appends hero name to message. Set -1 to not append a hero name.
 * @param message    The chat message itself.
 * @noreturn
 */
native sh_chat_message(idheroID = -1, const message[], any:...);

/**
 * Pass messages for debugging or set level to 0 and will always print message to log.
 *
 * @note        Adds "DEBUG: " to begining of message, may confuse some users if not an error.
 *
 * @param id        The index of the client.
 * @param level        The sh_debug_messages CVAR level to show the message at.
 * @param message    The message itself.
 * @noreturn
 */
native sh_debug_message(idlevel, const message[],  any:...);


/**************************
 *         STOCKS         *
 **************************/

/**
 * Checks if SuperHero is currently on or off.
 *
 * @return        Returns true if Shmod is active, otherwise false.
 */
stock bool:sh_is_active()
{
    static 
sv_superheros;

    if ( !
sv_superheros ) {
        
sv_superheros get_cvar_pointer("sv_superheros");
    }

    return (
sv_superheros ? (get_pcvar_num(sv_superheros) ? true false) : false);
}

/**
 * Checks if friendly fire is currently on or off.
 *
 * @return        Returns true if friendly fire is on, otherwise false.
 */
stock bool:sh_friendlyfire_on()
{
    static 
mp_friendlyfire;

    if ( !
mp_friendlyfire ) {
        
mp_friendlyfire get_cvar_pointer("mp_friendlyfire");
    }

    return (
get_pcvar_num(mp_friendlyfire) ? true false);
}

/**
 * Checks max players setting of server, better then using SH_MAXSLOTS most times.
 *
 * @return        Returns max players of server.
 */
stock sh_maxplayers()
{
    static 
maxplayers;

    if ( !
maxplayers )
        
maxplayers get_maxplayers();

    return 
maxplayers;
}

/**
 * Plays sound to inform the client they can not comply with the current action.
 *
 * @param id        The index of the client.
 * @noreturn
 */
stock sh_sound_deny(id)
{
    
// gSoundDeny precached by core
    
client_cmd(id"spk %s"gSoundDeny);
}

/**
 * Forces client to switch to specified weapon if they have the weapon.
 *
 * @param id        The index of the client.
 * @param weaponID    The CSW_ index of the weapon. (see amxconst.inc)
 * @noreturn
 */
stock sh_switch_weapon(idweaponID)
{
    if ( 
weaponID CSW_P228 || weaponID CSW_P90 ) return;

    if ( 
user_has_weapon(idweaponID) ) {
        static 
weaponName[32];
        
get_weaponname(weaponIDweaponNamecharsmax(weaponName));
        
engclient_cmd(idweaponName);
    }
}

/**
 * Creates a screen fade on the client.
 *
 * @param id        The index of the client.
 * @param fadeTime    The time in seconds the fade lasts.
 * @param holdTime    The time in seconds the fade is held.
 * @param red        The red rgb color value of the fade. (0-255)
 * @param green        The green rgb color value of the fade. (0-255)
 * @param blue        The blue rgb color value of the fade. (0-255)
 * @param alpha        The alpha transparency value of the fade. (0-255)
 * @param type        The type of fade. (see superheroconst.inc)
 * @noreturn
 */
stock sh_screen_fade(idFloat:fadeTimeFloat:holdTimeredgreenbluealphatype SH_FFADE_IN)
{
    static 
msgScreenFade;

    if ( !
msgScreenFade ) {
        
msgScreenFade get_user_msgid("ScreenFade");
    }

    
// Check unsigned short range
    
new fadehold;
    
fade clamp(floatround(fadeTime float(1<<12)), 00xFFFF);
    
hold clamp(floatround(holdTime float(1<<12)), 00xFFFF);

    
message_begin(MSG_ONE_UNRELIABLEmsgScreenFade_id);
    
write_short(fade);    // fade lasts this long duration
    
write_short(hold);    // fade lasts this long hold time
    
write_short(type);    // fade type (in / out)
    
write_byte(red);    // fade red
    
write_byte(green);    // fade green
    
write_byte(blue);    // fade blue
    
write_byte(alpha);    // fade alpha
    
message_end();
}

/**
 * Creates a screen shake on the client.
 *
 * @param id        The index of the client.
 * @param amplitude    The amount of displacement of the shake.
 * @param duration    The period of time of the shake.
 * @param frequency    The rate at which displacement of the shake is repeated.
 * @noreturn
 */
stock sh_screen_shake(idFloat:amplitudeFloat:durationFloat:frequency)
{
    static 
msgScreenShake;

    if ( !
msgScreenShake ) {
        
msgScreenShake get_user_msgid("ScreenShake");
    }

    
// Check unsigned short range
    
new ampdurafreq;
    
amp clamp(floatround(amplitude float(1<<12)), 00xFFFF);
    
dura clamp(floatround(duration float(1<<12)), 00xFFFF);
    
freq clamp(floatround(frequency float(1<<8)), 00xFFFF);

    
message_begin(MSG_ONE_UNRELIABLEmsgScreenShake_id);
    
write_short(amp);    // amplitude
    
write_short(dura);    // duration
    
write_short(freq);    // frequency
    
message_end();
}

/**
 * Set a render on an entity.
 * To set a typical glow set fx to kRenderFxGlowShell, the alpha amount of 16 is preferred.
 * To reset a glow or render on a client use sh_set_rendering(id).
 *
 * @note        For client's, lower visiblity takes preference unless it's a render reset.
 *
 * @param entity    The index of the entity.
 * @param r        The red color rgb value of the render. (0-255)
 * @param g        The green color rgb value of the render. (0-255)
 * @param b        The blue color rgb value of the render. (0-255)
 * @param amount    The alpha transparency value of the render. (0-255)
 * @param fx        The fx type of the render. (see amxconst.inc)
 * @param render    The type of render. (see amxconst.inc)
 * @return        Returns 1 on success, 0 on failure.
 */
stock sh_set_rendering(entity255255255amount 16fx kRenderFxNonerender kRenderNormal)
{
    if ( !
pev_valid(entity) ) return 0;

    new 
Float:alpha float(amount);

    
// This check is only to favor invisibility of a player over any other render expect a reset
    
if ( entity <= sh_maxplayers() ) {

        
// If client is in an alpha render do we need to block this render setting.
        
if ( pev(entitypev_rendermode) == kRenderTransAlpha ) {

            
// If just resetting render allow it to reset
            
if ( != 255 || != 255 || != 255 || amount != 16 || fx != kRenderFxNone || render != kRenderNormal ) {

                
// Skip setting any other render type, allow user to stay in alpha render
                
if ( render != kRenderTransAlpha ) return 0;

                new 
Float:currentAlpha;
                
pev(entitypev_renderamtcurrentAlpha);

                
// Only set alpha render if equal or less visible (equal to allow color changes etc.)
                
if ( alpha currentAlpha ) return 0;
            }
        }
    }

    new 
Float:renderColor[3];
    
renderColor[0] = float(r);
    
renderColor[1] = float(g);
    
renderColor[2] = float(b);

    
set_pev(entitypev_renderfxfx);
    
set_pev(entitypev_rendercolorrenderColor);
    
set_pev(entitypev_rendermoderender);
    
set_pev(entitypev_renderamtalpha);

    return 
1;
}

/**
 * Add to client's current health, up to a max limit.
 *
 * @param id        The index of the client.
 * @param hitPoints    The amount of health to add.
 * @param maxHealth    The maxium possible health to add up to, set 0 to use max from client's heroes.
 * @return        The amount of health added, 0 on failure.
 */
stock sh_add_hp(idhitPointsmaxHealth 0)
{
    if ( 
hitPoints == ) return 0;

    if ( 
maxHealth == maxHealth sh_get_max_hp(id);

    new 
currentHealth get_user_health(id);

    if ( 
currentHealth maxHealth ) {
        new 
newHealth min((currentHealth hitPoints), maxHealth);
        
set_user_health(idnewHealth);
        return 
newHealth currentHealth;
    }

    return 
0;
}

/**
 * Add to client's current armor, up to a max limit.
 *
 * @note    Armor power does not set til approx 0.6 seconds after spawn,
 *            do not regen armor during that time to allow sh to properly set AP.
 *
 * @param id        The index of the client.
 * @param armorPoints    The amount of armor to add.
 * @param maxArmor    The maxium possible armor to add up to, set 0 to use max from client's heroes.
 * @return        The amount of health added, 0 on failure.
 */
stock sh_add_ap(idarmorPointsmaxArmor 0)
{
    if ( 
armorPoints == ) return 0;

    if ( 
maxArmor == maxArmor sh_get_max_ap(id);

    new 
CsArmorType:armorType;
    new 
currentArmor cs_get_user_armor(idarmorType);

    if ( 
currentArmor maxArmor ) {
        if ( !
currentArmor armorType CS_ARMOR_VESTHELM;

        new 
newArmor min((currentArmor armorPoints), maxArmor);
        
cs_set_user_armor(idnewArmorarmorType);
        return 
newArmor currentArmor;
    }

    return 
0;
}

/**
 * Returns server flags for sh_blockvip cvar, can be used in heroes for custom VIP blocks.
 * (see superheroconst.inc for flag types)
 *
 * @note    You are still responsible to check if user is vip, use cs_get_user_vip(id).
 *             example usage: if(cs_get_user_vip(id) && sh_vip_flags()&VIP_BLOCK_CUSTOM) {//do something}
 *
 * @return    The flags currently set.
 */
stock sh_vip_flags()
{
    static 
sh_blockvip;

    if ( !
sh_blockvip ) {
        
sh_blockvip get_cvar_pointer("sh_blockvip");
    }

    if ( !
sh_blockvip ) return 0;

    static 
temp[9];
    
get_pcvar_string(sh_blockviptempcharsmax(temp));

    return 
read_flags(temp);
}

/**
 * Checks a hull to see if it is empty.
 * Good for checking if a client is or can be stuck at an origin.
 *
 * @note        While not very useful hitent is passed byref.
 *                 hitent is the index of ent in hull if any was found, otherwise 0 is passed.
 *
 * @param id        The index of the client that is ignored in the hull that is checked.
 * @param origin    The origin of the hull to check.
 * @param hullType    The type of hull to check, HULL_HEAD for crouching or HULL_HUMAN for standing. (see hlsdk_const.inc)
 * @return        True if hull is empty, otherwise false.
 */
stock bool:sh_hull_vacant(id, const Float:origin[3], hullType HULL_HEAD, &hitent 0)
{
    
// Thanks to VEN for his is_hull_vacant stock which this is based on

    // Find an open space and ignore id in that space
    
engfunc(EngFunc_TraceHulloriginorigin0hullTypeid0);

    
// byref index of what was hit, multiple things may be in hull so may not return what you expect
    
hitent get_tr2(0TraceResult:TR_pHit);

    
// Is the origin's hull empty for the hull type
    
if ( !get_tr2(0TraceResult:TR_StartSolid) && !get_tr2(0TraceResult:TR_AllSolid) && get_tr2(0TraceResult:TR_InOpen) )
        return 
true;

    return 
false;
}

/**
 * Gets a velocity to or from an origin.
 * Usually used for movement of created entities or to push players away from an explosion.
 *
 * @note        +/- speed is limited by servers sv_maxvelocity setting (default 2000)
 *                For explosions, set inital[2] a bit above final[2] to give a bit of a upward lift
 *
 * @param initial    The start origin. Generally an entity's origin on which to set velocity on.
 * @param final        The end origin. Generally the point where velocity is set to or from.
 * @param speed        Speed of the velocity to set:
 *                    - Positive value will set velocity TO final vector.
 *                    - Negative value will set velocity FROM final vector.
 * @param velocity    The return velocity. If a velocity is passed in, the return will add to it.
 */
stock sh_get_velocity(const Float:initial[3], const Float:final[3], Float:speedFloat:velocity[3])
{
    
// Lets make sure we are within range
    
static sv_maxvelocity;

    if ( !
sv_maxvelocity ) {
        
sv_maxvelocity get_cvar_pointer("sv_maxvelocity");
    }

    new 
Float:maxSpeed get_pcvar_float(sv_maxvelocity);

    
// Time = Distance / Speed
    
new Float:fTime vector_distance(initial, final) / floatclamp(speed, -maxSpeedmaxSpeed);

    
// Velocity = Distance / Time
    
velocity[0] += (final[0] - initial[0]) / fTime;
    
velocity[1] += (final[1] - initial[1]) / fTime;
    
velocity[2] += (final[2] - initial[2]) / fTime;
}

//------------
// Simple Functions to Help with Power Cooldowns.
//------------
// NOTE: The core will cancel cooldown task on a new spawn for safety, but
//       the hero itself must reset the gPlayerInCooldown variable to false.

/**
 * Global variable for cooldown status.
 *
 * @noreturn
 */
stock bool:gPlayerInCooldown[SH_MAXSLOTS+1];

/**
 * Sets a cooldown in a hero.
 *
 * @param id        The index of the client.
 * @param secs        The time in seconds the cooldown lasts before it is removed.
 * @noreturn
 */
stock sh_set_cooldown(idFloat:secs)
{
    
gPlayerInCooldown[id] = true;

    
set_task(secs"sh_end_cooldown"id+SH_COOLDOWN_TASKID);

    
sh_debug_message(id5"Cooldown Timer Started");
}

/**
 * Ends the cooldown in a hero.
 * This must be a public function since it is called by a task, rest can be stocks.
 *
 * @note        Called by cooldown through a task, so you do not need to call this.
 *                 However, it can be used to remove a cooldown earlier than task called to end it.
 *
 * @param id        The index of the client + SH_COOLDOWN_TASKID.
 * @noreturn
 */
public sh_end_cooldown(id)
{
    
// This is only here incase user wants to manually end cooldown
    // before task is over, does not matter if task is not going on.
    
remove_task(id);

    
id -= SH_COOLDOWN_TASKID;
    
gPlayerInCooldown[id] = false;

    
sh_debug_message(id5"Cooldown Timer Ended");
}

//------------
// Weapon Look Up Tables, faster then a switch statements.
//------------

/**
 * Returns max backpack ammo of weapon.
 *
 * @note        Stock created in superheroconst.inc, explained here for usage reference.
 *
 * @param weaponID    The CSW_ index of the weapon. (see amxconst.inc)
 * @return        The weapon's max backpack ammo.
 */
//sh_get_max_bpammo(weaponID)

/**
 * Returns max clip ammo of weapon.
 *
 * @note        Stock created in superheroconst.inc, explained here for usage reference.
 *
 * @param weaponID    The CSW_ index of the weapon. (see amxconst.inc)
 * @return        The weapon's max clip ammo.
 */
//sh_get_max_clipammo(weaponID)

/**
 * Returns weapon slot of weapon.
 * Useful to run code only on guns not on grenades, etc.
 *
 * @note        Stock created in superheroconst.inc, explained here for usage reference.
 *
 * @param weaponID    The CSW_ index of the weapon. (see amxconst.inc)
 * @return        The weapon slot.
 */
//sh_get_weapon_slot(weaponID)

/**
 * Gets the default speed of a weapon.
 *
 * @param weaponID    The CSW_ index of the weapon. (see amxconst.inc)
 * @param zoomed    Set True if weapon speed while zoomed is wanted, otherwise False.
 * @return        The speed of the weapon.
 */
stock Float:sh_get_weapon_speed(weaponIDbool:zoomed false)
{
    if ( 
zoomed ) {
        
// Only the 4 sniper rifles actually have different speeds when zoomed
        // And 3 of those have the same speed so lets just use a switch for them.
        
switch(weaponID) {
            case 
CSW_SCOUT: return 220.0;
            case 
CSW_SG550CSW_AWPCSW_G3SG1: return 150.0;
        }
    }

    return 
gWeaponSpeed[weaponID];
}

//------------
// Odd Stocks for core, not useful to most.
//------------

/**
 * Breaks a string into two parts, Left[] and Right[], keeping the quotes intact.
 *
 * @param text        The string to break.
 * @param Left        The string containing the first paramter broken.
 * @param leftLen    The size of the Left string.
 * @param Right        The string containing the rest after first parameter was broken off, not including the starting space. 
 * @param rightLen    The size of the Right string.
 * @return        Returns true upon completion.
 */
stock strbrkqt(const text[], Left[], leftLenRight[], rightLen)
{
    
// Breaks text[] into two parts, Left[], and Right[]
    // Left[] will contain the first parameter (either quoted or non-quoted)
    // Right[] contain the rest of the string after Left[], not including the space
    
new bool:in_quotes false;
    new 
bool:done_flag false;
    new 
ileft_pos 0;
    new 
textLen strlen(text);

    for ( 
0textLeni++) {

        if ( 
text[i] == '^"' && !done_flag ) {
            if ( 
in_quotes ) {
                
done_flag true;
                
in_quotes false;
            }
            else 
in_quotes true;
        }
        else if ( 
isspace(text[i]) && !in_quotes ) {
            if ( 
left_pos ) {
                
done_flag true;
            }
        }
        else if ( !
done_flag && left_pos <= leftLen ) {
            
setc(Left[left_pos], 1text[i]);
            
left_pos++;
        }
        else if ( 
done_flag ) break;
    }

    
Left[left_pos] = '^0';
    
copy(RightrightLentext[i]);

    return 
true;
}

/**
 * Prints heapsize. This is ONLY used to debug runtime 3 errors.
 *
 * @note        Unused but keep incase it is needed for debugging.
 *
 * @noreturn
 */
stock print_heapsize()
{
    
server_print("[SH] HeapSize: %i"heapspace());
}


//----------------------------------------------------------------------------------------------
// Below is for Backward compatibility layer only, please do not code with it any longer.
// You can test your code for compilance by commenting out SH_BACKCOMPAT in superheroconst.inc
// and compiling your hero. Then fix any compile errors with new functions above, below
// can be a reference.
//----------------------------------------------------------------------------------------------


#if defined SH_BACKCOMPAT


/**************************
 * BACKWARD COMPATIBILITY *
 **************************/

stock shCreateHero(const heroName[], const heroPower[], const heroHelp[], bool:requiresKeyEvents false, const heroLevel[])
{
    new 
heroID sh_create_hero(heroNameget_cvar_pointer(heroLevel));
    if ( 
heroID != -) {
        
sh_set_hero_info(heroIDheroPowerheroHelp);
        if ( 
requiresKeyEvents ) {
            
sh_set_hero_bind(heroID);
        }
    }
    return 
heroID;
}

stock shSetShieldRestrict(const heroName[])
{
    new 
heroID sh_get_hero_id(heroName);

    if ( 
heroID != -) {
        
sh_set_hero_shield(heroIDtrue);
    }
}

stock shSetMaxHealth(const heroName[], const heroHPCVAR[])
{
    new 
heroID sh_get_hero_id(heroName);

    if ( 
heroID != -) {
        
sh_set_hero_hpap(heroIDget_cvar_pointer(heroHPCVAR), _);
    }
}

stock shSetMaxArmor(const heroName[], const heroArmorCVAR[])
{
    new 
heroID sh_get_hero_id(heroName);

    if ( 
heroID != -) {
        
sh_set_hero_hpap(heroID_get_cvar_pointer(heroArmorCVAR));
    }
}

stock shSetMaxSpeed(const heroName[], const heroSpeedCVAR[], weaponString[])
{
    new 
heroID sh_get_hero_id(heroName);

    if ( 
heroID != -) {
        
//Convert old sh weapon string into an array of weapons
        
new number[3], weaponArray[33], i0;
        for ( 
0weaponString[i] != '^0'i++ ) {
            switch(
weaponString[i]) {
                case 
'[': continue;

                case 
']': {
                    
//Setup array
                    
weaponArray[x] = str_to_num(number);
                    ++
x;
                    
number[0] = '^0';
                }

                default: {
                    
//Single out weapon number
                    
add(numbercharsmax(number), weaponString[i]);
                }
            }
        }

        
sh_set_hero_speed(heroIDget_cvar_pointer(heroSpeedCVAR), weaponArray x);
    }
}

stock shSetMinGravity(const heroName[], const heroGravityCVAR[])
{
    new 
heroID sh_get_hero_id(heroName);

    if ( 
heroID != -) {
        
sh_set_hero_grav(heroIDget_cvar_pointer(heroGravityCVAR));
    }
}

//stock playSoundDenySelect(id)
#define playSoundDenySelect sh_sound_deny

//stock shAddXP(id, victim, Float:multiplier = 1.0 )
#define shAddXP sh_add_kill_xp

//stock shModActive()
#define shModActive sh_is_active

//stock shGetNumLevels()
#define shGetNumLevels sh_get_num_lvls

//stock hasRoundStarted()
#define hasRoundStarted() !sh_is_freezetime()

//stock shReloadAmmo(id, dropwpn = 0)
#define shReloadAmmo sh_reload_ammo

//stock shExtraDamage(id, attacker, damage, weaponDescription[], headshot = 0 )
#define shExtraDamage sh_extra_damage

#define getMaxClipAmmo(%1) gMaxClipAmmo[%1]
#define getMaxBPAmmo(%1) gMaxBPAmmo[%1]

//stock shResetSpeed(id)
#define shResetSpeed sh_reset_max_speed

//stock shSetGravityPower(id)
#define shSetGravityPower sh_reset_min_gravity

//stock shGiveWeapon(id, const weaponName[], bool:switchTo = false)
#define shGiveWeapon sh_give_item

//stock shGiveWeaponID(id, weaponID, bool:switchTo = false)
#define shGiveWeaponID sh_give_weapon

//stock shSwitchWeaponID(id, weaponID)
stock shSwitchWeaponID(idweaponID)
{
    if ( !
is_user_alive(id) ) return;

    
sh_switch_weapon(idweaponID);
}

//stock shOwnsWeaponID(id, weaponID)
#define shOwnsWeaponID user_has_weapon

//stock shOwnsWeapon(id, weaponName[])
#define shOwnsWeapon(%1, %2) user_has_weapon(%1, get_weaponid(%2))

//stock shUnglow(id)
#define shUnglow sh_set_rendering

//stock shAddHPs(id, hitPoints, maxHealth = 100)
stock shAddHPs(idhitPointsmaxHealth 100)
{
    if ( !
sh_is_active() ) return;

    
sh_add_hp(idhitPointsmaxHealth);
}

//stock shStun(id, secs)
stock shStun(idsecs)
{
    
sh_set_stun(idfloat(secs));
}

//stock shSetGodMode(id, secs)
stock shSetGodMode(idsecs)
{
    
sh_set_godmode(idfloat(secs));
}

//stock debugMessage(const message[], id = 0, level = 1)
stock debugMessage(const message[], id 0level 1)
{
    
sh_debug_message(idlevelmessage);
}

//stock shGlow(id, r, g, b)
stock shGlow(idrgb)
{
    
sh_set_rendering(idrgb16kRenderFxGlowShell);
}

//stock sh_setScreenFlash(id, red, green, blue, decisecs, alpha)
//stock setScreenFlash(id, red, green, blue, decisecs, alpha)
#define sh_setScreenFlash setScreenFlash
stock setScreenFlash(idredgreenbluedecisecsalpha)
{
    if ( !
is_user_connected(id) ) return;

    
sh_screen_fade(idfloat(decisecs)/10.0float(decisecs)/20.0redgreenbluealpha);
}

//stock sh_screenShake(id, amplitude, duration, frequency)
//stock setScreenShake(id, amplitude, duration, frequency)
#define sh_screenShake setScreenShake
stock setScreenShake(idamplitudedurationfrequency)
{
    if ( !
is_user_connected(id) ) return;

    
sh_screen_shake(idfloat(amplitude)/10.0float(duration)/10.0float(frequency)/10.0);
}

//cooldown stuff
#define gPlayerUltimateUsed gPlayerInCooldown
#define ultimateTimer sh_set_cooldown
#define enableUltimate sh_end_cooldown

stock shRegKeyUp(const heroName[], const keyUpFunction[])
{
    
server_cmd("sh_regKeyUp ^"%s^" ^"%s^""heroNamekeyUpFunction);
}

stock shRegKeyDown(const heroName[], const keyDownFunction[])
{
    
server_cmd("sh_regKeyDown ^"%s^" ^"%s^""heroNamekeyDownFunction);
}

stock shRegLevels(const heroName[], const levelFunction[])
{
    
server_cmd("sh_regLevels ^"%s^" ^"%s^""heroNamelevelFunction);
}

stock shRegMaxHealth(const heroName[], const healthFunction[])
{
    
server_cmd("sh_regMaxHealth ^"%s^" ^"%s^""heroNamehealthFunction);
}

stock shRegHeroInit(const heroName[], const initFunction[])
{
    
server_cmd("sh_regInit ^"%s^" ^"%s^""heroNameinitFunction);
}

//These stocks should now be ignored since removal upon hero drop is done in core
//Kept to allow heroes to compile without error
stock shResetShield(id)
{
    return 
id;
}
stock shRemHealthPower(id)
{
    return 
id;
}

stock shRemArmorPower(id)
{
    return 
id;
}

stock shRemGravityPower(id)
{
    return 
id;
}

stock shRemSpeedPower(id)
{
    return 
id;
}

//This is pointless, kept for backward compat only
stock bool:isDebugOn()
{
    static 
sh_debug_messages;

    if ( !
sh_debug_messages ) {
        
sh_debug_messages get_cvar_pointer("sh_debug_messages");
    }

    return (
get_pcvar_num(sh_debug_messages) > true false);
}

//------------
// Depreciated stocks
//------------

//Now in amxmodx 1.80.
#define maxof floatmax
#define minof floatmin

//old cmath.inc port of sqroot no longer needed.
#define sqrt(%1) sqroot(%1)

//This stock was moved to core.
//Forcing old heroes to throw a compile error so that they are
//forced to update to sh_extra_damage for better compatibility.
//stock logKill(id, victim, const weaponDescription[])


#endif 


This is "superheronvault.inc" :

PHP Code:

// SuperHero nVault Include File
// Version 1.2.0

//----------------------------------------------------------------------------------------------
// Abstract Methods that must be implemented by a save superhero include file...
//
// memoryTableWrite()
// loadXP(id, const savekey[32])
// cleanXP(clearAll = false)
//----------------------------------------------------------------------------------------------

#if defined _shsave_included || !defined SHCORE
    #endinput
#endif
#define _shsave_included

//Include the nvault file
#include <nvault>

//Global to save the vault handle
new gVaultHandle

//----------------------------------------------------------------------------------------------
saving_init()
{
    
gVaultHandle nvault_open("superhero")

    if ( 
gVaultHandle == INVALID_HANDLE ) {
        
debugMsg(00"Error opening nVault file: superhero.vault")
    }
}
//----------------------------------------------------------------------------------------------
public memoryTableWrite()
{
    if ( !
get_pcvar_num(sh_savexp) ) return

    
debugMsg(03"Writing XP Data to nVault file")

    
// Write Memory Table to File
    
for ( new 1gMemoryTableCountx++ ) {
        if ( 
gMemoryTableKeys[x][0] != '^0' ) {
            
writeData(x)
        }
        
// Can even clear the MemoryKey - if a player is disconnected no reason to save again and again...
        
gMemoryTableKeys[x][0] = '^0'
    
}

    
// No need to keep disconnected players around if this has been flushed...
    
gMemoryTableCount 33
}
//----------------------------------------------------------------------------------------------
writeData(id)
{
    
// Formats Player Information and writes to file:
    // "name" XP USERFLAGS "SKILL1" "SKILL2" ...
    
static data[1501]
    new 
heroIndexlen
    
new powerCount gMemoryTablePowers[id][0]

    
data[0] = '^0'

    
len += formatex(data[len], charsmax(data)-len"^"%s^" %d %d"gMemoryTableNames[id], gMemoryTableXP[id], gMemoryTableFlags[id])

    for ( new 
1<= powerCount && <= gSuperHeroCount && len charsmax(data); x++ ) {
        
heroIndex gMemoryTablePowers[id][x]
        if ( -
heroIndex gSuperHeroCount ) {
            
len += formatex(data[len], charsmax(data)-len" ^"%s^""gSuperHeros[heroIndex][hero])
        }
    }

    
nvault_set(gVaultHandlegMemoryTableKeys[id], data)

    if ( 
id <= SH_MAXSLOTS ) {
        
gChangedHeroes[id] = false
    
}
}
//----------------------------------------------------------------------------------------------
loadXP(id, const savekey[32])
{
    static 
Right[1501], temp
    Right
[0] = '^0'

    
if ( nvault_lookup(gVaultHandlesavekeyRightcharsmax(Right), temp) ) {
        
// parseXP

        // "name" XP USERFLAGS "SKILL1" "SKILL2" ...
        
new heroIndexpowerCountmaxPowersplayerLevel
        
static Left[32]
        
Left[0] = '^0'

        
// Get the name out
        
strbrkqt(RightLeftcharsmax(Left), Rightcharsmax(Right))
        
Left[0] = '^0'

        
// Get the XP out and save it
        
strbrkqt(RightLeftcharsmax(Left), Rightcharsmax(Right))
        
gPlayerXP[id] = str_to_num(Left)
        
gPlayerLevel[id] = playerLevel getPlayerLevel(id)
        
setLevel(idplayerLevel)
        
Left[0] = '^0'

        
// Get the User Flags out and save them
        
strbrkqt(RightLeftcharsmax(Left), Rightcharsmax(Right))
        
gPlayerFlags[id] = str_to_num(Left)

        
// Now load in all the skills
        
powerCount 0
        maxPowers 
min(get_pcvar_num(sh_maxpowers), SH_MAXLEVELS)

        while ( 
Right[0] != '^0' && powerCount maxPowers ) {
            
Left[0] = '^0'
            
strbrkqt(RightLeftcharsmax(Left), Rightcharsmax(Right))
            
heroIndex getHeroID(Left)
            if ( -
heroIndex gSuperHeroCount ) {
                if ( 
getHeroLevel(heroIndex) <= playerLevel ) {
                    
gPlayerPowers[id][0] = ++powerCount
                    gPlayerPowers
[id][powerCount] = heroIndex
                    initHero
(idheroIndexSH_HERO_ADD)
                }
            }
        }
    }

    
memoryTableUpdate(id)

    return 
true
}
//----------------------------------------------------------------------------------------------
cleanXP(bool:clearAll)
{
    if ( 
clearAll ) {
        
nvault_prune(gVaultHandle00)
    }
    else if ( 
get_pcvar_num(sh_savexp) ) {
        new 
xpSaveDays get_pcvar_num(sh_xpsavedays)

        if ( 
xpSaveDays ) return

        
nvault_prune(gVaultHandle0get_systime() - (xpSaveDays 24 3600))
    }
}
//----------------------------------------------------------------------------------------------
saving_end()
{
    
//Close the vault to save all the data
    
nvault_close(gVaultHandle)
}
//---------------------------------------------------------------------------------------------- 


And "nvault.inc" : (I don't know it should be there or not.)

PHP Code:

/* nVault functions
*
* by the AMX Mod X Development Team
*
* This file is provided as is (no warranties).
*/

#if defined _nvault_included
  #endinput
#endif
#define _nvault_included

#if AMXX_VERSION_NUM >= 175
 #pragma reqlib nvault
 #if !defined AMXMODX_NOAUTOLOAD
  #pragma loadlib nvault
 #endif
#else
 #pragma library nvault
#endif

/* All timestamps are in UNIX epoch form. */

/* Opens a vault by name (such as "myvault")
 * Returns a vault id, INVALID_HANDLE otherwise (-1)
 */
native nvault_open(const name[]);

/* Gets a vault value by returning an int
 * setting a byref float or setting a string + maxlength
 */
native nvault_get(vault, const key[], {Float,_}:...);

/* Looks up a vault value for full information
 * Returns 0 if the entry is not found
 */
native nvault_lookup(vault, const key[], value[], maxlen, &timestamp);

/* Sets a vault value (with current timestamp) */
native nvault_set(vault, const key[], const value[]);

/* Sets a permanent vault value (no timestamp) */
native nvault_pset(vault, const key[], const value[]);

/* Prunes the vault for entries that are within the given timestamps.
 * This will not erase values set with pset
 */
native nvault_prune(vaultstartend);

/* Closes a vault */
native nvault_close(vault);

/* Removes a key from the vault */
native nvault_remove(vault, const key[]);

/* "Touches" a key to update its timestamp value.  
 * If stamp is -1 (default), it will use the current time.
 * Like the unix command "touch," it will create an empty key
 *  if the value does not exist.
 */
native nvault_touch(vault, const key[], timestamp=-1); 



All times are GMT -4. The time now is 16:44.

Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.