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)); } } } }
bool CombatAction::IsAvailable() const { CombatAction* pThis = (CombatAction*) this; if (rval < 0) { pThis->rval = (int) Random(0, 100); if (rval > probability) pThis->status = SKIPPED; } if (status != PENDING) return false; if (min_rank > 0 || max_rank < 100) { Player* player = Player::GetCurrentPlayer(); if (player->Rank() < min_rank || player->Rank() > max_rank) return false; } Campaign* campaign = Campaign::GetCampaign(); if (campaign) { if (campaign->GetTime() < start_after) { return false; } if (campaign->GetTime() > start_before) { pThis->status = FAILED; // too late! return false; } // check requirements against actions in current campaign: ListIter<CombatActionReq> iter = pThis->requirements; while (++iter) { CombatActionReq* r = iter.value(); bool ok = false; if (r->action > 0) { ListIter<CombatAction> action = campaign->GetActions(); while (++action) { CombatAction* a = action.value(); if (a->Identity() == r->action) { if (r->not) { if (a->Status() == r->stat) return false; } else { if (a->Status() != r->stat) return false; } } } } // group-based requirement else if (r->group_type > 0) { if (r->c1) { CombatGroup* group = r->c1->FindGroup(r->group_type, r->group_id); if (group) { int test = 0; int comp = 0; if (r->intel) { test = group->IntelLevel(); comp = r->intel; } else { test = group->CalcValue(); comp = r->score; } switch (r->comp) { case CombatActionReq::LT: ok = (test < comp); break; case CombatActionReq::LE: ok = (test <= comp); break; case CombatActionReq::GT: ok = (test > comp); break; case CombatActionReq::GE: ok = (test >= comp); break; case CombatActionReq::EQ: ok = (test == comp); break; } } if (!ok) return false; } } // score-based requirement else { int test = 0; if (r->comp <= CombatActionReq::EQ) { // absolute if (r->c1) { int test = r->c1->Score(); switch (r->comp) { case CombatActionReq::LT: ok = (test < r->score); break; case CombatActionReq::LE: ok = (test <= r->score); break; case CombatActionReq::GT: ok = (test > r->score); break; case CombatActionReq::GE: ok = (test >= r->score); break; case CombatActionReq::EQ: ok = (test == r->score); break; } } } else { // relative if (r->c1 && r->c2) { int test = r->c1->Score() - r->c2->Score(); switch (r->comp) { case CombatActionReq::RLT: ok = (test < r->score); break; case CombatActionReq::RLE: ok = (test <= r->score); break; case CombatActionReq::RGT: ok = (test > r->score); break; case CombatActionReq::RGE: ok = (test >= r->score); break; case CombatActionReq::REQ: ok = (test == r->score); break; } } } if (!ok) return false; } if (delay > 0) { pThis->start_after = (int) campaign->GetTime() + delay; pThis->delay = 0; return IsAvailable(); } } } return true; }
void CampaignPlanMovement::MoveUnit(CombatUnit* u) { if (u) { // starship repair: double damage = u->GetSustainedDamage(); if (damage > 0 && u->GetDesign()) { int percent = (int) (100 * damage / u->GetDesign()->integrity); if (percent > 50) { u->SetSustainedDamage(0.90 * damage); } } Point loc = u->Location(); Point dir = loc; double dist = dir.Normalize(); const double MAX_RAD = 320e3; const double MIN_DIST = 150e3; if (dist < MAX_RAD) { double scale = 1 - dist/MAX_RAD; loc += dir * (Random(30e3, 90e3) * scale) + RandomDirection() * 10e3; if (fabs(loc.z) > 20e3) loc.z *= 0.1; u->MoveTo(loc); CombatGroup* g = u->GetCombatGroup(); if (g && g->Type() > CombatGroup::FLEET && g->GetFirstUnit() == u) { g->MoveTo(loc); if (g->IntelLevel() > Intel::KNOWN) g->SetIntelLevel(Intel::KNOWN); } } else if (dist > 1.25 * MAX_RAD) { double scale = 1 - dist/MAX_RAD; loc += dir * (Random(80e3, 120e3) * scale) + RandomDirection() * 3e3; if (fabs(loc.z) > 20e3) loc.z *= 0.1; u->MoveTo(loc); CombatGroup* g = u->GetCombatGroup(); if (g && g->Type() > CombatGroup::FLEET && g->GetFirstUnit() == u) { g->MoveTo(loc); if (g->IntelLevel() > Intel::KNOWN) g->SetIntelLevel(Intel::KNOWN); } } else { loc += RandomDirection() * 30e3; if (fabs(loc.z) > 20e3) loc.z *= 0.1; u->MoveTo(loc); CombatGroup* g = u->GetCombatGroup(); if (g && g->Type() > CombatGroup::FLEET && g->GetFirstUnit() == u) { g->MoveTo(loc); if (g->IntelLevel() > Intel::KNOWN) g->SetIntelLevel(Intel::KNOWN); } } CombatUnit* closest_unit = 0; double closest_dist = 1e6; ListIter<CombatUnit> iter = all_units; while (++iter) { CombatUnit* unit = iter.value(); if (unit->GetCombatGroup() != u->GetCombatGroup() && unit->GetRegion() == u->GetRegion() && !unit->IsDropship()) { Point delta = loc - unit->Location(); dist = delta.Normalize(); if (dist < closest_dist) { closest_unit = unit; closest_dist = dist; } } } if (closest_unit && closest_dist < MIN_DIST) { Point delta = loc - closest_unit->Location(); dist = delta.Normalize(); loc += delta * 1.1 * (MIN_DIST - closest_dist); if (fabs(loc.z) > 20e3) loc.z *= 0.1; u->MoveTo(loc); CombatGroup* g = u->GetCombatGroup(); if (g && g->Type() > CombatGroup::FLEET && g->GetFirstUnit() == u) { g->MoveTo(loc); if (g->IntelLevel() > Intel::KNOWN) g->SetIntelLevel(Intel::KNOWN); } } } }