/// returns true when a harborpoint is in SEAATTACK_DISTANCE for figures! bool GameWorldBase::IsAHarborInSeaAttackDistance(const MapPoint pos) const { for(unsigned i = 1; i <= GetNumHarborPoints(); ++i) { if(CalcDistance(pos, GetHarborPoint(i)) < SEAATTACK_DISTANCE) { if(FindHumanPath(pos, GetHarborPoint(i), SEAATTACK_DISTANCE) != 0xff) return true; } } return false; }
std::vector<unsigned short> GameWorldBase::GetFilteredSeaIDsForAttack(const MapPoint targetPt, const std::vector<unsigned short>& usableSeas, const unsigned char player_attacker) const { // Walk to the flag of the bld/harbor. Important to check because in some locations where the coast is north of the harbor this might be // blocked const MapPoint flagPt = GetNeighbour(targetPt, Direction::SOUTHEAST); std::vector<unsigned short> confirmedSeaIds; // Check each possible harbor for(unsigned curHbId = 1; curHbId <= GetNumHarborPoints(); ++curHbId) { const MapPoint harborPt = GetHarborPoint(curHbId); if(CalcDistance(harborPt, targetPt) > SEAATTACK_DISTANCE) continue; // Not attacking this harbor and harbors block? if(targetPt != harborPt && GetGGS().getSelection(AddonId::SEA_ATTACK) == 1) { // Does an enemy harbor exist at current harbor spot? -> Can't attack through this harbor spot const auto* hb = GetSpecObj<nobHarborBuilding>(harborPt); if(hb && GetPlayer(player_attacker).IsAttackable(hb->GetPlayer())) continue; } for(unsigned z = 0; z < 6; ++z) { const unsigned short seaId = GetSeaId(curHbId, Direction::fromInt(z)); if(!seaId) continue; // sea id is not in compare list or already confirmed? -> skip rest if(!helpers::contains(usableSeas, seaId) || helpers::contains(confirmedSeaIds, seaId)) continue; // checks previously tested sea ids to skip pathfinding bool previouslytested = false; for(unsigned k = 0; k < z; k++) { if(seaId == GetSeaId(curHbId, Direction::fromInt(k))) { previouslytested = true; break; } } if(previouslytested) continue; // Can figures reach flag from coast MapPoint coastalPt = GetCoastalPoint(curHbId, seaId); if((flagPt == coastalPt) || FindHumanPath(flagPt, coastalPt, SEAATTACK_DISTANCE) != INVALID_DIR) { confirmedSeaIds.push_back(seaId); // all sea ids confirmed? return without changes if(confirmedSeaIds.size() == usableSeas.size()) return confirmedSeaIds; } } } return confirmedSeaIds; }
unsigned GameWorldBase::GetHarborInDir(const MapPoint pt, const unsigned origin_harborId, const ShipDirection& dir, T_IsHarborOk isHarborOk) const { RTTR_Assert(origin_harborId); // Herausfinden, in welcher Richtung sich dieser Punkt vom Ausgangspunkt unterscheidet unsigned char coastal_point_dir = 0xFF; const MapPoint hbPt = GetHarborPoint(origin_harborId); for(unsigned char i = 0; i < 6; ++i) { if(GetNeighbour(hbPt, Direction::fromInt(i)) == pt) { coastal_point_dir = i; break; } } RTTR_Assert(coastal_point_dir != 0xff); unsigned short seaId = GetSeaId(origin_harborId, Direction::fromInt(coastal_point_dir)); const std::vector<HarborPos::Neighbor>& neighbors = GetHarborNeighbors(origin_harborId, dir); for(auto neighbor : neighbors) { if(IsHarborAtSea(neighbor.id, seaId) && isHarborOk(neighbor.id)) return neighbor.id; } // Nichts gefunden return 0; }
std::vector<unsigned> GameWorldBase::GetUsableTargetHarborsForAttack(const MapPoint targetPt, std::vector<bool>& use_seas, const unsigned char player_attacker) const { // Walk to the flag of the bld/harbor. Important to check because in some locations where the coast is north of the harbor this might be // blocked const MapPoint flagPt = GetNeighbour(targetPt, Direction::SOUTHEAST); std::vector<unsigned> harbor_points; // Check each possible harbor for(unsigned curHbId = 1; curHbId <= GetNumHarborPoints(); ++curHbId) { const MapPoint harborPt = GetHarborPoint(curHbId); if(CalcDistance(harborPt, targetPt) > SEAATTACK_DISTANCE) continue; // Not attacking this harbor and harbors block? if(targetPt != harborPt && GetGGS().getSelection(AddonId::SEA_ATTACK) == 1) { // Does an enemy harbor exist at current harbor spot? -> Can't attack through this harbor spot const auto* hb = GetSpecObj<nobHarborBuilding>(harborPt); if(hb && GetPlayer(player_attacker).IsAttackable(hb->GetPlayer())) continue; } // add seaIds from which we can actually attack the harbor bool harborinlist = false; for(unsigned z = 0; z < 6; ++z) { const unsigned short seaId = GetSeaId(curHbId, Direction::fromInt(z)); if(!seaId) continue; // checks previously tested sea ids to skip pathfinding bool previouslytested = false; for(unsigned k = 0; k < z; k++) { if(seaId == GetSeaId(curHbId, Direction::fromInt(k))) { previouslytested = true; break; } } if(previouslytested) continue; // Can figures reach flag from coast const MapPoint coastalPt = GetCoastalPoint(curHbId, seaId); if((flagPt == coastalPt) || FindHumanPath(flagPt, coastalPt, SEAATTACK_DISTANCE) != INVALID_DIR) { use_seas.at(seaId - 1) = true; if(!harborinlist) { harbor_points.push_back(curHbId); harborinlist = true; } } } } return harbor_points; }
/// Bestimmt für einen beliebigen Punkt auf der Karte die Entfernung zum nächsten Hafenpunkt unsigned GameWorldBase::CalcDistanceToNearestHarbor(const MapPoint pos) const { unsigned min_distance = 0xffffffff; for(unsigned i = 1; i <= GetNumHarborPoints(); ++i) min_distance = std::min(min_distance, this->CalcDistance(pos, GetHarborPoint(i))); return min_distance; }
/// Ist es an dieser Stelle für einen Spieler möglich einen Hafen zu bauen bool GameWorldBase::IsHarborPointFree(const unsigned harborId, const unsigned char player) const { MapPoint hbPos(GetHarborPoint(harborId)); // Überprüfen, ob das Gebiet in einem bestimmten Radius entweder vom Spieler oder gar nicht besetzt ist außer wenn der Hafen und die // Flagge im Spielergebiet liegen MapPoint flagPos = GetNeighbour(hbPos, Direction::SOUTHEAST); if(GetNode(hbPos).owner != player + 1 || GetNode(flagPos).owner != player + 1) { if(CheckPointsInRadius(hbPos, 4, IsPointOwnerDifferent(*this, player), false)) return false; } return GetNode(hbPos).bq == BQ_HARBOR; }
/// Liefert Hafenpunkte im Umkreis von einem bestimmten Militärgebäude std::vector<unsigned> GameWorldBase::GetHarborPointsAroundMilitaryBuilding(const MapPoint pt) const { std::vector<unsigned> harbor_points; // Nach Hafenpunkten in der Nähe des angegriffenen Gebäudes suchen // Alle unsere Häfen durchgehen for(unsigned i = 1; i <= GetNumHarborPoints(); ++i) { const MapPoint harborPt = GetHarborPoint(i); if(CalcDistance(harborPt, pt) <= SEAATTACK_DISTANCE) { // Wird ein Weg vom Militärgebäude zum Hafen gefunden bzw. Ziel = Hafen? if(pt == harborPt) harbor_points.push_back(i); else if(FindHumanPath(pt, harborPt, SEAATTACK_DISTANCE) != 0xff) harbor_points.push_back(i); } } return harbor_points; }
/// Ist es an dieser Stelle für einen Spieler möglich einen Hafen zu bauen bool GameWorldBase::IsHarborPointFree(const unsigned harbor_id, const unsigned char player, const unsigned short sea_id) const { Point<MapCoord> coords(GetHarborPoint(harbor_id)); // Befindet sich der Hafenpunkt auch an dem erforderlichen Meer? bool at_sea = false; for(unsigned i = 0;i<6;++i) { if(harbor_pos[harbor_id].cps[i].sea_id == sea_id) { at_sea = true; break; } } if(!at_sea) return false; // Überprüfen, ob das Gebiet in einem bestimmten Radius entweder vom Spieler oder gar nicht besetzt ist for(MapCoord tx=GetXA(coords.x,coords.y,0), r=1;r<=4;tx=GetXA(tx,coords.y,0),++r) { MapCoord tx2 = tx, ty2 = coords.y; for(unsigned i = 2;i<8;++i) { for(MapCoord r2=0;r2<r;GetPointA(tx2,ty2,i%6),++r2) { unsigned char owner = GetNode(tx2,ty2).owner; if(owner != 0 && owner != player+1) return false; } } } return (CalcBQ(coords.x,coords.y,0,false,false,true) == BQ_HARBOR); }