Hooks
static bool BeforeCvMilitaryAI_ScoreTarget(CvMilitaryAI* self, CvMilitaryTarget& target, AIOperationTypes eAIOperationType, int& result);static void AfterCvMilitaryAI_ScoreTarget(CvMilitaryAI* self, CvMilitaryTarget& target, AIOperationTypes eAIOperationType, int& result);static int ReplaceCvMilitaryAI_ScoreTarget(int (*original)(CvMilitaryAI*, CvMilitaryTarget&, AIOperationTypes), CvMilitaryAI* self, CvMilitaryTarget& target, AIOperationTypes eAIOperationType);// CivHooks.h gives this hook point no types, so nothing checks these hooks' parameters.host->RegisterHook(host->pluginIndex, CivHooks::CvMilitaryAI_ScoreTarget::ID, CIV_HOOK_BEFORE, (void*)&BeforeCvMilitaryAI_ScoreTarget);host->RegisterHook(host->pluginIndex, CivHooks::CvMilitaryAI_ScoreTarget::ID, CIV_HOOK_AFTER, (void*)&AfterCvMilitaryAI_ScoreTarget);host->RegisterHook(host->pluginIndex, CivHooks::CvMilitaryAI_ScoreTarget::ID, CIV_HOOK_REPLACE, (void*)&ReplaceCvMilitaryAI_ScoreTarget);
Code
1246/// Come up with a target priority looking at distance, strength, approaches (high score = more desirable target)1247int CvMilitaryAI::ScoreTarget(CvMilitaryTarget& target, AIOperationTypes eAIOperationType)1248{1249 unsigned long int uliRtnValue = 1; // Start with a high base number since divide into it later12501251 // Take into account distance to target (and use higher multipliers for land paths)1252 if(!target.m_bAttackBySea)1253 {1254 if(target.m_iPathLength < 10)1255 {1256 uliRtnValue *= 16;1257 }1258 else if(target.m_iPathLength < 15)1259 {1260 uliRtnValue *= 8;1261 }1262 else if(target.m_iPathLength < 20)1263 {1264 uliRtnValue *= 4;1265 }1266 else1267 {1268 uliRtnValue *= 2;1269 }12701271 // TODO - WH - relocation - should also check for an AllowsAirliftTo improvement in the vacinity1272 // Double if we can assemble troops in muster city with airlifts1273 if (target.m_pMusterCity->CanAirlift())1274 {1275 uliRtnValue *= 2;1276 }1277 }1278 else1279 {1280 if(target.m_iPathLength < 12)1281 {1282 uliRtnValue *= 5;1283 }1284 else if(target.m_iPathLength < 20)1285 {1286 uliRtnValue *= 3;1287 }1288 else if(target.m_iPathLength < 30)1289 {1290 uliRtnValue *= 2;1291 }12921293 // If coming over sea, inland cities are trickier1294 if(!target.m_pTargetCity->plot()->isCoastalLand())1295 {1296 uliRtnValue /= 2;1297 }1298 }12991300 // Is this a sneak attack? If so distance is REALLY important (want to target spaces on edge of empire)1301 // So let's cube what we have so far1302 if (eAIOperationType == AI_OPERATION_SNEAK_CITY_ATTACK || eAIOperationType == AI_OPERATION_NAVAL_SNEAK_ATTACK)1303 {1304 uliRtnValue = uliRtnValue * uliRtnValue * uliRtnValue;1305 }13061307 CityAttackApproaches eApproaches;1308 int iApproachMultiplier = 0;1309 eApproaches = EvaluateMilitaryApproaches(target.m_pTargetCity, true /* Assume units coming by sea can disembark */, target.m_bAttackBySea);1310 switch(eApproaches)1311 {1312 case ATTACK_APPROACH_UNRESTRICTED:1313 iApproachMultiplier = 10;1314 break;13151316 case ATTACK_APPROACH_OPEN:1317 iApproachMultiplier = 8;1318 break;13191320 case ATTACK_APPROACH_NEUTRAL:1321 iApproachMultiplier = 4;1322 break;13231324 case ATTACK_APPROACH_LIMITED:1325 iApproachMultiplier = 2;1326 break;13271328 case ATTACK_APPROACH_RESTRICTED:1329 iApproachMultiplier = 1;1330 break;13311332 case ATTACK_APPROACH_NONE:1333 iApproachMultiplier = 0;1334 break;1335 }13361337 uliRtnValue *= iApproachMultiplier;13381339 // should probably give a bonus if these cities are adjacent13401341 // Don't want to start at a city that isn't connected to our capital1342 if (!target.m_pMusterCity->IsRouteToCapitalConnected() && !target.m_pMusterCity->isCapital())1343 {1344 uliRtnValue /= 4;1345 }13461347 // this won't work if we are "just checking" as the zone are only built for actual war war opponents1348 // TODO come up with a better way to do this that is always correct13491350 int iFriendlyStrength = target.iMusterNearbyUnitPower;1351 int iEnemyStrength = target.iTargetNearbyUnitPower + (target.m_pTargetCity->getStrengthValue() / 50);1352 iFriendlyStrength = max(1, iFriendlyStrength);1353 iEnemyStrength = max(1, iEnemyStrength);1354 int iRatio = 1;1355 iRatio = (iFriendlyStrength * 100) / iEnemyStrength;1356 iRatio = min(1000, iRatio);1357 uliRtnValue *= iRatio;13581359 if (target.m_pTargetCity->IsOriginalCapital())1360 {1361 uliRtnValue *= GC.getAI_MILITARY_CAPTURING_ORIGINAL_CAPITAL();1362 uliRtnValue /= 100;1363 }13641365 if (target.m_pTargetCity->getOriginalOwner() == m_pPlayer->GetID())1366 {1367 uliRtnValue *= GC.getAI_MILITARY_RECAPTURING_OWN_CITY();1368 uliRtnValue /= 100;1369 }1370 1371 // Don't want it to already be targeted by an operation that's not well on its way1372 if(m_pPlayer->IsCityAlreadyTargeted(target.m_pTargetCity, NO_DOMAIN, 50))1373 {1374 uliRtnValue /= 10;1375 }13761377 uliRtnValue /= 1000;13781379 // Economic value of target1380 unsigned long int iEconomicValue = 1 + (target.m_pTargetCity->getPopulation() / 3);1381 // TODO: unhardcode this1382 // filter out all but the most productive1383 iEconomicValue += target.m_pTargetCity->getYieldRateTimes100(YIELD_FOOD, false) / 10;1384 iEconomicValue += target.m_pTargetCity->getYieldRateTimes100(YIELD_PRODUCTION, false) / 10;1385 iEconomicValue += target.m_pTargetCity->getYieldRateTimes100(YIELD_SCIENCE, false) / 10;1386 iEconomicValue += target.m_pTargetCity->getYieldRateTimes100(YIELD_GOLD, false) / 10;1387 iEconomicValue += target.m_pTargetCity->getYieldRateTimes100(YIELD_CULTURE, false) / 10;1388 iEconomicValue += target.m_pTargetCity->getYieldRateTimes100(YIELD_FAITH, false) / 10;1389#if defined(MOD_API_UNIFIED_YIELDS_TOURISM)1390 iEconomicValue += target.m_pTargetCity->getYieldRateTimes100(YIELD_TOURISM, false) / 10;1391#endif1392#if defined(MOD_API_UNIFIED_YIELDS_GOLDEN_AGE)1393 iEconomicValue += target.m_pTargetCity->getYieldRateTimes100(YIELD_GOLDEN_AGE_POINTS, false) / 10;1394#endif1395 uliRtnValue *= iEconomicValue;13961397 uliRtnValue /= 10;13981399 return min(10000000, (int)uliRtnValue & 0x7fffffff);1400}