//--------------------------------------------------------------------------------
// Purpose : Draw tick marks between start and end position of the given distance
//			 with text every tickTextDist steps apart. 
//--------------------------------------------------------------------------------
void NDebugOverlay::DrawTickMarkedLine(const Vector &startPos, const Vector &endPos, float tickDist, int tickTextDist, int r, int g, int b, bool noDepthTest, float duration )
{
	CBasePlayer* pPlayer = GetDebugPlayer();

	if ( !pPlayer ) 
		return;
	
	Vector	lineDir		= (endPos - startPos);
	float	lineDist	= VectorNormalize( lineDir );
	int		numTicks	= lineDist/tickDist;
	Vector	vBodyDir;
	
#if defined( CLIENT_DLL )
	AngleVectors( pPlayer->LocalEyeAngles(), &vBodyDir );
#else
	vBodyDir = pPlayer->BodyDirection2D( );
#endif

	Vector  upVec		= 4*vBodyDir;
	Vector	sideDir;
	Vector	tickPos		= startPos;
	int		tickTextCnt = 0;

	CrossProduct(lineDir, upVec, sideDir);

	// First draw the line
	Line(startPos, endPos, r,g,b,noDepthTest,duration);

	// Now draw the ticks
	for (int i=0;i<numTicks+1;i++)
	{
		// Draw tick mark
		Vector tickLeft	 = tickPos - sideDir;
		Vector tickRight = tickPos + sideDir;
		
		// Draw tick mark text
		if (tickTextCnt == tickTextDist)
		{
			char text[25];
			Q_snprintf(text,sizeof(text),"%i",i);
			Vector textPos = tickLeft + Vector(0,0,8);
			Line(tickLeft, tickRight, 255,255,255,noDepthTest,duration);
			Text( textPos, text, true, 0 );
			tickTextCnt = 0;
		}
		else
		{
			Line(tickLeft, tickRight, r,g,b,noDepthTest,duration);
		}
		
		tickTextCnt++;

		tickPos = tickPos + (tickDist * lineDir);
	}
}
//--------------------------------------------------------------------------------
// Purpose : Draw tick marks between start and end position of the given distance
//			 with text every tickTextDist steps apart. 
// Input   :
// Output  :
//--------------------------------------------------------------------------------
void NDebugOverlay::DrawTickMarkedLine(const Vector &startPos, const Vector &endPos, float tickDist, int tickTextDist, int r, int g, int b, bool noDepthTest, float duration )
{
	CBasePlayer* pPlayer = UTIL_PlayerByIndex(CBaseEntity::m_nDebugPlayer);

	if (!pPlayer) 
	{
		return;
	}
	

	Vector	lineDir		= (endPos - startPos);
	float	lineDist	= VectorNormalize( lineDir );
	int		numTicks	= lineDist/tickDist;
	Vector	vBodyDir	= pPlayer->BodyDirection2D( );
	Vector  upVec		= 4*vBodyDir;
	Vector	sideDir;
	Vector	tickPos		= startPos;
	int		tickTextCnt = 0;

	CrossProduct(lineDir, upVec, sideDir);

	// First draw the line
	NDebugOverlay::Line(startPos, endPos, r,g,b,noDepthTest,duration);

	// Now draw the ticks
	for (int i=0;i<numTicks+1;i++)
	{
		// Draw tick mark
		Vector tickLeft	 = tickPos - sideDir;
		Vector tickRight = tickPos + sideDir;
		
		// Draw tick mark text
		if (tickTextCnt == tickTextDist)
		{
			char text[25];
			Q_snprintf(text,sizeof(text),"%i",i);
			Vector textPos = tickLeft + Vector(0,0,8);
			NDebugOverlay::Line(tickLeft, tickRight, 255,255,255,noDepthTest,duration);
			NDebugOverlay::Text( textPos, text, true, 0 );
			tickTextCnt = 0;
		}
		else
		{
			NDebugOverlay::Line(tickLeft, tickRight, r,g,b,noDepthTest,duration);
		}
		tickTextCnt++;

		tickPos = tickPos + (tickDist * lineDir);
	}
}
	void CBaseSDKGrenade::DropGrenade()
	{
		CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
		if ( !pPlayer )
		{
			Assert( false );
			return;
		}

		// BUGBUG: Hardcoded grenade width of 4 - better not change the model :)
		Vector vecSrc;
		pPlayer->CollisionProp()->NormalizedToWorldSpace( Vector( 0.5f, 0.5f, 0.0f ), &vecSrc );
		vecSrc.z += GRENADE_RADIUS;

		Vector vecFacing = pPlayer->BodyDirection2D( );
		// no up/down direction
		vecFacing.z = 0;
		VectorNormalize( vecFacing );
		trace_t tr;
		UTIL_TraceLine( vecSrc, vecSrc - Vector(0,0,16), MASK_PLAYERSOLID, pPlayer, COLLISION_GROUP_NONE, &tr );
		if ( tr.fraction != 1.0 )
		{
			// compute forward vec parallel to floor plane and roll grenade along that
			Vector tangent;
			CrossProduct( vecFacing, tr.plane.normal, tangent );
			CrossProduct( tr.plane.normal, tangent, vecFacing );
		}
		vecSrc += (vecFacing * 18.0);
		CheckThrowPosition( pPlayer, pPlayer->WorldSpaceCenter(), vecSrc );

		Vector vecThrow;
		pPlayer->GetVelocity( &vecThrow, NULL );
		vecThrow += vecFacing * 300;
		// put it on its side
		QAngle orientation(0,pPlayer->GetLocalAngles().y,-90);
		// roll it
		AngularImpulse rotSpeed(0,0,320);

		EmitGrenade( vecSrc, orientation, vecThrow, rotSpeed, pPlayer, this );

		m_bRedraw = true;
		m_fThrowTime = 0.0f;
	}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CWeaponGaussGun::ChargedFire()
{
	if ( InGameRules()->IsMultiplayer() )
	{
	}

	CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
	
	if ( !pOwner )
		return;

	bool penetrated = false;

	//Play shock sounds
	WeaponSound( SINGLE );
	WeaponSound( SPECIAL2 );

	SendWeaponAnim( ACT_VM_SECONDARYATTACK );
	StopChargeSound();

	m_bCharging = false;
	m_bChargeIndicated = false;

	m_flNextPrimaryAttack	= gpGlobals->curtime + 0.2f;
	m_flNextSecondaryAttack = gpGlobals->curtime + 0.5f;

	//Shoot a shot straight out
	Vector	startPos= pOwner->Weapon_ShootPosition();
	Vector	aimDir	= pOwner->GetAutoaimVector( AUTOAIM_5DEGREES );
	Vector	endPos	= startPos + ( aimDir * MAX_TRACE_LENGTH );
	
	trace_t	tr;
	UTIL_TraceLine( startPos, endPos, MASK_SHOT, pOwner, COLLISION_GROUP_NONE, &tr );
	
#ifndef CLIENT_DLL

	ClearMultiDamage();

	//Find how much damage to do
	float flChargeAmount = ( gpGlobals->curtime - m_flChargeStartTime ) / MAX_GAUSS_CHARGE_TIME;

	//Clamp this
	if ( flChargeAmount > 1.0f )
		flChargeAmount = 1.0f;

	//Determine the damage amount
	float flDamage = sk_plr_dmg_gauss.GetFloat() + ( ( sk_plr_max_dmg_gauss.GetFloat() - sk_plr_dmg_gauss.GetFloat() ) * flChargeAmount );

#endif

	CBaseEntity *pHit = tr.m_pEnt;

	if ( tr.DidHitWorld() )
	{
		//Try wall penetration
		UTIL_ImpactTrace( &tr, GetAmmoDef()->DamageType(m_iPrimaryAmmoType), "ImpactGauss" );
		UTIL_DecalTrace( &tr, "RedGlowFade" );

		CPVSFilter filter( tr.endpos );
		te->GaussExplosion( filter, 0.0f, tr.endpos, tr.plane.normal, 0 );
		
		Vector	testPos = tr.endpos + ( aimDir * 48.0f );

		UTIL_TraceLine( testPos, tr.endpos, MASK_SHOT, pOwner, COLLISION_GROUP_NONE, &tr );
			
		if ( tr.allsolid == false )
		{
			UTIL_DecalTrace( &tr, "RedGlowFade" );

			penetrated = true;
		}
	}

#ifndef CLIENT_DLL
	else if ( pHit != NULL )
	{
		CTakeDamageInfo dmgInfo( this, pOwner, flDamage, DMG_SHOCK | DMG_DISSOLVE );
		CalculateBulletDamageForce( &dmgInfo, m_iPrimaryAmmoType, aimDir, tr.endpos );

		//Do direct damage to anything in our path
		pHit->DispatchTraceAttack( dmgInfo, aimDir, &tr );
	}

	ApplyMultiDamage();
#endif

	UTIL_ImpactTrace( &tr, GetAmmoDef()->DamageType(m_iPrimaryAmmoType), "ImpactGauss" );

	QAngle	viewPunch;

	viewPunch.x = random->RandomFloat( -4.0f, -8.0f );
	viewPunch.y = random->RandomFloat( -0.25f,  0.25f );
	viewPunch.z = 0;

	pOwner->ViewPunch( viewPunch );

	DrawBeam( startPos, tr.endpos, 25, true );

#ifndef CLIENT_DLL
	Vector	recoilForce = pOwner->BodyDirection2D() * -( flDamage * 10.0f );
	recoilForce[2] += 300.0f;//128

	pOwner->ApplyAbsVelocityImpulse( recoilForce );
#endif

	CPVSFilter filter( tr.endpos );
	te->GaussExplosion( filter, 0.0f, tr.endpos, tr.plane.normal, 0 );

#ifndef CLIENT_DLL
	if ( penetrated == true )
		RadiusDamage( CTakeDamageInfo( this, this, flDamage, DMG_SHOCK ), tr.endpos, 200.0f, CLASS_NONE, NULL );

	// Register a muzzleflash for the AI
	pOwner->SetMuzzleFlashTime( gpGlobals->curtime + 0.5 );
#endif
}