Bazaar developer reference

CvTacticalAI::ExecuteOneProtectedBombard(CvTacticalTarget &)

Defined in
CvTacticalAI.cpp, line 7909
Class
CvTacticalAI
Hook name
CivHooks::CvTacticalAI_ExecuteOneProtectedBombard

Hooks

static bool BeforeCvTacticalAI_ExecuteOneProtectedBombard(CvTacticalAI* self, CvTacticalTarget& kTarget, bool& result);static void AfterCvTacticalAI_ExecuteOneProtectedBombard(CvTacticalAI* self, CvTacticalTarget& kTarget, bool& result);static bool ReplaceCvTacticalAI_ExecuteOneProtectedBombard(bool (*original)(CvTacticalAI*, CvTacticalTarget&), CvTacticalAI* self, CvTacticalTarget& kTarget);CivRegisterBefore<CivHooks::CvTacticalAI_ExecuteOneProtectedBombard>(host, &BeforeCvTacticalAI_ExecuteOneProtectedBombard);CivRegisterAfter<CivHooks::CvTacticalAI_ExecuteOneProtectedBombard>(host, &AfterCvTacticalAI_ExecuteOneProtectedBombard);CivRegisterReplace<CivHooks::CvTacticalAI_ExecuteOneProtectedBombard>(host, &ReplaceCvTacticalAI_ExecuteOneProtectedBombard);

Code

7908/// Bombard an enemy target from a single plot we can protect from enemy attack (return true if some attack made)7909bool CvTacticalAI::ExecuteOneProtectedBombard(CvTacticalTarget& kTarget)7910{7911	UnitHandle pFirstAttacker;7912	int iDX, iDY;7913	CvPlot* pAttackPlot;7914	int iPlotIndex;7915	CvTacticalAnalysisCell* pCell;7916	int iPriority;7917	int iNumTurns;7918	int iNumUnitsRequiredToCover;79197920	CvPlot* pTargetPlot = GC.getMap().plot(kTarget.GetTargetX(), kTarget.GetTargetY());7921	if(PlotAlreadyTargeted(pTargetPlot) != -1)7922	{7923		return false;7924	}79257926	CvCity* pCity = pTargetPlot->getPlotCity();7927	if(pCity != NULL)7928	{7929		int iRequiredDamage = pCity->GetMaxHitPoints() - pCity->getDamage();79307931		// Can't eliminate a city with ranged fire, so don't target one if that low on health7932		if(iRequiredDamage <= 1)7933		{7934			return false;7935		}7936	}79377938	int iRange = m_pMap->GetBestFriendlyRange();7939	m_TempTargets.clear();79407941	// Build a list of all plots that have LOS to target where no enemy unit is adjacent7942	for(iDX = -(iRange); iDX <= iRange; iDX++)7943	{7944		for(iDY = -(iRange); iDY <= iRange; iDY++)7945		{7946			pAttackPlot = plotXY(kTarget.GetTargetX(), kTarget.GetTargetY(), iDX, iDY);7947			if(pAttackPlot != NULL)7948			{7949				int iPlotDistance = plotDistance(pAttackPlot->getX(), pAttackPlot->getY(), kTarget.GetTargetX(), kTarget.GetTargetY());7950				if(iPlotDistance > 0 && iPlotDistance <= iRange)7951				{7952					iPlotIndex = GC.getMap().plotNum(pAttackPlot->getX(), pAttackPlot->getY());7953					pCell = m_pMap->GetCell(iPlotIndex);7954					if(pCell->IsRevealed() && pCell->CanUseForOperationGathering())7955					{7956						if(pCell->IsWithinRangeOfTarget())7957						{7958							// Check for adjacent enemy unit7959							CvPlot* pLoopPlot;7960							bool bNoEnemyAdjacent = true;7961							for(int iI = 0; iI < NUM_DIRECTION_TYPES && bNoEnemyAdjacent; iI++)7962							{7963								pLoopPlot = plotDirection(pAttackPlot->getX(), pAttackPlot->getY(), ((DirectionTypes)iI));7964								if(pLoopPlot != NULL)7965								{7966									iPlotIndex = GC.getMap().plotNum(pLoopPlot->getX(), pLoopPlot->getY());7967									if(m_pMap->GetCell(iPlotIndex)->GetEnemyMilitaryUnit() != NULL)7968									{7969										bNoEnemyAdjacent = false;7970									}7971								}7972							}79737974							if(bNoEnemyAdjacent)7975							{7976								// Do we have a unit that can get off a bombard from here THIS turn7977								iNumTurns = -1;7978								bool bHaveLOS = pAttackPlot->canSeePlot(pTargetPlot, m_pPlayer->getTeam(), iRange, NO_DIRECTION);7979								if(FindClosestUnit(pAttackPlot, 0, false/*bMustHaveHalfHP*/, true /*bMustBeRangedUnit*/, iPlotDistance, !bHaveLOS, false/*bMustBeMeleeUnit*/,  false/*bIgnoreUnits*/, pTargetPlot))7980								{7981									iNumTurns = 0;7982								}7983								// What about next turn?7984								else if(FindClosestUnit(pAttackPlot, 1, false/*bMustHaveHalfHP*/, true /*bMustBeRangedUnit*/, iPlotDistance, !bHaveLOS, false/*bMustBeMeleeUnit*/,  false/*bIgnoreUnits*/,  pTargetPlot))7985								{7986									iNumTurns = 1;7987								}79887989								// If found a unit that could get here, see if we can cover the hex from enemy attack7990								if(iNumTurns >= 0)7991								{7992									if(CanCoverFromEnemy(pAttackPlot, iNumUnitsRequiredToCover, m_CurrentMoveUnits[0].GetID()))7993									{7994										CvTacticalTarget target;7995										target.SetTargetX(pAttackPlot->getX());7996										target.SetTargetY(pAttackPlot->getY());79977998										// How desirable is this move?7999										// Set up math so having to allocate 3 extra units to defend is worse than waiting a turn to attack8000										iPriority = 300 - (iNumTurns * 100);8001										iPriority -= 40 * iNumUnitsRequiredToCover;8002										target.SetAuxIntData(iPriority);8003										m_TempTargets.push_back(target);8004									}8005								}8006							}8007						}8008					}8009				}8010			}8011		}8012	}80138014	// No plots to shoot from?8015	if(m_TempTargets.size() == 0)8016	{8017		return false;8018	}80198020	// Sort potential spots8021	std::stable_sort(m_TempTargets.begin(), m_TempTargets.end());80228023	// Have to rebuild blocking position info for this specific spot8024	pAttackPlot = GC.getMap().plot(m_TempTargets[0].GetTargetX(), m_TempTargets[0].GetTargetY());8025	int iPlotDistance = plotDistance(pAttackPlot->getX(), pAttackPlot->getY(), kTarget.GetTargetX(), kTarget.GetTargetY());8026	bool bHaveLOS = pAttackPlot->canSeePlot(pTargetPlot, m_pPlayer->getTeam(), iRange, NO_DIRECTION);8027	if(FindClosestUnit(pAttackPlot, 0, false/*bMustHaveHalfHP*/, true /*bMustBeRangedUnit*/, iPlotDistance, !bHaveLOS, false/*bMustBeMeleeUnit*/,  false/*bIgnoreUnits*/, pTargetPlot) ||8028	        FindClosestUnit(pAttackPlot, 1, false/*bMustHaveHalfHP*/, true /*bMustBeRangedUnit*/, iPlotDistance, !bHaveLOS, false/*bMustBeMeleeUnit*/,  false/*bIgnoreUnits*/, pTargetPlot))8029	{8030		int iAttackingUnitID = m_CurrentMoveUnits[0].GetID();8031		if(pAttackPlot && CanCoverFromEnemy(pAttackPlot, iNumUnitsRequiredToCover, iAttackingUnitID))8032		{8033			// Make each blocking move8034			for(unsigned int iI = 0; iI < m_ChosenBlocks.size(); iI++)8035			{8036				CvUnit* pChosenUnit = m_pPlayer->getUnit(m_ChosenBlocks[iI].GetUnitID());8037				if(pChosenUnit)8038				{8039					if (pChosenUnit->plot() != m_ChosenBlocks[iI].GetPlot())8040					{8041						if(GC.getLogging() && GC.getAILogging())8042						{8043							CvString strMsg;8044							strMsg.Format("Moving to cover a protected bombard with %s, X: %d, Y: %d", pChosenUnit->getName().GetCString(),8045								m_ChosenBlocks[iI].GetPlot()->getX(), m_ChosenBlocks[iI].GetPlot()->getY());8046							LogTacticalMessage(strMsg, false);8047						}8048						pChosenUnit->PushMission(CvTypes::getMISSION_MOVE_TO(), m_ChosenBlocks[iI].GetPlot()->getX(), m_ChosenBlocks[iI].GetPlot()->getY());8049					}8050					else if (pChosenUnit->canPillage(pChosenUnit->plot()) && pChosenUnit->getDamage() > 0)8051					{8052						pChosenUnit->PushMission(CvTypes::getMISSION_PILLAGE());8053						if(GC.getLogging() && GC.getAILogging())8054						{8055							CvString strMsg;8056							strMsg.Format("Pillaging during a protected bombard with %s, X: %d, Y: %d", pChosenUnit->getName().GetCString(),8057								m_ChosenBlocks[iI].GetPlot()->getX(), m_ChosenBlocks[iI].GetPlot()->getY());8058							LogTacticalMessage(strMsg, false);8059						}8060					}8061					else if(pChosenUnit->canFortify(pChosenUnit->plot()))8062					{8063						pChosenUnit->PushMission(CvTypes::getMISSION_FORTIFY());8064						if(GC.getLogging() && GC.getAILogging())8065						{8066							CvString strMsg;8067							strMsg.Format("Fortifying during a protected bombard with %s, X: %d, Y: %d", pChosenUnit->getName().GetCString(),8068								m_ChosenBlocks[iI].GetPlot()->getX(), m_ChosenBlocks[iI].GetPlot()->getY());8069							LogTacticalMessage(strMsg, false);8070						}8071					}8072					else8073					{8074						if(GC.getLogging() && GC.getAILogging())8075						{8076							CvString strMsg;8077							strMsg.Format("Sitting during a protected bombard with %s, X: %d, Y: %d", pChosenUnit->getName().GetCString(),8078								m_ChosenBlocks[iI].GetPlot()->getX(), m_ChosenBlocks[iI].GetPlot()->getY());8079							LogTacticalMessage(strMsg, false);8080						}8081					}8082					pChosenUnit->finishMoves();8083					UnitProcessed(pChosenUnit->GetID());8084				}8085			}80868087			// Then move the attacking unit8088			CvUnit* pUnit = m_pPlayer->getUnit(iAttackingUnitID);8089			if(pUnit)8090			{8091				if(pAttackPlot != pUnit->plot())8092				{8093					pUnit->PushMission(CvTypes::getMISSION_MOVE_TO(), pAttackPlot->getX(), pAttackPlot->getY());80948095					if(GC.getLogging() && GC.getAILogging())8096					{8097						CvString strMsg;8098						strMsg.Format("Moving closer for protected bombard with %s, Target X: %d, Target Y: %d, At X: %d, At Y: %d", pUnit->getName().GetCString(),8099						              pAttackPlot->getX(), pAttackPlot->getY(), pUnit->getX(), pUnit->getY());8100						LogTacticalMessage(strMsg, false);8101					}8102				}81038104#if defined(MOD_AI_SMART_V3)8105				if (!MOD_AI_SMART_V3)8106#endif8107				UnitProcessed(iAttackingUnitID);81088109				if(pUnit->canSetUpForRangedAttack(NULL))8110				{8111					pUnit->setSetUpForRangedAttack(true);8112					if(GC.getLogging() && GC.getAILogging())8113					{8114						CvString strMsg;8115						strMsg.Format("Set up %s for ranged attack", pUnit->getName().GetCString());8116						LogTacticalMessage(strMsg, false);8117					}8118				}81198120				if(pUnit->canMove() && !pUnit->isOutOfAttacks() && pUnit->canRangeStrikeAt(kTarget.GetTargetX(), kTarget.GetTargetY()))8121				{8122					if(GC.getLogging() && GC.getAILogging())8123					{8124						CvString strMsg;8125						strMsg.Format("Making a protected bombard with %s, Target X: %d, Target Y: %d, At X: %d, At Y: %d", pUnit->getName().GetCString(),8126						              kTarget.GetTargetX(), kTarget.GetTargetY(), pUnit->getX(), pUnit->getY());8127						LogTacticalMessage(strMsg, false);8128					}81298130					if(QueueAttack((void*)pUnit, &kTarget, true /*bRanged*/, false /*bCityAttack*/))8131					{8132						pFirstAttacker = pUnit;8133					}8134				}8135				8136#if defined(MOD_AI_SMART_V3)8137				if (MOD_AI_SMART_V3)8138				UnitProcessed(iAttackingUnitID);8139#endif8140			}8141		}81428143		if(pFirstAttacker)8144		{8145			LaunchAttack((void*)pFirstAttacker.pointer(), &kTarget, true /*bFirst*/, true /*bFirstAttackRanged*/, false /*bCityAttack*/);8146			return true;8147		}8148	}81498150	return false;8151}

Calls

Called by