Ejemplo n.º 1
0
bool CASW_Sentry_Top::CanSee(CBaseEntity* pEnt)
{
	if (!pEnt)
		return false;
	// check if it's a valid target
	// check if its in range
	Vector vFiringPos = GetFiringPosition();

	Vector diff = pEnt->WorldSpaceCenter() - vFiringPos;
	float distance = diff.Length();
	if ( distance > GetRange() )
	{
		m_iCanSeeError = 0;
		return false;
	}
	// check the z angle is within X degrees of horizontal, if the z diff is significant
	if (fabs(diff.z) > 50.0f)
	{
		float fPitchDiff = fabs(UTIL_AngleDiff(GetPitchTo(pEnt), 0));
		if (fPitchDiff > 360.0f)
			fPitchDiff -= 360.0f;
		if (fabs(fPitchDiff) > 30.0f)
		{
			m_iCanSeeError = 1;
			return false;
		}
	}
	// check if the angle is within X degrees of our deploy radius
	float fYawDiff = fabs(UTIL_AngleDiff(CASW_Sentry_Top::GetYawTo(pEnt), m_fDeployYaw));
	if (fYawDiff > 360.0f)
		fYawDiff -= 360.0f;

	if (fabs(fYawDiff) > ASW_SENTRY_ANGLE)
	{
		m_iCanSeeError = 1;
		return false;
	}
	// do a trace from our shoot position to the enemy
	trace_t		tr;
	{
		ITraceFilter *pFilter = GetVisibilityTraceFilter();
		UTIL_TraceLine( vFiringPos, pEnt->WorldSpaceCenter(), MASK_OPAQUE_AND_NPCS,	// MASK_SHOT
			pFilter, &tr);
		delete pFilter;
	}
	m_iCanSeeError = 2;
	bool bClear = tr.fraction == 1.0;
	if (!bClear)
	{
		if (tr.m_pEnt == pEnt)
			return true;
	}
	return bClear;
}
float CAI_BlendedMotor::GetMoveScriptYaw( void )
{
	int i;

	// interpolate desired angle
	float flNewYaw = GetAbsAngles().y;
	float t = GetMoveInterval();
	for (i = 0; i < m_scriptTurn.Count()-1; i++)
	{
		if (t < m_scriptTurn[i].flTime)
		{
			// get new direction
			float a = t / m_scriptTurn[i].flTime;
			float deltaYaw = UTIL_AngleDiff( m_scriptTurn[i+1].flYaw, m_scriptTurn[i].flYaw );
			flNewYaw = UTIL_AngleMod( m_scriptTurn[i].flYaw + a * deltaYaw );
			break;
		}
		else
		{
			t -= m_scriptTurn[i].flTime;
		}
	}

	return flNewYaw;
}
Ejemplo n.º 3
0
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : *pController - 
//			*pObject - 
//			deltaTime - 
//			&linear - 
//			&angular - 
// Output : IMotionEvent::simresult_e
//-----------------------------------------------------------------------------
IMotionEvent::simresult_e CAI_BasePhysicsFlyingBot::Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular )
{
	static int count;

	IPhysicsObject *pPhysicsObject = VPhysicsGetObject();
	// Assert( pPhysicsObject );
	if (!pPhysicsObject) 
		return SIM_NOTHING;

	// move
	Vector actualVelocity;
	AngularImpulse actualAngularVelocity;
	pPhysicsObject->GetVelocity( &actualVelocity, &actualAngularVelocity );
	linear = (m_vCurrentVelocity - actualVelocity) * (0.1 / deltaTime) * 10.0;

	/*
	DevMsg("Sim %d : %5.1f %5.1f %5.1f\n", count++,
		m_vCurrentVelocity.x - actualVelocity.x, 
		m_vCurrentVelocity.y - actualVelocity.y, 
		m_vCurrentVelocity.z - actualVelocity.z );
	*/

	// do angles.
	Vector actualPosition;
	QAngle actualAngles;
	pPhysicsObject->GetPosition( &actualPosition, &actualAngles ); 

	// FIXME: banking currently disabled, forces simple upright posture
	angular.x = (UTIL_AngleDiff( m_vCurrentBanking.z, actualAngles.z ) - actualAngularVelocity.x) * (1 / deltaTime);
	angular.y = (UTIL_AngleDiff( m_vCurrentBanking.x, actualAngles.x ) - actualAngularVelocity.y) * (1 / deltaTime);

	// turn toward target
	angular.z = UTIL_AngleDiff( m_fHeadYaw, actualAngles.y + actualAngularVelocity.z * 0.1 ) * (1 / deltaTime);

	// angular = m_vCurrentAngularVelocity - actualAngularVelocity;

	// DevMsg("Sim %d : %.1f %.1f %.1f (%.1f)\n", count++, actualAngles.x, actualAngles.y, actualAngles.z, m_fHeadYaw );

	// FIXME: remove the stuff from MoveExecute();
	// FIXME: check MOVE?

	ClampMotorForces( linear, angular );

	return SIM_GLOBAL_ACCELERATION; // on my local axis.   SIM_GLOBAL_ACCELERATION
}
Ejemplo n.º 4
0
bool CNPC_Infected::OverrideMoveFacing( const AILocalMoveGoal_t &move, float flInterval )
{
	// required movement direction
	float flMoveYaw = UTIL_VecToYaw( move.dir );

	// FIXME: move this up to navigator so that path goals can ignore these overrides.
	Vector dir;
	float flInfluence = GetFacingDirection( dir );
	dir = move.facing * (1 - flInfluence) + dir * flInfluence;
	VectorNormalize( dir );

	// ideal facing direction
	float idealYaw = UTIL_AngleMod( UTIL_VecToYaw( dir ) );
		
	// FIXME: facing has important max velocity issues
	GetMotor()->SetIdealYawAndUpdate( idealYaw );	

	// find movement direction to compensate for not being turned far enough
	float flDiff = UTIL_AngleDiff( flMoveYaw, GetLocalAngles().y );

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

	vCurMovePose.x = cos( DEG2RAD( flDiff ) ) * 1.0f; //flPlaybackRate;
	vCurMovePose.y = -sin( DEG2RAD( flDiff ) ) * 1.0f; //flPlaybackRate;

	SetPoseParameter( gm_nMoveXPoseParam, vCurMovePose.x );
	SetPoseParameter( gm_nMoveYPoseParam, vCurMovePose.y );

	// ==== Update Lean pose parameters
	if ( gm_nLeanYawPoseParam >= 0 )
	{
		float targetLean = GetPoseParameter( gm_nMoveYPoseParam ) * 30.0f;
		float curLean = GetPoseParameter( gm_nLeanYawPoseParam );
		if( curLean < targetLean )
			curLean += MIN(fabs(targetLean-curLean), GetAnimTimeInterval()*12.0f); //was 15.0f
		else
			curLean -= MIN(fabs(targetLean-curLean), GetAnimTimeInterval()*12.0f); //was 15.0f
		SetPoseParameter( gm_nLeanYawPoseParam, curLean );
	}

	if( gm_nLeanPitchPoseParam >= 0 )
	{
		float targetLean = GetPoseParameter( gm_nMoveXPoseParam ) * -20.0f; //was -30.0f
		float curLean = GetPoseParameter( gm_nLeanPitchPoseParam );
		if( curLean < targetLean )
			curLean += MIN(fabs(targetLean-curLean), GetAnimTimeInterval()*10.0f); //was 15.0f
		else
			curLean -= MIN(fabs(targetLean-curLean), GetAnimTimeInterval()*10.0f); //was 15.0f
		SetPoseParameter( gm_nLeanPitchPoseParam, curLean );
	}

	return true;
}
Ejemplo n.º 5
0
void CPropVehicleManhack::UpdateHead( void )
{
	float yaw = GetPoseParameter( "head_yaw" );
	float pitch = GetPoseParameter( "head_pitch" );

	// If we should be watching our enemy, turn our head
	CNPC_Manhack *pManhack=GetManhack();
	
	if (pManhack != NULL) 
	{
		Vector vehicleEyeOrigin;
		QAngle vehicleEyeAngles;
		GetAttachment( "vehicle_driver_eyes", vehicleEyeOrigin, vehicleEyeAngles );

		// FIXME: cache this
		Vector vBodyDir;
		AngleVectors( vehicleEyeAngles, &vBodyDir );

		Vector	manhackDir = pManhack->GetAbsOrigin() - vehicleEyeOrigin;
		VectorNormalize( manhackDir );
		
		float angle = UTIL_VecToYaw( vBodyDir );
		float angleDiff = UTIL_VecToYaw( manhackDir );
		angleDiff = UTIL_AngleDiff( angleDiff, angle + yaw );

		SetPoseParameter( "head_yaw", UTIL_Approach( yaw + angleDiff, yaw, 1 ) );

		angle = UTIL_VecToPitch( vBodyDir );
		angleDiff = UTIL_VecToPitch( manhackDir );
		angleDiff = UTIL_AngleDiff( angleDiff, angle + pitch );

		SetPoseParameter( "head_pitch", UTIL_Approach( pitch + angleDiff, pitch, 1 ) );
	}
	else
	{
		// Otherwise turn the head back to its normal position
		SetPoseParameter( "head_yaw",	UTIL_Approach( 0, yaw, 10 ) );
		SetPoseParameter( "head_pitch", UTIL_Approach( 0, pitch, 10 ) );
	}
}
Ejemplo n.º 6
0
//=========================================================
// DeltaIdealYaw - returns the difference ( in degrees ) between
// npc's current yaw and ideal_yaw
//
// Positive result is left turn, negative is right turn
//=========================================================
float CAI_Motor::DeltaIdealYaw ( void )
{
	float	flCurrentYaw;

	flCurrentYaw = UTIL_AngleMod( GetLocalAngles().y );

	if ( flCurrentYaw == GetIdealYaw() )
	{
		return 0;
	}


	return UTIL_AngleDiff( GetIdealYaw(), flCurrentYaw );
}
Ejemplo n.º 7
0
void CAI_Motor::MoveFacing( const AILocalMoveGoal_t &move )
{
	if ( GetOuter()->OverrideMoveFacing( move, GetMoveInterval() ) )
		return;

	// required movement direction
	float flMoveYaw = UTIL_VecToYaw( move.dir );

	int nSequence = GetSequence();
	float fSequenceMoveYaw = GetSequenceMoveYaw( nSequence );
	if ( fSequenceMoveYaw == NOMOTION )
	{
		fSequenceMoveYaw = 0;
	}

	if (!HasPoseParameter( nSequence, "move_yaw" ))
	{
		SetIdealYawAndUpdate( UTIL_AngleMod( flMoveYaw - fSequenceMoveYaw ) );
	}
	else
	{
		// FIXME: move this up to navigator so that path goals can ignore these overrides.
		Vector dir;
		float flInfluence = GetFacingDirection( dir );
		dir = move.facing * (1 - flInfluence) + dir * flInfluence;
		VectorNormalize( dir );

		// ideal facing direction
		float idealYaw = UTIL_AngleMod( UTIL_VecToYaw( dir ) );
		
		// FIXME: facing has important max velocity issues
		SetIdealYawAndUpdate( idealYaw );	

		// find movement direction to compensate for not being turned far enough
		float flDiff = UTIL_AngleDiff( flMoveYaw, GetLocalAngles().y );
		SetPoseParameter( "move_yaw", flDiff );
		/*
		if ((GetOuter()->m_debugOverlays & OVERLAY_NPC_SELECTED_BIT))
		{
			Msg( "move %.1f : diff %.1f  : ideal %.1f\n", flMoveYaw, flDiff, m_IdealYaw );
		}
		*/
	}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input  :
// Output :
//-----------------------------------------------------------------------------
void CAI_BasePhysicsFlyingBot::TurnHeadToTarget(float flInterval, const Vector &MoveTarget )
{
	float desYaw = UTIL_AngleDiff(VecToYaw(MoveTarget - GetLocalOrigin()), 0 );

	m_fHeadYaw = desYaw;

	return;

	// If I've flipped completely around, reverse angles
	float fYawDiff = m_fHeadYaw - desYaw;
	if (fYawDiff > 180)
	{
		m_fHeadYaw -= 360;
	}
	else if (fYawDiff < -180)
	{
		m_fHeadYaw += 360;
	}

	// RIGHT NOW, this affects every flying bot. This rate should be member data that individuals
	// can manipulate. THIS change for MANHACKS E3 2003 (sjb)
	float iRate = 0.8;

	// Make frame rate independent
	float timeToUse = flInterval;
	while (timeToUse > 0)
	{
		m_fHeadYaw	   = (iRate * m_fHeadYaw) + (1-iRate)*desYaw;
		timeToUse -= 0.1;
	}

	while( m_fHeadYaw > 360 )  
	{
		m_fHeadYaw -= 360.0f;
	}

	while( m_fHeadYaw < 0 )
	{
		m_fHeadYaw += 360.f;
	}

	// SetBoneController( 0, m_fHeadYaw );
}
bool CASW_Jump_Trigger::ReasonableJump(CASW_Alien_Jumper *pJumper, int iJumpNum)
{
	if (!pJumper)
		return false;

	if (m_bOneJumpPerAlien && pJumper->m_bTriggerJumped)
		return false;

	if (!pJumper->GetEnemy())	// let him jump if he has no enemy
		return true;

	if (!m_bCheckEnemyDirection)		// let him jump if he doesn't care about the direction of his enemy
		return true;

	// if he does have an enemy, check it's in the direction of the jump
	float fEnemyYaw = UTIL_VecToYaw(pJumper->GetEnemy()->GetAbsOrigin() - pJumper->GetAbsOrigin());
	float fJumpYaw = UTIL_VecToYaw(m_vecJumpDestination[iJumpNum] - pJumper->GetAbsOrigin());

	return fabs(UTIL_AngleDiff(fEnemyYaw, fJumpYaw)) < 90;
}
Ejemplo n.º 10
0
//------------------------------------------------------------------------------
// Purpose: routine called to start when a task initially starts
// Input  : pTask - the task structure
//------------------------------------------------------------------------------
void CAI_ASW_MeleeBehavior::StartTask( const Task_t *pTask )
{
	switch( pTask->iTask )
	{
		case TASK_MELEE_FLIP_AROUND:
			{
				Assert( 0 ); // NOT DONE.  See example in shield behavior: TASK_SHIELD_MAINTAIN_FLIP
#if 0
				bool	bNeedFlip = false;

				if ( HaveSequenceForActivity( ACT_SPINAROUND ) == true )
				{
					CBaseEntity *pTarget = GetEnemy();
					if ( pTarget )
					{
						float flFacing = UTIL_VecToYaw( pTarget->GetAbsOrigin() - GetAbsOrigin() );
						float flDiff = UTIL_AngleDiff( GetAbsAngles()[ YAW ], flFacing );
					}
				}

				if ( bNeedFlip == false )
				{
					TaskComplete();
				}
				else
				{
					GetOuter()->SetIdealActivity( ACT_SPINAROUND );
				}
#endif
			}
			break;

		default:
			BaseClass::StartTask( pTask );
			break;
	}
}
Ejemplo n.º 11
0
AIMoveResult_t CAI_LocalNavigator::MoveCalc( AILocalMoveGoal_t *pMoveGoal, bool bPreviouslyValidated )
{
	bool bOnlyCurThink = ( bPreviouslyValidated && !HaveObstacles() );

	AIMoveResult_t result = MoveCalcRaw( pMoveGoal, bOnlyCurThink );

	if ( pMoveGoal->curExpectedDist > pMoveGoal->maxDist )
		pMoveGoal->curExpectedDist = pMoveGoal->maxDist;

	// If success, try to dampen really fast turning movement
	if ( result == AIMR_OK)
	{
		float interval = GetOuter()->GetMotor()->GetMoveInterval();
		float currentYaw = UTIL_AngleMod( GetLocalAngles().y );
		float goalYaw;
		float deltaYaw;
		float speed;
		float clampedYaw;

		// Clamp yaw
		goalYaw = UTIL_VecToYaw( pMoveGoal->facing );
		deltaYaw = fabs( UTIL_AngleDiff( goalYaw, currentYaw ) );
		if ( deltaYaw > 15 )
		{
			speed = deltaYaw * 4.0; // i.e., any maneuver takes a quarter a second
			clampedYaw = AI_ClampYaw( speed, currentYaw, goalYaw, interval );

			if ( clampedYaw != goalYaw )
			{
				pMoveGoal->facing = UTIL_YawToVector( clampedYaw );
			}
		}
	}
	
	return result;
}
int CAI_BlendedMotor::BuildTurnScript( int i, int j )
{
	int k;

	Vector vecDir = m_scriptTurn[j].vecLocation - m_scriptTurn[i].vecLocation;
	float interiorYaw = UTIL_VecToYaw( vecDir );

	float deltaYaw;

	deltaYaw = fabs( UTIL_AngleDiff( interiorYaw, m_scriptTurn[i].flYaw ) );
	float t1 = deltaYaw / YAWSPEED;

	deltaYaw = fabs( UTIL_AngleDiff( m_scriptTurn[j].flYaw, interiorYaw ) );
	float t2 = deltaYaw / YAWSPEED;

	float totalTime = m_scriptTurn[j].flElapsedTime - m_scriptTurn[i].flElapsedTime;

	//Assert( totalTime >  0 );

	if (t1 < 0.01)
	{
		if (t2 > totalTime * 0.8)
		{
			// too close, nothing to do
			return 0;
		}

		// go ahead and force yaw
		m_scriptTurn[i].flYaw = interiorYaw;

		// we're already aiming close enough to the interior yaw, set the point where we need to blend out
		k = BuildInsertNode( i, totalTime - t2 );
		m_scriptTurn[k].flYaw = interiorYaw;

		return 1;
	}
	else if (t2 < 0.01)
	{
		if (t1 > totalTime * 0.8)
		{
			// too close, nothing to do
			return 0;
		}

 		// we'll finish up aiming close enough to the interior yaw, set the point where we need to blend in
		k = BuildInsertNode( i, t1 );
		m_scriptTurn[k].flYaw = interiorYaw;
		
		return 1;
	}
	else if (t1 + t2 > totalTime)
	{
		// don't bother with interior node
		return 0;
		
		// waypoints need to much turning, ignore interior yaw
		float a = (t1 / (t1 + t2));
		t1 = a * totalTime;

		k = BuildInsertNode( i, t1 );

		deltaYaw = UTIL_AngleDiff( m_scriptTurn[j].flYaw, m_scriptTurn[i].flYaw );
		m_scriptTurn[k].flYaw = UTIL_ApproachAngle( m_scriptTurn[j].flYaw, m_scriptTurn[i].flYaw, deltaYaw * (1 - a) );

		return 1;
	}
	else if (t1 + t2 < totalTime * 0.8)
	{
		// turn to face interior, run a ways, then turn away
		k = BuildInsertNode( i, t1 );
		m_scriptTurn[k].flYaw = interiorYaw;

		k = BuildInsertNode( i, t2 );
		m_scriptTurn[k].flYaw = interiorYaw;

		return 2;
	}
	return 0;
}
//------------------------------------------------------------------------------
// Purpose : 
// Input   :
// Output  :
//------------------------------------------------------------------------------
void CNPC_CombineDropship::PrescheduleThink( void )
{
	BaseClass::PrescheduleThink();
	
	// keep track of think time deltas for burn calc below
	float dt = gpGlobals->curtime - m_flLastTime;
	m_flLastTime = gpGlobals->curtime;

	switch( m_iLandState )
	{
	case LANDING_NO:
		{
			if ( IsActivityFinished() && (GetActivity() != ACT_DROPSHIP_FLY_IDLE_EXAGG && GetActivity() != ACT_DROPSHIP_FLY_IDLE_CARGO) )
			{
				if ( m_hContainer )
				{
					SetIdealActivity( (Activity)ACT_DROPSHIP_FLY_IDLE_CARGO );
				}
				else
				{
					SetIdealActivity( (Activity)ACT_DROPSHIP_FLY_IDLE_EXAGG );
				}
			}

			DoRotorWash();
		}
		break;

	case LANDING_LEVEL_OUT:
		{
			// Approach the drop point
			Vector vecToTarget = (GetDesiredPosition() - GetAbsOrigin());
			float flDistance = vecToTarget.Length();

			// If we're slowing, make it look like we're slowing
			/*
			if ( IsActivityFinished() && GetActivity() != ACT_DROPSHIP_DESCEND_IDLE )
			{
				SetActivity( (Activity)ACT_DROPSHIP_DESCEND_IDLE );
			}
			*/

			// Are we there yet?
			float flSpeed = GetAbsVelocity().Length();
			if ( flDistance < 70 && flSpeed < 100 )
			{
				m_flLandingSpeed = flSpeed;
				m_iLandState = LANDING_DESCEND;
				// save off current angles so we can work them out over time
				QAngle angles = GetLocalAngles();
				m_existPitch = angles.x;
				m_existRoll = angles.z;

			}

			DoRotorWash();
		}
		break;

	case LANDING_DESCEND:
		{
			float	flAltitude;

			SetLocalAngularVelocity( vec3_angle );

			// Ensure we land on the drop point
			Vector vecToTarget = (GetDesiredPosition() - GetAbsOrigin());
			float flDistance = vecToTarget.Length();
			float flRampedSpeed = m_flLandingSpeed * (flDistance / 70);
			Vector vecVelocity = (flRampedSpeed / flDistance) * vecToTarget;
			vecVelocity.z = -75;
			SetAbsVelocity( vecVelocity );

			flAltitude = GetAltitude();			

			if ( IsActivityFinished() && GetActivity() != ACT_DROPSHIP_DESCEND_IDLE )
			{
				SetActivity( (Activity)ACT_DROPSHIP_DESCEND_IDLE );
			}

			if ( flAltitude < 72 )
			{
				QAngle angles = GetLocalAngles();

				// Level out quickly.
				angles.x = UTIL_Approach( 0.0, angles.x, 0.2 );
				angles.z = UTIL_Approach( 0.0, angles.z, 0.2 );

				SetLocalAngles( angles );
			}
			else
			{
				// randomly move as if buffeted by ground effects
				// gently flatten ship from starting pitch/yaw
				m_existPitch = UTIL_Approach( 0.0, m_existPitch, 1 );
				m_existRoll = UTIL_Approach( 0.0, m_existRoll, 1 );

				QAngle angles = GetLocalAngles();
				angles.x = m_existPitch + ( sin( gpGlobals->curtime * 3.5f ) * DROPSHIP_MAX_LAND_TILT );
				angles.z = m_existRoll + ( sin( gpGlobals->curtime * 3.75f ) * DROPSHIP_MAX_LAND_TILT );
				SetLocalAngles( angles );

				// figure out where to face (nav point)
				Vector targetDir = GetDesiredPosition() - GetAbsOrigin();
//				NDebugOverlay::Cross3D( m_pGoalEnt->GetAbsOrigin(), -Vector(2,2,2), Vector(2,2,2), 255, 0, 0, false, 20 );

				QAngle targetAngles = GetAbsAngles();
				targetAngles.y += UTIL_AngleDiff(UTIL_VecToYaw( targetDir ), targetAngles.y);
				// orient ship towards path corner on the way down
				angles = GetAbsAngles();
				angles.y = UTIL_Approach(targetAngles.y, angles.y, 2 );
				SetAbsAngles( angles );
			}

			if ( flAltitude <= 0.5f )
			{
				m_iLandState = LANDING_TOUCHDOWN;

				// upon landing, make sure ship is flat
				QAngle angles = GetLocalAngles();
				angles.x = 0;
				angles.z = 0;
				SetLocalAngles( angles );

				// TODO: Release cargo anim
				SetActivity( (Activity)ACT_DROPSHIP_DESCEND_IDLE );
			}

			DoRotorWash();

			// place danger sounds 1 foot above ground to get troops to scatter if they are below dropship
			Vector vecBottom = GetAbsOrigin();
			vecBottom.z += WorldAlignMins().z;
			Vector vecSpot = vecBottom + Vector(0, 0, -1) * (GetAltitude() - 12 );
			CSoundEnt::InsertSound( SOUND_DANGER, vecSpot, 400, 0.2, this, 0 );
			CSoundEnt::InsertSound( SOUND_PHYSICS_DANGER, vecSpot, 400, 0.2, this, 1 );
//			NDebugOverlay::Cross3D( vecSpot, -Vector(4,4,4), Vector(4,4,4), 255, 0, 255, false, 10.0f );

			// now check to see if player is below us, if so, cause heat damage to them (i.e. get them to move)
			trace_t tr;
			Vector vecBBoxMin = CRATE_BBOX_MIN;		// use flat box for check
			vecBBoxMin.z = -5;
			Vector vecBBoxMax = CRATE_BBOX_MAX;
			vecBBoxMax.z = 5;
			Vector pEndPoint = vecBottom + Vector(0, 0, -1) * ( GetAltitude() - 12 );
			AI_TraceHull( vecBottom, pEndPoint, vecBBoxMin, vecBBoxMax, MASK_SOLID, this, COLLISION_GROUP_NONE, &tr );

			if ( tr.fraction < 1.0f )
			{
				if ( tr.GetEntityIndex() == 1 )			// player???
				{
					CTakeDamageInfo info( this, this, 20 * dt, DMG_BURN );
					CBasePlayer *pPlayer = UTIL_PlayerByIndex(1);
					pPlayer->TakeDamage( info );
				}
			}

		}
		break;

	case LANDING_TOUCHDOWN:
		{
			if ( IsActivityFinished() && ( GetActivity() != ACT_DROPSHIP_DESCEND_IDLE ) )
			{
				SetActivity( (Activity)ACT_DROPSHIP_DESCEND_IDLE );
			}

			m_iLandState = LANDING_UNLOADING;
			m_flTroopDeployPause = gpGlobals->curtime + DROPSHIP_PAUSE_B4_TROOP_UNLOAD;
			m_flTimeTakeOff = m_flTroopDeployPause + DROPSHIP_DEPLOY_TIME;
		}
		break;

	case LANDING_UNLOADING:
		{
			// pause before dropping troops
			if ( gpGlobals->curtime > m_flTroopDeployPause )
			{
				if ( m_hContainer )	// don't drop troops if we don't have a crate any more
				{
					SpawnTroops();
					m_flTroopDeployPause = m_flTimeTakeOff + 2;	// only drop once
				}
			}
			// manage engine wash and volume
			if ( m_flTimeTakeOff - gpGlobals->curtime < 0.5f )
			{
				m_engineThrust = UTIL_Approach( 1.0f, m_engineThrust, 0.1f );
				DoRotorWash();
			}
			else
			{
				float idleVolume = 0.2f;
				m_engineThrust = UTIL_Approach( idleVolume, m_engineThrust, 0.04f );
				if ( m_engineThrust > idleVolume ) 
				{
					DoRotorWash();				// make sure we're kicking up dust/water as long as engine thrust is up
				}
			}

			if( gpGlobals->curtime > m_flTimeTakeOff )
			{
				m_iLandState = LANDING_LIFTOFF;
				SetActivity( (Activity)ACT_DROPSHIP_LIFTOFF );
				m_engineThrust = 1.0f;			// ensure max volume once we're airborne
				if ( m_bIsFiring )
				{
					StopCannon();				// kill cannon sounds if they are on
				}

				// detach container from ship
				if ( m_hContainer && m_leaveCrate )
				{
					m_hContainer->SetParent(NULL);
					m_hContainer->SetMoveType( (MoveType_t)m_iContainerMoveType );

					// If the container has a physics object, remove it's shadow
					IPhysicsObject *pPhysicsObject = m_hContainer->VPhysicsGetObject();
					if ( pPhysicsObject )
					{
						pPhysicsObject->RemoveShadowController();
					}

					m_hContainer = NULL;
				}
			}
		}
		break;

	case LANDING_LIFTOFF:
		{
			// give us some clearance before changing back to larger hull -- keeps ship from getting stuck on
			// things like the player, etc since we "pop" the hull...
			if ( GetAltitude() > 120 )		
			{
				m_OnFinishedDropoff.FireOutput( this, this );

				m_iLandState = LANDING_NO;

				// change bounding box back to normal ship hull
				Vector vecBBMin, vecBBMax;
				ExtractBbox( SelectHeaviestSequence( ACT_DROPSHIP_DEPLOY_IDLE ), vecBBMin, vecBBMax ); 
				UTIL_SetSize( this, vecBBMin, vecBBMax );
				Relink();
			}
		}
		break;

	case LANDING_SWOOPING:
		{
			// Did we lose our pickup target?
			if ( !m_hPickupTarget )
			{
				m_iLandState = LANDING_NO;
			}
			else
			{
				// Decrease altitude and speed to hit the target point.
				Vector vecToTarget = (GetDesiredPosition() - GetAbsOrigin());
				float flDistance = vecToTarget.Length();

				// Start cheating when we get near it
				if ( flDistance < 50 )
				{
					/*
					if ( flDistance > 10 )
					{
						// Cheat and ensure we touch the target
						float flSpeed = GetAbsVelocity().Length();
						Vector vecVelocity = vecToTarget;
						VectorNormalize( vecVelocity );
						SetAbsVelocity( vecVelocity * min(flSpeed,flDistance) );
					}
					else
					*/
					{
						// Grab the target
						m_hContainer = m_hPickupTarget;
						m_hPickupTarget = NULL;
						m_iContainerMoveType = m_hContainer->GetMoveType();

						// If the container has a physics object, move it to shadow
						IPhysicsObject *pPhysicsObject = m_hContainer->VPhysicsGetObject();
						if ( pPhysicsObject )
						{
							pPhysicsObject->SetShadow( Vector(1e4,1e4,1e4), AngularImpulse(1e4,1e4,1e4), false, false );
							pPhysicsObject->UpdateShadow( GetAbsOrigin(), GetAbsAngles(), false, 0 );
						}

						int iIndex = 0;//LookupAttachment("Cargo");
						/*
						Vector vecOrigin;
						QAngle vecAngles;
						GetAttachment( iIndex, vecOrigin, vecAngles );
						m_hContainer->SetAbsOrigin( vecOrigin );
						m_hContainer->SetAbsAngles( vec3_angle );
						*/
						m_hContainer->SetAbsOrigin( GetAbsOrigin() );
						m_hContainer->SetParent(this, iIndex);
						m_hContainer->SetMoveType( MOVETYPE_PUSH );
						m_hContainer->RemoveFlag( FL_ONGROUND );
						m_hContainer->Relink();
						m_hContainer->SetAbsAngles( vec3_angle );

						m_OnFinishedPickup.FireOutput( this, this );
						m_iLandState = LANDING_NO;
					}
				}
			}

			DoRotorWash();
		}
		break;
	}

	DoCombatStuff();

	if ( GetActivity() != GetIdealActivity() )
	{
		//Msg( "setactivity" );
		SetActivity( GetIdealActivity() );
	}
}
Ejemplo n.º 14
0
//-----------------------------------------------------------------------------
// Purpose: Aim Gun at a target
//-----------------------------------------------------------------------------
void CASW_PropJeep::AimGunAt( Vector *endPos, float flInterval )
{
	Vector	aimPos = *endPos;

	// See if the gun should be allowed to aim
	if ( IsOverturned() || m_bEngineLocked || m_bHasGun == false )
	{
		SetPoseParameter( JEEP_GUN_YAW, 0 );
		SetPoseParameter( JEEP_GUN_PITCH, 0 );
		SetPoseParameter( JEEP_GUN_SPIN, 0 );
		return;

		// Make the gun go limp and look "down"
		Vector	v_forward, v_up;
		AngleVectors( GetLocalAngles(), NULL, &v_forward, &v_up );
		aimPos = WorldSpaceCenter() + ( v_forward * -32.0f ) - Vector( 0, 0, 128.0f );
	}

	matrix3x4_t gunMatrix;
	GetAttachment( LookupAttachment("gun_ref"), gunMatrix );

	// transform the enemy into gun space
	Vector localEnemyPosition;
	VectorITransform( aimPos, gunMatrix, localEnemyPosition );

	// do a look at in gun space (essentially a delta-lookat)
	QAngle localEnemyAngles;
	VectorAngles( localEnemyPosition, localEnemyAngles );
	
	// convert to +/- 180 degrees
	localEnemyAngles.x = UTIL_AngleDiff( localEnemyAngles.x, 0 );	
	localEnemyAngles.y = UTIL_AngleDiff( localEnemyAngles.y, 0 );

	float targetYaw = m_aimYaw + localEnemyAngles.y;
	float targetPitch = m_aimPitch + localEnemyAngles.x;
	
	// Constrain our angles
	float newTargetYaw	= clamp( targetYaw, -CANNON_MAX_LEFT_YAW, CANNON_MAX_RIGHT_YAW );
	float newTargetPitch = clamp( targetPitch, -CANNON_MAX_DOWN_PITCH, CANNON_MAX_UP_PITCH );

	// If the angles have been clamped, we're looking outside of our valid range
	if ( fabs(newTargetYaw-targetYaw) > 1e-4 || fabs(newTargetPitch-targetPitch) > 1e-4 )
	{
		m_bUnableToFire = true;
	}

	targetYaw = newTargetYaw;
	targetPitch = newTargetPitch;

	// Exponentially approach the target
	float yawSpeed = 8;
	float pitchSpeed = 8;

	m_aimYaw = UTIL_Approach( targetYaw, m_aimYaw, yawSpeed );
	m_aimPitch = UTIL_Approach( targetPitch, m_aimPitch, pitchSpeed );

	SetPoseParameter( JEEP_GUN_YAW, -m_aimYaw);
	SetPoseParameter( JEEP_GUN_PITCH, -m_aimPitch );

	InvalidateBoneCache();

	// read back to avoid drift when hitting limits
	// as long as the velocity is less than the delta between the limit and 180, this is fine.
	m_aimPitch = -GetPoseParameter( JEEP_GUN_PITCH );
	m_aimYaw = -GetPoseParameter( JEEP_GUN_YAW );

	// Now draw crosshair for actual aiming point
	Vector	vecMuzzle, vecMuzzleDir;
	QAngle	vecMuzzleAng;

	GetAttachment( "Muzzle", vecMuzzle, vecMuzzleAng );
	AngleVectors( vecMuzzleAng, &vecMuzzleDir );

	trace_t	tr;
	UTIL_TraceLine( vecMuzzle, vecMuzzle + (vecMuzzleDir * MAX_TRACE_LENGTH), MASK_SHOT, this, COLLISION_GROUP_NONE, &tr );

		// see if we hit something, if so, adjust endPos to hit location
	if ( tr.fraction < 1.0 )
	{
		m_vecGunCrosshair = vecMuzzle + ( vecMuzzleDir * MAX_TRACE_LENGTH * tr.fraction );
	}
}
Ejemplo n.º 15
0
// we failed to move this interval
//   returns true if we lay in a new move target
bool CASW_Simple_Alien::FailedMove()
{
	m_bMoving = false;
	m_vecMoveTarget = GetAbsOrigin();

	// we've hit something
	if (m_MoveFailure.trace.m_pEnt)
	{
		Vector vecNormal = m_MoveFailure.trace.plane.normal;
		// todo: if we've hit a marine, hurt him?
		CASW_Marine *pMarine = dynamic_cast<CASW_Marine*>(m_MoveFailure.trace.m_pEnt);
		if (pMarine)
		{
			// it's okay to be stuck on a marine, since that means we're probably clawing him to bits!
			return false;
		}

		// if we've hit another alien, set our normal as though it were a cylinder collision, to get a more accurate avoidance
		//   note: won't work unless the actual movement of the alien is done with a cylinder too
		//CASW_Simple_Alien *pAlien = dynamic_cast<CASW_Simple_Alien*>(m_MoveFailure.trace.m_pEnt);
		//if (pAlien)
		//{
			//vecNormal = pAlien->GetAbsOrigin() - GetAbsOrigin();
			//vecNormal.NormalizeInPlace();
		//}

		// otherwise, assume we've hit some prop or geometry
		
		// if we have no enemy, just randomly move away from the wall
        if (!GetEnemy())
        {
        	SetMoveTarget(PickRandomDestination(32.0f, 16.0f * vecNormal));
			return true;
        }

		// pick a random distance to move away from the wall
		float fDist = 56.25f;
		float fDistPick = random->RandomFloat();
		if (fDistPick > 0.8f)
			fDist = 187.5f;
		else if (fDistPick > 0.4f)
			fDist = 112.5f;

		// find vectors for the two possible directions
		float wall_yaw = UTIL_VecToYaw(vecNormal);        
		float wall_yaw_left = wall_yaw - 90.0f;
		float wall_yaw_right = wall_yaw + 90.0f;
        
        // which one takes us closer to the enemy?
		float enemy_yaw = UTIL_VecToYaw(GetEnemy()->GetAbsOrigin() - GetAbsOrigin());
		if (fabs(UTIL_AngleDiff(enemy_yaw, wall_yaw_left)) < fabs(UTIL_AngleDiff(enemy_yaw, wall_yaw_right)))
		{
			// go left
			Vector vecLeft;
			AngleVectors(QAngle(0, wall_yaw_left, 0), &vecLeft);
			SetMoveTarget(GetAbsOrigin() + vecLeft * fDist);
		}
		else
		{
			// go right
			Vector vecRight;
			AngleVectors(QAngle(0, wall_yaw_right, 0), &vecRight);
			SetMoveTarget(GetAbsOrigin() + vecRight * fDist);			
		}
		return true;
	}

	return false;
}
Ejemplo n.º 16
0
void CLeech::SwimThink( void )
{
	TraceResult		tr;
	float			flLeftSide;
	float			flRightSide;
	float			targetSpeed;
	float			targetYaw = 0;
	CBaseEntity		*pTarget;

	if ( FNullEnt( FIND_CLIENT_IN_PVS( edict() ) ) )
	{
		pev->nextthink = gpGlobals->time + RANDOM_FLOAT(1,1.5);
		pev->velocity = g_vecZero;
		return;
	}
	else
		pev->nextthink = gpGlobals->time + 0.1;

	targetSpeed = LEECH_SWIM_SPEED;

	if ( m_waterTime < gpGlobals->time )
		RecalculateWaterlevel();

	if ( m_stateTime < gpGlobals->time )
		SwitchLeechState();

	ClearConditions( bits_COND_CAN_MELEE_ATTACK1 );
	switch( m_MonsterState )
	{
	case MONSTERSTATE_COMBAT:
		pTarget = m_hEnemy;
		if ( !pTarget )
			SwitchLeechState();
		else
		{
			// Chase the enemy's eyes
			m_height = pTarget->pev->origin.z + pTarget->pev->view_ofs.z - 5;
			// Clip to viable water area
			if ( m_height < m_bottom )
				m_height = m_bottom;
			else if ( m_height > m_top )
				m_height = m_top;
			Vector location = pTarget->pev->origin - pev->origin;
			location.z += (pTarget->pev->view_ofs.z);
			if ( location.Length() < 40 )
				SetConditions( bits_COND_CAN_MELEE_ATTACK1 );
			// Turn towards target ent
			targetYaw = UTIL_VecToYaw( location );

			targetYaw = UTIL_AngleDiff( targetYaw, UTIL_AngleMod( pev->angles.y ) );

			if ( targetYaw < (-LEECH_TURN_RATE*0.75) )
				targetYaw = (-LEECH_TURN_RATE*0.75);
			else if ( targetYaw > (LEECH_TURN_RATE*0.75) )
				targetYaw = (LEECH_TURN_RATE*0.75);
			else
				targetSpeed *= 2;
		}

		break;

	default:
		if ( m_zTime < gpGlobals->time )
		{
			float newHeight = RANDOM_FLOAT( m_bottom, m_top );
			m_height = 0.5 * m_height + 0.5 * newHeight;
			m_zTime = gpGlobals->time + RANDOM_FLOAT( 1, 4 );
		}
		if ( RANDOM_LONG( 0, 100 ) < 10 )
			targetYaw = RANDOM_LONG( -30, 30 );
		pTarget = NULL;
		// oldorigin test
		if ( (pev->origin - pev->oldorigin).Length() < 1 )
		{
			// If leech didn't move, there must be something blocking it, so try to turn
			m_sideTime = 0;
		}

		break;
	}

	m_obstacle = ObstacleDistance( pTarget );
	pev->oldorigin = pev->origin;
	if ( m_obstacle < 0.1 )
		m_obstacle = 0.1;

	// is the way ahead clear?
	if ( m_obstacle == 1.0 )
	{
		// if the leech is turning, stop the trend.
		if ( m_flTurning != 0 )
		{
			m_flTurning = 0;
		}

		m_fPathBlocked = FALSE;
		pev->speed = UTIL_Approach( targetSpeed, pev->speed, LEECH_SWIM_ACCEL * LEECH_FRAMETIME );
		pev->velocity = gpGlobals->v_forward * pev->speed;

	}
	else
	{
		m_obstacle = 1.0 / m_obstacle;
		// IF we get this far in the function, the leader's path is blocked!
		m_fPathBlocked = TRUE;

		if ( m_flTurning == 0 )// something in the way and leech is not already turning to avoid
		{
			Vector vecTest;
			// measure clearance on left and right to pick the best dir to turn
			vecTest = pev->origin + (gpGlobals->v_right * LEECH_SIZEX) + (gpGlobals->v_forward * LEECH_CHECK_DIST);
			UTIL_TraceLine(pev->origin, vecTest, missile, edict(), &tr);
			flRightSide = tr.flFraction;

			vecTest = pev->origin + (gpGlobals->v_right * -LEECH_SIZEX) + (gpGlobals->v_forward * LEECH_CHECK_DIST);
			UTIL_TraceLine(pev->origin, vecTest, missile, edict(), &tr);
			flLeftSide = tr.flFraction;

			// turn left, right or random depending on clearance ratio
			float delta = (flRightSide - flLeftSide);
			if ( delta > 0.1 || (delta > -0.1 && RANDOM_LONG(0,100)<50) )
				m_flTurning = -LEECH_TURN_RATE;
			else
				m_flTurning = LEECH_TURN_RATE;
		}
		pev->speed = UTIL_Approach( -(LEECH_SWIM_SPEED*0.5), pev->speed, LEECH_SWIM_DECEL * LEECH_FRAMETIME * m_obstacle );
		pev->velocity = gpGlobals->v_forward * pev->speed;
	}
	pev->ideal_yaw = m_flTurning + targetYaw;
	UpdateMotion();
}
//------------------------------------------------------------------------------
// Purpose: Fire a round from the cannon
// Notes:	Only call this if you have an enemy.
//------------------------------------------------------------------------------
void CNPC_CombineDropship::FireCannonRound( void )
{

	Vector vecPenetrate;
	trace_t tr;

	QAngle vecAimAngle;
	Vector vecToEnemy, vecEnemyTarget;
	Vector vecMuzzle;
	Vector vecAimDir;

	// HACKHACK until we actually get a muzzle attachment
//	GetAttachment( "muzzle", vecMuzzle, vecAimAngle );
	vecMuzzle = GetAbsOrigin();
	vecAimAngle = GetAbsAngles();

	Vector shipDir, shipLeft;
	AngleVectors( vecAimAngle, &shipDir );
	vecMuzzle.z += 72;
	vecMuzzle += shipDir * 96;

	vecEnemyTarget = GetEnemy()->BodyTarget( vecMuzzle, false );
	
	// Aim with the muzzle's attachment point.
	VectorSubtract( vecEnemyTarget, vecMuzzle, vecToEnemy );

	QAngle enemyAngles;
	VectorAngles(vecToEnemy, enemyAngles );
	float diff = fabs( UTIL_AngleDiff( enemyAngles.y, vecAimAngle.y ));	

	// only allow 90 degrees of freedom when firing
	if ( diff > 45 )
	{
		StopCannon();
		m_flTimeNextAttack = gpGlobals->curtime + 0.05;
		return;	
	}

	if ( !m_bIsFiring )				// start up sound
	{
		StartCannon();
	}

	VectorNormalize( vecToEnemy );

	// If the gun is wildly off target, stop firing!
	// FIXME  - this should use a vector pointing 
	// to the enemy's location PLUS the stitching 
	// error! (sjb) !!!BUGBUG
//	AngleVectors( vecAimAngle, &vecAimDir );	

/*	if( DotProduct( vecToEnemy, vecAimDir ) < 0.980 )
	{
		StopCannonBurst();
		m_flTimeNextAttack = gpGlobals->curtime + 0.1;
		return;
	}
*/
	//Add a muzzle flash
	g_pEffects->MuzzleFlash( vecMuzzle, vecAimAngle, random->RandomFloat( 5.0f, 7.0f ) , MUZZLEFLASH_TYPE_GUNSHIP );

	m_flTimeNextAttack = gpGlobals->curtime + 0.05;

	// Cheat. Fire directly at the target, plus noise.
	int ammoType = GetAmmoDef()->Index("CombineCannon"); 
	FireBullets( 1, vecMuzzle, vecToEnemy, VECTOR_CONE_2DEGREES, 8192, ammoType, 1, -1, -1, 1 /* override damage */ );
}
Ejemplo n.º 18
0
CAI_BaseNPC *CASW_Sentry_Top_Cannon::SelectOptimalEnemy()
{
	// prioritize unfrozen aliens who are going to leave the cone soon.
	// prioritize aliens less the more frozen they get.
	CUtlVectorFixedGrowable< CAI_BaseNPC *,16 > candidates;
	CUtlVectorFixedGrowable< float, 16 > candidatescores;

	// search through all npcs, any that are in LOS and have health
	CAI_BaseNPC **ppAIs = g_AI_Manager.AccessAIs();
	for ( int i = 0; i < g_AI_Manager.NumAIs(); i++ )
	{
		if (ppAIs[i]->GetHealth() > 0 && CanSee(ppAIs[i]))
		{
			// don't shoot marines
			if ( !asw_sentry_friendly_target.GetBool() && ppAIs[i]->Classify() == CLASS_ASW_MARINE )
				continue;

			if ( ppAIs[i]->Classify() == CLASS_SCANNER )
				continue;

			if ( !IsValidEnemy( ppAIs[i] ) )
				continue;

			candidates.AddToTail( ppAIs[i] );
		}
	}

	// bail out if we don't have anyone
	if ( candidates.Count() < 1 )
		return NULL;

	else if ( candidates.Count() == 1 ) // just one candidate is an obvious result
		return candidates[0];

	// score each of the candidates
	candidatescores.EnsureCount( candidates.Count() );
	for ( int i = candidates.Count() - 1; i >= 0 ; --i )
	{
		CAI_BaseNPC * RESTRICT pCandidate = candidates[i];

		// is the candidate moving into or out of the cone?
		Vector vCandVel = GetEnemyVelocity(pCandidate);
		Vector vMeToTarget = pCandidate->GetAbsOrigin() - GetFiringPosition();
		Vector vBaseForward = UTIL_YawToVector( m_fDeployYaw );

		// crush everything to 2d for simplicity
		vMeToTarget.z = 0.0f;
		vCandVel.z = 0.0f;
		vBaseForward.z = 0.0f;

		Vector velCross = vBaseForward.Cross(vCandVel); // this encodes also some info on perpendicularity
		Vector vAimCross = vBaseForward.Cross(vMeToTarget);
		bool bTargetHeadedOutOfCone = !vCandVel.IsZero() && velCross.z * vAimCross.z >= 0; // true if same sign
		float flConeLeavingUrgency;

		if ( bTargetHeadedOutOfCone )
		{
			flConeLeavingUrgency = fabs( velCross.z / vCandVel.Length2D() ); 
			// just the sin; varies 0..1 where 1 means moving perpendicular to my aim
		}
		else
		{
			flConeLeavingUrgency = 0; // not at threat of leaving just yet
		}

		// the angle between my current yaw and what's needed to hit the target
		float flSwivelNeeded = fabs( UTIL_AngleDiff(  // i wish we weren't storing euler angles
			UTIL_VecToYaw( vMeToTarget ), m_fDeployYaw ) );
		flSwivelNeeded /= ASW_SENTRY_ANGLE; // normalize to 0..2

		float fBigness = 0.0f;

		int nClassify = pCandidate->Classify();
		switch( nClassify )
		{
		case CLASS_ASW_SHIELDBUG:
		case CLASS_ASW_MORTAR_BUG:
			fBigness = 4.0f;
			break;

		case CLASS_ASW_HARVESTER:
		case CLASS_ASW_RANGER:
			fBigness = 2.0f;
			break;
		}

		candidatescores[i] = Vector( 3.0f, -1.5f, 4.0f ).Dot( Vector( flConeLeavingUrgency, flSwivelNeeded, fBigness ) );
	}
	// find the highest scoring candidate
	int best = 0;
	for ( int i = 1 ; i < candidatescores.Count() ; ++i )
	{
		if ( candidatescores[i] > candidatescores[best] )
			best = i;
	}

	// NDebugOverlay::EntityBounds(candidates[best], 255, 255, 0, 255, 0.2f );

	return candidates[best];
}
void CAI_BlendedMotor::BuildTurnScript( const AILocalMoveGoal_t &move  )
{
	int i;

	AI_Movementscript_t script;
	script.Init();

	// current location
	script.vecLocation = GetAbsOrigin();
	script.flYaw = GetAbsAngles().y;
	m_scriptTurn.AddToTail( script );

	//-------------------------

	// insert default turn parameters, try to turn 80% to goal at all corners before getting there
	int prev = 0;
	for (i = 0; i < m_scriptMove.Count(); i++)
	{
		AI_Waypoint_t *pCurWaypoint = m_scriptMove[i].pWaypoint;
		if (pCurWaypoint)
		{
			script.Init();
			script.vecLocation = pCurWaypoint->vecLocation;
			script.pWaypoint = pCurWaypoint;
			script.flElapsedTime = m_scriptMove[i].flElapsedTime;

			m_scriptTurn[prev].flTime = script.flElapsedTime - m_scriptTurn[prev].flElapsedTime;

			if (pCurWaypoint->GetNext())
			{
				Vector d1 = pCurWaypoint->GetNext()->vecLocation - script.vecLocation;
				Vector d2 = script.vecLocation - m_scriptTurn[prev].vecLocation;
				
				d1.z = 0;
				VectorNormalize( d1 );
				d2.z = 0;
				VectorNormalize( d2 );

				float y1 = UTIL_VecToYaw( d1 );
				float y2 = UTIL_VecToYaw( d2 );

				float deltaYaw = fabs( UTIL_AngleDiff( y1, y2 ) );

				if (deltaYaw > 0.1)
				{
					// turn to 80% of goal
					script.flYaw = UTIL_ApproachAngle( y1, y2, deltaYaw * 0.8 );
					m_scriptTurn.AddToTail( script );
					// DevMsg("turn waypoint %.1f %.1f %.1f\n", script.vecLocation.x, script.vecLocation.y, script.vecLocation.z );
					prev++;
				}
			}
			else
			{
				Vector vecDir = GetNavigator()->GetArrivalDirection();
				script.flYaw = UTIL_VecToYaw( vecDir );
				m_scriptTurn.AddToTail( script );
				// DevMsg("turn waypoint %.1f %.1f %.1f\n", script.vecLocation.x, script.vecLocation.y, script.vecLocation.z );
				prev++;
			}
		}
	}

	// propagate ending facing back over any nearby nodes
	// FIXME: this needs to minimize total turning, not just local/end turning.
	// depending on waypoint spacing, complexity, it may turn the wrong way!
	for (i = m_scriptTurn.Count()-1; i > 1; i--)
	{
		float deltaYaw = UTIL_AngleDiff( m_scriptTurn[i-1].flYaw, m_scriptTurn[i].flYaw );
	
		float maxYaw = YAWSPEED * m_scriptTurn[i-1].flTime;

		if (fabs(deltaYaw) > maxYaw)
		{
			m_scriptTurn[i-1].flYaw = UTIL_ApproachAngle( m_scriptTurn[i-1].flYaw, m_scriptTurn[i].flYaw, maxYaw );
		}
	}

	for (i = 0; i < m_scriptTurn.Count() - 1; )
	{
		i = i + BuildTurnScript( i, i + 1 ) + 1;
	}
	//-------------------------
}
void CAI_BlendedMotor::MaintainTurnActivity( void )
{
	if (m_flNextTurnGesture > gpGlobals->curtime || m_flNextTurnAct > gpGlobals->curtime || GetOuter()->IsMoving() )
	{
		// clear out turn detection if currently turing or moving
		m_doTurn = m_doRight = m_doLeft = 0;
		if ( GetOuter()->IsMoving())
		{
			m_flNextTurnAct = gpGlobals->curtime + 0.3;
		}
	}
	else 
	{
		// detect undirected turns
		if (m_prevYaw != GetAbsAngles().y)
		{
			float diff = UTIL_AngleDiff( m_prevYaw, GetAbsAngles().y );
			if (diff < 0.0)
			{
				m_doLeft += -diff;
			}
			else
			{
				m_doRight += diff;
			}
			m_prevYaw = GetAbsAngles().y;
		}
		// accumulate turn angle, delay response for short turns
		m_doTurn += m_doRight + m_doLeft;
		// accumulate random foot stick clearing
		m_doTurn += enginerandom->RandomFloat( 0.4, 0.6 );
	}

	if (m_doTurn > 15.0f)
	{
		// mostly a foot stick clear
		int iSeq = ACT_INVALID;
		if (m_doLeft > m_doRight)
		{
			iSeq = SelectWeightedSequence( ACT_GESTURE_TURN_LEFT );
		}
		else
		{
			iSeq = SelectWeightedSequence( ACT_GESTURE_TURN_RIGHT );
		}
		m_doLeft = 0;
		m_doRight = 0;

		if (iSeq != ACT_INVALID)
		{
			int iLayer = GetOuter()->AddGestureSequence( iSeq );
			if (iLayer != -1)
			{
				GetOuter()->SetLayerPriority( iLayer, 100 );
				// increase speed if we're getting behind or they're turning quickly
				float rate = enginerandom->RandomFloat( 0.8, 1.2 );
				if (m_doTurn > 90.0)
				{
					rate *= 1.5;
				}
				GetOuter()->SetLayerPlaybackRate( iLayer, rate );
				// disable turing for the duration of the gesture
				m_flNextTurnAct = gpGlobals->curtime + GetOuter()->GetLayerDuration( iLayer );
			}
			else
			{
				// too many active gestures, try again in half a second
				m_flNextTurnAct = gpGlobals->curtime + 0.3;
			}
		}
		m_doTurn = m_doRight = m_doLeft = 0;
	}
}
Ejemplo n.º 21
0
void CTank :: DriveThink ( void )
{
	pev->nextthink = gpGlobals->time + NEXTTHINK_TIME;
	StudioFrameAdvance ( );

	if ( pev->sequence == 1 )
		pev->sequence = 0;

//	ALERT ( at_console, "playerdrivetank : %s\n", m_pPlayer->m_iDrivingTank == TRUE ? "TRUE" : "FALSE" ); 

	// apres le changement de niveau, reinitialisation de la vue

	if ( bSetView == 1 )
	{
		// actualisation de la vie du bsp

		m_pTankBSP->pev->health = m_flTempHealth;

		// réglages camera & hud

		m_pCam->SetPlayerTankView ( TRUE );
		bSetView = 0;
	}

	//quitte le tank

	if (m_pPlayer->pev->button & IN_USE)
	{
		pev->velocity = pev->avelocity = m_pTankBSP->pev->velocity = m_pTankBSP->pev->avelocity =Vector (0,0,0);
		m_pTankBSP->pev->origin = pev->origin;
		m_pTankBSP->pev->angles = pev->angles;

		m_pCam->pev->velocity = ( vecCamOrigin() - m_pCam->pev->origin ) /2;
		UpdateCamAngle ( m_pCam->pev->origin, 2 );

		UpdateSound ();

		SetThink( StopThink );
		pev->nextthink = gpGlobals->time + 2;
		return;
	}


	float flNextVAngleY = pev->v_angle.y;
	float flNextVAngleX = pev->v_angle.x;
	float flNewAVelocity;
	Vector vecNewVelocity;

	//---------------------------------------------_-_-_ _  _
	//modifications de la direction de la tourelle
			
	if ( bTankOn == 0 )
	{
		bTankOn = 1;
		m_PlayerAngles.x = m_pPlayer->pev->angles.x ;
		m_PlayerAngles.y = m_pPlayer->pev->angles.y ;
	}

	if ( m_pPlayer->pev->angles.y != m_PlayerAngles.y )
	{
		int iSens;
		int iDist = ModifAngles ( m_pPlayer->pev->angles.y ) - ModifAngles ( m_PlayerAngles.y );

		if ( fabs(iDist) > 180 )
		{
			if ( iDist > 0 )
				iDist = iDist - 360;
			else
				iDist = iDist + 360;
		}

		iSens = iDist == fabs(iDist) ? 1 : -1 ;
		iDist = fabs(iDist);


		if ( iDist < TANK_TOURELLE_ROT_SPEED )
			flNextVAngleY += iDist * iSens;

		else
			flNextVAngleY += TANK_TOURELLE_ROT_SPEED * iSens;

		if ( flNextVAngleY > TOURELLE_MAX_ROT_Y )
			flNextVAngleY = TOURELLE_MAX_ROT_Y;

		if ( flNextVAngleY < -TOURELLE_MAX_ROT_Y )
			flNextVAngleY = -TOURELLE_MAX_ROT_Y;

	}

	if ( m_pPlayer->pev->angles.x != m_PlayerAngles.x )
	{
		int iSens;
		int iDist = ModifAngles ( m_pPlayer->pev->angles.x ) - ModifAngles ( m_PlayerAngles.x );

		if ( fabs(iDist) > 180 )
		{
			if ( iDist > 0 )
				iDist = iDist - 360;
			else
				iDist = iDist + 360;
		}

		iSens = iDist == fabs(iDist) ? 1 : -1 ;
		iDist = fabs(iDist);

		if ( iDist < TANK_TOURELLE_ROT_SPEED )
			flNextVAngleX += iDist * iSens;

		else
			flNextVAngleX += TANK_TOURELLE_ROT_SPEED * iSens;

		if ( flNextVAngleX > TOURELLE_MAX_ROT_X )
			flNextVAngleX = TOURELLE_MAX_ROT_X;

		if ( flNextVAngleX < TOURELLE_MAX_ROT_X2 )
			flNextVAngleX = TOURELLE_MAX_ROT_X2;

	}

	m_PlayerAngles.y = m_pPlayer->pev->angles.y;
	m_PlayerAngles.x = m_pPlayer->pev->angles.x;


	//---------------------------------
	// sons d'acceleration du tank

	float flSpeed = pev->velocity.Length();

	if ( m_flNextSound < gpGlobals->time)
	{
		if  ( (m_pPlayer->pev->button & IN_FORWARD) && ((flSpeed==0) || (m_iTankmove & MOVE_BACKWARD)) )
		{
			EMIT_SOUND_DYN(ENT(pev), CHAN_ITEM, ACCELERE_SOUND1, 1 , ATTN_NONE, 0, 100 );
			m_flNextSound = gpGlobals->time + 2.5;
		}
		else if  ( (m_pPlayer->pev->button & IN_BACK) && (m_iTankmove & MOVE_FORWARD) )
		{
			EMIT_SOUND_DYN(ENT(pev), CHAN_ITEM, DECCELERE_SOUND, 1 , ATTN_NONE, 0, 100 );
			m_flNextSound = gpGlobals->time + 2.5;
		}
		else if  ( (m_pPlayer->pev->button & IN_FORWARD) && (m_iTankmove & MOVE_FORWARD) && !(m_iTankmove & PUSH_FORWARD))
		{
			if ( RANDOM_LONG ( 0,1 ) )
				EMIT_SOUND_DYN(ENT(pev), CHAN_ITEM, ACCELERE_SOUND2, 1 , ATTN_NONE, 0, 100 );
			else
				EMIT_SOUND_DYN(ENT(pev), CHAN_ITEM, ACCELERE_SOUND3, 1 , ATTN_NONE, 0, 100 );
			m_flNextSound = gpGlobals->time + 2.5;
		}
	}


	//-------------------------------
	//modification de la vitesse du tank


	UTIL_MakeVectors( pev->angles );

	int iSens = UTIL_AngleDiff( UTIL_VecToAngles ( pev->velocity ).y,  UTIL_VecToAngles	( gpGlobals->v_forward ).y );

	if ( flSpeed == 0 )
		iSens = 0;
	else if ( iSens < -45 || iSens > 45 )
		iSens = -1;
	else 
		iSens = 1;

	if ( m_pPlayer->pev->button & IN_FORWARD)
	{
		m_iTankmove |= PUSH_FORWARD;
		m_iTankmove &= ~PUSH_BACKWARD;		

		if ( iSens == -1 )
		{
			if ( flSpeed > TANK_DECCELERATION * 2 )
				vecNewVelocity = gpGlobals->v_forward * - ( flSpeed - TANK_DECCELERATION );
			else
				vecNewVelocity = Vector ( 0,0,0 );
		}

		else if ( flSpeed < 250 )
			vecNewVelocity = gpGlobals->v_forward * ( flSpeed + TANK_ACCELERATION );

		else
			vecNewVelocity = gpGlobals->v_forward * 250;
	}


	else if ( m_pPlayer->pev->button & IN_BACK)
	{

		m_iTankmove |= PUSH_BACKWARD;
		m_iTankmove &= ~PUSH_FORWARD;		

		if ( iSens == 1 )
		{
			if ( flSpeed > TANK_DECCELERATION * 2 )
				vecNewVelocity = gpGlobals->v_forward * ( flSpeed - TANK_DECCELERATION );
			else
				vecNewVelocity = Vector ( 0,0,0 );
		}

		else if ( flSpeed < 150 )
			vecNewVelocity = gpGlobals->v_forward * - ( flSpeed + TANK_ACCELERATION );
		else
			vecNewVelocity = gpGlobals->v_forward * -150;
	}

	
	else
	{
		if ( flSpeed > 5 )
			vecNewVelocity = gpGlobals->v_forward * ( flSpeed - 1 ) * iSens;
		else
			vecNewVelocity = gpGlobals->v_forward * flSpeed * iSens;


		m_iTankmove &= ~PUSH_BACKWARD;
		m_iTankmove &= ~PUSH_FORWARD;
	}


	if ( iSens == 1)
	{
		m_iTankmove |= MOVE_FORWARD;
		m_iTankmove &= ~MOVE_BACKWARD;
	}
	else
	{
		m_iTankmove |= MOVE_BACKWARD;
		m_iTankmove &= ~MOVE_FORWARD;
	}



	//modification de la direction du tank

	if ( m_pPlayer->pev->button & IN_MOVELEFT )
		flNewAVelocity = TANK_ROT_SPEED;

	else if ( m_pPlayer->pev->button & IN_MOVERIGHT )
		flNewAVelocity = -TANK_ROT_SPEED;

	else
		flNewAVelocity = 0;


	// test de la position envisagée

	UTIL_MakeVectors ( pev->angles + Vector ( 0, flNewAVelocity / 10 , 0) );

	TraceResult	tr [4]/*1,tr2,tr3,tr4*/;
	Vector vecFrontLeft, vecFrontRight, vecBackLeft, vecBackRight;

	vecFrontLeft =	NEW_ORIGIN + gpGlobals->v_forward * DIST_FRONT_UP + gpGlobals->v_right * -DIST_SIDE + gpGlobals->v_up * DIST_TOP;
	vecFrontRight = NEW_ORIGIN + gpGlobals->v_forward * DIST_FRONT_UP + gpGlobals->v_right * DIST_SIDE + gpGlobals->v_up * DIST_TOP;
	vecBackLeft =	NEW_ORIGIN + gpGlobals->v_forward * DIST_BACK_UP + gpGlobals->v_right * -DIST_SIDE + gpGlobals->v_up * DIST_TOP;
	vecBackRight =	NEW_ORIGIN + gpGlobals->v_forward * DIST_BACK_UP + gpGlobals->v_right * DIST_SIDE + gpGlobals->v_up * DIST_TOP;
					
	UTIL_TraceLine (vecFrontLeft, vecFrontRight,ignore_monsters, ENT(m_pTankBSP->pev), &tr[0]);
	UTIL_TraceLine (vecFrontRight, vecBackRight,ignore_monsters, ENT(m_pTankBSP->pev), &tr[1]);
	UTIL_TraceLine (vecBackRight, vecBackLeft,	ignore_monsters, ENT(m_pTankBSP->pev), &tr[2]);
	UTIL_TraceLine (vecBackLeft, vecFrontLeft,	ignore_monsters, ENT(m_pTankBSP->pev), &tr[3]);


	//pas de collision - application de la nouvelle position

	if ( tr[0].vecEndPos == vecFrontRight && tr[1].vecEndPos == vecBackRight && tr[2].vecEndPos == vecBackLeft && tr[3].vecEndPos == vecFrontLeft )
	{
		StudioFrameAdvance ( 0.1 );

		pev->velocity = vecNewVelocity;
		pev->avelocity = Vector ( 0, flNewAVelocity, 0 );

		m_pCam->m_vecTourelleAngle = pev->v_angle;
		m_pCam->m_flNextFrameTime = pev->nextthink;

		pev->v_angle.y = flNextVAngleY;
		pev->v_angle.x = flNextVAngleX;


		m_pTankBSP->pev->velocity = (( pev->origin + vecNewVelocity * 10 ) - m_pTankBSP->pev-> origin ) / 10 ;
		m_pTankBSP->pev->avelocity = (( pev->angles + Vector ( 0, flNewAVelocity * 10, 0 ) - m_pTankBSP->pev->angles )) / 10;
		// pour combler la différence de vitesse entre le bsp et le mdl

	}

	//collision - arret du tank

	else
	{
		pev->velocity = pev->avelocity = Vector (0,0,0);
		m_pTankBSP->pev->velocity = ( pev->origin - m_pTankBSP->pev-> origin ) / 10 ;
		m_pTankBSP->pev->avelocity = ( pev->angles - m_pTankBSP->pev->angles ) / 10;

		if ( flSpeed > 50 )	// choc violent
		{
			EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, CHOC_SOUND, 0.9, ATTN_NORM, 0, 60 );

		}
	}


	// application des dommages

	vecFrontLeft = vecFrontLeft + Vector ( 0, 0, 10 - DIST_TOP );
	vecFrontRight = vecFrontRight + Vector ( 0, 0, 10 - DIST_TOP );
	vecBackRight = vecBackRight + Vector ( 0, 0, 10 - DIST_TOP );
	vecBackLeft = vecBackLeft + Vector ( 0, 0, 10 - DIST_TOP );

	UTIL_TraceLine (vecFrontLeft, vecFrontRight,dont_ignore_monsters, ENT(m_pTankBSP->pev), &tr[0]);
	UTIL_TraceLine (vecFrontRight, vecBackRight,dont_ignore_monsters, ENT(m_pTankBSP->pev), &tr[1]);
	UTIL_TraceLine (vecBackRight, vecBackLeft,	dont_ignore_monsters, ENT(m_pTankBSP->pev), &tr[2]);
	UTIL_TraceLine (vecBackLeft, vecFrontLeft,	dont_ignore_monsters, ENT(m_pTankBSP->pev), &tr[3]);

	CBaseEntity *pEntity = NULL;

	for ( int i = 0 ; i < 4 ; i ++ )
	{
		if ( tr [ i ].pHit != NULL )
		{
			pEntity =  CBaseEntity :: Instance ( tr [ i ].pHit );

			if ( pEntity != NULL && pEntity->pev->takedamage  )
			{
				float fDamage;

				if ( FClassnameIs ( tr[i].pHit, "func_breakable" ) )
				{
					fDamage =  pEntity->pev->health;
				}
				else
				{
					fDamage = pev->velocity.Length() * 1.5 + 20;
				}

				pEntity->TakeDamage ( pev, pev , fDamage , DMG_CRUSH );
			}
		}
	}

	//rectification de la position de la camera

	vecCamAim = UpdateCam();

	if ( m_pCam->pev->origin != vecCamAim )
		m_pCam->pev->velocity = ( vecCamAim - m_pCam->pev->origin ) * 10;

	UpdateCamAngle ( vecCamAim, NEXTTHINK_TIME );



	//tir de la tourelle

	if ( ( m_pPlayer->pev->button & IN_ATTACK ) && ( gpGlobals->time > m_flLastAttack1 + TANK_REFIRE_DELAY ) )
	{
		Fire ( bCanon );
		bCanon = bCanon == TRUE ? FALSE : TRUE;

		EMIT_SOUND(ENT(pev), CHAN_AUTO, TIR_SOUND, 1, ATTN_NORM);
		m_flLastAttack1 = gpGlobals->time;

		m_pCam->pev->avelocity.x -= 45;

	}

	//tir de la mitrailleuse

	if ( m_pPlayer->pev->button & IN_ATTACK2 )
	{
		Vector posGun, dirGun;
		GetAttachment( 3, posGun, Vector ( 0, 0, 0 ) );
		UTIL_MakeVectorsPrivate( TourelleAngle(), dirGun, NULL, NULL );
		FireBullets( 1, posGun, dirGun, VECTOR_CONE_5DEGREES, 8192, BULLET_MONSTER_12MM );

		EMIT_SOUND(ENT(pev), CHAN_WEAPON, MITRAILLEUSE_SOUND, 1, ATTN_NORM);

		if ( !FStrEq(STRING(gpGlobals->mapname), "l3m10") && !FStrEq(STRING(gpGlobals->mapname), "l3m12")  && !FStrEq(STRING(gpGlobals->mapname), "l3m14")  )
		{			
			CSprite *pSprite = CSprite::SpriteCreate( SPRITE_MUZ, posGun, TRUE );
			pSprite->AnimateAndDie( 15 );
			pSprite->SetTransparency( kRenderTransAdd, 255, 255, 255, 255, kRenderFxNoDissipation );
			pSprite->SetAttachment( edict(), 4 );
			pSprite->SetScale( SPRITE_MUZ_SCALE );
		}


	}



	//sond du tank

	UpdateSound ();

	CSoundEnt::InsertSound ( bits_SOUND_DANGER, pev->origin + pev->velocity * 2.5, 150, NEXTTHINK_TIME );
	CSoundEnt::InsertSound ( bits_SOUND_PLAYER, pev->origin, 2000, 0.5 );



}
//-----------------------------------------------------------------------------
// Purpose: 
// Output : int
//-----------------------------------------------------------------------------
int CAI_PolicingBehavior::SelectSchedule( void )
{
	CBaseEntity *pTarget = m_hPoliceGoal->GetTarget();

	// Validate our target
	if ( pTarget == NULL )
	{
		DevMsg( "ai_goal_police with NULL target entity!\n" );
		
		// Turn us off
		Disable();
		return SCHED_NONE;
	}

	// Attack if we're supposed to
	if ( ( m_flAggressiveTime >= gpGlobals->curtime ) && HasCondition( COND_CAN_MELEE_ATTACK1 ) )
	{
		return SCHED_MELEE_ATTACK1;
	}

	// See if we should immediately begin to attack our target
	if ( HasCondition( COND_POLICE_TARGET_TOO_CLOSE_SUPPRESS ) )
	{
		return SelectSuppressSchedule();
	}
	
	int newSchedule = SCHED_NONE;

	// See if we're harassing
	if ( HasCondition( COND_POLICE_TARGET_TOO_CLOSE_HARASS ) )
	{
		newSchedule = SelectHarassSchedule();
	}

	// Return that schedule if it was found
	if ( newSchedule != SCHED_NONE )
		return newSchedule;

	// If our enemy is set, fogeda'bout it!
	if ( m_flAggressiveTime < gpGlobals->curtime )
	{
		// Return to your initial spot
		if ( GetEnemy() )
		{
			GetOuter()->SetEnemy( NULL );
			GetOuter()->SetState( NPC_STATE_ALERT );
			GetOuter()->GetEnemies()->RefreshMemories();
		}

		HostSetBatonState( false );
		m_bTargetIsHostile = false;
	}	

	// If we just started to police, make sure we're on our mark
	if ( MaintainGoalPosition() )
		return SCHED_POLICE_RETURN_FROM_HARASS;

	// If I've got my baton on, keep looking at the target
	if ( HostBatonIsOn() )
		return SCHED_POLICE_TRACK_TARGET;

	// Re-align myself to the goal angles if I've strayed
	if ( fabs(UTIL_AngleDiff( GetAbsAngles().y, m_hPoliceGoal->GetAbsAngles().y )) > 15 )
		return SCHED_POLICE_FACE_ALONG_GOAL;

	return SCHED_IDLE_STAND;
}
Ejemplo n.º 23
0
//-----------------------------------------------------------------------------
// Purpose: MouseMove -- main entry point for applying mouse
// Input  : *cmd - 
//-----------------------------------------------------------------------------
void CInput::MouseMove( int nSlot, CUserCmd *cmd )
{
	float	mouse_x, mouse_y;
	float	mx, my;
	QAngle	viewangles;
	QAngle actual_viewangles;

	// Get view angles from engine
	engine->GetViewAngles( actual_viewangles );

	PerUserInput_t perUser = GetPerUser(nSlot);

	if (m_cinematic.GetBool()) {
		viewangles = perUser.m_angCinematicSetpoint;
	} else {
		viewangles = actual_viewangles;
	}

	// Validate mouse speed/acceleration settings
	CheckMouseAcclerationVars();

	// Don't drift pitch at all while mouselooking.
	view->StopPitchDrift ();

	//jjb - this disables normal mouse control if the user is trying to 
	//      move the camera, or if the mouse cursor is visible 
	if ( !GetPerUser( nSlot ).m_fCameraInterceptingMouse && g_pInputStackSystem->IsTopmostEnabledContext( m_hInputContext ) )
	{
		// Sample mouse one more time
		AccumulateMouse( nSlot );

		// Latch accumulated mouse movements and reset accumulators
		GetAccumulatedMouseDeltasAndResetAccumulators( nSlot, &mx, &my );

		// Filter, etc. the delta values and place into mouse_x and mouse_y
		GetMouseDelta( nSlot, mx, my, &mouse_x, &mouse_y );

		// Apply scaling factor
		ScaleMouse( nSlot, &mouse_x, &mouse_y );

		// Let the client mode at the mouse input before it's used
		GetClientMode()->OverrideMouseInput( &mouse_x, &mouse_y );

		// Add mouse X/Y movement to cmd
		ApplyMouse( nSlot, viewangles, cmd, mouse_x, mouse_y );

		// Re-center the mouse.
		ResetMouse();
	}

	GetPerUser(nSlot).m_angCinematicSetpoint = viewangles;

	if (m_cinematic.GetBool()) {
		float k = m_cinematic_depth.GetFloat();
		QAngle steering;
		steering.x = UTIL_AngleDiff(viewangles.x, actual_viewangles.x);
		steering.y = UTIL_AngleDiff(viewangles.y, actual_viewangles.y);
		steering.z = UTIL_AngleDiff(viewangles.z, actual_viewangles.z);

		actual_viewangles += steering * (1-k);

	} else {
		actual_viewangles = viewangles;
	}

	// Store out the new viewangles.
	engine->SetViewAngles( actual_viewangles );
}