Bazaar developer reference

CvAIOperation::FindBestFitReserveUnit(OperationSlot, CvPlot *, CvPlot *, bool *)

Defined in
CvAIOperation.cpp, line 1649
Class
CvAIOperation
Hook name
CivHooks::CvAIOperation_FindBestFitReserveUnit
Overridden by
CvAIOperationNukeAttack::FindBestFitReserveUnit(OperationSlot, CvPlot *, CvPlot *, bool *)

Hooks

static bool BeforeCvAIOperation_FindBestFitReserveUnit(CvAIOperation* self, OperationSlot thisOperationSlot, CvPlot* pMusterPlot, CvPlot* pTargetPlot, bool* bRequired, bool& result);static void AfterCvAIOperation_FindBestFitReserveUnit(CvAIOperation* self, OperationSlot thisOperationSlot, CvPlot* pMusterPlot, CvPlot* pTargetPlot, bool* bRequired, bool& result);static bool ReplaceCvAIOperation_FindBestFitReserveUnit(bool (*original)(CvAIOperation*, OperationSlot, CvPlot*, CvPlot*, bool*), CvAIOperation* self, OperationSlot thisOperationSlot, CvPlot* pMusterPlot, CvPlot* pTargetPlot, bool* bRequired);CivRegisterBefore<CivHooks::CvAIOperation_FindBestFitReserveUnit>(host, &BeforeCvAIOperation_FindBestFitReserveUnit);CivRegisterAfter<CivHooks::CvAIOperation_FindBestFitReserveUnit>(host, &AfterCvAIOperation_FindBestFitReserveUnit);CivRegisterReplace<CivHooks::CvAIOperation_FindBestFitReserveUnit>(host, &ReplaceCvAIOperation_FindBestFitReserveUnit);

Code

1648/// Find a unit from our reserves that could serve in this operation1649bool CvAIOperation::FindBestFitReserveUnit(OperationSlot thisOperationSlot, CvPlot* pMusterPlot, CvPlot* pTargetPlot, bool* bRequired)1650{1651	CvUnit* pBestUnit = NULL;1652	CvPlayerAI& ownerPlayer = GET_PLAYER(m_eOwner);1653	CvArmyAI* pThisArmy = ownerPlayer.getArmyAI(thisOperationSlot.m_iArmyID);1654	CvString strMsg;1655	CvPlot *pTargetToUse = pTargetPlot;16561657	CvOperationSearchUnitList kSearchList;16581659	*bRequired = true;16601661	// All naval operation targeting a city?   Change target1662	if (pTargetToUse && !pTargetToUse->isWater() && IsAllNavalOperation())1663	{1664		pTargetToUse = ownerPlayer.GetMilitaryAI()->GetCoastalPlotAdjacentToTarget(pTargetToUse, pThisArmy);1665	}16661667	int iThisFormationIndex = pThisArmy->GetFormationIndex();1668	if(iThisFormationIndex != NO_MUFORMATION)1669	{1670		CvMultiUnitFormationInfo* thisFormation = GC.getMultiUnitFormationInfo(iThisFormationIndex);1671		if(thisFormation)1672		{1673			const CvFormationSlotEntry& thisSlotEntry = thisFormation->getFormationSlotEntry(thisOperationSlot.m_iSlotID);1674			bool bMustBeDeepWaterNaval = GET_TEAM(ownerPlayer.getTeam()).canEmbarkAllWaterPassage() && thisFormation->IsRequiresNavalUnitConsistency();16751676			int iLoop = 0;1677			for(CvUnit* pLoopUnit = ownerPlayer.firstUnit(&iLoop); pLoopUnit != NULL; pLoopUnit = ownerPlayer.nextUnit(&iLoop))1678			{1679				const UnitAITypes eLoopUnitAIType = pLoopUnit->AI_getUnitAIType();16801681				// Make sure he's not needed by the tactical AI or already in an army or scouting1682				if(pLoopUnit->canRecruitFromTacticalAI() && pLoopUnit->getArmyID() == FFreeList::INVALID_INDEX &&1683				        eLoopUnitAIType != UNITAI_EXPLORE && eLoopUnitAIType != UNITAI_EXPLORE_SEA && pLoopUnit->getDropRange() == 0 /* no paratroopers */)1684				{1685					// Is this unit one of the requested types?1686					CvUnitEntry* unitInfo = GC.getUnitInfo(pLoopUnit->getUnitType());1687					if(unitInfo == NULL)1688						continue;16891690					// PRIMARY UNIT TYPE (ONLY)16911692					if(unitInfo->GetUnitAIType((UnitAITypes)thisSlotEntry.m_primaryUnitType))1693					{1694						// Is his health okay?1695						if(!pLoopUnit->IsCombatUnit() || pLoopUnit->GetCurrHitPoints() >= pLoopUnit->GetMaxHitPoints() * GC.getAI_OPERATIONAL_PERCENT_HEALTH_FOR_OPERATION() / 100)1696						{1697							// Not finishing up an operation?1698							if(pLoopUnit->GetDeployFromOperationTurn() + GC.getAI_TACTICAL_MAP_TEMP_ZONE_TURNS() < GC.getGame().getGameTurn())1699							{1700								if((!IsAllNavalOperation() && !IsMixedLandNavalOperation()) || pLoopUnit->getDomainType() == DOMAIN_SEA || pLoopUnit->CanEverEmbark())1701								{1702									if (!bMustBeDeepWaterNaval || pLoopUnit->getDomainType() != DOMAIN_SEA || !pLoopUnit->isTerrainImpassable(TERRAIN_OCEAN))1703									{1704										// Get raw distance to the muster point or target1705										CvPlot* pkLoopUnitPlot = pLoopUnit->plot();1706										int iDistance;1707										if(pMusterPlot != NULL)1708										{1709											iDistance = plotDistance(pkLoopUnitPlot->getX(), pkLoopUnitPlot->getY(), pMusterPlot->getX(), pMusterPlot->getY());1710											// Double the distance if this is a land unit on a different landmass (it's dangerous to go over water!)1711											if(pMusterPlot != NULL && pLoopUnit->getDomainType() == DOMAIN_LAND && pkLoopUnitPlot->getArea() != pMusterPlot->getArea())1712											{1713												iDistance *= 2;1714											}1715										}1716										else1717										{1718											if (pTargetToUse != NULL)1719												iDistance = plotDistance(pkLoopUnitPlot->getX(), pkLoopUnitPlot->getY(), pTargetToUse->getX(), pTargetToUse->getY());1720											else1721											{1722												CvAssertMsg(0, "No muster or target!");1723												iDistance = MAX_INT;1724											}1725										}17261727										kSearchList.push_back(CvOperationSearchUnit(pLoopUnit, iDistance));1728									}1729								}1730							}1731						}1732					}1733				}1734			}17351736			pBestUnit = GetClosestUnit(kSearchList, pMusterPlot, pTargetToUse, NeedToCheckPathToTarget());17371738			// Did we find one?1739			if(pBestUnit != NULL)1740			{1741				pThisArmy->AddUnit(pBestUnit->GetID(), thisOperationSlot.m_iSlotID);1742				return true;1743			}1744			else1745			{1746				if(GC.getLogging() && GC.getAILogging())1747				{1748					strMsg.Format("Could not recruit from primary units for muster at x=%d y=%d, target of x=%d y=%d", (pMusterPlot)?pMusterPlot->getX():-1, (pMusterPlot)?pMusterPlot->getY():-1, (pTargetToUse)?pTargetToUse->getX():-1, (pTargetToUse)?pTargetToUse->getY():-1);1749					LogOperationSpecialMessage(strMsg);1750				}1751			}17521753			kSearchList.clear();1754			// Loop again this time through secondary units1755			for(CvUnit* pLoopUnit = ownerPlayer.firstUnit(&iLoop); pLoopUnit != NULL; pLoopUnit = ownerPlayer.nextUnit(&iLoop))1756			{1757				const UnitAITypes eLoopUnitAIType = pLoopUnit->AI_getUnitAIType();17581759				// Make sure he's not needed by the tactical AI or already in an army or scouting1760				if(pLoopUnit->canRecruitFromTacticalAI() && pLoopUnit->getArmyID() == FFreeList::INVALID_INDEX &&1761				        eLoopUnitAIType != UNITAI_EXPLORE && eLoopUnitAIType != UNITAI_EXPLORE_SEA && pLoopUnit->getDropRange() == 0 /* no paratroopers */)1762				{1763					// Is this unit one of the requested types?1764					CvUnitEntry* unitInfo = GC.getUnitInfo(pLoopUnit->getUnitType());1765					if(unitInfo == NULL)1766						continue;17671768					// SECONDARY UNIT TYPE (ONLY)17691770					if(unitInfo->GetUnitAIType((UnitAITypes)thisSlotEntry.m_secondaryUnitType))1771					{1772						// Is his health okay?1773						if(!pLoopUnit->IsCombatUnit() || pLoopUnit->GetCurrHitPoints() >= pLoopUnit->GetMaxHitPoints() * GC.getAI_OPERATIONAL_PERCENT_HEALTH_FOR_OPERATION() / 100)1774						{1775							// Not finishing up an operation?1776							if(pLoopUnit->GetDeployFromOperationTurn() + GC.getAI_TACTICAL_MAP_TEMP_ZONE_TURNS() < GC.getGame().getGameTurn())1777							{1778								if((!IsAllNavalOperation() && !IsMixedLandNavalOperation()) || pLoopUnit->getDomainType() == DOMAIN_SEA || pLoopUnit->CanEverEmbark())1779								{1780									if (!bMustBeDeepWaterNaval || pLoopUnit->getDomainType() != DOMAIN_SEA || !pLoopUnit->isTerrainImpassable(TERRAIN_OCEAN))1781									{1782										// Get raw distance to the muster point or target1783										CvPlot* pkLoopUnitPlot = pLoopUnit->plot();1784										int iDistance;1785										if(pMusterPlot != NULL)1786										{1787											iDistance = plotDistance(pkLoopUnitPlot->getX(), pkLoopUnitPlot->getY(), pMusterPlot->getX(), pMusterPlot->getY());1788											// Double the distance if this is a land unit on a different landmass (it's dangerous to go over water!)1789											if(pMusterPlot != NULL && pLoopUnit->getDomainType() == DOMAIN_LAND && pkLoopUnitPlot->getArea() != pMusterPlot->getArea())1790											{1791												iDistance *= 2;1792											}1793										}1794										else1795										{1796											if (pTargetToUse != NULL)1797												iDistance = plotDistance(pkLoopUnitPlot->getX(), pkLoopUnitPlot->getY(), pTargetToUse->getX(), pTargetToUse->getY());1798											else1799											{1800												CvAssertMsg(0, "No muster or target!");1801												iDistance = MAX_INT;1802											}1803										}18041805										kSearchList.push_back(CvOperationSearchUnit(pLoopUnit, iDistance));1806									}1807								}1808							}1809						}1810					}1811				}1812			}18131814			pBestUnit = GetClosestUnit(kSearchList, pMusterPlot, pTargetToUse, NeedToCheckPathToTarget());18151816			// Did we find one?1817			if(pBestUnit != NULL)1818			{1819				pThisArmy->AddUnit(pBestUnit->GetID(), thisOperationSlot.m_iSlotID);1820				return true;1821			}1822			else1823			{1824				if(GC.getLogging() && GC.getAILogging())1825				{1826					strMsg.Format("Could not recruit from secondary units for muster at x=%d y=%d, target of x=%d y=%d", (pMusterPlot)?pMusterPlot->getX():-1, (pMusterPlot)?pMusterPlot->getY():-1, (pTargetToUse)?pTargetToUse->getX():-1, (pTargetToUse)?pTargetToUse->getY():-1);1827					LogOperationSpecialMessage(strMsg);1828				}1829			}18301831			// If not required, let our calling routine know that1832			if(!thisSlotEntry.m_requiredSlot)1833			{1834				*bRequired = false;1835			}1836		}1837	}18381839	return false;1840}

Calls

Called by