#include "weapon_hivehand"
//#include "weapon_hivehand2"
#include "weapon_barniel"
#include "monster_agruntdrone"
#include "monster_hgruntdrone"
#include "monster_zombiedrone"
#include "monster_barniel_new"
#include "weapon_hlsnark"
#include "weapon_hlhandgrenade"
#include "weapon_hlcrossbow"
#include "weapon_ofshockrifle"
#include "weapon_q2hyperblaster"
//#include "weapon_cofsyringe"
//#include "weapon_cofbooklaser"
//#include "weapon_tf2minigun"
#include "proj_hivehornet"
#include "proj_hivehornet2"
#include "proj_hivehornet3"
#include "item_armor"
#include "item_healthpack"
#include "item_ammopack"
#include "item_ammopack_large"
//#include "player_sentry"
#include "v_actions"
#include "BuyMenu"
#include "SayMenu"
#include "CAMMenu"
#include "CAFMenu"
#include "SayMenuNPC"

BuyMenu::BuyMenu g_BuyMenu;
SayMenu::SayMenu g_SayMenu;
CAMMenu::CAMMenu g_CAMMenu;
CAFMenu::CAFMenu g_CAFMenu;
SayMenu2::SayMenu2 g_SayMenu2;

array<dictionary> DICT_PLAYER_LOADOUT( g_Engine.maxClients + 1 );
bool m_bMapChanged = false;

enum respawndead_flags
{
    KEEP_WEAPONS    = 8,
    KEEP_AMMO       = 16,
    RESET_LOADOUT   = 32
};

array<string> WeaponsRespawn =
{
    'weapon_ins2beretta',
    'weapon_ins2glock17',
    'weapon_ins2usp',
    'weapon_ins2makarov',
    'weapon_ins2mp5k',
    'weapon_ins2mp40',
    'weapon_ins2ump45',
    'weapon_ins2l2a3',
    'weapon_ins2m1928',
    'weapon_ins2mp7',
    'weapon_ins2ppsh41',
    'weapon_ins2deagle',
    'weapon_ins2m29',
    'weapon_ins2python',
    'weapon_ins2webley',
    'weapon_ins2ithaca',
    'weapon_ins2m590',
    'weapon_ins2coach',
    'weapon_ins2saiga12',
    'weapon_ins2m1014',
    'weapon_ins2ithaca',
    'weapon_ins2m590',
    'weapon_ins2coach',
    'weapon_ins2saiga12',
    'weapon_ins2m1014',
    'weapon_ins2m40a1',
    'weapon_ins2mosin',
    'weapon_ins2kar98k',
    'weapon_ins2m16a4',
    'weapon_ins2ak12',
    'weapon_ins2ak74',
    'weapon_ins2akm',
    'weapon_ins2asval',
    'weapon_ins2f2000',
    'weapon_ins2galil',
    'weapon_ins2l85a2',
    'weapon_ins2stg44',
    'weapon_ins2fg42',
    'weapon_ins2fnfal',
    'weapon_ins2g3a3',
    'weapon_ins2m14ebr',
    'weapon_ins2aks74u',
    'weapon_ins2m1a1para',
    'weapon_ins2m4a1',
    'weapon_ins2mk18',
    'weapon_ins2sks',
    'weapon_ins2lewis',
    'weapon_ins2m60',
    'weapon_ins2m249',
    'weapon_ins2mg42',
    'weapon_ins2rpk',
    'weapon_ins2dragunov',
    'weapon_ins2g43',
    'weapon_ins2garand',
    'weapon_ins2m1911',
    'weapon_ins2mk2',
    'weapon_ins2stick',
    'weapon_ins2rgo',
    'weapon_ins2at4',
    'weapon_ins2law',
    'weapon_ins2pzfaust',
    'weapon_ins2pzschreck',
    'weapon_ins2rpg7',
    'weapon_ins2m79',
    'weapon_ins2scarh',
    'weapon_ins2mp5sd',
    'weapon_ins2m16a1',
    'weapon_ins2g36c',
    'weapon_ins2greasegun',
    'weapon_ins2enfield',
    'weapon_hlmp5',
    'weapon_hlmp5c',
    'weapon_ofm249',
    'weapon_hlglock',
    'weapon_ofeagle',
    'weapon_asscan',
    'weapon_hivehand',
    'weapon_aghivehand',
    'weapon_ofshockrifle',
    'weapon_ofknife',
    'weapon_npcspawner',
    'weapon_hlsnark',
    'weapon_hlhandgrenade',
    'weapon_hornetgun',
    'weapon_hgrunts',
    'weapon_hwgrunt',
    'weapon_ofgrunt',
    'weapon_fassn',
    'weapon_agrunt',
    'weapon_agruntf',
    'weapon_agruntfc',
    'weapon_kingpin',
    'weapon_pitdrone',
    'weapon_strooper',
    'weapon_gonome',
    'weapon_pipewrench',
    'weapon_medkit',
    'weapon_displacer',
    'weapon_gauss',
    'weapon_egon',
    'weapon_sporelauncher',
    'weapon_357',
    'weapon_9mmhandgun',
    'weapon_uzi',
    'weapon_uziakimbo',
    'weapon_m249',
    'weapon_wrench',
    'weapon_crossbow',
    'weapon_rpg',
    'weapon_9mmAR',
    'weapon_shotgun',
    'weapon_grapple',
    'weapon_as_jetpack',
    'weapon_as_shotgun',
    'weapon_as_soflam',
    'weapon_uzi',
    'weapon_m16',
    'weapon_sniperrifle',
    'weapon_eagle',
    'weapon_crowbar',
    "weapon_ak47",
    "weapon_awp",
    "weapon_csdeagle",
    "weapon_g3sg1",
    "weapon_hegrenade",
    "weapon_m4a1",
    "weapon_mac10",
    "weapon_p90",
    "weapon_sg552",
    "weapon_tmp",
    "weapon_ump45",
    "weapon_p228",
    "weapon_csm249",
    "weapon_mp5navy",
    "weapon_csknife",
    "weapon_usp",
    "weapon_csglock18",
    "weapon_m3",
    "weapon_xm1014",
    "weapon_sg550",
    "weapon_aug",
    "weapon_dualelites",
    "weapon_famas",
    "weapon_fiveseven",
    "weapon_galil",
    "weapon_scout",
    "weapon_c4",
    "weapon_enforcer",
    "weapon_payne",
    "weapon_garg",
    "weapon_bullsquid",
    "weapon_houndeye",
    "weapon_islave",
    "weapon_zombie",
    "weapon_babygarg",
    "weapon_bigmomma",
    "weapon_securityguard",
    "weapon_P904",
    "weapon_plasma",
    "weapon_vulcan",
    "weapon_meddart",
    "weapon_handgrenade",
    "weapon_satchel",
    "weapon_tripmine",
    "weapon_snark",
    "weapon_csocrossbow",
    "weapon_q2hyperblaster",
    "weapon_tf2minigun",
    "weapon_minigun"
};

array<string> WeaponsToSpawn =
{
    'weapon_ins2beretta',
    'weapon_ins2glock17',
    'weapon_ins2usp',
    'weapon_ins2makarov',
    'weapon_ins2mp5k',
    'weapon_ins2mp40',
    'weapon_ins2ump45',
    'weapon_ins2l2a3',
    'weapon_ins2m1928',
    'weapon_ins2mp7',
    'weapon_ins2ppsh41',
    'weapon_ins2deagle',
    'weapon_ins2m29',
    'weapon_ins2python',
    'weapon_ins2webley',
    'weapon_ins2ithaca',
    'weapon_ins2m590',
    'weapon_ins2coach',
    'weapon_ins2saiga12',
    'weapon_ins2m1014',
    'weapon_ins2ithaca',
    'weapon_ins2m590',
    'weapon_ins2coach',
    'weapon_ins2saiga12',
    'weapon_ins2m1014',
    'weapon_ins2m40a1',
    'weapon_ins2mosin',
    'weapon_ins2kar98k',
    'weapon_ins2m16a4',
    'weapon_ins2ak12',
    'weapon_ins2ak74',
    'weapon_ins2akm',
    'weapon_ins2asval',
    'weapon_ins2f2000',
    'weapon_ins2galil',
    'weapon_ins2l85a2',
    'weapon_ins2stg44',
    'weapon_ins2fg42',
    'weapon_ins2fnfal',
    'weapon_ins2g3a3',
    'weapon_ins2m14ebr',
    'weapon_ins2aks74u',
    'weapon_ins2m1a1para',
    'weapon_ins2m4a1',
    'weapon_ins2mk18',
    'weapon_ins2sks',
    'weapon_ins2lewis',
    'weapon_ins2m60',
    'weapon_ins2m249',
    'weapon_ins2mg42',
    'weapon_ins2rpk',
    'weapon_ins2dragunov',
    'weapon_ins2g43',
    'weapon_ins2garand',
    'weapon_ins2m1911',
    'weapon_ins2mk2',
    'weapon_ins2stick',
    'weapon_ins2rgo',
    'weapon_ins2at4',
    'weapon_ins2law',
    'weapon_ins2pzfaust',
    'weapon_ins2pzschreck',
    'weapon_ins2rpg7',
    'weapon_ins2m79',
    'weapon_ins2scarh',
    'weapon_ins2mp5sd',
    'weapon_ins2m16a1',
    'weapon_ins2g36c',
    'weapon_ins2greasegun',
    'weapon_hlmp5',
    'weapon_hlmp5c',
    'weapon_ofm249',
    'weapon_hlglock',
    'weapon_ofeagle',
    'weapon_asscan',
    'weapon_hivehand',
    'weapon_ofshockrifle',
    'weapon_knife',
    'weapon_npcspawner',
    'weapon_hlsnark',
    'weapon_hlhandgrenade',
    'weapon_hornetgun',
    'weapon_pipewrench',
    'weapon_medkit',
    'weapon_displacer',
    'weapon_gauss',
    'weapon_egon',
    'weapon_sporelauncher',
    'weapon_357',
    'weapon_9mmhandgun',
    'weapon_uzi',
    'weapon_m249',
    'weapon_wrench',
    'weapon_crossbow',
    'weapon_rpg',
    'weapon_grapple',
    'weapon_as_jetpack',
    'weapon_as_shotgun',
    'weapon_as_soflam',
    'weapon_uzi',
    'weapon_m16',
    'weapon_sniperrifle',
    'weapon_eagle',
    'weapon_crowbar',
    "weapon_ak47",
    "weapon_awp",
    "weapon_csdeagle",
    "weapon_g3sg1",
    "weapon_hegrenade",
    "weapon_m4a1",
    "weapon_mac10",
    "weapon_p90",
    "weapon_sg552",
    "weapon_tmp",
    "weapon_ump45",
    "weapon_p228",
    "weapon_csm249",
    "weapon_mp5navy",
    "weapon_csknife",
    "weapon_usp",
    "weapon_csglock18",
    "weapon_m3",
    "weapon_xm1014",
    "weapon_sg550",
    "weapon_aug",
    "weapon_dualelites",
    "weapon_famas",
    "weapon_fiveseven",
    "weapon_galil",
    "weapon_scout",
    "weapon_c4",
    "weapon_P904",
    "weapon_plasma",
    "weapon_vulcan"
};

void RegisterHivehand()
{
	HIVEHORNET::Register(); //start of the old register event
	//HIVEHORNETP::Register();
	HIVEHORNETF::Register();
	HIVEHORNETF2::Register();
	HIVEHAND::Register();
	//HIVEHAND2::Register();
	//AGHIVEHAND::Register();
	opfor_shockrifle::Register();
	//HLWanted_Gattlinggun::Register();
	//TF2Minigun::Register();
	//RegisterHLMP5();
	//RegisterHLMP5C();
	//RegisterHLGLOCK();
	//RegisterHLShotgun();
	//RegisterCoFSYRINGE();
	//RegisterCoFBOOKLASER();
	//RegisterOFM249();
	//RegisterOFSniper();
	//RegisterHLPYTHON();
	//CEagle::Register();
	//RegisterELITESSE();
	//RegisterKnife();
	//CS16_HEGRENADE::Register();
	ITEM_KEVLAR::Register();
	//ITEM_CASH::Register();
	//ITEM_CASH_2::Register();
	//ITEM_CASH_3::Register();
	//ITEM_CASH_4::Register();
	//ITEM_CASH_5::Register();
	//ITEM_CASH_10::Register();
	//ITEM_CASH_100::Register();
	//ITEM_CASH_LARGE::Register();
	ITEM_AMMOPACKLARGE::Register();
	ITEM_HEALTHPACK::Register();
	ITEM_HEALTHPACK2::Register();
	ITEM_HEALTHPACK3::Register();
	ITEM_HEALTHPACK4::Register();
	ITEM_HEALTHPACK5::Register();
	ITEM_HEALTHPACK_TH::Register();
	ITEM_AMMOPACKG::Register();
	ITEM_AMMOPACK2::Register();
	ITEM_AMMOPACK::Register();
	RegisterHLSnark();
	RegisterBarniel();
	RegisterAgruntDrone();
	RegisterHgruntDrone();
	RegisterZombieDrone();
	barnielCustomNew::Register();
	//RegisterHLTripmine();
	//RegisterHLRpg();
	RegisterHLHandgrenade();
	//RegisterHLSatchel();
	RegisterHLCrossbow();
	//RegisterHLCrowbar();
	RegisterCoFACTIONS();
	q2hyperblaster::Register();
	g_Hooks.RegisterHook( Hooks::Game::MapChange, @MapChanged );
	g_Hooks.RegisterHook( Hooks::Player::ClientSay, @ClientSay );
	g_Hooks.RegisterHook( Hooks::Player::PlayerSpawn, @PlayerSpawn );
	//g_Hooks.RegisterHook( Hooks::Player::PlayerPreThink, PlayerPreThink );
	g_Hooks.RegisterHook( Hooks::Player::PlayerRevived, @PlayerRevived );
	g_Hooks.RegisterHook( Hooks::Player::PlayerKilled, PlayerGotKilled );
}

HookReturnCode PlayerPreThink( CBasePlayer@ pPlayer, uint& out uiFlags )
{
	//doFallDamage( EHandle(pPlayer) );
	//PlayPlayerPainSounds( EHandle(pPlayer) );
	//q2_PlayPlayerJumpSounds( EHandle(pPlayer) );

	if ( pPlayer !is null && pPlayer.HasNamedPlayerItem("weapon_action") is null && (pPlayer.pev.flags & FL_FAKECLIENT) == 0 )
	{
		pPlayer.GiveNamedItem( "weapon_action" );
	}

	return HOOK_CONTINUE;
}

void PlayPlayerPainSounds( EHandle& in ePlayer )
{
		CBasePlayer@ pPlayer = cast<CBasePlayer@>( ePlayer.GetEntity() );
		KeyValueBuffer@ pKeys = g_EngineFuncs.GetInfoKeyBuffer(pPlayer.edict());
		
		//bool HasWeapon ( string classname )
		//{
			//return pPlayer.HasNamedPlayerItem(classname) !is null;
		//}

		CustomKeyvalues@ pCustom = pPlayer.GetCustomKeyvalues();
		float flLastHealth = pCustom.GetKeyvalue("$fl_lastHealth").GetFloat();
		float flLastPain = pCustom.GetKeyvalue("$fl_lastPain").GetFloat();

		//if( flLastHealth <= pPlayer.pev.health ) return;
		pCustom.SetKeyvalue( "$fl_lastHealth", pPlayer.pev.health );
		if( flLastPain > g_Engine.time ) return;
		if( pPlayer.pev.health <= 0 ) return;

		float flDmg = pPlayer.m_lastPlayerDamageAmount;
		if( flDmg < 5.0f || (flLastHealth - pPlayer.pev.health < 5.0f) ) return;

		/*if (pPlayer !is null && (pPlayer.pev.flags & FL_FAKECLIENT) != 0 && pPlayer.HasNamedPlayerItem("weapon_agrunt") !is null ) //&& string(pKeys.GetValue("model")) == "kgb"
		{
			int iDmgType = pPlayer.m_bitsDamageType;
			string sName;
			if((iDmgType & DMG_BURN) != 0)
			{
				if ( pPlayer.pev.health < 50 )
					sName = "kingpin/female/pain4.wav";
				else if ( pPlayer.pev.health < 125 )
					sName = "kingpin/female/pain3.wav";
				else if ( pPlayer.pev.health < 200 )
					sName = "kingpin/female/pain2.wav";
				else
					sName = "kingpin/female/pain1.wav";
			}
			else if((iDmgType & DMG_SLOWBURN) != 0)
			{
				if ( pPlayer.pev.health < 50 )
					sName = "kingpin/female/pain4.wav";
				else if ( pPlayer.pev.health < 125 )
					sName = "kingpin/female/pain3.wav";
				else if ( pPlayer.pev.health < 200 )
					sName = "kingpin/female/pain2.wav";
				else
					sName = "kingpin/female/pain1.wav";
			}
			else if((iDmgType & DMG_ACID) != 0)
			{
				if ( pPlayer.pev.health < 50 )
					sName = "kingpin/female/pain4.wav";
				else if ( pPlayer.pev.health < 125 )
					sName = "kingpin/female/pain3.wav";
				else if ( pPlayer.pev.health < 200 )
					sName = "kingpin/female/pain2.wav";
				else
					sName = "kingpin/female/pain1.wav";
			}
			else if( (iDmgType & DMG_FALL) != 0 )
			{
				if ( pPlayer.pev.health < 50 )
					sName = "kingpin/female/pain4.wav";
				else if ( pPlayer.pev.health < 125 )
					sName = "kingpin/female/pain3.wav";
				else if ( pPlayer.pev.health < 200 )
					sName = "kingpin/female/pain2.wav";
				else
					sName = "kingpin/female/pain1.wav";
			}
			else
			{
				if ( pPlayer.pev.health < 50 )
					sName = "kingpin/female/pain4.wav";
				else if ( pPlayer.pev.health < 125 )
					sName = "kingpin/female/pain3.wav";
				else if ( pPlayer.pev.health < 200 )
					sName = "kingpin/female/pain2.wav";
				else
					sName = "kingpin/female/pain1.wav";
			}

			pCustom.SetKeyvalue( "$fl_lastPain", g_Engine.time + 1.0f );
			g_SoundSystem.EmitSound( pPlayer.edict(), CHAN_VOICE, sName, 1, 0.3 );
		}*/
		if (pPlayer !is null && (pPlayer.pev.flags & FL_FAKECLIENT) != 0 && pPlayer.HasNamedPlayerItem("weapon_enforcer") !is null)
		{
			int iDmgType = pPlayer.m_bitsDamageType;
			string sName;
			if((iDmgType & DMG_BURN) != 0)
			{
				if ( pPlayer.pev.health < 50 )
					sName = "kingpin/male/pain25_" + string( Math.RandomLong(1, 2) ) + ".wav";
				else if ( pPlayer.pev.health < 125 )
					sName = "kingpin/male/pain50_" + string( Math.RandomLong(1, 2) ) + ".wav";
				else if ( pPlayer.pev.health < 200 )
					sName = "kingpin/male/pain75_" + string( Math.RandomLong(1, 2) ) + ".wav";
				else
					sName = "kingpin/male/pain100_" + string( Math.RandomLong(1, 2) ) + ".wav";
			}
			else if((iDmgType & DMG_SLOWBURN) != 0)
			{
				if ( pPlayer.pev.health < 50 )
					sName = "kingpin/male/pain25_" + string( Math.RandomLong(1, 2) ) + ".wav";
				else if ( pPlayer.pev.health < 125 )
					sName = "kingpin/male/pain50_" + string( Math.RandomLong(1, 2) ) + ".wav";
				else if ( pPlayer.pev.health < 200 )
					sName = "kingpin/male/pain75_" + string( Math.RandomLong(1, 2) ) + ".wav";
				else
					sName = "kingpin/male/pain100_" + string( Math.RandomLong(1, 2) ) + ".wav";
			}
			else if((iDmgType & DMG_ACID) != 0)
			{
				if ( pPlayer.pev.health < 50 )
					sName = "kingpin/male/pain25_" + string( Math.RandomLong(1, 2) ) + ".wav";
				else if ( pPlayer.pev.health < 125 )
					sName = "kingpin/male/pain50_" + string( Math.RandomLong(1, 2) ) + ".wav";
				else if ( pPlayer.pev.health < 200 )
					sName = "kingpin/male/pain75_" + string( Math.RandomLong(1, 2) ) + ".wav";
				else
					sName = "kingpin/male/pain100_" + string( Math.RandomLong(1, 2) ) + ".wav";
			}
			else if((iDmgType & DMG_FALL) != 0)
			{
				if ( pPlayer.pev.health < 50 )
					sName = "kingpin/male/pain25_" + string( Math.RandomLong(1, 2) ) + ".wav";
				else if ( pPlayer.pev.health < 125 )
					sName = "kingpin/male/pain50_" + string( Math.RandomLong(1, 2) ) + ".wav";
				else if ( pPlayer.pev.health < 200 )
					sName = "kingpin/male/pain75_" + string( Math.RandomLong(1, 2) ) + ".wav";
				else
					sName = "kingpin/male/pain100_" + string( Math.RandomLong(1, 2) ) + ".wav";
			}
			else
			{
				if ( pPlayer.pev.health < 50 )
					sName = "kingpin/male/pain25_" + string( Math.RandomLong(1, 2) ) + ".wav";
				else if ( pPlayer.pev.health < 125 )
					sName = "kingpin/male/pain50_" + string( Math.RandomLong(1, 2) ) + ".wav";
				else if ( pPlayer.pev.health < 200 )
					sName = "kingpin/male/pain75_" + string( Math.RandomLong(1, 2) ) + ".wav";
				else
					sName = "kingpin/male/pain100_" + string( Math.RandomLong(1, 2) ) + ".wav";
			}

			pCustom.SetKeyvalue( "$fl_lastPain", g_Engine.time + 1.0f );
			g_SoundSystem.EmitSound( pPlayer.edict(), CHAN_VOICE, sName, 1, 0.3 );
		}
		else if (pPlayer !is null && (pPlayer.pev.flags & FL_FAKECLIENT) != 0 && pPlayer.HasNamedPlayerItem("weapon_payne") !is null)
		{
			int iDmgType = pPlayer.m_bitsDamageType;
			string sName;
			if((iDmgType & DMG_BURN) != 0)
			{
				if ( pPlayer.pev.health < 50 )
					sName = "kingpin/male/pain25_" + string( Math.RandomLong(1, 2) ) + ".wav";
				else if ( pPlayer.pev.health < 125 )
					sName = "kingpin/male/pain50_" + string( Math.RandomLong(1, 2) ) + ".wav";
				else if ( pPlayer.pev.health < 200 )
					sName = "kingpin/male/pain75_" + string( Math.RandomLong(1, 2) ) + ".wav";
				else
					sName = "kingpin/male/pain100_" + string( Math.RandomLong(1, 2) ) + ".wav";
			}
			else if((iDmgType & DMG_SLOWBURN) != 0)
			{
				if ( pPlayer.pev.health < 50 )
					sName = "kingpin/male/pain25_" + string( Math.RandomLong(1, 2) ) + ".wav";
				else if ( pPlayer.pev.health < 125 )
					sName = "kingpin/male/pain50_" + string( Math.RandomLong(1, 2) ) + ".wav";
				else if ( pPlayer.pev.health < 200 )
					sName = "kingpin/male/pain75_" + string( Math.RandomLong(1, 2) ) + ".wav";
				else
					sName = "kingpin/male/pain100_" + string( Math.RandomLong(1, 2) ) + ".wav";
			}
			else if((iDmgType & DMG_ACID) != 0)
			{
				if ( pPlayer.pev.health < 50 )
					sName = "kingpin/male/pain25_" + string( Math.RandomLong(1, 2) ) + ".wav";
				else if ( pPlayer.pev.health < 125 )
					sName = "kingpin/male/pain50_" + string( Math.RandomLong(1, 2) ) + ".wav";
				else if ( pPlayer.pev.health < 200 )
					sName = "kingpin/male/pain75_" + string( Math.RandomLong(1, 2) ) + ".wav";
				else
					sName = "kingpin/male/pain100_" + string( Math.RandomLong(1, 2) ) + ".wav";
			}
			else if((iDmgType & DMG_FALL) != 0)
			{
				if ( pPlayer.pev.health < 50 )
					sName = "kingpin/male/pain25_" + string( Math.RandomLong(1, 2) ) + ".wav";
				else if ( pPlayer.pev.health < 125 )
					sName = "kingpin/male/pain50_" + string( Math.RandomLong(1, 2) ) + ".wav";
				else if ( pPlayer.pev.health < 200 )
					sName = "kingpin/male/pain75_" + string( Math.RandomLong(1, 2) ) + ".wav";
				else
					sName = "kingpin/male/pain100_" + string( Math.RandomLong(1, 2) ) + ".wav";
			}
			else
			{
				if ( pPlayer.pev.health < 50 )
					sName = "kingpin/male/pain25_" + string( Math.RandomLong(1, 2) ) + ".wav";
				else if ( pPlayer.pev.health < 125 )
					sName = "kingpin/male/pain50_" + string( Math.RandomLong(1, 2) ) + ".wav";
				else if ( pPlayer.pev.health < 200 )
					sName = "kingpin/male/pain75_" + string( Math.RandomLong(1, 2) ) + ".wav";
				else
					sName = "kingpin/male/pain100_" + string( Math.RandomLong(1, 2) ) + ".wav";
			}

			pCustom.SetKeyvalue( "$fl_lastPain", g_Engine.time + 1.0f );
			g_SoundSystem.EmitSound( pPlayer.edict(), CHAN_VOICE, sName, 1, 0.3 );
		}
		else if (pPlayer !is null && string(pKeys.GetValue("model")) == "STALKER_Bandit1" && (pPlayer.pev.effects & EF_NODRAW) != EF_NODRAW )
		{
			int iDmgType = pPlayer.m_bitsDamageType;
			string sName;
			if((iDmgType & DMG_SLOWBURN) == 0)
			{
				if ( pPlayer.pev.health < 25 )
					sName = "kingpin/male/pain25_" + string( Math.RandomLong(1, 2) ) + ".ogg";
				else if ( pPlayer.pev.health < 50 )
					sName = "kingpin/male/pain50_" + string( Math.RandomLong(1, 2) ) + ".ogg";
				else if ( pPlayer.pev.health < 75 )
					sName = "kingpin/male/pain75_" + string( Math.RandomLong(1, 2) ) + ".ogg";
				else
					sName = "kingpin/male/pain100_" + string( Math.RandomLong(1, 2) ) + ".ogg";
			}
			else
			{
				if ( pPlayer.pev.health < 25 || pPlayer.pev.health < 25 && pPlayer.pev.armorvalue > 0 )
					sName = "kingpin/male/pain25_" + string( Math.RandomLong(1, 2) ) + ".ogg";
				else if ( pPlayer.pev.health < 50 || pPlayer.pev.health < 50 && pPlayer.pev.armorvalue > 0 )
					sName = "kingpin/male/pain50_" + string( Math.RandomLong(1, 2) ) + ".ogg";
				else if ( pPlayer.pev.health < 75 || pPlayer.pev.health < 75 && pPlayer.pev.armorvalue > 0 )
					sName = "kingpin/male/pain75_" + string( Math.RandomLong(1, 2) ) + ".ogg";
				else if ( pPlayer.pev.health < 100 || pPlayer.pev.health < 100 && pPlayer.pev.armorvalue > 0 )
					sName = "kingpin/male/pain100_" + string( Math.RandomLong(1, 2) ) + ".ogg";
			}

			pCustom.SetKeyvalue( "$fl_lastPain", g_Engine.time + 1.0f );
			g_SoundSystem.EmitSound( pPlayer.edict(), CHAN_VOICE, sName, 1, 0.3 );
		}
		else if (pPlayer !is null && string(pKeys.GetValue("model")) == "STALKER_Bandit2" && (pPlayer.pev.effects & EF_NODRAW) != EF_NODRAW )
		{
			int iDmgType = pPlayer.m_bitsDamageType;
			string sName;
			if((iDmgType & DMG_SLOWBURN) == 0)
			{
				if ( pPlayer.pev.health < 25 )
					sName = "kingpin/male/pain25_" + string( Math.RandomLong(1, 2) ) + ".ogg";
				else if ( pPlayer.pev.health < 50 )
					sName = "kingpin/male/pain50_" + string( Math.RandomLong(1, 2) ) + ".ogg";
				else if ( pPlayer.pev.health < 75 )
					sName = "kingpin/male/pain75_" + string( Math.RandomLong(1, 2) ) + ".ogg";
				else
					sName = "kingpin/male/pain100_" + string( Math.RandomLong(1, 2) ) + ".ogg";
			}
			else
			{
				if ( pPlayer.pev.health < 25 )
					sName = "kingpin/male/pain25_" + string( Math.RandomLong(1, 2) ) + ".ogg";
				else if ( pPlayer.pev.health < 50 )
					sName = "kingpin/male/pain50_" + string( Math.RandomLong(1, 2) ) + ".ogg";
				else if ( pPlayer.pev.health < 75 )
					sName = "kingpin/male/pain75_" + string( Math.RandomLong(1, 2) ) + ".ogg";
				else
					sName = "kingpin/male/pain100_" + string( Math.RandomLong(1, 2) ) + ".ogg";
			}

			pCustom.SetKeyvalue( "$fl_lastPain", g_Engine.time + 1.0f );
			g_SoundSystem.EmitSound( pPlayer.edict(), CHAN_VOICE, sName, 1, 0.3 );
		}
		else if (pPlayer !is null && string(pKeys.GetValue("model")) == "ts_merc" && (pPlayer.pev.effects & EF_NODRAW) != EF_NODRAW )
		{
			int iDmgType = pPlayer.m_bitsDamageType;
			string sName;
			if((iDmgType & DMG_SLOWBURN) == 0)
			{
				if ( pPlayer.pev.health < 25 || pPlayer.pev.health < 25 && pPlayer.pev.armorvalue > 0 )
					sName = "kingpin/male/pain25_" + string( Math.RandomLong(1, 2) ) + ".ogg";
				else if ( pPlayer.pev.health < 50 || pPlayer.pev.health < 50 && pPlayer.pev.armorvalue > 0 )
					sName = "kingpin/male/pain50_" + string( Math.RandomLong(1, 2) ) + ".ogg";
				else if ( pPlayer.pev.health < 75 || pPlayer.pev.health < 75 && pPlayer.pev.armorvalue > 0 )
					sName = "kingpin/male/pain75_" + string( Math.RandomLong(1, 2) ) + ".ogg";
				else if ( pPlayer.pev.health < 999 || pPlayer.pev.health < 999 && pPlayer.pev.armorvalue > 0 )
					sName = "kingpin/male/pain100_" + string( Math.RandomLong(1, 2) ) + ".ogg";
			}
			else
			{
				if ( pPlayer.pev.health < 25 || pPlayer.pev.health < 25 && pPlayer.pev.armorvalue > 0 )
					sName = "kingpin/male/pain25_" + string( Math.RandomLong(1, 2) ) + ".ogg";
				else if ( pPlayer.pev.health < 50 || pPlayer.pev.health < 50 && pPlayer.pev.armorvalue > 0 )
					sName = "kingpin/male/pain50_" + string( Math.RandomLong(1, 2) ) + ".ogg";
				else if ( pPlayer.pev.health < 75 || pPlayer.pev.health < 75 && pPlayer.pev.armorvalue > 0 )
					sName = "kingpin/male/pain75_" + string( Math.RandomLong(1, 2) ) + ".ogg";
				else if ( pPlayer.pev.health < 999 || pPlayer.pev.health < 999 && pPlayer.pev.armorvalue > 0 )
					sName = "kingpin/male/pain100_" + string( Math.RandomLong(1, 2) ) + ".ogg";
			}

			pCustom.SetKeyvalue( "$fl_lastPain", g_Engine.time + 1.0f );
			g_SoundSystem.EmitSound( pPlayer.edict(), CHAN_VOICE, sName, 1, 0.3 );
		}
		else if (pPlayer !is null && string(pKeys.GetValue("model")) == "ts_seal" && (pPlayer.pev.effects & EF_NODRAW) != EF_NODRAW )
		{
			int iDmgType = pPlayer.m_bitsDamageType;
			string sName;
			if((iDmgType & DMG_SLOWBURN) == 0)
			{
				if ( pPlayer.pev.health < 25 )
					sName = "kingpin/male/pain25_" + string( Math.RandomLong(1, 2) ) + ".ogg";
				else if ( pPlayer.pev.health < 50 )
					sName = "kingpin/male/pain50_" + string( Math.RandomLong(1, 2) ) + ".ogg";
				else if ( pPlayer.pev.health < 75 )
					sName = "kingpin/male/pain75_" + string( Math.RandomLong(1, 2) ) + ".ogg";
				else
					sName = "kingpin/male/pain100_" + string( Math.RandomLong(1, 2) ) + ".ogg";
			}
			else
			{
				if ( pPlayer.pev.health < 25 )
					sName = "kingpin/male/pain25_" + string( Math.RandomLong(1, 2) ) + ".ogg";
				else if ( pPlayer.pev.health < 50 )
					sName = "kingpin/male/pain50_" + string( Math.RandomLong(1, 2) ) + ".ogg";
				else if ( pPlayer.pev.health < 75 )
					sName = "kingpin/male/pain75_" + string( Math.RandomLong(1, 2) ) + ".ogg";
				else
					sName = "kingpin/male/pain100_" + string( Math.RandomLong(1, 2) ) + ".ogg";
			}

			pCustom.SetKeyvalue( "$fl_lastPain", g_Engine.time + 1.0f );
			g_SoundSystem.EmitSound( pPlayer.edict(), CHAN_VOICE, sName, 1, 0.3 );
		}
		else
		{
			//nada
		}
}

array<int> g_tracerCount(33);

mixin class WeaponUtils
{
	float WeaponTimeBase()
	{
		return g_Engine.time;
	}

	void GetDefaultShellInfo(Vector& out vecShellVelocity, Vector& out vecShellOrigin, float forwardScale, float upScale, float rightScale)
	{
		Vector forward, right, up;
		g_EngineFuncs.AngleVectors(m_pPlayer.pev.angles, forward, right, up);

		const float fR = Math.RandomFloat(50.0, 70.0);
		const float fU = Math.RandomFloat(100.0, 150.0);

		for (int i = 0; i < 3; i++)
		{
			vecShellVelocity[i] = m_pPlayer.pev.velocity[i] + right[i] * fR + up[i] * fU + forward[i] * 25.0;
			vecShellOrigin[i] = m_pPlayer.pev.origin[i] + m_pPlayer.pev.view_ofs[i] + up[i] * upScale + forward[i] * forwardScale + right[i] * rightScale;
		}
	}

	// Lost the addition of DMG_ALWAYSGIB to DMG_BULLET if iDamage > 16 and some cases for iBulletType
	void FireBulletsPlayer(uint cShots, Vector vecSrc, Vector vecDirShooting, Vector vecSpread, float flDistance, int iBulletType, int iTracerFreq)
	{
		TraceResult tr;
		float x, y;

		g_WeaponFuncs.ClearMultiDamage();

		for (uint iShot = 1; iShot <= cShots; iShot++)
		{
			// Use player's random seed.
			// get circular gaussian spread
			x = g_PlayerFuncs.SharedRandomFloat(m_pPlayer.random_seed + iShot, -0.5, 0.5) + g_PlayerFuncs.SharedRandomFloat(m_pPlayer.random_seed + (1 + iShot), -0.5, 0.5);
			y = g_PlayerFuncs.SharedRandomFloat(m_pPlayer.random_seed + (2 + iShot), -0.5, 0.5) + g_PlayerFuncs.SharedRandomFloat(m_pPlayer.random_seed + (3 + iShot), -0.5, 0.5);
			// There's a notable diference with g_Utility.GetCircularGaussianSpread(x, y)?

			Vector vecDir = vecDirShooting + x * vecSpread.x * g_Engine.v_right + y * vecSpread.y * g_Engine.v_up;
			Vector vecEnd = vecSrc + vecDir * flDistance;

			g_Utility.TraceLine(vecSrc, vecEnd, dont_ignore_monsters, m_pPlayer.edict(), tr);

			if (iTracerFreq != 0 && (g_tracerCount[m_pPlayer.entindex()]++ % iTracerFreq) == 0)
			{
				// YOINKED from:
				// https://github.com/KernCore91/-SC-Insurgency-Weapons-Project/blob/master/scripts/maps/ins2/base.as#L691-L692
				Vector vecAttachOrigin, vecAttachAngles;
				g_EngineFuncs.GetAttachment(m_pPlayer.edict(), 0, vecAttachOrigin, vecAttachAngles);

				//Vector vecTracerSrc = vecAttachOrigin + g_Engine.v_forward * 64.0;
				Vector vecTracerSrc = vecSrc + g_Engine.v_right * 4 + g_Engine.v_up * -6;

				NetworkMessage message(MSG_PAS, NetworkMessages::SVC_TEMPENTITY, vecTracerSrc);
					message.WriteByte(TE_TRACER);
					message.WriteCoord(vecTracerSrc.x);
					message.WriteCoord(vecTracerSrc.y);
					message.WriteCoord(vecTracerSrc.z);
					message.WriteCoord(tr.vecEndPos.x);
					message.WriteCoord(tr.vecEndPos.y);
					message.WriteCoord(tr.vecEndPos.z);
						message.End();
			}

			// do damage, paint decals
			if (tr.flFraction < 1.0)
			{
				if (tr.pHit !is null)
				{
					CBaseEntity@ pHit = g_EntityFuncs.Instance(tr.pHit);

					if (pHit !is null)
					{
						switch (iBulletType)
						{
							case BULLET_PLAYER_357:
							pHit.TraceAttack(m_pPlayer.pev, g_EngineFuncs.CVarGetFloat('sk_plr_357_bullet'), vecEnd, tr, DMG_BULLET | DMG_NEVERGIB);
							break;

							case BULLET_PLAYER_EAGLE:
							// SC:66% of the magnum, OF:85% of the magnum; based on skillopfor.cfg
							pHit.TraceAttack(m_pPlayer.pev, g_EngineFuncs.CVarGetFloat('sk_plr_357_bullet') * 0.85, vecEnd, tr, DMG_BULLET | DMG_NEVERGIB);
							break;

							case BULLET_PLAYER_SAW:
							pHit.TraceAttack(m_pPlayer.pev, g_EngineFuncs.CVarGetFloat('sk_556_bullet'), vecEnd, tr, DMG_BULLET | DMG_NEVERGIB);
							break;

							case BULLET_PLAYER_SNIPER:
							pHit.TraceAttack(m_pPlayer.pev, g_EngineFuncs.CVarGetFloat('sk_plr_762_bullet'), vecEnd, tr, DMG_BULLET | DMG_NEVERGIB);
							break;

							/*case BULLET_PLAYER_MP5:
							pHit.TraceAttack(m_pPlayer.pev, g_EngineFuncs.CVarGetFloat('sk_plr_9mmAR_bullet'), vecEnd, tr, DMG_BLAST | DMG_NEVERGIB );
							break;*/
						}
					}

					g_SoundSystem.PlayHitSound(tr, vecSrc, vecEnd, iBulletType);

					if (pHit is null || pHit.IsBSPModel())
					g_WeaponFuncs.DecalGunshot(tr, iBulletType);
				}
			}
			// make bullet trails
			g_Utility.BubbleTrail(vecSrc, tr.vecEndPos, int((flDistance * tr.flFraction) / 64.0));
		}
			g_WeaponFuncs.ApplyMultiDamage(m_pPlayer.pev, m_pPlayer.pev);
	}
}

class CBaseCustomWeapon : ScriptBasePlayerWeaponEntity
{
	// Possible workaround for the SendWeaponAnim() access violation crash.
	// According to R4to0 this seems to provide at least some improvement.
	// GeckoN: TODO: Remove this once the core issue is addressed.
	protected CBasePlayer@ m_pPlayer
	{
		get const { return cast<CBasePlayer@>( self.m_hPlayer.GetEntity() ); }
		set { self.m_hPlayer = EHandle( @value ); }
	}

	protected bool m_fDropped;
	CBasePlayerItem@ DropItem()
	{
		m_fDropped = true;
		return self;
	}

	void GetDefaultShellInfo( CBasePlayer@ pPlayer, Vector& out ShellVelocity,
		Vector& out ShellOrigin, float forwardScale, float rightScale, float upScale )
	{
		Vector vecForward, vecRight, vecUp;

		g_EngineFuncs.AngleVectors( pPlayer.pev.v_angle, vecForward, vecRight, vecUp );

		const float fR = Math.RandomFloat( 50, 70 );
		const float fU = Math.RandomFloat( 100, 150 );

		for( int i = 0; i < 3; ++i )
		{
			ShellVelocity[i] = pPlayer.pev.velocity[i] + vecRight[i] * fR + vecUp[i] * fU + vecForward[i] * 25;
			ShellOrigin[i]   = pPlayer.pev.origin[i] + pPlayer.pev.view_ofs[i] + vecUp[i] * upScale + vecForward[i] * forwardScale + vecRight[i] * rightScale;
		}
	}
}

class CBaseCustomAmmo : ScriptBasePlayerAmmoEntity
{
	protected string m_strModel = "models/error.mdl";
	protected string m_strName;
	protected int m_iAmount = 0;
	protected int m_iMax = 0;

	protected string m_strPickupSound = "items/gunpickup2.wav";

	void Precache()
	{
		g_Game.PrecacheModel( m_strModel );

		g_SoundSystem.PrecacheSound( m_strPickupSound );
	}

	void Spawn()
	{
		Precache();
		g_EntityFuncs.SetModel( self, m_strModel );
		BaseClass.Spawn();
	}

	bool AddAmmo( CBaseEntity@ pOther )
	{
		if ( pOther.GiveAmmo( m_iAmount, m_strName, m_iMax, false ) == -1 )
			return false;

		g_SoundSystem.EmitSound( self.edict(), CHAN_ITEM, m_strPickupSound, 1, ATTN_NORM );

		return true;
	}
}

class CBaseCustomMonster : ScriptBaseMonsterEntity
{
	int SF_MONSTER_GAG = 2;
	int SF_MONSTER_FADECORPSE = 512;

	Vector VecCheckToss( edict_t@& in pEdict, const Vector& in vecSpot1, Vector vecSpot2, const float flGravityAdj = 1.0 )
	{
		TraceResult	tr;
		Vector		vecMidPoint;// halfway point between Spot1 and Spot2
		Vector		vecApex;// highest point 
		Vector		vecScale;
		Vector		vecGrenadeVel;
		Vector		vecTemp;
		//float flGravity = g_EngineFuncs.CVarGetFloat( "sv_gravity" ) * flGravityAdj;
		float flGravity = 800.0f * flGravityAdj;

		if( vecSpot2.z - vecSpot1.z > 500 )
			return g_vecZero; // to high, fail

		g_EngineFuncs.MakeVectors(pev.angles);

		// toss a little bit to the left or right, not right down on the enemy's bean (head). 
		vecSpot2 = vecSpot2 + g_Engine.v_right * ( Math.RandomFloat(-8,8) + Math.RandomFloat(-16,16) );
		vecSpot2 = vecSpot2 + g_Engine.v_forward * ( Math.RandomFloat(-8,8) + Math.RandomFloat(-16,16) );

		// calculate the midpoint and apex of the 'triangle'
		// UNDONE: normalize any Z position differences between spot1 and spot2 so that triangle is always RIGHT

		// How much time does it take to get there?

		// get a rough idea of how high it can be thrown
		vecMidPoint = vecSpot1 + (vecSpot2 - vecSpot1) * 0.5;
		g_Utility.TraceLine(vecMidPoint, vecMidPoint + Vector(0,0,500), ignore_monsters, self.edict(), tr);
		vecMidPoint = tr.vecEndPos;
		// (subtract 15 so the grenade doesn't hit the ceiling)
		vecMidPoint.z -= 15;

		if( vecMidPoint.z < vecSpot1.z || vecMidPoint.z < vecSpot2.z )
			return g_vecZero; // to not enough space, fail

		// How high should the grenade travel to reach the apex
		float distance1 = (vecMidPoint.z - vecSpot1.z);
		float distance2 = (vecMidPoint.z - vecSpot2.z);

		// How long will it take for the grenade to travel this distance
		float time1 = sqrt( distance1 / (0.5 * flGravity) );
		float time2 = sqrt( distance2 / (0.5 * flGravity) );

		if( time1 < 0.1 )
			return g_vecZero; // too close

		// how hard to throw sideways to get there in time.
		vecGrenadeVel = (vecSpot2 - vecSpot1) / (time1 + time2);
		// how hard upwards to reach the apex at the right time.
		vecGrenadeVel.z = flGravity * time1;

		// find the apex
		vecApex  = vecSpot1 + vecGrenadeVel * time1;
		vecApex.z = vecMidPoint.z;

		g_Utility.TraceLine(vecSpot1, vecApex, dont_ignore_monsters, self.edict(), tr);
		if (tr.flFraction != 1.0)
			return g_vecZero; // fail!

		// UNDONE: either ignore monsters or change it to not care if we hit our enemy
		g_Utility.TraceLine(vecSpot2, vecApex, ignore_monsters, self.edict(), tr); 
		if (tr.flFraction != 1.0)
			return g_vecZero; // fail!

		return vecGrenadeVel;
	}

	Vector VecCheckThrow( edict_t@& in pEdict, const Vector& in vecSpot1, Vector vecSpot2, const float flSpeed, const float flGravityAdj = 1.0 )
	{
		//float flGravity = g_EngineFuncs.CVarGetFloat( "sv_gravity" ) * flGravityAdj;
		float flGravity = 800.0f * flGravityAdj;

		Vector vecGrenadeVel = (vecSpot2 - vecSpot1);

		// throw at a constant time
		float time = vecGrenadeVel.Length( ) / flSpeed;
		vecGrenadeVel = vecGrenadeVel * (1.0 / time);

		// adjust upward toss to compensate for gravity loss
		vecGrenadeVel.z += flGravity * time * 0.5;

		Vector vecApex = vecSpot1 + (vecSpot2 - vecSpot1) * 0.5;
		vecApex.z += 0.5 * flGravity * (time * 0.5) * (time * 0.5);

		TraceResult tr;
		g_Utility.TraceLine(vecSpot1, vecApex, dont_ignore_monsters, pEdict, tr);
		if (tr.flFraction != 1.0)
				return g_vecZero; // fail!

		g_Utility.TraceLine(vecSpot2, vecApex, ignore_monsters, pEdict, tr);
		if (tr.flFraction != 1.0)
				return g_vecZero; // fail!

		return vecGrenadeVel;
	}
}

//bool HasWeapon ( string classname )
//{
	//return m_pPlayer.HasNamedPlayerItem(classname) !is null;
//}

void CS16GetDefaultShellInfo( CBasePlayer@ pPlayer, Vector& out ShellVelocity, Vector& out ShellOrigin, float forwardScale, float rightScale, float upScale, bool leftShell, bool downShell )
{  
	Vector vecForward, vecRight, vecUp;

	float fR;
	float fU;
	
	g_EngineFuncs.AngleVectors( pPlayer.pev.v_angle, vecForward, vecRight, vecUp );
	
	( leftShell == true ) ? fR = Math.RandomFloat( -70, -50 ) : fR = Math.RandomFloat( 50, 70 );
	( downShell == true ) ? fU = Math.RandomFloat( -150, -100 ) : fU = Math.RandomFloat( 100, 150 );
 
	for( int i = 0; i < 3; ++i )
	{
		ShellVelocity[i] = pPlayer.pev.velocity[i] + vecRight[i] * fR + vecUp[i] * fU + vecForward[i] * 25;
		ShellOrigin[i]   = pPlayer.pev.origin[i] + pPlayer.pev.view_ofs[i] + vecUp[i] * upScale + vecForward[i] * forwardScale + vecRight[i] * rightScale;
	}
}

// Dynamic light effects
void DynamicLight( Vector& in vecPos, int& in radius, Vector& in RGB, int8& in life, int& in decay ) 
{
	NetworkMessage DLight( MSG_BROADCAST, NetworkMessages::SVC_TEMPENTITY );
		DLight.WriteByte( TE_DLIGHT );
		DLight.WriteCoord( vecPos.x );
		DLight.WriteCoord( vecPos.y );
		DLight.WriteCoord( vecPos.z );
		DLight.WriteByte( radius );
		DLight.WriteByte( int(RGB.x) );
		DLight.WriteByte( int(RGB.y) );
		DLight.WriteByte( int(RGB.z) );
		DLight.WriteByte( life );
		DLight.WriteByte( decay );
	DLight.End();
}

void DynamicTracer( Vector start, Vector end ) // create tracer message
{
	NetworkMessage DTracer( MSG_PVS, NetworkMessages::SVC_TEMPENTITY, null );
		DTracer.WriteByte( TE_TRACER );
		DTracer.WriteCoord( start.x );
		DTracer.WriteCoord( start.y );
		DTracer.WriteCoord( start.z );
		DTracer.WriteCoord( end.x );
		DTracer.WriteCoord( end.y );
		DTracer.WriteCoord( end.z );
	DTracer.End();
}

void PlayTracer( Vector& in vecAttachOrigin, Vector& in vecAttachAngles, TraceResult& in tr ) // play tracer message
{
	//g_EngineFuncs.GetAttachment( pPlayer.edict(), 0, vecAttachOrigin, vecAttachAngles );
	DynamicTracer( vecAttachOrigin, tr.vecEndPos ); //+ g_Engine.v_forward * 64, tr.vecEndPos );
}

void WW2DynamicTracer( Vector start, Vector end, NetworkMessageDest msgType = MSG_PVS, edict_t@ dest = null )
{
	NetworkMessage WW2DT( msgType, NetworkMessages::SVC_TEMPENTITY, dest );
		WW2DT.WriteByte( TE_TRACER );
		WW2DT.WriteCoord( start.x );
		WW2DT.WriteCoord( start.y );
		WW2DT.WriteCoord( start.z );
		WW2DT.WriteCoord( end.x );
		WW2DT.WriteCoord( end.y );
		WW2DT.WriteCoord( end.z );
	WW2DT.End();
}

void WW2DynamicLight( Vector vecPos, int radius, int r, int g, int b, int8 life, int decay )
{
	NetworkMessage WW2DL( MSG_PVS, NetworkMessages::SVC_TEMPENTITY );
		WW2DL.WriteByte( TE_DLIGHT );
		WW2DL.WriteCoord( vecPos.x );
		WW2DL.WriteCoord( vecPos.y );
		WW2DL.WriteCoord( vecPos.z );
		WW2DL.WriteByte( radius );
		WW2DL.WriteByte( int(r) );
		WW2DL.WriteByte( int(g) );
		WW2DL.WriteByte( int(b) );
		WW2DL.WriteByte( life );
		WW2DL.WriteByte( decay );
	WW2DL.End();
}

void AlertMonsters(CBaseEntity@ pWho, Vector vecWhere, float flRadius) 
{
	array <CBaseEntity@> aEnts(32);
	int iNum = g_EntityFuncs.MonstersInSphere(aEnts, vecWhere, flRadius);
	for (int i = 0; i < iNum; ++i) 
	{
		CBaseEntity@ pEnt = aEnts[i];
		if (pEnt.pev.health > 0 && pEnt !is pWho && pEnt.IsMonster() && pEnt.pev.classname != "monster_barnield" && pEnt.pev.classname != "monster_hgruntdrone" && pEnt.pev.classname != "monster_hgruntdroneelite" 
		&& pEnt.pev.classname != "monster_agruntdrone"
		&& pEnt.pev.classname != "monster_hgruntdroneelite2") 
		{
			if (pEnt.FVisible(vecWhere))
			pEnt.Use(pWho, pWho, USE_TOGGLE);
		}
	}
}

HookReturnCode ClientSay( SayParameters@ pParams )
{
	CBasePlayer@ pPlayer = pParams.GetPlayer();
	const CCommand@ args = pParams.GetArguments();
	KeyValueBuffer@ pKeys = g_EngineFuncs.GetInfoKeyBuffer(pPlayer.edict()); // You have to get pPlayer from somewhere first.
	bool isAdmin = g_PlayerFuncs.AdminLevel(pPlayer) >= ADMIN_YES;
	Vector vecSrc = pPlayer.pev.origin; //pPlayer.GetGunPosition();
	g_EngineFuncs.MakeVectors( pPlayer.pev.v_angle );
	//Vector spawnForward, spawnRight, spawnUp;
	//g_EngineFuncs.AngleVectors(pPlayer.pev.v_angle, spawnForward, spawnRight, spawnUp);
	//vecSrc = vecSrc + (spawnForward * 64);
	vecSrc.z -= 36;
	string szClassname;
	dictionary keys;
	CBaseEntity@ pNPC;

	if( args.ArgC() == 1 && args.Arg(0) == "/CAM" || args.Arg(0).ToLowercase() == "/cam" )
	{
		if ( !pPlayer.IsAlive() && !isAdmin )
		{
			pParams.ShouldHide = true;
			g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTTALK, "[CAM] You must be alive\n" );
			return HOOK_CONTINUE;
		}

        	pParams.ShouldHide = true;
		g_CAMMenu.Show( pPlayer );
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/CAF" || args.Arg(0).ToLowercase() == "/caf" )
	{
		if ( !pPlayer.IsAlive() && !isAdmin )
		{
			pParams.ShouldHide = true;
			g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTTALK, "[CAF] You must be alive\n" );
			return HOOK_CONTINUE;
		}

        	pParams.ShouldHide = true;
		g_CAFMenu.Show( pPlayer );
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/responses" || args.ArgC() == 1 && args.Arg(0) == "/kpv" )
	{
		if ( !pPlayer.IsAlive() && !isAdmin )
		{
			pParams.ShouldHide = true;
			g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTTALK, "[Responses] You must be alive\n" );
			return HOOK_CONTINUE;
		}

        	pParams.ShouldHide = true;
		g_SayMenu.Show( pPlayer );
	}

	if( args.ArgC() == 1 && args.Arg(0) == "!vc" || args.ArgC() == 1 && args.Arg(0) == "/vc" || args.ArgC() == 1 && args.Arg(0) == ".vc" || args.ArgC() == 1 && args.Arg(0) == "/voicemenu" )
	{
		if ( !pPlayer.IsAlive() && !isAdmin )
		{
			pParams.ShouldHide = true;
			g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTTALK, "[Voice] You must be alive\n" );
			return HOOK_CONTINUE;
		}

        	pParams.ShouldHide = true;
		g_SayMenu2.Show( pPlayer );
	}

	if( args.ArgC() == 1 && args.Arg(0) == ".scientist" )
	{
		if ( !pPlayer.IsAlive() && !isAdmin )
		{
			pParams.ShouldHide = true;
			g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTTALK, "[Voice] You must be alive\n" );
			return HOOK_CONTINUE;
		}

        	pParams.ShouldHide = true;
		g_SayMenu2.Show2( pPlayer );
	}

	if( args.ArgC() == 1 && args.Arg(0) == ".barney" )
	{
		if ( !pPlayer.IsAlive() && !isAdmin )
		{
			pParams.ShouldHide = true;
			g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTTALK, "[Voice] You must be alive\n" );
			return HOOK_CONTINUE;
		}

        	pParams.ShouldHide = true;
		g_SayMenu2.Show3( pPlayer );
	}

	if( args.ArgC() == 1 && args.Arg(0) == ".hgrunt" )
	{
		if ( !pPlayer.IsAlive() && !isAdmin )
		{
			pParams.ShouldHide = true;
			g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTTALK, "[Voice] You must be alive\n" );
			return HOOK_CONTINUE;
		}

        	pParams.ShouldHide = true;
		g_SayMenu2.Show4( pPlayer );
	}

	if( args.ArgC() == 1 && args.Arg(0) == ".fgrunt" )
	{
		if ( !pPlayer.IsAlive() && !isAdmin )
		{
			pParams.ShouldHide = true;
			g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTTALK, "[Voice] You must be alive\n" );
			return HOOK_CONTINUE;
		}

        	pParams.ShouldHide = true;
		g_SayMenu2.Show6( pPlayer );
	}

	if( args.ArgC() == 1 && args.Arg(0) == ".otis" )
	{
		if ( !pPlayer.IsAlive() && !isAdmin )
		{
			pParams.ShouldHide = true;
			g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTTALK, "[Voice] You must be alive\n" );
			return HOOK_CONTINUE;
		}

        	pParams.ShouldHide = true;
		g_SayMenu2.Show7( pPlayer );
	}

	if( args.ArgC() == 1 && args.Arg(0) == ".agrunt" )
	{
		if ( !pPlayer.IsAlive() && !isAdmin )
		{
			pParams.ShouldHide = true;
			g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTTALK, "[Voice] You must be alive\n" );
			return HOOK_CONTINUE;
		}

        	pParams.ShouldHide = true;
		
		if( pPlayer.HasNamedPlayerItem("weapon_agrunt") !is null || pPlayer.HasNamedPlayerItem("weapon_agruntf") !is null )
		{
			g_SayMenu2.Show5( pPlayer );
		}
		else
		{
			pParams.ShouldHide = true;
			g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTTALK, "[Voice] You must be actively wielding an Alien Grunt control NPC!\n" );
			return HOOK_CONTINUE;
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/holster" )
	{
		if ( !pPlayer.IsAlive() )
		{
			pParams.ShouldHide = true;
			g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTTALK, "[Holster] You must be alive\n" );
			return HOOK_CONTINUE;
		}

        	pParams.ShouldHide = true;

		if ( pPlayer !is null && pPlayer.HasNamedPlayerItem("weapon_action") is null )
		{
			pPlayer.GiveNamedItem( "weapon_action" );
			pPlayer.SelectItem( "weapon_action" );
		}
		else
		{
			pPlayer.SelectItem( "weapon_action" );
		}
	}

	/*if( args.ArgC() == 1 && args.Arg(0) == "/dropcash")
	{
        	pParams.ShouldHide = true;

		if(pPlayer.pev.frags > 0)
		{
			Vector vecSrc;
			vecSrc = pPlayer.GetGunPosition() + g_Engine.v_forward * 32;
        		pParams.ShouldHide = true;
			CBaseEntity@ pCash = g_EntityFuncs.Create( "item_cash", vecSrc, pPlayer.pev.v_angle, false, pPlayer.edict() );
			pCash.pev.velocity = g_Engine.v_forward * 300;
			pPlayer.pev.frags -= 1;

			if(pPlayer.pev.frags == 0)
			{
				pPlayer.pev.frags = -1;
			}
		}
	}*/

	if( args.ArgC() == 1 && args.Arg(0) == "/ag" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_barnield";
			keys["origin"] = vecSrc.ToString();
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.velocity = g_Engine.v_up * 300;

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/ag2" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_agruntdrone";
			keys["origin"] = vecSrc.ToString();
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.velocity = g_Engine.v_up * 300;

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/ag3" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_agruntdrone4";
			keys["origin"] = vecSrc.ToString();
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.velocity = g_Engine.v_up * 300;

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/ag4" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_agruntdrone5";
			keys["origin"] = vecSrc.ToString();
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.velocity = g_Engine.v_up * 300;

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/ag5" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_agruntdrone8";
			keys["origin"] = vecSrc.ToString();
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.velocity = g_Engine.v_up * 300;

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/ag6" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_agruntdrone9";
			keys["origin"] = vecSrc.ToString();
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.velocity = g_Engine.v_up * 300;

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/ag7" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_agruntdrone14";
			keys["origin"] = vecSrc.ToString();
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.velocity = g_Engine.v_up * 300;

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/ag8" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_barnield";
			keys["origin"] = vecSrc.ToString();
			keys["netname"] = "nofollow";
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.velocity = g_Engine.v_up * 300;

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/ag9" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_agruntdrone";
			keys["origin"] = vecSrc.ToString();
			keys["netname"] = "nofollow";
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.velocity = g_Engine.v_up * 300;

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/ag10" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_agruntdrone4";
			keys["origin"] = vecSrc.ToString();
			keys["netname"] = "nofollow";
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.velocity = g_Engine.v_up * 300;

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/ag11" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_agruntdrone5";
			keys["origin"] = vecSrc.ToString();
			keys["netname"] = "nofollow";
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.velocity = g_Engine.v_up * 300;

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/ag12" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_agruntdrone8";
			keys["origin"] = vecSrc.ToString();
			keys["netname"] = "nofollow";
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.velocity = g_Engine.v_up * 300;

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/ag13" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_agruntdrone9";
			keys["origin"] = vecSrc.ToString();
			keys["netname"] = "nofollow";
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.velocity = g_Engine.v_up * 300;

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/ag14" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_agruntdrone14";
			keys["origin"] = vecSrc.ToString();
			keys["netname"] = "nofollow";
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.velocity = g_Engine.v_up * 300;

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/eag" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_agruntdrone2";
			keys["origin"] = vecSrc.ToString();
			//keys["netname"] = "nofollow";
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.velocity = g_Engine.v_up * 300;

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/eag2" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_agruntdrone3";
			keys["origin"] = vecSrc.ToString();
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.velocity = g_Engine.v_up * 300;

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/eag3" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_agruntdrone6";
			keys["origin"] = vecSrc.ToString();
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.velocity = g_Engine.v_up * 300;

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/eag4" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_agruntdrone7";
			keys["origin"] = vecSrc.ToString();
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.velocity = g_Engine.v_up * 300;

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/eag5" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_agruntdrone2";
			keys["origin"] = vecSrc.ToString();
			keys["netname"] = "nofollow";
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.velocity = g_Engine.v_up * 300;

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/eag6" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_agruntdrone3";
			keys["origin"] = vecSrc.ToString();
			keys["netname"] = "nofollow";
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.velocity = g_Engine.v_up * 300;

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/eag7" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_agruntdrone6";
			keys["origin"] = vecSrc.ToString();
			keys["netname"] = "nofollow";
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.velocity = g_Engine.v_up * 300;

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/eag8" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_agruntdrone7";
			keys["origin"] = vecSrc.ToString();
			keys["netname"] = "nofollow";
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.velocity = g_Engine.v_up * 300;

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/hg" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_hgruntdrone";
			keys["origin"] = vecSrc.ToString();
			keys["netname"] = "nofollow";
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.velocity = g_Engine.v_up * 300;

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/hg2" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_hgruntdroneelite";
			keys["origin"] = vecSrc.ToString();
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.velocity = g_Engine.v_up * 300;

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/specops" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_hgruntdroneelite2";
			keys["origin"] = vecSrc.ToString();
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.velocity = g_Engine.v_up * 300;

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/specops2" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_hgruntdroneelite3";
			keys["origin"] = vecSrc.ToString();
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.velocity = g_Engine.v_up * 300;

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/ehg" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_hgruntdrone2";
			keys["origin"] = vecSrc.ToString();
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.velocity = g_Engine.v_up * 300;
			pNPC.SetClassification(11);

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/terror" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_terrorist";
			keys["origin"] = vecSrc.ToString();
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.velocity = g_Engine.v_up * 300;
			pNPC.SetClassification(11);

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/terrorW" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_terrorist";
			keys["origin"] = vecSrc.ToString();
			keys["freeroam"] = 2;
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.velocity = g_Engine.v_up * 300;

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}


	if( args.ArgC() == 1 && args.Arg(0) == "/zombie" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_zombiedrone";
			keys["origin"] = vecSrc.ToString();
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.velocity = g_Engine.v_up * 300;

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/zombie2" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_zombiedrone2";
			keys["origin"] = vecSrc.ToString();
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.velocity = g_Engine.v_up * 300;

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/zombie3" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_zombiedrone3";
			keys["origin"] = vecSrc.ToString();
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.velocity = g_Engine.v_up * 300;

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/tyrant" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_tyrant";
			keys["origin"] = vecSrc.ToString();
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.velocity = g_Engine.v_up * 300;

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/nemesis" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_nemesis";
			keys["origin"] = vecSrc.ToString();
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.velocity = g_Engine.v_up * 300;

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/has" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_assassin";
			keys["origin"] = vecSrc.ToString();
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.velocity = g_Engine.v_up * 300;

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/has2" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_assassin2";
			keys["origin"] = vecSrc.ToString();
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.velocity = g_Engine.v_up * 300;

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/has3" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_assassin";
			keys["netname"] = "nofollow";
			keys["origin"] = vecSrc.ToString();
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.velocity = g_Engine.v_up * 300;

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/has4" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_assassin2";
			keys["origin"] = vecSrc.ToString();
			keys["netname"] = "nofollow";
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.velocity = g_Engine.v_up * 300;

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/eas" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_assassin3";
			keys["origin"] = vecSrc.ToString();
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.velocity = g_Engine.v_up * 300;
			pNPC.SetClassification(11);

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/eas2" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_assassin4";
			keys["origin"] = vecSrc.ToString();
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.velocity = g_Engine.v_up * 300;
			pNPC.SetClassification(11);

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/eas3" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_assassin3";
			keys["netname"] = "nofollow";
			keys["origin"] = vecSrc.ToString();
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.velocity = g_Engine.v_up * 300;
			pNPC.SetClassification(11);

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/eas4" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_assassin4";
			keys["netname"] = "nofollow";
			keys["origin"] = vecSrc.ToString();
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.velocity = g_Engine.v_up * 300;
			pNPC.SetClassification(11);

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/kate" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_angrykate";
			keys["origin"] = vecSrc.ToString();
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.armorvalue = 25;
			pNPC.pev.origin = pPlayer.pev.origin + g_Engine.v_forward * 32;
			pNPC.pev.velocity = g_Engine.v_up * 300;

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/kate2" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_angrykate";
			keys["origin"] = vecSrc.ToString();
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.armorvalue = 50;
			pNPC.pev.origin = pPlayer.pev.origin + g_Engine.v_forward * 32;
			pNPC.pev.velocity = g_Engine.v_up * 300;

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/kate3" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_angrykate";
			keys["origin"] = vecSrc.ToString();
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.armorvalue = 75;
			pNPC.pev.origin = pPlayer.pev.origin + g_Engine.v_forward * 32;
			pNPC.pev.velocity = g_Engine.v_up * 300;

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/kate4" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_angrykate";
			keys["origin"] = vecSrc.ToString();
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.armorvalue = 100;
			pNPC.pev.origin = pPlayer.pev.origin + g_Engine.v_forward * 32;
			pNPC.pev.velocity = g_Engine.v_up * 300;

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/kate5" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_angrykate";
			keys["origin"] = vecSrc.ToString();
			keys["netname"] = "nofollow";
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.armorvalue = 25;
			pNPC.pev.origin = pPlayer.pev.origin + g_Engine.v_forward * 32;
			pNPC.pev.velocity = g_Engine.v_up * 300;

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/kate6" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_angrykate";
			keys["origin"] = vecSrc.ToString();
			keys["netname"] = "nofollow";
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.armorvalue = 50;
			pNPC.pev.origin = pPlayer.pev.origin + g_Engine.v_forward * 32;
			pNPC.pev.velocity = g_Engine.v_up * 300;

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/kate7" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_angrykate";
			keys["origin"] = vecSrc.ToString();
			keys["netname"] = "nofollow";
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.armorvalue = 75;
			pNPC.pev.origin = pPlayer.pev.origin + g_Engine.v_forward * 32;
			pNPC.pev.velocity = g_Engine.v_up * 300;

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/kate8" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_angrykate";
			keys["origin"] = vecSrc.ToString();
			keys["netname"] = "nofollow";
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.armorvalue = 100;
			pNPC.pev.origin = pPlayer.pev.origin + g_Engine.v_forward * 32;
			pNPC.pev.velocity = g_Engine.v_up * 300;

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/kate9" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_angrykate2";
			keys["origin"] = vecSrc.ToString();
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.armorvalue = 100;
			pNPC.pev.origin = pPlayer.pev.origin + g_Engine.v_forward * 32;
			pNPC.pev.velocity = g_Engine.v_up * 300;

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/kate10" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_angrykate2";
			keys["origin"] = vecSrc.ToString();
			keys["netname"] = "nofollow";
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.armorvalue = 100;
			pNPC.pev.origin = pPlayer.pev.origin + g_Engine.v_forward * 32;
			pNPC.pev.velocity = g_Engine.v_up * 300;

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/kate11" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_angrykate2";
			keys["weapons"] = 1;
			keys["origin"] = vecSrc.ToString();
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			@pNPC.pev.euser1 = pPlayer.edict();
			pNPC.pev.armorvalue = 100;
			pNPC.pev.origin = pPlayer.pev.origin + g_Engine.v_forward * 32;
			pNPC.pev.velocity = g_Engine.v_up * 300;

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/snark" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_hlsnark";
			//keys["origin"] = vecSrc.ToString();
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			//@pNPC.pev.euser1 = pPlayer.edict();
			@pNPC.pev.owner = pPlayer.edict();
			pNPC.pev.velocity = g_Engine.v_forward * 300;
			pNPC.pev.origin = pPlayer.pev.origin + g_Engine.v_forward * 32;
			pNPC.pev.health = 15;

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/snark2" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			szClassname = "monster_snark";
			//keys["origin"] = vecSrc.ToString();
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			//@pNPC.pev.euser1 = pPlayer.edict();
			@pNPC.pev.owner = pPlayer.edict();
			pNPC.pev.velocity = g_Engine.v_forward * 300;
			pNPC.pev.origin = pPlayer.pev.origin + g_Engine.v_forward * 32;
			pNPC.pev.health = 15;

			if(pNPC !is null)
			{
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}

	/*if( args.ArgC() == 1 && args.Arg(0) == "/shocker" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			Vector vecSrc2 = pPlayer.pev.origin;
        		pParams.ShouldHide = true;
			CBaseEntity@ pAgrunt = g_EntityFuncs.Create( "monster_shocker", vecSrc2, pPlayer.pev.v_angle, false, pPlayer.edict() );
			pAgrunt.pev.velocity = g_Engine.v_up * 300;
			pAgrunt.pev.angles.z = 0;	
			pAgrunt.pev.angles.x = 0;
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/healthbot" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			Vector vecSrc2 = pPlayer.pev.origin;
        		pParams.ShouldHide = true;
			CBaseEntity@ pAgrunt = g_EntityFuncs.Create( "monster_human_medic_ally", vecSrc2, pPlayer.pev.v_angle, false, pPlayer.edict() );
			g_EntityFuncs.DispatchKeyValue(pAgrunt.edict(), "displayname", "Healthbot");
			g_EntityFuncs.DispatchKeyValue(pAgrunt.edict(), "bloodcolor", -1);
			g_EntityFuncs.SetModel( pAgrunt, "models/healthbot.mdl" );
			pAgrunt.pev.velocity = g_Engine.v_up * 300;
			pAgrunt.pev.angles.z = 0;	
			pAgrunt.pev.angles.x = 0;
			pAgrunt.pev.health = 600.0;
		}
	}*/

	if( args.ArgC() == 1 && args.Arg(0) == "/healthbot" )
	{
        	pParams.ShouldHide = true;

		if( isAdmin )
		{
			//pPlayer.pev.targetname = pPlayer.pev.netname;

			szClassname = "monster_human_medic_ally";
			keys["displayname"] = "Healthbot";
			keys["bloodcolor"] = "-1";
			//keys["guard_ent"] = string(pPlayer.pev.targetname);
			keys["angles"] = Vector(0, pPlayer.pev.v_angle.y, 0).ToString();

			@pNPC = g_EntityFuncs.CreateEntity( szClassname, keys, true );
			pNPC.pev.velocity = g_Engine.v_forward * 300;
			pNPC.pev.origin = pPlayer.pev.origin + g_Engine.v_forward * 32;
			pNPC.pev.flags |= FL_GODMODE;
			@pNPC.pev.euser1 = pPlayer.edict();

			if(pNPC !is null)
			{
				g_EntityFuncs.SetModel( pNPC, "models/healthbot.mdl" );
				g_EntityFuncs.DispatchSpawn(pNPC.edict());
			}
		}
	}
	
	if( args.ArgC() == 1 && args.Arg(0) == "boo" || args.ArgC() == 1 && args.Arg(0) == "Boo" || args.ArgC() == 1 && args.Arg(0) == "boo!" || args.ArgC() == 1 && args.Arg(0) == "Boo!" )
	{
		if ( !pPlayer.IsAlive() && !isAdmin )
		{
			g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTTALK, "[Voice] You must be alive\n" );
			return HOOK_CONTINUE;
		}

		if( isAdmin )
		{
        		pParams.ShouldHide = true;
		}

		g_SoundSystem.EmitSoundDyn( pPlayer.edict(), CHAN_VOICE, "misc/tf2/heavy_jeers01.wav", 0.75, ATTN_NORM, 0, PITCH_NORM );
	}

	if( args.ArgC() == 1 && args.Arg(0) == "aa" || args.ArgC() == 1 && args.Arg(0) == "aaa" || args.ArgC() == 1 && args.Arg(0) == "agh" || args.ArgC() == 1 && args.Arg(0) == "argh" )
	{
		if ( !pPlayer.IsAlive() && !isAdmin )
		{
			g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTTALK, "[Voice] You must be alive\n" );
			return HOOK_CONTINUE;
		}

		if( isAdmin )
		{
        		pParams.ShouldHide = true;
		}

		g_SoundSystem.EmitSoundDyn( pPlayer.edict(), CHAN_VOICE, "misc/tf2/heavy_jeers02.wav", 0.75, ATTN_NORM, 0, PITCH_NORM );
	}

	if( args.ArgC() == 1 && args.Arg(0) == "sad" || args.ArgC() == 1 && args.Arg(0) == "sadge" )
	{
		if ( !pPlayer.IsAlive() && !isAdmin )
		{
			g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTTALK, "[Voice] You must be alive\n" );
			return HOOK_CONTINUE;
		}

		if( isAdmin )
		{
        		pParams.ShouldHide = true;
		}

		g_SoundSystem.EmitSoundDyn( pPlayer.edict(), CHAN_VOICE, "misc/tf2/heavy_jeers05.wav", 0.75, ATTN_NORM, 0, PITCH_NORM );
	}

	if( args.ArgC() == 1 && args.Arg(0) == "how" || args.ArgC() == 1 && args.Arg(0) == "howw" || args.ArgC() == 1 && args.Arg(0) == "howww" || args.ArgC() == 1 && args.Arg(0) == "howwww" || args.ArgC() == 1 && args.Arg(0) == "how?" )
	{
		if ( !pPlayer.IsAlive() && !isAdmin )
		{
			g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTTALK, "[Voice] You must be alive\n" );
			return HOOK_CONTINUE;
		}

		if( isAdmin )
		{
        		pParams.ShouldHide = true;
		}

		g_SoundSystem.EmitSoundDyn( pPlayer.edict(), CHAN_VOICE, "misc/tf2/heavy_jeers09.wav", 0.75, ATTN_NORM, 0, PITCH_NORM );
	}

	if( args.ArgC() == 1 && args.Arg(0) == "stupid" )
	{
		if ( !pPlayer.IsAlive() && !isAdmin )
		{
			g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTTALK, "[Voice] You must be alive\n" );
			return HOOK_CONTINUE;
		}

		if( isAdmin )
		{
        		pParams.ShouldHide = true;
		}

		g_SoundSystem.EmitSoundDyn( pPlayer.edict(), CHAN_VOICE, "misc/tf2/heavy_jeers03.wav", 0.75, ATTN_NORM, 0, PITCH_NORM );
	}

	if( args.ArgC() == 1 && args.Arg(0) == "noo" || args.ArgC() == 1 && args.Arg(0) == "nooo" || args.ArgC() == 1 && args.Arg(0) == "noooo" || args.ArgC() == 1 && args.Arg(0) == "nooooo" || args.ArgC() == 1 && args.Arg(0) == "Noo" 
	|| args.ArgC() == 1 && args.Arg(0) == "Nooo" || args.ArgC() == 1 && args.Arg(0) == "Noooo" || args.ArgC() == 1 && args.Arg(0) == "Nooooo" )
	{
		if ( !pPlayer.IsAlive() && !isAdmin )
		{
			g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTTALK, "[Voice] You must be alive\n" );
			return HOOK_CONTINUE;
		}

		if( isAdmin )
		{
        		pParams.ShouldHide = true;
		}

		g_SoundSystem.EmitSoundDyn( pPlayer.edict(), CHAN_VOICE, "misc/tf2/heavy_jeers04.wav", 0.75, ATTN_NORM, 0, PITCH_NORM );
	}

	if( args.ArgC() == 1 && ( args.Arg(0) == "/jeers" || args.Arg(0) == ".jeers" ) )
	{
		if ( !pPlayer.IsAlive() && !isAdmin )
		{
			g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTTALK, "[Voice] You must be alive\n" );
			return HOOK_CONTINUE;
		}

        	pParams.ShouldHide = true;

		switch ( Math.RandomLong( 1, 9 ) )
		{
			case 1: g_SoundSystem.EmitSoundDyn( pPlayer.edict(), CHAN_VOICE, "misc/tf2/heavy_jeers01.wav", 0.75, ATTN_NORM, 0, PITCH_NORM ); break;
			case 2: g_SoundSystem.EmitSoundDyn( pPlayer.edict(), CHAN_VOICE, "misc/tf2/heavy_jeers02.wav", 0.75, ATTN_NORM, 0, PITCH_NORM ); break;
			case 3: g_SoundSystem.EmitSoundDyn( pPlayer.edict(), CHAN_VOICE, "misc/tf2/heavy_jeers03.wav", 0.75, ATTN_NORM, 0, PITCH_NORM ); break;
			case 4: g_SoundSystem.EmitSoundDyn( pPlayer.edict(), CHAN_VOICE, "misc/tf2/heavy_jeers04.wav", 0.75, ATTN_NORM, 0, PITCH_NORM ); break;
			case 5: g_SoundSystem.EmitSoundDyn( pPlayer.edict(), CHAN_VOICE, "misc/tf2/heavy_jeers05.wav", 0.75, ATTN_NORM, 0, PITCH_NORM ); break;
			case 6: g_SoundSystem.EmitSoundDyn( pPlayer.edict(), CHAN_VOICE, "misc/tf2/heavy_jeers06.wav", 0.75, ATTN_NORM, 0, PITCH_NORM ); break;
			case 7: g_SoundSystem.EmitSoundDyn( pPlayer.edict(), CHAN_VOICE, "misc/tf2/heavy_jeers07.wav", 0.75, ATTN_NORM, 0, PITCH_NORM ); break;
			case 8: g_SoundSystem.EmitSoundDyn( pPlayer.edict(), CHAN_VOICE, "misc/tf2/heavy_jeers08.wav", 0.75, ATTN_NORM, 0, PITCH_NORM ); break;
			case 9: g_SoundSystem.EmitSoundDyn( pPlayer.edict(), CHAN_VOICE, "misc/tf2/heavy_jeers09.wav", 0.75, ATTN_NORM, 0, PITCH_NORM ); break;
		}
	}

	/*if( args.ArgC() == 1 && args.Arg(0) == "F" )
	{
        	//pParams.ShouldHide = true;
		g_SoundSystem.EmitSoundDyn( pPlayer.edict(), CHAN_STATIC, "misc/death.wav", 1.0, 0.0, 0, PITCH_NORM );
	}*/

	/*if( args.ArgC() == 1 && args.Arg(0) == "/scxpmlevelup" )
	{
        	pParams.ShouldHide = true;
		g_SoundSystem.EmitSoundDyn( pPlayer.edict(), CHAN_STATIC, "misc/levelup.ogg", 1.0, ATTN_NONE, SND_SKIP_ORIGIN_USE_ENT, PITCH_NORM, pPlayer.entindex() );
	}*/

	if( args.ArgC() == 1 && args.Arg(0) == ".moveup" )
	{
		if( isAdmin )
		{
        		pParams.ShouldHide = true;
			GetSoundEntInstance().InsertSound ( bits_SOUND_COMBAT, pPlayer.pev.origin, NORMAL_GUN_VOLUME, 0.3, pPlayer ); 
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == ".move" )
	{
		if( isAdmin )
		{
        		pParams.ShouldHide = true;
			GetSoundEntInstance().InsertSound ( bits_SOUND_COMBAT, pPlayer.pev.origin, LOUD_GUN_VOLUME, 0.3, pPlayer ); 
		}
	}

	//if( args.ArgC() == 1 && args.Arg(0) == "/followme" )
	//{
        	//pParams.ShouldHide = true;
		//AlertMonsters(pPlayer, pPlayer.pev.origin, 800);
	//}

	if( args.ArgC() == 1 && args.Arg(0) == "/selectskills" )
	{
        	pParams.ShouldHide = true;
	}

	if( args.ArgC() == 1 && args.Arg(0) == "selectskills" )
	{
        	pParams.ShouldHide = true;
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/resetskills" )
	{
        	pParams.ShouldHide = true;
	}

	if( args.ArgC() == 1 && args.Arg(0) == "resetskills" )
	{
        	pParams.ShouldHide = true;
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/dynamicvote" )
	{
        	pParams.ShouldHide = true;
	}

	if( args.ArgC() == 1 && args.Arg(0) == "!exitnpc" || args.ArgC() == 1 && args.Arg(0) == "/exitnpc" || args.ArgC() == 1 && args.Arg(0) == ".exitnpc" )
	{
        	pParams.ShouldHide = true;

		if( pPlayer.m_hActiveItem.GetEntity() !is null )
		{
			CustomKeyvalues@ pCustom = pPlayer.GetCustomKeyvalues();
			pCustom.SetKeyvalue( CNPC::sCNPCKV, 0 );

			/*Vector vecOrigin = pPlayer.pev.origin;
			CBasePlayerWeapon@ pWeapon = cast<CBasePlayerWeapon@>( pPlayer.m_hActiveItem.GetEntity() );

			if( pWeapon.GetClassname() == "weapon_agrunt" or pWeapon.GetClassname() == "weapon_agruntf" or pWeapon.GetClassname() == "weapon_pitdrone" or pWeapon.GetClassname() == "weapon_strooper" 
			or pWeapon.GetClassname() == "weapon_hgrunts" or pWeapon.GetClassname() == "weapon_enforcer" or pWeapon.GetClassname() == "weapon_otis" or pWeapon.GetClassname() == "weapon_payne" 
			or pWeapon.GetClassname() == "weapon_ofgrunt" or pWeapon.GetClassname() == "weapon_srhgrunt" or pWeapon.GetClassname() == "weapon_gonome" or pWeapon.GetClassname() == "weapon_hwgrunt" 
			or pWeapon.GetClassname() == "weapon_fassn" or pWeapon.GetClassname() == "weapon_kingpin" or pWeapon.GetClassname() == "weapon_garg" or pWeapon.GetClassname() == "weapon_babygarg"
			or pWeapon.GetClassname() == "weapon_islave" or pWeapon.GetClassname() == "weapon_bigmomma" or pWeapon.GetClassname() == "weapon_bullsquid" or pWeapon.GetClassname() == "weapon_zombie" 
			or pWeapon.GetClassname() == "weapon_houndeye" or pWeapon.GetClassname() == "weapon_securityguard" or pWeapon.GetClassname() == "weapon_agruntfc" )
			{
				g_EntityFuncs.Remove( pWeapon );
				pPlayer.pev.solid = SOLID_SLIDEBOX;
				pPlayer.pev.effects &= ~EF_NODRAW;
				pPlayer.pev.flags &= ~FL_MONSTER;
				pPlayer.pev.flags &= ~FL_NOTARGET;
				pPlayer.pev.flags &= ~FL_GODMODE;
				pPlayer.pev.takedamage = DAMAGE_YES;
				pPlayer.pev.scale = 1.0;
				pPlayer.pev.iuser3 = 0;
				pPlayer.pev.fuser4 = 0;
				pPlayer.m_bloodColor = BLOOD_COLOR_RED;
				if( pPlayer.pev.health < 100 )
				{
					pPlayer.pev.health = pPlayer.pev.health;
				}
				else
				{
					pPlayer.pev.health = 100;
				}
				if( pPlayer.pev.armorvalue > 100 )
				{
					pPlayer.pev.armorvalue = 100;
				}
				pPlayer.pev.max_health = 100;
				pPlayer.pev.armortype = 100;
				pPlayer.pev.view_ofs = Vector( 0, 0, 28 );
				pPlayer.SetItemPickupTimes( 0.0 );

				NetworkMessage m1( MSG_ONE_UNRELIABLE, NetworkMessages::SVC_STUFFTEXT, pPlayer.edict() );
					m1.WriteString( "cl_movespeedkey 0.3;\n" );
				m1.End();

				CustomKeyvalues@ pCustom = pPlayer.GetCustomKeyvalues();
				pCustom.SetKeyvalue( CNPC::sCNPCKV, 0 );
			}

			if( pWeapon.GetClassname() == "weapon_babygarg" )
			{
				g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTTALK, "[ExitNPC] Baby Gargantua removed. $5000 were added back to your balance.\n" );
				CBaseEntity@ pAGDrone = g_EntityFuncs.Create( "item_money5000", vecOrigin, pPlayer.pev.v_angle, false, pPlayer.edict() );
				pAGDrone.pev.velocity = g_Engine.v_up * 1;
				pAGDrone.pev.spawnflags = 7168;
			}

			if( pWeapon.GetClassname() == "weapon_agruntf" )
			{
				g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTTALK, "[ExitNPC] Alien Grunt removed. $3000 were added back to your balance.\n" );
				CBaseEntity@ pAGDrone = g_EntityFuncs.Create( "item_money3000", vecOrigin, pPlayer.pev.v_angle, false, pPlayer.edict() );
				pAGDrone.pev.velocity = g_Engine.v_up * 1;
				pAGDrone.pev.spawnflags = 7168;
			}

			if( pWeapon.GetClassname() == "weapon_pitdrone" )
			{
				g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTTALK, "[ExitNPC] Pit Drone removed. $800 were added back to your balance.\n" );
				CBaseEntity@ pAGDrone = g_EntityFuncs.Create( "item_money800", vecOrigin, pPlayer.pev.v_angle, false, pPlayer.edict() );
				pAGDrone.pev.velocity = g_Engine.v_up * 300;
				pAGDrone.pev.spawnflags = 7168;
			}

			if( pWeapon.GetClassname() == "weapon_bullsquid" )
			{
				g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTTALK, "[ExitNPC] Bull Squid removed. $800 were added back to your balance.\n" );
				CBaseEntity@ pAGDrone = g_EntityFuncs.Create( "item_money800", vecOrigin, pPlayer.pev.v_angle, false, pPlayer.edict() );
				pAGDrone.pev.velocity = g_Engine.v_up * 300;
				pAGDrone.pev.spawnflags = 7168;
			}

			if( pWeapon.GetClassname() == "weapon_islave" )
			{
				g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTTALK, "[ExitNPC] Alien Slave removed. $500 were added back to your balance.\n" );
				CBaseEntity@ pAGDrone = g_EntityFuncs.Create( "item_money500", vecOrigin, pPlayer.pev.v_angle, false, pPlayer.edict() );
				pAGDrone.pev.velocity = g_Engine.v_up * 300;
				pAGDrone.pev.spawnflags = 7168;
			}

			if( pWeapon.GetClassname() == "weapon_zombie" )
			{
				g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTTALK, "[ExitNPC] Zombie removed. $500 were added back to your balance.\n" );
				CBaseEntity@ pAGDrone = g_EntityFuncs.Create( "item_money500", vecOrigin, pPlayer.pev.v_angle, false, pPlayer.edict() );
				pAGDrone.pev.velocity = g_Engine.v_up * 300;
				pAGDrone.pev.spawnflags = 7168;
			}

			if( pWeapon.GetClassname() == "weapon_houndeye" )
			{
				g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTTALK, "[ExitNPC] Houndeye removed. $500 were added back to your balance.\n" );
				CBaseEntity@ pAGDrone = g_EntityFuncs.Create( "item_money500", vecOrigin, pPlayer.pev.v_angle, false, pPlayer.edict() );
				pAGDrone.pev.velocity = g_Engine.v_up * 300;
				pAGDrone.pev.spawnflags = 7168;
			}

			if( pWeapon.GetClassname() == "weapon_securityguard" )
			{
				g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTTALK, "[ExitNPC] Security guard removed. $500 were added back to your balance.\n" );
				CBaseEntity@ pAGDrone = g_EntityFuncs.Create( "item_money500", vecOrigin, pPlayer.pev.v_angle, false, pPlayer.edict() );
				pAGDrone.pev.velocity = g_Engine.v_up * 300;
				pAGDrone.pev.spawnflags = 7168;
			}

			if( pWeapon.GetClassname() == "weapon_strooper" )
			{
				g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTTALK, "[ExitNPC] Shock Trooper removed. $1000 were added back to your balance.\n" );
				CBaseEntity@ pAGDrone = g_EntityFuncs.Create( "item_money1000", vecOrigin, pPlayer.pev.v_angle, false, pPlayer.edict() );
				pAGDrone.pev.velocity = g_Engine.v_up * 1;
				pAGDrone.pev.spawnflags = 7168;
			}

			if( pWeapon.GetClassname() == "weapon_hgrunts" )
			{
				g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTTALK, "[ExitNPC] Human Grunt removed. $1500 were added back to your balance.\n" );
				CBaseEntity@ pAGDrone = g_EntityFuncs.Create( "item_money1000", vecOrigin, pPlayer.pev.v_angle, false, pPlayer.edict() );
				pAGDrone.pev.velocity = g_Engine.v_up * 1;
				pAGDrone.pev.spawnflags = 7168;

				CBaseEntity@ pAGDrone2 = g_EntityFuncs.Create( "item_money500", vecOrigin, pPlayer.pev.v_angle, false, pPlayer.edict() );
				pAGDrone2.pev.velocity = g_Engine.v_up * 1;
				pAGDrone2.pev.spawnflags = 7168;
			}

			if( pWeapon.GetClassname() == "weapon_hwgrunt" )
			{
				g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTTALK, "[ExitNPC] Heavy Weapons Grunt removed. $4000 were added back to your balance.\n" );
				CBaseEntity@ pAGDrone = g_EntityFuncs.Create( "item_money4000", vecOrigin, pPlayer.pev.v_angle, false, pPlayer.edict() );
				pAGDrone.pev.velocity = g_Engine.v_up * 1;
				pAGDrone.pev.spawnflags = 7168;
			}

			if( pWeapon.GetClassname() == "weapon_kingpin" )
			{
				g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTTALK, "[ExitNPC] Kingpin removed. $5000 were added back to your balance.\n" );
				CBaseEntity@ pAGDrone = g_EntityFuncs.Create( "item_money5000", vecOrigin, pPlayer.pev.v_angle, false, pPlayer.edict() );
				pAGDrone.pev.velocity = g_Engine.v_up * 1;
				pAGDrone.pev.spawnflags = 7168;
			}

			if( pWeapon.GetClassname() == "weapon_fassn" )
			{
				g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTTALK, "[ExitNPC] Female Assassin removed. $3000 were added back to your balance.\n" );
				CBaseEntity@ pAGDrone = g_EntityFuncs.Create( "item_money3000", vecOrigin, pPlayer.pev.v_angle, false, pPlayer.edict() );
				pAGDrone.pev.velocity = g_Engine.v_up * 1;
				pAGDrone.pev.spawnflags = 7168;
			}

			if( pWeapon.GetClassname() == "weapon_gonome" )
			{
				g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTTALK, "[ExitNPC] Gonome removed. $1000 were added back to your balance.\n" );
				CBaseEntity@ pAGDrone = g_EntityFuncs.Create( "item_money1000", vecOrigin, pPlayer.pev.v_angle, false, pPlayer.edict() );
				pAGDrone.pev.velocity = g_Engine.v_up * 1;
				pAGDrone.pev.spawnflags = 7168;
			}

			if( pWeapon.GetClassname() == "weapon_ofgrunt" )
			{
				g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTTALK, "[ExitNPC] OPFOR Grunt removed. $2000 were added back to your balance.\n" );
				CBaseEntity@ pAGDrone = g_EntityFuncs.Create( "item_money2000", vecOrigin, pPlayer.pev.v_angle, false, pPlayer.edict() );
				pAGDrone.pev.velocity = g_Engine.v_up * 1;
				pAGDrone.pev.spawnflags = 7168;
			}*/
		}
	}

	if( args.ArgC() == 1 && args.Arg(0) == ".help" || args.ArgC() == 1 && args.Arg(0) == "!help" || args.ArgC() == 1 && args.Arg(0) == "/help" )
	{
        	pParams.ShouldHide = true;
		//g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTTALK, "[Help] Displaying help information. Check your console for more information.\n" );
		//g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTCONSOLE, "[Help] Say /holster to lower/holster your weapon, can use fists to fight your enemies (10 damage a hit).\n" );
		//g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTCONSOLE, "[Help] Say /cam, /caf or /voicemenu for voice commands.\n" );
		//g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTCONSOLE, "[Help] Say /dropcash to share cash with other players.\n" );
		//g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTCONSOLE, "[Help] Say /summon to summon an NPC to fight for you.\n" );
		//g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTCONSOLE, "[Help] Say buy, /buy or /shop to open a buymenu.\n" );
		//g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTCONSOLE, "[Help] Say .e for emotes.\n" );

		NetworkMessage help( MSG_ONE, NetworkMessages::SVC_STUFFTEXT, pPlayer.edict() );
			help.WriteString( "servermotd\n" );
		help.End();
	}

	if( args.ArgC() == 1 && args.Arg(0) == ".pee" || args.ArgC() == 1 && args.Arg(0) == ".coom" || args.ArgC() == 1 && args.Arg(0) == ".barf" || args.ArgC() == 1 && args.Arg(0) == ".fart" 
	|| args.ArgC() == 1 && args.Arg(0) == "fart" || args.ArgC() == 1 && args.Arg(0) == "/fart" )
	{
        	pParams.ShouldHide = true;
		g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTTALK, "[Server] What is wrong with you?!\n" );
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/rtv" || args.ArgC() == 1 && args.Arg(0) == ".rtv" || args.ArgC() == 1 && args.Arg(0) == "rtv" )
	{
        	pParams.ShouldHide = true;
		g_PlayerFuncs.ClientPrint( pPlayer, HUD_PRINTTALK, "[Help] If the rtv does not work, say /votemenu instead.\n" );
	}

	if( args.ArgC() == 1 && args.Arg(0) == "/votemenu" || args.ArgC() == 1 && args.Arg(0) == ".votemenu" || args.ArgC() == 1 && args.Arg(0) == "votemenu" || args.ArgC() == 1 && args.Arg(0) == ".vote" 
	|| args.ArgC() == 1 && args.Arg(0) == "/vote" )
	{
        	pParams.ShouldHide = true;
		NetworkMessage votemenu( MSG_ONE, NetworkMessages::SVC_STUFFTEXT, pPlayer.edict() );
			votemenu.WriteString( "votemenu\n" );
		votemenu.End();
	}
	
	if (args.ArgC() > 0 && doCommand(pPlayer, args, false))
	{
		pParams.ShouldHide = true;
		return HOOK_HANDLED;
	}
	return HOOK_CONTINUE;
}

CClientCommand _g("secretweaponstash", "Weapon commands", @consoleCmd );

void consoleCmd( const CCommand@ args ) 
{
	CBasePlayer@ plr = g_ConCommandSystem.GetCurrentPlayer();
	doCommand(plr, args, true);
}

bool doCommand(CBasePlayer@ plr, const CCommand@ args, bool inConsole) 
{
	bool isAdmin = g_PlayerFuncs.AdminLevel(plr) >= ADMIN_YES;
	
	if (args.ArgC() >= 1 && isAdmin)
	{
		if (args[0] == "secretweaponstash") 
		{
			g_BuyMenu.Show( plr );
			
			return true;
		}
	}
	
	return false;
}

HookReturnCode PlayerRevived(CBasePlayer@ pPlayer)
{
	EHandle ePlayer = pPlayer;
	g_Scheduler.SetTimeout( "RespawnDeadThink", 1.0f, ePlayer );

	/*if ( pPlayer !is null && pPlayer.HasNamedPlayerItem("weapon_action") is null && (pPlayer.pev.flags & FL_FAKECLIENT) == 0 )
	{
		pPlayer.GiveNamedItem( "weapon_action" );
	}*/

	if ( pPlayer !is null && pPlayer.HasNamedPlayerItem("weapon_ofeagle") is null && (pPlayer.pev.flags & FL_FAKECLIENT) != 0 )
	{
		pPlayer.GiveNamedItem( "weapon_ofeagle" );
	}
	
	return HOOK_CONTINUE;
}

void ReEquipCollected(EHandle hPlayer, bool blKeepAmmo = true, bool blResetLoadout = false)
{
	if( !hPlayer )
		return;

	CBaseEntity@ pActivator; 
	CBaseEntity@ pCaller;
	CBasePlayer@ pPlayer = cast<CBasePlayer@>( hPlayer.GetEntity() );
	array<string> STR_LOADOUT_WEAPONS = DICT_PLAYER_LOADOUT[pPlayer.entindex()].getKeys();
	//const bool
		//blKeepAmmo = true,
		//blResetLoadout = pCaller !is null ? pCaller.pev.SpawnFlagBitSet( RESET_LOADOUT ) : false;

	if( blResetLoadout )
		pPlayer.RemoveAllItems( false );

	for( uint i = 0; i < STR_LOADOUT_WEAPONS.length(); i++ )
	{
		if( STR_LOADOUT_WEAPONS[i] == "" )
			continue;
            
		if( STR_LOADOUT_WEAPONS[i] == "item_longjump" )
		{
			if( bool( DICT_PLAYER_LOADOUT[pPlayer.entindex()]["item_longjump"] ) && !pPlayer.m_fLongJump )
			{
				pPlayer.m_fLongJump = true;
				g_EngineFuncs.GetPhysicsKeyBuffer( pPlayer.edict() ).SetValue( "slj", "1" );
			}
              
			continue;
		}
        
		if( STR_LOADOUT_WEAPONS[i] == "item_suit" )
		{
			if( bool( DICT_PLAYER_LOADOUT[pPlayer.entindex()]["item_suit"] ) && !pPlayer.HasSuit() )
				pPlayer.SetHasSuit( true );
              
			continue;
		}

		if( STR_LOADOUT_WEAPONS[i] == "weapon_npcspawner" )
		{
			continue;
		}

		if( STR_LOADOUT_WEAPONS[i] == "weapon_action" )
		{
			continue;
		}

		if( pPlayer.HasNamedPlayerItem( STR_LOADOUT_WEAPONS[i] ) is null )
			pPlayer.GiveNamedItem( STR_LOADOUT_WEAPONS[i] ); // Would be nice if this returned the actual item ptr...

		DICT_PLAYER_LOADOUT[pPlayer.entindex()] = GetPlayerLoadout( pPlayer );

		CBasePlayerWeapon@ pEquippedWeapon = cast<CBasePlayerWeapon@>( pPlayer.HasNamedPlayerItem( STR_LOADOUT_WEAPONS[i] ) );
		const Vector2D vec2DAmmoValues = Vector2D( DICT_PLAYER_LOADOUT[pPlayer.entindex()][STR_LOADOUT_WEAPONS[i]] );

		if( pEquippedWeapon is null )
			continue;

		if( blKeepAmmo && pEquippedWeapon.m_iPrimaryAmmoType > 0 )
		{
			pPlayer.m_rgAmmo( pEquippedWeapon.m_iPrimaryAmmoType, int( vec2DAmmoValues.x ) );

			if( int( vec2DAmmoValues.y ) > 0 )
				pPlayer.m_rgAmmo( pEquippedWeapon.m_iSecondaryAmmoType, int( vec2DAmmoValues.y ) );
		}
	}

	DICT_PLAYER_LOADOUT[pPlayer.entindex()] = dictionary();
}

dictionary GetPlayerLoadout(EHandle hPlayer)
{
	if( !hPlayer )
	return dictionary();
        
	CBasePlayer@ pPlayer = cast<CBasePlayer@>( hPlayer.GetEntity() );
    
	dictionary dictLoadout =
	{
		//{ "item_suit", pPlayer.HasSuit() },
		{ "item_longjump", pPlayer.m_fLongJump }
	};
    
	for( uint i = 0; i < MAX_ITEM_TYPES; i++ )
	{
		CBasePlayerWeapon@ pWeapon = cast<CBasePlayerWeapon@>( pPlayer.m_rgpPlayerItems( i ) );

		while( pWeapon !is null && pWeapon.pev.targetname != "nosave" && WeaponsRespawn.find( pWeapon.GetClassname() ) >= 0 )
		{
			const string strWeapon = pWeapon.GetClassname(); //== "weapon_uzi" && pWeapon.m_fIsAkimbo ? "weapon_uziakimbo" : pWeapon.GetClassname();
			dictLoadout[strWeapon] = pWeapon.m_iPrimaryAmmoType < 0 ? Vector2D() : Vector2D( pPlayer.m_rgAmmo( pWeapon.m_iPrimaryAmmoType ), pWeapon.m_iSecondaryAmmoType > 0 ? 
				pPlayer.m_rgAmmo( pWeapon.m_iSecondaryAmmoType ) : 0 );

			@pWeapon = cast<CBasePlayerWeapon@>( pWeapon.m_hNextItem.GetEntity() );
		}
	}
    
	return dictLoadout;
}

HookReturnCode PlayerSpawn(CBasePlayer@ pPlayer)
{
	if( pPlayer.pev.health > pPlayer.pev.max_health )
	{
		pPlayer.pev.health = pPlayer.pev.max_health;
	}

	pPlayer.SetMaxAmmo( "health", 200 );
	pPlayer.SetMaxAmmo( "9mm", 600 );
	pPlayer.SetMaxAmmo( "357", 150 );
	pPlayer.SetMaxAmmo( "buckshot", 160 );
	pPlayer.SetMaxAmmo( "bolts", 200 );
	pPlayer.SetMaxAmmo( "556", 600 );
	pPlayer.SetMaxAmmo( "ARgrenades", 20 );
	pPlayer.SetMaxAmmo( "rockets", 10 );
	pPlayer.SetMaxAmmo( "uranium", 300 );
	pPlayer.SetMaxAmmo( "m40a1", 200 );
	pPlayer.SetMaxAmmo( "sporeclip", 60 );
	pPlayer.SetMaxAmmo( "Snarks", 20 );
	pPlayer.SetMaxAmmo( "Hand Grenade", 15 );
	pPlayer.SetMaxAmmo( "Satchel Charge", 5 );
	pPlayer.SetMaxAmmo( "Trip Mine", 5 );

	if( !m_bMapChanged )
	{
		EHandle ePlayer = pPlayer;
		g_Scheduler.SetTimeout( "RespawnDeadThink", 1.0f, ePlayer );
	}

	if ( pPlayer !is null && (pPlayer.pev.flags & FL_FAKECLIENT) != 0 )
	{
		CustomKeyvalues@ pCustom = pPlayer.GetCustomKeyvalues();
		pCustom.SetKeyvalue( "$fl_lastHealth", pPlayer.pev.health );
		pCustom.SetKeyvalue( "$fl_lastPain", 0.0f );
		pPlayer.GiveNamedItem( "weapon_crowbar" );
		pPlayer.SelectItem( "weapon_crowbar" );
		
		/*int amt = 0;
		CBasePlayerItem@ pItem;
		CBasePlayerItem@ pItemHold;
		CBasePlayerWeapon@ pWeapon;
		for(uint j = 0; j < MAX_ITEM_TYPES; j++)
		{
			@pItem = pPlayer.m_rgpPlayerItems(j);
			while(pItem !is null)
			{
				@pWeapon = pItem.GetWeaponPtr();
							
				if(pWeapon.GetClassname() != "weapon_crowbar")
				{
					@pItemHold = pItem;
					@pItem = cast<CBasePlayerItem@>(pItem.m_hNextItem.GetEntity());
					pPlayer.RemovePlayerItem(pItemHold);
					amt++;
					continue;
				}
							
				@pItem = cast<CBasePlayerItem@>(pItem.m_hNextItem.GetEntity());
			}
		}*/

		//pPlayer.GiveNamedItem( "weapon_crowbar" );
	
		//pPlayer.m_bloodColor = DONT_BLEED;
		//pPlayer.pev.effects |= EF_NODRAW;
		//pPlayer.pev.flags |= FL_NOTARGET;
		//pPlayer.pev.health = 300;
		g_EntityFuncs.DispatchKeyValue(pPlayer.edict(), "max_health", 300);
		g_EntityFuncs.DispatchKeyValue(pPlayer.edict(), "health", 300);
		//g_EntityFuncs.DispatchKeyValue(pPlayer.edict(), "armorvalue", 25);
	}


	return HOOK_CONTINUE;
}

HookReturnCode PlayerGotKilled( CBasePlayer@ pPlayer, CBaseEntity@ pAttacker, int iGib )
{
	if( pPlayer is null )
		return HOOK_CONTINUE;

	if( pPlayer !is null && (pPlayer.pev.flags & FL_FAKECLIENT) == 0 )
	{
		m_bMapChanged = false;
		DICT_PLAYER_LOADOUT[pPlayer.entindex()] = GetPlayerLoadout( pPlayer );
	}

	/*dictionary dictKeys = {};
	g_EngineFuncs.MakeVectors( pPlayer.pev.angles );
	Vector vecItemDrop = pPlayer.pev.origin;
	string szMapName = string(g_Engine.mapname);
	CBasePlayerWeapon@ pWeapon = cast<CBasePlayerWeapon@>( pPlayer.m_hActiveItem.GetEntity() );
	string szClassname = pPlayer.m_hActiveItem.GetEntity().GetClassname();
	if( szMapName.Split( "_" )[0] == "pvp" || szMapName.Split( "_" )[0] == "ctf" || szMapName.Split( "_" )[0] == "bm" )
	{
		CBaseEntity@ ammo = g_EntityFuncs.Create( "item_money300", vecItemDrop, pPlayer.pev.angles, false );
		ammo.pev.velocity = g_Engine.v_up * 350;
		ammo.pev.spawnflags = 7168;
		ammo.pev.angles.z = 0;
		ammo.pev.angles.x = 0;
	}
	if( pWeapon !is null && pWeapon.pev.classname != "weapon_crowbar" && pWeapon.pev.classname != "weapon_pipewrench" && pWeapon.pev.classname != "weapon_wrench" && pWeapon.pev.classname != "weapon_grapple"
	&& pWeapon.pev.classname != "weapon_action" && pWeapon.pev.classname != "weapon_knife" && pWeapon.pev.classname != "weapon_npcspawner" && pWeapon.pev.classname != "weapon_hgrunts" 
	&& pWeapon.pev.classname != "weapon_ofgrunt" && pWeapon.pev.classname != "weapon_agrunt" && pWeapon.pev.classname != "weapon_agruntf" 
	&& pWeapon.pev.classname != "weapon_pitdrone" && pWeapon.pev.classname != "weapon_strooper" && pWeapon.pev.classname != "weapon_kinpin" 
	&& pWeapon.pev.classname != "weapon_babygarg" && pWeapon.pev.classname != "weapon_garg" && pWeapon.pev.classname != "weapon_bigmomma" 
	&& pWeapon.pev.classname != "weapon_islave" && pWeapon.pev.classname != "weapon_zombie" && pWeapon.pev.classname != "weapon_payne" 
	&& pWeapon.pev.classname != "weapon_enforcer" && pWeapon.pev.classname != "weapon_hwgrunt" && pWeapon.pev.classname != "weapon_gonome" 
	&& pWeapon.pev.classname != "weapon_bullsquid" && pWeapon.pev.classname != "weapon_fassn" && (pPlayer.pev.effects & EF_NODRAW) != EF_NODRAW )
	{
		CBaseEntity@ pDroppedItem = g_EntityFuncs.CreateEntity( szClassname, dictKeys, true );
		pDroppedItem.pev.targetname = "nosave";
		pDroppedItem.pev.origin = vecItemDrop;
		pDroppedItem.pev.spawnflags = 7424;
		pDroppedItem.pev.angles.z = 0;
		pDroppedItem.pev.angles.x = 0;
		@pDroppedItem.pev.owner = pPlayer.edict();

		if(pDroppedItem !is null)
		{
			g_EntityFuncs.DispatchSpawn(pDroppedItem.edict());
		}
	}*/

	return HOOK_CONTINUE;
}

HookReturnCode MapChanged(const string& in szLevel)
{
	//CBasePlayer@ pPlayer;
	//DICT_PLAYER_LOADOUT[pPlayer.entindex()] = dictionary();
	string szMapName = string(g_Engine.mapname);
	if( szMapName.Split( "_" )[0] == "hl" || szMapName.Split( "_" )[0] == "sl" || szMapName.Split( "_" )[0] == "hr" || szMapName.Split( "_" )[0] == "cad" || szMapName.Split( "_" )[0] == "th" )
	{
		m_bMapChanged = false;
	}
	else
	{
		m_bMapChanged = true;
	}

	return HOOK_HANDLED;
}

void RespawnDeadThink(EHandle ePlayer)
{
	if( ePlayer )
	{
		CBaseEntity@ pPlayer = ePlayer;
		ReEquipCollected(cast<CBasePlayer@>(pPlayer));
	}
}