171{
172 if (
Player ==
nullptr || Candidates.IsEmpty())
173 {
174 return nullptr;
175 }
176
178 int32 BestNeighborCount = INDEX_NONE;
179 float BestDistanceToClusterCenterSq = TNumericLimits<float>::Max();
180 float BestDistanceToPlayerSq = TNumericLimits<float>::Max();
182 const FVector PlayerLocation =
Player->GetActorLocation();
183
185 {
186 if (Candidate == nullptr)
187 {
188 continue;
189 }
190
191 const FVector CandidateLocation = Candidate->GetTargetedActorLocation();
192 FVector ClusterCenter = FVector::ZeroVector;
193 int32 NeighborCount = 0;
194
196 {
197 if (Other == nullptr)
198 {
199 continue;
200 }
201
202 const FVector OtherLocation = Other->GetTargetedActorLocation();
203
204 if (FVector::DistSquared2D(CandidateLocation, OtherLocation) > DensityRadiusSq)
205 {
206 continue;
207 }
208
209 ClusterCenter += OtherLocation;
210 NeighborCount++;
211 }
212
213 if (NeighborCount <= 0)
214 {
215 continue;
216 }
217
218 ClusterCenter /= static_cast<float>(NeighborCount);
219
220 const float DistanceToClusterCenterSq = FVector::DistSquared2D(CandidateLocation, ClusterCenter);
221 const float DistanceToPlayerSq = FVector::DistSquared2D(CandidateLocation, PlayerLocation);
222 const bool bHasMoreNeighbors = NeighborCount > BestNeighborCount;
223 const bool bCloserToClusterCenter = NeighborCount == BestNeighborCount && DistanceToClusterCenterSq < BestDistanceToClusterCenterSq;
224 const bool bCloserToPlayer = NeighborCount == BestNeighborCount && FMath::IsNearlyEqual(DistanceToClusterCenterSq, BestDistanceToClusterCenterSq) && DistanceToPlayerSq < BestDistanceToPlayerSq;
225
226 if (bHasMoreNeighbors || bCloserToClusterCenter || bCloserToPlayer)
227 {
228 BestTarget = Candidate;
229 BestNeighborCount = NeighborCount;
230 BestDistanceToClusterCenterSq = DistanceToClusterCenterSq;
231 BestDistanceToPlayerSq = DistanceToPlayerSq;
232 }
233 }
234
235 return BestTarget;
236}
float DensityRadius
Definition TargetSelector.h:74