CombatGroup* CombatGroup::LoadOrderOfBattle(const char* filename, int team, Combatant* combatant) { CombatGroup* force = 0; DataLoader* loader = DataLoader::GetLoader(); BYTE* block; loader->LoadBuffer(filename, block, true); Parser parser(new(__FILE__,__LINE__) BlockReader((const char*) block)); Term* term = parser.ParseTerm(); if (!term) { Print("ERROR: could not parse order of battle '%s'\n", filename); return 0; } else { TermText* file_type = term->isText(); if (!file_type || file_type->value() != "ORDER_OF_BATTLE") { Print("ERROR: invalid Order of Battle file '%s'\n", filename); term->print(10); return 0; } } do { delete term; term = 0; term = parser.ParseTerm(); if (term) { TermDef* def = term->isDef(); if (def) { if (def->name()->value() == "group") { if (!def->term() || !def->term()->isStruct()) { Print("WARNING: group struct missing in '%s'\n", filename); } else { TermStruct* val = def->term()->isStruct(); char name[256]; char type[64]; char intel[64]; char region[64]; char system[64]; char parent_type[64]; int parent_id = 0; int id = 0; int iff = -1; Vec3 loc = Vec3(1.0e9f,0.0f,0.0f); List<CombatUnit> unit_list; char unit_name[64]; char unit_regnum[16]; char unit_design[64]; char unit_skin[64]; int unit_class = 0; int unit_count = 1; int unit_dead = 0; int unit_damage = 0; int unit_heading= 0; int unit_index = 0; *name = 0; *type = 0; *intel = 0; *region = 0; *system = 0; *parent_type = 0; *unit_name = 0; *unit_regnum = 0; *unit_design = 0; *unit_skin = 0; strcpy_s(intel, "KNOWN"); // all groups in this OOB default to the IFF of the main force if (force) iff = force->GetIFF(); for (int i = 0; i < val->elements()->size(); i++) { TermDef* pdef = val->elements()->at(i)->isDef(); if (pdef && (iff < 0 || team < 0 || iff == team)) { GET_DEF_TEXT(name); else GET_DEF_TEXT(type); else GET_DEF_TEXT(intel); else GET_DEF_TEXT(region); else GET_DEF_TEXT(system); else GET_DEF_VEC(loc); else GET_DEF_TEXT(parent_type); else GET_DEF_NUM(parent_id);
void CampaignPlanStrategic::AssignZones(Combatant* c) { // find the list of assignable groups, in priority order: List<CombatGroup> groups; BuildGroupList(c->GetForce(), groups); groups.sort(); // for each group, assign a zone: ListIter<CombatGroup> g_iter = groups; // first pass: fighter and attack squadrons assigned to star bases while (++g_iter) { CombatGroup* g = g_iter.value(); int gtype = g->Type(); if (gtype == CombatGroup::ATTACK_SQUADRON || gtype == CombatGroup::FIGHTER_SQUADRON || gtype == CombatGroup::INTERCEPT_SQUADRON) { CombatGroup* parent = g->GetParent(); if (parent && parent->Type() == CombatGroup::WING) parent = parent->GetParent(); if (!parent || parent->Type() == CombatGroup::CARRIER_GROUP) continue; // these groups are attached to fixed resources, // so they must be assigned to the parent's zone: CombatZone* parent_zone = campaign->GetZone(parent->GetRegion()); if (parent_zone) { ZoneForce* parent_force = parent_zone->FindForce(g->GetIFF()); if (parent_force) { g->SetAssignedZone(parent_zone); parent_force->AddNeed(g->Type(), -(g->Value())); } } } } // second pass: carrier groups g_iter.reset(); while (++g_iter) { CombatGroup* g = g_iter.value(); int gtype = g->Type(); if (gtype == CombatGroup::CARRIER_GROUP) { int current_zone_need = 0; int highest_zone_need = 0; CombatZone* highest_zone = 0; ZoneForce* highest_force = 0; CombatZone* current_zone = 0; ZoneForce* current_force = 0; List<CombatZone> possible_zones; if (g->IsZoneLocked()) { current_zone = g->GetAssignedZone(); current_force = current_zone->FindForce(g->GetIFF()); } else { ListIter<CombatZone> z_iter = campaign->GetZones(); while (++z_iter) { CombatZone* zone = z_iter.value(); ZoneForce* force = zone->FindForce(g->GetIFF()); int need = force->GetNeed(CombatGroup::CARRIER_GROUP) + force->GetNeed(CombatGroup::ATTACK_SQUADRON) + force->GetNeed(CombatGroup::FIGHTER_SQUADRON) + force->GetNeed(CombatGroup::INTERCEPT_SQUADRON); if (g->IsSystemLocked() && zone->System() != g->GetAssignedSystem()) continue; possible_zones.append(zone); if (zone->HasRegion(g->GetRegion())) { current_zone_need = need; current_zone = zone; current_force = force; } if (need > highest_zone_need) { highest_zone_need = need; highest_zone = zone; highest_force = force; } } } CombatZone* assigned_zone = current_zone; ZoneForce* assigned_force = current_force; if (highest_zone_need > current_zone_need) { assigned_zone = highest_zone; assigned_force = highest_force; } // if we couldn't find anything suitable, // just pick a zone at random: if (!assigned_zone) { if (possible_zones.isEmpty()) possible_zones.append(campaign->GetZones()); int nzones = possible_zones.size(); int n = RandomIndex() % nzones; assigned_zone = possible_zones.at(n); assigned_force = assigned_zone->FindForce(g->GetIFF()); } if (assigned_force && assigned_zone) { Text assigned_rgn; if (!campaign->GetZone(g->GetRegion())) { assigned_rgn = *assigned_zone->GetRegions().at(0); g->AssignRegion(assigned_rgn); } g->SetAssignedZone(assigned_zone); assigned_force->AddNeed(g->Type(), -(g->Value())); // also assign the carrier's wing and squadrons to the same zone: ListIter<CombatGroup> squadron = g->GetComponents(); while (++squadron) { squadron->SetAssignedZone(assigned_zone); assigned_force->AddNeed(squadron->Type(), -(squadron->Value())); if (squadron->Type() == CombatGroup::WING) { ListIter<CombatGroup> s = squadron->GetComponents(); while (++s) { s->SetAssignedZone(assigned_zone); assigned_force->AddNeed(s->Type(), -(s->Value())); } } } } } } // third pass: everything else g_iter.reset(); while (++g_iter) { CombatGroup* g = g_iter.value(); int gtype = g->Type(); if (gtype == CombatGroup::BATTLE_GROUP || gtype == CombatGroup::DESTROYER_SQUADRON) { int current_zone_need = 0; int highest_zone_need = 0; CombatZone* highest_zone = 0; ZoneForce* highest_force = 0; CombatZone* current_zone = 0; ZoneForce* current_force = 0; List<CombatZone> possible_zones; if (g->IsZoneLocked()) { current_zone = g->GetAssignedZone(); current_force = current_zone->FindForce(g->GetIFF()); } else { ListIter<CombatZone> z_iter = campaign->GetZones(); while (++z_iter) { CombatZone* zone = z_iter.value(); ZoneForce* force = zone->FindForce(g->GetIFF()); int need = force->GetNeed(g->Type()); if (g->IsSystemLocked() && zone->System() != g->GetAssignedSystem()) continue; possible_zones.append(zone); // battle groups can do double-duty: if (gtype == CombatGroup::BATTLE_GROUP) need += force->GetNeed(CombatGroup::DESTROYER_SQUADRON); if (zone->HasRegion(g->GetRegion())) { current_zone_need = need; current_zone = zone; current_force = force; } if (need > highest_zone_need) { highest_zone_need = need; highest_zone = zone; highest_force = force; } } } if (highest_zone_need > current_zone_need) { g->SetAssignedZone(highest_zone); if (highest_force) highest_force->AddNeed(g->Type(), -(g->Value())); } else { if (!current_zone) { if (possible_zones.isEmpty()) possible_zones.append(campaign->GetZones()); int nzones = possible_zones.size(); int n = RandomIndex() % nzones; current_zone = possible_zones.at(n); current_force = current_zone->FindForce(g->GetIFF()); } g->SetAssignedZone(current_zone); if (current_force) current_force->AddNeed(g->Type(), -(g->Value())); Text assigned_rgn; if (!campaign->GetZone(g->GetRegion())) { assigned_rgn = *current_zone->GetRegions().at(0); g->AssignRegion(assigned_rgn); } } } } }