//---------------------------------------------------------
//---------------------------------------------------------
void C_ASW_TeslaTrap::UpdateEffects( void )
{
	//m_iTrapState = iState;
	if ( !m_hEffects && m_bAssembled )
	{
		Vector vecOrigin;
		QAngle vecAngles;
		// Get the muzzle origin
		if ( !GetAttachment( "effects", vecOrigin, vecAngles ) )
		{
			vecOrigin = GetAbsOrigin();
			vecAngles = QAngle( 0, 0, 0 );
		}

		m_hEffects = ParticleProp()->Create( "tesla_trap_fx", PATTACH_ABSORIGIN_FOLLOW, -1, vecOrigin - GetAbsOrigin() );

		if ( m_hEffects )
		{
			//m_hEffects->SetSortOrigin( vecOrigin );
			//m_hEffects->SetControlPoint( 0, vecOrigin );
			Vector vecForward, vecRight, vecUp;
			AngleVectors( vecAngles, &vecForward, &vecRight, &vecUp );
			m_hEffects->SetControlPointOrientation( 0, vecForward, vecRight, vecUp );
		}
	}
	
	if ( m_hEffects )
	{
		switch( m_iTrapState )
		{
		case TESLATRAP_STATE_DORMANT:
			// off
			m_hEffects->SetControlPoint( 1, Vector( 0, 0, 0 ) );
			//UpdateLight( false, 0, 0, 0, 0 );
			break;

		case TESLATRAP_STATE_DEPLOY:
			// setting up (blue, no ring)
			m_hEffects->SetControlPoint( 1, Vector( 0, 0, 0 ) );
			//UpdateLight( true, 0, 0, 255, 190 );
			break;

		case TESLATRAP_STATE_CHARGING:
			{
				// searching (green glow, red ring)
				// TODO: fix this hardcoded recharge time limit
				// 3 seconds hardcoded charge time, plus extra time so the scale pops to full from charging so the state is more obvious
				float flAmount = 1.0f - ((m_flNextFullChargeTime - gpGlobals->curtime) / (3.0f * 1.5f) );
				m_hEffects->SetControlPoint( 1, Vector( flAmount, flAmount, 0 ) );
				//UpdateLight( false, 0, 255, 0, 255 );
				break;
			}

		case TESLATRAP_STATE_CHARGED:
			// found poetntial enemy (red glow, red ring)
			m_hEffects->SetControlPoint( 1, Vector( 1, 1, 0 ) );
			//UpdateLight( false, 255, 0, 0, 255 );
			break;

		default:
			DevMsg("**Unknown Trap State: %d\n", m_iTrapState );
			break;
		}
	}
}
bool CFlashlightEffect::ComputeLightPosAndOrientation( const Vector &vecPos, const Vector &vecForward, const Vector &vecRight, const Vector &vecUp,
														Vector& vecFinalPos, Quaternion& quatOrientation, bool bTracePlayers )
{
	const float flEpsilon = 0.1f;			// Offset flashlight position along vecUp
	float flDistCutoff = r_flashlighttracedistcutoff.GetFloat();
	const float flDistDrag = 0.2;
	bool bDebugVis = r_flashlightvisualizetrace.GetBool();

	C_BasePlayer *pPlayer = UTIL_PlayerByIndex( m_nEntIndex );
	if ( !pPlayer )
	{

		pPlayer = C_BasePlayer::GetLocalPlayer();

		if ( !pPlayer )
		{
			Assert( false );
			return false;
		}
	}

	// We will lock some of the flashlight params if player is on a ladder, to prevent oscillations due to the trace-rays
	bool bPlayerOnLadder = ( pPlayer->GetMoveType() == MOVETYPE_LADDER );

	CTraceFilterSkipPlayerAndViewModel traceFilter( pPlayer, bTracePlayers );

	//	Vector vOrigin = vecPos + r_flashlightoffsety.GetFloat() * vecUp;
	Vector vecOffset;
	pPlayer->GetFlashlightOffset( vecForward, vecRight, vecUp, &vecOffset );
	Vector vOrigin = vecPos + vecOffset;

	// Not on ladder...trace a hull
	if ( !bPlayerOnLadder ) 
	{
		Vector vecPlayerEyePos = pPlayer->GetRenderOrigin() + pPlayer->GetViewOffset();

		trace_t pmOriginTrace;
		UTIL_TraceHull( vecPlayerEyePos, vOrigin, Vector(-2, -2, -2), Vector(2, 2, 2), ( MASK_SOLID & ~(CONTENTS_HITBOX) ) | CONTENTS_WINDOW | CONTENTS_GRATE, &traceFilter, &pmOriginTrace );//1

		if ( bDebugVis )
		{
			debugoverlay->AddBoxOverlay( pmOriginTrace.endpos, Vector( -2, -2, -2 ), Vector( 2, 2, 2 ), QAngle( 0, 0, 0 ), 0, 255, 0, 16, 0 );
			if ( pmOriginTrace.DidHit() || pmOriginTrace.startsolid )
			{
				debugoverlay->AddLineOverlay( pmOriginTrace.startpos, pmOriginTrace.endpos, 255, 128, 128, true, 0 );
			}
			else
			{
				debugoverlay->AddLineOverlay( pmOriginTrace.startpos, pmOriginTrace.endpos, 255, 0, 0, true, 0 );
			}
		}

		if ( pmOriginTrace.DidHit() || pmOriginTrace.startsolid )
		{
			vOrigin = pmOriginTrace.endpos;
		}
		else
		{
			if ( pPlayer->m_vecFlashlightOrigin != vecPlayerEyePos )
			{
				vOrigin = vecPos;
			}
		}
	}
	else // on ladder...skip the above hull trace
	{
		vOrigin = vecPos;
	}

	// Now do a trace along the flashlight direction to ensure there is nothing within range to pull back from
	int iMask = MASK_OPAQUE_AND_NPCS;
	iMask &= ~CONTENTS_HITBOX;
	iMask |= CONTENTS_WINDOW | CONTENTS_GRATE | CONTENTS_IGNORE_NODRAW_OPAQUE;

	Vector vTarget = vOrigin + vecForward * r_flashlightfar.GetFloat();

	// Work with these local copies of the basis for the rest of the function
	Vector vDir   = vTarget - vOrigin;
	Vector vRight = vecRight;
	Vector vUp    = vecUp;
	VectorNormalize( vDir   );
	VectorNormalize( vRight );
	VectorNormalize( vUp    );

	// Orthonormalize the basis, since the flashlight texture projection will require this later...
	vUp -= DotProduct( vDir, vUp ) * vDir;
	VectorNormalize( vUp );
	vRight -= DotProduct( vDir, vRight ) * vDir;
	VectorNormalize( vRight );
	vRight -= DotProduct( vUp, vRight ) * vUp;
	VectorNormalize( vRight );

	AssertFloatEquals( DotProduct( vDir, vRight ), 0.0f, 1e-3 );
	AssertFloatEquals( DotProduct( vDir, vUp    ), 0.0f, 1e-3 );
	AssertFloatEquals( DotProduct( vRight, vUp  ), 0.0f, 1e-3 );

	trace_t pmDirectionTrace;
	UTIL_TraceHull( vOrigin, vTarget, Vector( -1.5, -1.5, -1.5 ), Vector( 1.5, 1.5, 1.5 ), iMask, &traceFilter, &pmDirectionTrace );//.5

	if ( bDebugVis )
	{
		debugoverlay->AddBoxOverlay( pmDirectionTrace.endpos, Vector( -4, -4, -4 ), Vector( 4, 4, 4 ), QAngle( 0, 0, 0 ), 0, 0, 255, 16, 0 );
		debugoverlay->AddLineOverlay( vOrigin, pmDirectionTrace.endpos, 255, 0, 0, false, 0 );
	}

	float flTargetPullBackDist = 0.0f;
	float flDist = (pmDirectionTrace.endpos - vOrigin).Length();

	if ( flDist < flDistCutoff )
	{
		// We have an intersection with our cutoff range
		// Determine how far to pull back, then trace to see if we are clear
		float flPullBackDist = bPlayerOnLadder ? r_flashlightladderdist.GetFloat() : flDistCutoff - flDist;	// Fixed pull-back distance if on ladder

		flTargetPullBackDist = flPullBackDist;

		if ( !bPlayerOnLadder )
		{
			trace_t pmBackTrace;
			// start the trace away from the actual trace origin a bit, to avoid getting stuck on small, close "lips"
			UTIL_TraceHull( vOrigin - vDir * ( flDistCutoff * r_flashlightbacktraceoffset.GetFloat() ), vOrigin - vDir * ( flPullBackDist - flEpsilon ),
				Vector( -1.5f, -1.5f, -1.5f ), Vector( 1.5f, 1.5f, 1.5f ), iMask, &traceFilter, &pmBackTrace );

			if ( bDebugVis )
			{
				debugoverlay->AddLineOverlay( pmBackTrace.startpos, pmBackTrace.endpos, 255, 0, 255, true, 0 );
			}

			if( pmBackTrace.DidHit() )
			{
				// We have an intersection behind us as well, so limit our flTargetPullBackDist
				float flMaxDist = (pmBackTrace.endpos - vOrigin).Length() - flEpsilon;
				flTargetPullBackDist = MIN( flMaxDist, flTargetPullBackDist );
				//m_flCurrentPullBackDist = MIN( flMaxDist, m_flCurrentPullBackDist );	// possible pop
			}
		}
	}

	if ( bDebugVis )
	{
		// visualize pullback
		debugoverlay->AddBoxOverlay( vOrigin - vDir * m_flCurrentPullBackDist, Vector( -2, -2, -2 ), Vector( 2, 2, 2 ), QAngle( 0, 0, 0 ), 255, 255, 0, 16, 0 );
		debugoverlay->AddBoxOverlay( vOrigin - vDir * flTargetPullBackDist, Vector( -1, -1, -1 ), Vector( 1, 1, 1 ), QAngle( 0, 0, 0 ), 128, 128, 0, 16, 0 );
	}

	m_flCurrentPullBackDist = Lerp( flDistDrag, m_flCurrentPullBackDist, flTargetPullBackDist );
	m_flCurrentPullBackDist = MIN( m_flCurrentPullBackDist, flDistCutoff );	// clamp to max pullback dist
	vOrigin = vOrigin - vDir * m_flCurrentPullBackDist;

	vecFinalPos = vOrigin;
	BasisToQuaternion( vDir, vRight, vUp, quatOrientation );

	return true;
}
	C_RotatingPickup() {
		ClientRotAng = QAngle(45,0,0);
		m_bRespawning = m_bRespawning_Cache = false;
	}
void CWeapon357::PrimaryAttack( void )
{
	// Only the player fires this way so we can cast
	CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );

	if ( !pPlayer )
	{
		return;
	}

	if ( m_iClip1 <= 0 )
	{
		if ( !m_bFireOnEmpty )
		{
			Reload();
		}
		else
		{
			WeaponSound( EMPTY );
			m_flNextPrimaryAttack = 0.15;
		}

		return;
	}

	m_flNextPrimaryAttack = gpGlobals->curtime + 0.75;
	m_flNextSecondaryAttack = gpGlobals->curtime + 0.75;

	m_iPrimaryAttacks++;
	gamestats->Event_WeaponFired( pPlayer, true, GetClassname() );

	WeaponSound( SINGLE );
	pPlayer->DoMuzzleFlash();

	SendWeaponAnim( ACT_VM_PRIMARYATTACK );
	pPlayer->SetAnimation( PLAYER_ATTACK1 );

	if (GetWpnData().m_bUseMuzzleSmoke)
	{
		DispatchParticleEffect("weapon_muzzle_smoke", PATTACH_POINT_FOLLOW, pPlayer->GetViewModel(), "muzzle", true);
	}

	m_flNextPrimaryAttack = gpGlobals->curtime + 0.75;
	m_flNextSecondaryAttack = gpGlobals->curtime + 0.75;

	m_iClip1--;

	Vector vecSrc		= pPlayer->Weapon_ShootPosition();
	Vector vecAiming	= pPlayer->GetAutoaimVector( AUTOAIM_SCALE_DEFAULT );	

	pPlayer->FireBullets( 1, vecSrc, vecAiming, vec3_origin, MAX_TRACE_LENGTH, m_iPrimaryAmmoType, 0 );

	pPlayer->SetMuzzleFlashTime( gpGlobals->curtime + 0.5 );

	//Disorient the player
	QAngle angles = pPlayer->GetLocalAngles();

	angles.x += random->RandomInt( -1, 1 );
	angles.y += random->RandomInt( -1, 1 );
	angles.z = 0;

	pPlayer->SnapEyeAngles( angles );

	pPlayer->ViewPunch( QAngle( -8, random->RandomFloat( -2, 2 ), 0 ) );

	CSoundEnt::InsertSound( SOUND_COMBAT, GetAbsOrigin(), 600, 0.2, GetOwner() );

	if ( !m_iClip1 && pPlayer->GetAmmoCount( m_iPrimaryAmmoType ) <= 0 )
	{
		// HEV suit - indicate out of ammo condition
		pPlayer->SetSuitUpdate( "!HEV_AMO0", FALSE, 0 ); 
	}
}
Beispiel #5
0
// this is the think that flips the weapon into the world when it is spawned
void CASW_Laser_Mine::SpawnFlipThink()
{
	// we are still flagged as spawn flipping in the air
	if ( m_bIsSpawnFlipping == false )
	{
		// we get here if we spawned, but haven't started spawn flipping yet, please try again!
		SetContextThink( &CASW_Laser_Mine::SpawnFlipThink, gpGlobals->curtime, s_pLaserMineSpawnFlipThink );		
		return;
	}

	// when we should hit the ground
	float flEndTime = m_flSpawnFlipEndTime;

	// the total time it takes for us to flip
	float flFlipTime = flEndTime - m_flSpawnFlipStartTime;
	float flFlipProgress = ( gpGlobals->curtime - m_flSpawnFlipStartTime ) / flFlipTime;
	flFlipProgress = clamp( flFlipProgress, 0.0f, 2.5f );

	if ( !m_bIsSpawnLanded )
	{
		// high gravity, it looks more satisfying
		float flGravity = 2200;

		float flInitialZVelocity = (m_vecSpawnFlipEndPos.z - m_vecSpawnFlipStartPos.z)/flFlipTime + (flGravity/2) * flFlipTime;
		float flZVelocity = flInitialZVelocity - flGravity * (gpGlobals->curtime - m_flSpawnFlipStartTime);

		float flXDiff = (m_vecSpawnFlipEndPos.x - m_vecSpawnFlipStartPos.x) / flFlipTime;
		float flYDiff = (m_vecSpawnFlipEndPos.y - m_vecSpawnFlipStartPos.y) / flFlipTime;

		Vector vecVelocity( flXDiff, flYDiff, flZVelocity );

		SetAbsVelocity( vecVelocity );

		// angular velocity
		QAngle angCurAngVel = GetLocalAngularVelocity();
		float flXAngDiff = 360 / flFlipTime;
		// keep the Y angular velocity that was given to it at the start (it's random)
		SetLocalAngularVelocity( QAngle( flXAngDiff, angCurAngVel.y, 0 ) );
	}

	if ( flFlipProgress >= 1.0f )
	{
		if ( !m_bIsSpawnLanded )
		{
			Vector vecVelStop( 0,0,0 );
			SetAbsVelocity( vecVelStop );

			SetAbsOrigin( m_vecSpawnFlipEndPos );


			QAngle angVel( 0, 0, 0 );
			SetLocalAngularVelocity( angVel );
			/*
			// get the current angles of the item so we can use them to determine the final angles
			QAngle angPrevAngles = GetAbsAngles();
			float flYAngles = angPrevAngles.y;
			QAngle angFlat( 0, flYAngles, 0 );
			*/
			SetAbsAngles( m_angSpawnFlipEndAngle );

			EmitSound("ASW_Laser_Mine.Lay");

			m_bIsSpawnLanded = true;
		}

		if ( flFlipProgress >= 2.5f )
		{
			SetContextThink( NULL, 0, s_pLaserMineSpawnFlipThink );

			EmitSound("ASW_Mine.Lay");

			m_bMineActive = true;
			return;
		}
	}

	SetContextThink( &CASW_Laser_Mine::SpawnFlipThink, gpGlobals->curtime, s_pLaserMineSpawnFlipThink );
}
// apply custom pitch to bone merge
void CASW_Bone_Merge_Cache::MergeMatchingBones( int boneMask, CBoneBitList &boneComputed, bool bOverrideDirection, const Vector &vecDir )
{
	UpdateCache();

	// If this is set, then all the other cache data is set.
	if ( !m_pOwnerHdr || m_MergedBones.Count() == 0 )
		return;

	// Have the entity we're following setup its bones.
	m_pFollow->SetupBones( NULL, -1, m_nFollowBoneSetupMask, gpGlobals->curtime );

	matrix3x4_t matPitchUp;
	AngleMatrix( QAngle( asw_weapon_pitch.GetFloat(), 0, 0 ), matPitchUp );

	// Now copy the bone matrices.
	for ( int i=0; i < m_MergedBones.Count(); i++ )
	{
		int iOwnerBone = m_MergedBones[i].m_iMyBone;
		int iParentBone = m_MergedBones[i].m_iParentBone;

		// Only update bones reference by the bone mask.
		if ( !( m_pOwnerHdr->boneFlags( iOwnerBone ) & boneMask ) )
			continue;

		if ( bOverrideDirection && m_nRightHandBoneID == -1 )		// only want to change direction of the right hand bone, cache its index here
		{
			mstudiobone_t *pOwnerBones = m_pOwnerHdr->pBone( 0 );
			for ( int k = 0; k < m_pOwnerHdr->numbones(); k++ )
			{
				if ( !Q_stricmp( pOwnerBones[k].pszName(), "ValveBiped.Bip01_R_Hand" ) )
				{
					m_nRightHandBoneID = k;
					break;
				}
			}
		}
		
		if ( bOverrideDirection && i == m_nRightHandBoneID )
		{
			matrix3x4_t matParentBoneToWorld;
			m_pFollow->GetBoneTransform( iParentBone, matParentBoneToWorld );
			MatrixSetColumn( vec3_origin, 3, matParentBoneToWorld );		// remove translation

			matrix3x4_t matParentBoneToWorldInv;
			MatrixInvert( matParentBoneToWorld, matParentBoneToWorldInv );

			QAngle angAiming;
			VectorAngles( vecDir, Vector( 0, 0, -1 ), angAiming );
			matrix3x4_t matAimDirection;
			AngleMatrix( angAiming, matAimDirection );
			MatrixSetColumn( vec3_origin, 3, matAimDirection );		// remove translation

			matrix3x4_t matCorrection;
			ConcatTransforms( matParentBoneToWorldInv, matAimDirection, matCorrection );

			ConcatTransforms( m_pFollow->GetBone( iParentBone ), matCorrection, m_pOwner->GetBoneForWrite( iOwnerBone ) );
		}
		else
		{
			ConcatTransforms( m_pFollow->GetBone( iParentBone ), matPitchUp, m_pOwner->GetBoneForWrite( iOwnerBone ) );
		}

		boneComputed.Set( i );
	}
}
//-----------------------------------------------------------------------------
// Purpose: Runs movement commands for the player
// Input  : *player - 
//			*ucmd - 
//			*moveHelper - 
// Output : void CPlayerMove::RunCommand
//-----------------------------------------------------------------------------
void CPlayerMove::RunCommand ( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper *moveHelper )
{
	const float playerCurTime = player->m_nTickBase * TICK_INTERVAL; 
	const float playerFrameTime = player->m_bGamePaused ? 0 : TICK_INTERVAL;
	const float flTimeAllowedForProcessing = player->ConsumeMovementTimeForUserCmdProcessing( playerFrameTime );
	if ( !player->IsBot() && ( flTimeAllowedForProcessing < playerFrameTime ) )
	{
		// Make sure that the activity in command is erased because player cheated or dropped too many packets
		double dblWarningFrequencyThrottle = sv_maxusrcmdprocessticks_warning.GetFloat();
		if ( dblWarningFrequencyThrottle >= 0 )
		{
			static double s_dblLastWarningTime = 0;
			double dblTimeNow = Plat_FloatTime();
			if ( !s_dblLastWarningTime || ( dblTimeNow - s_dblLastWarningTime >= dblWarningFrequencyThrottle ) )
			{
				s_dblLastWarningTime = dblTimeNow;
				Warning( "sv_maxusrcmdprocessticks_warning at server tick %u: Ignored client %s usrcmd (%.6f < %.6f)!\n", gpGlobals->tickcount, player->GetPlayerName(), flTimeAllowedForProcessing, playerFrameTime );
			}
		}
		return; // Don't process this command
	}

	StartCommand( player, ucmd );

	// Set globals appropriately
	gpGlobals->curtime		=  playerCurTime;
	gpGlobals->frametime	=  playerFrameTime;

	// Prevent hacked clients from sending us invalid view angles to try to get leaf server code to crash
	if ( !ucmd->viewangles.IsValid() || !IsEntityQAngleReasonable(ucmd->viewangles) )
	{
		ucmd->viewangles = vec3_angle;
	}

	// Add and subtract buttons we're forcing on the player
	ucmd->buttons |= player->m_afButtonForced;
	ucmd->buttons &= ~player->m_afButtonDisabled;

	if ( player->m_bGamePaused )
	{
		// If no clipping and cheats enabled and noclipduring game enabled, then leave
		//  forwardmove and angles stuff in usercmd
		if ( player->GetMoveType() == MOVETYPE_NOCLIP &&
			 sv_cheats->GetBool() && 
			 sv_noclipduringpause.GetBool() )
		{
			gpGlobals->frametime = TICK_INTERVAL;
		}
	}

	// Assign the tracked weapon offset
	player->m_eyeToWeaponOffset = ucmd->viewToWeaponOffset;
	player->m_eyeOffset = ucmd->eyeOffset;
	player->m_torsoAngles = QAngle(0, ucmd->torsoYaw, 0);


	/*
	// TODO:  We can check whether the player is sending more commands than elapsed real time
	cmdtimeremaining -= ucmd->msec;
	if ( cmdtimeremaining < 0 )
	{
	//	return;
	}
	*/

	g_pGameMovement->StartTrackPredictionErrors( player );

	CommentarySystem_PePlayerRunCommand( player, ucmd );

	// Do weapon selection
	if ( ucmd->weaponselect != 0 )
	{
		CBaseCombatWeapon *weapon = dynamic_cast< CBaseCombatWeapon * >( CBaseEntity::Instance( ucmd->weaponselect ) );
		if ( weapon )
		{
			VPROF( "player->SelectItem()" );
			player->SelectItem( weapon->GetName(), ucmd->weaponsubtype );
		}
	}

	IServerVehicle *pVehicle = player->GetVehicle();

	// Latch in impulse.
	if ( ucmd->impulse )
	{
		// Discard impulse commands unless the vehicle allows them.
		// FIXME: UsingStandardWeapons seems like a bad filter for this. The flashlight is an impulse command, for example.
		if ( !pVehicle || player->UsingStandardWeaponsInVehicle() )
		{
			player->m_nImpulse = ucmd->impulse;
		}
	}

	// Update player input button states
	VPROF_SCOPE_BEGIN( "player->UpdateButtonState" );
	player->UpdateButtonState( ucmd->buttons );
	VPROF_SCOPE_END();

	CheckMovingGround( player, TICK_INTERVAL );

	g_pMoveData->m_vecOldAngles = player->pl.v_angle;

	// Copy from command to player unless game .dll has set angle using fixangle
	if ( player->pl.fixangle == FIXANGLE_NONE )
	{
		player->pl.v_angle = ucmd->viewangles;
	}
	else if( player->pl.fixangle == FIXANGLE_RELATIVE )
	{
		player->pl.v_angle = ucmd->viewangles + player->pl.anglechange;
	}

	// Call standard client pre-think
	RunPreThink( player );

	// Call Think if one is set
	RunThink( player, TICK_INTERVAL );

	// Setup input.
	SetupMove( player, ucmd, moveHelper, g_pMoveData );

	// Let the game do the movement.
	if ( !pVehicle )
	{
		VPROF( "g_pGameMovement->ProcessMovement()" );
		Assert( g_pGameMovement );
		g_pGameMovement->ProcessMovement( player, g_pMoveData );
	}
	else
	{
		VPROF( "pVehicle->ProcessMovement()" );
		pVehicle->ProcessMovement( player, g_pMoveData );
	}
			
	// Copy output
	FinishMove( player, ucmd, g_pMoveData );

	// Let server invoke any needed impact functions
	VPROF_SCOPE_BEGIN( "moveHelper->ProcessImpacts" );
	moveHelper->ProcessImpacts();
	VPROF_SCOPE_END();

	RunPostThink( player );

	g_pGameMovement->FinishTrackPredictionErrors( player );

	FinishCommand( player );

	// Let time pass
	if ( gpGlobals->frametime > 0 )
	{
		player->m_nTickBase++;
	}
}
void CHL2MP_Player::KickAttack(void)
{
	if (!IsDead())
	{
		CBaseViewModel *vm = GetViewModel(1);

		if (vm)
		{
			int	idealSequence = vm->SelectWeightedSequence(ACT_VM_PRIMARYATTACK);

			if (idealSequence >= 0)
			{
				vm->SendViewModelMatchingSequence(idealSequence);
				m_flNextKickAttack = gpGlobals->curtime + vm->SequenceDuration(idealSequence) - 0.5f;
			}
			QAngle	recoil = QAngle(random->RandomFloat(1.0f, 2.0f), random->RandomFloat(-1.0f, 1.0f), 0);
			this->ViewPunch(recoil);

			// Trace up or down based on where the enemy is...
			// But only if we're basically facing that direction
			Vector vecDirection;
			int kick_maxrange = 120;
			AngleVectors(QAngle(clamp(EyeAngles().x, 20, kick_maxrange), EyeAngles().y, EyeAngles().z), &vecDirection);

			CBaseEntity *pEnemy = MyNPCPointer() ? MyNPCPointer()->GetEnemy() : NULL;
			if (pEnemy)
			{
				Vector vecDelta;
				VectorSubtract(pEnemy->WorldSpaceCenter(), Weapon_ShootPosition(), vecDelta);
				VectorNormalize(vecDelta);

				Vector2D vecDelta2D = vecDelta.AsVector2D();
				Vector2DNormalize(vecDelta2D);
				if (DotProduct2D(vecDelta2D, vecDirection.AsVector2D()) > 0.8f)
				{
					vecDirection = vecDelta;
				}
			}

			Vector vecEnd;
			VectorMA(Weapon_ShootPosition(), 50, vecDirection, vecEnd);
			trace_t tr;
			UTIL_TraceHull(Weapon_ShootPosition(), vecEnd, Vector(-16, -16, -16), Vector(16, 16, 16), MASK_SHOT_HULL, this, COLLISION_GROUP_NONE, &tr);

			// did I hit someone?
			float KickDamageMult = 50 + (1 * ((fabs(GetAbsVelocity().x) + fabs(GetAbsVelocity().y) + fabs(GetAbsVelocity().z)) / 48));
			float KickThrowForceMult = 20 + (1 * ((fabs(GetAbsVelocity().x) + fabs(GetAbsVelocity().y) + fabs(GetAbsVelocity().z)) / 48));

			DevMsg("Kicking at %.2f of damage!\n", KickDamageMult);
			DevMsg("Kicking at %.2f of force!\n", KickThrowForceMult);

			if (tr.m_pEnt)
			{
				if (!(tr.m_pEnt))
				{
					//	return;
				}
				else
				{
					CBasePropDoor *pDoor = dynamic_cast<CBasePropDoor*>((CBaseEntity*)tr.m_pEnt);
					if (pDoor)
					{
						if (pDoor->HasSpawnFlags(SF_BREAKABLE_BY_PLAYER))
						{
							AngularImpulse angVelocity(random->RandomFloat(0, 45), 18, random->RandomFloat(-45, 45));
							pDoor->PlayBreakOpenSound();
							pDoor->BreakDoor(Weapon_ShootPosition(), angVelocity);
							return;
						}
						pDoor->PlayBreakFailSound();
						pDoor->KickFail();
						return;
					}

					CBaseEntity *Victim = this->CheckTraceHullAttack(Weapon_ShootPosition(), vecEnd, Vector(-16, -16, -16), Vector(16, 16, 16), KickDamageMult, DMG_CRUSH, KickThrowForceMult, true);
					if (Victim)
					{
						EmitSound("HL2Player.kick_body");
						return;
					}
				}
			}
			UTIL_TraceLine(Weapon_ShootPosition(), vecEnd, MASK_SHOT_HULL, this, COLLISION_GROUP_NONE, &tr);//IF we hit anything else
			if (tr.DidHit())
			{
				EmitSound("HL2Player.kick_wall");
			}
			else
			{
				EmitSound("HL2Player.kick_fire");
			}

		}
	}
}
void CASW_Parasite::InfestMarine(CASW_Marine* pMarine)
{
	if ( !pMarine )	
		return;

	pMarine->BecomeInfested(this);

	// attach
	int attachment = pMarine->LookupAttachment( "chest" );
	if ( attachment )
	{
		SetSolid( SOLID_NONE );
		SetMoveType( MOVETYPE_NONE );
		QAngle current(0,0,0);

		Vector diff = pMarine->GetAbsOrigin() - GetAbsOrigin();
		float angle = UTIL_VecToYaw(diff);
		angle -= pMarine->GetAbsAngles()[YAW];	// get the diff between our angle from the marine and the marine's facing;
		
		current = GetAbsAngles();

		Vector vAttachmentPos;
		pMarine->GetAttachment( attachment, vAttachmentPos );

		// Make sure it's near the chest attachement before parenting
		Teleport( &vAttachmentPos, &vec3_angle, &vec3_origin );
		
		SetParent( pMarine, attachment );

		float flRaise = RandomFloat( 15.0f, 18.0f );
		float flForward = RandomFloat( -3.0f, 0.0f );
		float flSide = RandomFloat( 1.75f, 3.0f ) * ( RandomInt( 0, 1 ) == 0 ? 1.0f : -1.0f );

		if ( asw_debug_alien_damage.GetBool() )
		{
			Msg( "INFEST: flRaise = %f flForward = %f flSide = %f yaw = %f\n", flRaise, flForward, flSide, angle + asw_infest_angle.GetFloat() );
		}
		SetLocalOrigin( Vector( flForward, flSide, flRaise ) );
		SetLocalAngles( QAngle( asw_infest_pitch.GetFloat(), angle + asw_infest_angle.GetFloat(), 0 ) );
		// play our infesting anim
		if ( asw_parasite_inside.GetBool() )
		{
			SetActivity(ACT_RANGE_ATTACK2);
		}
		else
		{
			int iInfestAttack = LookupSequence("Infest_attack");
			if (GetSequence() != iInfestAttack)
			{
				ResetSequence(iInfestAttack);
			}
		}
		
		AddFlag( FL_NOTARGET );
		SetThink( &CASW_Parasite::InfestThink );
		SetTouch( NULL );
		m_bInfesting = true;		
	}
	else
	{
		FinishedInfesting();
	}		
}
void CNB_Lobby_Tooltip::OnTick()
{
	if ( ASWGameRules() && ASWGameRules()->GetCurrentVoteType() != ASW_VOTE_NONE )
	{
		SetVisible( false );
		return;
	}
	SetVisible( true );

	m_bValidTooltip = false;
	m_pTitle->SetVisible( false );

	int nPromotion = 0;
	if ( m_bPromotionTooltip )
	{
		nPromotion = Briefing()->GetCommanderPromotion( m_nLobbySlot );
	}

	if ( m_nLobbySlot == -1 || !Briefing()->IsLobbySlotOccupied( m_nLobbySlot ) || ( m_bPromotionTooltip && nPromotion <= 0 ) )
	{
		m_pTitle->SetVisible( false );
		m_pSkillPanel0->SetVisible( false );
		m_pSkillPanel1->SetVisible( false );
		m_pSkillPanel2->SetVisible( false );
		m_pSkillPanel3->SetVisible( false );
		m_pSkillPanel4->SetVisible( false );
		m_pPromotionIcon->SetVisible( false );
		m_pPromotionLabel->SetVisible( false );
		m_pItemModelPanel->SetVisible( false );

		m_pWeaponDetail0->m_bHidden = true;
		m_pWeaponDetail1->m_bHidden = true;
		m_pWeaponDetail2->m_bHidden = true;
		m_pWeaponDetail3->m_bHidden = true;
		m_pWeaponDetail4->m_bHidden = true;
		m_pWeaponDetail5->m_bHidden = true;
	}
	else if ( m_bPromotionTooltip )
	{
		m_pPromotionIcon->SetVisible( true );
		m_pPromotionLabel->SetVisible( true );

		m_pSkillPanel0->SetVisible( false );
		m_pSkillPanel1->SetVisible( false );
		m_pSkillPanel2->SetVisible( false );
		m_pSkillPanel3->SetVisible( false );
		m_pSkillPanel4->SetVisible( false );
		m_pItemModelPanel->SetVisible( false );

		m_pWeaponDetail0->m_bHidden = true;
		m_pWeaponDetail1->m_bHidden = true;
		m_pWeaponDetail2->m_bHidden = true;
		m_pWeaponDetail3->m_bHidden = true;
		m_pWeaponDetail4->m_bHidden = true;
		m_pWeaponDetail5->m_bHidden = true;

		m_pTitle->SetVisible( true );

		switch( nPromotion )
		{
			case 1: m_pPromotionLabel->SetText( "#nb_first_promotion" );  m_pTitle->SetText( "#nb_promotion_medal_1"); break;
			case 2: m_pPromotionLabel->SetText( "#nb_second_promotion" );  m_pTitle->SetText( "#nb_promotion_medal_2"); break;
			case 3: m_pPromotionLabel->SetText( "#nb_third_promotion" );  m_pTitle->SetText( "#nb_promotion_medal_3"); break;
			case 4: m_pPromotionLabel->SetText( "#nb_fourth_promotion" );  m_pTitle->SetText( "#nb_promotion_medal_4"); break;
			case 5: m_pPromotionLabel->SetText( "#nb_fifth_promotion" );  m_pTitle->SetText( "#nb_promotion_medal_5"); break;
			case 6: m_pPromotionLabel->SetText( "#nb_sixth_promotion" );  m_pTitle->SetText( "#nb_promotion_medal_6"); break;
		}
		m_pPromotionIcon->SetImage( VarArgs( "briefing/promotion_%d_LG", nPromotion ) );
	}
	else if ( m_bMarineTooltip )
	{
		CASW_Marine_Profile *pProfile = Briefing()->GetMarineProfile( m_nLobbySlot );
		if ( pProfile )
		{
			m_pTitle->SetVisible( true );
			m_pSkillPanel0->SetVisible( true );		
			m_pSkillPanel1->SetVisible( true );
			m_pSkillPanel2->SetVisible( true );
			m_pSkillPanel3->SetVisible( true );
			m_pSkillPanel4->SetVisible( true );
			m_pPromotionIcon->SetVisible( false );
			m_pPromotionLabel->SetVisible( false );

			m_pWeaponDetail0->m_bHidden = true;
			m_pWeaponDetail1->m_bHidden = true;
			m_pWeaponDetail2->m_bHidden = true;
			m_pWeaponDetail3->m_bHidden = true;
			m_pWeaponDetail4->m_bHidden = true;
			m_pWeaponDetail5->m_bHidden = true;
			m_pItemModelPanel->m_bShouldPaint = false;
			m_pItemModelPanel->SetVisible( false );

			m_pTitle->SetText( Briefing()->GetMarineName( m_nLobbySlot ) );
			m_pSkillPanel0->SetSkillDetails( pProfile->m_ProfileIndex, 0, Briefing()->GetMarineSkillPoints( m_nLobbySlot, 0 ) );
			m_pSkillPanel1->SetSkillDetails( pProfile->m_ProfileIndex, 1, Briefing()->GetMarineSkillPoints( m_nLobbySlot, 1 ) );
			m_pSkillPanel2->SetSkillDetails( pProfile->m_ProfileIndex, 2, Briefing()->GetMarineSkillPoints( m_nLobbySlot, 2 ) );
			m_pSkillPanel3->SetSkillDetails( pProfile->m_ProfileIndex, 3, Briefing()->GetMarineSkillPoints( m_nLobbySlot, 3 ) );
			m_pSkillPanel4->SetSkillDetails( pProfile->m_ProfileIndex, 4, Briefing()->GetMarineSkillPoints( m_nLobbySlot, 4 ) );

			m_bValidTooltip = true;
		}
	}
	else
	{
		m_pTitle->SetVisible( true );
		m_pSkillPanel0->SetVisible( false );
		m_pSkillPanel1->SetVisible( false );
		m_pSkillPanel2->SetVisible( false );
		m_pSkillPanel3->SetVisible( false );
		m_pSkillPanel4->SetVisible( false );
		m_pPromotionIcon->SetVisible( false );
		m_pPromotionLabel->SetVisible( false );

		int nWeapon = Briefing()->GetMarineSelectedWeapon( m_nLobbySlot, m_nInventorySlot );

		if ( nWeapon == -1 || !ASWEquipmentList() )
		{
			m_pTitle->SetVisible( false );
			m_pWeaponDetail0->m_bHidden = true;
			m_pWeaponDetail1->m_bHidden = true;
			m_pWeaponDetail2->m_bHidden = true;
			m_pWeaponDetail3->m_bHidden = true;
			m_pWeaponDetail4->m_bHidden = true;
			m_pWeaponDetail5->m_bHidden = true;
			m_pItemModelPanel->m_bShouldPaint = false;
			m_pItemModelPanel->SetVisible( false );
			return;
		}

		CASW_EquipItem *pItem = ASWEquipmentList()->GetItemForSlot( m_nInventorySlot, nWeapon );
		if ( !pItem )
			return;

		CASW_WeaponInfo* pWeaponInfo = ASWEquipmentList()->GetWeaponDataFor( STRING( pItem->m_EquipClass ) );
		if ( !pWeaponInfo )
			return;

		bool bShowDetails = ( m_nInventorySlot != ASW_INVENTORY_SLOT_EXTRA && pWeaponInfo->m_flBaseDamage > 0 );

		int nWeaponHash = nWeapon * ( m_nInventorySlot + 1 );
		bool bWeaponChanged = false;
		if ( nWeaponHash != m_nLastWeaponHash || m_nInventorySlot != m_nLastInventorySlot )
		{
			m_nLastWeaponHash = nWeaponHash;
			m_nLastInventorySlot = m_nInventorySlot;
			bWeaponChanged = true;
			// debug
			//Msg( "m_nInventorySlot = %d\nnWeapon = %d\nnWeaponHash = %d\nbShowDetails = %d\n", m_nInventorySlot, nWeapon, nWeaponHash, bShowDetails ? 1 : 0 );
		}

		if ( bShowDetails )
		{
			m_pWeaponDetail0->m_bHidden = false;
			m_pWeaponDetail1->m_bHidden = false;
			m_pWeaponDetail2->m_bHidden = false;
			m_pWeaponDetail3->m_bHidden = false;
			m_pWeaponDetail4->m_bHidden = false;
			m_pWeaponDetail5->m_bHidden = false;
			m_pItemModelPanel->m_bShouldPaint = false;
			m_pItemModelPanel->SetVisible( false );
		}
		else
		{
			m_pWeaponDetail0->m_bHidden = true;
			m_pWeaponDetail1->m_bHidden = true;
			m_pWeaponDetail2->m_bHidden = true;
			m_pWeaponDetail3->m_bHidden = true;
			m_pWeaponDetail4->m_bHidden = true;
			m_pWeaponDetail5->m_bHidden = false;

			Vector vecPos = Vector( -275.0, 0.0, 190.0 );
			QAngle angRot = QAngle( 32.0, 0.0, 0.0 );

			vecPos.z += pWeaponInfo->m_flModelPanelZOffset;

			Vector vecBoundsMins, vecBoundsMax;
			m_pItemModelPanel->GetBoundingBox( vecBoundsMins, vecBoundsMax );
			int iMaxBounds = -vecBoundsMins.x + vecBoundsMax.x;
			iMaxBounds = MAX( iMaxBounds, -vecBoundsMins.y + vecBoundsMax.y );
			iMaxBounds = MAX( iMaxBounds, -vecBoundsMins.z + vecBoundsMax.z );
			vecPos *= (float)iMaxBounds/64.0f;

			m_pItemModelPanel->SetCameraPositionAndAngles( vecPos, angRot );
			m_pItemModelPanel->SetModelAnglesAndPosition( QAngle( 0.0f, gpGlobals->curtime * 45.0f , 0.0f ), vec3_origin );

			if ( bWeaponChanged )
			{
				m_pItemModelPanel->ClearMergeMDLs();
				if ( Q_stricmp( pWeaponInfo->szDisplayModel, "" ) )
				{
					m_pItemModelPanel->SetMDL( pWeaponInfo->szDisplayModel );
					if ( Q_stricmp( pWeaponInfo->szDisplayModel2, "" ) )
						m_pItemModelPanel->SetMergeMDL( pWeaponInfo->szDisplayModel2 );
				}
				else
				{
					m_pItemModelPanel->SetMDL( pWeaponInfo->szWorldModel );
				}

				int nSkin = 0;
				if ( pWeaponInfo->m_iDisplayModelSkin > 0 )
					nSkin = pWeaponInfo->m_iDisplayModelSkin;
				else
					nSkin = pWeaponInfo->m_iPlayerModelSkin;

				m_pItemModelPanel->SetSkin( nSkin );
				m_pItemModelPanel->SetModelAnim( m_pItemModelPanel->FindAnimByName( "idle" ) );
				m_pItemModelPanel->m_bShouldPaint = true;
				m_pItemModelPanel->SetVisible( true );

				// force resetup of various things (this block of code fixes size popping when changing model)
				m_pItemModelPanel->InvalidateLayout( true );

				m_pItemModelPanel->GetBoundingBox( vecBoundsMins, vecBoundsMax );
				int iMaxBounds = -vecBoundsMins.x + vecBoundsMax.x;
				iMaxBounds = MAX( iMaxBounds, -vecBoundsMins.y + vecBoundsMax.y );
				iMaxBounds = MAX( iMaxBounds, -vecBoundsMins.z + vecBoundsMax.z );
				vecPos *= (float)iMaxBounds/64.0f;

				m_pItemModelPanel->SetCameraPositionAndAngles( vecPos, angRot );
				m_pItemModelPanel->SetModelAnglesAndPosition( QAngle( 0.0f, gpGlobals->curtime * 45.0f , 0.0f ), vec3_origin );

				m_pItemModelPanel->InvalidateLayout( true );
				m_pItemModelPanel->SetAlpha( 0 );
				vgui::GetAnimationController()->RunAnimationCommand( m_pItemModelPanel, "Alpha", 255, 0.01f, 0.5f, vgui::AnimationController::INTERPOLATOR_LINEAR);
			}
		}

		CASW_Marine_Profile *pProfile = Briefing()->GetMarineProfile( m_nLobbySlot );
		if ( pProfile )
		{
			int nProfileIndex = pProfile->m_ProfileIndex;
			int nEquipIndex = Briefing()->GetProfileSelectedWeapon( nProfileIndex, m_nInventorySlot );
			m_pWeaponDetail0->SetWeaponDetails( nEquipIndex, m_nInventorySlot, nProfileIndex, 0 );
			m_pWeaponDetail1->SetWeaponDetails( nEquipIndex, m_nInventorySlot, nProfileIndex, 1 );
			m_pWeaponDetail2->SetWeaponDetails( nEquipIndex, m_nInventorySlot, nProfileIndex, 2 );
			m_pWeaponDetail3->SetWeaponDetails( nEquipIndex, m_nInventorySlot, nProfileIndex, 3 );
			m_pWeaponDetail4->SetWeaponDetails( nEquipIndex, m_nInventorySlot, nProfileIndex, 4 );
			m_pWeaponDetail5->SetWeaponDetails( nEquipIndex, m_nInventorySlot, nProfileIndex, 5 );
		}

		m_pTitle->SetText( pWeaponInfo->szEquipLongName );

		m_bValidTooltip = true;
	}
}
void CWeaponShotgun::PrimaryAttack( void )
{
	// Only the player fires this way so we can cast
	CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );

	if (!pPlayer)
	{
		return;
	}

	if ( m_iClip1 <= 0 )
	{
		Reload();
		if ( m_iClip1 <= 0 )
			DryFire( );

		return;
	}

	// MUST call sound before removing a round from the clip of a CMachineGun
	WeaponSound( SINGLE );

	pPlayer->m_fEffects |= EF_MUZZLEFLASH;

	SendWeaponAnim( ACT_VM_PRIMARYATTACK );
	pPlayer->SetAnimation( PLAYER_ATTACK1 );

	// Don't fire again until fire animation has completed
	m_flNextPrimaryAttack = gpGlobals->curtime + 0.75;
	m_flNextSecondaryAttack = gpGlobals->curtime + 0.75;
	m_iClip1 -= 1;

	Vector vecSrc		= pPlayer->Weapon_ShootPosition();
	Vector vecAiming	= pPlayer->GetAutoaimVector( AUTOAIM_5DEGREES );	

	if ( g_pGameRules->IsMultiplayer() )
	{
		pPlayer->FireBullets( 4, vecSrc, vecAiming, VECTOR_CONE_DM_SHOTGUN, MAX_TRACE_LENGTH, m_iPrimaryAmmoType, 0 );
	}
	else
	{
		pPlayer->FireBullets( 6, vecSrc, vecAiming, VECTOR_CONE_10DEGREES, MAX_TRACE_LENGTH, m_iPrimaryAmmoType, 0 );
	}

	pPlayer->SetMuzzleFlashTime( gpGlobals->curtime + 1.0 );

	pPlayer->ViewPunch( QAngle( -5, 0, 0 ) );

	CSoundEnt::InsertSound( SOUND_COMBAT, GetAbsOrigin(), 400, 0.2 );

	if ( !m_iClip1 && pPlayer->GetAmmoCount( m_iPrimaryAmmoType ) <= 0 )
	{
		// HEV suit - indicate out of ammo condition
		pPlayer->SetSuitUpdate("!HEV_AMO0", FALSE, 0); 
	}


	if ( m_iClip1 > 0 )
	{
		m_flPumpTime = gpGlobals->curtime + 0.5;
		SetWeaponIdleTime( gpGlobals->curtime + 5.0 );
	}
	else
	{
		SetWeaponIdleTime( gpGlobals->curtime + 0.75 );
	}

	m_fInSpecialReload = 0;
}
void CSDKPlayer::FireBullet( 
						   Vector vecSrc,	// shooting postion
						   const QAngle &shootAngles,  //shooting angle
						   float vecSpread, // spread vector
						   int iDamage, // base damage
						   int iBulletType, // ammo type
						   CBaseEntity *pevAttacker, // shooter
						   bool bDoEffects,	// create impact effect ?
						   float x,	// spread x factor
						   float y	// spread y factor
						   )
{
	float fCurrentDamage = iDamage;   // damage of the bullet at it's current trajectory
	float flCurrentDistance = 0.0;  //distance that the bullet has traveled so far

	Vector vecDirShooting, vecRight, vecUp;
	AngleVectors( shootAngles, &vecDirShooting, &vecRight, &vecUp );

	if ( !pevAttacker )
		pevAttacker = this;  // the default attacker is ourselves

	// add the spray 
	Vector vecDir = vecDirShooting +
		x * vecSpread * vecRight +
		y * vecSpread * vecUp;

	VectorNormalize( vecDir );

	float flMaxRange = 8000;

	Vector vecEnd = vecSrc + vecDir * flMaxRange; // max bullet range is 10000 units

	trace_t tr; // main enter bullet trace

	UTIL_TraceLine( vecSrc, vecEnd, MASK_SOLID|CONTENTS_DEBRIS|CONTENTS_HITBOX, this, COLLISION_GROUP_NONE, &tr );

		if ( tr.fraction == 1.0f )
			return; // we didn't hit anything, stop tracing shoot

	if ( sv_showimpacts.GetBool() )
	{
#ifdef CLIENT_DLL
		// draw red client impact markers
		debugoverlay->AddBoxOverlay( tr.endpos, Vector(-2,-2,-2), Vector(2,2,2), QAngle( 0, 0, 0), 255,0,0,127, 4 );

		if ( tr.m_pEnt && tr.m_pEnt->IsPlayer() )
		{
			C_BasePlayer *player = ToBasePlayer( tr.m_pEnt );
			player->DrawClientHitboxes( 4, true );
		}
#else
		// draw blue server impact markers
		NDebugOverlay::Box( tr.endpos, Vector(-2,-2,-2), Vector(2,2,2), 0,0,255,127, 4 );

		if ( tr.m_pEnt && tr.m_pEnt->IsPlayer() )
		{
			CBasePlayer *player = ToBasePlayer( tr.m_pEnt );
			player->DrawServerHitboxes( 4, true );
		}
#endif
	}

		//calculate the damage based on the distance the bullet travelled.
		flCurrentDistance += tr.fraction * flMaxRange;

		// damage get weaker of distance
		fCurrentDamage *= pow ( 0.85f, (flCurrentDistance / 500));

		int iDamageType = DMG_BULLET | DMG_NEVERGIB;

		if( bDoEffects )
		{
			// See if the bullet ended up underwater + started out of the water
			if ( enginetrace->GetPointContents( tr.endpos ) & (CONTENTS_WATER|CONTENTS_SLIME) )
			{	
				trace_t waterTrace;
				UTIL_TraceLine( vecSrc, tr.endpos, (MASK_SHOT|CONTENTS_WATER|CONTENTS_SLIME), this, COLLISION_GROUP_NONE, &waterTrace );

				if( waterTrace.allsolid != 1 )
				{
					CEffectData	data;
					data.m_vOrigin = waterTrace.endpos;
					data.m_vNormal = waterTrace.plane.normal;
					data.m_flScale = random->RandomFloat( 8, 12 );

					if ( waterTrace.contents & CONTENTS_SLIME )
					{
						data.m_fFlags |= FX_WATER_IN_SLIME;
					}

					DispatchEffect( "gunshotsplash", data );
				}
			}
			else
			{
				//Do Regular hit effects

				// Don't decal nodraw surfaces
				if ( !( tr.surface.flags & (SURF_SKY|SURF_NODRAW|SURF_HINT|SURF_SKIP) ) )
				{
					CBaseEntity *pEntity = tr.m_pEnt;
					if ( !( !friendlyfire.GetBool() && pEntity && pEntity->IsPlayer() && pEntity->GetTeamNumber() == GetTeamNumber() ) )
					{
						UTIL_ImpactTrace( &tr, iDamageType );
					}
				}
			}
		} // bDoEffects

		// add damage to entity that we hit

#ifdef GAME_DLL
		ClearMultiDamage();

		CTakeDamageInfo info( pevAttacker, pevAttacker, fCurrentDamage, iDamageType );
		CalculateBulletDamageForce( &info, iBulletType, vecDir, tr.endpos );
		tr.m_pEnt->DispatchTraceAttack( info, vecDir, &tr );

		TraceAttackToTriggers( info, tr.startpos, tr.endpos, vecDir );

		ApplyMultiDamage();
#endif
}
Beispiel #13
0
//-----------------------------------------------------------------------------
// Purpose: Do the headlight
//-----------------------------------------------------------------------------
void CFlashlightEffect::UpdateLightNew(const Vector &vecPos, const Vector &vecForward, const Vector &vecRight, const Vector &vecUp)
{
	FlashlightState_t state;

	Vector end = vecPos + r_flashlightoffsety.GetFloat() * vecUp;

	trace_t pmEye, pmEyeBack;
	CTraceFilterSkipPlayerAndViewModel traceFilter;

	UTIL_TraceHull( vecPos, end, Vector( -4, -4, -4 ), Vector ( 4, 4, 4 ), MASK_SOLID & ~(CONTENTS_HITBOX), &traceFilter, &pmEye );

	if ( pmEye.fraction != 1.0f )
	{
		end = vecPos;
	}

	int iMask = MASK_OPAQUE_AND_NPCS;
	iMask &= ~CONTENTS_HITBOX;
	iMask |= CONTENTS_WINDOW;

	// Trace a line outward, skipping the player model and the view model.
	//Eye -> EyeForward
	UTIL_TraceHull( end, vecPos + vecForward * r_flashlightfar.GetFloat(), Vector( -4, -4, -4 ), Vector ( 4, 4, 4 ), iMask, &traceFilter, &pmEye );
	UTIL_TraceHull( end, vecPos - vecForward * 128, Vector( -4, -4, -4 ), Vector ( 4, 4, 4 ), iMask, &traceFilter, &pmEyeBack );

	float flDist;
	float flLength = (pmEye.endpos - end).Length();

	if ( flLength <= 128 )
	{
		flDist = ( ( 1.0f - ( flLength / 128 ) ) * 128.0f );
	}
	else
	{
		flDist = 0.0f;
	}


	m_flDistMod = Lerp( 0.3f, m_flDistMod, flDist );

	float flMaxDist = (pmEyeBack.endpos - end).Length();
	if( m_flDistMod > flMaxDist )
		m_flDistMod = flMaxDist;

	Vector vStartPos = end;
	Vector vEndPos = pmEye.endpos;
	Vector vDir = vEndPos - vStartPos;
	
	VectorNormalize( vDir );

	if ( vDir == vec3_origin )
	{
		vDir = vecForward;
	}

	vStartPos = vStartPos - vDir * m_flDistMod;

	if ( r_flashlightvisualizetrace.GetBool() == true )
	{
		debugoverlay->AddBoxOverlay( vEndPos, Vector( -4, -4, -4 ), Vector( 4, 4, 4 ), QAngle( 0, 0, 0 ), 0, 0, 255, 16, 0 );
		debugoverlay->AddLineOverlay( vStartPos, vEndPos, 255, 0, 0, false, 0 );
	}

	state.m_vecLightOrigin = vStartPos;
	state.m_vecLightDirection = vDir;

	state.m_fQuadraticAtten = r_flashlightquadratic.GetFloat();

	bool bFlicker = false;

#ifdef HL2_EPISODIC
	
	C_BaseHLPlayer *pPlayer = (C_BaseHLPlayer *)C_BasePlayer::GetLocalPlayer();
	if ( pPlayer && pPlayer->m_HL2Local.m_flSuitPower <= 10.0f )
	{
		float flScale = SimpleSplineRemapVal( pPlayer->m_HL2Local.m_flSuitPower, 10.0f, 4.8f, 1.0f, 0.0f );
		flScale = clamp( flScale, 0.0f, 1.0f );

		if ( flScale < 0.35f )
		{
			float flFlicker = cosf( gpGlobals->curtime * 6.0f ) * sinf( gpGlobals->curtime * 15.0f );
			
			if ( flFlicker > 0.25f && flFlicker < 0.75f )
			{
				// On
				state.m_fLinearAtten = r_flashlightlinear.GetFloat() * flScale;
			}
			else
			{
				// Off
				state.m_fLinearAtten = 0.0f;
			}
		}
		else
		{
			float flNoise = cosf( gpGlobals->curtime * 7.0f ) * sinf( gpGlobals->curtime * 25.0f );
			state.m_fLinearAtten = r_flashlightlinear.GetFloat() * flScale + 1.5f * flNoise;
		}

		state.m_fHorizontalFOVDegrees = r_flashlightfov.GetFloat() - ( 16.0f * (1.0f-flScale) );
		state.m_fVerticalFOVDegrees = r_flashlightfov.GetFloat() - ( 16.0f * (1.0f-flScale) );
		
		bFlicker = true;
	}

#endif
	
	if ( bFlicker == false )
	{
		state.m_fLinearAtten = r_flashlightlinear.GetFloat();
		state.m_fHorizontalFOVDegrees = r_flashlightfov.GetFloat();
		state.m_fVerticalFOVDegrees = r_flashlightfov.GetFloat();
	}

	state.m_fConstantAtten = r_flashlightconstant.GetFloat();
	state.m_Color.Init( 1.0f, 1.0f, 1.0f );
	state.m_NearZ = r_flashlightnear.GetFloat();
	state.m_FarZ = r_flashlightfar.GetFloat();
	
	if( m_FlashlightHandle == CLIENTSHADOW_INVALID_HANDLE )
	{
		m_FlashlightHandle = g_pClientShadowMgr->CreateFlashlight( state );
	}
	else
	{
		if( !r_flashlightlockposition.GetBool() )
		{
			g_pClientShadowMgr->UpdateFlashlightState( m_FlashlightHandle, state );
		}
	}
	
	g_pClientShadowMgr->UpdateProjectedTexture( m_FlashlightHandle, true );
	
	// Kill the old flashlight method if we have one.
	LightOffOld();
}
Beispiel #14
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CWeaponAR2::DelayedAttack( void )
{
	m_bShotDelayed = false;
	
	CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
	
	if ( pOwner == NULL )
		return;

	// Deplete the clip completely
	SendWeaponAnim( ACT_VM_SECONDARYATTACK );
	m_flNextSecondaryAttack = pOwner->m_flNextAttack = gpGlobals->curtime + SequenceDuration();

	// Register a muzzleflash for the AI
	pOwner->DoMuzzleFlash();
	pOwner->SetMuzzleFlashTime( gpGlobals->curtime + 0.5 );
	
	WeaponSound( WPN_DOUBLE );

	pOwner->RumbleEffect(RUMBLE_SHOTGUN_DOUBLE, 0, RUMBLE_FLAG_RESTART );

	// Fire the bullets
	Vector vecSrc	 = pOwner->Weapon_ShootPosition( );
	Vector vecAiming = pOwner->GetAutoaimVector( AUTOAIM_SCALE_DEFAULT );
	Vector impactPoint = vecSrc + ( vecAiming * MAX_TRACE_LENGTH );

	// Fire the bullets
	Vector vecVelocity = vecAiming * 1000.0f;

	// Fire the combine ball
	CreateCombineBall(	vecSrc, 
						vecVelocity, 
						sk_weapon_ar2_alt_fire_radius.GetFloat(), 
						sk_weapon_ar2_alt_fire_mass.GetFloat(),
						sk_weapon_ar2_alt_fire_duration.GetFloat(),
						pOwner );

	// View effects
	color32 white = {255, 255, 255, 64};
	UTIL_ScreenFade( pOwner, white, 0.1, 0, FFADE_IN  );
	
	//Disorient the player
	QAngle angles = pOwner->GetLocalAngles();

	angles.x += random->RandomInt( -4, 4 );
	angles.y += random->RandomInt( -4, 4 );
	angles.z = 0;

	pOwner->SnapEyeAngles( angles );
	
	pOwner->ViewPunch( QAngle( random->RandomInt( -8, -12 ), random->RandomInt( 1, 2 ), 0 ) );

	// Decrease ammo
	pOwner->RemoveAmmo( 1, m_iSecondaryAmmoType );

	// Can shoot again immediately
	m_flNextPrimaryAttack = gpGlobals->curtime + 0.5f;

	// Can blow up after a short delay (so have time to release mouse button)
	m_flNextSecondaryAttack = gpGlobals->curtime + 1.0f;
}
//-----------------------------------------------------------------------------
// Purpose: Crane rotates around with +left and +right, and extends/retracts 
//			the cable with +forward and +back.
//-----------------------------------------------------------------------------
void CPropCrane::DriveCrane( int iDriverButtons, int iButtonsPressed, float flNPCSteering )
{
	bool bWasExtending = m_bExtending;

	// Handle rotation of the crane
	if ( iDriverButtons & IN_MOVELEFT )
	{
		// NPCs may cheat and set the steering
		if ( flNPCSteering )
		{
			m_flTurn = flNPCSteering;
		}
		else
		{
			// Try adding some randomness to make it feel shaky? 
			float flTurnAdd = m_flTurnAccel;
			// If we're turning back on ourselves, use decel speed
			if ( m_flTurn < 0 )
			{
				flTurnAdd = MAX( flTurnAdd, m_flTurnDecel );
			}

			m_flTurn = UTIL_Approach( m_flMaxTurnSpeed, m_flTurn, flTurnAdd * gpGlobals->frametime );
		}
		m_iTurning = TURNING_LEFT;
	}
	else if ( iDriverButtons & IN_MOVERIGHT )
	{
		// NPCs may cheat and set the steering
		if ( flNPCSteering )
		{
			m_flTurn = flNPCSteering;
		}
		else
		{
			// Try adding some randomness to make it feel shaky?
			float flTurnAdd = m_flTurnAccel;
			// If we're turning back on ourselves, increase the rate
			if ( m_flTurn > 0 )
			{
				flTurnAdd = MAX( flTurnAdd, m_flTurnDecel );
			}
			m_flTurn = UTIL_Approach( -m_flMaxTurnSpeed, m_flTurn, flTurnAdd * gpGlobals->frametime );
		}
		m_iTurning = TURNING_RIGHT;
	}
	else
	{
		m_flTurn = UTIL_Approach( 0, m_flTurn, m_flTurnDecel * gpGlobals->frametime );
		m_iTurning = TURNING_NOT;
	}

	if ( m_hPlayer )
	{
		float maxTurn = GetMaxTurnRate();
		static float maxRumble = 0.35f;
		static float minRumble = 0.1f;
		float rumbleRange = maxRumble - minRumble;
		float rumble;

		float factor = fabs(m_flTurn) / maxTurn;
		factor = MIN( factor, 1.0f );
		rumble = minRumble + (rumbleRange * factor);

		m_hPlayer->RumbleEffect( RUMBLE_FLAT_BOTH, (int)(rumble * 100), RUMBLE_FLAG_UPDATE_SCALE );
	}

	SetLocalAngularVelocity( QAngle(0,m_flTurn * 10,0) );

	// Handle extension / retraction of the arm
	if ( iDriverButtons & IN_FORWARD )
	{
		m_flExtensionRate = UTIL_Approach( m_flMaxExtensionSpeed, m_flExtensionRate, m_flExtensionAccel * gpGlobals->frametime );
		m_bExtending = true;
	}
	else if ( iDriverButtons & IN_BACK )
	{
		m_flExtensionRate = UTIL_Approach( -m_flMaxExtensionSpeed, m_flExtensionRate, m_flExtensionAccel * gpGlobals->frametime );
		m_bExtending = true;
	}
	else
	{
		m_flExtensionRate = UTIL_Approach( 0, m_flExtensionRate, m_flExtensionDecel * gpGlobals->frametime );
		m_bExtending = false;
	}

	//Msg("Turn: %f\nExtensionRate: %f\n", m_flTurn, m_flExtensionRate );

	//If we're holding down an attack button, update our state
	if ( iButtonsPressed & (IN_ATTACK | IN_ATTACK2) )
	{
		// If we have something on the magnet, turn the magnet off
		if ( m_hCraneMagnet->GetTotalMassAttachedObjects() )
		{
			TurnMagnetOff();
		}
		else if ( !m_bDropping && m_flNextDropAllowedTime < gpGlobals->curtime )
		{
			TurnMagnetOn();

			// Drop the magnet till it hits something
			m_bDropping = true;
			m_hCraneMagnet->ResetHasHitSomething();
			m_hCraneTip->m_pSpring->SetSpringConstant( CRANE_SPRING_CONSTANT_LOWERING );

			m_ServerVehicle.PlaySound( VS_MISC1 );
		}
	}

	float flSpeedPercentage = clamp( fabs(m_flTurn) / m_flMaxTurnSpeed, 0, 1 );
	vbs_sound_update_t params;
	params.Defaults();
	params.bThrottleDown = (m_iTurning != TURNING_NOT);
	params.flCurrentSpeedFraction = flSpeedPercentage;
	params.flWorldSpaceSpeed = 0;

	m_ServerVehicle.SoundUpdate( params );

	// Play sounds for arm extension / retraction
	if ( m_bExtending && !bWasExtending )
	{
		m_ServerVehicle.StopSound( VS_ENGINE2_STOP );
		m_ServerVehicle.PlaySound( VS_ENGINE2_START );
	}
	else if ( !m_bExtending && bWasExtending )
	{
		m_ServerVehicle.StopSound( VS_ENGINE2_START );
		m_ServerVehicle.PlaySound( VS_ENGINE2_STOP );
	}
}
Beispiel #16
0
//-----------------------------------------------------------------------------
// Purpose: Called when spawning, after keyvalues have been set.
//-----------------------------------------------------------------------------
void CFuncRotating::Spawn( )
{
#ifdef TF_DLL
	AddSpawnFlags( SF_BRUSH_ROTATE_CLIENTSIDE );
#endif

	//
	// Maintain compatibility with previous maps.
	//
	if (m_flVolume == 0.0)
	{
		m_flVolume = 1.0;
	}

	//
	// If the designer didn't set a sound attenuation, default to one.
	//
	if ( HasSpawnFlags(SF_BRUSH_ROTATE_SMALLRADIUS) )
	{
		m_flAttenuation = ATTN_IDLE;
	}
	else if ( HasSpawnFlags(SF_BRUSH_ROTATE_MEDIUMRADIUS) )
	{
		m_flAttenuation = ATTN_STATIC;
	}
	else if ( HasSpawnFlags(SF_BRUSH_ROTATE_LARGERADIUS) )
	{
		m_flAttenuation = ATTN_NORM;
	}
	else
	{
		m_flAttenuation = ATTN_NORM;
	}

	//
	// Prevent divide by zero if level designer forgets friction!
	//
	if ( m_flFanFriction == 0 )
	{
		m_flFanFriction = 1;
	}
	
	//
	// Build the axis of rotation based on spawnflags.
	//
	if ( HasSpawnFlags(SF_BRUSH_ROTATE_Z_AXIS) )
	{
		m_vecMoveAng = QAngle(0,0,1);
	}
	else if ( HasSpawnFlags(SF_BRUSH_ROTATE_X_AXIS) )
	{
		m_vecMoveAng = QAngle(1,0,0);
	}
	else
	{
		m_vecMoveAng = QAngle(0,1,0);	// y-axis
	}

	//
	// Check for reverse rotation.
	//
	if ( HasSpawnFlags(SF_BRUSH_ROTATE_BACKWARDS) )
	{
		m_vecMoveAng = m_vecMoveAng * -1;
	}

	SetSolid( SOLID_VPHYSICS );

	//
	// Some rotating objects like fake volumetric lights will not be solid.
	//
	if ( HasSpawnFlags(SF_ROTATING_NOT_SOLID) )
	{
		AddSolidFlags( FSOLID_NOT_SOLID );
		SetMoveType( MOVETYPE_PUSH );
	}
	else
	{
		RemoveSolidFlags( FSOLID_NOT_SOLID );
		SetMoveType( MOVETYPE_PUSH );
	}

	SetModel( STRING( GetModelName() ) );

	SetUse( &CFuncRotating::RotatingUse );

	//
	// Did level designer forget to assign a maximum speed? Prevent a divide by
	// zero in RampPitchVol as well as allowing the rotator to work.
	//
	m_flMaxSpeed = fabs( m_flMaxSpeed );
	if (m_flMaxSpeed == 0)
	{
		m_flMaxSpeed = 100;
	}

	//
	// If the brush should be initially rotating, use it in a little while.
	//
	if ( HasSpawnFlags(SF_BRUSH_ROTATE_START_ON) )
	{		
		SetThink( &CFuncRotating::SUB_CallUseToggle );
		SetNextThink( gpGlobals->curtime + .2 );	// leave a magic delay for client to start up
	}

	//
	// Can this brush inflict pain?
	//
	if ( HasSpawnFlags(SF_BRUSH_HURT) )
	{
		SetTouch( &CFuncRotating::HurtTouch );
	}

	//
	// Set speed to 0 in case there's an old "speed" key lying around.
	//
	m_flSpeed = 0;
	
	Precache( );
	CreateVPhysics();

	m_angStart = GetLocalAngles();
	
	// Slam the object back to solid - if we really want it to be solid.
	if ( m_bSolidBsp )
	{
		SetSolid( SOLID_BSP );
	}

	if ( HasSpawnFlags(SF_BRUSH_ROTATE_CLIENTSIDE) )
	{
		m_vecClientOrigin = GetLocalOrigin();
		m_vecClientAngles = GetLocalAngles();
	}
}
void CSnark::HuntThink( void )
{
	if (!IsInWorld())
	{
		SetTouch( NULL );
		UTIL_Remove( this );
		return;
	}
	
	StudioFrameAdvance( );
	SetNextThink( gpGlobals->curtime + 0.1f );

	// explode when ready
	if ( gpGlobals->curtime >= m_flDie )
	{
		g_vecAttackDir = GetAbsVelocity();
		VectorNormalize( g_vecAttackDir );
		m_iHealth = -1;
		CTakeDamageInfo	info( this, this, 1, DMG_GENERIC );
		Event_Killed( info );
		return;
	}

	// float
	if ( GetWaterLevel() != 0)
	{
		if ( GetMoveType() == MOVETYPE_FLYGRAVITY )
		{
			SetMoveType( MOVETYPE_FLY, MOVECOLLIDE_FLY_BOUNCE );
		}

		Vector vecVel = GetAbsVelocity();
		vecVel *= 0.9;
		vecVel.z += 8.0;
		SetAbsVelocity( vecVel );
	}
	else if ( GetMoveType() == MOVETYPE_FLY )
	{
		SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE );
	}

	// return if not time to hunt
	if ( m_flNextHunt > gpGlobals->curtime )
		return;

	m_flNextHunt = gpGlobals->curtime + 2.0;
	
	Vector vecFlat = GetAbsVelocity();
	vecFlat.z = 0;
	VectorNormalize( vecFlat );

	if ( GetEnemy() == NULL || !GetEnemy()->IsAlive() )
	{
		// find target, bounce a bit towards it.
		GetSenses()->Look( 512 );
		SetEnemy( BestEnemy() );
	}

	// squeek if it's about time blow up
	if ( (m_flDie - gpGlobals->curtime <= 0.5) && (m_flDie - gpGlobals->curtime >= 0.3) )
	{
		CPASAttenuationFilter filter( this );
		enginesound->EmitSound( filter, entindex(), CHAN_VOICE, "squeek/sqk_die1.wav", 1, ATTN_NORM, 0, 100 + random->RandomInt( 0, 0x3F ) );
		CSoundEnt::InsertSound( SOUND_COMBAT, GetAbsOrigin(), 256, 0.25 );
	}

	// higher pitch as squeeker gets closer to detonation time
	float flpitch = 155.0 - 60.0 * ( (m_flDie - gpGlobals->curtime) / SQUEEK_DETONATE_DELAY );
	if ( flpitch < 80 )
		flpitch = 80;

	if ( GetEnemy() != NULL )
	{
		if ( FVisible( GetEnemy() ) )
		{
			m_vecTarget = GetEnemy()->EyePosition() - GetAbsOrigin();
			VectorNormalize( m_vecTarget );
		}

		float flVel = GetAbsVelocity().Length();
		float flAdj = 50.0 / ( flVel + 10.0 );

		if ( flAdj > 1.2 )
			flAdj = 1.2;
		
		// ALERT( at_console, "think : enemy\n");

		// ALERT( at_console, "%.0f %.2f %.2f %.2f\n", flVel, m_vecTarget.x, m_vecTarget.y, m_vecTarget.z );

		SetAbsVelocity( GetAbsVelocity() * flAdj + (m_vecTarget * 300) );
	}

	if ( GetFlags() & FL_ONGROUND )
	{
		SetLocalAngularVelocity( QAngle( 0, 0, 0 ) );
	}
	else
	{
		QAngle angVel = GetLocalAngularVelocity();
		if ( angVel == QAngle( 0, 0, 0 ) )
		{
			angVel.x = random->RandomFloat( -100, 100 );
			angVel.z = random->RandomFloat( -100, 100 );
			SetLocalAngularVelocity( angVel );
		}
	}

	if ( ( GetAbsOrigin() - m_posPrev ).Length() < 1.0 )
	{
		Vector vecVel = GetAbsVelocity();
		vecVel.x = random->RandomFloat( -100, 100 );
		vecVel.y = random->RandomFloat( -100, 100 );
		SetAbsVelocity( vecVel );
	}

	m_posPrev = GetAbsOrigin();

	QAngle angles;
	VectorAngles( GetAbsVelocity(), angles );
	angles.z = 0;
	angles.x = 0;
	SetAbsAngles( angles );
}
Beispiel #18
0
void C_ASW_Sentry_Top::Scan()
{
	C_ASW_Sentry_Base * RESTRICT pBase = GetSentryBase();
	if ( !pBase )
	{
		if ( m_hRadiusDisplay )
		{
			ParticleProp()->StopEmissionAndDestroyImmediately( m_hRadiusDisplay );
			m_hRadiusDisplay = NULL;
		}
		if ( m_hWarningLight )
		{
			ParticleProp()->StopEmissionAndDestroyImmediately( m_hWarningLight );
			m_hWarningLight = NULL;
		}
		return;
	}

	if ( pBase->GetAmmo() <= 0 )
	{
		if ( m_hRadiusDisplay )
		{
			ParticleProp()->StopEmissionAndDestroyImmediately( m_hRadiusDisplay );
			m_hRadiusDisplay = NULL;

			if ( m_hWarningLight )
			{
				ParticleProp()->StopEmissionAndDestroyImmediately( m_hWarningLight );
				m_hWarningLight = NULL;
			}

			if ( !m_hWarningLight )
			{
				m_hWarningLight = ParticleProp()->Create( "sentry_light_noammo", PATTACH_ABSORIGIN_FOLLOW );
				if ( m_hWarningLight )
				{
					ParticleProp()->AddControlPoint( m_hWarningLight, 0, this, PATTACH_POINT_FOLLOW, "attach_light" );
				}
			}
		}
		return;
	}
	else if ( !m_bLowAmmo && m_hWarningLight )
	{
		if ( m_hWarningLight )
		{
			m_hWarningLight->StopEmission(false, false , true);
			m_hWarningLight = NULL;
		}
	}

	//if( gpGlobals->curtime >= m_flTimeNextScanPing )
	//{
	//	m_flTimeNextScanPing = gpGlobals->curtime + 1.0f;
	//}

	QAngle	scanAngle;
	Vector	forward;
	Vector	vecEye = pBase->GetAbsOrigin() + Vector( 0, 0, 38 );// + m_vecLightOffset;

	if ( !m_hRadiusDisplay )
	{
		// this sets up the outter, "heavier" lines that make up the edges and the middle
		m_hRadiusDisplay = ParticleProp()->Create( "sentry_radius_display_beam", PATTACH_CUSTOMORIGIN );
		m_hRadiusDisplay->SetControlPoint( 0, vecEye );

		// Draw the outer extents
		scanAngle = pBase->GetAbsAngles();
		scanAngle.y -= GetSentryAngle();
		AngleVectors( scanAngle, &forward, NULL, NULL );
		CreateRadiusBeamEdges( vecEye, forward, 1 );

		scanAngle = pBase->GetAbsAngles();
		scanAngle.y += GetSentryAngle();
		AngleVectors( scanAngle, &forward, NULL, NULL );
		CreateRadiusBeamEdges( vecEye, forward, 2 );

		// scanAngle = pBase->GetAbsAngles();
		// AngleVectors( scanAngle, &forward, NULL, NULL );
		CreateRadiusBeamEdges( vecEye, pBase->Forward(), 3 );

		// create the sweeping beam control points
		ParticleProp()->AddControlPoint( m_hRadiusDisplay, 4, this, PATTACH_CUSTOMORIGIN );
		m_hRadiusDisplay->SetControlPointEntity( 4, this );
		ParticleProp()->AddControlPoint( m_hRadiusDisplay, 5, this, PATTACH_CUSTOMORIGIN );
		m_hRadiusDisplay->SetControlPointEntity( 5, this );
	}

	if ( m_hRadiusDisplay )
	{
		// now move the sweeping beams
		QAngle baseAngle = pBase->GetAbsAngles();
		baseAngle.y = m_fPrevDeployYaw;
		if ( m_fDeployYaw != m_fPrevDeployYaw )
		{
			//baseAngle.y = Approach( m_fDeployYaw, m_fPrevDeployYaw, 20.0f );
			//m_fPrevDeployYaw = baseAngle.y;

			float flDeltatime = 1.0f;
			float flDir = m_fDeployYaw > m_fPrevDeployYaw ? 1 : -1 ;
			float flDist = fabs(m_fDeployYaw - m_fPrevDeployYaw);

			if (flDist > 180)
			{
				flDist = 360 - flDist;
				flDir = -flDir;
			}

			// set our turn rate depending on if we have an enemy or not
			float fTurnRate = 10.0f;//ASW_SENTRY_TURNRATE * 0.5f;

			if (fabs(flDist) < flDeltatime * fTurnRate)
			{
				m_fPrevDeployYaw = m_fDeployYaw;
			}
			else
			{
				// turn it		
				m_fPrevDeployYaw += flDeltatime * fTurnRate * flDir;
			}

			if (m_fPrevDeployYaw < 0)
				m_fPrevDeployYaw += 360;
			else if (m_fPrevDeployYaw >= 360)
				m_fPrevDeployYaw -= 360;

			baseAngle.y = m_fPrevDeployYaw;
		}

		AngleVectors( baseAngle + QAngle( 0, -GetSentryAngle(), 0), &forward, NULL, NULL );
		AdjustRadiusBeamEdges( vecEye, forward, 1 );

		AngleVectors( baseAngle + QAngle( 0, GetSentryAngle(), 0), &forward, NULL, NULL );
		AdjustRadiusBeamEdges( vecEye, forward, 2 );

		AngleVectors( baseAngle, &forward, NULL, NULL );
		AdjustRadiusBeamEdges( vecEye, forward, 3 );

		scanAngle = baseAngle;
		scanAngle.y += GetSentryAngle() * sin( gpGlobals->curtime * 3.0f );

		Vector	vecBase = pBase->GetAbsOrigin() + Vector( 0, 0, 2 );// + m_vecLightOffset;
		AngleVectors( scanAngle, &forward, NULL, NULL );

		m_hRadiusDisplay->SetControlPoint( 4, vecBase + forward * 190.0f );
		m_hRadiusDisplay->SetControlPoint( 5, vecBase + forward * 80.0f );
	}
}
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : *pPlayer - 
//-----------------------------------------------------------------------------
void CWeaponBugBait::ThrowGrenade( CBasePlayer *pPlayer )
{
	Vector	vForward, vRight, vUp, vThrowPos, vThrowVel;
	
	pPlayer->EyeVectors( &vForward, &vRight, &vUp );

	vThrowPos = pPlayer->EyePosition();

	vThrowPos += vForward * 18.0f;
	vThrowPos += vRight * 12.0f;

	pPlayer->GetVelocity( &vThrowVel, NULL );
	vThrowVel += vForward * 1000;

	CGrenadeBugBait *pGrenade = BugBaitGrenade_Create( vThrowPos, vec3_angle, vThrowVel, QAngle(600,random->RandomInt(-1200,1200),0), pPlayer );

	if ( pGrenade != NULL )
	{
		// If the shot is clear to the player, give the missile a grace period
		trace_t	tr;
		UTIL_TraceLine( pPlayer->EyePosition(), pPlayer->EyePosition() + ( vForward * 128 ), MASK_SHOT, this, COLLISION_GROUP_NONE, &tr );
		
		if ( tr.fraction == 1.0 )
		{
			pGrenade->SetGracePeriod( 0.1f );
		}
	}

	m_bRedraw = true;
}
//-----------------------------------------------------------------------------
// Purpose: Crane rotates around with +left and +right, and extends/retracts 
//			the cable with +forward and +back.
//-----------------------------------------------------------------------------
void CPropCannon::DriveCannon( int iDriverButtons, int iButtonsPressed )
{
	bool bWasExtending = m_bExtending;

	// Handle rotation of the crane
	if ( iDriverButtons & IN_MOVELEFT )
	{
		// Try adding some randomness to make it feel shaky? 
		float flTurnAdd = m_flTurnAccel;
		// If we're turning back on ourselves, use decel speed
		if ( m_flTurn < 0 )
		{
			flTurnAdd = MAX( flTurnAdd, m_flTurnDecel );
		}

		m_flTurn = UTIL_Approach( m_flMaxTurnSpeed, m_flTurn, flTurnAdd * gpGlobals->frametime );

		m_iTurning = CANNON_TURNING_LEFT;
	}
	else if ( iDriverButtons & IN_MOVERIGHT )
	{
		// Try adding some randomness to make it feel shaky?
		float flTurnAdd = m_flTurnAccel;
		// If we're turning back on ourselves, increase the rate
		if ( m_flTurn > 0 )
		{
			flTurnAdd = MAX( flTurnAdd, m_flTurnDecel );
		}
		m_flTurn = UTIL_Approach( -m_flMaxTurnSpeed, m_flTurn, flTurnAdd * gpGlobals->frametime );

		m_iTurning = CANNON_TURNING_RIGHT;
	}
	else
	{
		m_flTurn = UTIL_Approach( 0, m_flTurn, m_flTurnDecel * gpGlobals->frametime );
		m_iTurning = CANNON_TURNING_NOT;
	}

	SetLocalAngularVelocity( QAngle(0,m_flTurn * 10,0) );

	// Handle extension / retraction of the arm
	if ( iDriverButtons & IN_FORWARD )
	{
		m_flExtensionRate = UTIL_Approach( m_flMaxExtensionSpeed, m_flExtensionRate, m_flExtensionAccel * gpGlobals->frametime );
		m_bExtending = true;
	}
	else if ( iDriverButtons & IN_BACK )
	{
		m_flExtensionRate = UTIL_Approach( -m_flMaxExtensionSpeed, m_flExtensionRate, m_flExtensionAccel * gpGlobals->frametime );
		m_bExtending = true;
	}
	else
	{
		m_flExtensionRate = UTIL_Approach( 0, m_flExtensionRate, m_flExtensionDecel * gpGlobals->frametime );
		m_bExtending = false;
	}

	//Msg("Turn: %f\nExtensionRate: %f\n", m_flTurn, m_flExtensionRate );

	//If we're holding down an attack button, update our state
	if ( iButtonsPressed & (IN_ATTACK | IN_ATTACK2) )
	{
		if ( m_flNextAttackTime <= gpGlobals->curtime )
		{
			LaunchProjectile();
		}
	}

	float flSpeedPercentage = clamp( fabs(m_flTurn) / m_flMaxTurnSpeed, 0, 1 );
	vbs_sound_update_t params;
	params.Defaults();
	params.bThrottleDown = (m_iTurning != CANNON_TURNING_NOT);
	params.flCurrentSpeedFraction = flSpeedPercentage;
	params.flWorldSpaceSpeed = 0;

	m_ServerVehicle.SoundUpdate( params );

	// Play sounds for arm extension / retraction
	if ( m_bExtending && !bWasExtending )
	{
		m_ServerVehicle.StopSound( VS_ENGINE2_STOP );
		m_ServerVehicle.PlaySound( VS_ENGINE2_START );
	}
	else if ( !m_bExtending && bWasExtending )
	{
		m_ServerVehicle.StopSound( VS_ENGINE2_START );
		m_ServerVehicle.PlaySound( VS_ENGINE2_STOP );
	}
}
//-----------------------------------------------------------------------------
// Purpose: Do the headlight
//-----------------------------------------------------------------------------
void CFlashlightEffect::UpdateLightNew(const Vector &vecPos, const Vector &vecForward, const Vector &vecRight, const Vector &vecUp )
{
	VPROF_BUDGET( "CFlashlightEffect::UpdateLightNew", VPROF_BUDGETGROUP_SHADOW_DEPTH_TEXTURING );

	FlashlightState_t state;

	// We will lock some of the flashlight params if player is on a ladder, to prevent oscillations due to the trace-rays
	bool bPlayerOnLadder = ( C_BasePlayer::GetLocalPlayer()->GetMoveType() == MOVETYPE_LADDER );

	const float flEpsilon = 0.1f;			// Offset flashlight position along vecUp
	const float flDistCutoff = 128.0f;
	const float flDistDrag = 0.2;

	CTraceFilterSkipPlayerAndViewModel traceFilter;
	float flOffsetY = r_flashlightoffsety.GetFloat();

	if( r_swingflashlight.GetBool() )
	{
		// This projects the view direction backwards, attempting to raise the vertical
		// offset of the flashlight, but only when the player is looking down.
		Vector vecSwingLight = vecPos + vecForward * -12.0f;
		if( vecSwingLight.z > vecPos.z )
		{
			flOffsetY += (vecSwingLight.z - vecPos.z);
		}
	}

	Vector vOrigin = vecPos + flOffsetY * vecUp;

	// Not on ladder...trace a hull
	if ( !bPlayerOnLadder ) 
	{
		trace_t pmOriginTrace;
		UTIL_TraceHull( vecPos, vOrigin, Vector(-4, -4, -4), Vector(4, 4, 4), MASK_SOLID & ~(CONTENTS_HITBOX), &traceFilter, &pmOriginTrace );

		if ( pmOriginTrace.DidHit() )
		{
			vOrigin = vecPos;
		}
	}
	else // on ladder...skip the above hull trace
	{
		vOrigin = vecPos;
	}

	// Now do a trace along the flashlight direction to ensure there is nothing within range to pull back from
	int iMask = MASK_OPAQUE_AND_NPCS;
	iMask &= ~CONTENTS_HITBOX;
	iMask |= CONTENTS_WINDOW;

	// VR SOURCE - Use weap angle forward vector here
	
	Vector vTarget;

	/*if ( VR_Controller()->initialized() && VR_Controller()->hasWeaponTracking() ) 
	{
		vTarget = vecPos + 
	} 
	else 
	{*/
		vTarget = vecPos + vecForward * r_flashlightfar.GetFloat();
	// }
	

	// Work with these local copies of the basis for the rest of the function
	Vector vDir   = vTarget - vOrigin;
	Vector vRight = vecRight;
	Vector vUp    = vecUp;
	VectorNormalize( vDir   );
	VectorNormalize( vRight );
	VectorNormalize( vUp    );

	// Orthonormalize the basis, since the flashlight texture projection will require this later...
	vUp -= DotProduct( vDir, vUp ) * vDir;
	VectorNormalize( vUp );
	vRight -= DotProduct( vDir, vRight ) * vDir;
	VectorNormalize( vRight );
	vRight -= DotProduct( vUp, vRight ) * vUp;
	VectorNormalize( vRight );

	AssertFloatEquals( DotProduct( vDir, vRight ), 0.0f, 1e-3 );
	AssertFloatEquals( DotProduct( vDir, vUp    ), 0.0f, 1e-3 );
	AssertFloatEquals( DotProduct( vRight, vUp  ), 0.0f, 1e-3 );

	trace_t pmDirectionTrace;
	UTIL_TraceHull( vOrigin, vTarget, Vector( -4, -4, -4 ), Vector( 4, 4, 4 ), iMask, &traceFilter, &pmDirectionTrace );

	if ( r_flashlightvisualizetrace.GetBool() == true )
	{
		debugoverlay->AddBoxOverlay( pmDirectionTrace.endpos, Vector( -4, -4, -4 ), Vector( 4, 4, 4 ), QAngle( 0, 0, 0 ), 0, 0, 255, 16, 0 );
		debugoverlay->AddLineOverlay( vOrigin, pmDirectionTrace.endpos, 255, 0, 0, false, 0 );
	}

	float flDist = (pmDirectionTrace.endpos - vOrigin).Length();
	if ( flDist < flDistCutoff )
	{
		// We have an intersection with our cutoff range
		// Determine how far to pull back, then trace to see if we are clear
		float flPullBackDist = bPlayerOnLadder ? r_flashlightladderdist.GetFloat() : flDistCutoff - flDist;	// Fixed pull-back distance if on ladder
		m_flDistMod = Lerp( flDistDrag, m_flDistMod, flPullBackDist );
		
		if ( !bPlayerOnLadder )
		{
			trace_t pmBackTrace;
			UTIL_TraceHull( vOrigin, vOrigin - vDir*(flPullBackDist-flEpsilon), Vector( -4, -4, -4 ), Vector( 4, 4, 4 ), iMask, &traceFilter, &pmBackTrace );
			if( pmBackTrace.DidHit() )
			{
				// We have an intersection behind us as well, so limit our m_flDistMod
				float flMaxDist = (pmBackTrace.endpos - vOrigin).Length() - flEpsilon;
				if( m_flDistMod > flMaxDist )
					m_flDistMod = flMaxDist;
			}
		}
	}
	else
	{
		m_flDistMod = Lerp( flDistDrag, m_flDistMod, 0.0f );
	}
	vOrigin = vOrigin - vDir * m_flDistMod;

	state.m_vecLightOrigin = vOrigin;

	BasisToQuaternion( vDir, vRight, vUp, state.m_quatOrientation );

	state.m_fQuadraticAtten = r_flashlightquadratic.GetFloat();

	bool bFlicker = false;

#ifdef HL2_EPISODIC
	C_BaseHLPlayer *pPlayer = (C_BaseHLPlayer *)C_BasePlayer::GetLocalPlayer();
	if ( pPlayer )
	{
		float flBatteryPower = ( pPlayer->m_HL2Local.m_flFlashBattery >= 0.0f ) ? ( pPlayer->m_HL2Local.m_flFlashBattery ) : pPlayer->m_HL2Local.m_flSuitPower;
		if ( flBatteryPower <= 10.0f )
		{
			float flScale;
			if ( flBatteryPower >= 0.0f )
			{	
				flScale = ( flBatteryPower <= 4.5f ) ? SimpleSplineRemapVal( flBatteryPower, 4.5f, 0.0f, 1.0f, 0.0f ) : 1.0f;
			}
			else
			{
				flScale = SimpleSplineRemapVal( flBatteryPower, 10.0f, 4.8f, 1.0f, 0.0f );
			}
			
			flScale = clamp( flScale, 0.0f, 1.0f );

			if ( flScale < 0.35f )
			{
				float flFlicker = cosf( gpGlobals->curtime * 6.0f ) * sinf( gpGlobals->curtime * 15.0f );
				
				if ( flFlicker > 0.25f && flFlicker < 0.75f )
				{
					// On
					state.m_fLinearAtten = r_flashlightlinear.GetFloat() * flScale;
				}
				else
				{
					// Off
					state.m_fLinearAtten = 0.0f;
				}
			}
			else
			{
				float flNoise = cosf( gpGlobals->curtime * 7.0f ) * sinf( gpGlobals->curtime * 25.0f );
				state.m_fLinearAtten = r_flashlightlinear.GetFloat() * flScale + 1.5f * flNoise;
			}

			state.m_fHorizontalFOVDegrees = r_flashlightfov.GetFloat() - ( 16.0f * (1.0f-flScale) );
			state.m_fVerticalFOVDegrees = r_flashlightfov.GetFloat() - ( 16.0f * (1.0f-flScale) );
			
			bFlicker = true;
		}
	}
#endif // HL2_EPISODIC

	if ( bFlicker == false )
	{
		state.m_fLinearAtten = r_flashlightlinear.GetFloat();
		state.m_fHorizontalFOVDegrees = r_flashlightfov.GetFloat();
		state.m_fVerticalFOVDegrees = r_flashlightfov.GetFloat();
	}

	state.m_fConstantAtten = r_flashlightconstant.GetFloat();
	state.m_Color[0] = 1.0f;
	state.m_Color[1] = 1.0f;
	state.m_Color[2] = 1.0f;
	state.m_Color[3] = r_flashlightambient.GetFloat();
	state.m_NearZ = r_flashlightnear.GetFloat() + m_flDistMod;	// Push near plane out so that we don't clip the world when the flashlight pulls back 
	state.m_FarZ = r_flashlightfar.GetFloat();
	state.m_bEnableShadows = r_flashlightdepthtexture.GetBool();
	state.m_flShadowMapResolution = r_flashlightdepthres.GetInt();

	state.m_pSpotlightTexture = m_FlashlightTexture;
	state.m_nSpotlightTextureFrame = 0;

	state.m_flShadowAtten = r_flashlightshadowatten.GetFloat();
	state.m_flShadowSlopeScaleDepthBias = mat_slopescaledepthbias_shadowmap.GetFloat();
	state.m_flShadowDepthBias = mat_depthbias_shadowmap.GetFloat();

	if( m_FlashlightHandle == CLIENTSHADOW_INVALID_HANDLE )
	{
		m_FlashlightHandle = g_pClientShadowMgr->CreateFlashlight( state );
	}
	else
	{
		if( !r_flashlightlockposition.GetBool() )
		{
			g_pClientShadowMgr->UpdateFlashlightState( m_FlashlightHandle, state );
		}
	}
	
	g_pClientShadowMgr->UpdateProjectedTexture( m_FlashlightHandle, true );
	
	// Kill the old flashlight method if we have one.
	LightOffOld();

#ifndef NO_TOOLFRAMEWORK
	if ( clienttools->IsInRecordingMode() )
	{
		KeyValues *msg = new KeyValues( "FlashlightState" );
		msg->SetFloat( "time", gpGlobals->curtime );
		msg->SetInt( "entindex", m_nEntIndex );
		msg->SetInt( "flashlightHandle", m_FlashlightHandle );
		msg->SetPtr( "flashlightState", &state );
		ToolFramework_PostToolMessage( HTOOLHANDLE_INVALID, msg );
		msg->deleteThis();
	}
#endif
}
void CNPC_Hydra::GetDesiredImpaledPosition( Vector *vecOrigin, QAngle *vecAngles )
{
	*vecOrigin = m_body[m_body.Count()-2].vecPos;
	*vecAngles = QAngle(0,0,0);
}
/*
==============================
CAM_Think

==============================
*/
void CInput::CAM_Think( void )
{
	VPROF("CAM_Think");
	//
	if ( m_pCameraThirdData )
	{
		return CAM_CameraThirdThink();
	}

	Vector idealAngles;
	Vector camOffset;
	float flSensitivity;
	QAngle viewangles;
	
	switch( cam_command.GetInt() )
	{
	case CAM_COMMAND_TOTHIRDPERSON:
		CAM_ToThirdPerson();
		break;
		
	case CAM_COMMAND_TOFIRSTPERSON:
		CAM_ToFirstPerson();
		break;
		
	case CAM_COMMAND_NONE:
	default:
		break;
	}

	//All this code after this comment has to do with thirdperson

	g_ThirdPersonManager.Update();

	if( !m_fCameraInThirdPerson )
		return;

	// In Maya-mode
	if ( Is_CAM_ThirdPerson_MayaMode() )
	{
		// Unless explicitly moving the camera, don't move it
		m_fCameraInterceptingMouse = m_fCameraMovingWithMouse =
			vgui::input()->IsKeyDown( KEY_LALT ) || vgui::input()->IsKeyDown( KEY_RALT );
		if ( !m_fCameraMovingWithMouse )
			return;

		// Zero-out camera-control kbutton_t structures
		memset( &cam_pitchup, 0, sizeof( cam_pitchup ) );
		memset( &cam_pitchdown, 0, sizeof( cam_pitchdown ) );
		memset( &cam_yawleft, 0, sizeof( cam_yawleft ) );
		memset( &cam_yawright, 0, sizeof( cam_yawright ) );
		memset( &cam_in, 0, sizeof( cam_in ) );
		memset( &cam_out, 0, sizeof( cam_out ) );

		// Unless left or right mouse button is down, don't do anything
#ifndef _XBOX
		if ( /* Left+Middle Button Down */ vgui::input()->IsMouseDown( MOUSE_LEFT ) && vgui::input()->IsMouseDown( MOUSE_MIDDLE ) )
		{
			// Do only zoom in/out camera adjustment
			m_fCameraDistanceMove = true;
		}
		else if ( /* Left Button Down */ vgui::input()->IsMouseDown( MOUSE_LEFT ) )
		{
			// Do only rotational camera movement
			m_fCameraDistanceMove = false;
		}
		else if ( /* Right Button Down */ vgui::input()->IsMouseDown( MOUSE_RIGHT ) )
		{
			// Do only zoom in/out camera adjustment
			m_fCameraDistanceMove = true;
		}
		else
		{
			// Neither left or right buttons down, don't do anything
			ResetMouse();
			return;
		}
#endif
	}
	
	idealAngles[ PITCH ] = cam_idealpitch.GetFloat();
	idealAngles[ YAW ]   = cam_idealyaw.GetFloat();
	idealAngles[ DIST ]  = cam_idealdist.GetFloat();

	//
	//movement of the camera with the mouse
	//
	if ( m_fCameraMovingWithMouse )
	{
		int cpx, cpy;
#ifndef _XBOX		
		//get windows cursor position
		GetMousePos (cpx, cpy);
#else
		//xboxfixme
		cpx = cpy = 0;
#endif
		
		m_nCameraX = cpx;
		m_nCameraY = cpy;
		
		//check for X delta values and adjust accordingly
		//eventually adjust YAW based on amount of movement
		//don't do any movement of the cam using YAW/PITCH if we are zooming in/out the camera	
		if (!m_fCameraDistanceMove)
		{
			int x, y;
			GetWindowCenter( x,  y );
			
			//keep the camera within certain limits around the player (ie avoid certain bad viewing angles)  
			if (m_nCameraX>x)
			{
				//if ((idealAngles[YAW]>=225.0)||(idealAngles[YAW]<135.0))
				if (idealAngles[YAW]<c_maxyaw.GetFloat())
				{
					idealAngles[ YAW ] += (CAM_ANGLE_MOVE)*((m_nCameraX-x)/2);
				}
				if (idealAngles[YAW]>c_maxyaw.GetFloat())
				{
					
					idealAngles[YAW]=c_maxyaw.GetFloat();
				}
			}
			else if (m_nCameraX<x)
			{
				//if ((idealAngles[YAW]<=135.0)||(idealAngles[YAW]>225.0))
				if (idealAngles[YAW]>c_minyaw.GetFloat())
				{
					idealAngles[ YAW ] -= (CAM_ANGLE_MOVE)* ((x-m_nCameraX)/2);
					
				}
				if (idealAngles[YAW]<c_minyaw.GetFloat())
				{
					idealAngles[YAW]=c_minyaw.GetFloat();
					
				}
			}
			
			//check for y delta values and adjust accordingly
			//eventually adjust PITCH based on amount of movement
			//also make sure camera is within bounds
			if (m_nCameraY > y)
			{
				if(idealAngles[PITCH]<c_maxpitch.GetFloat())
				{
					idealAngles[PITCH] +=(CAM_ANGLE_MOVE)* ((m_nCameraY-y)/2);
				}
				if (idealAngles[PITCH]>c_maxpitch.GetFloat())
				{
					idealAngles[PITCH]=c_maxpitch.GetFloat();
				}
			}
			else if (m_nCameraY<y)
			{
				if (idealAngles[PITCH]>c_minpitch.GetFloat())
				{
					idealAngles[PITCH] -= (CAM_ANGLE_MOVE)*((y-m_nCameraY)/2);
				}
				if (idealAngles[PITCH]<c_minpitch.GetFloat())
				{
					idealAngles[PITCH]=c_minpitch.GetFloat();
				}
			}
			
			//set old mouse coordinates to current mouse coordinates
			//since we are done with the mouse
			
			if ( ( flSensitivity = gHUD.GetSensitivity() ) != 0 )
			{
				m_nCameraOldX=m_nCameraX*flSensitivity;
				m_nCameraOldY=m_nCameraY*flSensitivity;
			}
			else
			{
				m_nCameraOldX=m_nCameraX;
				m_nCameraOldY=m_nCameraY;
			}
#ifndef _XBOX
			ResetMouse();
#endif
		}
	}
	
	//Nathan code here
	if( input->KeyState( &cam_pitchup ) )
		idealAngles[ PITCH ] += cam_idealdelta.GetFloat();
	else if( input->KeyState( &cam_pitchdown ) )
		idealAngles[ PITCH ] -= cam_idealdelta.GetFloat();
	
	if( input->KeyState( &cam_yawleft ) )
		idealAngles[ YAW ] -= cam_idealdelta.GetFloat();
	else if( input->KeyState( &cam_yawright ) )
		idealAngles[ YAW ] += cam_idealdelta.GetFloat();
	
	if( input->KeyState( &cam_in ) )
	{
		idealAngles[ DIST ] -= 2*cam_idealdelta.GetFloat();
		if( idealAngles[ DIST ] < CAM_MIN_DIST )
		{
			// If we go back into first person, reset the angle
			idealAngles[ PITCH ] = 0;
			idealAngles[ YAW ] = 0;
			idealAngles[ DIST ] = CAM_MIN_DIST;
		}
		
	}
	else if( input->KeyState( &cam_out ) )
		idealAngles[ DIST ] += 2*cam_idealdelta.GetFloat();
	
	if (m_fCameraDistanceMove)
	{
		int x, y;
		GetWindowCenter( x, y );

		if (m_nCameraY>y)
		{
			if(idealAngles[ DIST ]<c_maxdistance.GetFloat())
			{
				idealAngles[ DIST ] +=cam_idealdelta.GetFloat() * ((m_nCameraY-y)/2);
			}
			if (idealAngles[ DIST ]>c_maxdistance.GetFloat())
			{
				idealAngles[ DIST ]=c_maxdistance.GetFloat();
			}
		}
		else if (m_nCameraY<y)
		{
			if (idealAngles[ DIST ]>c_mindistance.GetFloat())
			{
				idealAngles[ DIST ] -= (cam_idealdelta.GetFloat())*((y-m_nCameraY)/2);
			}
			if (idealAngles[ DIST ]<c_mindistance.GetFloat())
			{
				idealAngles[ DIST ]=c_mindistance.GetFloat();
			}
		}
		//set old mouse coordinates to current mouse coordinates
		//since we are done with the mouse
		m_nCameraOldX=m_nCameraX*gHUD.GetSensitivity();
		m_nCameraOldY=m_nCameraY*gHUD.GetSensitivity();
#ifndef _XBOX
		ResetMouse();
#endif
	}

	// Obtain engine view angles and if they popped while the camera was static,
	// fix the camera angles as well
	engine->GetViewAngles( viewangles );
	static QAngle s_oldAngles = viewangles;
	if ( Is_CAM_ThirdPerson_MayaMode() && ( s_oldAngles != viewangles ) )
	{
		idealAngles[ PITCH ] += s_oldAngles[ PITCH ] - viewangles[ PITCH ];
		idealAngles[  YAW  ] += s_oldAngles[  YAW  ] - viewangles[  YAW  ];
		s_oldAngles = viewangles;
	}

	// bring the pitch values back into a range that MoveToward can handle
	if ( idealAngles[ PITCH ] > 180 )
		idealAngles[ PITCH ] -= 360;
	else if ( idealAngles[ PITCH ] < -180 )
		idealAngles[ PITCH ] += 360;

	// bring the yaw values back into a range that MoveToward can handle
	// --
	// Vitaliy: going with >= 180 and <= -180.
	// This introduces a potential discontinuity when looking directly at model face
	// as camera yaw will be jumping from +180 to -180 and back, but when working with
	// the camera allows smooth rotational transitions from left to right and back.
	// Otherwise one of the transitions that has ">"-comparison will be locked.
	// --
	if ( idealAngles[ YAW ] >= 180 )
		idealAngles[ YAW ] -= 360;
	else if ( idealAngles[ YAW ] <= -180 )
		idealAngles[ YAW ] += 360;

	// clamp pitch, yaw and dist...
	idealAngles[ PITCH ] = clamp( idealAngles[ PITCH ], c_minpitch.GetFloat(), c_maxpitch.GetFloat() );
	idealAngles[ YAW ]   = clamp( idealAngles[ YAW ], c_minyaw.GetFloat(), c_maxyaw.GetFloat() );
	idealAngles[ DIST ]  = clamp( idealAngles[ DIST ], c_mindistance.GetFloat(), c_maxdistance.GetFloat() );

	// update ideal angles
	cam_idealpitch.SetValue( idealAngles[ PITCH ] );
	cam_idealyaw.SetValue( idealAngles[ YAW ] );
	cam_idealdist.SetValue( idealAngles[ DIST ] );
	
	// Move the CameraOffset "towards" the idealAngles
	// Note: CameraOffset = viewangle + idealAngle
	VectorCopy( g_ThirdPersonManager.GetCameraOffsetAngles(), camOffset );
	
	if( cam_snapto.GetInt() )
	{
		camOffset[ YAW ] = cam_idealyaw.GetFloat() + viewangles[ YAW ];
		camOffset[ PITCH ] = cam_idealpitch.GetFloat() + viewangles[ PITCH ];
		camOffset[ DIST ] = cam_idealdist.GetFloat();
	}
	else
	{
		float lag = MAX( 1, 1 + cam_ideallag.GetFloat() );

		if( camOffset[ YAW ] - viewangles[ YAW ] != cam_idealyaw.GetFloat() )
			camOffset[ YAW ] = MoveToward( camOffset[ YAW ], cam_idealyaw.GetFloat() + viewangles[ YAW ], lag );
		
		if( camOffset[ PITCH ] - viewangles[ PITCH ] != cam_idealpitch.GetFloat() )
			camOffset[ PITCH ] = MoveToward( camOffset[ PITCH ], cam_idealpitch.GetFloat() + viewangles[ PITCH ], lag );
		
		if( abs( camOffset[ DIST ] - cam_idealdist.GetFloat() ) < 2.0 )
			camOffset[ DIST ] = cam_idealdist.GetFloat();
		else
			camOffset[ DIST ] += ( cam_idealdist.GetFloat() - camOffset[ DIST ] ) / lag;
	}

	// move the camera closer to the player if it hit something
	if ( cam_collision.GetInt() )
	{
		QAngle desiredCamAngles = QAngle( camOffset[ PITCH ], camOffset[ YAW ], camOffset[ DIST ] );

		if ( g_ThirdPersonManager.IsOverridingThirdPerson() == false )
		{
			desiredCamAngles = viewangles;
		}

		g_ThirdPersonManager.PositionCamera( C_BasePlayer::GetLocalPlayer(), desiredCamAngles );
    }

	if ( cam_showangles.GetInt() )
	{
		engine->Con_NPrintf( 4, "Pitch: %6.1f   Yaw: %6.1f %38s", viewangles[ PITCH ], viewangles[ YAW ], "view angles" );
		engine->Con_NPrintf( 6, "Pitch: %6.1f   Yaw: %6.1f   Dist: %6.1f %19s", cam_idealpitch.GetFloat(), cam_idealyaw.GetFloat(), cam_idealdist.GetFloat(), "ideal angles" );
		engine->Con_NPrintf( 8, "Pitch: %6.1f   Yaw: %6.1f   Dist: %6.1f %16s", g_ThirdPersonManager.GetCameraOffsetAngles()[ PITCH ], g_ThirdPersonManager.GetCameraOffsetAngles()[ YAW ], g_ThirdPersonManager.GetCameraOffsetAngles()[ DIST ], "camera offset" );
	}

	//g_ThirdPersonManager.SetCameraOffsetAngles( camOffset );
	g_ThirdPersonManager.SetCameraOffsetAngles(camOffset);
}
Beispiel #24
0
//=========================================================
// SonicAttack
//=========================================================
void CNPC_Houndeye::SonicAttack ( void )
{
	EmitSound( "NPC_Houndeye.SonicAttack" );

	if (m_pEnergyWave)
	{
		UTIL_Remove(m_pEnergyWave);
	}
	Vector vFacingDir = EyeDirection3D( );
	m_pEnergyWave = (CEnergyWave*)Create( "energy_wave", EyePosition(), GetLocalAngles() );
	m_flEndEnergyWaveTime = gpGlobals->curtime + 1; //<<TEMP>> magic
	m_pEnergyWave->SetAbsVelocity( 100*vFacingDir );

	CBaseEntity *pEntity = NULL;
	// iterate on all entities in the vicinity.
	for ( CEntitySphereQuery sphere( GetAbsOrigin(), HOUNDEYE_MAX_ATTACK_RADIUS ); pEntity = sphere.GetCurrentEntity(); sphere.NextEntity() )
	{
		if (pEntity->Classify()	== CLASS_HOUNDEYE)
		{
			continue;
		}

		if (pEntity->GetFlags() & FL_NOTARGET)
		{
			continue;
		}

		IPhysicsObject *pPhysicsObject = pEntity->VPhysicsGetObject();

		if ( pEntity->m_takedamage != DAMAGE_NO || pPhysicsObject)
		{
			// --------------------------
			// Adjust damage by distance
			// --------------------------
			float flDist = (pEntity->WorldSpaceCenter() - GetAbsOrigin()).Length();
			float flDamageAdjuster = 1-( flDist / HOUNDEYE_MAX_ATTACK_RADIUS );

			// --------------------------
			// Adjust damage by direction
			// --------------------------
			Vector forward;
			AngleVectors( GetAbsAngles(), &forward );
			Vector vEntDir		= (pEntity->GetAbsOrigin() - GetAbsOrigin());
			VectorNormalize(vEntDir);
			float flDotPr		= DotProduct(forward,vEntDir);
			flDamageAdjuster   *= flDotPr;

			if (flDamageAdjuster < 0)
			{
				continue;
			}

			// --------------------------
			// Adjust damage by visibility
			// --------------------------
			if ( !FVisible( pEntity ) )
			{
				if ( pEntity->IsPlayer() )
				{
					// if this entity is a client, and is not in full view, inflict half damage. We do this so that players still 
					// take the residual damage if they don't totally leave the houndeye's effective radius. We restrict it to clients
					// so that monsters in other parts of the level don't take the damage and get pissed.
					flDamageAdjuster *= 0.5;
				}
				else if ( !FClassnameIs( pEntity, "func_breakable" ) && !FClassnameIs( pEntity, "func_pushable" ) ) 
				{
					// do not hurt nonclients through walls, but allow damage to be done to breakables
					continue;
				}
			}

			// ------------------------------
			//  Apply the damage
			// ------------------------------
			if (pEntity->m_takedamage != DAMAGE_NO)
			{
				CTakeDamageInfo info( this, this, flDamageAdjuster * sk_Houndeye_dmg_blast.GetFloat(), DMG_SONIC | DMG_ALWAYSGIB );
				CalculateExplosiveDamageForce( &info, (pEntity->GetAbsOrigin() - GetAbsOrigin()), pEntity->GetAbsOrigin() );

				pEntity->TakeDamage( info );

				// Throw the player
				if ( pEntity->IsPlayer() )
				{
					Vector forward;
					AngleVectors( GetLocalAngles(), &forward );

					Vector vecVelocity = pEntity->GetAbsVelocity();
					vecVelocity	+= forward * 250 * flDamageAdjuster;
					vecVelocity.z = 300 * flDamageAdjuster;
					pEntity->SetAbsVelocity( vecVelocity );
					pEntity->ViewPunch( QAngle(random->RandomInt(-20,20), 0, random->RandomInt(-20,20)) );
				}
			}
			// ------------------------------
			//  Apply physics foces
			// ------------------------------
			IPhysicsObject *pPhysicsObject = pEntity->VPhysicsGetObject();
			if (pPhysicsObject)
			{
				float flForce	= flDamageAdjuster * 8000;
				pPhysicsObject->ApplyForceCenter( (vEntDir+Vector(0,0,0.2)) * flForce );
				pPhysicsObject->ApplyTorqueCenter( vEntDir * flForce );
			}
		}
	}
}
Beispiel #25
0
//-----------------------------------------------------------------------------
// Purpose: Moves the client pitch angle towards cl.idealpitch sent by the server.
// If the user is adjusting pitch manually, either with lookup/lookdown,
//   mlook and mouse, or klook and keyboard, pitch drifting is constantly stopped.
//-----------------------------------------------------------------------------
void CViewRender::DriftPitch (void)
{
	float		delta, move;

	C_BasePlayer *player = C_BasePlayer::GetLocalPlayer();
	if ( !player )
		return;

#if defined( REPLAY_ENABLED )
	if ( engine->IsHLTV() || g_pEngineClientReplay->IsPlayingReplayDemo() || ( player->GetGroundEntity() == NULL ) || engine->IsPlayingDemo() )
#else
	if ( engine->IsHLTV() || ( player->GetGroundEntity() == NULL ) || engine->IsPlayingDemo() )
#endif
	{
		m_PitchDrift.driftmove = 0;
		m_PitchDrift.pitchvel = 0;
		return;
	}

	// Don't count small mouse motion
	if ( m_PitchDrift.nodrift )
	{
		if ( fabs( input->GetLastForwardMove() ) < cl_forwardspeed.GetFloat() )
		{
			m_PitchDrift.driftmove = 0;
		}
		else
		{
			m_PitchDrift.driftmove += gpGlobals->frametime;
		}
	
		if ( m_PitchDrift.driftmove > v_centermove.GetFloat() )
		{
			StartPitchDrift ();
		}
		return;
	}
	
	// How far off are we
	delta = prediction->GetIdealPitch() - player->GetAbsAngles()[ PITCH ];
	if ( !delta )
	{
		m_PitchDrift.pitchvel = 0;
		return;
	}

	// Determine movement amount
	move = gpGlobals->frametime * m_PitchDrift.pitchvel;
	// Accelerate
	m_PitchDrift.pitchvel += gpGlobals->frametime * v_centerspeed.GetFloat();
	
	// Move predicted pitch appropriately
	if (delta > 0)
	{
		if ( move > delta )
		{
			m_PitchDrift.pitchvel = 0;
			move = delta;
		}
		player->SetLocalAngles( player->GetLocalAngles() + QAngle( move, 0, 0 ) );
	}
	else if ( delta < 0 )
	{
		if ( move > -delta )
		{
			m_PitchDrift.pitchvel = 0;
			move = -delta;
		}
		player->SetLocalAngles( player->GetLocalAngles() - QAngle( move, 0, 0 ) );
	}
}
//-----------------------------------------------------------------------------
// Purpose: Override for backpeddling
// Input  : dt - 
//-----------------------------------------------------------------------------
void CBasePlayerAnimState::ComputePoseParam_MoveYaw( CStudioHdr *pStudioHdr )
{
	VPROF( "CBasePlayerAnimState::ComputePoseParam_MoveYaw" );

	//Matt: Goldsrc style animations need to not rotate the model
	if ( m_AnimConfig.m_LegAnimType == LEGANIM_GOLDSRC )
	{
#ifndef CLIENT_DLL
		//Adrian: Make the model's angle match the legs so the hitboxes match on both sides.
		GetOuter()->SetLocalAngles( QAngle( 0, m_flCurrentFeetYaw, 0 ) );
#endif
	}

	// If using goldsrc-style animations where he's moving in the direction that his feet are facing,
	// we don't use move yaw.
	if ( m_AnimConfig.m_LegAnimType != LEGANIM_9WAY && m_AnimConfig.m_LegAnimType != LEGANIM_8WAY )
		return;

	// view direction relative to movement
	float flYaw;	 

	EstimateYaw();

	float ang = m_flEyeYaw;
	if ( ang > 180.0f )
	{
		ang -= 360.0f;
	}
	else if ( ang < -180.0f )
	{
		ang += 360.0f;
	}

	// calc side to side turning
	flYaw = ang - m_flGaitYaw;
	// Invert for mapping into 8way blend
	flYaw = -flYaw;
	flYaw = flYaw - (int)(flYaw / 360) * 360;

	if (flYaw < -180)
	{
		flYaw = flYaw + 360;
	}
	else if (flYaw > 180)
	{
		flYaw = flYaw - 360;
	}

	
	if ( m_AnimConfig.m_LegAnimType == LEGANIM_9WAY )
	{
#ifndef CLIENT_DLL
		//Adrian: Make the model's angle match the legs so the hitboxes match on both sides.
		GetOuter()->SetLocalAngles( QAngle( 0, m_flCurrentFeetYaw, 0 ) );
#endif

		int iMoveX = GetOuter()->LookupPoseParameter( pStudioHdr, "move_x" );
		int iMoveY = GetOuter()->LookupPoseParameter( pStudioHdr, "move_y" );
		if ( iMoveX < 0 || iMoveY < 0 )
			return;

		bool bIsMoving;
		float flPlaybackRate = CalcMovementPlaybackRate( &bIsMoving );

		// Setup the 9-way blend parameters based on our speed and direction.
		Vector2D vCurMovePose( 0, 0 );

		if ( bIsMoving )
		{
			vCurMovePose.x = cos( DEG2RAD( flYaw ) ) * flPlaybackRate;
			vCurMovePose.y = -sin( DEG2RAD( flYaw ) ) * flPlaybackRate;
		}

		GetOuter()->SetPoseParameter( pStudioHdr, iMoveX, vCurMovePose.x );
		GetOuter()->SetPoseParameter( pStudioHdr, iMoveY, vCurMovePose.y );

		m_vLastMovePose = vCurMovePose;
	}
	else
	{
		int iMoveYaw = GetOuter()->LookupPoseParameter( pStudioHdr, "move_yaw" );
		if ( iMoveYaw >= 0 )
		{
			GetOuter()->SetPoseParameter( pStudioHdr, iMoveYaw, flYaw );
			m_flLastMoveYaw = flYaw;

			// Now blend in his idle animation.
			// This makes the 8-way blend act like a 9-way blend by blending to 
			// an idle sequence as he slows down.
#if defined(CLIENT_DLL)
#ifndef INFESTED_DLL
			bool bIsMoving;
			CAnimationLayer *pLayer = m_pOuter->GetAnimOverlay( MAIN_IDLE_SEQUENCE_LAYER );
			
			pLayer->SetWeight( 1 - CalcMovementPlaybackRate( &bIsMoving ) );
			if ( !bIsMoving )
			{
				pLayer->SetWeight( 1 );
			}

			if ( ShouldChangeSequences() )
			{
				// Whenever this layer stops blending, we can choose a new idle sequence to blend to, so he 
				// doesn't always use the same idle.
				if ( pLayer->GetWeight() < 0.02f || m_iCurrent8WayIdleSequence == -1 )
				{
					m_iCurrent8WayIdleSequence = m_pOuter->SelectWeightedSequence( ACT_IDLE );
					m_iCurrent8WayCrouchIdleSequence = m_pOuter->SelectWeightedSequence( ACT_CROUCHIDLE );
				}

				if ( m_eCurrentMainSequenceActivity == ACT_CROUCHIDLE || m_eCurrentMainSequenceActivity == ACT_RUN_CROUCH )
					pLayer->SetSequence( m_iCurrent8WayCrouchIdleSequence );
				else
					pLayer->SetSequence( m_iCurrent8WayIdleSequence );
			}
			
			pLayer->SetPlaybackRate( 1 );
			pLayer->SetCycle( pLayer->GetCycle() + m_pOuter->GetSequenceCycleRate( pStudioHdr, pLayer->GetSequence() ) * gpGlobals->frametime );
			pLayer->SetCycle( fmod( pLayer->GetCycle(), 1 ) );
			pLayer->SetOrder( MAIN_IDLE_SEQUENCE_LAYER );
#endif
#endif
		}
	}
}
void CWeaponStunStick::Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator )
{
	switch( pEvent->event )
	{
		case EVENT_WEAPON_MELEE_HIT:
		{
			// Trace up or down based on where the enemy is...
			// But only if we're basically facing that direction
			Vector vecDirection;
			AngleVectors( GetAbsAngles(), &vecDirection );

			CBaseEntity *pEnemy = pOperator->MyNPCPointer() ? pOperator->MyNPCPointer()->GetEnemy() : NULL;
			if ( pEnemy )
			{
				Vector vecDelta;
				VectorSubtract( pEnemy->WorldSpaceCenter(), pOperator->Weapon_ShootPosition(), vecDelta );
				VectorNormalize( vecDelta );
				
				Vector2D vecDelta2D = vecDelta.AsVector2D();
				Vector2DNormalize( vecDelta2D );
				if ( DotProduct2D( vecDelta2D, vecDirection.AsVector2D() ) > 0.8f )
				{
					vecDirection = vecDelta;
				}
			}

			Vector vecEnd;
			VectorMA( pOperator->Weapon_ShootPosition(), 32, vecDirection, vecEnd );
			// Stretch the swing box down to catch low level physics objects
			CBaseEntity *pHurt = pOperator->CheckTraceHullAttack( pOperator->Weapon_ShootPosition(), vecEnd, 
				Vector(-16,-16,-40), Vector(16,16,16), GetDamageForActivity( GetActivity() ), DMG_CLUB, 0.5f, false );
			
			// did I hit someone?
			if ( pHurt )
			{
				// play sound
				WeaponSound( MELEE_HIT );

				CBasePlayer *pPlayer = ToBasePlayer( pHurt );

				CNPC_MetroPolice *pCop = dynamic_cast<CNPC_MetroPolice *>(pOperator);
				bool bFlashed = false;

				if ( pCop != NULL && pPlayer != NULL )
				{
					// See if we need to knock out this target
					if ( pCop->ShouldKnockOutTarget( pHurt ) )
					{
						float yawKick = random->RandomFloat( -48, -24 );

						//Kick the player angles
						pPlayer->ViewPunch( QAngle( -16, yawKick, 2 ) );

						color32 white = {255,255,255,255};
						UTIL_ScreenFade( pPlayer, white, 0.2f, 1.0f, FFADE_OUT|FFADE_PURGE|FFADE_STAYOUT );
						bFlashed = true;
						
						pCop->KnockOutTarget( pHurt );

						break;
					}
					else
					{
						// Notify that we've stunned a target
						pCop->StunnedTarget( pHurt );
					}
				}
				
				// Punch angles
				if ( pPlayer != NULL && !(pPlayer->GetFlags() & FL_GODMODE) )
				{
					float yawKick = random->RandomFloat( -48, -24 );

					//Kick the player angles
					pPlayer->ViewPunch( QAngle( -16, yawKick, 2 ) );

					Vector	dir = pHurt->GetAbsOrigin() - GetAbsOrigin();

					// If the player's on my head, don't knock him up
					if ( pPlayer->GetGroundEntity() == pOperator )
					{
						dir = vecDirection;
						dir.z = 0;
					}

					VectorNormalize(dir);

					dir *= 500.0f;

					//If not on ground, then don't make them fly!
					if ( !(pPlayer->GetFlags() & FL_ONGROUND ) )
						 dir.z = 0.0f;

					//Push the target back
					pHurt->ApplyAbsVelocityImpulse( dir );

					if ( !bFlashed )
					{
						color32 red = {128,0,0,128};
						UTIL_ScreenFade( pPlayer, red, 0.5f, 0.1f, FFADE_IN );
					}
					
					// Force the player to drop anyting they were holding
					pPlayer->ForceDropOfCarriedPhysObjects();
				}
				
				// do effect?
			}
			else
			{
				WeaponSound( MELEE_MISS );
			}
		}
		break;
		default:
			BaseClass::Operator_HandleAnimEvent( pEvent, pOperator );
			break;
	}
}
	virtual QAngle	PreferredCarryAngles( void ) { return QAngle( 180, -90, 180 ); }
bool ShouldRemoveThisRagdoll( CBaseAnimating *pRagdoll )
{
	if ( g_RagdollLVManager.IsLowViolence() )
	{
		return true;
	}

#ifdef CLIENT_DLL

	/* we no longer ignore enemies just because they are on fire -- a ragdoll in front of me
	   is always a higher priority for retention than a flaming zombie behind me. At the 
	   time I put this in, the ragdolls do clean up their own effects if culled via SUB_Remove().
	   If you're encountering trouble with ragdolls leaving effects behind, try renabling the code below.
    /////////////////////
	//Just ignore it until we're done burning/dissolving.
	if ( pRagdoll->GetEffectEntity() )
		return false;
	*/

	Vector vMins, vMaxs;
		
	Vector origin = pRagdoll->m_pRagdoll->GetRagdollOrigin();
	pRagdoll->m_pRagdoll->GetRagdollBounds( vMins, vMaxs );

	if( engine->IsBoxInViewCluster( vMins + origin, vMaxs + origin) == false )
	{
		if ( g_debug_ragdoll_removal.GetBool() )
		{
			debugoverlay->AddBoxOverlay( origin, vMins, vMaxs, QAngle( 0, 0, 0 ), 0, 255, 0, 16, 5 );
			debugoverlay->AddLineOverlay( origin, origin + Vector( 0, 0, 64 ), 0, 255, 0, true, 5 );
		}

		return true;
	}
	else if( engine->CullBox( vMins + origin, vMaxs + origin ) == true )
	{
		if ( g_debug_ragdoll_removal.GetBool() )
		{
			debugoverlay->AddBoxOverlay( origin, vMins, vMaxs, QAngle( 0, 0, 0 ), 0, 0, 255, 16, 5 );
			debugoverlay->AddLineOverlay( origin, origin + Vector( 0, 0, 64 ), 0, 0, 255, true, 5 );
		}

		return true;
	}

#else
	CBasePlayer *pPlayer = UTIL_GetLocalPlayer();

	if( !UTIL_FindClientInPVS( pRagdoll->edict() ) )
	{
		if ( g_debug_ragdoll_removal.GetBool() )
			 NDebugOverlay::Line( pRagdoll->GetAbsOrigin(), pRagdoll->GetAbsOrigin() + Vector( 0, 0, 64 ), 0, 255, 0, true, 5 );

		return true;
	}
	else if( !pPlayer->FInViewCone( pRagdoll ) )
	{
		if ( g_debug_ragdoll_removal.GetBool() )
			 NDebugOverlay::Line( pRagdoll->GetAbsOrigin(), pRagdoll->GetAbsOrigin() + Vector( 0, 0, 64 ), 0, 0, 255, true, 5 );
		
		return true;
	}

#endif

	return false;
}
//-----------------------------------------------------------------------------
// Creates a single sfm file
//-----------------------------------------------------------------------------
void CSFMGenApp::GenerateSFMFile( const SFMGenInfo_t& sfmGenInfo, const SFMInfo_t &info, 
	studiohdr_t *pStudioHdr, const char *pOutputDirectory, const char *pExportFacPath )
{
	CSFMSession session;
	session.Init();

	char pAnimationSetName[256];
	Q_FileBase( pStudioHdr->name, pAnimationSetName, sizeof(pAnimationSetName) );

	// Set the file id(	necessary for phoneme extraction)
	DmFileId_t fileid = g_pDataModel->FindOrCreateFileId( pAnimationSetName );
	session.Root()->SetFileId( fileid, TD_DEEP );
	g_pModelPresetGroupMgr->AssociatePresetsWithFile( fileid );

	// Get the shot.
	CDmeFilmClip *pMovie = session.Root()->GetValueElement<CDmeFilmClip>( "activeClip" );
	CDmeFilmClip* pShot = CastElement< CDmeFilmClip >( pMovie->GetFilmTrack()->GetClip( 0 ) );

	// Create a camera for the shot
	DmeCameraParams_t cameraParams( pAnimationSetName, vec3_origin, QAngle( 0, 180, 0 ) );
	cameraParams.origin.x = pStudioHdr->hull_max.x + 20;
	cameraParams.origin.z = Lerp( 0.95f, pStudioHdr->hull_min.z, pStudioHdr->hull_max.z );
	cameraParams.fov = 75.0f;
	CDmeCamera* pCamera = session.CreateCamera( cameraParams );
	pShot->SetCamera( pCamera );

	// Create a game model for the studio hdr
	CDmeGameModel *pGameModel = session.CreateEditorGameModel( pStudioHdr, vec3_origin, Quaternion( 0, 0, 0, 1 ) );

	// Create a scene for the shot
	CDmeDag *pScene = session.FindOrCreateScene( pShot, pAnimationSetName );
	pScene->AddChild( pGameModel );

	// Create a sound clip
	CDmeGameSound *pGameSound;
	CDmeSoundClip *pSoundClip = CreateSoundClip( pMovie, pAnimationSetName, info.m_GameSound, pStudioHdr, &pGameSound );

	pShot->SetDuration( pSoundClip->GetDuration() );
	pMovie->SetDuration( pSoundClip->GetDuration() );

	// Create an animation set
	CDmeAnimationSet *pAnimationSet = CreateAnimationSet( pMovie, pShot, pGameModel, pAnimationSetName, 0, false );

	// Extract phonemes
	if ( pSoundClip )
	{
		CExtractInfo extractInfo;
		extractInfo.m_pClip = pSoundClip;
		extractInfo.m_pSound = pGameSound;
		extractInfo.m_sHintText = info.m_Text;
		extractInfo.m_bUseSentence = sfmGenInfo.m_bUsePhonemesInWavs;

		ExtractDesc_t extractDesc;
		extractDesc.m_nExtractType = EXTRACT_WIPE_CLIP;
		extractDesc.m_pMovie = pMovie;
		extractDesc.m_pShot = pShot;
		extractDesc.m_pSet = pAnimationSet;
		extractDesc.m_flSampleRateHz = sfmGenInfo.m_flSampleRateHz;
		extractDesc.m_flSampleFilterSize = sfmGenInfo.m_flSampleFilterSize;
		extractDesc.m_WorkList.AddToTail( extractInfo );
		BuildFacialControlList( pShot, pAnimationSet, extractDesc.m_ControlList );
		sfm_phonemeextractor->Extract( SPEECH_API_LIPSINC, extractDesc, sfmGenInfo.m_bWritePhonemesInWavs );

		CExtractInfo &results = extractDesc.m_WorkList[ 0 ];
		CDmElement *pExtractionSettings = pGameSound->FindOrAddPhonemeExtractionSettings();
		pExtractionSettings->SetValue< float >( "duration", results.m_flDuration );
		// Store off phonemes
		if ( !pExtractionSettings->HasAttribute( "results" ) )
		{
			pExtractionSettings->AddAttribute( "results", AT_ELEMENT_ARRAY );
		}

		CDmrElementArray< CDmElement > resultsArray( pExtractionSettings, "results" );
		resultsArray.RemoveAll();
		for ( int i = 0; i < results.m_ApplyTags.Count(); ++i )
		{
			CBasePhonemeTag *tag = results.m_ApplyTags[ i ];
			CDmElement *tagElement = CreateElement< CDmElement >( ConvertPhoneme( tag->GetPhonemeCode() ), pGameSound->GetFileId() );
			tagElement->SetValue< float >( "start", tag->GetStartTime() );
			tagElement->SetValue< float >( "end", tag->GetEndTime() );
			resultsArray.AddToTail( tagElement );
		}

		if ( pExportFacPath )
		{
			char pFACFileName[MAX_PATH];
			Q_ComposeFileName( pExportFacPath, info.m_DMXFileName, pFACFileName, sizeof(pFACFileName) );
			Q_SetExtension( pFACFileName, ".dmx", sizeof(pFACFileName) ); 
			ExportFacialAnimation( pFACFileName, pMovie, pShot, pAnimationSet );
		}
	}

	SaveSFMFile( session.Root(), pOutputDirectory, info.m_DMXFileName );

	session.Shutdown();
}