Пример #1
0
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;
}
Пример #2
0
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;
	}
}