Beispiel #1
0
// check whether a ship is in jump range of a stargate ------------------------
//
PRIVATE
int ShipInStargateJumpRange( Stargate *stargate, ShipObject *ship, geomv_t range )
{
	ASSERT( stargate != NULL );
	ASSERT( ship != NULL );

	//NOTE:
	// the ship is treated as a point for jump
	// range detection.

	Vector3 gatenormal;
	FetchZVector( stargate->ObjPosition, &gatenormal );

	Vertex3 gatepos;
	FetchTVector( stargate->ObjPosition, &gatepos );

	Vertex3 shippos;
	FetchTVector( ship->ObjPosition, &shippos );

	geomv_t shipdot  = -DOT_PRODUCT( &gatenormal, &shippos );
	geomv_t gatedot  = -DOT_PRODUCT( &gatenormal, &gatepos );
	geomv_t distance = shipdot - gatedot;

	// not in range if ship in wrong halfspace
	if ( GEOMV_NEGATIVE( distance ) ) {
		return FALSE;
	}

	// check whether inside of boundingsphere around stargate
	Vector3 stargate_ship;
	VECSUB( &stargate_ship, &shippos, &gatepos );

	geomv_t stargate_ship_len = VctLenX( &stargate_ship );
	if ( stargate_ship_len > stargate->BoundingSphere ) {
		return FALSE;
	}

	// inside the activation distance/range ?
	if ( distance < range ) {

		Vector3 shipnormal;
		FetchZVector( ship->ObjPosition, &shipnormal );

		// ship must be flying approximately head-on into the gate
		//FIXME: cone_angle like for teleporter
		geomv_t dirdot = DOT_PRODUCT( &gatenormal, &shipnormal );
		return ( dirdot > FLOAT_TO_GEOMV( 0.7f ) );
	}

	return FALSE;
}
Beispiel #2
0
// check whether a ship is in range of a stargate -----------------------------
//
PRIVATE
int ShipInStargateRange( Stargate *stargate, ShipObject *ship, geomv_t range )
{
	ASSERT( stargate != NULL );
	ASSERT( ship != NULL );

	//NOTE:
	// the ship is treated as a sphere for activation
	// range detection.

	Vector3 gatenormal;
	FetchZVector( stargate->ObjPosition, &gatenormal );

	Vertex3 gatepos;
	FetchTVector( stargate->ObjPosition, &gatepos );

	Vertex3 shippos;
	FetchTVector( ship->ObjPosition, &shippos );

	geomv_t shipdot  = -DOT_PRODUCT( &gatenormal, &shippos );
	geomv_t gatedot  = -DOT_PRODUCT( &gatenormal, &gatepos );
	geomv_t distance = shipdot - gatedot;

	// bounding sphere touching in negative halfspace is still ok
	distance += ship->BoundingSphere;

	// not in range if ship in wrong halfspace
	if ( GEOMV_NEGATIVE( distance ) ) {
		return FALSE;
	}

	// in range if ship bounding sphere intersects gate range hemisphere
	range += ship->BoundingSphere * 2;
	return ( distance < range );
}
Beispiel #3
0
// ----------------------------------------------------------------------------
//
void BOT_AI::_SteerToPosition( Vector3* targetPos, object_control_s* pObjctl )
{
	// get vector to target
	Vector3 vec2Target;	
	VECSUB( &vec2Target, targetPos, &m_AgentPos );

	float oldaccel = pObjctl->accel;

	UTL_LocomotionController _LomoCtrl;
	_LomoCtrl.ControlOjbect( pObjctl, &vec2Target, pObjctl->pShip->MaxSpeed );

	if ( pObjctl->accel != oldaccel ) {
#ifdef BOT_LOGFILES
		BOT_AccelMode_MsgOut( "%f %f %f", m_AgentPos.X, m_AgentPos.Y, m_AgentPos.Z );
#endif // BOT_LOGFILES
	}

	Vector3 xDir, yDir, zDir;
	FetchXVector( m_pShip->ObjPosition, &xDir );
	FetchYVector( m_pShip->ObjPosition, &yDir );
	FetchZVector( m_pShip->ObjPosition, &zDir );

#ifdef BOT_LOGFILES
	BOT_MsgOut( "pos: %7.2f/%7.2f/%7.2f vec2target: %7.2f/%7.2f/%7.2f xDir: %7.2f/%7.2f/%7.2f yDir: %7.2f/%7.2f/%7.2f rot_x: %7.2f rot_y: %7.2f accel: %7.2f",
		m_AgentPos.X, m_AgentPos.Y, m_AgentPos.Z,
				vec2Target.X, vec2Target.Y, vec2Target.Z,
				xDir.X, xDir.Y, xDir.Z,
				yDir.X, yDir.Y, yDir.Z,
				pObjctl->rot_x, pObjctl->rot_y, pObjctl->accel );

	BOT_Pos_MsgOut ( "%f %f %f", m_AgentPos.X, m_AgentPos.Y, m_AgentPos.Z );
	BOT_XDir_MsgOut( "%f %f %f", xDir.X, xDir.Y, xDir.Z );
	BOT_ZDir_MsgOut( "%f %f %f", zDir.X, zDir.Y, zDir.Z );
#endif // BOT_LOGFILES

}
Beispiel #4
0
// ----------------------------------------------------------------------------
//
void UTL_LocomotionController::ControlOjbect( object_control_s* pObjctl, Vector3* pDesiredVelocity, fixed_t _DesiredSpeed )
{
	ASSERT( pObjctl != NULL );
	ASSERT( pDesiredVelocity != NULL );

	Vector3 xDir, yDir, zDir;
	FetchXVector( pObjctl->pShip->ObjPosition, &xDir );
	FetchYVector( pObjctl->pShip->ObjPosition, &yDir );
	FetchZVector( pObjctl->pShip->ObjPosition, &zDir );

	geomv_t len = VctLenX( pDesiredVelocity );

	// stop control if desired velocity is zero 
	if ( len <= GEOMV_VANISHING ) {
		pObjctl->rot_x = 0;
		pObjctl->rot_y = 0;
		pObjctl->accel = -0.82;

#ifdef BOT_LOGFILES
		BOT_MsgOut( "ControlOjbect() got dimishing desired velocity" );
#endif // BOT_LOGFILES

		return;
	} else {
		Vector3 DesVelNorm;
		DesVelNorm.X = FLOAT_TO_GEOMV( pDesiredVelocity->X / len );
		DesVelNorm.Y = FLOAT_TO_GEOMV( pDesiredVelocity->Y / len );
		DesVelNorm.Z = FLOAT_TO_GEOMV( pDesiredVelocity->Z / len );
		
		geomv_t yaw_dot		= DOT_PRODUCT( &DesVelNorm, &xDir );
		geomv_t pitch_dot	= DOT_PRODUCT( &DesVelNorm, &yDir );
		geomv_t heading_dot = DOT_PRODUCT( &DesVelNorm, &zDir );

		float fDesiredSpeed = FIXED_TO_FLOAT( _DesiredSpeed );
		float fCurSpeed	  = FIXED_TO_FLOAT( pObjctl->pShip->CurSpeed );

		float pitch = 0;
		float yaw   = 0;

		// target is behind us
		sincosval_s fullturn;
		GetSinCos( DEG_TO_BAMS( 2 * m_nRelaxedHeadingAngle ), &fullturn );
		//if ( heading_dot < 0.0f ) {
		if ( heading_dot < -fullturn.cosval ) {

			// we must initiate a turn, if not already in a turn
			if ( !pObjctl->IsYaw() || !pObjctl->IsPitch() ) {

				// default to random
				yaw   = (float)( RAND() % 3 ) - 1;
				pitch = (float)( RAND() % 3 ) - 1;

				// steer towards goal
				if ( yaw_dot < -GEOMV_VANISHING ) {
					yaw = OCT_YAW_LEFT;
				} else if ( yaw_dot > GEOMV_VANISHING ) {
					yaw = OCT_YAW_RIGHT;
				}
				if ( pitch_dot < -GEOMV_VANISHING ) {
					pitch = OCT_PITCH_UP;
				} else if ( pitch_dot > GEOMV_VANISHING ) {
					pitch = OCT_PITCH_DOWN;
				}

			} else {
				// reuse prev. turn information
				pitch = pObjctl->rot_x;
				yaw   = pObjctl->rot_y;
			}

			// slow down, until in direction of target
		       // pObjctl->accel = heading_dot;
			//pObjctl->accel = OCT_DECELERATE;

			// also maintain min. speed during turns
			if ( fCurSpeed > m_fMinSpeedTurn ) {
				pObjctl->accel = -0.42;
			}

		} else {

			// determine accel
			if ( fDesiredSpeed > fCurSpeed ) {
				// accelerate towards target
				pObjctl->accel = OCT_ACCELERATE;
			} else if ( fDesiredSpeed < fCurSpeed ) {
				// decelerate towards target
				pObjctl->accel = OCT_DECELERATE;
			} else {
				// no accel
				pObjctl->accel = 0;
			}

			// heading must be inside of 5 degrees cone angle
			sincosval_s sincosv;
			GetSinCos( DEG_TO_BAMS( m_nRelaxedHeadingAngle ), &sincosv );
			if ( yaw_dot < -sincosv.sinval ) {
				yaw = OCT_YAW_LEFT;
			} else if ( yaw_dot > sincosv.sinval ) {
				yaw = OCT_YAW_RIGHT;
			}
			if ( pitch_dot < -sincosv.sinval ) {
				pitch = OCT_PITCH_UP;
			} else if ( pitch_dot > sincosv.sinval ) {
				pitch = OCT_PITCH_DOWN;
			}

			// if heading outside of 30 degrees cone angle, we decelerate
			GetSinCos( DEG_TO_BAMS( m_nFullSpeedHeading ), &sincosv );
			bool_t bYawOutsideHeading	= ( ( yaw_dot   < -sincosv.sinval ) || ( yaw_dot   > sincosv.sinval ) );
			bool_t bPitchOutsideHeading = ( ( pitch_dot < -sincosv.sinval ) || ( pitch_dot > sincosv.sinval ) );
			if ( bYawOutsideHeading || bPitchOutsideHeading ) {

				// also maintain min. speed during turns
				if ( fCurSpeed > min( m_fMinSpeedTurn, fDesiredSpeed ) ) {
					// decelerate towards target
					pObjctl->accel = OCT_DECELERATE;
				}
			}
		}

#ifdef BOT_LOGFILES
		BOT_MsgOut( "heading_dot: %f, yaw_dot: %f, pitch_dot: %f", heading_dot, yaw_dot, pitch_dot );
#endif // BOT_LOGFILES

		//FIXME: oct must also handle slide horiz./vert.

		pObjctl->rot_x = pitch;
		pObjctl->rot_y = yaw;
	}
}