Hooks
static bool BeforeCvTacticalAI_FindClosestUnit(CvTacticalAI* self, CvPlot* pTarget, int iNumTurnsAway, bool bMustHaveHalfHP, bool bMustBeRangedUnit, int iRangeRequired, bool bNeedsIgnoreLOS, bool bMustBeMeleeUnit, bool bIgnoreUnits, CvPlot* pRangedAttackTarget, bool& result);static void AfterCvTacticalAI_FindClosestUnit(CvTacticalAI* self, CvPlot* pTarget, int iNumTurnsAway, bool bMustHaveHalfHP, bool bMustBeRangedUnit, int iRangeRequired, bool bNeedsIgnoreLOS, bool bMustBeMeleeUnit, bool bIgnoreUnits, CvPlot* pRangedAttackTarget, bool& result);static bool ReplaceCvTacticalAI_FindClosestUnit(bool (*original)(CvTacticalAI*, CvPlot*, int, bool, bool, int, bool, bool, bool, CvPlot*), CvTacticalAI* self, CvPlot* pTarget, int iNumTurnsAway, bool bMustHaveHalfHP, bool bMustBeRangedUnit, int iRangeRequired, bool bNeedsIgnoreLOS, bool bMustBeMeleeUnit, bool bIgnoreUnits, CvPlot* pRangedAttackTarget);CivRegisterBefore<CivHooks::CvTacticalAI_FindClosestUnit>(host, &BeforeCvTacticalAI_FindClosestUnit);CivRegisterAfter<CivHooks::CvTacticalAI_FindClosestUnit>(host, &AfterCvTacticalAI_FindClosestUnit);CivRegisterReplace<CivHooks::CvTacticalAI_FindClosestUnit>(host, &ReplaceCvTacticalAI_FindClosestUnit);
Code
9309/// Fills m_CurrentMoveUnits with all units within X turns of a target (returns TRUE if 1 or more found)9310bool CvTacticalAI::FindClosestUnit(CvPlot* pTarget, int iNumTurnsAway, bool bMustHaveHalfHP, bool bMustBeRangedUnit, int iRangeRequired, bool bNeedsIgnoreLOS, bool bMustBeMeleeUnit, bool bIgnoreUnits, CvPlot* pRangedAttackTarget)9311{9312 list<int>::iterator it;9313 UnitHandle pLoopUnit;93149315 bool rtnValue = false;9316 m_CurrentMoveUnits.clear();93179318 // Loop through all units available to tactical AI this turn9319 for(it = m_CurrentTurnUnits.begin(); it != m_CurrentTurnUnits.end(); it++)9320 {9321 pLoopUnit = m_pPlayer->getUnit(*it);9322 if(pLoopUnit)9323 {9324 bool bValidUnit = true;93259326 // don't use non-combat units (but consider embarked for now)9327 if(pLoopUnit->getUnitInfo().GetCombat() == 0)9328 {9329 bValidUnit = false;9330 }93319332#if defined(MOD_UNITS_MAX_HP)9333 else if (bMustHaveHalfHP && (pLoopUnit->getDamage() * 2 > pLoopUnit->GetMaxHitPoints()))9334#else9335 else if (bMustHaveHalfHP && (pLoopUnit->getDamage() * 2 > GC.getMAX_HIT_POINTS()))9336#endif9337 {9338 bValidUnit = false;9339 }93409341 else if(bMustBeRangedUnit && ((pTarget->isWater() && pLoopUnit->getDomainType() == DOMAIN_LAND) ||9342 (!pTarget->isWater() && !pTarget->isCity() && pLoopUnit->getDomainType() == DOMAIN_SEA)))9343 {9344 bValidUnit = false;9345 }93469347 else if(bMustBeRangedUnit && !pLoopUnit->IsCanAttackRanged())9348 {9349 bValidUnit = false;9350 }93519352 else if(bMustBeRangedUnit && pLoopUnit->GetRange() < iRangeRequired)9353 {9354 bValidUnit = false;9355 }93569357 else if(bMustBeRangedUnit && !pLoopUnit->canEverRangeStrikeAt(pRangedAttackTarget->getX(), pRangedAttackTarget->getY()))9358 {9359 bValidUnit = false;9360 }93619362 else if(bMustBeRangedUnit && pLoopUnit->isOutOfAttacks())9363 {9364 bValidUnit = false;9365 }93669367 else if(pRangedAttackTarget != NULL && bMustBeRangedUnit && !IsExpectedToDamageWithRangedAttack(pLoopUnit, pRangedAttackTarget))9368 {9369 bValidUnit = false;9370 }93719372 else if(bNeedsIgnoreLOS && !pLoopUnit->IsRangeAttackIgnoreLOS())9373 {9374 bValidUnit = false;9375 }93769377 else if(bMustBeMeleeUnit && pLoopUnit->IsCanAttackRanged())9378 {9379 bValidUnit = false;9380 }93819382 int iDistance = plotDistance(pLoopUnit->getX(), pLoopUnit->getY(), pTarget->getX(), pTarget->getY());9383 if(iNumTurnsAway == 0 && iDistance > (m_iRecruitRange / 2) || iNumTurnsAway == 1 && iDistance > m_iRecruitRange)9384 {9385 bValidUnit = false;9386 }93879388 if(bValidUnit)9389 {9390 int iTurns = TurnsToReachTarget(pLoopUnit, pTarget, false /*bReusePaths*/, bIgnoreUnits, (iNumTurnsAway==0));9391 if(iTurns <= iNumTurnsAway)9392 {9393 CvTacticalUnit unit;9394 unit.SetID(pLoopUnit->GetID());9395#if defined(MOD_AI_SMART_V3)9396 // Simple trick to sort also by plot distance if is the same turn.9397 int plDistance = plotDistance(pLoopUnit->getX(), pLoopUnit->getY(), pTarget->getX(), pTarget->getY());9398 int iAttachStrength = MOD_AI_SMART_V3 ? (1000 - (iTurns * 20)) - plDistance : 1000-iTurns;9399 unit.SetAttackStrength(iAttachStrength);9400 unit.SetHealthPercent(10,10);9401 unit.SetMovesToTarget(plDistance);9402#else9403 unit.SetAttackStrength(1000-iTurns);9404 unit.SetHealthPercent(10,10);9405 unit.SetMovesToTarget(plotDistance(pLoopUnit->getX(), pLoopUnit->getY(), pTarget->getX(), pTarget->getY()));9406#endif9407 m_CurrentMoveUnits.push_back(unit);9408 rtnValue = true;9409 }9410 }9411 }9412 }94139414 // Now sort them by turns to reach9415 std::stable_sort(m_CurrentMoveUnits.begin(), m_CurrentMoveUnits.end());94169417 return rtnValue;9418}