Bazaar developer reference

CvTacticalAI::FindUnitsWithinStrikingDistance(CvPlot *, int, int, bool, bool, bool, bool, bool, bool)

Defined in
CvTacticalAI.cpp, line 9055
Class
CvTacticalAI
Hook name
CivHooks::CvTacticalAI_FindUnitsWithinStrikingDistance

Hooks

static bool BeforeCvTacticalAI_FindUnitsWithinStrikingDistance(CvTacticalAI* self, CvPlot* pTarget, int iNumTurnsAway, int iPreferredDamageLevel, bool bNoRangedUnits, bool bNavalOnly, bool bMustMoveThrough, bool bIncludeBlockedUnits, bool bWillPillage, bool bTargetUndefended, bool& result);static void AfterCvTacticalAI_FindUnitsWithinStrikingDistance(CvTacticalAI* self, CvPlot* pTarget, int iNumTurnsAway, int iPreferredDamageLevel, bool bNoRangedUnits, bool bNavalOnly, bool bMustMoveThrough, bool bIncludeBlockedUnits, bool bWillPillage, bool bTargetUndefended, bool& result);static bool ReplaceCvTacticalAI_FindUnitsWithinStrikingDistance(bool (*original)(CvTacticalAI*, CvPlot*, int, int, bool, bool, bool, bool, bool, bool), CvTacticalAI* self, CvPlot* pTarget, int iNumTurnsAway, int iPreferredDamageLevel, bool bNoRangedUnits, bool bNavalOnly, bool bMustMoveThrough, bool bIncludeBlockedUnits, bool bWillPillage, bool bTargetUndefended);CivRegisterBefore<CivHooks::CvTacticalAI_FindUnitsWithinStrikingDistance>(host, &BeforeCvTacticalAI_FindUnitsWithinStrikingDistance);CivRegisterAfter<CivHooks::CvTacticalAI_FindUnitsWithinStrikingDistance>(host, &AfterCvTacticalAI_FindUnitsWithinStrikingDistance);CivRegisterReplace<CivHooks::CvTacticalAI_FindUnitsWithinStrikingDistance>(host, &ReplaceCvTacticalAI_FindUnitsWithinStrikingDistance);

Code

9054/// Fills m_CurrentMoveUnits with all units within X turns of a target (returns TRUE if 1 or more found)9055bool CvTacticalAI::FindUnitsWithinStrikingDistance(CvPlot* pTarget, int iNumTurnsAway, int iPreferredDamageLevel, bool bNoRangedUnits, bool bNavalOnly, bool bMustMoveThrough, bool bIncludeBlockedUnits, bool bWillPillage, bool bTargetUndefended)9056{9057	list<int>::iterator it;9058	UnitHandle pLoopUnit;90599060	bool rtnValue = false;9061	m_CurrentMoveUnits.clear();90629063	bool bIsCityTarget = pTarget->getPlotCity() != NULL;9064#if defined(MOD_AI_SMART_V3)9065	bool bAirUnitsAdded = false;9066#endif90679068	// Loop through all units available to tactical AI this turn9069	for(it = m_CurrentTurnUnits.begin(); it != m_CurrentTurnUnits.end(); it++)9070	{9071		pLoopUnit = m_pPlayer->getUnit(*it);9072		if(pLoopUnit)9073		{9074			if(!bNavalOnly || pLoopUnit->getDomainType() == DOMAIN_SEA)9075			{9076				// don't use non-combat units9077				if(!pLoopUnit->IsCanAttack())9078				{9079					continue;9080				}90819082				if(pLoopUnit->isOutOfAttacks())9083				{9084					continue;9085				}90869087				if (!bIsCityTarget && pLoopUnit->IsCityAttackOnly())9088				{9089					continue;9090				}90919092				if (bWillPillage && !pLoopUnit->canPillage(pTarget))9093				{9094					continue;9095				}9096				9097#if defined(MOD_AI_SMART_V3)9098				//Don't pull melee units out of camps to attack.9099				if(MOD_AI_SMART_V3 && pLoopUnit->isBarbarian() && !pLoopUnit->isRanged() && (pLoopUnit->plot()->getImprovementType() == GC.getBARBARIAN_CAMP_IMPROVEMENT()))9100				{9101					continue;9102				}91039104				//AMS: To effectively skip all ranged units...9105				if (MOD_AI_SMART_V3 && bNoRangedUnits && pLoopUnit->IsCanAttackRanged())9106				{9107					continue;9108				}9109#endif91109111				int iAttackStrength = pLoopUnit->GetMaxAttackStrength(NULL, NULL, NULL);91129113				// Looking for damaged units?  If so, recalculate attack strength9114				if (iPreferredDamageLevel > 0)9115				{9116					int iDamage = pLoopUnit->getDamage();9117					if (iDamage > iPreferredDamageLevel)9118					{9119						iAttackStrength *= 3;9120					}9121				}91229123				int iTurnsCalculated = -1;	// If CanReachInXTurns does an actual pathfind, save the result so we don't just do the same one again.9124				if (bTargetUndefended && CanReachInXTurns(pLoopUnit, pTarget, iNumTurnsAway, false /*bIgnoreUnits*/, &iTurnsCalculated))9125				{9126					CvTacticalUnit unit;9127					unit.SetID(pLoopUnit->GetID());9128					unit.SetAttackStrength(iAttackStrength / 2);9129					unit.SetHealthPercent(pLoopUnit->GetCurrHitPoints(), pLoopUnit->GetMaxHitPoints());9130					m_CurrentMoveUnits.push_back(unit);9131					rtnValue = true;9132				}91339134				else if(!bNoRangedUnits && !bWillPillage && pLoopUnit->IsCanAttackRanged())9135				{9136					// Don't use air units for air strikes if at or below half health9137#if defined(MOD_UNITS_MAX_HP)9138					if (pLoopUnit->getDomainType() != DOMAIN_AIR || (pLoopUnit->getDamage() * 2) < pLoopUnit->GetMaxHitPoints())9139#else9140					if (pLoopUnit->getDomainType() != DOMAIN_AIR || (pLoopUnit->getDamage() * 2) < GC.getMAX_HIT_POINTS())9141#endif9142					{9143#if defined(MOD_AI_SMART_V3)9144						if (MOD_AI_SMART_V3)9145						{9146							// AMS: Are we in range or could be in range with movement?9147							int getDistance = plotDistance(pLoopUnit->getX(), pLoopUnit->getY(), pTarget->getX(), pTarget->getY());9148							if(getDistance < pLoopUnit-> GetRangePlusMoveToshot())9149							{9150								// Will we do any damage9151								if(IsExpectedToDamageWithRangedAttack(pLoopUnit, pTarget))9152								{9153									CvTacticalUnit unit;9154									unit.SetID(pLoopUnit->GetID());9155									unit.SetAttackStrength(100 * pLoopUnit->GetMaxRangedCombatStrength(NULL, /*pCity*/ NULL, true, true));9156									unit.SetHealthPercent(100, 100);  // Don't take damage from bombarding, so show as fully healthy9157									m_CurrentMoveUnits.push_back(unit);9158									rtnValue = true;91599160									if (pLoopUnit->getDomainType() == DOMAIN_AIR)9161									{9162										bAirUnitsAdded = true;9163									}9164								}9165							}9166						}9167						else9168						{9169#endif9170							// Are we in range?9171							if(plotDistance(pLoopUnit->getX(), pLoopUnit->getY(), pTarget->getX(), pTarget->getY()) <= pLoopUnit->GetRange())9172							{9173								// Do we have LOS to the target?9174								if(pLoopUnit->canEverRangeStrikeAt(pTarget->getX(), pTarget->getY()))9175								{9176									// Will we do any damage9177									if(IsExpectedToDamageWithRangedAttack(pLoopUnit, pTarget))9178									{9179										CvTacticalUnit unit;9180										unit.SetID(pLoopUnit->GetID());91819182										// Want ranged units to attack first, so inflate this9183										unit.SetAttackStrength(100 * pLoopUnit->GetMaxRangedCombatStrength(NULL, /*pCity*/ NULL, true, true));9184										unit.SetHealthPercent(100, 100);  // Don't take damage from bombarding, so show as fully healthy9185										m_CurrentMoveUnits.push_back(unit);9186										rtnValue = true;9187									}9188								}9189							}9190#if defined(MOD_AI_SMART_V3)9191						}9192#endif9193					}9194				}9195				else9196				{9197					if (bMustMoveThrough && (iTurnsCalculated == 0 || (iTurnsCalculated == -1 && CanReachInXTurns(pLoopUnit, pTarget, 0, false /*bIgnoreUnits*/, &iTurnsCalculated))))9198					{9199						CvTacticalUnit unit;9200						unit.SetID(pLoopUnit->GetID());9201						unit.SetAttackStrength(iAttackStrength);9202						unit.SetHealthPercent(pLoopUnit->GetCurrHitPoints(), pLoopUnit->GetMaxHitPoints());9203						m_CurrentMoveUnits.push_back(unit);9204						rtnValue = true;9205					}92069207					else if ( (iTurnsCalculated != -1 && iTurnsCalculated <= iNumTurnsAway) || (iTurnsCalculated == -1 && CanReachInXTurns(pLoopUnit, pTarget, iNumTurnsAway, false /*bIgnoreUnits*/)) )9208					{9209						CvTacticalUnit unit;9210						unit.SetID(pLoopUnit->GetID());9211						unit.SetAttackStrength(iAttackStrength);9212						unit.SetHealthPercent(pLoopUnit->GetCurrHitPoints(), pLoopUnit->GetMaxHitPoints());9213						m_CurrentMoveUnits.push_back(unit);9214						rtnValue = true;9215					}92169217					// Units that can make it when others get out of the way are also potentially useful, but give them half priority so they bring up the rear9218					else if (bIncludeBlockedUnits && CanReachInXTurns(pLoopUnit, pTarget, iNumTurnsAway, true /*bIgnoreUnits*/))9219					{9220						CvTacticalUnit unit;9221						unit.SetID(pLoopUnit->GetID());9222						unit.SetAttackStrength(iAttackStrength / 2);9223						unit.SetHealthPercent(pLoopUnit->GetCurrHitPoints(), pLoopUnit->GetMaxHitPoints());9224						m_CurrentMoveUnits.push_back(unit);9225						rtnValue = true;9226					}9227				}9228			}9229		}9230	}92319232#if defined(MOD_AI_SMART_V3)9233	if (MOD_AI_SMART_V3)9234	{9235		//AMS: As we have air units on the attack targets we should also check possible air sweeps9236		if (bAirUnitsAdded)9237			FindAirUnitsToAirSweep(pTarget);9238		else9239			m_CurrentAirUnits.clear();9240	}9241#endif92429243	// Now sort them in the order we'd like them to attack9244	std::stable_sort(m_CurrentMoveUnits.begin(), m_CurrentMoveUnits.end());92459246	return rtnValue;9247}

Calls

Called by