/*
Copyright (C) 1997-2001 Id Software, Inc.

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  

See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/

/*
==========================================================================

- SPLITMODELS -

==========================================================================
*/
// - Adding the View Weapon in split pieces


#include "cg_local.h"

viewweaponinfo_t	vweap;


//======================================================================
//						Predict WeaponChange
//======================================================================

qboolean CG_UseWeapon( int newweapon, qboolean feedback ) {
	gitem_t *item;

	if( cg.demoPlaying )
		return qfalse;

	if( newweapon < WEAP_GUNBLADE || newweapon >= WEAP_TOTAL )
		return qfalse;

	item = GS_FindItemByTag( newweapon );
	if( !item )
		return qfalse;

	//check if we have the weapon
	if( !cg.frame.playerState.weaponlist[newweapon-1][0] ) {
		if( feedback ) {
			Com_Printf( "Out of item: %s\n", item->pickup_name );
			trap_S_StartSound( cg.refdef.vieworg, 0, CHAN_AUTO, CG_MediaSfx( cgs.media.sfxWeaponUpNoAmmo ),
					cg_volume_effects->value, ATTN_NONE, 0 );
		}
		return qfalse;
	}

	//check we have ammo for it
	if( !cg.frame.playerState.weaponlist[newweapon-1][1] && !cg.frame.playerState.weaponlist[newweapon-1][2] &&
			newweapon != WEAP_GUNBLADE ) {
		if( feedback ) {
			Com_Printf( "No ammo for %s\n", item->pickup_name );
			trap_S_StartSound( cg.refdef.vieworg, 0, CHAN_AUTO, CG_MediaSfx( cgs.media.sfxWeaponUpNoAmmo ),
					cg_volume_effects->value, ATTN_NONE, 0 );
		}
		return qfalse;
	}

	cg.latched_weapon = newweapon;
	trap_Cmd_ExecuteText( EXEC_NOW, va("svuse %s", item->pickup_name ) );
	return qtrue;
}

//=================
//CG_Cmd_Use_f
//=================
void CG_Cmd_Use_f( void )
{
	gitem_t		*item;

	if( cg.demoPlaying )
		return;

	if( cg.frame.playerState.pmove.pm_type == PM_CHASECAM ||
		cg.frame.playerState.pmove.pm_type == PM_DEAD ||
		cg.frame.playerState.pmove.pm_type == PM_SPECTATOR )
		return;

	if( trap_Cmd_Argc() < 2 )
		return;

	item = GS_FindItemByName( trap_Cmd_Args() );
	if( !item ) {
		CG_Printf( "unknown item: %s\n", trap_Cmd_Args() );
		return;
	}

	if( !(item->flags & ITFLAG_USABLE) ) {
		CG_Printf( "%s is not usable.\n", item->pickup_name );
		return;
	}

	if( item->type & IT_WEAPON ) {
		CG_UseWeapon( item->tag, qtrue );
		return;
	}

	trap_Cmd_ExecuteText( EXEC_NOW, va("svuse %s", item->pickup_name ) );
}


void CG_ChasePrev( void );
void CG_ChaseNext( void );
/*
=================
CG_WeapPrev_f
=================
*/
void CG_WeapPrev_f( void )
{
	int			tag;
	int			selected_weapon;

	if( cg.frame.playerState.pmove.pm_type == PM_CHASECAM ) {
		CG_ChasePrev();
		return;
	}

	if( cg.frame.playerState.pmove.pm_type == PM_DEAD )
		return;

	if( cg.demoPlaying )
		return;

	if( cg.latched_weapon == WEAP_NONE ) {
		selected_weapon = cg.frame.playerState.stats[STAT_WEAPON_ITEM];
	} else {
		selected_weapon = cg.latched_weapon;
	}
	if( selected_weapon < WEAP_GUNBLADE || selected_weapon >= WEAP_TOTAL )
		selected_weapon = WEAP_GUNBLADE; // don't get stuck to a loop with invalid weapon data

	tag = selected_weapon;
	tag--;
	if( tag < WEAP_GUNBLADE ) tag = WEAP_TOTAL - 1;
	while( tag != selected_weapon )
	{
		if( CG_UseWeapon( tag, qfalse ) )
			return; // successful

		tag--;
		if( tag < WEAP_GUNBLADE ) 
			tag = WEAP_TOTAL - 1;
	}
}

/*
=================
CG_WeapNext_f
=================
*/
void CG_WeapNext_f( void )
{
	int			tag;
	int			selected_weapon;

	if( cg.frame.playerState.pmove.pm_type == PM_CHASECAM ) {
		CG_ChaseNext();
		return;
	}

	if( cg.frame.playerState.pmove.pm_type == PM_DEAD )
		return;

	if( cg.demoPlaying )
		return;

	if( cg.latched_weapon == WEAP_NONE ) {
		selected_weapon = cg.frame.playerState.stats[STAT_WEAPON_ITEM];
	} else {
		selected_weapon = cg.latched_weapon;
	}
	if( selected_weapon < WEAP_GUNBLADE || selected_weapon >= WEAP_TOTAL )
		selected_weapon = WEAP_GUNBLADE; // don't get stuck to a loop with invalid weapon data

	tag = selected_weapon;
	tag++;
	if( tag >= WEAP_TOTAL ) tag = WEAP_GUNBLADE;
	while( tag != selected_weapon )
	{
		if( CG_UseWeapon( tag, qfalse ) )
			return; // successful

		tag++;
		if( tag >= WEAP_TOTAL )
			tag = WEAP_GUNBLADE;
	}
}

//=================
//CG_NoAmmoWeaponChange
//
// Called only from the ViewWeapon events filter
//=================
void CG_NoAmmoWeaponChange( void )
{
	int				weaptag;
	int				newweapon = WEAP_GUNBLADE;

	if( cg.frame.playerState.pmove.pm_type == PM_DEAD )
		return;

	// check if we're already changing weapon
	if( cg.demoPlaying || cg.frame.playerState.pmove.pm_type == PM_CHASECAM ) {
		if( cg.changing_weapon )
			return;
	} else {
		if( cg.latched_weapon != WEAP_NONE )
			return;
	}

	trap_S_StartSound( cg.refdef.vieworg, 0, CHAN_AUTO, CG_MediaSfx( cgs.media.sfxWeaponUpNoAmmo ),
			cg_volume_effects->value, ATTN_NONE, 0 );

	if( cg.demoPlaying || cg.frame.playerState.pmove.pm_type == PM_CHASECAM ) {
		cg.changing_weapon = qtrue;
		return;
	}

	// in playerstate, GUNBLADE is 0
	for( weaptag = WEAP_TOTAL-1; weaptag > WEAP_NONE; weaptag-- ) // we could ignore the gunblade here, but I prefer the 'if' being visible
	{
		if( !cg.frame.playerState.weaponlist[weaptag-1][0] )	// has the weapon?
			continue;

		if( !cg.frame.playerState.weaponlist[weaptag-1][1] )	// has strong ammo?
			continue;

		if( weaptag != WEAP_GUNBLADE )	{		// gunblade is ignored in strong list
			newweapon = weaptag;
			goto found;
		}
	}

	for( weaptag = WEAP_TOTAL-1; weaptag > WEAP_NONE; weaptag-- )
	{
		if( !cg.frame.playerState.weaponlist[weaptag-1][0] )	// has the weapon?
			continue;

		if( weaptag != WEAP_GUNBLADE )
		{
			if( !cg.frame.playerState.weaponlist[weaptag-1][2] )	// has weak ammo?
				continue;
		}

		newweapon = weaptag;
		goto found;
	}
found:
	{
		CG_UseWeapon( newweapon, qfalse );
	}
}

void CG_CheckWeaponState( void )
{
	if( cg.frame.playerState.pmove.pm_type == PM_CHASECAM || cg.frame.playerState.pmove.pm_type == PM_DEAD ) {
		static int last_weapon = WEAP_NONE;
		if( cg.changing_weapon && last_weapon != cg.frame.playerState.stats[STAT_WEAPON_ITEM] )
			cg.changing_weapon = qfalse;
		last_weapon = cg.frame.playerState.stats[STAT_WEAPON_ITEM];
		cg.latched_weapon = WEAP_NONE;
		return;
	}

	// check if the weapon change is complete
	if( cg.latched_weapon == cg.frame.playerState.stats[STAT_WEAPON_ITEM] )
		cg.latched_weapon = WEAP_NONE;

	// check if we don't have the weapon/ammo we're changing to anymore
	if( cg.latched_weapon != WEAP_NONE ) {
		if( !cg.frame.playerState.weaponlist[cg.latched_weapon-1][0] ||
				(!cg.frame.playerState.weaponlist[cg.latched_weapon-1][1] &&
				!cg.frame.playerState.weaponlist[cg.latched_weapon-1][2] && cg.latched_weapon != WEAP_GUNBLADE) )
			cg.latched_weapon = WEAP_NONE;
	}
}



//======================================================================
//						ViewWeapon
//======================================================================

void CG_AddKickAngles( vec3_t viewangles );

/*
==============
CG_CalcGunOffset
==============
*/
static void CG_CalcGunOffset( vec3_t angles )
{
	int		i;
	float	delta;

	// gun angles from bobbing
	if( cg.bobCycle & 1 ) {
		angles[ROLL] -= cg.xyspeed * cg.bobFracSin * 0.002 * cg_bobRoll->value;
		angles[YAW] -= cg.xyspeed * cg.bobFracSin * 0.002 * cg_bobYaw->value;
	} else {
		angles[ROLL] += cg.xyspeed * cg.bobFracSin * 0.002 * cg_bobRoll->value;
		angles[YAW] += cg.xyspeed * cg.bobFracSin * 0.002 * cg_bobYaw->value;
	}
	angles[PITCH] += cg.xyspeed * cg.bobFracSin * 0.002 * cg_bobPitch->value;

	// gun angles from delta movement
	for( i = 0; i < 3; i++ ) {
		delta = ( cg.player.oldps->viewangles[i] - cg.player.curps->viewangles[i] ) * cg.lerpfrac;
		if( delta > 180 )
			delta -= 360;
		if( delta < -180 )
			delta += 360;
		clamp( delta, -45, 45 );

		
		if( i == YAW )
			angles[ROLL] += 0.001 * delta;
		angles[i] += 0.002 * delta;
	}

	// gun angles from kicks
	if( !cg_damage_kick->integer )
		CG_AddKickAngles( angles );
}

/*
==============
CG_vWeapStartFallKickEff
==============
*/
void CG_vWeapStartFallKickEff( int parms )
{
	int	bouncetime;

	bouncetime = ((parms + 1)*50)+150;
	vweap.fallEff_Time = cg.time + 2*bouncetime;
	vweap.fallEff_rebTime = cg.time + bouncetime;
}

/*
===============
CG_vWeapSetPosition 

  Custom gun position
===============
*/
static void CG_vWeapGetPosition( vec3_t origin, vec3_t axis[3] )
{
	vec3_t			gun_angles;
	vec3_t			forward, right, up;
	float			gunx, guny, gunz;

	// set up gun position
	VectorCopy( cg.refdef.vieworg, origin );
	VectorCopy( cg.refdef.viewangles, gun_angles );

	//offset by client cvars
	gunx = cg_gunx->value;
	guny = cg_guny->value;
	gunz = cg_gunz->value;

	//move hand to the left/center
	if( cg.demoPlaying && !cg_demo_truePOV->integer ) {
		if( hand->integer == 0 )
			gunx += cg_handOffset->value;
		else if( hand->integer == 1 )
			gunx -= cg_handOffset->value;
	} else {
		if( cgs.clientInfo[cg.chasedNum].hand == 0 )
			gunx += cg_handOffset->value;
		else if( cgs.clientInfo[cg.chasedNum].hand == 1 )
			gunx -= cg_handOffset->value;
	}

	//Add fallkick effect
	if( vweap.fallEff_Time > cg.time )
		vweap.fallKick += (vweap.fallEff_rebTime*0.001f - cg.time*0.001f);
	else
		vweap.fallKick = 0;

	guny -= vweap.fallKick;

	//Move the gun
	AngleVectors( gun_angles, forward, right, up );
	VectorMA( origin, gunx, right, origin );
	VectorMA( origin, gunz, forward, origin );
	VectorMA( origin, guny, up, origin );

	//add bobbing
	CG_CalcGunOffset( gun_angles );
	AnglesToAxis( gun_angles, axis );
}

/*
===============
CG_vWeapUpdateProjectionSource
===============
*/
static void CG_vWeapUpdateProjectionSource( vec3_t hand_origin, vec3_t hand_axis[3], vec3_t weap_origin, vec3_t weap_axis[3] )
{
	orientation_t *tag_result = &vweap.projectionSource;
	orientation_t	tag_weapon;

	VectorCopy( vec3_origin, tag_weapon.origin );
	Matrix_Copy( axis_identity, tag_weapon.axis );

	// move to tag_weapon
	CG_MoveToTag( tag_weapon.origin, tag_weapon.axis,
		hand_origin, hand_axis,
		weap_origin, weap_axis );
	
	// move to projectionSource tag
	if( vweap.pweapon.weaponInfo ) {
		VectorCopy( vec3_origin, tag_result->origin );
		Matrix_Copy( axis_identity, tag_result->axis );
		CG_MoveToTag( tag_result->origin, tag_result->axis,
			tag_weapon.origin, tag_weapon.axis,
			vweap.pweapon.weaponInfo->tag_projectionsource.origin, vweap.pweapon.weaponInfo->tag_projectionsource.axis );
		return;
	}

	// fallback: copy gun origin and move it front by 16 units and 8 up
	VectorCopy( tag_weapon.origin, tag_result->origin );
	Matrix_Copy( tag_weapon.axis, tag_result->axis );
	VectorMA( tag_result->origin, 16, tag_result->axis[0], tag_result->origin );
	VectorMA( tag_result->origin, 8, tag_result->axis[2], tag_result->origin );
}

/*
===============
CG_vWeapSetFrame
===============
*/
void CG_vWeapSetFrame( void )
{

	vweap.oldframe = vweap.frame;
	vweap.frame++;
	
	//looping
	if (vweap.frame > vweap.pweapon.weaponInfo->lastframe[vweap.currentAnim])
	{
		if (vweap.pweapon.weaponInfo->loopingframes[vweap.currentAnim]) {
			vweap.frame = (vweap.pweapon.weaponInfo->lastframe[vweap.currentAnim] - (vweap.pweapon.weaponInfo->loopingframes[vweap.currentAnim] - 1));
		}
		else if (!vweap.newAnim)
			vweap.newAnim = VWEAP_STANDBY;
	}

	//new animation
	if ( vweap.newAnim )
	{
		if ( vweap.newAnim == VWEAP_WEAPONUP ) //weapon change
		{
			vweap.pweapon.weaponInfo = vweap.newWeaponInfo;
			vweap.oldframe = vweap.pweapon.weaponInfo->firstframe[vweap.newAnim];//don't lerp
		}
		vweap.currentAnim = vweap.newAnim;
		vweap.frame = vweap.pweapon.weaponInfo->firstframe[vweap.newAnim];
		vweap.newAnim = 0;
	}
}


/*
===============
CG_vWeapUpdateAnimation
===============
*/
void CG_vWeapUpdateAnimation( void )
{
	if (cg.time > vweap.nextframetime)
	{
		vweap.backlerp = 1.0f;

		CG_vWeapSetFrame ();//the model can change at this point

		vweap.prevframetime = cg.time;
		vweap.nextframetime = cg.time + vweap.pweapon.weaponInfo->frametime[vweap.currentAnim];
			
	} else {
		
		vweap.backlerp = 1.0f - ((cg.time - vweap.prevframetime)/(vweap.nextframetime - vweap.prevframetime));
		if (vweap.backlerp > 1)
			vweap.backlerp = 1.0f;
		else if (vweap.backlerp < 0)
			vweap.backlerp = 0;
	}
}

/*
==================
CG_vWeapUpdateState

  Called each new serverframe
==================
*/
void CG_vWeapUpdateState( void )
{
	int i;
	centity_t		*cent;
	int				torsoNewAnim;

	cent = &cg_entities[cg.chasedNum+1]; // player in POV
	if( cent->serverFrame != cg.frame.serverFrame ) {
		vweap.state = NULL;
		return;
	}
	vweap.state = &cent->current;	//store the current entity state for later access
	
	// no weapon to draw
	if( !vweap.state->weapon || vweap.state->effects & EF_CORPSE ) {
		vweap.pweapon.weaponInfo = NULL;
		return;
	}

	//update newweapon info
	vweap.newWeaponInfo = CG_GetWeaponFromPModelIndex( &cg_entPModels[cg.chasedNum+1], vweap.state->weapon );

	//Update animations based on Torso

	//filter repeated animations coming from game
	torsoNewAnim = (cent->current.frame>>6 &0x3F) * ((cent->current.frame>>6 &0x3F) != (cent->prev.frame>>6 &0x3F));

	if (torsoNewAnim == TORSO_FLIPOUT && vweap.newAnim < VWEAP_WEAPDOWN)
		vweap.newAnim = VWEAP_WEAPDOWN;

	//Update based on Events
	for ( i = 0; i < 2; i++ ) {

		switch ( vweap.state->events[i] )
		{	
			case EV_FALL:
				CG_vWeapStartFallKickEff( vweap.state->eventParms[i] );
				break;

			case EV_PAIN:
				//add damage kickangles?
				break;

			case EV_JUMP:
				//add some kind of jumping angles?
				break;

			case EV_JUMP_PAD:
				//add jumpad kickangles?
				break;

			case EV_MUZZLEFLASH:
				//WEAK
				if( vweap.state->eventParms[i] == FIRE_MODE_WEAK && vweap.newAnim < VWEAP_ATTACK_WEAK )
				{
					vweap.newAnim = VWEAP_ATTACK_WEAK;
					
					//activate flash
					if( vweap.state->weapon != WEAP_GUNBLADE ) { // gunblade knife doesn't flash
						if (cg_weaponFlashes->integer == 2 && vweap.pweapon.weaponInfo)
							//vweap.pweapon.flashtime = cg.time + (int)((vweap.pweapon.weaponInfo->frametime[VWEAP_ATTACK_WEAK]/4)*3);
							vweap.pweapon.flashtime = cg.time + (int)vweap.pweapon.weaponInfo->frametime[VWEAP_ATTACK_WEAK];
					}
				}
				//STRONG
				else if( vweap.state->eventParms[i] == FIRE_MODE_STRONG && vweap.newAnim < VWEAP_ATTACK_STRONG )
				{
					vweap.newAnim = VWEAP_ATTACK_STRONG;

					//activate flash
					if (cg_weaponFlashes->integer == 2 && vweap.pweapon.weaponInfo)
						//vweap.pweapon.flashtime = cg.time + (int)((vweap.pweapon.weaponInfo->frametime[VWEAP_ATTACK_STRONG]/4)*3);
						vweap.pweapon.flashtime = cg.time + (int)vweap.pweapon.weaponInfo->frametime[VWEAP_ATTACK_STRONG];
				}

				//eject brass-debris
				if (cg_ejectBrass->integer && cg_ejectBrass->integer < 3 && vweap.pweapon.weaponInfo && vweap.active) {
					vec3_t origin;
					vec3_t	forward, right, up;
					
					VectorCopy( cg.refdef.vieworg, origin );
					AngleVectors( cg.refdef.viewangles, forward, right, up );
					//move it a bit fordward and up
					VectorMA( origin, 16, forward, origin );
					VectorMA( origin, 4, up, origin );
					if( cgs.clientInfo[cg.chasedNum].hand == 0)
						VectorMA( origin, 8, right, origin );
					else if( cgs.clientInfo[cg.chasedNum].hand == 1)
						VectorMA( origin, -4, right, origin );				
				}

				break;
					
			case EV_DROP:
				break;

			case EV_WEAPONUP:
				vweap.newAnim = VWEAP_WEAPONUP;//is top priority
				break;
		}
	}

	//remove when there is no hand model, so it tries to reboot
	if (vweap.pweapon.weaponInfo && !vweap.pweapon.weaponInfo->model[HAND])
		vweap.pweapon.weaponInfo = NULL;

	//Init
	if (!vweap.pweapon.weaponInfo && vweap.newWeaponInfo)
	{
		vweap.newAnim = 0;

		if (vweap.newWeaponInfo->model[HAND])
		{
			vweap.nextframetime = cg.time;//don't wait for next frame 
			vweap.pweapon.weaponInfo = vweap.newWeaponInfo;

			if ( !vweap.newAnim )
				vweap.currentAnim = VWEAP_STANDBY;
			else
				vweap.currentAnim = vweap.newAnim;

			vweap.frame = vweap.pweapon.weaponInfo->firstframe[vweap.currentAnim];
			vweap.oldframe = vweap.frame;//don't lerp
		}

		return;
	}

	//if showing the wrong weapon, fix. (It happens in chasecam when changing POV)
	if ((vweap.pweapon.weaponInfo && vweap.newWeaponInfo) 
		&& (vweap.pweapon.weaponInfo != vweap.newWeaponInfo) )
	{
		if ( (vweap.newAnim != VWEAP_WEAPONUP) && (vweap.currentAnim != VWEAP_WEAPDOWN)
			&& (vweap.newWeaponInfo->model[HAND]) )
		{
			if (cg_debugWeaponModels->integer)
				CG_Printf ("fixing wrong viewWeapon\n");

			if ( !vweap.currentAnim )
			{
				if ( !vweap.newAnim )
					vweap.currentAnim = VWEAP_WEAPONUP;
				else
					vweap.currentAnim = vweap.newAnim;
			}

			vweap.nextframetime = cg.time;//don't wait for next frame 
			vweap.pweapon.weaponInfo = vweap.newWeaponInfo;
			vweap.frame = vweap.pweapon.weaponInfo->firstframe[vweap.currentAnim];
			vweap.oldframe = vweap.frame;//don't lerp
		}
	}
}

static entity_t	gun;	// hand model

/*
==============
CG_CalcViewWeapon
==============
*/
void CG_CalcViewWeapon( void )
{
	orientation_t	tag;

	// gun disabled
	if( !vweap.active || !vweap.state )
		return;

	//remove if player in POV has changed
	if( vweap.state->number != cg.chasedNum+1 )
		vweap.pweapon.weaponInfo = NULL;

	if( !vweap.pweapon.weaponInfo )
		return;

	if( !vweap.pweapon.weaponInfo->model[HAND] )
		return;

	//setup
	CG_vWeapUpdateAnimation();
	CG_vWeapGetPosition( vweap.origin, vweap.axis );
	
	//hand entity
	memset( &gun, 0, sizeof(gun) );
	gun.model = vweap.pweapon.weaponInfo->model[HAND];

	//if the player doesn't want to view the weapon we still have to build the projection source
	if( CG_GrabTag( &tag, &gun, "tag_weapon" ) )
		CG_vWeapUpdateProjectionSource( vweap.origin, vweap.axis, tag.origin, tag.axis );
	else
		CG_vWeapUpdateProjectionSource( vweap.origin, vweap.axis, vec3_origin, axis_identity );
}
/*
==============
CG_AddViewWeapon
==============
*/
void CG_AddViewWeapon( void )
{
	orientation_t	tag;

	// gun disabled
	if( !vweap.active || !vweap.state )
		return;

	//remove if player in POV has changed
	if( vweap.state->number != cg.chasedNum+1 )
		vweap.pweapon.weaponInfo = NULL;

	if( !vweap.pweapon.weaponInfo )
		return;

	if( !vweap.pweapon.weaponInfo->model[HAND] )
		return;

	if( !cg_gun->integer )
		return;
	
	//hand entity
	gun.model = vweap.pweapon.weaponInfo->model[HAND];

	//update the position
	VectorCopy( vweap.origin, gun.origin );
	VectorCopy( vweap.origin, gun.oldorigin );
	VectorCopy( vweap.origin, gun.lightingOrigin );
	Matrix_Copy( vweap.axis, gun.axis );

	gun.flags = RF_MINLIGHT|RF_WEAPONMODEL;
	gun.scale = 1.0f;
	gun.frame = vweap.frame;
	gun.oldframe = vweap.oldframe;
	gun.backlerp = vweap.backlerp;

	CG_AddEntityToScene( &gun );
	CG_AddColoredOutLineEffect( &gun, cg.effects, 0, 0, 0, 255 );
	CG_AddShellEffects( &gun, cg.effects );

	// add attached weapon
	if( CG_GrabTag( &tag, &gun, "tag_weapon" ) )
		CG_AddWeaponOnTag( &gun, &tag, &vweap.pweapon, cg.effects|EF_OUTLINE, NULL );
}

