Bazaar developer reference

CvTacticalAI::PlotNavalEscortOperationMoves(CvAINavalEscortedOperation *)

Defined in
CvTacticalAI.cpp, line 4511
Class
CvTacticalAI
Hook name
CivHooks::CvTacticalAI_PlotNavalEscortOperationMoves

Hooks

static bool BeforeCvTacticalAI_PlotNavalEscortOperationMoves(CvTacticalAI* self, CvAINavalEscortedOperation* pOperation);static void AfterCvTacticalAI_PlotNavalEscortOperationMoves(CvTacticalAI* self, CvAINavalEscortedOperation* pOperation);static void ReplaceCvTacticalAI_PlotNavalEscortOperationMoves(void (*original)(CvTacticalAI*, CvAINavalEscortedOperation*), CvTacticalAI* self, CvAINavalEscortedOperation* pOperation);CivRegisterBefore<CivHooks::CvTacticalAI_PlotNavalEscortOperationMoves>(host, &BeforeCvTacticalAI_PlotNavalEscortOperationMoves);CivRegisterAfter<CivHooks::CvTacticalAI_PlotNavalEscortOperationMoves>(host, &AfterCvTacticalAI_PlotNavalEscortOperationMoves);CivRegisterReplace<CivHooks::CvTacticalAI_PlotNavalEscortOperationMoves>(host, &ReplaceCvTacticalAI_PlotNavalEscortOperationMoves);

Code

4510/// Move a large army to its destination against an enemy target4511void CvTacticalAI::PlotNavalEscortOperationMoves(CvAINavalEscortedOperation* pOperation)4512{4513	CvUnit* pCivilian = 0, *pEscort = 0;4514	int iUnitID;45154516	// Simplification - assume only 1 army per operation now4517	if(pOperation->GetFirstArmyID() == -1)4518	{4519		return;4520	}4521	CvArmyAI* pThisArmy = m_pPlayer->getArmyAI(pOperation->GetFirstArmyID());4522	iUnitID = pThisArmy->GetFirstUnitID();4523	if(iUnitID != -1)4524	{4525		pCivilian = m_pPlayer->getUnit(iUnitID);45264527		iUnitID = pThisArmy->GetNextUnitID();4528		if(iUnitID != -1)4529		{4530			pEscort = m_pPlayer->getUnit(iUnitID);4531			if(pEscort->getDomainType() != DOMAIN_LAND)4532			{4533				pEscort = NULL;   // Second unit wasn't the escort4534			}4535		}4536	}45374538	if(!pCivilian && pOperation->IsCivilianRequired())4539	{4540		return;4541	}45424543	m_OperationUnits.clear();4544	pThisArmy->UpdateCheckpointTurns();45454546	// RECRUITING4547	if(pThisArmy->GetArmyAIState() == ARMYAISTATE_WAITING_FOR_UNITS_TO_REINFORCE)4548	{4549		// If no estimate for when recruiting will end, let the rest of the AI use these units4550		if(pThisArmy->GetTurnAtNextCheckpoint() == ARMYSLOT_UNKNOWN_TURN_AT_CHECKPOINT)4551		{4552			return;4553		}4554		else4555		{4556			for(int iI = 0; iI < pThisArmy->GetNumFormationEntries(); iI++)4557			{4558				CvArmyFormationSlot* pSlot = pThisArmy->GetFormationSlot(iI);4559				if(pSlot->GetUnitID() != NO_UNIT)4560				{4561					// See if we are just able to get to muster point in time.  If so, time for us to head over there4562					UnitHandle pUnit = m_pPlayer->getUnit(pSlot->GetUnitID());4563					if(pUnit && !pUnit->TurnProcessed())4564					{4565						CvMultiUnitFormationInfo* pkUnitFormationInfo = GC.getMultiUnitFormationInfo(pThisArmy->GetFormationIndex());4566						if (pkUnitFormationInfo)4567						{4568							const CvFormationSlotEntry& thisSlotEntry = pkUnitFormationInfo->getFormationSlotEntry(iI);45694570							// Continue moving to target4571							if(pSlot->HasStartedOnOperation())4572							{4573								MoveWithFormation(pUnit, thisSlotEntry.m_ePositionType);4574							}45754576							else4577							{4578								// See if we are just able to get to muster point in time.  If so, time for us to head over there4579								int iTurns = TurnsToReachTarget(pUnit, pOperation->GetMusterPlot(), true /*bReusePaths*/, true, true);4580								if(iTurns + GC.getGame().getGameTurn() >= pThisArmy->GetTurnAtNextCheckpoint())4581								{4582									pSlot->SetStartedOnOperation(true);4583									MoveWithFormation(pUnit, thisSlotEntry.m_ePositionType);4584								}4585							}4586						}4587					}4588				}4589			}4590			ExecuteNavalFormationMoves(pThisArmy, pOperation->GetMusterPlot());4591		}4592	}45934594	// GATHERING FORCES4595	else if(pThisArmy->GetArmyAIState() == ARMYAISTATE_WAITING_FOR_UNITS_TO_CATCH_UP)4596	{4597		ExecuteFleetMoveToTarget(pThisArmy, pOperation->GetMusterPlot());4598	}45994600	// MOVING TO TARGET with a civilian4601	else if(pThisArmy->GetArmyAIState() == ARMYAISTATE_MOVING_TO_DESTINATION && pOperation->IsCivilianRequired())4602	{4603		// Update army's current location4604		CvPlot* pThisTurnTarget;4605		pThisTurnTarget = pThisArmy->GetCenterOfMass(DOMAIN_SEA);4606		if(pThisTurnTarget != NULL)4607		{4608			pThisArmy->SetXY(pThisTurnTarget->getX(), pThisTurnTarget->getY());4609		}46104611		// Settler at the target?4612		if(!pCivilian->plot()->isWater() && pCivilian->plot() == pThisArmy->GetGoalPlot())4613		{4614			if(pCivilian->canFound(pCivilian->plot()))4615			{4616				pCivilian->PushMission(CvTypes::getMISSION_FOUND());4617				if(GC.getLogging() && GC.getAILogging())4618				{4619					CvString strMsg;4620					strMsg.Format("City founded, At X=%d, At Y=%d", pCivilian->plot()->getX(), pCivilian->plot()->getY());4621					pOperation->LogOperationSpecialMessage(strMsg);4622				}4623				pOperation->SetToAbort(AI_ABORT_SUCCESS);4624			}4625		}46264627		// Is our settler and his escort both one move from the destination?  If so, targeted moves to finish up4628		else if(TurnsToReachTarget(pCivilian, pOperation->GetTargetPlot()) <= 1 &&4629		        (!pEscort || TurnsToReachTarget(pEscort, pOperation->GetTargetPlot()) <= 1))4630		{4631			ExecuteMoveToPlot(pCivilian, pOperation->GetTargetPlot(), true);4632			if(GC.getLogging() && GC.getAILogging())4633			{4634				CvString strTemp;4635				CvString strLogString;4636				strTemp = GC.getUnitInfo(pCivilian->getUnitType())->GetDescription();4637				strLogString.Format("Moving %s to target, X: %d, Y: %d", strTemp.GetCString(), pCivilian->getX(), pCivilian->getY());4638				LogTacticalMessage(strLogString);4639			}46404641			if(pEscort)4642			{4643				ExecuteMoveToPlot(pEscort, pOperation->GetTargetPlot(), false);4644				if(GC.getLogging() && GC.getAILogging())4645				{4646					CvString strTemp;4647					CvString strLogString;4648					strTemp = GC.getUnitInfo(pEscort->getUnitType())->GetDescription();4649					strLogString.Format("Moving %s to target, X: %d, Y: %d", strTemp.GetCString(), pEscort->getX(), pEscort->getY());4650					LogTacticalMessage(strLogString);4651				}4652			}46534654			// Move naval escorts in close4655			for(int iI = 2; iI < pThisArmy->GetNumFormationEntries(); iI++)4656			{4657				CvArmyFormationSlot* pSlot = pThisArmy->GetFormationSlot(iI);4658				if(pSlot->GetUnitID() != NO_UNIT)4659				{4660					UnitHandle pUnit = m_pPlayer->getUnit(pSlot->GetUnitID());4661					if(pUnit && !pUnit->TurnProcessed())4662					{4663						MoveToEmptySpaceNearTarget(pUnit, pOperation->GetTargetPlot(), false /*bLand */);4664						if(GC.getLogging() && GC.getAILogging())4665						{4666							CvString strTemp;4667							CvString strLogString;4668							strTemp = GC.getUnitInfo(pUnit->getUnitType())->GetDescription();4669							strLogString.Format("Moving %s near target, Now at X: %d, Y: %d", strTemp.GetCString(), pCivilian->getX(), pCivilian->getY());4670							LogTacticalMessage(strLogString);4671						}4672					}4673				}4674			}4675		}46764677		// Still further away, move as formation4678		else4679		{4680			int iBestDistance = MAX_INT;4681			CvPlot* pBestPlot = NULL;46824683			// Request moves for all units4684			for(int iI = 0; iI < pThisArmy->GetNumFormationEntries(); iI++)4685			{4686				CvArmyFormationSlot* pSlot = pThisArmy->GetFormationSlot(iI);4687				if(pSlot->GetUnitID() != NO_UNIT)4688				{4689					UnitHandle pUnit = m_pPlayer->getUnit(pSlot->GetUnitID());4690					if(pUnit && !pUnit->TurnProcessed())4691					{4692						const CvFormationSlotEntry& thisSlotEntry = GC.getMultiUnitFormationInfo(pThisArmy->GetFormationIndex())->getFormationSlotEntry(iI);4693						MoveWithFormation(pUnit, thisSlotEntry.m_ePositionType);4694					}4695				}4696			}46974698			// Plot one turn of movement for the first unit in the army we find out in the water4699			UnitHandle pUnitAtSea = pThisArmy->GetFirstUnitInDomain(DOMAIN_SEA);4700			if(!pUnitAtSea)4701			{4702				pOperation->RetargetCivilian(pCivilian, pThisArmy);4703				for(int iI = 0; iI < pThisArmy->GetNumFormationEntries(); iI++)4704				{4705					CvArmyFormationSlot* pSlot = pThisArmy->GetFormationSlot(iI);4706					if(pSlot->GetUnitID() != NO_UNIT)4707					{4708						UnitHandle pUnit = m_pPlayer->getUnit(pSlot->GetUnitID());4709						if(pUnit)4710						{4711							pUnit->finishMoves();4712						}4713					}4714				}4715				if(GC.getLogging() && GC.getAILogging())4716				{4717					CvString strLogString;4718					strLogString.Format("Retargeting naval escort operation (no unit in water!), X: %d, Y: %d", pOperation->GetTargetPlot()->getX(), pOperation->GetTargetPlot()->getY());4719					LogTacticalMessage(strLogString);4720				}4721			}4722			else4723			{4724				int iFlags;4725				if(pThisArmy->GetUnitsOfType((MultiunitPositionTypes)m_CachedInfoTypes[eMUPOSITION_NAVAL_ESCORT]) > 0)4726				{4727					iFlags = MOVE_UNITS_IGNORE_DANGER;4728				}47294730				// Goal should be a water tile one hex shy of our target4731				for(int iI = 0; iI < NUM_DIRECTION_TYPES; iI++)4732				{4733					CvPlot* pAdjacentPlot = plotDirection(pThisArmy->GetGoalX(), pThisArmy->GetGoalY(), ((DirectionTypes)iI));4734					if(pAdjacentPlot != NULL && pAdjacentPlot->isWater())4735					{4736						if(pUnitAtSea->plot() == pAdjacentPlot)4737						{4738							pBestPlot = pAdjacentPlot;4739							break;4740						}4741						else4742						{4743							// Using step finder could get tripped up by ocean hexes (since they are in the area but not valid movement targets for coastal vessels.  Watch this!4744							int iDistance = GC.getStepFinder().GetStepDistanceBetweenPoints(m_pPlayer->GetID(), pOperation->GetEnemy(), pUnitAtSea->plot(), pAdjacentPlot);4745							if(iDistance > 0 && iDistance < iBestDistance)4746							{4747								iBestDistance = iDistance;4748								int iDistanceToMove = min(4, iDistance);4749								PlayerTypes eEnemy = pOperation->GetEnemy();4750								pBestPlot = GC.getStepFinder().GetXPlotsFromEnd(m_pPlayer->GetID(), eEnemy, pUnitAtSea->plot(), pAdjacentPlot, (iDistance - iDistanceToMove), false);4751							}4752						}4753					}4754				}47554756				if(pBestPlot == NULL)4757				{4758					pOperation->RetargetCivilian(pCivilian, pThisArmy);4759					for(int iI = 0; iI < pThisArmy->GetNumFormationEntries(); iI++)4760					{4761						CvArmyFormationSlot* pSlot = pThisArmy->GetFormationSlot(iI);4762						if(pSlot->GetUnitID() != NO_UNIT)4763						{4764							UnitHandle pUnit = m_pPlayer->getUnit(pSlot->GetUnitID());4765							if(pUnit)4766							{4767								pUnit->finishMoves();4768							}4769						}4770					}4771					if(GC.getLogging() && GC.getAILogging())4772					{4773						CvString strLogString;4774						strLogString.Format("Retargeting naval escort operation (path lost to target), X: %d, Y: %d", pOperation->GetTargetPlot()->getX(), pOperation->GetTargetPlot()->getY());4775						LogTacticalMessage(strLogString);4776					}4777				}4778				else4779				{4780					ExecuteNavalFormationMoves(pThisArmy, pBestPlot);4781				}4782			}4783		}4784	}47854786	// MOVING TO TARGET as an army4787	else if(pThisArmy->GetArmyAIState() == ARMYAISTATE_MOVING_TO_DESTINATION && !pOperation->IsCivilianRequired())4788	{4789		int iBestDistance = MAX_INT;4790		int iDistance;4791		CvPlot *pBestPlot = NULL;4792		int iSlowestMovementRate = MAX_INT;4793		UnitHandle pClosestUnitAtSea;4794		pBestPlot = m_pPlayer->GetMilitaryAI()->GetCoastalPlotAdjacentToTarget(pThisArmy->GetGoalPlot(), pThisArmy);47954796		// Error handling: couldn't find path to plot next to target4797		if (pBestPlot == NULL)4798		{4799			pOperation->RetargetCivilian(pCivilian, pThisArmy);4800			for (int iI = 0; iI < pThisArmy->GetNumFormationEntries(); iI++)4801			{4802				CvArmyFormationSlot *pSlot = pThisArmy->GetFormationSlot(iI);4803				if (pSlot->GetUnitID() != NO_UNIT)4804				{4805					UnitHandle pUnit = m_pPlayer->getUnit(pSlot->GetUnitID());4806					if (pUnit) 4807					{4808						pUnit->finishMoves();4809					}4810				}4811			}4812			if (GC.getLogging() && GC.getAILogging())4813			{4814				CvString strLogString;4815				strLogString.Format("Retargeting naval escort operation (path lost to target), X: %d, Y: %d", pOperation->GetTargetPlot()->getX(), pOperation->GetTargetPlot()->getY());4816				LogTacticalMessage(strLogString);4817			}4818		}48194820		else4821		{4822			// Request moves for all units, getting the slowest movement rate and the closest unit4823			iBestDistance = MAX_INT;4824			for (int iI = 0; iI < pThisArmy->GetNumFormationEntries(); iI++)4825			{4826				CvArmyFormationSlot *pSlot = pThisArmy->GetFormationSlot(iI);4827				if (pSlot->GetUnitID() != NO_UNIT)4828				{4829					UnitHandle pUnit = m_pPlayer->getUnit(pSlot->GetUnitID());4830					if (pUnit && !pUnit->TurnProcessed())4831					{4832						CvMultiUnitFormationInfo* pMultiUnitFormationInfo = GC.getMultiUnitFormationInfo(pThisArmy->GetFormationIndex());4833						if (pMultiUnitFormationInfo)4834						{4835							const CvFormationSlotEntry& thisSlotEntry = pMultiUnitFormationInfo->getFormationSlotEntry(iI);4836							MoveWithFormation(pUnit, thisSlotEntry.m_ePositionType);48374838							int iMoves = pUnit->getMoves() / GC.getMOVE_DENOMINATOR();4839							if (iMoves < iSlowestMovementRate)4840							{4841								iSlowestMovementRate = iMoves;4842							}48434844							// At sea?4845							iDistance = GC.getStepFinder().GetStepDistanceBetweenPoints(m_pPlayer->GetID(), pOperation->GetEnemy(), pUnit->plot(), pBestPlot);4846							if (iDistance > 0 && iDistance < iBestDistance)4847							{4848								iBestDistance = iDistance;4849								pClosestUnitAtSea = pUnit;4850							}4851						}4852					}4853				}4854			}	48554856			// Error handling: no one at sea, retarget4857			if (!pClosestUnitAtSea)4858			{4859				pOperation->RetargetCivilian(pCivilian, pThisArmy);4860				for (int iI = 0; iI < pThisArmy->GetNumFormationEntries(); iI++)4861				{4862					CvArmyFormationSlot *pSlot = pThisArmy->GetFormationSlot(iI);4863					if (pSlot->GetUnitID() != NO_UNIT)4864					{4865						UnitHandle pUnit = m_pPlayer->getUnit(pSlot->GetUnitID());4866						if (pUnit) 4867						{4868							pUnit->finishMoves();4869						}4870					}4871				}4872				if (GC.getLogging() && GC.getAILogging())4873				{4874					CvString strLogString;4875					strLogString.Format("Retargeting naval escort operation (no unit in water!), X: %d, Y: %d", pOperation->GetTargetPlot()->getX(), pOperation->GetTargetPlot()->getY());4876					LogTacticalMessage(strLogString);4877				}4878			}4879			else4880			{4881				// If not close yet, find best plot for this turn's movement along path to ultimate best plot4882				if (iBestDistance > iSlowestMovementRate)4883				{4884					pBestPlot = GC.getStepFinder().GetXPlotsFromEnd(m_pPlayer->GetID(), pOperation->GetEnemy(), pClosestUnitAtSea->plot(), pBestPlot, (iBestDistance - iSlowestMovementRate), true);					4885				}4886				if (pBestPlot)4887				{4888					pThisArmy->SetXY(pBestPlot->getX(), pBestPlot->getY());4889					ExecuteNavalFormationMoves(pThisArmy, pBestPlot);4890				}4891				else4892				{4893					CvAssertMsg (false, "Naval operation logic error.");4894				}4895			}4896		}4897	}4898}

Calls

Called by