Hooks
static bool BeforeCvTacticalAI_ExecuteGatherMoves(CvTacticalAI* self, CvArmyAI* pArmy);static void AfterCvTacticalAI_ExecuteGatherMoves(CvTacticalAI* self, CvArmyAI* pArmy);static void ReplaceCvTacticalAI_ExecuteGatherMoves(void (*original)(CvTacticalAI*, CvArmyAI*), CvTacticalAI* self, CvArmyAI* pArmy);CivRegisterBefore<CivHooks::CvTacticalAI_ExecuteGatherMoves>(host, &BeforeCvTacticalAI_ExecuteGatherMoves);CivRegisterAfter<CivHooks::CvTacticalAI_ExecuteGatherMoves>(host, &AfterCvTacticalAI_ExecuteGatherMoves);CivRegisterReplace<CivHooks::CvTacticalAI_ExecuteGatherMoves>(host, &ReplaceCvTacticalAI_ExecuteGatherMoves);
Code
5080/// Gather all units requested through calls to MoveWithFormation() to army's location5081void CvTacticalAI::ExecuteGatherMoves(CvArmyAI* pArmy)5082{5083 CvPlot* pTarget;5084 UnitHandle pUnit;5085 int iUnits;5086 AITacticalTargetType eTargetType;5087 CvPlot* pLoopPlot;50885089 if(m_OperationUnits.size() == 0)5090 {5091 return;5092 }50935094 pTarget = pArmy->Plot();50955096 // Gathering - treat everyone as a melee unit; don't need ranged in the rear yet5097 iUnits = m_OperationUnits.size();50985099 // Range around target based on number of units we need to place5100 int iRange = OperationalAIHelpers::GetGatherRangeForXUnits(iUnits);51015102 // Try one time with computed range5103 bool bFoundEnoughDeploymentPlots = false;5104 if (ScoreDeploymentPlots(pTarget, pArmy, iUnits, 0, iRange))5105 {5106 // Did we get twice as many possible plots as units?5107 if (m_TempTargets.size() >= (unsigned)(iUnits * 2))5108 {5109 bFoundEnoughDeploymentPlots = true;5110 }5111 else5112 {5113 m_TempTargets.clear();5114 iRange = 3;5115 }5116 }51175118 if (!bFoundEnoughDeploymentPlots)5119 {5120 if (!ScoreDeploymentPlots(pTarget, pArmy, iUnits, 0, iRange))5121 {5122 if(GC.getLogging() && GC.getAILogging())5123 {5124 CvString strLogString;5125 strLogString.Format("Operation aborting. Army ID: %d. Not enough spaces to deploy near target", pArmy->GetID());5126 LogTacticalMessage(strLogString);5127 }5128 m_pPlayer->getAIOperation(pArmy->GetOperationID())->SetToAbort(AI_ABORT_NO_ROOM_DEPLOY);5129 return;5130 }5131 }51325133 // Compute the moves to get the best deployment5134 std::stable_sort(m_TempTargets.begin(), m_TempTargets.end());5135 m_PotentialBlocks.clear();5136 bool bDone = false;51375138 int iUnitsToPlace = iUnits;51395140 for(unsigned int iI = 0; iI < m_TempTargets.size() && !bDone; iI++)5141 {5142 eTargetType = m_TempTargets[iI].GetTargetType();51435144 pLoopPlot = GC.getMap().plot(m_TempTargets[iI].GetTargetX(), m_TempTargets[iI].GetTargetY());5145 5146 // Don't use if there's already a unit not in the army here5147 UnitHandle pUnitAlreadyThere = pLoopPlot->getBestDefender(NO_PLAYER);5148 if (!pUnitAlreadyThere || pUnitAlreadyThere->getArmyID() == pArmy->GetID())5149 {5150 if(FindClosestOperationUnit(pLoopPlot, true /*bSafeForRanged*/, false /*bMustBeRangedUnit*/))5151 {5152 for(unsigned int jJ = 0; jJ < m_CurrentMoveUnits.size(); jJ++)5153 {5154 CvBlockingUnit block;5155 block.SetUnitID(m_CurrentMoveUnits[jJ].GetID());5156 block.SetPlot(pLoopPlot);5157 block.SetNumChoices((int)m_CurrentMoveUnits.size());5158 block.SetDistanceToTarget(m_CurrentMoveUnits[jJ].GetMovesToTarget());5159 m_PotentialBlocks.push_back(block);5160 }5161 iUnitsToPlace--;5162 if(iUnitsToPlace == 0)5163 {5164 bDone = true;5165 } 5166 }5167 }5168 }51695170 // Now ready to make the assignments5171 AssignDeployingUnits(iUnits - iUnitsToPlace);51725173 PerformChosenMoves();51745175 // Log if someone in army didn't get a move assigned (how do we address this in the future?)5176 if(m_ChosenBlocks.size() < (unsigned int)(iUnits))5177 {5178 if(GC.getLogging() && GC.getAILogging())5179 {5180 CvString strMsg;5181 strMsg.Format("No gather move for %d units", iUnits - m_ChosenBlocks.size());5182 LogTacticalMessage(strMsg);5183 }5184 }5185}