diff options
Diffstat (limited to 'Stars45/ShipAI.cpp')
-rw-r--r-- | Stars45/ShipAI.cpp | 1970 |
1 files changed, 985 insertions, 985 deletions
diff --git a/Stars45/ShipAI.cpp b/Stars45/ShipAI.cpp index 1118a8a..b06d20a 100644 --- a/Stars45/ShipAI.cpp +++ b/Stars45/ShipAI.cpp @@ -1,15 +1,15 @@ /* Project Starshatter 5.0
- Destroyer Studios LLC
- Copyright © 1997-2007. All Rights Reserved.
+ Destroyer Studios LLC
+ Copyright © 1997-2007. All Rights Reserved.
- SUBSYSTEM: Stars.exe
- FILE: ShipAI.cpp
- AUTHOR: John DiCamillo
+ SUBSYSTEM: Stars.exe
+ FILE: ShipAI.cpp
+ AUTHOR: John DiCamillo
- OVERVIEW
- ========
- Starship (low-level) Artificial Intelligence class
+ OVERVIEW
+ ========
+ Starship (low-level) Artificial Intelligence class
*/
#include "MemDebug.h"
@@ -42,37 +42,37 @@ // +----------------------------------------------------------------------+
ShipAI::ShipAI(SimObject* s)
- : SteerAI(s),
- support(0), rumor(0), threat(0), threat_missile(0), drop_time(0),
- too_close(0), navpt(0), patrol(0), engaged_ship_id(0),
- bracket(false), identify(false), hold(false), takeoff(false),
- throttle(0), old_throttle(0), element_index(1), splash_count(0),
- tactical(0), farcaster(0), ai_level(2), last_avoid_time(0),
- last_call_time(0)
+: SteerAI(s),
+support(0), rumor(0), threat(0), threat_missile(0), drop_time(0),
+too_close(0), navpt(0), patrol(0), engaged_ship_id(0),
+bracket(false), identify(false), hold(false), takeoff(false),
+throttle(0), old_throttle(0), element_index(1), splash_count(0),
+tactical(0), farcaster(0), ai_level(2), last_avoid_time(0),
+last_call_time(0)
{
- ship = (Ship*) self;
-
- Sim* sim = Sim::GetSim();
- Ship* pship = sim->GetPlayerShip();
- int player_team = 1;
-
- if (pship)
- player_team = pship->GetIFF();
-
- Player* player = Player::GetCurrentPlayer();
- if (player) {
- if (ship && ship->GetIFF() && ship->GetIFF() != player_team) {
- ai_level = player->AILevel();
- }
- else if (player->AILevel() == 0) {
- ai_level = 1;
- }
- }
-
- // evil alien ships are *always* smart:
- if (ship && ship->GetIFF() > 1 && ship->Design()->auto_roll > 1) {
- ai_level = 2;
- }
+ ship = (Ship*) self;
+
+ Sim* sim = Sim::GetSim();
+ Ship* pship = sim->GetPlayerShip();
+ int player_team = 1;
+
+ if (pship)
+ player_team = pship->GetIFF();
+
+ Player* player = Player::GetCurrentPlayer();
+ if (player) {
+ if (ship && ship->GetIFF() && ship->GetIFF() != player_team) {
+ ai_level = player->AILevel();
+ }
+ else if (player->AILevel() == 0) {
+ ai_level = 1;
+ }
+ }
+
+ // evil alien ships are *always* smart:
+ if (ship && ship->GetIFF() > 1 && ship->Design()->auto_roll > 1) {
+ ai_level = 2;
+ }
}
@@ -80,14 +80,14 @@ ShipAI::ShipAI(SimObject* s) ShipAI::~ShipAI()
{
- delete tactical;
+ delete tactical;
}
void
ShipAI::ClearTactical()
{
- delete tactical;
- tactical = 0;
+ delete tactical;
+ tactical = 0;
}
// +--------------------------------------------------------------------+
@@ -95,116 +95,116 @@ ShipAI::ClearTactical() Ship*
ShipAI::GetWard() const
{
- return ship->GetWard();
+ return ship->GetWard();
}
void
ShipAI::SetWard(Ship* s)
{
- if (s == ship->GetWard())
- return;
-
- ship->SetWard(s);
-
- Point form = RandomDirection();
- form.SwapYZ();
-
- if (fabs(form.x) < 0.5) {
- if (form.x < 0)
- form.x = -0.5;
- else
- form.x = 0.5;
- }
-
- if (ship && ship->IsStarship()) {
- form *= 30e3;
- }
- else {
- form *= 15e3;
- form.y = 500;
- }
-
- SetFormationDelta(form);
+ if (s == ship->GetWard())
+ return;
+
+ ship->SetWard(s);
+
+ Point form = RandomDirection();
+ form.SwapYZ();
+
+ if (fabs(form.x) < 0.5) {
+ if (form.x < 0)
+ form.x = -0.5;
+ else
+ form.x = 0.5;
+ }
+
+ if (ship && ship->IsStarship()) {
+ form *= 30e3;
+ }
+ else {
+ form *= 15e3;
+ form.y = 500;
+ }
+
+ SetFormationDelta(form);
}
void
ShipAI::SetSupport(Ship* s)
{
- if (support == s)
- return;
+ if (support == s)
+ return;
- support = s;
+ support = s;
- if (support)
- Observe(support);
+ if (support)
+ Observe(support);
}
void
ShipAI::SetRumor(Ship* s)
{
- if (!s || rumor == s)
- return;
+ if (!s || rumor == s)
+ return;
- rumor = s;
+ rumor = s;
- if (rumor)
- Observe(rumor);
+ if (rumor)
+ Observe(rumor);
}
void
ShipAI::ClearRumor()
{
- rumor = 0;
+ rumor = 0;
}
void
ShipAI::SetThreat(Ship* s)
{
- if (threat == s)
- return;
+ if (threat == s)
+ return;
- threat = s;
+ threat = s;
- if (threat)
- Observe(threat);
+ if (threat)
+ Observe(threat);
}
void
ShipAI::SetThreatMissile(Shot* s)
{
- if (threat_missile == s)
- return;
+ if (threat_missile == s)
+ return;
- threat_missile = s;
+ threat_missile = s;
- if (threat_missile)
- Observe(threat_missile);
+ if (threat_missile)
+ Observe(threat_missile);
}
bool
ShipAI::Update(SimObject* obj)
{
- if (obj == support)
- support = 0;
+ if (obj == support)
+ support = 0;
- if (obj == threat)
- threat = 0;
+ if (obj == threat)
+ threat = 0;
- if (obj == threat_missile)
- threat_missile = 0;
+ if (obj == threat_missile)
+ threat_missile = 0;
- if (obj == rumor)
- rumor = 0;
+ if (obj == rumor)
+ rumor = 0;
- return SteerAI::Update(obj);
+ return SteerAI::Update(obj);
}
const char*
ShipAI::GetObserverName() const
{
- static char name[64];
- sprintf(name, "ShipAI(%s)", self->Name());
- return name;
+ static char name[64];
+ sprintf(name, "ShipAI(%s)", self->Name());
+ return name;
}
// +--------------------------------------------------------------------+
@@ -212,20 +212,20 @@ ShipAI::GetObserverName() const Point
ShipAI::GetPatrol() const
{
- return patrol_loc;
+ return patrol_loc;
}
void
ShipAI::SetPatrol(const Point& p)
{
- patrol = 1;
- patrol_loc = p;
+ patrol = 1;
+ patrol_loc = p;
}
void
ShipAI::ClearPatrol()
{
- patrol = 0;
+ patrol = 0;
}
// +--------------------------------------------------------------------+
@@ -233,90 +233,90 @@ ShipAI::ClearPatrol() void
ShipAI::ExecFrame(double secs)
{
- seconds = secs;
+ seconds = secs;
- if (drop_time > 0) drop_time -= seconds;
- if (!ship) return;
+ if (drop_time > 0) drop_time -= seconds;
+ if (!ship) return;
- ship->SetDirectorInfo(" ");
+ ship->SetDirectorInfo(" ");
- // check to make sure current navpt is still valid:
- if (navpt)
- navpt = ship->GetNextNavPoint();
+ // check to make sure current navpt is still valid:
+ if (navpt)
+ navpt = ship->GetNextNavPoint();
- if (ship->GetFlightPhase() == Ship::TAKEOFF || ship->GetFlightPhase() == Ship::LAUNCH)
- takeoff = true;
+ if (ship->GetFlightPhase() == Ship::TAKEOFF || ship->GetFlightPhase() == Ship::LAUNCH)
+ takeoff = true;
- if (takeoff) {
- FindObjective();
- Navigator();
+ if (takeoff) {
+ FindObjective();
+ Navigator();
- if (ship->MissionClock() > 10000)
- takeoff = false;
+ if (ship->MissionClock() > 10000)
+ takeoff = false;
- return;
- }
+ return;
+ }
- // initial assessment:
- if (ship->MissionClock() < 5000)
- return;
+ // initial assessment:
+ if (ship->MissionClock() < 5000)
+ return;
- element_index = ship->GetElementIndex();
+ element_index = ship->GetElementIndex();
- NavlightControl();
- CheckTarget();
+ NavlightControl();
+ CheckTarget();
- if (tactical)
- tactical->ExecFrame(seconds);
+ if (tactical)
+ tactical->ExecFrame(seconds);
- if (target && target != ship->GetTarget()) {
- ship->LockTarget(target);
+ if (target && target != ship->GetTarget()) {
+ ship->LockTarget(target);
- // if able to lock target, and target is a ship (not a shot)...
- if (target == ship->GetTarget() && target->Type() == SimObject::SIM_SHIP) {
+ // if able to lock target, and target is a ship (not a shot)...
+ if (target == ship->GetTarget() && target->Type() == SimObject::SIM_SHIP) {
- // if this isn't the same ship we last called out:
- if (target->Identity() != engaged_ship_id && Game::GameTime() - last_call_time > 10000) {
- // call engaging:
- RadioMessage* msg = new(__FILE__,__LINE__) RadioMessage(ship->GetElement(), ship, RadioMessage::CALL_ENGAGING);
- msg->AddTarget(target);
- RadioTraffic::Transmit(msg);
- last_call_time = Game::GameTime();
+ // if this isn't the same ship we last called out:
+ if (target->Identity() != engaged_ship_id && Game::GameTime() - last_call_time > 10000) {
+ // call engaging:
+ RadioMessage* msg = new(__FILE__,__LINE__) RadioMessage(ship->GetElement(), ship, RadioMessage::CALL_ENGAGING);
+ msg->AddTarget(target);
+ RadioTraffic::Transmit(msg);
+ last_call_time = Game::GameTime();
- engaged_ship_id = target->Identity();
- }
- }
- }
+ engaged_ship_id = target->Identity();
+ }
+ }
+ }
- else if (!target) {
- target = ship->GetTarget();
+ else if (!target) {
+ target = ship->GetTarget();
- if (engaged_ship_id && !target) {
- engaged_ship_id = 0;
+ if (engaged_ship_id && !target) {
+ engaged_ship_id = 0;
- /***
- *** XXX
- *** Not the right place to make this decision.
- ***
- *** There is a brief wait between killing a target and
- *** selecting a new one, so this message is sent after
- *** every kill.
- ***
- *** Need to track when the entire element has been
- *** put down.
+ /***
+ *** XXX
+ *** Not the right place to make this decision.
+ ***
+ *** There is a brief wait between killing a target and
+ *** selecting a new one, so this message is sent after
+ *** every kill.
+ ***
+ *** Need to track when the entire element has been
+ *** put down.
- if (element_index == 1) {
- RadioMessage* msg = new(__FILE__,__LINE__) RadioMessage(ship->GetElement(), ship, RadioMessage::RESUME_MISSION);
- RadioTraffic::Transmit(msg);
- }
+ if (element_index == 1) {
+ RadioMessage* msg = new(__FILE__,__LINE__) RadioMessage(ship->GetElement(), ship, RadioMessage::RESUME_MISSION);
+ RadioTraffic::Transmit(msg);
+ }
- ***
- ***/
- }
- }
+ ***
+ ***/
+ }
+ }
- FindObjective();
- Navigator();
+ FindObjective();
+ Navigator();
}
// +--------------------------------------------------------------------+
@@ -324,32 +324,32 @@ ShipAI::ExecFrame(double secs) Point
ShipAI::ClosingVelocity()
{
- if (ship && target) {
- if (ship->GetPrimaryDesign()) {
- WeaponDesign* guns = ship->GetPrimaryDesign();
- Point delta = target->Location() - ship->Location();
-
- // fighters need to aim the ship so that the guns will hit the target
- if (guns->firing_cone < 10*DEGREES && guns->max_range <= delta.length()) {
- Point aim_vec = ship->Heading();
- aim_vec.Normalize();
-
- Point shot_vel = ship->Velocity() + aim_vec * guns->speed;
- return shot_vel - target->Velocity();
- }
-
- // ships with turreted weapons just need to worry about actual closing speed
- else {
- return ship->Velocity() - target->Velocity();
- }
- }
-
- else {
- return ship->Velocity();
- }
- }
-
- return Point(1,0,0);
+ if (ship && target) {
+ if (ship->GetPrimaryDesign()) {
+ WeaponDesign* guns = ship->GetPrimaryDesign();
+ Point delta = target->Location() - ship->Location();
+
+ // fighters need to aim the ship so that the guns will hit the target
+ if (guns->firing_cone < 10*DEGREES && guns->max_range <= delta.length()) {
+ Point aim_vec = ship->Heading();
+ aim_vec.Normalize();
+
+ Point shot_vel = ship->Velocity() + aim_vec * guns->speed;
+ return shot_vel - target->Velocity();
+ }
+
+ // ships with turreted weapons just need to worry about actual closing speed
+ else {
+ return ship->Velocity() - target->Velocity();
+ }
+ }
+
+ else {
+ return ship->Velocity();
+ }
+ }
+
+ return Point(1,0,0);
}
// +--------------------------------------------------------------------+
@@ -357,109 +357,109 @@ ShipAI::ClosingVelocity() void
ShipAI::FindObjective()
{
- distance = 0;
-
- int order = ship->GetRadioOrders()->Action();
-
- if (order == RadioMessage::QUANTUM_TO ||
- order == RadioMessage::FARCAST_TO) {
-
- FindObjectiveQuantum();
- objective = Transform(obj_w);
- return;
- }
-
- bool form = (order == RadioMessage::WEP_HOLD) ||
- (order == RadioMessage::FORM_UP) ||
- (order == RadioMessage::MOVE_PATROL) ||
- (order == RadioMessage::RTB) ||
- (order == RadioMessage::DOCK_WITH) ||
- (!order && !target) ||
- (farcaster);
-
- Ship* ward = ship->GetWard();
-
- // if not the element leader, stay in formation:
- if (form && element_index > 1) {
- ship->SetDirectorInfo(Game::GetText("ai.formation"));
-
- if (navpt && navpt->Action() == Instruction::LAUNCH) {
- FindObjectiveNavPoint();
- }
- else {
- navpt = 0;
- FindObjectiveFormation();
- }
-
- // transform into camera coords:
- objective = Transform(obj_w);
- return;
- }
-
- // under orders?
- bool directed = false;
- if (tactical)
- directed = (tactical->RulesOfEngagement() == TacticalAI::DIRECTED);
-
- // threat processing:
- if (threat && !directed) {
- double d_threat = Point(threat->Location() - ship->Location()).length();
-
- // seek support:
- if (support) {
- double d_support = Point(support->Location() - ship->Location()).length();
- if (d_support > 35e3) {
- ship->SetDirectorInfo(Game::GetText("ai.regroup"));
- FindObjectiveTarget(support);
- objective = Transform(obj_w);
- return;
- }
- }
-
- // run away:
- else if (threat != target) {
- ship->SetDirectorInfo(Game::GetText("ai.retreat"));
- obj_w = ship->Location() + Point(ship->Location() - threat->Location()) * 100;
- objective = Transform(obj_w);
- return;
- }
- }
-
- // normal processing:
- if (target) {
- ship->SetDirectorInfo(Game::GetText("ai.seek-target"));
- FindObjectiveTarget(target);
- objective = AimTransform(obj_w);
- }
-
- else if (patrol) {
- ship->SetDirectorInfo(Game::GetText("ai.patrol"));
- FindObjectivePatrol();
- objective = Transform(obj_w);
- }
-
- else if (ward) {
- ship->SetDirectorInfo(Game::GetText("ai.seek-ward"));
- FindObjectiveFormation();
- objective = Transform(obj_w);
- }
-
- else if (navpt && form) {
- ship->SetDirectorInfo(Game::GetText("ai.seek-navpt"));
- FindObjectiveNavPoint();
- objective = Transform(obj_w);
- }
-
- else if (rumor) {
- ship->SetDirectorInfo(Game::GetText("ai.search"));
- FindObjectiveTarget(rumor);
- objective = Transform(obj_w);
- }
-
- else {
- obj_w = Point();
- objective = Point();
- }
+ distance = 0;
+
+ int order = ship->GetRadioOrders()->Action();
+
+ if (order == RadioMessage::QUANTUM_TO ||
+ order == RadioMessage::FARCAST_TO) {
+
+ FindObjectiveQuantum();
+ objective = Transform(obj_w);
+ return;
+ }
+
+ bool form = (order == RadioMessage::WEP_HOLD) ||
+ (order == RadioMessage::FORM_UP) ||
+ (order == RadioMessage::MOVE_PATROL) ||
+ (order == RadioMessage::RTB) ||
+ (order == RadioMessage::DOCK_WITH) ||
+ (!order && !target) ||
+ (farcaster);
+
+ Ship* ward = ship->GetWard();
+
+ // if not the element leader, stay in formation:
+ if (form && element_index > 1) {
+ ship->SetDirectorInfo(Game::GetText("ai.formation"));
+
+ if (navpt && navpt->Action() == Instruction::LAUNCH) {
+ FindObjectiveNavPoint();
+ }
+ else {
+ navpt = 0;
+ FindObjectiveFormation();
+ }
+
+ // transform into camera coords:
+ objective = Transform(obj_w);
+ return;
+ }
+
+ // under orders?
+ bool directed = false;
+ if (tactical)
+ directed = (tactical->RulesOfEngagement() == TacticalAI::DIRECTED);
+
+ // threat processing:
+ if (threat && !directed) {
+ double d_threat = Point(threat->Location() - ship->Location()).length();
+
+ // seek support:
+ if (support) {
+ double d_support = Point(support->Location() - ship->Location()).length();
+ if (d_support > 35e3) {
+ ship->SetDirectorInfo(Game::GetText("ai.regroup"));
+ FindObjectiveTarget(support);
+ objective = Transform(obj_w);
+ return;
+ }
+ }
+
+ // run away:
+ else if (threat != target) {
+ ship->SetDirectorInfo(Game::GetText("ai.retreat"));
+ obj_w = ship->Location() + Point(ship->Location() - threat->Location()) * 100;
+ objective = Transform(obj_w);
+ return;
+ }
+ }
+
+ // normal processing:
+ if (target) {
+ ship->SetDirectorInfo(Game::GetText("ai.seek-target"));
+ FindObjectiveTarget(target);
+ objective = AimTransform(obj_w);
+ }
+
+ else if (patrol) {
+ ship->SetDirectorInfo(Game::GetText("ai.patrol"));
+ FindObjectivePatrol();
+ objective = Transform(obj_w);
+ }
+
+ else if (ward) {
+ ship->SetDirectorInfo(Game::GetText("ai.seek-ward"));
+ FindObjectiveFormation();
+ objective = Transform(obj_w);
+ }
+
+ else if (navpt && form) {
+ ship->SetDirectorInfo(Game::GetText("ai.seek-navpt"));
+ FindObjectiveNavPoint();
+ objective = Transform(obj_w);
+ }
+
+ else if (rumor) {
+ ship->SetDirectorInfo(Game::GetText("ai.search"));
+ FindObjectiveTarget(rumor);
+ objective = Transform(obj_w);
+ }
+
+ else {
+ obj_w = Point();
+ objective = Point();
+ }
}
// +--------------------------------------------------------------------+
@@ -467,71 +467,71 @@ ShipAI::FindObjective() void
ShipAI::FindObjectiveTarget(SimObject* tgt)
{
- if (!tgt) {
- obj_w = Point();
- return;
- }
-
- navpt = 0; // this tells fire control that we are chasing a target,
- // instead of a navpoint!
-
- Point cv = ClosingVelocity();
- double cvl = cv.length();
- double time = 0;
-
- if (cvl > 50) {
- // distance from self to target:
- distance = Point(tgt->Location() - self->Location()).length();
-
- // time to reach target:
- time = distance / cvl;
-
- // where the target will be when we reach it:
- if (time < 15) {
- Point run_vec = tgt->Velocity();
- obj_w = tgt->Location() + (run_vec * time);
-
-
- if (time < 10)
- obj_w += (tgt->Acceleration() * 0.33 * time * time);
- }
- else {
- obj_w = tgt->Location();
- }
- }
-
- else {
- obj_w = tgt->Location();
- }
-
- distance = Point(obj_w - self->Location()).length();
-
- if (cvl > 50) {
- time = distance / cvl;
-
- // where we will be when the target gets there:
- if (time < 15) {
- Point self_dest = self->Location() + cv * time;
- Point err = obj_w - self_dest;
-
- obj_w += err;
- }
- }
-
- Point approach = obj_w - self->Location();
- distance = approach.length();
-
- if (bracket && distance > 25e3) {
- Point offset = approach.cross(Point(0,1,0));
- offset.Normalize();
- offset *= 15e3;
-
- Ship* s = (Ship*) self;
- if (s->GetElementIndex() & 1)
- obj_w -= offset;
- else
- obj_w += offset;
- }
+ if (!tgt) {
+ obj_w = Point();
+ return;
+ }
+
+ navpt = 0; // this tells fire control that we are chasing a target,
+ // instead of a navpoint!
+
+ Point cv = ClosingVelocity();
+ double cvl = cv.length();
+ double time = 0;
+
+ if (cvl > 50) {
+ // distance from self to target:
+ distance = Point(tgt->Location() - self->Location()).length();
+
+ // time to reach target:
+ time = distance / cvl;
+
+ // where the target will be when we reach it:
+ if (time < 15) {
+ Point run_vec = tgt->Velocity();
+ obj_w = tgt->Location() + (run_vec * time);
+
+
+ if (time < 10)
+ obj_w += (tgt->Acceleration() * 0.33 * time * time);
+ }
+ else {
+ obj_w = tgt->Location();
+ }
+ }
+
+ else {
+ obj_w = tgt->Location();
+ }
+
+ distance = Point(obj_w - self->Location()).length();
+
+ if (cvl > 50) {
+ time = distance / cvl;
+
+ // where we will be when the target gets there:
+ if (time < 15) {
+ Point self_dest = self->Location() + cv * time;
+ Point err = obj_w - self_dest;
+
+ obj_w += err;
+ }
+ }
+
+ Point approach = obj_w - self->Location();
+ distance = approach.length();
+
+ if (bracket && distance > 25e3) {
+ Point offset = approach.cross(Point(0,1,0));
+ offset.Normalize();
+ offset *= 15e3;
+
+ Ship* s = (Ship*) self;
+ if (s->GetElementIndex() & 1)
+ obj_w -= offset;
+ else
+ obj_w += offset;
+ }
}
// +--------------------------------------------------------------------+
@@ -539,18 +539,18 @@ ShipAI::FindObjectiveTarget(SimObject* tgt) void
ShipAI::FindObjectivePatrol()
{
- navpt = 0;
+ navpt = 0;
- Point npt = patrol_loc;
- obj_w = npt;
+ Point npt = patrol_loc;
+ obj_w = npt;
- // distance from self to navpt:
- distance = Point(obj_w - self->Location()).length();
+ // distance from self to navpt:
+ distance = Point(obj_w - self->Location()).length();
- if (distance < 1000) {
- ship->ClearRadioOrders();
- ClearPatrol();
- }
+ if (distance < 1000) {
+ ship->ClearRadioOrders();
+ ClearPatrol();
+ }
}
// +--------------------------------------------------------------------+
@@ -558,60 +558,60 @@ ShipAI::FindObjectivePatrol() void
ShipAI::FindObjectiveNavPoint()
{
- SimRegion* self_rgn = ship->GetRegion();
- SimRegion* nav_rgn = navpt->Region();
- QuantumDrive* qdrive = ship->GetQuantumDrive();
+ SimRegion* self_rgn = ship->GetRegion();
+ SimRegion* nav_rgn = navpt->Region();
+ QuantumDrive* qdrive = ship->GetQuantumDrive();
- if (!self_rgn)
- return;
+ if (!self_rgn)
+ return;
- if (!nav_rgn) {
- nav_rgn = self_rgn;
- navpt->SetRegion(nav_rgn);
- }
+ if (!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
- );
+ bool use_farcaster = self_rgn != nav_rgn &&
+ (navpt->Farcast() ||
+ !qdrive ||
+ !qdrive->IsPowerOn() ||
+ qdrive->Status() < System::DEGRADED
+ );
- if (use_farcaster) {
- FindObjectiveFarcaster(self_rgn, nav_rgn);
- }
+ if (use_farcaster) {
+ FindObjectiveFarcaster(self_rgn, nav_rgn);
+ }
- else {
- if (farcaster) {
- if (farcaster->GetShip()->GetRegion() != self_rgn)
- farcaster = farcaster->GetDest()->GetFarcaster();
+ else {
+ if (farcaster) {
+ if (farcaster->GetShip()->GetRegion() != self_rgn)
+ farcaster = farcaster->GetDest()->GetFarcaster();
- obj_w = farcaster->EndPoint();
- }
+ obj_w = farcaster->EndPoint();
+ }
- else {
- // transform from starsystem to world coordinates:
- Point npt = navpt->Region()->Location() + navpt->Location();
+ else {
+ // transform from starsystem to world coordinates:
+ Point npt = navpt->Region()->Location() + navpt->Location();
- SimRegion* active_region = ship->GetRegion();
+ SimRegion* active_region = ship->GetRegion();
- if (active_region)
- npt -= active_region->Location();
+ if (active_region)
+ npt -= active_region->Location();
- npt = npt.OtherHand();
+ npt = npt.OtherHand();
- obj_w = npt;
- }
+ obj_w = npt;
+ }
- // distance from self to navpt:
- distance = Point(obj_w - ship->Location()).length();
+ // distance from self to navpt:
+ distance = Point(obj_w - ship->Location()).length();
- if (farcaster && distance < 1000)
- farcaster = 0;
+ if (farcaster && distance < 1000)
+ farcaster = 0;
- if (distance < 1000 || (navpt->Action() == Instruction::LAUNCH && distance > 25000))
- ship->SetNavptStatus(navpt, Instruction::COMPLETE);
- }
+ if (distance < 1000 || (navpt->Action() == Instruction::LAUNCH && distance > 25000))
+ ship->SetNavptStatus(navpt, Instruction::COMPLETE);
+ }
}
// +--------------------------------------------------------------------+
@@ -619,109 +619,109 @@ ShipAI::FindObjectiveNavPoint() void
ShipAI::FindObjectiveQuantum()
{
- Instruction* orders = ship->GetRadioOrders();
- SimRegion* self_rgn = ship->GetRegion();
- SimRegion* nav_rgn = orders->Region();
- QuantumDrive* qdrive = ship->GetQuantumDrive();
-
- if (!self_rgn || !nav_rgn)
- return;
-
- bool use_farcaster = self_rgn != nav_rgn &&
- (orders->Farcast() ||
- !qdrive ||
- !qdrive->IsPowerOn() ||
- qdrive->Status() < System::DEGRADED
- );
-
- if (use_farcaster) {
- FindObjectiveFarcaster(self_rgn, nav_rgn);
- }
-
- else {
- if (farcaster) {
- if (farcaster->GetShip()->GetRegion() != self_rgn)
- farcaster = farcaster->GetDest()->GetFarcaster();
-
- obj_w = farcaster->EndPoint();
- }
-
- else {
- // transform from starsystem to world coordinates:
- Point npt = orders->Region()->Location() + orders->Location();
-
- SimRegion* active_region = ship->GetRegion();
-
- if (active_region)
- npt -= active_region->Location();
-
- npt = npt.OtherHand();
-
- obj_w = npt;
-
- if (qdrive && qdrive->ActiveState() == QuantumDrive::ACTIVE_READY) {
- qdrive->SetDestination(nav_rgn, orders->Location());
- qdrive->Engage();
- return;
- }
- }
-
- // distance from self to navpt:
- distance = Point(obj_w - ship->Location()).length();
-
- if (farcaster) {
- if (distance < 1000) {
- farcaster = 0;
- ship->ClearRadioOrders();
- }
- }
- else if (self_rgn == nav_rgn) {
- ship->ClearRadioOrders();
- }
- }
+ Instruction* orders = ship->GetRadioOrders();
+ SimRegion* self_rgn = ship->GetRegion();
+ SimRegion* nav_rgn = orders->Region();
+ QuantumDrive* qdrive = ship->GetQuantumDrive();
+
+ if (!self_rgn || !nav_rgn)
+ return;
+
+ bool use_farcaster = self_rgn != nav_rgn &&
+ (orders->Farcast() ||
+ !qdrive ||
+ !qdrive->IsPowerOn() ||
+ qdrive->Status() < System::DEGRADED
+ );
+
+ if (use_farcaster) {
+ FindObjectiveFarcaster(self_rgn, nav_rgn);
+ }
+
+ else {
+ if (farcaster) {
+ if (farcaster->GetShip()->GetRegion() != self_rgn)
+ farcaster = farcaster->GetDest()->GetFarcaster();
+
+ obj_w = farcaster->EndPoint();
+ }
+
+ else {
+ // transform from starsystem to world coordinates:
+ Point npt = orders->Region()->Location() + orders->Location();
+
+ SimRegion* active_region = ship->GetRegion();
+
+ if (active_region)
+ npt -= active_region->Location();
+
+ npt = npt.OtherHand();
+
+ obj_w = npt;
+
+ if (qdrive && qdrive->ActiveState() == QuantumDrive::ACTIVE_READY) {
+ qdrive->SetDestination(nav_rgn, orders->Location());
+ qdrive->Engage();
+ return;
+ }
+ }
+
+ // distance from self to navpt:
+ distance = Point(obj_w - ship->Location()).length();
+
+ if (farcaster) {
+ if (distance < 1000) {
+ farcaster = 0;
+ ship->ClearRadioOrders();
+ }
+ }
+ else if (self_rgn == nav_rgn) {
+ ship->ClearRadioOrders();
+ }
+ }
}
void
ShipAI::FindObjectiveFarcaster(SimRegion* src_rgn, SimRegion* dst_rgn)
{
- if (!farcaster) {
- ListIter<Ship> s = src_rgn->Ships();
- while (++s && !farcaster) {
- if (s->GetFarcaster()) {
- const Ship* dest = s->GetFarcaster()->GetDest();
- if (dest && dest->GetRegion() == dst_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;
- }
-
- else {
- double r2 = (ship->Location() - apt).length();
- double r3 = (npt - apt).length();
-
- if (r1+r2 < 1.2*r3) {
- obj_w = npt;
- distance = r1;
- }
- else {
- obj_w = apt;
- distance = r2;
- }
- }
-
- objective = Transform(obj_w);
- }
+ if (!farcaster) {
+ ListIter<Ship> s = src_rgn->Ships();
+ while (++s && !farcaster) {
+ if (s->GetFarcaster()) {
+ const Ship* dest = s->GetFarcaster()->GetDest();
+ if (dest && dest->GetRegion() == dst_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;
+ }
+
+ else {
+ double r2 = (ship->Location() - apt).length();
+ double r3 = (npt - apt).length();
+
+ if (r1+r2 < 1.2*r3) {
+ obj_w = npt;
+ distance = r1;
+ }
+ else {
+ obj_w = apt;
+ distance = r2;
+ }
+ }
+
+ objective = Transform(obj_w);
+ }
}
// +--------------------------------------------------------------------+
@@ -729,101 +729,101 @@ ShipAI::FindObjectiveFarcaster(SimRegion* src_rgn, SimRegion* dst_rgn) void
ShipAI::SetFormationDelta(const Point& point)
{
- formation_delta = point;
+ formation_delta = point;
}
void
ShipAI::FindObjectiveFormation()
{
- const double prediction = 5;
-
- // find the base position:
- Element* elem = ship->GetElement();
- Ship* lead = elem->GetShip(1);
- Ship* ward = ship->GetWard();
-
- if (!lead || lead == ship) {
- lead = ward;
-
- distance = (lead->Location() - self->Location()).length();
- if (distance < 30e3 && lead->Velocity().length() < 50) {
- obj_w = self->Location() + lead->Heading() * 1e6;
- distance = -1;
- return;
- }
- }
-
- obj_w = lead->Location() + lead->Velocity() * prediction;
- Matrix m; m.Rotate(0, 0, lead->CompassHeading() - PI);
- Point fd = formation_delta * m;
- obj_w += fd;
-
- // try to avoid smacking into the ground...
- if (ship->IsAirborne()) {
- if (ship->AltitudeAGL() < 3000 || lead->AltitudeAGL() < 3000) {
- obj_w.y += 500;
- }
- }
-
- Point dst_w = self->Location() + self->Velocity() * prediction;
- Point dlt_w = obj_w - dst_w;
-
- distance = dlt_w.length();
-
- // get slot z distance:
- dlt_w += ship->Location();
- slot_dist = Transform(dlt_w).z;
-
- Director* lead_dir = lead->GetDirector();
- if (lead_dir && (lead_dir->Type() == FIGHTER || lead_dir->Type() == STARSHIP)) {
- ShipAI* lead_ai = (ShipAI*) lead_dir;
- farcaster = lead_ai->GetFarcaster();
- }
- else {
- Instruction* navpt = elem->GetNextNavPoint();
- if (!navpt) {
- farcaster = 0;
- return;
- }
-
- 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) {
- 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();
- }
- }
- }
- }
- else 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;
- }
- }
+ const double prediction = 5;
+
+ // find the base position:
+ Element* elem = ship->GetElement();
+ Ship* lead = elem->GetShip(1);
+ Ship* ward = ship->GetWard();
+
+ if (!lead || lead == ship) {
+ lead = ward;
+
+ distance = (lead->Location() - self->Location()).length();
+ if (distance < 30e3 && lead->Velocity().length() < 50) {
+ obj_w = self->Location() + lead->Heading() * 1e6;
+ distance = -1;
+ return;
+ }
+ }
+
+ obj_w = lead->Location() + lead->Velocity() * prediction;
+ Matrix m; m.Rotate(0, 0, lead->CompassHeading() - PI);
+ Point fd = formation_delta * m;
+ obj_w += fd;
+
+ // try to avoid smacking into the ground...
+ if (ship->IsAirborne()) {
+ if (ship->AltitudeAGL() < 3000 || lead->AltitudeAGL() < 3000) {
+ obj_w.y += 500;
+ }
+ }
+
+ Point dst_w = self->Location() + self->Velocity() * prediction;
+ Point dlt_w = obj_w - dst_w;
+
+ distance = dlt_w.length();
+
+ // get slot z distance:
+ dlt_w += ship->Location();
+ slot_dist = Transform(dlt_w).z;
+
+ Director* lead_dir = lead->GetDirector();
+ if (lead_dir && (lead_dir->Type() == FIGHTER || lead_dir->Type() == STARSHIP)) {
+ ShipAI* lead_ai = (ShipAI*) lead_dir;
+ farcaster = lead_ai->GetFarcaster();
+ }
+ else {
+ Instruction* navpt = elem->GetNextNavPoint();
+ if (!navpt) {
+ farcaster = 0;
+ return;
+ }
+
+ 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) {
+ 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();
+ }
+ }
+ }
+ }
+ else 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;
+ }
+ }
}
// +--------------------------------------------------------------------+
@@ -831,12 +831,12 @@ ShipAI::FindObjectiveFormation() void
ShipAI::Splash(const Ship* targ)
{
- if (splash_count > 6)
- splash_count = 4;
+ if (splash_count > 6)
+ splash_count = 4;
- // call splash:
- RadioTraffic::SendQuickMessage(ship, RadioMessage::SPLASH_1 + splash_count);
- splash_count++;
+ // call splash:
+ RadioTraffic::SendQuickMessage(ship, RadioMessage::SPLASH_1 + splash_count);
+ splash_count++;
}
// +--------------------------------------------------------------------+
@@ -844,34 +844,34 @@ ShipAI::Splash(const Ship* targ) void
ShipAI::SetTarget(SimObject* targ, System* sub)
{
- if (targ != target) {
- bracket = false;
- }
+ if (targ != target) {
+ bracket = false;
+ }
- SteerAI::SetTarget(targ, sub);
+ SteerAI::SetTarget(targ, sub);
}
void
ShipAI::DropTarget(double dtime)
{
- SetTarget(0);
- drop_time = dtime; // seconds until we can re-acquire
+ SetTarget(0);
+ drop_time = dtime; // seconds until we can re-acquire
- ship->DropTarget();
+ ship->DropTarget();
}
void
ShipAI::SetBracket(bool b)
{
- bracket = b;
- identify = false;
+ bracket = b;
+ identify = false;
}
void
ShipAI::SetIdentify(bool i)
{
- identify = i;
- bracket = false;
+ identify = i;
+ bracket = false;
}
// +--------------------------------------------------------------------+
@@ -879,33 +879,33 @@ ShipAI::SetIdentify(bool i) void
ShipAI::Navigator()
{
- accumulator.Clear();
- magnitude = 0;
+ accumulator.Clear();
+ magnitude = 0;
- hold = false;
- if ((ship->GetElement() && ship->GetElement()->GetHoldTime() > 0) ||
- (navpt && navpt->Status() == Instruction::COMPLETE && navpt->HoldTime() > 0))
- hold = true;
+ hold = false;
+ if ((ship->GetElement() && ship->GetElement()->GetHoldTime() > 0) ||
+ (navpt && navpt->Status() == Instruction::COMPLETE && navpt->HoldTime() > 0))
+ hold = true;
- ship->SetFLCSMode(Ship::FLCS_HELM);
+ ship->SetFLCSMode(Ship::FLCS_HELM);
- if (target)
- ship->SetDirectorInfo(Game::GetText("ai.seek-target"));
- else if (rumor)
- ship->SetDirectorInfo(Game::GetText("ai.seek-rumor"));
- else
- ship->SetDirectorInfo(Game::GetText("ai.none"));
+ if (target)
+ ship->SetDirectorInfo(Game::GetText("ai.seek-target"));
+ else if (rumor)
+ ship->SetDirectorInfo(Game::GetText("ai.seek-rumor"));
+ else
+ ship->SetDirectorInfo(Game::GetText("ai.none"));
- Accumulate(AvoidCollision());
- Accumulate(AvoidTerrain());
+ Accumulate(AvoidCollision());
+ Accumulate(AvoidTerrain());
- if (!hold)
- Accumulate(SeekTarget());
+ if (!hold)
+ Accumulate(SeekTarget());
- HelmControl();
- ThrottleControl();
- FireControl();
- AdjustDefenses();
+ HelmControl();
+ ThrottleControl();
+ FireControl();
+ AdjustDefenses();
}
// +--------------------------------------------------------------------+
@@ -913,89 +913,89 @@ ShipAI::Navigator() void
ShipAI::HelmControl()
{
- double trans_x = 0;
- double trans_y = 0;
- double trans_z = 0;
+ double trans_x = 0;
+ double trans_y = 0;
+ double trans_z = 0;
- ship->SetHelmHeading(accumulator.yaw);
+ ship->SetHelmHeading(accumulator.yaw);
- if (fabs(accumulator.pitch) < 5*DEGREES || fabs(accumulator.pitch) > 45*DEGREES) {
- trans_z = objective.y;
- ship->SetHelmPitch(0);
- }
+ if (fabs(accumulator.pitch) < 5*DEGREES || fabs(accumulator.pitch) > 45*DEGREES) {
+ trans_z = objective.y;
+ ship->SetHelmPitch(0);
+ }
- else {
- ship->SetHelmPitch(accumulator.pitch);
- }
+ else {
+ ship->SetHelmPitch(accumulator.pitch);
+ }
- ship->SetTransX(trans_x);
- ship->SetTransY(trans_y);
- ship->SetTransZ(trans_z);
+ ship->SetTransX(trans_x);
+ ship->SetTransY(trans_y);
+ ship->SetTransZ(trans_z);
- ship->ExecFLCSFrame();
+ ship->ExecFLCSFrame();
}
/*****************************************
- **
- ** NOTE:
- ** No one is really using this method.
- ** It is overridden by both StarshipAI
- ** and FighterAI.
- **
- *****************************************/
+**
+** NOTE:
+** No one is really using this method.
+** It is overridden by both StarshipAI
+** and FighterAI.
+**
+*****************************************/
void
ShipAI::ThrottleControl()
{
- if (navpt && !threat && !target) { // lead only, get speed from navpt
- double speed = navpt->Speed();
-
- if (speed > 0)
- throttle = speed / ship->VelocityLimit() * 100;
- else
- throttle = 50;
- }
-
- else if (patrol && !threat && !target) { // lead only, get speed from navpt
- double speed = 200;
-
- if (distance > 5000)
- speed = 500;
-
- if (ship->Velocity().length() > speed)
- throttle = 0;
- else
- throttle = 50;
- }
-
- else {
- if (threat || target || element_index < 2) { // element lead
- throttle = 100;
-
- if (!threat && !target)
- throttle = 50;
-
- if (accumulator.brake > 0) {
- throttle *= (1 - accumulator.brake);
- }
- }
-
- else { // wingman
- Ship* lead = ship->GetElement()->GetShip(1);
- double lv = lead->Velocity().length();
- double sv = ship->Velocity().length();
- double dv = lv-sv;
- double dt = 0;
-
- if (dv > 0) dt = dv * 1e-2 * seconds;
- else if (dv < 0) dt = dv * 1e-2 * seconds;
-
- throttle = old_throttle + dt;
- }
- }
-
- old_throttle = throttle;
- ship->SetThrottle((int) throttle);
+ if (navpt && !threat && !target) { // lead only, get speed from navpt
+ double speed = navpt->Speed();
+
+ if (speed > 0)
+ throttle = speed / ship->VelocityLimit() * 100;
+ else
+ throttle = 50;
+ }
+
+ else if (patrol && !threat && !target) { // lead only, get speed from navpt
+ double speed = 200;
+
+ if (distance > 5000)
+ speed = 500;
+
+ if (ship->Velocity().length() > speed)
+ throttle = 0;
+ else
+ throttle = 50;
+ }
+
+ else {
+ if (threat || target || element_index < 2) { // element lead
+ throttle = 100;
+
+ if (!threat && !target)
+ throttle = 50;
+
+ if (accumulator.brake > 0) {
+ throttle *= (1 - accumulator.brake);
+ }
+ }
+
+ else { // wingman
+ Ship* lead = ship->GetElement()->GetShip(1);
+ double lv = lead->Velocity().length();
+ double sv = ship->Velocity().length();
+ double dv = lv-sv;
+ double dt = 0;
+
+ if (dv > 0) dt = dv * 1e-2 * seconds;
+ else if (dv < 0) dt = dv * 1e-2 * seconds;
+
+ throttle = old_throttle + dt;
+ }
+ }
+
+ old_throttle = throttle;
+ ship->SetThrottle((int) throttle);
}
// +--------------------------------------------------------------------+
@@ -1003,21 +1003,21 @@ ShipAI::ThrottleControl() void
ShipAI::NavlightControl()
{
- Ship* leader = ship->GetLeader();
+ Ship* leader = ship->GetLeader();
- if (leader && leader != ship) {
- bool navlight_enabled = false;
+ if (leader && leader != ship) {
+ bool navlight_enabled = false;
- if (leader->NavLights().size() > 0)
- navlight_enabled = leader->NavLights().at(0)->IsEnabled();
+ if (leader->NavLights().size() > 0)
+ navlight_enabled = leader->NavLights().at(0)->IsEnabled();
- for (int i = 0; i < ship->NavLights().size(); i++) {
- if (navlight_enabled)
- ship->NavLights().at(i)->Enable();
- else
- ship->NavLights().at(i)->Disable();
- }
- }
+ for (int i = 0; i < ship->NavLights().size(); i++) {
+ if (navlight_enabled)
+ ship->NavLights().at(i)->Enable();
+ else
+ ship->NavLights().at(i)->Disable();
+ }
+ }
}
// +--------------------------------------------------------------------+
@@ -1025,8 +1025,8 @@ ShipAI::NavlightControl() Steer
ShipAI::AvoidTerrain()
{
- Steer avoid;
- return avoid;
+ Steer avoid;
+ return avoid;
}
// +--------------------------------------------------------------------+
@@ -1034,214 +1034,214 @@ ShipAI::AvoidTerrain() Steer
ShipAI::AvoidCollision()
{
- Steer avoid;
-
- if (!ship || !ship->GetRegion() || !ship->GetRegion()->IsActive())
- return avoid;
-
- if (other && (other->Life() == 0 || other->Integrity() < 1)) {
- other = 0;
- last_avoid_time = 0; // check for a new obstacle immediately
- }
-
- if (!other && Game::GameTime() - last_avoid_time < 500)
- return avoid;
-
- brake = 0;
-
- // don't get closer than this:
- double avoid_dist = 5 * self->Radius();
-
- if (avoid_dist < 1e3) avoid_dist = 1e3;
- else if (avoid_dist > 12e3) avoid_dist = 12e3;
-
- // find the soonest potential collision,
- // ignore any that occur after this:
- double avoid_time = 15;
-
- if (ship->Design()->avoid_time > 0)
- avoid_time = ship->Design()->avoid_time;
- else if (ship->IsStarship())
- avoid_time *= 1.5;
-
- Point bearing = self->Velocity();
- bearing.Normalize();
-
- bool found = false;
- int num_contacts = ship->NumContacts();
- ListIter<Contact> contact = ship->ContactList();
-
- // check current obstacle first:
- if (other) {
- found = AvoidTestSingleObject(other, bearing, avoid_dist, avoid_time, avoid);
- }
-
- if (!found) {
- // avoid ships:
- while (++contact && !found) {
- Ship* c_ship = contact->GetShip();
-
- if (c_ship && c_ship != ship && c_ship->IsStarship()) {
- found = AvoidTestSingleObject(c_ship, bearing, avoid_dist, avoid_time, avoid);
- }
- }
-
- // also avoid large pieces of debris:
- if (!found) {
- ListIter<Debris> iter = ship->GetRegion()->Rocks();
- while (++iter && !found) {
- Debris* debris = iter.value();
-
- if (debris->Mass() > ship->Mass())
- found = AvoidTestSingleObject(debris, bearing, avoid_dist, avoid_time, avoid);
- }
- }
-
- // and asteroids:
- if (!found) {
- // give asteroids a wider berth -
- avoid_dist *= 8;
-
- ListIter<Asteroid> iter = ship->GetRegion()->Roids();
- while (++iter && !found) {
- Asteroid* roid = iter.value();
- found = AvoidTestSingleObject(roid, bearing, avoid_dist, avoid_time, avoid);
- }
-
- if (!found)
- avoid_dist /= 8;
- }
-
- // if found, steer to avoid:
- if (other) {
- avoid = Avoid(obstacle, (float) (ship->Radius() + other->Radius() + avoid_dist * 0.9));
- avoid.brake = brake;
-
- ship->SetDirectorInfo(Game::GetText("ai.avoid-collision"));
- }
- }
-
- last_avoid_time = Game::GameTime();
- return avoid;
+ Steer avoid;
+
+ if (!ship || !ship->GetRegion() || !ship->GetRegion()->IsActive())
+ return avoid;
+
+ if (other && (other->Life() == 0 || other->Integrity() < 1)) {
+ other = 0;
+ last_avoid_time = 0; // check for a new obstacle immediately
+ }
+
+ if (!other && Game::GameTime() - last_avoid_time < 500)
+ return avoid;
+
+ brake = 0;
+
+ // don't get closer than this:
+ double avoid_dist = 5 * self->Radius();
+
+ if (avoid_dist < 1e3) avoid_dist = 1e3;
+ else if (avoid_dist > 12e3) avoid_dist = 12e3;
+
+ // find the soonest potential collision,
+ // ignore any that occur after this:
+ double avoid_time = 15;
+
+ if (ship->Design()->avoid_time > 0)
+ avoid_time = ship->Design()->avoid_time;
+ else if (ship->IsStarship())
+ avoid_time *= 1.5;
+
+ Point bearing = self->Velocity();
+ bearing.Normalize();
+
+ bool found = false;
+ int num_contacts = ship->NumContacts();
+ ListIter<Contact> contact = ship->ContactList();
+
+ // check current obstacle first:
+ if (other) {
+ found = AvoidTestSingleObject(other, bearing, avoid_dist, avoid_time, avoid);
+ }
+
+ if (!found) {
+ // avoid ships:
+ while (++contact && !found) {
+ Ship* c_ship = contact->GetShip();
+
+ if (c_ship && c_ship != ship && c_ship->IsStarship()) {
+ found = AvoidTestSingleObject(c_ship, bearing, avoid_dist, avoid_time, avoid);
+ }
+ }
+
+ // also avoid large pieces of debris:
+ if (!found) {
+ ListIter<Debris> iter = ship->GetRegion()->Rocks();
+ while (++iter && !found) {
+ Debris* debris = iter.value();
+
+ if (debris->Mass() > ship->Mass())
+ found = AvoidTestSingleObject(debris, bearing, avoid_dist, avoid_time, avoid);
+ }
+ }
+
+ // and asteroids:
+ if (!found) {
+ // give asteroids a wider berth -
+ avoid_dist *= 8;
+
+ ListIter<Asteroid> iter = ship->GetRegion()->Roids();
+ while (++iter && !found) {
+ Asteroid* roid = iter.value();
+ found = AvoidTestSingleObject(roid, bearing, avoid_dist, avoid_time, avoid);
+ }
+
+ if (!found)
+ avoid_dist /= 8;
+ }
+
+ // if found, steer to avoid:
+ if (other) {
+ avoid = Avoid(obstacle, (float) (ship->Radius() + other->Radius() + avoid_dist * 0.9));
+ avoid.brake = brake;
+
+ ship->SetDirectorInfo(Game::GetText("ai.avoid-collision"));
+ }
+ }
+
+ last_avoid_time = Game::GameTime();
+ return avoid;
}
bool
ShipAI::AvoidTestSingleObject(SimObject* obj,
- const Point& bearing,
- double avoid_dist,
- double& avoid_time,
- Steer& avoid)
+const Point& bearing,
+double avoid_dist,
+double& avoid_time,
+Steer& avoid)
{
- if (too_close == obj->Identity()) {
- double dist = (ship->Location() - obj->Location()).length();
- double closure = (ship->Velocity() - obj->Velocity()) * bearing;
-
- if (closure > 1 && dist < avoid_dist) {
- avoid = AvoidCloseObject(obj);
- return true;
- }
- else {
- too_close = 0;
- }
- }
-
- // will we get close?
- double time = ClosestApproachTime(ship->Location(), ship->Velocity(),
- obj->Location(), obj->Velocity());
-
- // already past the obstacle:
- if (time <= 0) {
- if (other == obj) other = 0;
- return false;
- }
-
- // how quickly could we collide?
- Point current_relation = ship->Location() - obj->Location();
- double current_distance = current_relation.length() - ship->Radius() - obj->Radius();
-
- // are we really far away?
- if (current_distance > 25e3) {
- if (other == obj) other = 0;
- return false;
- }
-
- // is the obstacle a farcaster?
- if (obj->Type() == SimObject::SIM_SHIP) {
- Ship* c_ship = (Ship*) obj;
-
- if (c_ship->GetFarcaster()) {
- // are we on a safe vector?
- Point dir = ship->Velocity();
- dir.Normalize();
-
- double angle_off = fabs(acos(dir * obj->Cam().vpn()));
-
- if (angle_off > 90*DEGREES)
- angle_off = 180*DEGREES - angle_off;
-
- if (angle_off < 35*DEGREES) {
- // will we pass through the center?
- Point d = ship->Location() + dir * (current_distance + ship->Radius() + obj->Radius());
- double err = (obj->Location() - d).length();
-
- if (err < 0.667 * obj->Radius()) {
- return false;
- }
- }
- }
- }
-
- // rate of closure:
- double closing_velocity = (ship->Velocity() - obj->Velocity()) * bearing;
-
- // are we too close already?
- if (current_distance < (avoid_dist * 0.35)) {
- if (closing_velocity > 1 || current_distance < ship->Radius()) {
- avoid = AvoidCloseObject(obj);
- return true;
- }
- }
-
- // too far away to worry about:
- double separation = (avoid_dist + obj->Radius());
- if ((current_distance-separation) / closing_velocity > avoid_time) {
- if (other == obj) other = 0;
- return false;
- }
-
- // where will we be?
- Point selfpt = ship->Location() + ship->Velocity() * time;
- Point testpt = obj->Location() + obj->Velocity() * time;
-
- // how close will we get?
- double dist = (selfpt - testpt).length()
- - ship->Radius()
- - obj->Radius();
-
- // that's too close:
- if (dist < avoid_dist) {
- if (dist < avoid_dist * 0.25 && time < avoid_time * 0.5) {
- avoid = AvoidCloseObject(obj);
- return true;
- }
-
- obstacle = Transform(testpt);
-
- if (obstacle.z > 0) {
- other = obj;
- avoid_time = time;
- brake = 0.5;
-
- Observe(other);
- }
- }
-
- // hysteresis:
- else if (other == obj && dist > avoid_dist * 1.25) {
- other = 0;
- }
-
- return false;
+ if (too_close == obj->Identity()) {
+ double dist = (ship->Location() - obj->Location()).length();
+ double closure = (ship->Velocity() - obj->Velocity()) * bearing;
+
+ if (closure > 1 && dist < avoid_dist) {
+ avoid = AvoidCloseObject(obj);
+ return true;
+ }
+ else {
+ too_close = 0;
+ }
+ }
+
+ // will we get close?
+ double time = ClosestApproachTime(ship->Location(), ship->Velocity(),
+ obj->Location(), obj->Velocity());
+
+ // already past the obstacle:
+ if (time <= 0) {
+ if (other == obj) other = 0;
+ return false;
+ }
+
+ // how quickly could we collide?
+ Point current_relation = ship->Location() - obj->Location();
+ double current_distance = current_relation.length() - ship->Radius() - obj->Radius();
+
+ // are we really far away?
+ if (current_distance > 25e3) {
+ if (other == obj) other = 0;
+ return false;
+ }
+
+ // is the obstacle a farcaster?
+ if (obj->Type() == SimObject::SIM_SHIP) {
+ Ship* c_ship = (Ship*) obj;
+
+ if (c_ship->GetFarcaster()) {
+ // are we on a safe vector?
+ Point dir = ship->Velocity();
+ dir.Normalize();
+
+ double angle_off = fabs(acos(dir * obj->Cam().vpn()));
+
+ if (angle_off > 90*DEGREES)
+ angle_off = 180*DEGREES - angle_off;
+
+ if (angle_off < 35*DEGREES) {
+ // will we pass through the center?
+ Point d = ship->Location() + dir * (current_distance + ship->Radius() + obj->Radius());
+ double err = (obj->Location() - d).length();
+
+ if (err < 0.667 * obj->Radius()) {
+ return false;
+ }
+ }
+ }
+ }
+
+ // rate of closure:
+ double closing_velocity = (ship->Velocity() - obj->Velocity()) * bearing;
+
+ // are we too close already?
+ if (current_distance < (avoid_dist * 0.35)) {
+ if (closing_velocity > 1 || current_distance < ship->Radius()) {
+ avoid = AvoidCloseObject(obj);
+ return true;
+ }
+ }
+
+ // too far away to worry about:
+ double separation = (avoid_dist + obj->Radius());
+ if ((current_distance-separation) / closing_velocity > avoid_time) {
+ if (other == obj) other = 0;
+ return false;
+ }
+
+ // where will we be?
+ Point selfpt = ship->Location() + ship->Velocity() * time;
+ Point testpt = obj->Location() + obj->Velocity() * time;
+
+ // how close will we get?
+ double dist = (selfpt - testpt).length()
+ - ship->Radius()
+ - obj->Radius();
+
+ // that's too close:
+ if (dist < avoid_dist) {
+ if (dist < avoid_dist * 0.25 && time < avoid_time * 0.5) {
+ avoid = AvoidCloseObject(obj);
+ return true;
+ }
+
+ obstacle = Transform(testpt);
+
+ if (obstacle.z > 0) {
+ other = obj;
+ avoid_time = time;
+ brake = 0.5;
+
+ Observe(other);
+ }
+ }
+
+ // hysteresis:
+ else if (other == obj && dist > avoid_dist * 1.25) {
+ other = 0;
+ }
+
+ return false;
}
// +--------------------------------------------------------------------+
@@ -1249,17 +1249,17 @@ ShipAI::AvoidTestSingleObject(SimObject* obj, Steer
ShipAI::AvoidCloseObject(SimObject* obj)
{
- too_close = obj->Identity();
- obstacle = Transform(obj->Location());
- other = obj;
+ too_close = obj->Identity();
+ obstacle = Transform(obj->Location());
+ other = obj;
- Observe(other);
+ Observe(other);
- Steer avoid = Flee(obstacle);
- avoid.brake = 0.3;
+ Steer avoid = Flee(obstacle);
+ avoid.brake = 0.3;
- ship->SetDirectorInfo(Game::GetText("ai.avoid-collision"));
- return avoid;
+ ship->SetDirectorInfo(Game::GetText("ai.avoid-collision"));
+ return avoid;
}
// +--------------------------------------------------------------------+
@@ -1267,44 +1267,44 @@ ShipAI::AvoidCloseObject(SimObject* obj) Steer
ShipAI::SeekTarget()
{
- Ship* ward = ship->GetWard();
-
- if (!target && !ward && !navpt && !patrol) {
- if (element_index > 1) {
- // wingmen keep in formation:
- return Seek(objective);
- }
-
- if (farcaster) {
- return Seek(objective);
- }
-
- if (rumor) {
- return Seek(objective);
- }
-
- return Steer();
- }
-
- if (patrol) {
- Steer result = Seek(objective);
-
- if (distance < 2000) {
- result.brake = 1;
- }
-
- return result;
- }
-
- if (target && too_close == target->Identity()) {
- drop_time = 4;
- return Avoid(objective, 0.0f);
- }
- else if (drop_time > 0) {
- return Steer();
- }
-
- return Seek(objective);
+ Ship* ward = ship->GetWard();
+
+ if (!target && !ward && !navpt && !patrol) {
+ if (element_index > 1) {
+ // wingmen keep in formation:
+ return Seek(objective);
+ }
+
+ if (farcaster) {
+ return Seek(objective);
+ }
+
+ if (rumor) {
+ return Seek(objective);
+ }
+
+ return Steer();
+ }
+
+ if (patrol) {
+ Steer result = Seek(objective);
+
+ if (distance < 2000) {
+ result.brake = 1;
+ }
+
+ return result;
+ }
+
+ if (target && too_close == target->Identity()) {
+ drop_time = 4;
+ return Avoid(objective, 0.0f);
+ }
+ else if (drop_time > 0) {
+ return Steer();
+ }
+
+ return Seek(objective);
}
// +--------------------------------------------------------------------+
@@ -1312,7 +1312,7 @@ ShipAI::SeekTarget() Steer
ShipAI::EvadeThreat()
{
- return Steer();
+ return Steer();
}
// +--------------------------------------------------------------------+
@@ -1327,16 +1327,16 @@ ShipAI::FireControl() void
ShipAI::AdjustDefenses()
{
- Shield* shield = ship->GetShield();
+ Shield* shield = ship->GetShield();
- if (shield) {
- double desire = 50;
+ if (shield) {
+ double desire = 50;
- if (threat_missile || threat)
- desire = 100;
+ if (threat_missile || threat)
+ desire = 100;
- shield->SetPowerLevel(desire);
- }
+ shield->SetPowerLevel(desire);
+ }
}
// +--------------------------------------------------------------------+
@@ -1344,15 +1344,15 @@ ShipAI::AdjustDefenses() void
ShipAI::CheckTarget()
{
- if (target) {
- if (target->Life() == 0)
- target = 0;
+ if (target) {
+ if (target->Life() == 0)
+ target = 0;
- else if (target->Type() == SimObject::SIM_SHIP) {
- Ship* tgt_ship = (Ship*) target;
+ else if (target->Type() == SimObject::SIM_SHIP) {
+ Ship* tgt_ship = (Ship*) target;
- if (tgt_ship->GetIFF() == ship->GetIFF() && !tgt_ship->IsRogue())
- target = 0;
- }
- }
+ if (tgt_ship->GetIFF() == ship->GetIFF() && !tgt_ship->IsRogue())
+ target = 0;
+ }
+ }
}
|