@@ -165,29 +165,28 @@ nofAttacker* nobBaseMilitary::FindAggressor(nofAggressiveDefender& defender)
165165
166166MapPoint nobBaseMilitary::FindAnAttackerPlace (unsigned short & ret_radius, const nofAttacker& soldier)
167167{
168- const MapPoint flagPos = world->GetNeighbour (pos, Direction::SouthEast);
168+ const MapPoint flagPos = GetFlagPos ();
169+ const MapPoint soldierPos = soldier.GetPos ();
169170
170- // Diesen Flaggenplatz nur nehmen, wenn es auch nich gerade eingenommen wird, sonst gibts Deserteure!
171- // Eigenommen werden können natürlich nur richtige Militärgebäude
172- bool capturing =
173- ( BuildingProperties::IsMilitary (bldType_)) ? ( static_cast <nobMilitary*>(this )->IsBeingCaptured ()) : false ;
171+ // Only consider the flag position for fighting if the building isn't currently being captured.
172+ // Only "real" military buildings can be captured
173+ const bool capturing =
174+ BuildingProperties::IsMilitary (bldType_) && static_cast <nobMilitary*>(this )->IsBeingCaptured ();
174175
175- if (!capturing && world->IsValidPointForFighting (flagPos, soldier, false ))
176+ // Also check if we can reach this.
177+ // If not, still consider the other points as the flag could become reachable by then.
178+ if (!capturing && world->IsValidPointForFighting (flagPos, soldier, false )
179+ && (soldierPos == flagPos || world->FindHumanPath (soldierPos, flagPos) != boost::none))
176180 {
177181 ret_radius = 0 ;
178182 return flagPos;
179183 }
180184
181- const MapPoint soldierPos = soldier.GetPos ();
182- // Get points AROUND the flag. Never AT the flag
183- const auto nodes = world->GetPointsInRadius (flagPos, 3 , ReturnMapPointWithRadius{});
184-
185- // Weg zu allen möglichen Punkten berechnen und den mit den kürzesten Weg nehmen
186- // Die bisher kürzeste gefundene Länge
185+ // Check all points around the flag and take shortest
187186 unsigned min_length = std::numeric_limits<unsigned >::max ();
188187 MapPoint minPt = MapPoint::Invalid ();
189188 ret_radius = 100 ;
190- for (const auto & node : nodes )
189+ for (const auto & node : world-> GetPointsInRadius (flagPos, 3 , ReturnMapPointWithRadius{}) )
191190 {
192191 // We found a point with a better radius
193192 if (node.second > ret_radius)
@@ -196,18 +195,18 @@ MapPoint nobBaseMilitary::FindAnAttackerPlace(unsigned short& ret_radius, const
196195 if (!world->ValidWaitingAroundBuildingPoint (node.first , pos))
197196 continue ;
198197
199- // Derselbe Punkt? Dann können wir gleich abbrechen, finden ja sowieso keinen kürzeren Weg mehr
198+ // If this is where the soldier currently is, it is already the shortest possible distance
200199 if (soldierPos == node.first )
201200 {
202201 ret_radius = node.second ;
203202 return node.first ;
204203 }
205204
206205 unsigned length = 0 ;
207- // Gültiger Weg gefunden
206+ // Is there a path at all?
208207 if (world->FindHumanPath (soldierPos, node.first , 100 , false , &length))
209208 {
210- // Kürzer als bisher kürzester Weg? --> Dann nehmen wir diesen Punkt (vorerst)
209+ // Take if shorter
211210 if (length < min_length)
212211 {
213212 minPt = node.first ;
@@ -252,30 +251,30 @@ bool nobBaseMilitary::CallDefender(nofAttacker& attacker)
252251
253252nofAttacker* nobBaseMilitary::FindAttackerNearBuilding ()
254253{
255- // Alle angreifenden Soldaten durchgehen
256- // Den Soldaten, der am nächsten dran steht, nehmen
257254 nofAttacker* best_attacker = nullptr ;
258- unsigned best_radius = 0xFFFFFFFF ;
259-
260- for (auto * aggressor : aggressors)
255+ do
261256 {
262- // Ist der Soldat überhaupt bereit zum Kämpfen (also wartet er um die Flagge herum oder rückt er nach)?
263- if (aggressor->IsAttackerReady ())
257+ // Call the closest attacker to fight the defender
258+ best_attacker = nullptr ;
259+ unsigned best_radius = 0xFFFFFFFF ;
260+ for (auto * aggressor : aggressors)
264261 {
265- // Besser als bisher bester?
266- if (aggressor->GetRadius () < best_radius || !best_attacker )
262+ // Only consider those waiting around the flag, otherwise the defender could go/stay inside
263+ if (aggressor->IsAttackerReady () )
267264 {
268- best_attacker = aggressor;
269- best_radius = best_attacker->GetRadius ();
265+ if (!best_attacker || aggressor->GetRadius () < best_radius)
266+ {
267+ best_attacker = aggressor;
268+ best_radius = aggressor->GetRadius ();
269+ }
270270 }
271271 }
272- }
273-
274- if (best_attacker)
275- best_attacker->AttackDefenderAtFlag ();
276-
277- // und ihn zurückgeben, wenns keine gibt, natürlich 0
278- return best_attacker;
272+ // Return the attacker if found and he starts attacking, else try again
273+ // The current one will be removed from aggressors or not be ready again
274+ if (best_attacker && best_attacker->AttackDefenderAtFlag ())
275+ return best_attacker;
276+ } while (best_attacker); // Stop if we didn't found any attacker at all
277+ return nullptr ;
279278}
280279
281280void nobBaseMilitary::CheckArrestedAttackers ()
0 commit comments