void
FltDlg::OnAlert(AWEvent* event)
{
	if (!filter_list || !hangar_list || !ship) return;

	int         squad  = filter_list->GetSelectedIndex();
	Hangar*     hangar = ship->GetHangar();
	Sim*        sim    = Sim::GetSim();
	const char* call   = sim->FindAvailCallsign(ship->GetIFF());
	Element*    elem   = sim->CreateElement(call, ship->GetIFF());
	FlightDeck* deck   = 0;
	int         queue  = 1000;
	const int*  load   = 0;

	elem->SetSquadron(hangar->SquadronName(squad));
	elem->SetCarrier(ship);

	for (int i = 0; i < ship->NumFlightDecks(); i++) {
		FlightDeck* d = ship->GetFlightDeck(i);

		if (d && d->IsLaunchDeck()) {
			int dq = hangar->PreflightQueue(d);

			if (dq < queue) {
				queue = dq;
				deck  = d;
			}
		}
	}

	int nalert = 0;
	int slots[4];

	for (int i = 0; i < 4; i++)
	slots[i] = -1;

	for (int i = 0; i < hangar_list->NumItems(); i++) {
		if (hangar_list->IsSelected(i)) {
			int nslot = hangar_list->GetItemData(i);
			slots[nalert] = nslot;

			if (!load) {
				const HangarSlot* hangar_slot = hangar->GetSlot(squad, nslot);
				if (hangar_slot) {
					load = hangar->GetLoadout(hangar_slot);
					elem->SetLoadout((int*) load);
				}
			}

			hangar->GotoAlert(squad, nslot, deck, elem);
			hangar_list->SetSelected(i, false);
			nalert++;

			if (nalert >= 4)
			break;
		}
	}

	NetUtil::SendElemCreate(elem, squad, slots, true);
}
void
CameraDirector::Docking(double seconds)
{
    FlightDeck* dock = ship->GetDock();

    if (!dock) {
        Cockpit(seconds);
        return;
    }

    if (!ship->IsAirborne())
    sim->GetScene()->SetAmbient(Color(120,130,140));
    int flight_phase = ship->GetFlightPhase();

    Point bridge = ship->BridgeLocation();
    Point cloc   = ship->Location()                    +
    ship->Cam().vrt() * bridge.x        +
    ship->Cam().vpn() * bridge.y        +
    ship->Cam().vup() * bridge.z;

    Point cpos   = dock->CamLoc();

    // preflight:
    if (flight_phase < Ship::LOCKED) {
        base_loc = cpos;
    }

    else if (flight_phase == Ship::LOCKED) {
        if (hud)
        hud->SetHUDMode(HUDView::HUD_MODE_TAC);
        cpos = base_loc * transition +
        cloc     * (1-transition);
    }

    // recovery:
    else if (flight_phase > Ship::APPROACH) {
        if (hud)
        hud->SetTacticalMode(1);
    }

    camera.MoveTo(cpos);
    camera.LookAt(cloc);
}
void
NetGameClient::DoElemCreate(NetMsg* msg)
{
	if (!msg) return;

	NetElemCreate elem_create;
	elem_create.Unpack(msg->Data());

	const char* elem_name = elem_create.GetName().data();

	::Print("NetGameClient::DoElemCreate name: %s iff: %d type %s\n",
	elem_name,
	elem_create.GetIFF(),
	Mission::RoleName(elem_create.GetType()));

	Sim*     sim   = Sim::GetSim();
	Element* elem  = sim->FindElement(elem_name);
	if (elem) {
		::Print("  element '%' already exists - ignored\n", elem_name);
		return;
	}

	elem = sim->CreateElement(elem_name,
	elem_create.GetIFF(),
	elem_create.GetType());

	int*     load     = elem_create.GetLoadout();
	int*     slots    = elem_create.GetSlots();
	int      squadron = elem_create.GetSquadron();
	int      code     = elem_create.GetObjCode();
	Text     target   = elem_create.GetObjective();
	bool     alert    = elem_create.GetAlert();
	bool     active   = elem_create.GetInFlight();

	elem->SetIntelLevel(elem_create.GetIntel());
	elem->SetLoadout(load);

	if (code > Instruction::RTB || target.length() > 0) {
		Instruction* obj  = new(__FILE__,__LINE__) Instruction(code, target);
		elem->AddObjective(obj);
	}

	Ship* carrier = sim->FindShip(elem_create.GetCarrier());
	if (carrier) {
		elem->SetCarrier(carrier);

		Hangar* hangar = carrier->GetHangar();
		if (hangar) {
			Text squadron_name = hangar->SquadronName(squadron);
			elem->SetSquadron(squadron_name);

			if (active) {
				for (int i = 0; i < 4; i++) {
					int slot = slots[i];
					if (slot > -1) {
						hangar->GotoActiveFlight(squadron, slot, elem, load);
					}
				}
			}

			else {
				FlightDeck* deck   = 0;
				int         queue  = 1000;

				for (int i = 0; i < carrier->NumFlightDecks(); i++) {
					FlightDeck* d = carrier->GetFlightDeck(i);

					if (d && d->IsLaunchDeck()) {
						int dq = hangar->PreflightQueue(d);

						if (dq < queue) {
							queue = dq;
							deck  = d;
						}
					}
				}

				for (int i = 0; i < 4; i++) {
					int slot = slots[i];
					if (slot > -1) {
						hangar->GotoAlert(squadron, slot, deck, elem, load, !alert);
					}
				}
			}
		}
	}
}
void
FltDlg::OnPackage(AWEvent* event)
{
	if (!filter_list || !hangar_list || !ship) return;

	int         code   = Mission::PATROL;

	switch (mission_type) {
	case 0:  code = Mission::PATROL;       break;
	case 1:  code = Mission::INTERCEPT;    break;
	case 2:  code = Mission::ASSAULT;      break;
	case 3:  code = Mission::STRIKE;       break;
	case 4:  code = Mission::ESCORT;       break;
	case 5:  code = Mission::INTEL;        break;
	}

	int         squad  = filter_list->GetSelectedIndex();
	Hangar*     hangar = ship->GetHangar();
	Sim*        sim    = Sim::GetSim();
	const char* call   = sim->FindAvailCallsign(ship->GetIFF());
	Element*    elem   = sim->CreateElement(call, ship->GetIFF(), code);
	Element*    tgt    = 0;
	FlightDeck* deck   = 0;
	int         queue  = 1000;
	int*        load   = 0;

	elem->SetSquadron(hangar->SquadronName(squad));
	elem->SetCarrier(ship);

	if (objective_list) {
		int   index     = objective_list->GetListIndex();
		Text  target    = objective_list->GetItemText(index);

		Instruction* objective = new(__FILE__,__LINE__) Instruction(code, target.data());
		elem->AddObjective(objective);

		tgt = sim->FindElement(target.data());
	}

	if (loadout_list && design) {
		int   index    = loadout_list->GetListIndex();
		Text  loadname = loadout_list->GetItemText(index);

		ListIter<ShipLoad> sl = (List<ShipLoad>&) design->loadouts;
		while (++sl && !load) {
			if (sl->name == loadname) {
				load = sl->load;
				elem->SetLoadout(load);
			}
		}
	}

	for (int i = 0; i < ship->NumFlightDecks(); i++) {
		FlightDeck* d = ship->GetFlightDeck(i);

		if (d && d->IsLaunchDeck()) {
			int dq = hangar->PreflightQueue(d);
			
			if (dq < queue) {
				queue = dq;
				deck  = d;
			}
		}
	}

	int npackage = 0;
	int slots[6];

	for (int i = 0; i < 6; i++)
	slots[i] = -1;

	for (int i = 0; i < hangar_list->NumItems(); i++) {
		if (hangar_list->IsSelected(i)) {
			int nslot = hangar_list->GetItemData(i);
			hangar->GotoAlert(squad, nslot, deck, elem, load, true);
			slots[npackage] = nslot;
			hangar_list->SetSelected(i, false);
			npackage++;

			if (npackage >= 6)
			break;
		}
	}

	NetUtil::SendElemCreate(elem, squad, slots, false);

	if (flight_planner) {
		switch (mission_type) {
		case 0:
		default:
			flight_planner->CreatePatrolRoute(elem, patrol_pattern++);
			break;

		case 1:
		case 2:
		case 3:
			if (tgt)
			flight_planner->CreateStrikeRoute(elem, tgt);
			else
			flight_planner->CreatePatrolRoute(elem, patrol_pattern++);
			break;

		case 4:
			if (tgt)
			flight_planner->CreateEscortRoute(elem, tgt);
			else
			flight_planner->CreatePatrolRoute(elem, patrol_pattern++);
			break;
		}

		if (patrol_pattern < 0 || patrol_pattern > 3)
		patrol_pattern = 0;
	}
}
void
FltDlg::OnFilter(AWEvent* event)
{
	if (!filter_list || !hangar_list) return;

	int seln = filter_list->GetSelectedIndex();

	hangar_list->ClearItems();

	if (!ship) return;

	Hangar* hangar = ship->GetHangar();

	// selected squadron:
	if (seln < hangar->NumSquadrons()) {
		int         nslots   = hangar->SquadronSize(seln);

		for (int i = 0; i < nslots; i++) {
			char txt[32];
			sprintf_s(txt, " %2d    ", i+1);

			const HangarSlot* s = hangar->GetSlot(seln, i);
			hangar_list->AddItemWithData(txt, i);

			hangar_list->SetItemText(i, 1, "--");
			hangar_list->SetItemText(i, 2, hangar->StatusName(s));

			FormatTime(txt, hangar->TimeRemaining(s));
			hangar_list->SetItemText(i, 4, txt);
		}
	}

	// selected pending filter:
	else if (seln == hangar->NumSquadrons()) {
		int item = 0;

		for (int f = 0; f < ship->NumFlightDecks(); f++) {
			FlightDeck* deck = ship->GetFlightDeck(f);

			if (deck->IsLaunchDeck()) {
				for (int i = 0; i < deck->NumSlots(); i++) {
					int      state    = deck->State(i);
					int      seq      = deck->Sequence(i);
					double   time     = deck->TimeRemaining(i);
					Ship*    deckship = deck->GetShip(i);

					int      squadron = -1;
					int      slot     = -1;

					char txt[32];
					sprintf_s(txt, "%d-%d    ", f+1, i+1);

					hangar_list->AddItemWithData(txt, item); // use data for sort

					if (deckship) {
						hangar_list->SetItemText(item, 1, deckship->Name());

						const HangarSlot* s = 0;

						for (int a = 0; !s && a < hangar->NumSquadrons(); a++) {
							for (int b = 0; !s && b < hangar->SquadronSize(a); b++) {
								const HangarSlot* test = hangar->GetSlot(a, b);
								if (hangar->GetShip(test) == deckship) {
									s          = test;
									squadron   = a;
									slot       = b;
								}
							}
						}

						if (s) {
							hangar_list->SetItemText(item, 2, hangar->StatusName(s));
							if (hangar->GetPackageElement(s))
							hangar_list->SetItemText(item, 3, Mission::RoleName(hangar->GetPackageElement(s)->Type()));
						}
					}
					else {
						hangar_list->SetItemText(item, 1, "--");
						hangar_list->SetItemText(item, 2, Game::GetText("FltDlg.Open"));
					}


					FormatTime(txt, time);
					hangar_list->SetItemText(item, 4, txt);

					hangar_list->SetItemData(item, 1, f);
					hangar_list->SetItemData(item, 2, i);
					hangar_list->SetItemData(item, 3, squadron);
					hangar_list->SetItemData(item, 4, slot);

					item++;
				}
			}
		}
	}

	// selected active filter:
	else if (seln == hangar->NumSquadrons()+1) {
		int item = 0;

		for (int i = 0; i < hangar->NumSquadrons(); i++) {
			int         nslots   = hangar->SquadronSize(i);

			for (int j = 0; j < nslots; j++) {
				const HangarSlot* s = hangar->GetSlot(i,j);

				if (hangar->GetState(s) >= Hangar::ACTIVE) {
					char txt[32];
					sprintf_s(txt, " %2d    ", item+1);

					hangar_list->AddItemWithData(txt, item); // use data for sort

					if (hangar->GetShip(s))
					hangar_list->SetItemText(item, 1, hangar->GetShip(s)->Name());

					hangar_list->SetItemText(item, 2, hangar->StatusName(s));

					if (hangar->GetPackageElement(s))
					hangar_list->SetItemText(item, 3, Mission::RoleName(hangar->GetPackageElement(s)->Type()));

					FormatTime(txt, hangar->TimeRemaining(s));
					hangar_list->SetItemText(item, 4, txt);

					hangar_list->SetItemData(item, 1, i);
					hangar_list->SetItemData(item, 2, j);

					item++;
				}
			}
		}
	}
}
void
FltDlg::UpdateSelection()
{
	if (!filter_list || !hangar_list || !ship) return;

	design   = 0;

	bool        package  = false;
	bool        alert    = false;
	bool        launch   = false;
	bool        stand    = false;
	bool        recall   = false;

	Hangar*     hangar   = ship->GetHangar();
	int         seln     = filter_list->GetSelectedIndex();
	char        txt[32];
	int item;

	// selected squadron:
	if (seln < hangar->NumSquadrons()) {
		int         nslots   = hangar->SquadronSize(seln);

		for (item = 0; item < hangar_list->NumItems(); item++) {
			int i = hangar_list->GetItemData(item);
			const HangarSlot* s = hangar->GetSlot(seln, i);

			if (hangar->GetState(s) == Hangar::UNAVAIL)
			hangar_list->SetItemColor(item, Color::DarkGray);
			else if (hangar->GetState(s) == Hangar::MAINT)
			hangar_list->SetItemColor(item, Color::Gray);
			else
			hangar_list->SetItemColor(item, Color::White);

			if (hangar->GetState(s) > Hangar::STORAGE) {
				if (hangar->GetShip(s))
				hangar_list->SetItemText(item, 1, hangar->GetShip(s)->Name());
				else if (hangar->GetPackageElement(s))
				hangar_list->SetItemText(item, 1, hangar->GetPackageElement(s)->Name());
				else
				hangar_list->SetItemText(item, 1, hangar->SquadronName(seln));

				if (hangar->GetPackageElement(s))
				hangar_list->SetItemText(item, 3, Mission::RoleName(hangar->GetPackageElement(s)->Type()));
				else
				hangar_list->SetItemText(item, 3, "--");

			}
			else {
				hangar_list->SetItemText(item, 1, "--");
				hangar_list->SetItemText(item, 3, "--");
			}

			hangar_list->SetItemText(item, 2, hangar->StatusName(s));

			if (hangar->GetState(s) >= Hangar::ACTIVE) {
				FormatTime(txt, hangar->GetShip(s)->MissionClock() / 1000);
				hangar_list->SetItemText(item, 4, txt);
			}

			else if (hangar->GetState(s) == Hangar::MAINT ||
					hangar->GetState(s) >  Hangar::STORAGE) {
				FormatTime(txt, hangar->TimeRemaining(s));
				hangar_list->SetItemText(item, 4, txt);
			}

			else {
				hangar_list->SetItemText(item, 4, "");
			}

			if (hangar_list->IsSelected(item)) {
				if (!design) design = hangar->GetDesign(s);

				switch (hangar->GetState(s)) {
				case Hangar::STORAGE:      alert  = true; break;
				case Hangar::ALERT:        launch = true; 
					stand  = true; break;
				case Hangar::QUEUED:       stand  = true; break;
				case Hangar::ACTIVE:       recall = true; break;
				}
			}
		}
	}

	// selected pending filter:
	else if (seln == hangar->NumSquadrons()) {
		for (item = 0; item < hangar_list->NumItems(); item++) {
			int f = hangar_list->GetItemData(item, 1);
			int i = hangar_list->GetItemData(item, 2);

			int squadron = -1;
			int slot     = -1;
			const HangarSlot* s = 0;

			FlightDeck* deck        = ship->GetFlightDeck(f);

			if (deck->IsLaunchDeck()) {
				int      state    = deck->State(i);
				int      seq      = deck->Sequence(i);
				double   time     = deck->TimeRemaining(i);
				Ship*    deckship = deck->GetShip(i);

				if (deckship) {
					hangar_list->SetItemText(item, 1, deckship->Name());

					for (int a = 0; !s && a < hangar->NumSquadrons(); a++) {
						for (int b = 0; !s && b < hangar->SquadronSize(a); b++) {
							const HangarSlot* test = hangar->GetSlot(a,b);
							if (hangar->GetShip(test) == deckship) {
								s           = test;
								squadron    = a;
								slot        = b;
							}
						}
					}

					if (s) {
						hangar_list->SetItemText(item, 2, hangar->StatusName(s));
						if (hangar->GetPackageElement(s))
						hangar_list->SetItemText(item, 3, Mission::RoleName(hangar->GetPackageElement(s)->Type()));
					}
				}
				else {
					hangar_list->SetItemText(item, 1, "--");
					hangar_list->SetItemText(item, 2, Game::GetText("FltDlg.Open"));
				}

				FormatTime(txt, time);
				hangar_list->SetItemText(item, 4, txt);
				hangar_list->SetItemData(item, 3, squadron);
				hangar_list->SetItemData(item, 4, slot);

				if (hangar_list->IsSelected(item) && s) {
					if (!design) design = hangar->GetDesign(s);

					switch (hangar->GetState(s)) {
					case Hangar::ALERT:        launch = true; 
						stand  = true; break;
					case Hangar::QUEUED:       stand  = true; break;
					}
				}
			}
		}
	}

	// selected active filter:
	else if (seln == hangar->NumSquadrons()+1) {
		int last_index = -1;

		for (item = 0; item < hangar_list->NumItems(); item++) {
			int squadron = hangar_list->GetItemData(item, 1);
			int slot     = hangar_list->GetItemData(item, 2);

			int         nslots   = hangar->SquadronSize(squadron);

			if (slot >= 0 && slot < nslots) {
				const HangarSlot* s = hangar->GetSlot(squadron, slot);

				if (hangar->GetState(s) > Hangar::STORAGE) {
					if (hangar->GetShip(s))
					hangar_list->SetItemText(item, 1, hangar->GetShip(s)->Name());
					else if (hangar->GetPackageElement(s))
					hangar_list->SetItemText(item, 1, hangar->GetPackageElement(s)->Name());
					else
					hangar_list->SetItemText(item, 1, hangar->SquadronName(squadron));

					if (hangar->GetPackageElement(s))
					hangar_list->SetItemText(item, 3, Mission::RoleName(hangar->GetPackageElement(s)->Type()));
					else
					hangar_list->SetItemText(item, 3, "--");

					hangar_list->SetItemText(item, 2, hangar->StatusName(s));

					FormatTime(txt, hangar->GetShip(s)->MissionClock() / 1000);
					hangar_list->SetItemText(item, 4, txt);

					if (last_index < (int) hangar_list->GetItemData(item))
					last_index = (int) hangar_list->GetItemData(item);
				}
				else {
					hangar_list->RemoveItem(item);
					item--;
				}
			}
			else {
				hangar_list->RemoveItem(item);
				item--;
			}
		}

		for (int i = 0; i < hangar->NumSquadrons(); i++) {
			int         nslots   = hangar->SquadronSize(i);

			for (int j = 0; j < nslots; j++) {
				const HangarSlot* s = hangar->GetSlot(i, j);

				if (hangar->GetState(s) >= Hangar::ACTIVE) {
					bool found = false;

					for (int n = 0; !found && n < hangar_list->NumItems(); n++) {
						if (hangar_list->GetItemData(n, 1) == (DWORD) i &&
								hangar_list->GetItemData(n, 2) == (DWORD) j)
						found = true;
					}

					if (!found) {
						last_index++;

						char txt[32];
						sprintf_s(txt, "%2d    ", last_index+1);
						hangar_list->AddItemWithData(txt, last_index); // use data for sort

						if (hangar->GetShip(s))
						hangar_list->SetItemText(item, 1, hangar->GetShip(s)->Name());

						hangar_list->SetItemText(item, 2, hangar->StatusName(s));

						if (hangar->GetPackageElement(s))
						hangar_list->SetItemText(item, 3, Mission::RoleName(hangar->GetPackageElement(s)->Type()));

						FormatTime(txt, hangar->GetShip(s)->MissionClock() / 1000);
						hangar_list->SetItemText(item, 4, txt);

						hangar_list->SetItemData(item, 1, i);
						hangar_list->SetItemData(item, 2, j);

						item++;
					}
				}
			}
		}

		if (hangar_list->GetSelCount() > 0)
		recall = true;
	}

	if (package_btn) {
		bool pkg_ok = alert && mission_type > -1;

		if (pkg_ok && mission_type > 0) {
			pkg_ok = objective_list    && 
			objective_list->GetSelCount() > 0;

			if (pkg_ok) {
				int   obj_index = objective_list->GetSelection();
				DWORD obj_data  = objective_list->GetItemData(obj_index, 2);

				if (obj_data > 1e9)
				pkg_ok = false;
			}
		}

		package_btn->SetEnabled(pkg_ok);
	}

	if (alert_btn) {
		alert_btn->SetEnabled(alert);

		for (int i = 0; i < 6; i++)
		if (mission_btn[i])
		mission_btn[i]->SetEnabled(alert);
	}

	if (launch_btn)
	launch_btn->SetEnabled(launch);

	if (stand_btn)
	stand_btn->SetEnabled(stand);

	if (recall_btn)
	recall_btn->SetEnabled(recall);
}