| 225 | } |
| 226 | |
| 227 | TechnoClass* ScriptExt::FindBestObject(TechnoClass* pTechno, int method, int calcThreatMode, bool pickAllies, int attackAITargetType, int idxAITargetTypeItem) |
| 228 | { |
| 229 | TechnoClass* pBestObject = nullptr; |
| 230 | double bestVal = -1; |
| 231 | HouseClass* pEnemyHouse = nullptr; |
| 232 | const auto pTechnoType = pTechno->GetTechnoType(); |
| 233 | |
| 234 | // Favorite Enemy House case. If set, AI will focus against that House |
| 235 | if (!pickAllies && pTechno->BelongsToATeam()) |
| 236 | { |
| 237 | if (const auto pFoot = abstract_cast<FootClass*>(pTechno)) |
| 238 | { |
| 239 | const auto pTeam = pFoot->Team; |
| 240 | const int enemyHouseIndex = pTeam->FirstUnit->Owner->EnemyHouseIndex; |
| 241 | |
| 242 | if (pTeam->Type->OnlyTargetHouseEnemy && enemyHouseIndex >= 0) |
| 243 | pEnemyHouse = HouseClass::Array.GetItem(enemyHouseIndex); |
| 244 | } |
| 245 | } |
| 246 | |
| 247 | // Generic method for targeting |
| 248 | for (int i = 0; i < TechnoClass::Array.Count; i++) |
| 249 | { |
| 250 | const auto pTarget = TechnoClass::Array.GetItem(i); |
| 251 | |
| 252 | if (pickAllies != pTechno->Owner->IsAlliedWith(pTarget->Owner)) |
| 253 | continue; |
| 254 | |
| 255 | if (pEnemyHouse && pEnemyHouse != pTarget->Owner) |
| 256 | continue; |
| 257 | |
| 258 | // Exclude most of invalid target first |
| 259 | if (!ScriptExt::EvaluateObjectWithMask(pTarget, method, attackAITargetType, idxAITargetTypeItem, pTechno)) |
| 260 | continue; |
| 261 | |
| 262 | const auto pTargetType = pTarget->GetTechnoType(); |
| 263 | |
| 264 | // Discard invisible structures |
| 265 | const auto pTargetBuildingType = abstract_cast<BuildingTypeClass*, true>(pTargetType); |
| 266 | |
| 267 | if (pTargetBuildingType && pTargetBuildingType->InvisibleInGame) |
| 268 | continue; |
| 269 | |
| 270 | if (pTarget == pTechno) |
| 271 | continue; |
| 272 | |
| 273 | if (pTargetType->Naval) |
| 274 | { |
| 275 | // Submarines aren't a valid target |
| 276 | if (pTarget->CloakState == CloakState::Cloaked |
| 277 | && pTargetType->Underwater) |
| 278 | { |
| 279 | const auto navalTargeting = pTechnoType->NavalTargeting; |
| 280 | |
| 281 | if (navalTargeting == NavalTargetingType::Underwater_Never |
| 282 | || navalTargeting == NavalTargetingType::Naval_None) |
| 283 | { |
| 284 | continue; |
nothing calls this directly
no test coverage detected