#include <sourcemod>
#include <sdktools>
#include <sdkhooks>
#undef REQUIRE_EXTENSIONS
#include <cstrike>
#define REQUIRE_EXTENSIONS
//this variable defines how many checkpoints per player there will be
#define CPLIMIT 10
//this variable defines who is allowed to execute admin commands
#define ADMIN_LEVEL ADMFLAG_UNBAN
//-----------------------------//
// nothing to change over here //
//-----------------------------//
//...
#define VERSION "2.1.0"
#define YELLOW 0x01
#define TEAMCOLOR 0x02
#define LIGHTGREEN 0x03
#define GREEN 0x04
#define POS_START 0
#define POS_STOP 1
#define RECORD_TIME 0
#define RECORD_JUMP 1
#define MYSQL 0
#define SQLITE 1
#define MAX_MAP_LENGTH 32
//-------------------//
// many variables :) //
//-------------------//
new g_DbType;
new Handle:g_hDb = INVALID_HANDLE;
new Handle:g_hcvarEnable = INVALID_HANDLE;
new bool:g_bEnabled = false;
new Handle:g_hcvarCleanupGuns = INVALID_HANDLE;
new bool:g_bCleanupGuns = false;
new g_WeaponParent;
new Handle:g_hcvarTimer = INVALID_HANDLE;
new bool:g_bTimer = false;
new Handle:g_hcvarRecordType = INVALID_HANDLE;
new g_bRecordType = RECORD_TIME;
new Handle:g_hcvarRotation = INVALID_HANDLE;
new bool:g_bRotation = false;
new Handle:g_hDrawZoneTimer = INVALID_HANDLE;
new bool:g_bStartCordsSet = false;
new bool:g_bStopCordsSet = false;
new Handle:g_hcvarRestore = INVALID_HANDLE;
new bool:g_bRestore = false;
new Handle:g_hcvarNoBlock = INVALID_HANDLE;
new bool:g_bNoBlock = false;
new Handle:g_hcvarPlayerBlock = INVALID_HANDLE;
new bool:g_bPlayerBlock = false;
new Handle:g_hcvarPlayerHide = INVALID_HANDLE;
new bool:g_bPlayerHide = false;
new Handle:g_hcvarAlpha = INVALID_HANDLE;
new g_Alpha = 255;
new Handle:g_hcvarAutoFlash = INVALID_HANDLE
new bool:g_bAutoFlash = false;
new Handle:g_hcvarTracer = INVALID_HANDLE;
new bool:g_bTracer = false;
new Handle:g_hcvarGunLimit = INVALID_HANDLE;
new g_GunLimit = 0;
new Handle:g_hcvarGravity = INVALID_HANDLE;
new bool:g_bGravity = false;
new Handle:g_hcvarHealClient = INVALID_HANDLE;
new bool:g_bHealClient = false;
new Handle:g_hcvarHintSound = INVALID_HANDLE;
new bool:g_bHintSound = false;
new Handle:g_hcvarStartSound = INVALID_HANDLE;
new String:g_szStartSound[PLATFORM_MAX_PATH];
new bool:g_bStartSound = false;
new Handle:g_hcvarFinishSound = INVALID_HANDLE;
new String:g_szFinishSound[PLATFORM_MAX_PATH];
new bool:g_bFinishSound = false;
new Handle:g_hcvarRecordSound = INVALID_HANDLE;
new String:g_szRecordSound[PLATFORM_MAX_PATH];
new bool:g_bRecordSound = false;
new bool:g_bSpeedUnit = false;
new Handle:g_hcvarSpeedUnit = INVALID_HANDLE;
new bool:g_bChatVisible = false;
new Handle:g_hcvarChatVisible = INVALID_HANDLE;
new Handle:g_hTraceTimer[MAXPLAYERS+1];
new Handle:g_hMapTimer[MAXPLAYERS+1];
new bool:g_bRacing[MAXPLAYERS+1];
new Handle:g_hCleanTimer = INVALID_HANDLE;
new Handle:g_hcpSetterTimer = INVALID_HANDLE;
new Float:g_fCpSetBCords[3];
new Float:g_fCpSetECords[3];
//coordinates
new Float:g_fMapTimer_spawn_cords[3];
new Float:g_fMapTimer_start0_cords[3];
new Float:g_fMapTimer_start1_cords[3];
new Float:g_fMapTimer_end0_cords[3];
new Float:g_fMapTimer_end1_cords[3];
new Float:g_fPlayerCords[MAXPLAYERS+1][CPLIMIT][3];
new Float:g_fPlayerAngles[MAXPLAYERS+1][CPLIMIT][3];
//number of current checkpoint in the storage array
new g_CurrentCp[MAXPLAYERS+1];
//amount of checkpoints available
new g_WholeCp[MAXPLAYERS+1];
new bool:g_bBlocking[MAXPLAYERS+1];
new bool:g_bHidden[MAXPLAYERS+1];
new g_Scouts[MAXPLAYERS+1];
new g_Usps[MAXPLAYERS+1];
new g_RunTime[MAXPLAYERS+1];
new g_RunJumps[MAXPLAYERS+1];
new String:g_szMapName[MAX_MAP_LENGTH];
new g_RecordJumps;
new g_RecordTime;
new g_BeamSpriteFollow, g_BeamSpriteRing1, g_BeamSpriteRing2;
new bool:g_bCpPanelOpen = false;
//----------//
// includes //
//----------//
#include "cPMod/admin.sp"
#include "cPMod/commands.sp"
#include "cPMod/helper.sp"
#include "cPMod/hooks.sp"
#include "cPMod/sql.sp"
public Plugin:myinfo = {
name = "cPMod",
author = "byaaaaah",
description = "Bunnyhop / Surf / Tricks server modification",
version = VERSION,
url = "http://b-com.tk"
}
//----------------//
// initialization //
//----------------//
public OnPluginStart(){
LoadTranslations("cpmod.phrases");
HookEvent("player_spawn", Event_player_spawn);
HookEvent("player_jump",Event_player_jump);
db_setupDatabase();
CreateConVar("cPMod_version", VERSION, "cP Mod version.", FCVAR_DONTRECORD|FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY);
g_hcvarEnable = CreateConVar("sm_cp_enabled", "1", "Enable/Disable the plugin.", FCVAR_PLUGIN|FCVAR_NOTIFY, true, 0.0, true, 1.0);
g_bEnabled = GetConVarBool(g_hcvarEnable);
HookConVarChange(g_hcvarEnable, OnSettingChanged);
g_hcvarCleanupGuns = CreateConVar("sm_cp_cleanupguns", "1", "Enable/Disable automatic removal of scouts.", FCVAR_PLUGIN, true, 0.0, true, 1.0);
HookConVarChange(g_hcvarCleanupGuns, OnSettingChanged);
g_bCleanupGuns = GetConVarBool(g_hcvarCleanupGuns);
g_WeaponParent = FindSendPropOffs("CBaseCombatWeapon", "m_hOwnerEntity");
g_hcvarTimer = CreateConVar("sm_cp_timer", "1", "Enable/Disable map based timer.", FCVAR_PLUGIN, true, 0.0, true, 1.0);
g_bTimer = GetConVarBool(g_hcvarTimer);
HookConVarChange(g_hcvarTimer, OnSettingChanged);
g_hcvarRecordType = CreateConVar("sm_cp_recordtype", "0", "Sets recordtype to time(0) or jumps(1).", FCVAR_PLUGIN, true, 0.0, true, 1.0);
g_bRecordType = GetConVarInt(g_hcvarRecordType);
HookConVarChange(g_hcvarRecordType, OnSettingChanged);
g_hcvarRotation = CreateConVar("sm_cp_cprotation", "0", "<Enable/Disable automatic checkpoint rotation.", FCVAR_PLUGIN, true, 0.0, true, 1.0);
g_bRotation = GetConVarBool(g_hcvarRotation);
HookConVarChange(g_hcvarRotation, OnSettingChanged);
g_hcvarRestore = CreateConVar("sm_cp_restore", "1", "Enable/Disable automatic saving of checkpoints to database.", FCVAR_PLUGIN, true, 0.0, true, 1.0);
g_bRestore = GetConVarBool(g_hcvarRestore);
HookConVarChange(g_hcvarRestore, OnSettingChanged);
g_hcvarNoBlock = CreateConVar("sm_cp_noblock", "1", "Enable/Disable player blocking.", FCVAR_PLUGIN, true, 0.0, true, 1.0);
g_bNoBlock = GetConVarBool(g_hcvarNoBlock);
HookConVarChange(g_hcvarNoBlock, OnSettingChanged);
g_hcvarPlayerBlock = CreateConVar("sm_cp_playerblock", "1", "Enable/Disable player !block command.", FCVAR_PLUGIN, true, 0.0, true, 1.0);
g_bPlayerBlock = GetConVarBool(g_hcvarPlayerBlock);
HookConVarChange(g_hcvarPlayerBlock, OnSettingChanged);
g_hcvarPlayerHide = CreateConVar("sm_cp_playerhide", "1", "Enable/Disable player !hide command.", FCVAR_PLUGIN, true, 0.0, true, 1.0);
g_bPlayerHide = GetConVarBool(g_hcvarPlayerHide);
HookConVarChange(g_hcvarPlayerHide, OnSettingChanged);
g_hcvarAlpha = CreateConVar("sm_cp_alpha", "70", "<0|255> Sets player alpha (0=invisible - 255=visible).", FCVAR_PLUGIN, true, 0.0, true, 255.0);
g_Alpha = GetConVarInt(g_hcvarAlpha);
HookConVarChange(g_hcvarAlpha, OnSettingChanged);
g_hcvarAutoFlash = CreateConVar("sm_cp_autoflash", "0", "Enable/Disable auto flashbang giver.", FCVAR_PLUGIN, true, 0.0, true, 1.0);
g_bAutoFlash = GetConVarBool(g_hcvarAutoFlash);
HookConVarChange(g_hcvarAutoFlash, OnSettingChanged);
if(g_bAutoFlash){
HookEvent("player_blind" , Event_flashbang_detonate);
HookEvent("weapon_fire" , Event_weapon_fire);
}
g_hcvarTracer = CreateConVar("sm_cp_tracer", "0", "Enable/Disable admin Tracers.", FCVAR_PLUGIN, true, 0.0, true, 1.0);
g_bTracer = GetConVarBool(g_hcvarTracer);
HookConVarChange(g_hcvarTracer, OnSettingChanged);
g_hcvarGunLimit = CreateConVar("sm_cp_gunlimit", "0", "Sets the gun limit for each player. 0 to disable.", FCVAR_PLUGIN, true, 0.0, true, 10.0);
g_GunLimit = GetConVarInt(g_hcvarGunLimit);
HookConVarChange(g_hcvarGunLimit, OnSettingChanged);
g_hcvarGravity = CreateConVar("sm_cp_gravity", "0", "Enable/Disable player gravity.", FCVAR_PLUGIN, true, 0.0, true, 1.0);
g_bGravity = GetConVarBool(g_hcvarGravity);
HookConVarChange(g_hcvarGravity, OnSettingChanged);
g_hcvarHealClient = CreateConVar("sm_cp_healclient", "0", "Enable/Disable healing of damage.", FCVAR_PLUGIN, true, 0.0, true, 1.0);
g_bHealClient = GetConVarBool(g_hcvarHealClient);
HookConVarChange(g_hcvarHealClient, OnSettingChanged);
if(g_bHealClient)
HookEvent("player_hurt", Event_player_hurt);
g_hcvarHintSound = CreateConVar("sm_cp_hintsound", "0", "Enable/Disable playing sound on popup.", FCVAR_PLUGIN, true, 0.0, true, 1.0);
g_bHintSound = GetConVarBool(g_hcvarHintSound);
HookConVarChange(g_hcvarHintSound, OnSettingChanged);
g_hcvarChatVisible = CreateConVar("sm_cp_chatvisible", "1", "Sets chat output visible to all or not.", FCVAR_PLUGIN, true, 0.0, true, 1.0);
g_bChatVisible = GetConVarBool(g_hcvarChatVisible);
HookConVarChange(g_hcvarChatVisible, OnSettingChanged);
g_hcvarStartSound = CreateConVar("sm_cp_startsound", "quake/play.wav", "Sets the sound that is played on starting race.", FCVAR_PLUGIN);
GetConVarString(g_hcvarStartSound, g_szStartSound, PLATFORM_MAX_PATH);
HookConVarChange(g_hcvarStartSound, OnSettingChanged);
g_hcvarFinishSound = CreateConVar("sm_cp_finishsound", "quake/perfect.mp3", "Sets the sound that is played on finishing race.", FCVAR_PLUGIN);
GetConVarString(g_hcvarFinishSound, g_szFinishSound, PLATFORM_MAX_PATH);
HookConVarChange(g_hcvarFinishSound, OnSettingChanged);
g_hcvarRecordSound = CreateConVar("sm_cp_recordsound", "quake/holyshit.mp3", "Sets the sound that is played on new record.", FCVAR_PLUGIN);
GetConVarString(g_hcvarRecordSound, g_szRecordSound, PLATFORM_MAX_PATH);
HookConVarChange(g_hcvarRecordSound, OnSettingChanged);
g_hcvarSpeedUnit = CreateConVar("sm_cp_speedunit", "0", "Changes the unit of speed displayed in timerpanel 0=default 1=kmh.", FCVAR_PLUGIN, true, 0.0, true, 1.0);
g_bSpeedUnit = GetConVarBool(g_hcvarSpeedUnit);
HookConVarChange(g_hcvarSpeedUnit, OnSettingChanged);
RegConsoleCmd("sm_block", Client_Block, "Toogles blocking");
RegConsoleCmd("sm_hide", Client_Hide, "Toogles hiding");
RegConsoleCmd("sm_lowgrav", Client_Lowgrav, "Sets player gravity to low");
RegConsoleCmd("sm_normalgrav", Client_Normalgrav, "Sets player gravity to default");
RegConsoleCmd("sm_scout", Client_Scout, "Spawns a scout");
RegConsoleCmd("sm_usp", Client_Usp, "Spawns a usp");
RegConsoleCmd("sm_next", Client_Next, "Next checkpoint");
RegConsoleCmd("sm_prev", Client_Prev, "Previous checkpoint");
RegConsoleCmd("sm_save", Client_Save, "Saves a checkpoint");
RegConsoleCmd("sm_tele", Client_Tele, "Teleports you to last checkpoint");
RegConsoleCmd("sm_cp", Client_Cp, "Opens teleportmenu");
RegConsoleCmd("sm_clear", Client_Clear, "Erases all checkpoints");
RegConsoleCmd("sm_help", Client_Help, "Displays the help menu");
RegConsoleCmd("sm_record", Client_Record, "Displays your record");
RegConsoleCmd("sm_precord", Client_Player_Record, "Displays the record of a given player");
RegConsoleCmd("sm_start", Client_Start, "Teleports you to the start");
RegConsoleCmd("sm_restart", Client_Restart, "Restarts your timer");
RegConsoleCmd("sm_r", Client_Restart, "Restarts your timer");
RegConsoleCmd("sm_stop", Client_Stop, "Stops the timer");
RegConsoleCmd("sm_wr", Client_Wr, "Displays the record on the current map");
RegAdminCmd("sm_cpadmin", Admin_CpPanel, ADMIN_LEVEL, "Displays the admin panel.");
RegAdminCmd("sm_purgeplayer", Admin_PurgePlayer, ADMIN_LEVEL, "Purges all old players.");
RegAdminCmd("sm_dropmaps", Admin_DropMap, ADMIN_LEVEL, "Drops all stored map start/end points.");
RegAdminCmd("sm_dropplayers", Admin_DropPlayer, ADMIN_LEVEL, "Drops all players.");
RegAdminCmd("sm_resetmaptimer", Admin_ResetMapTimer, ADMIN_LEVEL, "Resets timer for given map.");
RegAdminCmd("sm_resetcheckpoints", Admin_ResetCheckpoints, ADMIN_LEVEL, "Resets all checkpoints for given player with / without given map.");
RegAdminCmd("sm_resetrecords", Admin_ResetRecords, ADMIN_LEVEL, "Resets all records for given player with / without given map.");
AutoExecConfig(true, "sm_cpmod");
}
//--------------------------//
// executed on start of map //
//--------------------------//
public OnMapStart(){
//precache some files
g_BeamSpriteFollow = PrecacheModel("materials/sprites/laserbeam.vmt");
g_BeamSpriteRing1 = PrecacheModel("materials/sprites/tp_beam001.vmt");
g_BeamSpriteRing2 = PrecacheModel("materials/sprites/crystal_beam1.vmt");
PrecacheSound("buttons/blip1.wav", true);
GetCurrentMap(g_szMapName, MAX_MAP_LENGTH);
//reset player slots
for(new i = 0; i <= MAXPLAYERS; i++){
g_CurrentCp = -1;
g_WholeCp = 0;
g_Scouts = 0;
g_Usps = 0;
}
//if map timer active
if(g_bTimer){
//query the timer start stop zones
db_selectMapStartStop();
//select record depending on record type
if(g_bRecordType == RECORD_TIME)
db_selectWorldRecordTime();
else
db_selectWorldRecordJump();
//setup draw zone timer
g_hDrawZoneTimer = CreateTimer(1.0, ActionDrawZoneTimer, _, TIMER_REPEAT);
}
//if cleanup guns timer active
if(g_bCleanupGuns)
//create the cleanup timer
g_hCleanTimer = CreateTimer(10.0, ActionCleanTimer, _, TIMER_REPEAT);
//setup sounds
setupStartSound();
setupFinishSound();
setupRecordSound();
}
//------------------------//
// executed on end of map //
//------------------------//
public OnMapEnd(){
new max = GetMaxClients();
//for all of the players
for(new i = 0; i <= max; i++){
//if client valid
if(i != 0 && IsClientInGame(i) && !IsFakeClient(i) && IsClientConnected(i)){
new current = g_CurrentCp;
//if checkpoint restoring and valid checkpoint
if(g_bRestore && current != -1){
//update the checkpoint in the database
db_updatePlayerCheckpoint(i, current);
}
//if a tracer still active: close it!
if(g_bTracer && g_hTraceTimer != INVALID_HANDLE){
CloseHandle(g_hTraceTimer);
g_hTraceTimer = INVALID_HANDLE;
}
//if a timer still active: close it!
if(g_bTimer && g_hMapTimer != INVALID_HANDLE){
CloseHandle(g_hMapTimer);
g_hMapTimer = INVALID_HANDLE;
}
//cleanup visibility
if(g_bPlayerHide)
SDKUnhook(i, SDKHook_SetTransmit, SetTransmit);
}
}
//also close the cleanup timer
if(g_bCleanupGuns && g_hCleanTimer != INVALID_HANDLE){
CloseHandle(g_hCleanTimer);
g_hCleanTimer = INVALID_HANDLE;
}
//close draw zone timer
CloseHandle(g_hDrawZoneTimer);
g_hDrawZoneTimer = INVALID_HANDLE;
}
//-----------------------------------//
// hook executed on changed settings //
//-----------------------------------//
public OnSettingChanged(Handle:convar, const String:oldValue[], const String:newValue[]){
if(convar == g_hcvarEnable){
if(newValue[0] == '1')
g_bEnabled = true;
else
g_bEnabled = false;
}else if(convar == g_hcvarTimer){
if(newValue[0] == '1'){
g_bTimer = true;
}else{
g_bTimer = false;
for(new i=0; i<=MAXPLAYERS; i++){
if(g_hMapTimer != INVALID_HANDLE){
CloseHandle(g_hMapTimer);
g_hMapTimer = INVALID_HANDLE;
}
}
}
}else if(convar == g_hcvarRecordType){
g_bRecordType = newValue[0];
}else if(convar == g_hcvarRotation){
if(newValue[0] == '1')
g_bRotation = true;
else
g_bRotation = false;
}else if(convar == g_hcvarCleanupGuns){
if(newValue[0] == '1'){
g_bCleanupGuns = true;
//seems to be obsolent
//g_hCleanTimer = CreateTimer(10.0, ActionCleanTimer, _, TIMER_REPEAT);
}else{
g_bCleanupGuns = false;
CloseHandle(g_hCleanTimer);
g_hCleanTimer = INVALID_HANDLE;
}
}else if(convar == g_hcvarRestore){
if(newValue[0] == '1')
g_bRestore = true;
else
g_bRestore = false;
}else if(convar == g_hcvarNoBlock){
if(newValue[0] == '1')
g_bNoBlock = true;
else
g_bNoBlock = false;
}else if(convar == g_hcvarPlayerBlock){
if(newValue[0] == '1'){
g_bPlayerBlock = true;
for(new i=0; i<=MAXPLAYERS; i++){
SDKHook(i, SDKHook_SetTransmit, SetTransmit);
}
}else{
g_bPlayerBlock = false;
new max = GetMaxClients();
for(new i=0; i<=max; i++){
SDKUnhook(i, SDKHook_SetTransmit, SetTransmit);
}
}
}else if(convar == g_hcvarPlayerHide){
if(newValue[0] == '1')
g_bPlayerHide = true;
else
g_bPlayerHide = false;
}else if(convar == g_hcvarAlpha){
g_Alpha = StringToInt(newValue[0]);
}else if(convar == g_hcvarAutoFlash){
if(newValue[0] == '1'){
g_bAutoFlash = true;
HookEvent("player_blind" , Event_flashbang_detonate);
HookEvent("weapon_fire" , Event_weapon_fire);
}else{
g_bAutoFlash = false;
UnhookEvent("player_blind" , Event_flashbang_detonate);
UnhookEvent("weapon_fire" , Event_weapon_fire);
}
}else if(convar == g_hcvarTracer){
if(newValue[0] == '1'){
g_bTracer = true;
}else{
g_bTracer = false;
for(new i=0; i<=MAXPLAYERS; i++){
CloseHandle(g_hTraceTimer );
g_hTraceTimer = INVALID_HANDLE;
}
}
}else if(convar == g_hcvarGunLimit){
g_GunLimit = StringToInt(newValue[0]);
}else if(convar == g_hcvarGravity){
if(newValue[0] == '1')
g_bGravity = true;
else
g_bGravity = false;
}else if(convar == g_hcvarHealClient){
if(newValue[0] == '1'){
g_bHealClient = true;
HookEvent("player_hurt", Event_player_hurt);
}else{
g_bHealClient = false;
UnhookEvent("player_hurt", Event_player_hurt, EventHookMode_Post);
}
}else if(convar == g_hcvarHintSound){
if(newValue[0] == '1')
g_bHintSound = true;
else
g_bHintSound = false;
}else if(convar == g_hcvarChatVisible){
if(newValue[0] == '1')
g_bChatVisible = true;
else
g_bChatVisible = false;
}else if(convar == g_hcvarStartSound){
strcopy(g_szStartSound, PLATFORM_MAX_PATH, newValue);
setupStartSound();
}else if(convar == g_hcvarFinishSound){
strcopy(g_szFinishSound, PLATFORM_MAX_PATH, newValue);
setupFinishSound();
}else if(convar == g_hcvarRecordSound){
strcopy(g_szRecordSound, PLATFORM_MAX_PATH, newValue);
setupRecordSound();
}else if(convar == g_hcvarSpeedUnit){
if(newValue[0] == '1')
g_bSpeedUnit = true;
else
g_bSpeedUnit = false;
}
}
//------------------------------------//
// executed on client post admincheck //
//------------------------------------//
public OnClientPostAdminCheck(client){
//if g_Enabled and client valid
if(IsClientInGame(client) && !IsFakeClient(client)){
if(g_bEnabled){
//reset some settings
g_CurrentCp[client] = -1;
g_WholeCp[client] = 0;
//if checkpoint restoring select the last one
if(g_bRestore)
db_selectPlayerCheckpoint(client);
//display the help panel
HelpPanel(client);
}
g_hTraceTimer[client] = INVALID_HANDLE;
g_hMapTimer[client] = INVALID_HANDLE;
//if visibility enabled
if(g_bPlayerHide)
SDKHook(client, SDKHook_SetTransmit, SetTransmit);
//select playerdata; creates a player if none found
db_selectPlayer(client);
}
}
//-------------------------------//
// executed on player disconnect //
//-------------------------------//
public OnClientDisconnect(client){
if(g_bEnabled){
new current = g_CurrentCp[client];
//if checkpoint restoring and valid checkpoint
if(g_bRestore && current != -1){
//update the checkpoint in the database
db_updatePlayerCheckpoint(client, current);
}
}
//cleanup the timer
if(g_bTimer && g_hMapTimer[client] != INVALID_HANDLE){
CloseHandle(g_hMapTimer[client]);
g_hMapTimer[client] = INVALID_HANDLE;
}
//cleanup the tracer
if(g_bTracer && g_hTraceTimer[client] != INVALID_HANDLE){
CloseHandle(g_hTraceTimer[client]);
g_hTraceTimer[client] = INVALID_HANDLE;
}
//cleanup visibility
if(g_bPlayerHide)
SDKUnhook(client, SDKHook_SetTransmit, SetTransmit);
}