コード例 #1
0
void
FltDlg::UpdateObjective()
{
	if (!objective_list || mission_type < 0 || !ship) return;

	Sim* sim = Sim::GetSim();
	char txt[32];

	for (int item = 0; item < objective_list->NumItems(); item++) {
		const char* obj_name = objective_list->GetItemText(item);

		Element* elem = sim->FindElement(obj_name);

		// if element has expired, remove it from the objective list
		if (!elem || !elem->IsActive() || elem->IsFinished()) {
			objective_list->RemoveItem(item);
			item--;
		}

		// otherwise, the element is still active, so update range/region
		else {
			Ship*    s   = elem->GetShip(1);
			double   r   = 0;
			bool     con = false;

			if (s) {
				Point s_loc = s->Location()    + s->GetRegion()->Location();
				Point h_loc = ship->Location() + ship->GetRegion()->Location();

				r = (s_loc - h_loc).length();

				con = ship->FindContact(s) != 0;

				if (con) {
					FormatNumber(txt, r);
				}
				else {
					strcpy_s(txt, Game::GetText("FltDlg.Unknown").data());
					r = 2e9;
				}
			}

			objective_list->SetItemText(item, 1, s->GetRegion()->Name());

			objective_list->SetItemText(item, 2, txt);
			objective_list->SetItemData(item, 2, (DWORD) r);
		}
	}
}
コード例 #2
0
bool
CameraDirector::Update(SimObject* obj)
{
    if (obj->Type() == SimObject::SIM_SHIP) {
        Ship* s = (Ship*) obj;
        if (ship == s)
        ship = 0;

        if (external_ship == s) {
            external_point = s->Location();
            external_ship = 0;
        }

        if (external_group.contains(s))
        external_group.remove(s);
    }

    return SimObserver::Update(obj);
}
コード例 #3
0
void
TacticalAI::CheckTarget()
{
    SimObject* tgt = ship_ai->GetTarget();

    if (!tgt) return;

    if (tgt->GetRegion() != ship->GetRegion()) {
        ship_ai->DropTarget();
        return;
    }

    if (tgt->Type() == SimObject::SIM_SHIP) {
        Ship* target = (Ship*) tgt;

        // has the target joined our side?
        if (target->GetIFF() == ship->GetIFF() && !target->IsRogue()) {
            ship_ai->DropTarget();
            return;
        }

        // is the target already jumping/breaking/dying?
        if (target->InTransition()) {
            ship_ai->DropTarget();
            return;
        }

        // have we been ordered to pursue the target?
        if (directed_tgtid) {
            if (directed_tgtid != target->Identity()) {
                ship_ai->DropTarget();
            }

            return;
        }

        // can we catch the target?
        if (target->Design()->vlimit  <= ship->Design()->vlimit ||
                ship->Velocity().length() <= ship->Design()->vlimit)
        return;

        // is the target now out of range?
        WeaponDesign* wep_dsn = ship->GetPrimaryDesign();
        if (!wep_dsn)
        return;

        // compute the "give up" range:
        double drop_range = 3 * wep_dsn->max_range;
        if (drop_range > 0.75 * ship->Design()->commit_range)
        drop_range = 0.75 * ship->Design()->commit_range;

        double range = Point(target->Location() - ship->Location()).length();
        if (range < drop_range)
        return;

        // is the target closing or separating?
        Point  delta = (target->Location() + target->Velocity()) -
        (ship->Location()   + ship->Velocity());

        if (delta.length() < range)
        return;

        ship_ai->DropTarget();
    }

    else if (tgt->Type() == SimObject::SIM_DRONE) {
        Drone* drone = (Drone*) tgt;

        // is the target still a threat?
        if (drone->GetEta() < 1 || drone->GetTarget() == 0)
        ship_ai->DropTarget();
    }
}
コード例 #4
0
void
TacticalAI::SelectTargetOpportunity()
{
    // NON-COMBATANTS do not pick targets of opportunity:
    if (ship->GetIFF() == 0)
    return;

    SimObject* potential_target = 0;

    // pick the closest combatant ship with a different IFF code:
    double target_dist = ship->Design()->commit_range;

    SimObject* ward   = ship_ai->GetWard();

    // FRIGATES are primarily anti-air platforms, but may
    // also attack smaller starships:

    if (ship->Class() == Ship::CORVETTE || ship->Class() == Ship::FRIGATE) {
        Ship* current_ship_target = 0;
        Shot* current_shot_target = 0;

        // if we are escorting a larger warship, it is good to attack
        // the same target as our ward:

        if (ward) {
            Ship* s = (Ship*) ward;

            if (s->Class() > ship->Class()) {
                SimObject* obj = s->GetTarget();

                if (obj && obj->Type() == SimObject::SIM_SHIP) {
                    current_ship_target = (Ship*) obj;
                    target_dist = (ship->Location() - obj->Location()).length();
                }
            }
        }

        ListIter<Contact> contact = ship->ContactList();
        while (++contact) {
            Ship* c_ship = contact->GetShip();
            Shot* c_shot = contact->GetShot();

            if (!c_ship && !c_shot)
            continue;

            int   c_iff  = contact->GetIFF(ship);
            bool  rogue  = c_ship && c_ship->IsRogue();
            bool  tgt_ok = c_iff > 0               &&
            c_iff != ship->GetIFF() &&
            c_iff < 1000;

            if (rogue || tgt_ok) {
                if (c_ship && c_ship != ship && !c_ship->InTransition()) {
                    if (c_ship->Class() <  Ship::DESTROYER || 
                            (c_ship->Class() >= Ship::MINE && c_ship->Class() <= Ship::DEFSAT)) {
                        // found an enemy, check distance:
                        double dist = (ship->Location() - c_ship->Location()).length();

                        if (dist < 0.75 * target_dist &&
                                (!current_ship_target || c_ship->Class() <= current_ship_target->Class())) {
                            current_ship_target = c_ship;
                            target_dist = dist;
                        }
                    }
                }

                else if (c_shot) {
                    // found an enemy shot, is there enough time to engage?
                    if (c_shot->GetEta() < 3)
                    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) || c_shot->IsTracking(ship)) &&
                                (!current_shot_target->IsTracking(ward) || 
                                    !current_shot_target->IsTracking(ship))) {
                            current_shot_target = c_shot;
                            target_dist = dist;
                        }
                        else if (dist < target_dist) {
                            current_shot_target = c_shot;
                            target_dist = dist;
                        }
                    }
                }
            }
        }

        if (current_shot_target)
        potential_target = current_shot_target;
        else
        potential_target = current_ship_target;
    }

    // ALL OTHER SHIP CLASSES ignore fighters and only engage
    // other starships:

    else {
        List<Ship> ward_threats;

        ListIter<Contact> contact = ship->ContactList();
        while (++contact) {
            Ship* c_ship = contact->GetShip();

            if (!c_ship)
            continue;

            int   c_iff  = contact->GetIFF(ship);
            bool  rogue  = c_ship->IsRogue();
            bool  tgt_ok = c_ship != ship          && 
            c_iff > 0               && 
            c_iff != ship->GetIFF() && 
            !c_ship->InTransition();

            if (rogue || tgt_ok) {
                if (c_ship->IsStarship() || c_ship->IsStatic()) {
                    // found an enemy, check distance:
                    double dist = (ship->Location() - c_ship->Location()).length();

                    if (dist < 0.75 * target_dist) {
                        potential_target = c_ship;
                        target_dist = dist;
                    }

                    if (ward && c_ship->IsTracking(ward)) {
                        ward_threats.append(c_ship);
                    }
                }
            }
        }

        // if this ship is protecting a ward,
        // prefer targets that are threatening that ward:
        if (potential_target && ward_threats.size() && !ward_threats.contains((Ship*)potential_target)) {
            target_dist *= 2;
            
            ListIter<Ship> iter = ward_threats;
            while (++iter) {
                Ship* threat = iter.value();

                double dist = (ward->Location() - threat->Location()).length();

                if (dist < target_dist) {
                    potential_target = threat;
                    target_dist = dist;
                }
            }
        }
    }

    if (ship->Class() != Ship::CARRIER && ship->Class() != Ship::SWACS)
    ship_ai->SetTarget(potential_target);
}
コード例 #5
0
bool
TacticalAI::ProcessOrders()
{
    if (ship_ai)
        ship_ai->ClearPatrol();

    if (orders && orders->EMCON() > 0) {
        int desired_emcon = orders->EMCON();

        if (ship_ai && (ship_ai->GetThreat() || ship_ai->GetThreatMissile()))
        desired_emcon = 3;

        if (ship->GetEMCON() != desired_emcon)
        ship->SetEMCON(desired_emcon);
    }

    if (orders && orders->Action()) {
        switch (orders->Action()) {
        case RadioMessage::ATTACK:
        case RadioMessage::BRACKET:
        case RadioMessage::IDENTIFY:
            {
                bool        tgt_ok   = false;
                SimObject*  tgt      = orders->GetTarget();

                if (tgt && tgt->Type() == SimObject::SIM_SHIP) {
                    Ship* tgt_ship = (Ship*) tgt;

                    if (CanTarget(tgt_ship)) {
                        roe = DIRECTED;
                        SelectTargetDirected((Ship*) tgt);

                        ship_ai->SetBracket(orders->Action() == RadioMessage::BRACKET);
                        ship_ai->SetIdentify(orders->Action() == RadioMessage::IDENTIFY);
                        ship_ai->SetNavPoint(0);

                        tgt_ok = true;
                    }
                }

                if (!tgt_ok)
                ClearRadioOrders();
            }
            break;

        case RadioMessage::ESCORT:
        case RadioMessage::COVER_ME:
            {
                SimObject* tgt = orders->GetTarget();
                if (tgt && tgt->Type() == SimObject::SIM_SHIP) {
                    roe = DEFENSIVE;
                    ship_ai->SetWard((Ship*) tgt);
                    ship_ai->SetNavPoint(0);
                }
                else {
                    ClearRadioOrders();
                }
            }
            break;

        case RadioMessage::WEP_FREE:
            roe = AGRESSIVE;
            ship_ai->DropTarget(0.1);
            break;

        case RadioMessage::WEP_HOLD:
        case RadioMessage::FORM_UP:
            roe = NONE;
            ship_ai->DropTarget(5);
            break;

        case RadioMessage::MOVE_PATROL:
            roe = SELF_DEFENSIVE;
            ship_ai->SetPatrol(orders->Location());
            ship_ai->SetNavPoint(0);
            ship_ai->DropTarget(Random(5, 10));
            break;

        case RadioMessage::RTB:
        case RadioMessage::DOCK_WITH:
            roe = NONE;

            ship_ai->DropTarget(10);
            
            if (!ship->GetInbound()) {
                RadioMessage* msg = 0;
                Ship* controller = ship->GetController();

                if (orders->Action() == RadioMessage::DOCK_WITH && orders->GetTarget()) {
                    controller = (Ship*) orders->GetTarget();
                }

                if (!controller) {
                    Element* elem = ship->GetElement();
                    if (elem && elem->GetCommander()) {
                        Element* cmdr = elem->GetCommander();
                        controller    = cmdr->GetShip(1);
                    }
                }

                if (controller && controller->GetHangar() &&
                        controller->GetHangar()->CanStow(ship)) {
                    SimRegion*  self_rgn = ship->GetRegion();
                    SimRegion*  rtb_rgn  = controller->GetRegion();

                    if (self_rgn == rtb_rgn) {
                        double range = Point(controller->Location() - ship->Location()).length();

                        if (range < 50e3) {
                            msg = new(__FILE__,__LINE__) RadioMessage(controller, ship, RadioMessage::CALL_INBOUND);
                            RadioTraffic::Transmit(msg);
                        }
                    }
                }
                else {
                    ship->ClearRadioOrders();
                }

                ship_ai->SetNavPoint(0);
            }
            break;

        case RadioMessage::QUANTUM_TO:
        case RadioMessage::FARCAST_TO:
            roe = NONE;
            ship_ai->DropTarget(10);
            break;

        }

        action = orders->Action();
        return true;
    }

    // if we had an action before, this must be a "cancel orders" 
    else if (action) {
        ClearRadioOrders();
    }

    return false;
}
コード例 #6
0
bool
MissionEvent::CheckTrigger()
{
	Sim* sim = Sim::GetSim();

	if (time > 0 && time > sim->MissionClock())
	return false;

	switch (trigger) {
	case TRIGGER_TIME: {
			if (time <= sim->MissionClock())
			Activate();
		}
		break;

	case TRIGGER_DAMAGE: {
			Ship* ship = sim->FindShip(trigger_ship);
			if (ship) {
				double damage = 100.0 * (ship->Design()->integrity - ship->Integrity()) /
				(ship->Design()->integrity);
				
				if (damage >= trigger_param[0])
				Activate();
			}
		}
		break;

	case TRIGGER_DETECT: {
			Ship* ship = sim->FindShip(trigger_ship);
			Ship* tgt  = sim->FindShip(trigger_target);
			
			if (ship && tgt) {
				if (ship->FindContact(tgt))
				Activate();
			}
			else {
				Skip();
			}
		}
		break;

	case TRIGGER_RANGE: {
			Ship* ship = sim->FindShip(trigger_ship);
			Ship* tgt  = sim->FindShip(trigger_target);
			
			if (ship && tgt) {
				double range     = (ship->Location() - tgt->Location()).length();
				double min_range = 0;
				double max_range = 1e12;

				if (trigger_param[0] > 0)
				min_range = trigger_param[0];
				else
				max_range = -trigger_param[0];

				if (range < min_range || range > max_range)
				Activate();
			}
			else {
				Skip();
			}
		}
		break;

	case TRIGGER_SHIPS_LEFT: {
			int alive   = 0;
			int count   = 0;
			int iff     = -1;
			int nparams = NumTriggerParams();

			if (nparams > 0) count = TriggerParam(0);
			if (nparams > 1) iff   = TriggerParam(1);

			ListIter<SimRegion> iter = sim->GetRegions();
			while (++iter) {
				SimRegion* rgn = iter.value();

				ListIter<Ship> s_iter = rgn->Ships();
				while (++s_iter) {
					Ship* ship = s_iter.value();

					if (ship->Type() >= Ship::STATION)
					continue;

					if (ship->Life() == 0 && ship->RespawnCount() < 1)
					continue;

					if (iff < 0 || ship->GetIFF() == iff)
					alive++;
				}
			}

			if (alive <= count)
			Activate();
		}
		break;

	case TRIGGER_EVENT_ALL: {
			bool  all     = true;
			int   nparams = NumTriggerParams();
			for (int i = 0; all && i < nparams; i++) {
				int trigger_id = TriggerParam(i);

				ListIter<MissionEvent> iter = sim->GetEvents();
				while (++iter) {
					MissionEvent* e = iter.value();
					if (e->EventID() == trigger_id) {
						if (e->Status() != COMPLETE)
						all = false;
						break;
					}

					else if (e->EventID() == -trigger_id) {
						if (e->Status() == COMPLETE)
						all = false;
						break;
					}
				}
			}

			if (all)
			Activate();
		}
		break;

	case TRIGGER_EVENT_ANY: {
			bool  any     = false;
			int   nparams = NumTriggerParams();
			for (int i = 0; !any && i < nparams; i++) {
				int trigger_id = TriggerParam(i);

				ListIter<MissionEvent> iter = sim->GetEvents();
				while (++iter) {
					MissionEvent* e = iter.value();
					if (e->EventID() == trigger_id) {
						if (e->Status() == COMPLETE)
						any = true;
						break;
					}
				}
			}

			if (any)
			Activate();
		}
		break;
	}

	return status == ACTIVE;
}
コード例 #7
0
void
FltDlg::OnMissionType(AWEvent* event)
{
	mission_type = -1;

	for (int i = 0; i < 6; i++) {
		if (mission_btn[i]) {
			if (mission_btn[i] == event->window) {
				mission_btn[i]->SetButtonState(1);
				mission_type = i;
			}
			else {
				mission_btn[i]->SetButtonState(0);
			}
		}
	}

	if (objective_list && mission_type > -1) {
		objective_list->ClearItems();

		char txt[32];
		Sim* sim = Sim::GetSim();
		ListIter<Element> iter = sim->GetElements();

		while (++iter) {
			Element* elem = iter.value();

			if (!elem->IsActive() || elem->IsFinished() || elem->IsSquadron())
			continue;

			CombatGroup*   group = elem->GetCombatGroup();
			int            iff   = elem->GetIFF();
			Ship*          s     = elem->GetShip(1);
			double         r     = 0;
			bool           con   = false;

			if (iff != ship->GetIFF()) {
				if (elem->IntelLevel() < Intel::LOCATED)
				continue;

				if (group && group->IntelLevel() < Intel::LOCATED)
				continue;
			}

			if (s) {
				Point s_loc = s->Location()    + s->GetRegion()->Location();
				Point h_loc = ship->Location() + ship->GetRegion()->Location();

				r = (s_loc - h_loc).length();

				con = ship->FindContact(s) != 0;

				if (con) {
					FormatNumber(txt, r);
				}
				else {
					strcpy_s(txt, Game::GetText("FltDlg.Unknown").data());
					r = 2e9;
				}
			}

			switch (mission_type) {
			case 1:  // INTERCEPT
				if (iff && iff != ship->GetIFF() && s && s->IsDropship()) {
					int item = objective_list->AddItem(elem->Name()) - 1;
					objective_list->SetItemText(item, 1, s->GetRegion()->Name());

					objective_list->SetItemText(item, 2, txt);
					objective_list->SetItemData(item, 2, (DWORD) r);
				}
				break;

			case 2:  // ASSAULT
				if (iff && iff != ship->GetIFF() && s && (s->IsStarship() || s->IsStatic())) {
					int item = objective_list->AddItem(elem->Name()) - 1;
					objective_list->SetItemText(item, 1, s->GetRegion()->Name());

					objective_list->SetItemText(item, 2, txt);
					objective_list->SetItemData(item, 2, (DWORD) r);
				}
				break;

			case 3:  // STRIKE
				if (iff && iff != ship->GetIFF() && s && s->IsGroundUnit()) {
					int item = objective_list->AddItem(elem->Name()) - 1;
					objective_list->SetItemText(item, 1, s->GetRegion()->Name());

					objective_list->SetItemText(item, 2, txt);
					objective_list->SetItemData(item, 2, (DWORD) r);
				}
				break;

			case 4:  // ESCORT
				if ((iff == 0 || iff == ship->GetIFF()) && (!s || !s->IsStatic())) {
					int item = objective_list->AddItem(elem->Name()) - 1;

					if (s) {
						objective_list->SetItemText(item, 1, s->GetRegion()->Name());
						objective_list->SetItemText(item, 2, txt);
						objective_list->SetItemData(item, 2, (DWORD) r);
					}

					else {
						objective_list->SetItemText(item, 1, "0");
						objective_list->SetItemData(item, 1, 0);
					}
				}
				break;

			case 5:  // SCOUT?
				break;

			default: break;
			}
		}
	}

	if (loadout_list && mission_type > -1) {
		loadout_list->ClearItems();

		if (design) {
			ListIter<ShipLoad> sl = (List<ShipLoad>&) design->loadouts;
			while (++sl) {
				int item = loadout_list->AddItem(sl->name) - 1;

				char weight[32];
				sprintf_s(weight, "%d kg", (int) ((design->mass + sl->mass) * 1000));
				loadout_list->SetItemText(item, 1, weight);
				loadout_list->SetItemData(item, 1, (DWORD) (sl->mass * 1000));
			}
		}
	}
}