Steer
StarshipAI::SeekTarget()
{
	if (navpt) {
		SimRegion*     self_rgn = ship->GetRegion();
		SimRegion*     nav_rgn  = navpt->Region();
		QuantumDrive*  qdrive   = ship->GetQuantumDrive();

		if (self_rgn && !nav_rgn) {
			nav_rgn = self_rgn;
			navpt->SetRegion(nav_rgn);
		}

		bool use_farcaster      = self_rgn != nav_rgn && 
		(navpt->Farcast() || 
		!qdrive ||
		!qdrive->IsPowerOn() ||
		qdrive->Status() < System::DEGRADED
		);

		if (use_farcaster) {
			if (!farcaster) {
				ListIter<Ship> s = self_rgn->Ships();
				while (++s && !farcaster) {
					if (s->GetFarcaster()) {
						const Ship* dest = s->GetFarcaster()->GetDest();
						if (dest && dest->GetRegion() == nav_rgn) {
							farcaster = s->GetFarcaster();
						}
					}
				}
			}

			if (farcaster) {
				if (farcaster->GetShip()->GetRegion() != self_rgn)
				farcaster = farcaster->GetDest()->GetFarcaster();

				obj_w = farcaster->EndPoint();
				distance = Point(obj_w - ship->Location()).length();

				if (distance < 1000)
				farcaster = 0;
			}
		}
		else if (self_rgn != nav_rgn) {
			QuantumDrive* q = ship->GetQuantumDrive();

			if (q) {
				if (q->ActiveState() == QuantumDrive::ACTIVE_READY) {
					q->SetDestination(navpt->Region(), navpt->Location());
					q->Engage();
				}
			}
		}
	}

	return ShipAI::SeekTarget();
}
Esempio n. 2
0
void
NavAI::FindObjective()
{
	navpt    = 0;
	distance = 0;

	// runway takeoff:
	if (takeoff) {
		obj_w   = ship->Location()   + ship->Heading() * 10e3;
		obj_w.y = ship->Location().y + 2e3;

		// transform into camera coords:
		objective = Transform(obj_w);
		ship->SetDirectorInfo(Game::GetText("ai.takeoff"));
		return;
	}

	// PART I: Find next NavPoint:
	if (ship->GetNavSystem())
	navpt = ship->GetNextNavPoint();

	complete = !navpt;
	if (complete) return;

	// PART II: Compute Objective from NavPoint:
	Point       npt = navpt->Location();
	Sim*        sim = Sim::GetSim();
	SimRegion*  self_rgn = ship->GetRegion();
	SimRegion*  nav_rgn = navpt->Region();

	if (self_rgn && !nav_rgn) {
		nav_rgn = self_rgn;
		navpt->SetRegion(nav_rgn);
	}

	if (self_rgn == nav_rgn) {
		if (farcaster) {
			if (farcaster->GetShip()->GetRegion() != self_rgn)
			farcaster = farcaster->GetDest()->GetFarcaster();

			obj_w = farcaster->EndPoint();
		}

		else {
			obj_w = npt.OtherHand();
		}

		// distance from self to navpt:
		distance = Point(obj_w - self->Location()).length();

		// transform into camera coords:
		objective = Transform(obj_w);

		if (!ship->IsStarship())
		objective.Normalize();

		if (farcaster && distance < 1000)
		farcaster = 0;
	}

	// PART III: Deal with orbital transitions:
	else if (ship->IsDropship()) {
		if (nav_rgn->GetOrbitalRegion()->Primary() ==
				self_rgn->GetOrbitalRegion()->Primary()) {

			Point npt = nav_rgn->Location() - self_rgn->Location();
			obj_w = npt.OtherHand();

			// distance from self to navpt:
			distance = Point(obj_w - ship->Location()).length();

			// transform into camera coords:
			objective = Transform(obj_w);

			if (nav_rgn->IsAirSpace()) {
				drop_state = -1;
			}
			else if (nav_rgn->IsOrbital()) {
				drop_state = 1;
			}
		}

		// PART IIIa: Deal with farcaster jumps:
		else if (nav_rgn->IsOrbital() && self_rgn->IsOrbital()) {
			ListIter<Ship> s = self_rgn->Ships();
			while (++s && !farcaster) {
				if (s->GetFarcaster()) {
					const Ship* dest = s->GetFarcaster()->GetDest();
					if (dest && dest->GetRegion() == nav_rgn) {
						farcaster = s->GetFarcaster();
					}
				}
			}

			if (farcaster) {
				Point apt   = farcaster->ApproachPoint(0);
				Point npt   = farcaster->StartPoint();
				double r1   = (ship->Location() - npt).length();

				if (r1 > 50e3) {
					obj_w     = apt;
					distance  = r1;
					objective = Transform(obj_w);
				}

				else {
					double r2 = (ship->Location() - apt).length();
					double r3 = (npt - apt).length();

					if (r1+r2 < 1.2*r3) {
						obj_w     = npt;
						distance  = r1;
						objective = Transform(obj_w);
					}
					else {
						obj_w     = apt;
						distance  = r2;
						objective = Transform(obj_w);
					}
				}
			}
		}
	}

	// PART IV: Deal with quantum jumps:
	else if (ship->IsStarship()) {
		quantum_state = 1;

		Point npt = nav_rgn->Location() + navpt->Location();
		npt -= self_rgn->Location();
		obj_w = npt.OtherHand();

		// distance from self to navpt:
		distance = Point(obj_w - ship->Location()).length();

		// transform into camera coords:
		objective = Transform(obj_w);
	}
}