#include < amxmodx >
#include < cstrike >
#include < engine > 
#include < fakemeta >
#include < hamsandwich >
#include < zombieplague >

new const PLUGIN_VERSION[ ]    =  "0.0.1";

const OFFSET_WEAPONOWNER    =      41
const OFFSET_LINUX    =    5
const OFFSET_LINUX_WEAPONS     =      4

const WEAP_KEY   =	545464464
const MAX_PLAYERS   =		32

const m_iClip			=		51
const m_flNextAttack		=		83
const m_flNextPrimaryAttack    =    46

enum _:Coord_e 
{ 
	Float:x,
	Float:y, 
	Float:z 
};

enum ( <<= 1 ) 
{ 
	angles = 1, 
	v_angle, 
	punchangle 
};

enum _:Angle_e 
{ 
	Float:pitch, 
	Float:yaw, 
	Float:roll 
};

enum ( <<=1 )
{
	DROP_PRIMARY = 1,
	DROP_SECONDARY
};

enum _:OTHERS
{
	TRAIL = 1 , 
	DECALINDEX , 
	EXPLODESPR , 
	PUFFSPR  
}	

enum eState:
{
	State_Shown = 0,
	State_Hidden
};

const IDLE = 0 
const RELOAD = 3
const DRAW = 4
const SHOOT_1 = 1
const SHOOT_2 = 2 

#define write_coord_f(%1)	engfunc(EngFunc_WriteCoord,%1)
#define HoldCBaseWeapon(%0)	( get_user_weapon( %0 ) == g_iWeaponID  && g_pWeaponA[ %0 ] )
#define IsValidPrivateData(%0)	( pev_valid( %0 ) == 2 )

#define VectorScale(%1,%2,%3)    ( %3[ x ] = %2 * %1[ x ], %3[ y ] = %2 * %1[ y ], %3[ z ] = %2 * %1[ z ] )
#define VectorAdd(%1,%2,%3)      ( %3[ x ] = %1[ x ] + %2[ x ], %3[ y ] = %1[ y ] + %2[ y ], %3[ z ] = %1[ z ] + %2[ z ] )

new const WEAPON_SOUND_FIRE[ ] = "weapons/at4-1.wav";

new const WEAPON_LIST[ ]   =   "weapon_at4cs_sh";
new const WEAPON_BASE_NAME[ ]   =  "weapon_sg552";

const Float:RELOAD_TIME  =   4.0

const AMMO__WEAPON        =  10 
const CLIP__WEAPON  =  1 
const COST__GRENADE   =  200 

const Float:ROCKET__DAMAGE   =   1000.0
const Float:ROCKET__RADIUS = 300.0
const Float:ROCKET__SPEED    = 1600.0

new const EXTRA_ITEM_NAME[ ]    =   "AT4CS";

new V_MODEL[ ] = "models/zm/v_at4ex.mdl";
new P_MODEL[ ] = "models/zm/p_at4ex.mdl";
new W_MODEL[ ] = "models/zm/w_weapons.mdl";

new R_MODEL[ ] = "models/zm/s_rocket.mdl"

new const BUYAMMO_SOUND[ ] = "items/9mmclip1.wav";

new const HUD_SPRITES[ ] [ ] = 
{
	"sprites/zm/640hud7.spr" , 
	"sprites/zm/640hud53.spr" , 
	"sprites/zm/at4_scope.spr" 
}	

new g_iItem , g_iOriginEvent , g_iMaxPlayers , g_iForwardIndex;


new g_iEffect[ OTHERS ]; 

new g_pWeaponA[ MAX_PLAYERS + 1 ] , 
    bool:g_iPrimaryAttack;
	
new g_iClipAmmo[ MAX_PLAYERS + 1 ], 
	g_TmpClip[ MAX_PLAYERS + 1 ] , 
	g_iWeaponID = 0;
	
const HIDE_CROSSHAIR = ( 1 << 6 );	

new const ROCKET__CLASSNAME[ ]  =   "Rocket_at";	

const WEAPONS_PRIMARY_BITSUM 	= (1<<CSW_SCOUT)|(1<<CSW_XM1014)|(1<<CSW_MAC10)|(1<<CSW_AUG)|(1<<CSW_UMP45)|(1<<CSW_SG550)|(1<<CSW_GALIL)|(1<<CSW_FAMAS)|(1<<CSW_AWP)|(1<<CSW_MP5NAVY)|(1<<CSW_M249)|(1<<CSW_M3)|(1<<CSW_M4A1)|(1<<CSW_TMP)|(1<<CSW_G3SG1)|(1<<CSW_SG552)|(1<<CSW_AK47)|(1<<CSW_P90);
const WEAPONS_SECONDARY_BITSUM 	= (1<<CSW_P228)|(1<<CSW_ELITE)|(1<<CSW_FIVESEVEN)|(1<<CSW_USP)|(1<<CSW_GLOCK18)|(1<<CSW_DEAGLE);

public plugin_precache()
{
	precache_model(V_MODEL);
	precache_model(P_MODEL);
	precache_model(W_MODEL);
	precache_model(R_MODEL);
	
	PrecacheSoundsFromModel( V_MODEL );
	
	precache_sound(WEAPON_SOUND_FIRE);
	
	static iFile
	
	for( iFile = 0 ; iFile < sizeof HUD_SPRITES; iFile++ ) 
	{
		precache_generic( HUD_SPRITES[ iFile ] )
	}	
	
	static szFile [ 64 ];
	
	formatex ( szFile , charsmax( szFile ) , "sprites/%s.txt" , WEAPON_LIST );
	precache_generic( szFile );
	
	precache_sound( BUYAMMO_SOUND ) 
	
	g_iEffect[ EXPLODESPR ]  = precache_model( "sprites/zm/zerogxplode-big1.spr"  )
	g_iEffect[ TRAIL ] = precache_model("sprites/xbeam3.spr")
	g_iEffect[ PUFFSPR ]  = precache_model("sprites/effects/rainsplash.spr")
	
	g_iForwardIndex = register_forward( FM_PrecacheEvent, "Forward_PrecacheEventPost", true );
}

public plugin_init()
{
	register_plugin( "[CSO] Extra Item Ethereal" , PLUGIN_VERSION , "Shurik07" );
	register_clcmd( WEAPON_LIST, "weapon_hook_an" );
	
	unregister_forward( FM_PrecacheEvent, g_iForwardIndex, true );
	register_forward(FM_SetModel, "Forward_SetModel" , false );
	register_forward(FM_PlaybackEvent, "Forward_PlayBackEvent" , false )
	register_forward(FM_UpdateClientData, "Forward_UpdateClientData" , true );
	
	RegisterHam( Ham_Item_AddToPlayer, WEAPON_BASE_NAME, "CBaseWeapon__AddToPlayer__Pre" , .Post = false );
	RegisterHam( Ham_Item_Deploy, WEAPON_BASE_NAME , "CBaseWeapon__Deploy__Post", .Post = true );
	RegisterHam( Ham_Item_Holster, WEAPON_BASE_NAME, "CBaseWeapon_Holster_Post", .Post = true );
	RegisterHam( Ham_Weapon_PrimaryAttack, WEAPON_BASE_NAME, "CBaseWeapon__PrimaryAttack__Pre" , .Post = false );
	RegisterHam( Ham_Weapon_PrimaryAttack, WEAPON_BASE_NAME, "CBaseWeapon_PrimaryAttack_Post", .Post = true );
	RegisterHam( Ham_Item_PostFrame, WEAPON_BASE_NAME, "CBaseWeapon__PostFrame__Pre" , .Post = false );
	RegisterHam( Ham_Weapon_Reload, WEAPON_BASE_NAME, "CBaseWeapon__Reload_Pre" , .Post = false );
	RegisterHam( Ham_Weapon_Reload, WEAPON_BASE_NAME, "CBaseWeapon__Reload_Post", .Post = true );


	RegisterHam(Ham_TraceAttack, "worldspawn", "fw_TraceAttack", 0)
	RegisterHam(Ham_TraceAttack, "player", "fw_TraceAttack", 0)
	
	register_touch( ROCKET__CLASSNAME , "*", "CTouch_Rocket" )
	register_think( ROCKET__CLASSNAME , "CThink_Rocket" )
	
	
	g_iEffect[ DECALINDEX ]   = get_decal_index("{scorch3")

	g_iItem = zp_register_extra_item( EXTRA_ITEM_NAME, 150, ZP_TEAM_HUMAN );
	g_iMaxPlayers = get_maxplayers();
	g_iWeaponID = get_weaponid( WEAPON_BASE_NAME );
}

public fw_TraceAttack(Victim, Attacker, Float:Damage, Float:Direction[3], Ptr, DamageBits)
{
	if(!is_user_alive(Attacker))
		return HAM_IGNORED	
	if(get_user_weapon(Attacker) != CSW_G3SG1 || !g_pWeaponA[Attacker])
		return HAM_IGNORED
		
	return HAM_SUPERCEDE
}

public plugin_natives()
{
	register_native("zp_get_weapon_rocket", "native_weapon_rocket", 1)
}

public native_weapon_rocket(id)
{
	return g_pWeaponA[id];
}

public zp_extra_item_selected( pPlayer , pItem )
{
	if( pItem == g_iItem  )
	{
		 UTIL__DropWeapons( pPlayer, DROP_PRIMARY )
		 
		 g_pWeaponA[ pPlayer ]  = true;
		 
		 static pEntity;
		 
		 pEntity = fm_give_item( pPlayer , WEAPON_BASE_NAME ); 
		 
		 if( pEntity > 0 )
		 {
		    cs_set_weapon_ammo( pEntity, CLIP__WEAPON );	
		 }	
		 
		 cs_set_user_bpammo( pPlayer , g_iWeaponID , AMMO__WEAPON );
		 
		 UTIL__WeaponList( pPlayer,  WEAPON_LIST , 4 , 90 , -1 , -1 , 0 , 10 , g_iWeaponID , 0 );
	}	
}

public weapon_hook_an( pPlayer  ) 
{
        engclient_cmd( pPlayer, WEAPON_BASE_NAME);
        return PLUGIN_HANDLED;
}

public zp_user_humanized_post( pPlayer )
{
	g_pWeaponA[ pPlayer ] = false;
}

public client_disconnect( pPlayer )
{
	g_pWeaponA[ pPlayer ]  = false;
}

public Forward_PrecacheEventPost(type, const pName[ ] )
{
	if ( equal ("events/sg552.sc", pName ) )
	{
		g_iOriginEvent = get_orig_retval( );
		return FMRES_HANDLED;
	}
	return FMRES_IGNORED;
}

public Forward_SetModel( pEntity, pModel[])
{
	if( !is_valid_ent( pEntity ) ) 
	{
		return FMRES_IGNORED;
	}	
	
	static szClassName [ 33 ]
	entity_get_string( pEntity, EV_SZ_classname, szClassName, charsmax ( szClassName ) )
		
	if( !equal ( szClassName, "weaponbox" ) )
	{
		return FMRES_IGNORED;
	}	
	
	static pOwner , pModel
	
	pModel = find_ent_by_owner ( -1, WEAPON_BASE_NAME, pEntity );
	
	pOwner = entity_get_edict(pEntity, EV_ENT_owner)
	
	if ( g_pWeaponA [ pOwner ]  && is_valid_ent ( pModel ) )
	{
		entity_set_int( pModel, EV_INT_impulse, WEAP_KEY);
		
		entity_set_model( pEntity, W_MODEL );
		set_pev(pEntity, pev_body, 22)

		g_pWeaponA [ pOwner ]   = false;
		
		return FMRES_SUPERCEDE;
	}

	return FMRES_IGNORED;
}

public Forward_UpdateClientData( pPlayer , SendWeapons, CD_Handle )
{
	if ( !HoldCBaseWeapon( pPlayer ) )
	{
		return HAM_IGNORED;
	}

	static Float:fGametime;
	fGametime = get_gametime();
	
	set_cd ( CD_Handle, CD_flNextAttack, fGametime + 0.001 );

	return FMRES_HANDLED;
}

public Forward_PlayBackEvent(flags, invoker, eventid, Float:delay, Float:origin[3], Float:fvangles[3], Float:fparam1, Float:fparam2, iParam1, iParam2, bParam1, bParam2)
{
	if ( ( eventid != g_iOriginEvent) || !g_iPrimaryAttack )
	{
		return FMRES_IGNORED;
	}	
		
	if (!( 1 <= invoker <= g_iMaxPlayers ) )
	{
        return FMRES_IGNORED;
	}	
	
	if( flags & FEV_GLOBAL )
	{	
		flags &= ~FEV_GLOBAL;
	}

	playback_event(flags | FEV_HOSTONLY, invoker, eventid, delay, origin, fvangles, fparam1, fparam2, iParam1, iParam2, bParam1, bParam2)
	return FMRES_SUPERCEDE
}

public CBaseWeapon__AddToPlayer__Pre( pEnity , pPlayer )
{
	if( !pev_valid( pEnity ) && !is_user_connected( pPlayer ) ) 
	{
		 return HAM_IGNORED;
	}
	
	if( pev( pEnity, pev_impulse ) == WEAP_KEY || g_pWeaponA[ pPlayer ] )
	{
		g_pWeaponA[ pPlayer ]  = true;
		
		UTIL__WeaponList( pPlayer,  WEAPON_LIST , 4 , 90 , -1 , -1 , 0 , 10 , g_iWeaponID , 0 );

		return HAM_HANDLED;
	}
	else
	{
		UTIL__WeaponList( pPlayer,  WEAPON_BASE_NAME , 4 , 90 , -1 , -1 , 0 , 10 , g_iWeaponID , 0 );
	}	

	return HAM_IGNORED;
}

public CBaseWeapon__Deploy__Post( pEntity )
{
	if( !IsValidPrivateData( pEntity ) )
	{
                return HAM_HANDLED;
	}
	
	static pId 
	pId = get_pdata_cbase( pEntity , OFFSET_WEAPONOWNER , OFFSET_LINUX_WEAPONS );
	
	if (!g_pWeaponA[pId]  )
	{
		return HAM_IGNORED;
	}	
	
	set_pev(pId, pev_viewmodel2, V_MODEL);
	set_pev(pId, pev_weaponmodel2, P_MODEL);
	
	set_pdata_float( pId, m_flNextAttack, 1.0, OFFSET_LINUX);
	
	UTIL__SetCrosshairStatus( pId, State_Hidden  )
	UTIL_SenwWeaponAnim( pId, DRAW );
	
	return HAM_IGNORED;
}

public CBaseWeapon_Holster_Post( pEntity )
{
	if( !IsValidPrivateData( pEntity ) )
	{
				return HAM_HANDLED;
	}

	static pPlayer;

	pPlayer = get_pdata_cbase( pEntity , OFFSET_WEAPONOWNER , OFFSET_LINUX_WEAPONS );

	UTIL__SetCrosshairStatus( pPlayer, State_Shown );

	if ( !HoldCBaseWeapon( pPlayer ) )
	{
		return HAM_IGNORED;
	}

	return HAM_IGNORED;
}

public CBaseWeapon__PrimaryAttack__Pre(pEntity)
{
	if( !IsValidPrivateData( pEntity ) )
	{
		return HAM_IGNORED;
	}

	static 	pId;

	pId = get_pdata_cbase( pEntity , OFFSET_WEAPONOWNER , OFFSET_LINUX_WEAPONS );

	if ( !HoldCBaseWeapon( pId ) )
	{
		return HAM_IGNORED;
	}

	g_iClipAmmo[pId] = cs_get_weapon_ammo(pEntity);

	g_iPrimaryAttack = true;
	
	return HAM_IGNORED;
}

public CBaseWeapon_PrimaryAttack_Post( pEntity )
{
	if( !IsValidPrivateData( pEntity ) )
	{
		return HAM_IGNORED;
	}
	g_iPrimaryAttack = false;
	
	static pId ; pId = get_pdata_cbase( pEntity, OFFSET_WEAPONOWNER, OFFSET_LINUX_WEAPONS );
	
	if ( !HoldCBaseWeapon( pId ) )
	{
		return HAM_IGNORED;
	}

	if (!g_iClipAmmo[pId])
	{
			return HAM_IGNORED;
	}	
		
		
	client_cmd(pId, "spk %s", WEAPON_SOUND_FIRE)
	UTIL_SenwWeaponAnim( pId, random_num( SHOOT_1 , SHOOT_2 ) );
	
	static Float:vf_Forward[ Coord_e ], Float:vf_vAngle[ Angle_e ];
	static Float:vf_Source [ Coord_e ], Float:vf_Angles[ Coord_e ];
	
	engfunc( EngFunc_GetAttachment, pId, 0, vf_Source, vf_Angles )

	global_get ( glb_v_forward, vf_Forward );
	pev ( pId, pev_v_angle, vf_vAngle );
	
	set_pev( pId , pev_punchangle , Float:{ 3.2 , 3.2 , 0.0 } ); 

	static Float:vf_VelocitySR[ Coord_e ]
	
	VectorScale ( vf_Forward, ROCKET__SPEED , vf_VelocitySR );
	GLauncher_ShootRocket ( vf_Source, vf_VelocitySR, pId );
	
	return HAM_IGNORED;
}

GLauncher_ShootRocket ( const Float:vf_Origin[], const Float:vf_Velocity[], const i_Owner )
{
	static i_Rocket;

	if ( ( i_Rocket = engfunc ( EngFunc_CreateNamedEntity, engfunc ( EngFunc_AllocString, "info_target" ) ) ) )
	{
		static vf_Temp[ Angle_e ]

		set_pev ( i_Rocket, pev_classname, ROCKET__CLASSNAME );
		set_pev ( i_Rocket, pev_origin, vf_Origin );
		set_pev ( i_Rocket, pev_owner, i_Owner );

		set_pev ( i_Rocket, pev_movetype, MOVETYPE_FLYMISSILE );
		set_pev ( i_Rocket, pev_solid, SOLID_BBOX );
		set_pev ( i_Rocket, pev_takedamage, DAMAGE_NO );
		set_pev ( i_Rocket, pev_gravity, 0.5 );
		
		engfunc ( EngFunc_VecToAngles, vf_Velocity, vf_Temp );
		set_pev ( i_Rocket, pev_angles, vf_Temp );
		
		engfunc ( EngFunc_ParticleEffect, vf_Origin, vf_Velocity, 8.0 , 25.0 )

		engfunc ( EngFunc_SetModel , i_Rocket, R_MODEL );
		engfunc ( EngFunc_SetSize  , i_Rocket, Float:{ 0.0, 0.0, 0.0 }, Float:{ 0.0, 0.0, 0.0 } );
		engfunc ( EngFunc_SetOrigin, i_Rocket, vf_Origin );

		set_pev ( i_Rocket, pev_velocity, vf_Velocity );
		
		FX_BeamFollow ( i_Rocket, g_iEffect[ TRAIL ] , 25, 7, 255, 0, 0, 200 );	
		
		set_pev(i_Rocket, pev_nextthink, get_gametime( ) + 0.1)
	}
}

public CBaseWeapon__PostFrame__Pre( pEntity ) 
{
	if( !IsValidPrivateData( pEntity ) )
	{
                return HAM_HANDLED;
	}

	static pId;

	pId = get_pdata_cbase( pEntity , OFFSET_WEAPONOWNER , OFFSET_LINUX_WEAPONS );

	if ( !is_user_connected( pId ) && !HoldCBaseWeapon( pId ) && !g_iMaxPlayers )
	{
		return HAM_HANDLED;
	}
	
	new fInReload = get_pdata_int( pEntity, 54, OFFSET_LINUX_WEAPONS );
	new Float:flNextAttack = get_pdata_float( pId, m_flNextAttack, OFFSET_LINUX_WEAPONS );
	new iClip  = get_pdata_int( pEntity, m_iClip, OFFSET_LINUX_WEAPONS );
	new iAmmoType = 376 + get_pdata_int( pEntity, 49, OFFSET_LINUX_WEAPONS );
	new iBpAmmo  = get_pdata_int( pId, iAmmoType, OFFSET_LINUX );
	
	if ( fInReload && flNextAttack <= 1.4 )
	{
		new j = min( CLIP__WEAPON  - iClip, iBpAmmo);
	
		set_pdata_int( pEntity, m_iClip, iClip + j, OFFSET_LINUX_WEAPONS );
		set_pdata_int( pId, iAmmoType, iBpAmmo-j, OFFSET_LINUX );
		set_pdata_int( pEntity, 54, 0, OFFSET_LINUX_WEAPONS );

		fInReload = 0;
	}	 
	
	return HAM_IGNORED;
}

public CBaseWeapon__Reload_Pre(pEntity) 
{
	if( !IsValidPrivateData( pEntity ) )
	{
		return HAM_HANDLED;
	}

	static pId;

	pId = get_pdata_cbase( pEntity , OFFSET_WEAPONOWNER , OFFSET_LINUX_WEAPONS );

	if ( !is_user_connected( pId ) || !HoldCBaseWeapon( pId ) )
	{
		return HAM_IGNORED;
	}
	
	static iClipExtra;
	iClipExtra = CLIP__WEAPON ;
	
	g_TmpClip[pId] = -1;
	
	new iAmmoType = 376 + get_pdata_int( pEntity, 49, OFFSET_LINUX_WEAPONS );
	new iBpAmmo = get_pdata_int( pId, iAmmoType, OFFSET_LINUX );
	new iClip = get_pdata_int( pEntity, m_iClip, OFFSET_LINUX );
	
	if ( iBpAmmo <= 0 || iClip >= iClipExtra )
	{
	   return HAM_SUPERCEDE;
	}  
	
	g_TmpClip[pId] = iClip;
	
	return HAM_HANDLED;
}

public CBaseWeapon__Reload_Post( pEntity ) 
{
	if( !IsValidPrivateData( pEntity ) )
	{
                return HAM_HANDLED;
	}

	static pId ; pId  = get_pdata_cbase( pEntity , OFFSET_WEAPONOWNER , OFFSET_LINUX_WEAPONS );
	
	if ( !HoldCBaseWeapon( pId ) )
	{
		return HAM_IGNORED;
	}

	if (g_TmpClip[ pId ] == -1)
	{
		return HAM_IGNORED;
	}
	
	set_pdata_float( pId, m_flNextAttack, RELOAD_TIME , OFFSET_LINUX);
	
	UTIL_SenwWeaponAnim(pId, RELOAD);

	return HAM_HANDLED;
}

public CTouch_Rocket(pEntity, id)
{
	if( !pev_valid( pEntity ) )
	{
		return;
	}

	static Float:flOrigin[ Coord_e ];
	pev( pEntity, pev_origin, flOrigin );
	
	set_pev(pEntity, pev_movetype, MOVETYPE_NONE)
	set_pev(pEntity, pev_solid, SOLID_NOT)	
	
	message_begin(MSG_BROADCAST,SVC_TEMPENTITY)
	write_byte(TE_EXPLOSION)
	write_coord_f(  flOrigin[x])
	write_coord_f(  flOrigin[y])
	write_coord_f( flOrigin[z] +50.0 )
	write_short(g_iEffect[ EXPLODESPR ] )
	write_byte( 50 )
	write_byte( 30 )
	write_byte( 0 )
	message_end()

	message_begin(MSG_ALL, SVC_TEMPENTITY) 
	write_byte(TE_WORLDDECAL)
	write_coord_f(flOrigin[x])
	write_coord_f( flOrigin[y])
	write_coord_f( flOrigin[z])
	write_byte(g_iEffect[ DECALINDEX ] )
	message_end()

	new pOwner = pev( pEntity, pev_owner );
       
	static pevVictim, Float:flDistance,Float:fDamage;
                       
	pevVictim  = -1;
       
	while( ( pevVictim = engfunc( EngFunc_FindEntityInSphere, pevVictim, flOrigin, ROCKET__RADIUS) ) != 0 )
	{
			if( !is_user_alive( pevVictim ) )
					continue;

			if( !zp_get_user_zombie( pevVictim ) )
				continue;

			flDistance = entity_range( pEntity, pevVictim );

			fDamage = UTIL_FloatRadius( ROCKET__DAMAGE, ROCKET__RADIUS , flDistance );


			if( fDamage > 0.0 )
			{
					ExecuteHamB( Ham_TakeDamage, pevVictim, pEntity, pOwner, fDamage, DMG_BULLET | DMG_ALWAYSGIB);

			}

			message_begin( MSG_ONE_UNRELIABLE, get_user_msgid("ScreenFade"), {0,0,0}, pevVictim )
			write_short(1<<10)
			write_short(1<<10)
			write_short(0x0000)
			write_byte(200)
			write_byte(0)
			write_byte(0)
			write_byte(75)
			message_end()
	}
       
	engfunc( EngFunc_RemoveEntity, pEntity );
}

Float:UTIL_FloatRadius( Float:flMaxAmount, Float:flRadius, Float:flDistance )
{
        return floatsub( flMaxAmount, floatmul( floatdiv( flMaxAmount, flRadius ), flDistance ) );
}

public CThink_Rocket( iRocket )
{
	if(!pev_valid( iRocket ))
	{
		return
	}	

	static Float:fOrigin[3]
	pev( iRocket , pev_origin, fOrigin)
		
	message_begin( MSG_BROADCAST, SVC_TEMPENTITY )
	write_byte( TE_SPRITE )
	engfunc( EngFunc_WriteCoord, fOrigin[0] )
	engfunc( EngFunc_WriteCoord, fOrigin[1] )
	engfunc( EngFunc_WriteCoord, fOrigin[2] )
	write_short( g_iEffect[ PUFFSPR ] ) 
	write_byte( 6 ) 
	write_byte( 255 )
	message_end( )
	
	message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
	write_byte( TE_SPARKS ) 
	engfunc( EngFunc_WriteCoord, fOrigin[0] )
	engfunc( EngFunc_WriteCoord, fOrigin[1] )
	engfunc( EngFunc_WriteCoord, fOrigin[2] )
	message_end( )
		
	set_pev( iRocket , pev_nextthink, get_gametime( ) + 0.275 )
}

stock UTIL__DropWeapons(id, bitsDropType)
{
	static weapons[32], num, i, weaponid
	num = 0 
	get_user_weapons(id, weapons, num)
	
	for (i = 0; i < num; i++)
	{
		weaponid = weapons[i]
		
		if ((bitsDropType == DROP_PRIMARY && ((1<<weaponid) & WEAPONS_PRIMARY_BITSUM)) || (bitsDropType == DROP_SECONDARY && ((1<<weaponid) & WEAPONS_SECONDARY_BITSUM)))
		{
			static wname[32]
			get_weaponname(weaponid, wname, charsmax(wname))
			
			engclient_cmd(id, "drop", wname)
			cs_set_user_bpammo(id, weaponid, 0)
		}
	}
}

stock fm_find_ent_by_owner(entity, const classname[], owner)
{
	while ((entity = engfunc(EngFunc_FindEntityByString, entity, "classname", classname)) && pev(entity, pev_owner) != owner) { /* keep looping */ }
	return entity;
}

stock UTIL_SenwWeaponAnim(const pPlayer, const Sequence)
{
	set_pev(pPlayer, pev_weaponanim, Sequence)
	
	message_begin(MSG_ONE_UNRELIABLE, SVC_WEAPONANIM, .player = pPlayer)
	write_byte(Sequence)
	write_byte(pev(pPlayer, pev_body))
	message_end()
}

UTIL__WeaponList( pPlayer, const szWeapon[ ], int, int2, int3, int4, int5, int6, int7, int8 )
{
	message_begin( MSG_ONE, get_user_msgid( "WeaponList" ) , _, pPlayer );
	write_string( szWeapon );
	write_byte( int );
	write_byte( int2);
	write_byte( int3 );
	write_byte( int4 );
	write_byte( int5 );
	write_byte( int6 );
	write_byte( int7 );
	write_byte( int8 );
	message_end( );
}

stock fm_give_item(id, const item[])
{
	static ent
	ent = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, item))
	if (!pev_valid(ent)) return 0;
	
	static Float:originF[3]
	pev(id, pev_origin, originF)
	set_pev(ent, pev_origin, originF)
	set_pev(ent, pev_spawnflags, pev(ent, pev_spawnflags) | SF_NORESPAWN)
	dllfunc(DLLFunc_Spawn, ent)
	
	static save
	save = pev(ent, pev_solid)
	dllfunc(DLLFunc_Touch, ent, id)
	if (pev(ent, pev_solid) != save)
		return ent ;
	
	engfunc(EngFunc_RemoveEntity, ent)
	
	return -1;
}

FX_BeamFollow ( const i_Ent, const i_Trail, const i_Life, const i_Width, const i_Red, const i_Green, const i_Blue, const i_Brightness )
{
	message_begin ( MSG_BROADCAST, SVC_TEMPENTITY );
	write_byte ( TE_BEAMFOLLOW );
	write_short ( i_Ent );          // --| Enntity.
	write_short ( i_Trail );        // --| Model.
	write_byte ( i_Life );          // --| Life.
	write_byte ( i_Width );         // --| Width.
	write_byte ( i_Red );           // --| Red color.
	write_byte ( i_Green );         // --| Green color.
	write_byte ( i_Blue );          // --| Blue color.
	write_byte ( i_Brightness );    // --| Brightness.
	message_end ();
}

stock UTIL__SetCrosshairStatus( Player, eState:mState )
{
	static afFlags
	afFlags = 0;
	
	if( mState == State_Hidden )
		afFlags |= HIDE_CROSSHAIR;
	else
		afFlags &= ~HIDE_CROSSHAIR;
	
	message_begin( MSG_ONE, get_user_msgid( "HideWeapon" ), _, Player );
	write_byte( afFlags );
	message_end( );
}


PrecacheSoundsFromModel(const szModelPath[])
{
	new iFile;
	
	if ((iFile = fopen(szModelPath, "rt")))
	{
		new szSoundPath[64];
		
		new iNumSeq, iSeqIndex;
		new iEvent, iNumEvents, iEventIndex;
		
		fseek(iFile, 164, SEEK_SET);
		fread(iFile, iNumSeq, BLOCK_INT);
		fread(iFile, iSeqIndex, BLOCK_INT);
		
		for (new k, i = 0; i < iNumSeq; i++)
		{
			fseek(iFile, iSeqIndex + 48 + 176 * i, SEEK_SET);
			fread(iFile, iNumEvents, BLOCK_INT);
			fread(iFile, iEventIndex, BLOCK_INT);
			fseek(iFile, iEventIndex + 176 * i, SEEK_SET);

			for (k = 0; k < iNumEvents; k++)
			{
				fseek(iFile, iEventIndex + 4 + 76 * k, SEEK_SET);
				fread(iFile, iEvent, BLOCK_INT);
				fseek(iFile, 4, SEEK_CUR);
				
				if (iEvent != 5004)
				{
					continue;
				}

				fread_blocks(iFile, szSoundPath, 64, BLOCK_CHAR);
				
				if (strlen(szSoundPath))
				{
					strtolower(szSoundPath);
					precache_sound(szSoundPath);
				}
			}
		}
	}
	
	fclose(iFile);
}