bool FighterTacticalAI::IsStrikeComplete(Instruction* instr) { // wingmen can not call a halt to a strike: if (!ship || element_index > 1) return false; // if there's nothing to shoot at, we must be done: if (!instr || !instr->GetTarget() || instr->GetTarget()->Life() == 0 || instr->GetTarget()->Type() != SimObject::SIM_SHIP) return true; // break off strike only when ALL weapons are expended: // (remember to check all relevant wingmen) Element* element = ship->GetElement(); Ship* target = (Ship*) instr->GetTarget(); if (!element) return true; for (int i = 0; i < element->NumShips(); i++) { Ship* s = element->GetShip(i+1); if (!s || s->Integrity() < 25) // || (s->Location() - target->Location()).length() > 250e3) continue; ListIter<WeaponGroup> g_iter = s->Weapons(); while (++g_iter) { WeaponGroup* w = g_iter.value(); if (w->Ammo() && w->CanTarget(target->Class())) { ListIter<Weapon> w_iter = w->GetWeapons(); while (++w_iter) { Weapon* weapon = w_iter.value(); if (weapon->Status() > System::CRITICAL) return false; } } } } // still here? we must be done! return true; }
void NetPlayer::SetShip(Ship* s) { if (ship != s) { if (ship) { ship->EnableRepair(true); Ignore(ship); } ship = s; if (ship) { Observe(ship); ship->SetNetworkControl(this); ship->SetObjID(objid); iff = ship->GetIFF(); // Turn off auto-repair. All repair data should // come in over the network from the remote player: ship->EnableRepair(false); // Set all ship weapons back to manual fire control. // All trigger events should come over the network, // not from weapon auto aiming ai: ListIter<WeaponGroup> iter = ship->Weapons(); while (++iter) { WeaponGroup* group = iter.value(); ListIter<Weapon> w_iter = group->GetWeapons(); while (++w_iter) { Weapon* weapon = w_iter.value(); weapon->SetFiringOrders(Weapon::MANUAL); } } } } }
bool StarshipAI::AssessTargetPointDefense() { if (Game::GameTime() - point_defense_time < 3500) return tgt_point_defense; tgt_point_defense = false; if (!target || target->Type() != SimObject::SIM_SHIP || GetAILevel() < 2) return tgt_point_defense; Ship* tgt_ship = (Ship*) target; if (!tgt_ship->IsStarship()) return tgt_point_defense; Weapon* subtgt = 0; Point svec = ship->Location() - tgt_ship->Location(); point_defense_time = Game::GameTime(); // first pass: turrets ListIter<WeaponGroup> g_iter = tgt_ship->Weapons(); while (++g_iter && !tgt_point_defense) { WeaponGroup* g = g_iter.value(); if (g->CanTarget(1)) { ListIter<Weapon> w_iter = g->GetWeapons(); while (++w_iter && !tgt_point_defense) { Weapon* w = w_iter.value(); if (w->Availability() > 35 && w->GetAimVector() * svec > 0) tgt_point_defense = true; } } } return tgt_point_defense; }
System* StarshipAI::SelectSubtarget() { if (Game::GameTime() - sub_select_time < 2345) return subtarget; subtarget = 0; if (!target || target->Type() != SimObject::SIM_SHIP || GetAILevel() < 1) return subtarget; Ship* tgt_ship = (Ship*) target; if (!tgt_ship->IsStarship()) return subtarget; Weapon* subtgt = 0; double dist = 50e3; Point svec = ship->Location() - tgt_ship->Location(); sub_select_time = Game::GameTime(); // first pass: turrets ListIter<WeaponGroup> g_iter = tgt_ship->Weapons(); while (++g_iter) { WeaponGroup* g = g_iter.value(); if (g->GetDesign() && g->GetDesign()->turret_model) { ListIter<Weapon> w_iter = g->GetWeapons(); while (++w_iter) { Weapon* w = w_iter.value(); if (w->Availability() < 35) continue; if (w->GetAimVector() * svec < 0) continue; if (w->GetTurret()) { Point tloc = w->GetTurret()->Location(); Point delta = tloc - ship->Location(); double dlen = delta.length(); if (dlen < dist) { subtgt = w; dist = dlen; } } } } } // second pass: major weapons if (!subtgt) { g_iter.reset(); while (++g_iter) { WeaponGroup* g = g_iter.value(); if (g->GetDesign() && !g->GetDesign()->turret_model) { ListIter<Weapon> w_iter = g->GetWeapons(); while (++w_iter) { Weapon* w = w_iter.value(); if (w->Availability() < 35) continue; if (w->GetAimVector() * svec < 0) continue; Point tloc = w->MountLocation(); Point delta = tloc - ship->Location(); double dlen = delta.length(); if (dlen < dist) { subtgt = w; dist = dlen; } } } } } subtarget = subtgt; return subtarget; }
void StarshipAI::FireControl() { // identify unknown contacts: if (identify) { if (fabs(ship->GetHelmHeading() - ship->CompassHeading()) < 10*DEGREES) { Contact* contact = ship->FindContact(target); if (contact && !contact->ActLock()) { if (!ship->GetProbe()) { ship->LaunchProbe(); } } } return; } // investigate last known location of enemy ship: if (rumor && !target && ship->GetProbeLauncher() && !ship->GetProbe()) { // is rumor in basket? Point rmr = Transform(rumor->Location()); rmr.Normalize(); double dx = fabs(rmr.x); double dy = fabs(rmr.y); if (dx < 10*DEGREES && dy < 10*DEGREES && rmr.z > 0) { ship->LaunchProbe(); } } // Corvettes and Frigates are anti-air platforms. They need to // target missile threats even when the threat is aimed at another // friendly ship. Forward facing weapons must be on auto fire, // while lateral and aft facing weapons are set to point defense. if (ship->Class() == Ship::CORVETTE || ship->Class() == Ship::FRIGATE) { ListIter<WeaponGroup> iter = ship->Weapons(); while (++iter) { WeaponGroup* group = iter.value(); ListIter<Weapon> w_iter = group->GetWeapons(); while (++w_iter) { Weapon* weapon = w_iter.value(); double az = weapon->GetAzimuth(); if (fabs(az) < 45*DEGREES) { weapon->SetFiringOrders(Weapon::AUTO); weapon->SetTarget(target, 0); } else { weapon->SetFiringOrders(Weapon::POINT_DEFENSE); } } } } // All other starships are free to engage ship targets. Weapon // fire control is managed by the type of weapon. else { System* subtgt = SelectSubtarget(); ListIter<WeaponGroup> iter = ship->Weapons(); while (++iter) { WeaponGroup* weapon = iter.value(); if (weapon->GetDesign()->target_type & Ship::DROPSHIPS) { // anti-air weapon? weapon->SetFiringOrders(Weapon::POINT_DEFENSE); } else if (weapon->IsDrone()) { // torpedoes weapon->SetFiringOrders(Weapon::MANUAL); weapon->SetTarget(target, 0); if (target && target->GetRegion() == ship->GetRegion()) { Point delta = target->Location() - ship->Location(); double range = delta.length(); if (range < weapon->GetDesign()->max_range * 0.9 && !AssessTargetPointDefense()) weapon->SetFiringOrders(Weapon::AUTO); else if (range < weapon->GetDesign()->max_range * 0.5) weapon->SetFiringOrders(Weapon::AUTO); } } else { // anti-ship weapon weapon->SetFiringOrders(Weapon::AUTO); weapon->SetTarget(target, subtgt); weapon->SetSweep(subtgt ? Weapon::SWEEP_NONE : Weapon::SWEEP_TIGHT); } } } }