bool QuitView::CanAccept() { sim = Sim::GetSim(); if (!sim || sim->IsNetGame()) return true; Ship* player_ship = sim->GetPlayerShip(); if (player_ship->MissionClock() < 60000) { RadioView::Message(Game::GetText("QuitView.too-soon")); RadioView::Message(Game::GetText("QuitView.abort")); return false; } ListIter<Contact> iter = player_ship->ContactList(); while (++iter) { Contact* c = iter.value(); Ship* cship = c->GetShip(); int ciff = c->GetIFF(player_ship); if (c->Threat(player_ship)) { RadioView::Message(Game::GetText("QuitView.threats-present")); RadioView::Message(Game::GetText("QuitView.abort")); return false; } else if (cship && ciff > 0 && ciff != player_ship->GetIFF()) { Point delta = c->Location() - player_ship->Location(); double dist = delta.length(); if (cship->IsDropship() && dist < 50e3) { RadioView::Message(Game::GetText("QuitView.threats-present")); RadioView::Message(Game::GetText("QuitView.abort")); return false; } else if (cship->IsStarship() && dist < 100e3) { RadioView::Message(Game::GetText("QuitView.threats-present")); RadioView::Message(Game::GetText("QuitView.abort")); return false; } } } return true; }
void GroundAI::SelectTarget() { SimObject* potential_target = 0; // pick the closest combatant ship with a different IFF code: double target_dist = 1.0e15; Ship* current_ship_target = 0; ListIter<Contact> c_iter = ship->ContactList(); while (++c_iter) { Contact* contact = c_iter.value(); int c_iff = contact->GetIFF(ship); Ship* c_ship = contact->GetShip(); Shot* c_shot = contact->GetShot(); bool rogue = false; if (c_ship) rogue = c_ship->IsRogue(); if (rogue || c_iff > 0 && c_iff != ship->GetIFF() && c_iff < 1000) { if (c_ship && !c_ship->InTransition()) { // found an enemy, check distance: double dist = (ship->Location() - c_ship->Location()).length(); if (!current_ship_target || (c_ship->Class() <= current_ship_target->Class() && dist < target_dist)) { current_ship_target = c_ship; target_dist = dist; } } } potential_target = current_ship_target; } SetTarget(potential_target); }
void FighterTacticalAI::SelectTargetOpportunity() { // NON-COMBATANTS do not pick targets of opportunity: if (ship->GetIFF() == 0) return; Ship* potential_target = 0; Shot* current_shot_target = 0; // pick the closest combatant ship with a different IFF code: double target_dist = 1.0e15; double min_dist = 5.0e3; // FIGHTERS are primarily anti-air platforms, but may // also attack smaller starships: Ship* ward = 0; if (element_index > 1) ward = ship->GetLeader(); // commit range for patrol/sweep is 80 Km // (about 2 minutes for a fighter at max speed) if (roe == FLEXIBLE || roe == AGRESSIVE) target_dist = ship->Design()->commit_range; if (roe < FLEXIBLE) target_dist = 0.5 * ship->Design()->commit_range; int class_limit = Ship::LCA; if (ship->Class() == Ship::ATTACK) class_limit = Ship::DESTROYER; ListIter<Contact> c_iter = ship->ContactList(); while (++c_iter) { Contact* contact = c_iter.value(); Ship* c_ship = contact->GetShip(); Shot* c_shot = contact->GetShot(); int c_iff = contact->GetIFF(ship); bool rogue = false; if (c_ship) rogue = c_ship->IsRogue(); if (!rogue && (c_iff <= 0 || c_iff == ship->GetIFF() || c_iff == 1000)) continue; // reasonable target? if (c_ship && c_ship->Class() <= class_limit && !c_ship->InTransition()) { if (!rogue) { SimObject* ttgt = c_ship->GetTarget(); // if we are self-defensive, is this contact engaging us? if (roe == SELF_DEFENSIVE && ttgt != ship) continue; // if we are defending, is this contact engaging us or our ward? if (roe == DEFENSIVE && ttgt != ship && ttgt != ward) continue; } // found an enemy, check distance: double dist = (ship->Location() - c_ship->Location()).length(); if (dist < 0.75 * target_dist) { // if on patrol, check target distance from navpoint: if (roe == FLEXIBLE && navpt) { double ndist = (navpt->Location().OtherHand() - c_ship->Location()).length(); if (ndist > 80e3) continue; } potential_target = c_ship; target_dist = dist; } } else if (c_shot && c_shot->IsDrone()) { // found an enemy shot, do we have enough time to engage? if (c_shot->GetEta() < 10) continue; // found an enemy shot, check distance: double dist = (ship->Location() - c_shot->Location()).length(); if (!current_shot_target) { current_shot_target = c_shot; target_dist = dist; } // is this shot a better target than the one we've found? else { Ship* ward = ship_ai->GetWard(); if ((c_shot->IsTracking(ward) && !current_shot_target->IsTracking(ward)) || (dist < target_dist)) { current_shot_target = c_shot; target_dist = dist; } } } } if (current_shot_target) { ship_ai->SetTarget(current_shot_target); } else { ship_ai->SetTarget(potential_target); SelectSecondaryForTarget(potential_target); } }
void RadioTraffic::DisplayMessage(RadioMessage* msg) { if (!msg) return; char txt_buf[256]; txt_buf[0] = 0; char msg_buf[128]; msg_buf[0] = 0; char src_buf[64]; src_buf[0] = 0; char dst_buf[64]; dst_buf[0] = 0; char act_buf[64]; act_buf[0] = 0; int vox_channel = 0; Ship* dst_ship = msg->DestinationShip(); Element* dst_elem = msg->DestinationElem(); // BUILD SRC AND DST BUFFERS ------------------- if (msg->Sender()) { const Ship* sender = msg->Sender(); // orders to self? if (dst_elem && dst_elem->NumShips() == 1 && dst_elem->GetShip(1) == sender) { if (msg->Action() >= RadioMessage::CALL_ENGAGING) { sprintf_s(src_buf, "%s", sender->Name()); if (sender->IsStarship()) vox_channel = (sender->Identity()%3) + 5; } } // orders to other ships: else { if (sender->IsStarship()) { vox_channel = (sender->Identity()%3) + 5; } else { vox_channel = sender->GetElementIndex(); } if (msg->Action() >= RadioMessage::CALL_ENGAGING) { sprintf_s(src_buf, "%s", sender->Name()); } else { sprintf_s(src_buf, "This is %s", sender->Name()); if (dst_ship) { // internal announcement if (dst_ship->GetElement() == sender->GetElement()) { dst_elem = sender->GetElement(); int index = sender->GetElementIndex(); if (index > 1 && dst_elem) { sprintf_s(dst_buf, "%s Leader", (const char*) dst_elem->Name()); sprintf_s(src_buf, "this is %s %d", (const char*) dst_elem->Name(), index); } else { sprintf_s(src_buf, "this is %s leader", (const char*) dst_elem->Name()); } } else { strcpy_s(dst_buf, (const char*) dst_ship->Name()); src_buf[0] = tolower(src_buf[0]); } } else if (dst_elem) { // flight if (dst_elem->NumShips() > 1) { sprintf_s(dst_buf, "%s Flight", (const char*) dst_elem->Name()); // internal announcement if (sender->GetElement() == dst_elem) { int index = sender->GetElementIndex(); if (index > 1) { sprintf_s(dst_buf, "%s Leader", (const char*) dst_elem->Name()); sprintf_s(src_buf, "this is %s %d", (const char*) dst_elem->Name(), index); } else { sprintf_s(src_buf, "this is %s leader", (const char*) dst_elem->Name()); } } } // solo else { strcpy_s(dst_buf, (const char*) dst_elem->Name()); src_buf[0] = tolower(src_buf[0]); } } } } } // BUILD ACTION AND TARGET BUFFERS ------------------- SimObject* target = 0; strcpy_s(act_buf, RadioMessage::ActionName(msg->Action())); if (msg->TargetList().size() > 0) target = msg->TargetList()[0]; if (msg->Action() == RadioMessage::ACK || msg->Action() == RadioMessage::NACK) { if (dst_ship == msg->Sender()) { src_buf[0] = 0; dst_buf[0] = 0; if (msg->Action() == RadioMessage::ACK) sprintf_s(msg_buf, "%s.", TranslateVox("Acknowledged").data()); else sprintf_s(msg_buf, "%s.", TranslateVox("Unable").data()); } else if (msg->Sender()) { dst_buf[0] = 0; if (msg->Info().length()) { sprintf_s(msg_buf, "%s. %s", TranslateVox(act_buf).data(), (const char*) msg->Info()); } else { sprintf_s(msg_buf, "%s.", TranslateVox(act_buf).data()); } } else { if (msg->Info().length()) { sprintf_s(msg_buf, "%s. %s", TranslateVox(act_buf).data(), (const char*) msg->Info()); } else { sprintf_s(msg_buf, "%s.", TranslateVox(act_buf).data()); } } } else if (msg->Action() == RadioMessage::MOVE_PATROL) { sprintf_s(msg_buf, TranslateVox("Move patrol.").data()); } else if (target && dst_ship && msg->Sender()) { Contact* c = msg->Sender()->FindContact(target); if (c && c->GetIFF(msg->Sender()) > 10) { sprintf_s(msg_buf, "%s %s.", TranslateVox(act_buf).data(), TranslateVox("unknown contact").data()); } else { sprintf_s(msg_buf, "%s %s.", TranslateVox(act_buf).data(), target->Name()); } } else if (target) { sprintf_s(msg_buf, "%s %s.", TranslateVox(act_buf).data(), target->Name()); } else if (msg->Info().length()) { sprintf_s(msg_buf, "%s %s", TranslateVox(act_buf).data(), (const char*) msg->Info()); } else { strcpy_s(msg_buf, TranslateVox(act_buf).data()); } char last_char = msg_buf[strlen(msg_buf)-1]; if (last_char != '!' && last_char != '.' && last_char != '?') strcat_s(msg_buf, "."); // final format: if (dst_buf[0] && src_buf[0]) { sprintf_s(txt_buf, "%s %s. %s", TranslateVox(dst_buf).data(), TranslateVox(src_buf).data(), msg_buf); txt_buf[0] = toupper(txt_buf[0]); } else if (src_buf[0]) { sprintf_s(txt_buf, "%s. %s", TranslateVox(src_buf).data(), msg_buf); txt_buf[0] = toupper(txt_buf[0]); } else if (dst_buf[0]) { sprintf_s(txt_buf, "%s %s", TranslateVox(dst_buf).data(), msg_buf); txt_buf[0] = toupper(txt_buf[0]); } else { strcpy_s(txt_buf, msg_buf); } // vox: const char* path[8] = { "1", "1", "2", "3", "4", "5", "6", "7" }; RadioVox* vox = new(__FILE__,__LINE__) RadioVox(vox_channel, path[vox_channel], txt_buf); vox->AddPhrase(dst_buf); vox->AddPhrase(src_buf); vox->AddPhrase(act_buf); if (vox && !vox->Start()) { RadioView::Message(txt_buf); delete vox; } }