Hooks
static bool BeforeCvArmyAI_GetCenterOfMass(CvArmyAI* self, DomainTypes eDomainRequired, CvPlot*& result);static void AfterCvArmyAI_GetCenterOfMass(CvArmyAI* self, DomainTypes eDomainRequired, CvPlot*& result);static CvPlot* ReplaceCvArmyAI_GetCenterOfMass(CvPlot* (*original)(CvArmyAI*, DomainTypes), CvArmyAI* self, DomainTypes eDomainRequired);CivRegisterBefore<CivHooks::CvArmyAI_GetCenterOfMass>(host, &BeforeCvArmyAI_GetCenterOfMass);CivRegisterAfter<CivHooks::CvArmyAI_GetCenterOfMass>(host, &AfterCvArmyAI_GetCenterOfMass);CivRegisterReplace<CivHooks::CvArmyAI_GetCenterOfMass>(host, &ReplaceCvArmyAI_GetCenterOfMass);
Code
217/// Get center of mass of units in army (account for world wrap!)218CvPlot* CvArmyAI::GetCenterOfMass(DomainTypes eDomainRequired)219{220 CvPlot* pRtnValue = NULL;221 int iTotalX = 0;222 int iTotalY = 0;223 int iNumUnits = 0;224 UnitHandle pUnit;225 int iReferenceUnitX = -1;226 int iWorldWidth = GC.getMap().getGridWidth();227228 pUnit = GetFirstUnit();229 if(pUnit)230 {231 iReferenceUnitX = pUnit->getX();232 }233234 while(pUnit)235 {236 int iUnitX = pUnit->getX();237238 bool bWorldWrapAdjust = false;239 int iDiff = iUnitX - iReferenceUnitX;240 if(abs(iDiff) > (iWorldWidth / 2))241 {242 bWorldWrapAdjust = true;243 }244245 if(bWorldWrapAdjust)246 {247 iTotalX += iUnitX + iWorldWidth;248 }249 else250 {251 iTotalX += iUnitX;252 }253 iTotalY += pUnit->getY();254 iNumUnits++;255 pUnit = GetNextUnit();256 }257258 if(iNumUnits > 0)259 {260 int iAverageX = (iTotalX + (iNumUnits / 2)) / iNumUnits;261 if(iAverageX >= iWorldWidth)262 {263 iAverageX = iAverageX - iWorldWidth;264 }265 int iAverageY = (iTotalY + (iNumUnits / 2)) / iNumUnits;266 pRtnValue = GC.getMap().plot(iAverageX, iAverageY);267 }268269 // Domain check270 if (eDomainRequired != NO_DOMAIN && pRtnValue)271 {272 if (pRtnValue->isWater() && eDomainRequired == DOMAIN_LAND || !pRtnValue->isWater() && eDomainRequired == DOMAIN_SEA)273 {274 // Find an adjacent plot that works275 for (int iI = 0; iI < NUM_DIRECTION_TYPES; iI++)276 {277 CvPlot *pLoopPlot = plotDirection(pRtnValue->getX(), pRtnValue->getY(), ((DirectionTypes)iI));278 if (pLoopPlot != NULL)279 {280 if (pLoopPlot->isWater() && eDomainRequired == DOMAIN_SEA || !pLoopPlot->isWater() && eDomainRequired == DOMAIN_LAND)281 {282 return pLoopPlot;283 }284 }285 }286287 // Try two plots out if really having problems288 for (int iDX = -2; iDX <= 2; iDX++)289 {290 for (int iDY = -2; iDY <= 2; iDY++)291 {292 CvPlot *pLoopPlot = plotXYWithRangeCheck(pRtnValue->getX(), pRtnValue->getY(), iDX, iDY, 2);293 if (pLoopPlot)294 {295 if (plotDistance(pRtnValue->getX(), pRtnValue->getY(), pLoopPlot->getX(), pLoopPlot->getY()) == 2)296 {297 if (pLoopPlot->isWater() && eDomainRequired == DOMAIN_SEA || !pLoopPlot->isWater() && eDomainRequired == DOMAIN_LAND)298 {299 return pLoopPlot;300 }301 }302 }303 }304 }305306 // Give up - just use location of first unit307 pUnit = GetFirstUnit();308 pRtnValue = pUnit->plot();309 }310 }311312 return pRtnValue;313}