Esempio n. 1
0
int Plane::OnSameSide(const Vec3& pa, const Vec3& pb) const {
	auto da = DistanceTo(pa);
	auto db = DistanceTo(pb);

	if (da < 0 && db < 0)
		return -1;

	if (da > 0 && db > 0)
		return 1;

	return 0;
}
/*
================
rvMonsterConvoyGround::State_Legs_Move
================
*/
stateResult_t rvMonsterConvoyGround::State_Legs_Move ( const stateParms_t& parms ) {
	enum {
		STAGE_INIT,
		STAGE_MOVE
	};
	switch ( parms.stage ) {
		case STAGE_INIT:
			move.fl.allowAnimMove		= true;
			move.fl.allowPrevAnimMove	= false;
			move.fl.running				= true;
			move.currentDirection		= MOVEDIR_FORWARD;
			// TODO: Looks like current anim rate never gets reset, so they do not correctly accelerate from a stop
			//	unfortunately, adding this change (with a decent acceleration factor) caused them to do lots of
			//	not-so-good looking short moves.
//			moveCurrentAnimRate = 0;

			oldOrigin = physicsObj.GetOrigin ( );
			PlayCycle ( ANIMCHANNEL_LEGS, "run", 0 );
			StartSound( "snd_move", SND_CHANNEL_BODY3, 0, false, NULL );

			return SRESULT_STAGE ( STAGE_MOVE );
			
		case STAGE_MOVE:

			// If not moving forward just go back to idle
			if ( !move.fl.moving || !CanMove() ) {
				StopSound( SND_CHANNEL_BODY3, 0 );
				PostAnimState ( ANIMCHANNEL_LEGS, "Legs_Idle", 0 );
				return SRESULT_DONE;
			}

			// If on the ground update the animation rate based on the normal of the ground plane
			if ( !ai_debugHelpers.GetBool ( ) && physicsObj.HasGroundContacts ( ) ) {
				float	rate;
				idVec3	dir;
								
				dir = (physicsObj.GetOrigin ( ) - oldOrigin);
				
				if ( DistanceTo ( move.moveDest ) < move.walkRange ) {
					rate = moveAnimRateMin;
				} else if ( dir.Normalize ( ) > 0.0f ) {
					rate = idMath::ClampFloat ( -0.7f, 0.7f, physicsObj.GetGravityNormal ( ) * dir ) / 0.7f;
					rate = moveAnimRateMin + moveAnimRateRange * (1.0f + rate) / 2.0f;
				} else {
					rate = moveAnimRateMin + moveAnimRateRange * 0.5f;
				}
				moveCurrentAnimRate += ((rate - moveCurrentAnimRate) * moveAccelRate);
				
				animator.CurrentAnim ( ANIMCHANNEL_LEGS )->SetPlaybackRate ( gameLocal.time, moveCurrentAnimRate );
			}

			oldOrigin = physicsObj.GetOrigin ( );
			
			return SRESULT_WAIT;
	}
		
	return SRESULT_ERROR;
}
END_CLASS_STATES

//------------------------------------------------------------
// rvMonsterBossBuddy::State_Torso_RocketAttack
//------------------------------------------------------------
stateResult_t rvMonsterBossBuddy::State_Torso_RocketAttack( const stateParms_t& parms ) 
{
	enum 
	{ 
		STAGE_INIT,
		STAGE_WAITSTART,
		STAGE_LOOP,
		STAGE_WAITLOOP,
		STAGE_WAITEND
	};
	switch ( parms.stage ) 
	{
		case STAGE_INIT:
			DisableAnimState( ANIMCHANNEL_LEGS );
			PlayAnim( ANIMCHANNEL_TORSO, "attack_rocket2start", parms.blendFrames );
			mShots = (gameLocal.random.RandomInt( 3 ) + 2) * combat.aggressiveScale;
			return SRESULT_STAGE( STAGE_WAITSTART );
			
		case STAGE_WAITSTART:
			if ( AnimDone( ANIMCHANNEL_TORSO, 0 )) 
			{
				return SRESULT_STAGE( STAGE_LOOP );
			}
			return SRESULT_WAIT;
		
		case STAGE_LOOP:
			PlayAnim( ANIMCHANNEL_TORSO, "attack_rocket2loop2", 0 );
			return SRESULT_STAGE( STAGE_WAITLOOP );
		
		case STAGE_WAITLOOP:
			if ( AnimDone( ANIMCHANNEL_TORSO, 0 )) 
			{
				if ( --mShots <= 0 ||										// exhausted mShots? .. or
						(!IsEnemyVisible() && rvRandom::irand(0,10)>=8 ) ||	// ... player is no longer visible .. or
						( enemy.ent && DistanceTo(enemy.ent)<256 ) ) 		// ... player is so close, we prolly want to do a melee attack
				{
					PlayAnim( ANIMCHANNEL_TORSO, "attack_rocket2end", 0 );
					return SRESULT_STAGE( STAGE_WAITEND );
				}
				return SRESULT_STAGE( STAGE_LOOP );
			}
			return SRESULT_WAIT;
		
		case STAGE_WAITEND:
			if ( AnimDone( ANIMCHANNEL_TORSO, 4 )) 
			{
				return SRESULT_DONE;
			}
			return SRESULT_WAIT;				
	}
	return SRESULT_ERROR; 
}
Esempio n. 4
0
double Point2d::DistanceToLine(Point2d p0, Point2d dp, bool segment) {
    double m = dp.x*dp.x + dp.y*dp.y;
    if(m < LENGTH_EPS*LENGTH_EPS) return VERY_POSITIVE;
   
    // Let our line be p = p0 + t*dp, for a scalar t from 0 to 1
    double t = (dp.x*(x - p0.x) + dp.y*(y - p0.y))/m;

    if((t < 0 || t > 1) && segment) {
        // The closest point is one of the endpoints; determine which.
        double d0 = DistanceTo(p0);
        double d1 = DistanceTo(p0.Plus(dp));

        return min(d1, d0);
    } else {
        Point2d closest = p0.Plus(dp.ScaledBy(t));
        return DistanceTo(closest);
    }
}
Esempio n. 5
0
//---------------------------------------------------------------------------
int Plane3::WhichSide(const Vec3& p) const
{
	Real distance = DistanceTo(p);
	if (distance<0.0f)
		return -1;
	if (distance>0.0)
		return 1;
	return 0;
}
Esempio n. 6
0
Path PathFinder::findPath(const Coord& start, const Coord& end)
{
  Coord mapEnd;
  if ( makeMap( start, DistanceTo(end), ReachedPos(end), &mapEnd ) )
  {
    return getPath(start, end);
  }
  return Path();
}
Esempio n. 7
0
E_PlaneSide mxPlane::ClassifyPointRelation( const Vec3D& point ) const
{
	const f32  fDist = DistanceTo( point );
	if ( fDist < -PLANESIDE_EPSILON ) {
		return SIDE_BACK;
	}
	else if ( fDist > +PLANESIDE_EPSILON ) {
		return SIDE_FRONT;
	}
	return SIDE_ON;
}
Esempio n. 8
0
E_PlaneSide mxPlane::ClassifyPointRelation_epsilon( const Vec3D& point, const f32 epsilon /* =PLANESIDE_EPSILON */ ) const
{
	const f32  fDist = DistanceTo( point );
	if ( fDist < -epsilon ) {
		return SIDE_BACK;
	}
	else if ( fDist > +epsilon ) {
		return SIDE_FRONT;
	}
	return SIDE_ON;
}
Esempio n. 9
0
int Plane3x::WhichSide (const Vector3x& rkQ) const
{
	fixed fDistance = DistanceTo(rkQ);
	
	if (fDistance < FIXED_ZERO)
	{
		return -1;
	}
	
	if (fDistance > FIXED_ZERO)
	{
		return +1;
	}
	
	return 0;
}
Esempio n. 10
0
void Key::cursor_value( const DataSource::PixelInfo& info, float value )
{
    bool approx = false;
    if ( std::isnan(value) ) {
        /* Search for color in key closest to info.color */
        std::vector<Color>::iterator element = 
            std::min_element( colors.begin(), colors.end(), 
                              DistanceTo(info.pixel) );
        
        value = values[ element - colors.begin() ];
        approx = true;
    }

    wxChar cbuffer[128];
    float remainder; const wxChar *SI_unit_prefix;
    make_SI_prefix( value, remainder, SI_unit_prefix );
    wxSnprintf(cbuffer, 128, wxT("%.3g %s"), 
        remainder, SI_unit_prefix);
    cursor->SetLabel( ((approx) ? wxT("ca. ") : wxT("")) + wxString(cbuffer) );
}
Esempio n. 11
0
void Mass::ApplyGravityFrom(const Mass body, float timestep)
{
    float dx = this->position.X() - body.GetPosition().X(),
          dy = this->position.Y() - body.GetPosition().Y(),
          d  = DistanceTo(body);
    
    if(d < 20) d = 20.0f;
    
    /* Accel due to gravity = GM / d^2 = d / t^2
    We want change in velocity, which is d/t
    So multiply accel by t:
    GM / d^2 * t = GMt / d^2    unit: d/t
    But we want the components of that velocity
    So multiply by dx/d and dy/d:
       delta xv = GMt * dx / d^3
       delta yv = GMt * dy / d^3
    Calculate once GMt / d^3: */
    float hertz = body.GetMass() * timestep * -0.0015 / (d*d*d);
    
    this->velocity = this->velocity + Vector2D(hertz*dx, hertz*dy);
}
Esempio n. 12
0
E_PlaneSide mxPlane::ClassifyVolumeRelation( const AABB& bv, const f32 epsilon /* =PLANESIDE_EPSILON */ ) const
{
	// if mxBounds is an axis aligned bounding box
	Vec3D  vCenter = (bv.MinEdge + bv.MaxEdge) * 0.5f;

	f32  dist1 = DistanceTo( vCenter );

	const f32 * center	= reinterpret_cast< const f32* >( & vCenter );
	const f32 * b1		= reinterpret_cast< const f32* >( & bv.MaxEdge );
	const f32 * normal	= reinterpret_cast< const f32* >( & Normal );

	f32  dist2 = idMath::Fabs( ( b1[0] - center[0] ) * normal[0] ) +
					idMath::Fabs( ( b1[1] - center[1] ) * normal[1] ) +
						idMath::Fabs( ( b1[2] - center[2] ) * normal[2] );

	if ( dist1 - dist2 > epsilon ) {
		return SIDE_FRONT;
	}
	if ( dist1 + dist2 < -epsilon ) {
		return SIDE_BACK;
	}
	return SIDE_CROSS;
}
Esempio n. 13
0
// ********************************************************************************************
// Checks for changes every NPS_TICKRATE milliseconds
// Checks:
//			* if we've gotten close enough to a nav point for it to be counted as "Visited"
//			* If we're current AutoNavigating it checks if we need to autodisengage
void NavSystem_Do()
{
	static unsigned int last_update = 0;
	if (clock () - last_update > NPS_TICKRATE)
	{
		if (AutoPilotEngaged)
		{
			if (The_mission.flags & MISSION_FLAG_USE_AP_CINEMATICS)
			{
				camera *cam = nav_get_set_camera();
				if (CinematicStarted)
				{
					// update our cinematic and possibly perform warp
					//if (!CameraMoving)
					if(cam != NULL)
						cam->set_rotation_facing(&Player_obj->pos);

					if (timestamp() >= MoveCamera && !CameraMoving && vm_vec_mag(&cameraTarget) > 0.0f)
					{
						//Free_camera->set_position(&cameraTarget, float(camMovingTime), float(camMovingTime)/2.0f);
						//Free_camera->set_translation_velocity(&cameraTarget);
						CameraMoving = true;
					}


					if (timestamp() >= EndAPCinematic || !CanAutopilot())
					{
						nav_warp();
						EndAutoPilot();
					}
				}
				else
				{
					// start cinematic
					if (UseCutsceneBars)
					{
						Cutscene_bar_flags |= CUB_CUTSCENE;
						Cutscene_bar_flags &= ~CUB_GRADUAL;
					}
					nav_warp(true);

					if(cam != NULL)
					{
						cam->set_position(&cameraPos);
						cam->set_rotation_facing(&Autopilot_flight_leader->pos);
					}

					CinematicStarted = true;
				}
			}
			else
			{
				if (!CanAutopilot())
					EndAutoPilot();

			}

		}
		// check if a NavPoints target has left, delete it if so
		int i;

		for (i = 0; i < MAX_NAVPOINTS; i++)
		{
			if ((Navs[i].flags & NP_SHIP) && (Navs[i].target_obj != NULL))
			{
				if (((ship*)Navs[i].target_obj)->objnum == -1)
				{
					if (CurrentNav == i)
						CurrentNav = -1;
					DelNavPoint(i);
				}
			}
		}
		
		// check if we're reached a Node
		for (i = 0; i < MAX_NAVPOINTS; i++)
		{
			if (Navs[i].target_obj != NULL)
			{
				if (Navs[i].flags & NP_VALIDTYPE && DistanceTo(i) < 1000)
					Navs[i].flags |= NP_VISITED;
			}
		}
	}

	// ramp time compression - only if not using cinematics
	if (AutoPilotEngaged && !(The_mission.flags & MISSION_FLAG_USE_AP_CINEMATICS))
	{
		int dstfrm_start = start_dist - DistanceTo(CurrentNav);

		// Ramp UP time compression
		if (dstfrm_start < (3500*ramp_bias))
		{

			if (dstfrm_start >= (3000*ramp_bias) && DistanceTo(CurrentNav) > 30000)
				set_time_compression(64);
			else if (dstfrm_start >= (2000*ramp_bias))
				set_time_compression(32);
			else if (dstfrm_start >= (1600*ramp_bias))
				set_time_compression(16);
			else if (dstfrm_start >= (1200*ramp_bias))
				set_time_compression(8);
			else if (dstfrm_start >= (800*ramp_bias))
				set_time_compression(4);
			else if (dstfrm_start >= (400*ramp_bias))
				set_time_compression(2);
		}

		// Ramp DOWN time compression
		if (DistanceTo(CurrentNav) <= (7000*ramp_bias))
		{
			int dist = DistanceTo(CurrentNav);
			if (dist >= (5000*ramp_bias))
				set_time_compression(32);
			else if (dist >= (4000*ramp_bias))
				set_time_compression(16);
			else if (dist >= (3000*ramp_bias))
				set_time_compression(8);
			else if (dist >= (2000*ramp_bias))
				set_time_compression(4);
			else if (dist >= (1000*ramp_bias))
				set_time_compression(2);
		}
	}

	/* Link in any ships that need to be linked in when the player gets close
	enough.  Always done by the player because: "making sure the AI fighters 
	are where they're supposed to be at all times is like herding cats" -Woolie Wool
	*/
	for (int i = 0; i < MAX_SHIPS; i++)
	{
		if (Ships[i].objnum != -1 && Ships[i].flags2 & SF2_NAVPOINT_NEEDSLINK)
		{
			object *other_objp = &Objects[Ships[i].objnum];

			if (vm_vec_dist_quick(&Player_obj->pos, &other_objp->pos) < (NavLinkDistance + other_objp->radius))
			{
				Ships[i].flags2 &= ~SF2_NAVPOINT_NEEDSLINK;
				Ships[i].flags2 |= SF2_NAVPOINT_CARRY;
				
				send_autopilot_msgID(NP_MSG_MISC_LINKED);
			}
		
		}
	}
}
Esempio n. 14
0
bool Plane::Contains(const Vector& v) const {
  return (Abs(DistanceTo(v)) < EPSILON);
}
Esempio n. 15
0
unsigned int DistanceTo(char *nav)
{
	int n = FindNav(nav);

	return DistanceTo(n);
}
Esempio n. 16
0
bool Plane::OnFrontSide(const Vector& v) const {
  return (DistanceTo(v) > -EPSILON);
}
Esempio n. 17
0
bool Plane::OnBackSide(const Vector& v) const {
  return (DistanceTo(v) < EPSILON);
}
Esempio n. 18
0
Vector Plane::Reflect(const Vector& v) const {
  return (v - (2.0f * m_Normal * DistanceTo(v)));
}
Esempio n. 19
0
Vec3 Plane::ProjectPoint(const Vec3& p) const
{
	auto d = DistanceTo(p);
	return p - mNormal * p;
}
Esempio n. 20
0
// ********************************************************************************************
// Engages autopilot
// This does:
//        * Control switched from player to AI
//        * Time compression to 32x
//        * Lock time compression -WMC
//        * Tell AI to fly to targeted Nav Point (for all nav-status wings/ships)
//		  * Sets max waypoint speed to the best-speed of the slowest ship tagged
bool StartAutopilot()
{
	// Check for support ship and dismiss it if it is not doing anything.
	// If the support ship is doing something then tell the user such.
	for ( object *objp = GET_FIRST(&obj_used_list); objp !=END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp) )
	{
		if ((objp->type == OBJ_SHIP) && !(objp->flags & OF_SHOULD_BE_DEAD))
		{
			Assertion((objp->instance >= 0) && (objp->instance < MAX_SHIPS),
				"objp does not have a valid pointer to a ship. Pointer is %d, which is smaller than 0 or bigger than %d",
				objp->instance, MAX_SHIPS);
			ship *shipp = &Ships[objp->instance];

			if (shipp->team != Player_ship->team)
				continue;

			Assertion((shipp->ship_info_index >= 0) && (shipp->ship_info_index < MAX_SHIP_CLASSES),
				"Ship '%s' does not have a valid pointer to a ship class. Pointer is %d, which is smaller than 0 or bigger than %d",
				shipp->ship_name, shipp->ship_info_index, MAX_SHIP_CLASSES);
			ship_info *sip = &Ship_info[shipp->ship_info_index];

			if ( !(sip->flags & SIF_SUPPORT) )
				continue;

			// don't deal with dying or departing support ships
			if ( shipp->flags & (SF_DYING | SF_DEPARTING) )
				continue;

			Assert(shipp->ai_index != -1);
			ai_info* support_ship_aip = &(Ai_info[Ships[objp->instance].ai_index]);

			// is support ship trying to rearm-repair
			if ( ai_find_goal_index( support_ship_aip->goals, AI_GOAL_REARM_REPAIR ) == -1 ) {
				// no, so tell it to depart
				ai_add_ship_goal_player( AIG_TYPE_PLAYER_SHIP, AI_GOAL_WARP, -1, NULL, support_ship_aip );
			} else {
				// yes
				send_autopilot_msgID(NP_MSG_FAIL_SUPPORT_WORKING);
				return false;
			}
		}
	}
	if (!CanAutopilot())
		return false;

	AutoPilotEngaged = true;

	// find the ship that is "leading" all of the ships when the player starts
	// autopilot
	// by default the ship that is leading the autopilot session the player's
	// wing leader (if the player is the wing leader then it will be the
	// player).
	// TODO:implement a way to allow a FREDer to say a different ship is leader
	Autopilot_flight_leader = get_wing_leader(Player_ship->wingnum);
	if ( Autopilot_flight_leader == NULL ) {
		// force player to be the leader if he doesn't have a wing
		Autopilot_flight_leader = Player_obj;
	}

	if (The_mission.flags & MISSION_FLAG_USE_AP_CINEMATICS)
		LockAPConv = timestamp(); // lock convergence instantly
	else
		LockAPConv = timestamp(3000); // 3 seconds before we lock convergence
	Player_use_ai = 1;
	set_time_compression(1);
	lock_time_compression(true);

	// determine speed cap
	int i,j, wcount=1, tc_factor=1;
	float speed_cap = 1000000.0; // 1m is a safe starting point
	float radius = Player_obj->radius, distance = 0.0f, ftemp;
	bool capshipPresent = false;
	int capship_counts[3]; // three size classes
	capship_counts[0] = 0;
	capship_counts[1] = 0;
	capship_counts[2] = 0;

	int capship_placed[3]; // three size classes
	capship_placed[0] = 0;
	capship_placed[1] = 0;
	capship_placed[2] = 0;

	float capship_spreads[3];
	capship_spreads[0] = 0.0f;
	capship_spreads[1] = 0.0f;
	capship_spreads[2] = 0.0f;

	SCP_vector<int> capIndexes;

	// empty the autopilot wings map
	autopilot_wings.clear();

	// vars for usage w/ cinematic
	vec3d pos, norm1, perp, tpos, rpos = Player_obj->pos, zero;
	memset(&zero, 0, sizeof(vec3d));


	// instantly turn player toward tpos
	if (The_mission.flags & MISSION_FLAG_USE_AP_CINEMATICS)
	{
		vm_vec_sub(&norm1, Navs[CurrentNav].GetPosition(), &Player_obj->pos);
		vm_vector_2_matrix(&Player_obj->orient, &norm1, NULL, NULL);
	}

	for (i = 0; i < MAX_SHIPS; i++)
	{
		if (Ships[i].objnum != -1 && 
				(Ships[i].flags2 & SF2_NAVPOINT_CARRY || 
					(Ships[i].wingnum != -1 && Wings[Ships[i].wingnum].flags & WF_NAV_CARRY)
				)
			)
		{
			if (speed_cap > vm_vec_mag(&Ship_info[Ships[i].ship_info_index].max_vel))
				speed_cap = vm_vec_mag(&Ship_info[Ships[i].ship_info_index].max_vel);
		}
	}

	// damp speed_cap to 90% of actual -- to make sure ships stay in formation
	if (The_mission.flags & MISSION_FLAG_USE_AP_CINEMATICS)
		speed_cap = 0.90f * speed_cap;

	if ( speed_cap < 1.0f ) {
		/* We need to deal with this so that incorrectly flagged ships will not
		cause the engine to fail to limit all the ships speeds correctly. */
		Warning(LOCATION, "Ship speed cap is way too small (%f)!\n"
			"This is normally caused by a ship that has nav-carry-status set, but cannot move itself (like a Cargo container).\n"
			"Speed cap has been set to 1.0 m/s.",
			speed_cap);
		speed_cap = 1.0f;
	}

	ramp_bias = speed_cap/50.0f;

	// assign ship goals
	// when assigning goals to individual ships only do so if Ships[shipnum].wingnum != -1 
	// we will assign wing goals below

	for (i = 0; i < MAX_SHIPS; i++)
	{
		if (Ships[i].objnum != -1 && 
				(Ships[i].flags2 & SF2_NAVPOINT_CARRY || 
					(Ships[i].wingnum != -1 && Wings[Ships[i].wingnum].flags & WF_NAV_CARRY)
				)
			)
		{
			// do we have capital ships in the area?
			if (Ship_info[Ships[i].ship_info_index].flags 
				& ( SIF_CRUISER | SIF_CAPITAL | SIF_SUPERCAP | SIF_CORVETTE | SIF_AWACS | SIF_GAS_MINER | SIF_FREIGHTER | SIF_TRANSPORT))
			{
				capshipPresent = true;

				capIndexes.push_back(i);
				// ok.. what size class

				if (Ship_info[Ships[i].ship_info_index].flags & (SIF_CAPITAL | SIF_SUPERCAP))
				{
					capship_counts[0]++;
					if (capship_spreads[0] < Objects[Ships[i].objnum].radius)
						capship_spreads[0] = Objects[Ships[i].objnum].radius;
				}
				else if (Ship_info[Ships[i].ship_info_index].flags & (SIF_CORVETTE))
				{
					capship_counts[1]++;
					if (capship_spreads[1] < Objects[Ships[i].objnum].radius)
						capship_spreads[1] = Objects[Ships[i].objnum].radius;
				}
				else
				{
					capship_counts[2]++;
					if (capship_spreads[2] < Objects[Ships[i].objnum].radius)
						capship_spreads[2] = Objects[Ships[i].objnum].radius;
				}
			}



			// check for bigger radius for usage later
			/*if (!vm_vec_cmp(&rpos, &Player_obj->pos)) 
				// want to make sure rpos isn't player pos - we can worry about it being largest object's later
			{
				rpos = Objects[Ships[i].objnum].pos;
			}*/

			if (Objects[Ships[i].objnum].radius > radius)
			{
				rpos = Objects[Ships[i].objnum].pos;
				radius = Objects[Ships[i].objnum].radius;
			}

			if (The_mission.flags & MISSION_FLAG_USE_AP_CINEMATICS)
			{// instantly turn the ship to match the direction player is looking
				//vm_vec_sub(&norm1, Navs[CurrentNav].GetPosition(), &Player_obj->pos);
				vm_vector_2_matrix(&Objects[Ships[i].objnum].orient, &norm1, NULL, NULL);
			}

			// snap wings into formation
			if (The_mission.flags & MISSION_FLAG_USE_AP_CINEMATICS &&  // only if using cinematics 
				(Ships[i].wingnum != -1 && Wings[Ships[i].wingnum].flags & WF_NAV_CARRY) // only if in a wing
				&& Autopilot_flight_leader != &Objects[Ships[i].objnum]) //only if not flight leader's object
			{	
				ai_info	*aip = &Ai_info[Ships[i].ai_index];
				int wingnum = aip->wing, wing_index = get_wing_index(&Objects[Ships[i].objnum], wingnum);
				vec3d goal_point;
				object *leader_objp = get_wing_leader(wingnum);
				
				if (leader_objp != &Objects[Ships[i].objnum])
				{
					// not leader.. get our position relative to leader
					get_absolute_wing_pos_autopilot(&goal_point, leader_objp, wing_index, aip->ai_flags & AIF_FORMATION_OBJECT);
				}
				else
				{
					ai_clear_wing_goals(wingnum);
					j = 1+int( (float)floor(double(wcount-1)/2.0) );
					switch (wcount % 2)
					{
						case 1: // back-left
							vm_vec_add(&perp, &zero, &Autopilot_flight_leader->orient.vec.rvec);
							//vm_vec_sub(&perp, &perp, &Player_obj->orient.vec.fvec);
							vm_vec_normalize(&perp);
							vm_vec_scale(&perp, -166.0f*j); // 166m is supposedly the optimal range according to tolwyn
							vm_vec_add(&goal_point, &Autopilot_flight_leader->pos, &perp);
							break;

						default: //back-right
						case 0:
							vm_vec_add(&perp, &zero, &Autopilot_flight_leader->orient.vec.rvec);
							//vm_vec_sub(&perp, &perp, &Player_obj->orient.vec.fvec);
							vm_vec_normalize(&perp);
							vm_vec_scale(&perp, 166.0f*j);
							vm_vec_add(&goal_point, &Autopilot_flight_leader->pos, &perp);
							break;
					}
					autopilot_wings[wingnum] = wcount;
					wcount++;
				}
				Objects[Ships[i].objnum].pos = goal_point;			
				if (vm_vec_dist_quick(&Autopilot_flight_leader->pos, &Objects[Ships[i].objnum].pos) > distance)
				{
					distance = vm_vec_dist_quick(&Autopilot_flight_leader->pos, &Objects[Ships[i].objnum].pos);
				}
			}
			// lock primary and secondary weapons
			if ( LockWeaponsDuringAutopilot )
				Ships[i].flags2 |= (SF2_PRIMARIES_LOCKED | SF2_SECONDARIES_LOCKED);

			// clear the ship goals and cap the waypoint speed
			ai_clear_ship_goals(&Ai_info[Ships[i].ai_index]);
			Ai_info[Ships[i].ai_index].waypoint_speed_cap = (int)speed_cap;

			
			// if they're not part of a wing set their goal
			if (Ships[i].wingnum == -1 || The_mission.flags & MISSION_FLAG_USE_AP_CINEMATICS)
			{ 
				if (Navs[CurrentNav].flags & NP_WAYPOINT)
				{
					ai_add_ship_goal_player( AIG_TYPE_PLAYER_SHIP, AI_GOAL_WAYPOINTS_ONCE, 0, ((waypoint_list*)Navs[CurrentNav].target_obj)->get_name(), &Ai_info[Ships[i].ai_index] );
					//fixup has to wait until after wing goals
				}
				else
				{
					ai_add_ship_goal_player( AIG_TYPE_PLAYER_SHIP, AI_GOAL_FLY_TO_SHIP, 0, ((ship*)Navs[CurrentNav].target_obj)->ship_name, &Ai_info[Ships[i].ai_index] );
				}

			}
		}
	}

	// assign wing goals
	if (!(The_mission.flags & MISSION_FLAG_USE_AP_CINEMATICS))
	{
		for (i = 0; i < MAX_WINGS; i++)
		{
			if (Wings[i].flags & WF_NAV_CARRY )
			{	
				//ai_add_ship_goal_player( int type, int mode, int submode, char *shipname, ai_info *aip );

				//ai_add_wing_goal_player( AIG_TYPE_PLAYER_WING, AI_GOAL_STAY_NEAR_SHIP, 0, target_shipname, wingnum );
				//ai_add_wing_goal_player( AIG_TYPE_PLAYER_WING, AI_GOAL_WAYPOINTS_ONCE, 0, target_shipname, wingnum );
				//ai_clear_ship_goals( &(Ai_info[Ships[num].ai_index]) );
				
				ai_clear_wing_goals( i );
				if (Navs[CurrentNav].flags & NP_WAYPOINT)
				{
					
					ai_add_wing_goal_player( AIG_TYPE_PLAYER_WING, AI_GOAL_WAYPOINTS_ONCE, 0, ((waypoint_list*)Navs[CurrentNav].target_obj)->get_name(), i );

					// "fix up" the goal
					for (j = 0; j < MAX_AI_GOALS; j++)
					{
						if (Wings[i].ai_goals[j].ai_mode == AI_GOAL_WAYPOINTS_ONCE ||
							Wings[i].ai_goals[j].ai_mode == AIM_WAYPOINTS )
						{
							autopilot_ai_waypoint_goal_fixup(&(Wings[i].ai_goals[j]));
						}
					}
				}
				else
				{
					ai_add_wing_goal_player( AIG_TYPE_PLAYER_WING, AI_GOAL_FLY_TO_SHIP, 0, ((ship*)Navs[CurrentNav].target_obj)->ship_name, i );

				}
			}
		}
	}

	// fixup has to go down here because ships are assigned goals during wing goals as well
	for (i = 0; i < MAX_SHIPS; i++)
	{
		if (Ships[i].objnum != -1)
		{
			if (Ships[i].flags2 & SF2_NAVPOINT_CARRY || 
				(Ships[i].wingnum != -1 && Wings[Ships[i].wingnum].flags & WF_NAV_CARRY))
				for (j = 0; j < MAX_AI_GOALS; j++)
				{
					if (Ai_info[Ships[i].ai_index].goals[j].ai_mode == AI_GOAL_WAYPOINTS_ONCE ||
						Ai_info[Ships[i].ai_index].goals[j].ai_mode == AIM_WAYPOINTS)
					{
						autopilot_ai_waypoint_goal_fixup( &(Ai_info[Ships[i].ai_index].goals[j]) );

						
						// formation fixup
						//ai_form_on_wing(&Objects[Ships[i].objnum], &Objects[Player_ship->objnum]);
					}
				}
		}
	}
	start_dist = DistanceTo(CurrentNav);

	// ----------------------------- setup cinematic -----------------------------
	if (The_mission.flags & MISSION_FLAG_USE_AP_CINEMATICS)
	{	
		if (capshipPresent)
		{
			// position capships

			vec3d right, front, up, offset;
			for (SCP_vector<int>::iterator idx = capIndexes.begin(); idx != capIndexes.end(); ++idx)
			{
				vm_vec_add(&right, &Autopilot_flight_leader->orient.vec.rvec, &zero);
				vm_vec_add(&front, &Autopilot_flight_leader->orient.vec.fvec, &zero);
				vm_vec_add(&up, &Autopilot_flight_leader->orient.vec.uvec, &zero);
				vm_vec_add(&offset, &zero, &zero);
				if (Ship_info[Ships[*idx].ship_info_index].flags & (SIF_CAPITAL | SIF_SUPERCAP))
				{
					//0 - below - three lines of position

					// front/back to zero
					vm_vec_add(&front, &zero, &zero);

					// position below
					vm_vec_scale(&up, capship_spreads[0]); // scale the up vector by the radius of the largest ship in this formation part


					switch (capship_placed[0] % 3)
					{
						case 1: // right
							vm_vec_scale(&right, capship_spreads[0]);
							break;
							
						case 2: // left
							vm_vec_scale(&right, -capship_spreads[0]);
							break;

						default: // straight
						case 0:
							vm_vec_add(&right, &zero, &zero);
							vm_vec_scale(&up, 1.5); // add an extra half-radius
							break;
					}
		
					// scale by  row
					vm_vec_scale(&right, (1+((float)floor((float)capship_placed[0]/3)))); 
					vm_vec_scale(&up, -(1+((float)floor((float)capship_placed[0]/3))));

					capship_placed[0]++;
				}
				else if (Ship_info[Ships[*idx].ship_info_index].flags & SIF_CORVETTE)
				{
					//1 above - 3 lines of position
					// front/back to zero
					vm_vec_add(&front, &zero, &zero);

					// position below
					vm_vec_scale(&up, capship_spreads[1]); // scale the up vector by the radius of the largest ship in this formation part


					switch (capship_placed[1] % 3)
					{
						case 1: // right
							vm_vec_scale(&right, capship_spreads[1]); 
							break;
							
						case 2: // left
							vm_vec_scale(&right, -capship_spreads[1]); 
							break;

						default: // straight
						case 0:
							vm_vec_add(&right, &zero, &zero);
							vm_vec_scale(&up, 1.5); // add an extra half-radius
							break;
					}
		
					// scale by  row
					vm_vec_scale(&right, (1+((float)floor((float)capship_placed[1]/3)))); 
					vm_vec_scale(&up, (1+((float)floor((float)capship_placed[1]/3))));

					// move ourselves up and out of the way of the smaller ships
					vm_vec_add(&perp, &Autopilot_flight_leader->orient.vec.uvec, &zero);
					vm_vec_scale(&perp, capship_spreads[2]);
					vm_vec_add(&up, &up, &perp);

					capship_placed[1]++;
				}
				else
				{
					//2 either side - 6 lines of position (right (dir, front, back), left (dir, front, back) )
					// placing pattern: right, left, front right, front left, rear right, rear left

					// up/down to zero
					vm_vec_add(&up, &zero, &zero);


					switch (capship_placed[2] % 6)
					{
						case 5:  // rear left
							vm_vec_scale(&right, -capship_spreads[2]);
							vm_vec_scale(&front, -capship_spreads[2]); 
							break;

						case 4:  // rear right
							vm_vec_scale(&right, capship_spreads[2]); 
							vm_vec_scale(&front, -capship_spreads[2]); 
							break;

						case 3:  // front left
							vm_vec_scale(&right, -capship_spreads[2]); 
							vm_vec_scale(&front, capship_spreads[2]); 
							break;

						case 2:  // front right
							vm_vec_scale(&right, capship_spreads[2]); 
							vm_vec_scale(&front, capship_spreads[2]);
							break;

						case 1:  // straight left
							vm_vec_scale(&right, 1.5);
							vm_vec_scale(&right, -capship_spreads[2]);
							vm_vec_add(&front, &zero, &zero);
							break;

						default: // straight right
						case 0:
							vm_vec_scale(&right, 1.5);
							vm_vec_scale(&right, capship_spreads[2]);
							vm_vec_add(&front, &zero, &zero);
							break;
					}
					// these ships seem to pack a little too tightly
					vm_vec_scale(&right, 2*(1+((float)floor((float)capship_placed[2]/3)))); 
					vm_vec_scale(&front, 2*(1+((float)floor((float)capship_placed[2]/3))));

					// move "out" by 166*(wcount-1) so we don't bump into fighters
					vm_vec_add(&perp, &Autopilot_flight_leader->orient.vec.rvec, &zero);
					vm_vec_scale(&perp, 166.0f*float(wcount-1));
					if ( (capship_placed[2] % 2) == 0)
						vm_vec_add(&right, &right, &perp);
					else
						vm_vec_sub(&right, &right, &perp);

					capship_placed[2]++;
				}

				// integrate the up/down componant
				vm_vec_add(&offset, &offset, &up);

				//integrate the left/right componant
				vm_vec_add(&offset, &offset, &right);

				//integrate the left/right componant
				vm_vec_add(&offset, &offset, &front);

				// global scale the position by 50%
				//vm_vec_scale(&offset, 1.5);

				vm_vec_add(&Objects[Ships[*idx].objnum].pos, &Autopilot_flight_leader->pos, &offset);

				if (vm_vec_dist_quick(&Autopilot_flight_leader->pos, &Objects[Ships[*idx].objnum].pos) > distance)
				{
					distance = vm_vec_dist_quick(&Autopilot_flight_leader->pos, &Objects[Ships[*idx].objnum].pos);
				}
			}
		}

		ftemp = floor(Autopilot_flight_leader->phys_info.max_vel.xyz.z/speed_cap);
		if (ftemp >= 2.0f && ftemp < 4.0f)
			tc_factor = 2;
		else if (ftemp >= 4.0f && ftemp < 8.0f)
			tc_factor = 4;
		else if (ftemp >= 8.0f)
			tc_factor = 8;



		tpos = *Navs[CurrentNav].GetPosition();
		// determine distance toward nav at which camera will be
		vm_vec_sub(&pos, &tpos, &Autopilot_flight_leader->pos);
		vm_vec_normalize(&pos); // pos is now a unit vector in the direction we will be moving the camera
		//norm1 = pos;
		vm_vec_scale(&pos, 5*speed_cap*tc_factor); // pos is now scaled by 5 times the speed (5 seconds ahead)
		vm_vec_add(&pos, &pos, &Autopilot_flight_leader->pos); // pos is now 5*speed cap in front of player ship

		switch (myrand()%24) 
		// 8 different ways of getting perp points
		// 4 of which will not be used when capships are present (anything below, or straight above)
		{

			case 1: // down
			case 9:
			case 16:
				if (capship_placed[0] == 0)
					vm_vec_sub(&perp, &zero, &Autopilot_flight_leader->orient.vec.uvec);
				else
				{	// become up-left
					vm_vec_add(&perp, &zero, &Autopilot_flight_leader->orient.vec.uvec);
					vm_vec_sub(&perp, &perp, &Autopilot_flight_leader->orient.vec.rvec);
				}
				break;

			case 2: // up
			case 10:
			case 23:
				vm_vec_add(&perp, &perp, &Autopilot_flight_leader->orient.vec.uvec);
				if (capshipPresent) // become up-right
					vm_vec_add(&perp, &perp, &Autopilot_flight_leader->orient.vec.rvec);
				break;

			case 3: // left
			case 11:
			case 22:
				vm_vec_sub(&perp, &zero, &Autopilot_flight_leader->orient.vec.rvec);
				break;

			case 4: // up-left
			case 12:
			case 21:
				vm_vec_sub(&perp, &zero, &Autopilot_flight_leader->orient.vec.rvec);
				vm_vec_add(&perp, &perp, &Autopilot_flight_leader->orient.vec.uvec);
				break;

			case 5: // up-right
			case 13:
			case 20:
				vm_vec_add(&perp, &zero, &Autopilot_flight_leader->orient.vec.rvec);
				vm_vec_add(&perp, &perp, &Autopilot_flight_leader->orient.vec.uvec);
				break;

			case 6: // down-left
			case 14:
			case 19:
				vm_vec_sub(&perp, &zero, &Autopilot_flight_leader->orient.vec.rvec);
				if (capship_placed[0] < 2)
					vm_vec_sub(&perp, &perp, &Autopilot_flight_leader->orient.vec.uvec);
				else
					vm_vec_add(&perp, &perp, &Autopilot_flight_leader->orient.vec.uvec);
				break;

			case 7: // down-right
			case 15:
			case 18:
				vm_vec_add(&perp, &zero, &Autopilot_flight_leader->orient.vec.rvec);
				if (capship_placed[0] < 1)
					vm_vec_sub(&perp, &perp, &Autopilot_flight_leader->orient.vec.uvec);
				else
					vm_vec_add(&perp, &perp, &Autopilot_flight_leader->orient.vec.uvec);
				break;

			default:
			case 0: // right
			case 8:
			case 17:
				perp = Autopilot_flight_leader->orient.vec.rvec;
				break;

		}
		vm_vec_normalize(&perp);
		//vm_vec_scale(&perp, 2*radius+distance);

		vm_vec_scale(&perp,  Autopilot_flight_leader->radius+radius);

		// randomly scale up/down by up to 20%
		j = 20-myrand()%40; // [-20,20]

		vm_vec_scale(&perp, 1.0f+(float(j)/100.0f));
		vm_vec_add(&cameraPos, &pos, &perp);

		if (capshipPresent)
		{
			vm_vec_normalize(&perp);

			// place it behind
			//vm_vec_copy_scale(&norm1, &Player_obj->orient.vec.fvec, -2*(Player_obj->radius+radius*(1.0f+(float(j)/100.0f))));
			//vm_vec_add(&cameraTarget, &cameraTarget, &norm1);

			vm_vec_copy_scale(&cameraTarget,&perp, radius/5.0f);

			//vm_vec_scale(&cameraTarget, Player_obj->radius+radius*(1.0f+(float(j)/100.0f)));

			//vm_vec_add(&cameraTarget, &pos, &cameraTarget);
			//CameraSpeed = (radius+distance)/25;

			//vm_vec_add(&cameraTarget, &zero, &perp);
			//vm_vec_scale(&CameraVelocity, (radius+distance/100.f));
			//vm_vec_scale(&CameraVelocity, 1.0f/float(NPS_TICKRATE*tc_factor));
		}
		else
		{
			vm_vec_add(&cameraTarget, &zero, &zero);
			//CameraSpeed = 0;
		}
		//CameraMoving = false;


		EndAPCinematic = timestamp((10000*tc_factor)+NPS_TICKRATE); // 10 objective seconds before end of cinematic 
		MoveCamera = timestamp((5500*tc_factor)+NPS_TICKRATE);
		camMovingTime = int(4.5*float(tc_factor));
		set_time_compression((float)tc_factor);
	}

	return true;
}
qboolean
Pet_FindTarget(edict_t * self)
{
	edict_t * enemy = 0;
	edict_t * PetOwner = self->monsterinfo.PetOwner;
	int radius = 500;
//	int bCammed = false;

	// follow mode means ignore combat
	if (self->monsterinfo.PetState & PET_FOLLOW)
	{
		self->enemy = 0;
		self->goalentity = PetOwner;
		return true;
	}

// optional bonus for a pet actively being cammed
//	if (PetOwner->client->petcam == self)
//	{
//		bCammed = true;
//		radius = 1000;
//	}

	// help master if appropriate
	if (!(self->monsterinfo.PetState & PET_FREETARGET)
		&& PetOwner->enemy)
	{
		vec3_t dir;
		double distance;
		VectorSubtract(self->s.origin,PetOwner->s.origin, dir);
		distance = VectorLength(dir);
		if ( distance < 400)
			enemy = PetOwner->enemy;
	}

	if (!enemy)
		enemy = FindEnemy(self, radius);

	if (enemy)
	{
		self->enemy = enemy;
		FoundTarget (self);

		if (!(self->monsterinfo.aiflags & AI_SOUND_TARGET) && (self->monsterinfo.sight))
			self->monsterinfo.sight (self, self->enemy);
		return true;
	}

	// no enemy, what about following owner ?
	self->enemy = 0; // 2000/05/27
	self->goalentity = 0;
	if (!(self->monsterinfo.PetState & PET_FREE)
			&& visible(self, PetOwner))
	{
		if (DistanceTo(self, PetOwner) > 100)
		{
			self->goalentity = PetOwner;
			self->monsterinfo.pausetime = level.time;
		}
		else
		{
			self->monsterinfo.stand (self);
			self->monsterinfo.pausetime = level.time + 30;
		}
	}
	return false;
}
Esempio n. 22
0
/*
================
rvMonsterStroggHover::Think
================
*/
void rvMonsterStroggHover::Think ( void ) {
	idAI::Think ( );
	
	if ( !aifl.dead )
	{
		// If thinking we should play an effect on the ground under us
		if ( !fl.hidden && !fl.isDormant && (thinkFlags & TH_THINK ) && !aifl.dead ) {
			trace_t tr;
			idVec3	origin;
			idMat3	axis;
			
			// Project the effect 80 units down from the bottom of our bbox
			GetJointWorldTransform ( jointDust, gameLocal.time, origin, axis );
			
	// RAVEN BEGIN
	// ddynerman: multiple clip worlds
			gameLocal.TracePoint ( this, tr, origin, origin + axis[0] * (GetPhysics()->GetBounds()[0][2]+80.0f), CONTENTS_SOLID, this );
	// RAVEN END

			// Start the dust effect if not already started
			if ( !effectDust ) {
				effectDust = gameLocal.PlayEffect ( gameLocal.GetEffect ( spawnArgs, "fx_dust" ), tr.endpos, tr.c.normal.ToMat3(), true );
			}
			
			// If the effect is playing we should update its attenuation as well as its origin and axis
			if ( effectDust ) {
				effectDust->Attenuate ( 1.0f - idMath::ClampFloat ( 0.0f, 1.0f, (tr.endpos - origin).LengthFast ( ) / 127.0f ) );
				effectDust->SetOrigin ( tr.endpos );
				effectDust->SetAxis ( tr.c.normal.ToMat3() );
			}
			
			// If the hover effect is playing we can set its end origin to the ground
			/*
			if ( effectHover ) {
				effectHover->SetEndOrigin ( tr.endpos );
			}
			*/
		} else if ( effectDust ) {
			effectDust->Stop ( );
			effectDust = NULL;
		}

		//Try to circle strafe or pursue
		if ( circleStrafing )
		{
			CircleStrafe();
		}
		else if ( !inPursuit )
		{
			if ( !aifl.action && move.fl.done && !aifl.scripted )
			{
				if ( GetEnemy() )
				{
					if ( DistanceTo( GetEnemy() ) > 2000.0f 
						|| (GetEnemy()->GetPhysics()->GetLinearVelocity()*(GetEnemy()->GetPhysics()->GetOrigin()-GetPhysics()->GetOrigin())) > 1000.0f )
					{//enemy is far away or moving away from us at a pretty decent speed
						TryStartPursuit();
					}
				}
			}
		}
		else
		{
			Pursue();
		}

		//Dodge
		if ( !circleStrafing ) {
			if( combat.shotAtTime && gameLocal.GetTime() - combat.shotAtTime < 1000.0f ) {
				if ( nextBombFireTime < gameLocal.GetTime() - 3000 ) {
					if ( gameLocal.random.RandomFloat() > evadeChance ) {
						//40% chance of ignoring it - makes them dodge rockets less often but bullets more often?
						combat.shotAtTime = 0;
					} else if ( evadeDebounce < gameLocal.GetTime() ) {
						//ramps down from 400 to 100 over 1 second
						float speed = evadeSpeed - ((((float)(gameLocal.GetTime()-combat.shotAtTime))/1000.0f)*(evadeSpeed-(evadeSpeed*0.25f)));
						idVec3 evadeVel = viewAxis[1] * ((combat.shotAtAngle >= 0)?-1:1) * speed;
						evadeVel.z *= 0.5f;
						move.addVelocity += evadeVel;
						move.addVelocity.Normalize();
						move.addVelocity *= speed;
						/*
						if ( move.moveCommand < NUM_NONMOVING_COMMANDS ) {
							//just need to do it once?
							combat.shotAtTime = 0;
						}
						*/
						if ( evadeDebounceRate > 1 )
						{
							evadeDebounce = gameLocal.GetTime() + gameLocal.random.RandomInt( evadeDebounceRate ) + (ceil(((float)evadeDebounceRate)/2.0f));
						}
					}
				}
			}
		}

		//If using melee rush to nav to him, stop when we're close enough to attack
		if ( combat.tacticalCurrent == AITACTICAL_MELEE 
			&& move.moveCommand == MOVE_TO_ENEMY
			&& !move.fl.done
			&& nextBombFireTime < gameLocal.GetTime() - 3000
			&& enemy.fl.visible && DistanceTo( GetEnemy() ) < 2000.0f ) {
			StopMove( MOVE_STATUS_DONE );
			ForceTacticalUpdate();
		} else {
			//whenever we're not in the middle of something, force an update of our tactical
			if ( !aifl.action ) {
				if ( !aasFind ) {
					if ( move.fl.done ) {
						if ( !inPursuit && !circleStrafing ) {
							ForceTacticalUpdate();
						}
					}
				}
			}
		}
	}

	//update light
//	if ( lightOn ) {
		UpdateLightDef ( );
//	}
}
Esempio n. 23
0
// The only difference between ProjectPoint and
// ProjectVector is the addition of m_Distance...
Vector Plane::ProjectPoint(const Vector& v) const {
  return (v - (m_Normal * DistanceTo(v)));
}
Esempio n. 24
0
 /* virtual methods from class ObservationZone */
 virtual bool IsInSector(const GeoPoint &location) const override {
   return DistanceTo(location) <= radius;
 }