From 69209c38968c6f4066a772e0a51a2928749217de Mon Sep 17 00:00:00 2001 From: "FWoltermann@gmail.com" Date: Fri, 9 Dec 2011 19:00:23 +0000 Subject: Re-indenting the code to use standard tabs. Yes, I know this is pretty pointless, but who cares? --- Stars45/ShipAI.cpp | 1970 ++++++++++++++++++++++++++-------------------------- 1 file changed, 985 insertions(+), 985 deletions(-) (limited to 'Stars45/ShipAI.cpp') 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 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 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 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 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 = 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 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 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 = 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 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 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; + } + } } -- cgit v1.1