/// Gibt eine Liste mit möglichen Verbindungen zurück void nobHarborBuilding::GetShipConnections(std::vector<ShipConnection>& connections) const { // Is there any harbor building at all? (could be destroyed)? if(gwg->GetGOT(this->x,this->y) !=GOT_NOB_HARBORBUILDING) // Then good-bye return; // Is the harbor being destroyed right now? if (IsBeingDestroyedNow()) return; std::vector<nobHarborBuilding*> harbor_buildings; for(unsigned short sea_id = 0;sea_id<6;++sea_id) { if(sea_ids[sea_id] != 0) players->getElement(player)->GetHarborBuildings(harbor_buildings,sea_ids[sea_id]); } for(unsigned i = 0;i<harbor_buildings.size();++i) { ShipConnection sc; sc.dest = harbor_buildings[i]; // Als Kantengewicht nehmen wir die doppelte Entfernung (evtl muss ja das Schiff erst kommen) // plus einer Kopfpauschale (Ein/Ausladen usw. dauert ja alles) sc.way_costs = 2*gwg->CalcHarborDistance(GetHarborPosID(),harbor_buildings[i]->GetHarborPosID()) + 10; connections.push_back(sc); } }
/// Gibt eine Liste mit möglichen Verbindungen zurück std::vector<nobHarborBuilding::ShipConnection> nobHarborBuilding::GetShipConnections() const { std::vector<ShipConnection> connections; // Is the harbor being destroyed right now? Could happen due to pathfinding for wares that get notified about this buildings destruction if (IsBeingDestroyedNow()) return connections; // Should already be handled by the above check, but keep the runtime check for now (TODO: remove runtime check) RTTR_Assert(gwg->GetGOT(pos) == GOT_NOB_HARBORBUILDING); // Is there any harbor building at all? (could be destroyed)? if(gwg->GetGOT(pos) != GOT_NOB_HARBORBUILDING) return connections; std::vector<nobHarborBuilding*> harbor_buildings; for(unsigned short sea_id = 0; sea_id < 6; ++sea_id) { if(sea_ids[sea_id] != 0) gwg->GetPlayer(player).GetHarborBuildings(harbor_buildings, sea_ids[sea_id]); } for(unsigned i = 0; i < harbor_buildings.size(); ++i) { ShipConnection sc; sc.dest = harbor_buildings[i]; // Als Kantengewicht nehmen wir die doppelte Entfernung (evtl muss ja das Schiff erst kommen) // plus einer Kopfpauschale (Ein/Ausladen usw. dauert ja alles) sc.way_costs = 2 * gwg->CalcHarborDistance(GetHarborPosID(), harbor_buildings[i]->GetHarborPosID()) + 10; connections.push_back(sc); } return connections; }
/// Gibt die Angreifergebäude zurück, die dieser Hafen für einen Seeangriff zur Verfügung stellen kann void nobHarborBuilding::GetAttackerBuildingsForSeaAttack(std::vector<SeaAttackerBuilding> * buildings, const std::vector<unsigned>& defender_harbors) { std::list<nobBaseMilitary*> all_buildings; gwg->LookForMilitaryBuildings(all_buildings,x,y,3); // Und zählen for(std::list<nobBaseMilitary*>::iterator it = all_buildings.begin();it!=all_buildings.end();++it) { if((*it)->GetGOT() != GOT_NOB_MILITARY) continue; // Liegt er auch im groben Raster und handelt es sich um den gleichen Besitzer? if((*it)->GetPlayer() != player || gwg->CalcDistance((*it)->GetX(),(*it)->GetY(),x,y) > BASE_ATTACKING_DISTANCE) continue; // Weg vom Hafen zum Militärgebäude berechnen if(!gwg->FindFreePath((*it)->GetX(),(*it)->GetY(),x,y,false,MAX_ATTACKING_RUN_DISTANCE,NULL,NULL,NULL,NULL,NULL,NULL,false)) continue; // Entfernung zwischen Hafen und möglichen Zielhafenpunkt ausrechnen unsigned min_distance = 0xffffffff; for(unsigned i = 0;i<defender_harbors.size();++i) { min_distance = min(min_distance, gwg->CalcHarborDistance(GetHarborPosID(),defender_harbors.at(i))); } // Gebäude suchen, vielleicht schon vorhanden? std::vector<SeaAttackerBuilding>::iterator it2 = std::find(buildings->begin(), buildings->end(), static_cast<nobMilitary*>(*it)); // Noch nicht vorhanden? if(it2 == buildings->end()) { // Dann neu hinzufügen SeaAttackerBuilding sab = { static_cast<nobMilitary*>(*it), this, min_distance }; buildings->push_back(sab); } // Oder vorhanden und jetzige Distanz ist kleiner? else if(min_distance < it2->distance) { // Dann Distanz und betreffenden Hafen aktualisieren it2->distance = min_distance; it2->harbor = this; } } }
/// Schiff ist angekommen void nobHarborBuilding::ShipArrived(noShip* ship) { // get a new job - priority is given according to this list: attack,expedition,exploration,transport // any attackers ready? if(!soldiers_for_ships.empty()) { // load all soldiers that share the same target as the first soldier in the list std::list<noFigure*> attackers; MapPoint ship_dest = soldiers_for_ships.begin()->dest; for(std::list<SoldierForShip>::iterator it = soldiers_for_ships.begin(); it != soldiers_for_ships.end();) { if(it->dest == ship_dest) { inventory.visual.Remove(it->attacker->GetJobType()); attackers.push_back(it->attacker); it = soldiers_for_ships.erase(it); } else ++it; } ship->PrepareSeaAttack(GetHarborPosID(), ship_dest, attackers); return; } //Expedition ready? if(expedition.active && expedition.builder && expedition.boards == BUILDING_COSTS[nation][BLD_HARBORBUILDING].boards && expedition.stones == BUILDING_COSTS[nation][BLD_HARBORBUILDING].stones) { // Aufräumen am Hafen expedition.active = false; // Expedition starten ship->StartExpedition(GetHarborPosID()); return; } // Exploration-Expedition ready? if(IsExplorationExpeditionReady()) { // Aufräumen am Hafen exploration_expedition.active = false; // Expedition starten ship->StartExplorationExpedition(GetHarborPosID()); inventory.visual.Remove(JOB_SCOUT, exploration_expedition.scouts); return; } // Gibt es Waren oder Figuren, die ein Schiff von hier aus nutzen wollen? if(!wares_for_ships.empty() || !figures_for_ships.empty()) { // Das Ziel wird nach der ersten Figur bzw. ersten Ware gewählt // actually since the wares might not yet have informed the harbor that their target harbor was destroyed we pick the first figure/ware with a valid target instead MapPoint dest; bool gotdest = false; for(std::list<FigureForShip>::iterator it = figures_for_ships.begin(); it != figures_for_ships.end(); ++it) { noBase* nb = gwg->GetNO(it->dest); if(nb->GetGOT() == GOT_NOB_HARBORBUILDING && gwg->GetNode(it->dest).owner == player + 1) //target is a harbor and owned by the same player { dest = it->dest; gotdest = true; break; } } for(std::list<Ware*>::iterator it = wares_for_ships.begin(); !gotdest && it != wares_for_ships.end(); ++it) { noBase* nb = gwg->GetNO((*it)->GetNextHarbor()); if(nb->GetGOT() == GOT_NOB_HARBORBUILDING && gwg->GetNode((*it)->GetNextHarbor()).owner == player + 1) { dest = (*it)->GetNextHarbor(); gotdest = true; break; } } if(gotdest) { std::list<noFigure*> figures; // Figuren auswählen, die zu diesem Ziel wollen for(std::list<FigureForShip>::iterator it = figures_for_ships.begin(); it != figures_for_ships.end() && figures.size() < SHIP_CAPACITY;) { if(it->dest == dest) { figures.push_back(it->fig); it->fig->StartShipJourney(); inventory.visual.Remove(it->fig->GetJobType()); it = figures_for_ships.erase(it); } else ++it; } // Und noch die Waren auswählen std::list<Ware*> wares; for(std::list<Ware*>::iterator it = wares_for_ships.begin(); it != wares_for_ships.end() && figures.size() + wares.size() < SHIP_CAPACITY;) { if((*it)->GetNextHarbor() == dest) { wares.push_back(*it); (*it)->StartShipJourney(); inventory.visual.Remove(ConvertShields((*it)->type)); it = wares_for_ships.erase(it); } else ++it; } // Und das Schiff starten lassen ship->PrepareTransport(GetHarborPosID(), dest, figures, wares); } } }