Hooks
static bool BeforeCvTacticalAI_FindUnitsForThisMove(CvTacticalAI* self, TacticalAIMoveTypes eMove, CvPlot* pTarget, int iNumTurnsAway, bool bRangedOnly, bool& result);static void AfterCvTacticalAI_FindUnitsForThisMove(CvTacticalAI* self, TacticalAIMoveTypes eMove, CvPlot* pTarget, int iNumTurnsAway, bool bRangedOnly, bool& result);static bool ReplaceCvTacticalAI_FindUnitsForThisMove(bool (*original)(CvTacticalAI*, TacticalAIMoveTypes, CvPlot*, int, bool), CvTacticalAI* self, TacticalAIMoveTypes eMove, CvPlot* pTarget, int iNumTurnsAway, bool bRangedOnly);CivRegisterBefore<CivHooks::CvTacticalAI_FindUnitsForThisMove>(host, &BeforeCvTacticalAI_FindUnitsForThisMove);CivRegisterAfter<CivHooks::CvTacticalAI_FindUnitsForThisMove>(host, &AfterCvTacticalAI_FindUnitsForThisMove);CivRegisterReplace<CivHooks::CvTacticalAI_FindUnitsForThisMove>(host, &ReplaceCvTacticalAI_FindUnitsForThisMove);
Code
8933/// Finds both high and normal priority units we can use for this move (returns true if at least 1 unit found)8934bool CvTacticalAI::FindUnitsForThisMove(TacticalAIMoveTypes eMove, CvPlot* pTarget, int iNumTurnsAway /* = -1 if any distance okay */, bool bRangedOnly)8935{8936 UnitHandle pLoopUnit;8937 bool rtnValue = false;89388939 list<int>::iterator it;8940 m_CurrentMoveUnits.clear();8941 m_CurrentMoveHighPriorityUnits.clear();89428943 // Loop through all units available to tactical AI this turn8944 for(it = m_CurrentTurnUnits.begin(); it != m_CurrentTurnUnits.end(); it++)8945 {8946 pLoopUnit = m_pPlayer->getUnit(*it);8947 if(pLoopUnit && pLoopUnit->getDomainType() != DOMAIN_AIR && pLoopUnit->IsCombatUnit())8948 {8949 // Make sure domain matches8950 if(pLoopUnit->getDomainType() == DOMAIN_SEA && !pTarget->isWater() ||8951 pLoopUnit->getDomainType() == DOMAIN_LAND && pTarget->isWater())8952 {8953 continue;8954 }89558956 bool bSuitableUnit = false;8957 bool bHighPriority = false;89588959 if(eMove == (TacticalAIMoveTypes)m_CachedInfoTypes[eTACTICAL_GARRISON_ALREADY_THERE] ||8960 eMove == (TacticalAIMoveTypes)m_CachedInfoTypes[eTACTICAL_GARRISON_1_TURN])8961 {8962 // Want to put ranged units in cities to give them a ranged attack8963 if(pLoopUnit->isRanged())8964 {8965 bSuitableUnit = true;8966 bHighPriority = true;8967 }89688969 else if(bRangedOnly)8970 {8971 continue;8972 }89738974 // Don't put units with a combat strength boosted from promotions in cities, these boosts are ignored8975 if(pLoopUnit->getDefenseModifier() == 0 &&8976 pLoopUnit->getAttackModifier() == 0 &&8977 pLoopUnit->getExtraCombatPercent() == 0)8978 {8979 bSuitableUnit = true;8980 }8981 }89828983 else if(eMove == (TacticalAIMoveTypes)m_CachedInfoTypes[eTACTICAL_GUARD_IMPROVEMENT_ALREADY_THERE] ||8984 eMove == (TacticalAIMoveTypes)m_CachedInfoTypes[eTACTICAL_GUARD_IMPROVEMENT_1_TURN] ||8985 eMove == (TacticalAIMoveTypes)m_CachedInfoTypes[eTACTICAL_BASTION_ALREADY_THERE] ||8986 eMove == (TacticalAIMoveTypes)m_CachedInfoTypes[eTACTICAL_BASTION_1_TURN])8987 {8988 // No ranged units or units without defensive bonuses as plot defenders8989 if(!pLoopUnit->isRanged() && !pLoopUnit->noDefensiveBonus())8990 {8991 bSuitableUnit = true;89928993 // Units with defensive promotions are especially valuable8994 if(pLoopUnit->getDefenseModifier() > 0 || pLoopUnit->getExtraCombatPercent() > 0)8995 {8996 bHighPriority = true;8997 }8998 }8999 }90009001 else if(eMove == (TacticalAIMoveTypes)m_CachedInfoTypes[eTACTICAL_ANCIENT_RUINS])9002 {9003 // Fast movers are top priority9004 if(pLoopUnit->getUnitInfo().GetUnitAIType(UNITAI_FAST_ATTACK))9005 {9006 bSuitableUnit = true;9007 bHighPriority = true;9008 }9009 else if(pLoopUnit->IsCanAttack())9010 {9011 bSuitableUnit = true;9012 }9013 }90149015 if(bSuitableUnit)9016 {9017 // Is it even possible for the unit to reach in the number of requested turns (ignoring roads and RR)9018 int iDistance = plotDistance(pLoopUnit->getX(), pLoopUnit->getY(), pTarget->getX(), pTarget->getY());9019 if(pLoopUnit->maxMoves() > 0)9020 {9021 int iMovesPerTurn = pLoopUnit->maxMoves() / GC.getMOVE_DENOMINATOR();9022 int iLeastTurns = (iDistance + iMovesPerTurn - 1) / iMovesPerTurn;9023 if(iNumTurnsAway == -1 || iLeastTurns <= iNumTurnsAway)9024 {9025 // If unit was suitable, and close enough, add it to the proper list9026 int iMoves = TurnsToReachTarget(pLoopUnit, pTarget);9027 if(iMoves != MAX_INT && (iNumTurnsAway == -1 ||9028 (iNumTurnsAway == 0 && pLoopUnit->plot() == pTarget) || iMoves <= iNumTurnsAway))9029 {9030 CvTacticalUnit unit;9031 unit.SetID(pLoopUnit->GetID());9032 unit.SetHealthPercent(pLoopUnit->GetCurrHitPoints(), pLoopUnit->GetMaxHitPoints());9033 unit.SetMovesToTarget(iMoves);90349035 if(bHighPriority)9036 {9037 m_CurrentMoveHighPriorityUnits.push_back(unit);9038 }9039 else9040 {9041 m_CurrentMoveUnits.push_back(unit);9042 }9043 rtnValue = true;9044 }9045 }9046 }9047 }9048 }9049 }90509051 return rtnValue;9052}