Hooks
static bool BeforeCvAIOperation_ComputeCenterOfMassForTurn(const CvAIOperation* self, CvArmyAI* pArmy, CvPlot ** ppClosestCurrentCOMonPath, CvPlot*& result);static void AfterCvAIOperation_ComputeCenterOfMassForTurn(const CvAIOperation* self, CvArmyAI* pArmy, CvPlot ** ppClosestCurrentCOMonPath, CvPlot*& result);static CvPlot* ReplaceCvAIOperation_ComputeCenterOfMassForTurn(CvPlot* (*original)(const CvAIOperation*, CvArmyAI*, CvPlot **), const CvAIOperation* self, CvArmyAI* pArmy, CvPlot ** ppClosestCurrentCOMonPath);CivRegisterBefore<CivHooks::CvAIOperation_ComputeCenterOfMassForTurn>(host, &BeforeCvAIOperation_ComputeCenterOfMassForTurn);CivRegisterAfter<CivHooks::CvAIOperation_ComputeCenterOfMassForTurn>(host, &AfterCvAIOperation_ComputeCenterOfMassForTurn);CivRegisterReplace<CivHooks::CvAIOperation_ComputeCenterOfMassForTurn>(host, &ReplaceCvAIOperation_ComputeCenterOfMassForTurn);
Code
1010/// Pick this turn's desired "center of mass" for the army1011CvPlot* CvAIOperation::ComputeCenterOfMassForTurn(CvArmyAI* pArmy, CvPlot **ppClosestCurrentCOMonPath) const1012{1013 CvPlot* pRtnValue = NULL;1014 CvPlayer &kPlayer = GET_PLAYER(m_eOwner);10151016 switch(m_eCurrentState)1017 {1018 case AI_OPERATION_STATE_ABORTED:1019 case AI_OPERATION_STATE_AT_TARGET:1020 case AI_OPERATION_STATE_SUCCESSFUL_FINISH:1021 break;10221023 case AI_OPERATION_STATE_RECRUITING_UNITS:1024 case AI_OPERATION_STATE_GATHERING_FORCES:1025 // Just use the muster point if we're still recruiting/gathering1026 pRtnValue = GetMusterPlot();1027 break;10281029 case AI_OPERATION_STATE_MOVING_TO_TARGET:1030 {1031 CvPlot* pCenterOfMass = 0;1032 CvPlot* pLastTurnArmyPlot = 0;1033 CvAStarNode* pNode1 = 0;1034 CvAStarNode* pNode2 = 0;1035 int iLastNodeIndex = 0;1036 FStaticVector<CvAStarNode*, SAFE_ESTIMATE_MAX_PATH_LEN, true, c_eCiv5GameplayDLL, 0> m_NodesOnPath;10371038 m_NodesOnPath.clear();10391040 // Is goal a city and we're a naval operation? If so, go just offshore.1041 CvPlot *pGoalPlot = pArmy->GetGoalPlot();1042 if (!pGoalPlot->isWater() && IsAllNavalOperation())1043 {1044 pGoalPlot = kPlayer.GetMilitaryAI()->GetCoastalPlotAdjacentToTarget(pGoalPlot, pArmy);1045 }10461047 pLastTurnArmyPlot = pArmy->Plot();1048 pCenterOfMass = pArmy->GetCenterOfMass(IsAllNavalOperation() || IsMixedLandNavalOperation() ? DOMAIN_SEA : DOMAIN_LAND);1049 if (pLastTurnArmyPlot && pCenterOfMass && pGoalPlot)1050 {1051 // Push center of mass forward a number of hexes equal to average movement1052 GC.getStepFinder().SetData(&m_eEnemy);1053 GC.getStepFinder().SetDestValidFunc(NULL); // remove the area check1054 GC.getStepFinder().SetValidFunc(StepValidAnyArea); // remove the area check1055 bool bFound = GC.getStepFinder().GeneratePath(pCenterOfMass->getX(), pCenterOfMass->getY(), pGoalPlot->getX(), pGoalPlot->getY(), m_eOwner, false);1056 GC.getStepFinder().SetValidFunc(StepValid); // remove the area check1057 GC.getStepFinder().SetDestValidFunc(StepDestValid); // restore the area check1058 if (bFound)1059 {1060 pNode1 = GC.getStepFinder().GetLastNode();10611062 // Starting at the end, loop through the entire path1063 while (pNode1)1064 {1065 m_NodesOnPath.push_back(pNode1);1066 pNode1 = pNode1->m_pParent;1067 }10681069 iLastNodeIndex = m_NodesOnPath.size() - 1;10701071 // Move back up path from best node a number of spaces equal to army's movement rate + 11072 int iJumpAhead = pArmy->GetMovementRate() + 1;1073 int iNode1Index = max(0, iLastNodeIndex - iJumpAhead);1074 int iNode2Index = min(iNode1Index + 2, iLastNodeIndex);1075 pNode1 = m_NodesOnPath[iNode1Index];1076 pNode2 = m_NodesOnPath[iNode2Index];1077 1078 pRtnValue = GC.getMap().plot(pNode1->m_iX, pNode1->m_iY);1079 *ppClosestCurrentCOMonPath = GC.getMap().plot(pNode2->m_iX, pNode2->m_iY);1080 }1081 else1082 {1083 // Can't plot a path, probably due to change of control of hexes. Will probably abort the operation1084 return NULL;1085 }1086 }1087 }1088 break;1089 }1090 return pRtnValue;1091}