Bazaar developer reference

CvUnit::AI_promotionValue(PromotionTypes)

Defined in
CvUnit.cpp, line 24429
Class
CvUnit
Hook name
CivHooks::CvUnit_AI_promotionValue

Hooks

static bool BeforeCvUnit_AI_promotionValue(CvUnit* self, PromotionTypes ePromotion, int& result);static void AfterCvUnit_AI_promotionValue(CvUnit* self, PromotionTypes ePromotion, int& result);static int ReplaceCvUnit_AI_promotionValue(int (*original)(CvUnit*, PromotionTypes), CvUnit* self, PromotionTypes ePromotion);CivRegisterBefore<CivHooks::CvUnit_AI_promotionValue>(host, &BeforeCvUnit_AI_promotionValue);CivRegisterAfter<CivHooks::CvUnit_AI_promotionValue>(host, &AfterCvUnit_AI_promotionValue);CivRegisterReplace<CivHooks::CvUnit_AI_promotionValue>(host, &ReplaceCvUnit_AI_promotionValue);

Code

24428// XXX make sure we include any new UnitAITypes...24429int CvUnit::AI_promotionValue(PromotionTypes ePromotion)24430{24431	VALIDATE_OBJECT2443224433	CvPromotionEntry* pkPromotionInfo = GC.getPromotionInfo(ePromotion);24434	if(pkPromotionInfo == NULL)24435	{24436		//This function really really really should not be called with an invalid promotion type.24437		CvAssert(pkPromotionInfo);24438		return 0;24439	}2444024441	int iValue = 0;2444224443	int iTemp;24444#if defined(MOD_AI_SMART_V3)24445	int lowPriority = 100;24446	int mediumPriority	 = 110;24447	int highPriority = 120;24448	int absolutePriority = 200;24449	int plotPercents;24450	int doubleMove;24451#endif24452	int iExtra;24453	int iI;2445424455	// Get flavor info we can use24456#if defined(MOD_BUGFIX_USE_GETTERS)24457	CvFlavorManager* pFlavorMgr = GET_MY_PLAYER().GetFlavorManager();24458#else24459	CvFlavorManager* pFlavorMgr = GET_PLAYER(m_eOwner).GetFlavorManager();24460#endif24461	int iFlavorOffense = pFlavorMgr->GetPersonalityIndividualFlavor((FlavorTypes)GC.getInfoTypeForString("FLAVOR_OFFENSE"));24462	int iFlavorDefense = pFlavorMgr->GetPersonalityIndividualFlavor((FlavorTypes)GC.getInfoTypeForString("FLAVOR_DEFENSE"));24463	int iFlavorRanged = pFlavorMgr->GetPersonalityIndividualFlavor((FlavorTypes)GC.getInfoTypeForString("FLAVOR_RANGED"));24464	int iFlavorRecon = pFlavorMgr->GetPersonalityIndividualFlavor((FlavorTypes)GC.getInfoTypeForString("FLAVOR_RECON"));24465	int iFlavorMobile = pFlavorMgr->GetPersonalityIndividualFlavor((FlavorTypes)GC.getInfoTypeForString("FLAVOR_MOBILE"));24466	int iFlavorNaval = pFlavorMgr->GetPersonalityIndividualFlavor((FlavorTypes)GC.getInfoTypeForString("FLAVOR_NAVAL"));24467	int iFlavorAir = pFlavorMgr->GetPersonalityIndividualFlavor((FlavorTypes)GC.getInfoTypeForString("FLAVOR_AIR"));2446824469#if defined(MOD_AI_SMART_V3)24470	if (MOD_AI_SMART_V3)24471	{24472		int iFlavorOffDef = (iFlavorOffense + iFlavorDefense) / 2;2447324474		// If we are damaged, insta heal is the way to go24475		if(pkPromotionInfo->IsInstaHeal())24476		{24477			// Half health or less?24478			if(getDamage() >= (GetMaxHitPoints() / 2))24479			{24480				iValue = absolutePriority;   // Enough to lock this one up24481			}24482			else24483			{24484				// Give insta-heal a very low priority otherwise.24485				iValue = GetPromotionValue(pkPromotionInfo->IsInstaHeal() ? 1 : 0, -20, 0, lowPriority);24486			}24487		}2448824489		// High priority promotions24490		if (iValue == 0)24491		{24492			iValue = GetPromotionValue(pkPromotionInfo->GetExtraAttacks(), 0, iFlavorOffense, highPriority);24493		}2449424495		if (iValue == 0)24496		{24497			iValue = GetPromotionValue(pkPromotionInfo->IsAlwaysHeal() ? 1 : 0, 0, iFlavorDefense, highPriority);24498		}2449924500		if (iValue == 0)24501		{24502			iValue = GetPromotionValue(pkPromotionInfo->IsBlitz() ? 1 : 0, 0, iFlavorMobile, highPriority);24503		}2450424505		if (iValue == 0)24506		{24507			iValue = GetPromotionValue(pkPromotionInfo->GetRangeChange(), 0, iFlavorRanged, getDomainType() == DOMAIN_AIR ? mediumPriority : highPriority);24508		}2450924510		if (iValue == 0)24511		{24512			plotPercents = 0;24513			doubleMove = 0;2451424515			for(iI = 0; iI < GC.getNumTerrainInfos(); iI++)24516			{24517				const TerrainTypes eTerrain = static_cast<TerrainTypes>(iI);24518				CvTerrainInfo* pkTerrainInfo = GC.getTerrainInfo(eTerrain);2451924520				if(pkTerrainInfo)24521				{24522					plotPercents += pkPromotionInfo->GetTerrainAttackPercent(iI) + pkPromotionInfo->GetTerrainDefensePercent(iI);24523					doubleMove += pkPromotionInfo->GetTerrainDoubleMove(iI) ? 1 : 0;24524				}24525			}2452624527			iValue = GetPromotionValue(doubleMove, 0, iFlavorMobile, highPriority);2452824529			if (iValue == 0)24530			{24531				iValue = GetPromotionValue(plotPercents, 0, iFlavorOffDef, mediumPriority);24532			}24533		}2453424535		if (iValue == 0)24536		{24537			plotPercents = 0;24538			doubleMove = 0;2453924540			for(iI = 0; iI < GC.getNumFeatureInfos(); iI++)24541			{24542				const FeatureTypes eFeature = static_cast<FeatureTypes>(iI);24543				CvFeatureInfo* pkFeatureInfo = GC.getFeatureInfo(eFeature);2454424545				if(pkFeatureInfo)24546				{24547					plotPercents += pkPromotionInfo->GetFeatureAttackPercent(iI) + pkPromotionInfo->GetFeatureDefensePercent(iI);24548					doubleMove += pkPromotionInfo->GetFeatureDoubleMove(iI) ? 1 : 0;24549				}24550			}2455124552			iValue = GetPromotionValue(doubleMove, 0, iFlavorMobile, highPriority);2455324554			if (iValue == 0)24555			{24556				iValue = GetPromotionValue(plotPercents, 0, iFlavorOffDef, mediumPriority);24557			}24558		}2455924560		// Medium priority promotions24561		if (iValue == 0)24562		{24563			iTemp = pkPromotionInfo->GetEnemyHealChange() + pkPromotionInfo->GetNeutralHealChange() + pkPromotionInfo->GetFriendlyHealChange() + pkPromotionInfo->GetAdjacentTileHealChange();24564			iValue = GetPromotionValue(iTemp, getDefenseModifier(), iFlavorDefense, mediumPriority);24565		}2456624567		if (iValue == 0)24568		{24569			iValue = GetPromotionValue(pkPromotionInfo->IsRangeAttackIgnoreLOS() ? 1 : 0, 0, iFlavorRanged, mediumPriority);24570		}2457124572		if (iValue == 0)24573		{24574			iValue = GetPromotionValue(pkPromotionInfo->GetAttackWoundedMod(), getExtraAttackWoundedMod(), iFlavorOffense, mediumPriority);24575		}2457624577		if (iValue == 0)24578		{24579			iValue = GetPromotionValue(pkPromotionInfo->GetMovesChange(), 0, iFlavorMobile, mediumPriority);24580		}2458124582		if (iValue == 0)24583		{24584			iValue = GetPromotionValue(pkPromotionInfo->GetAttackFortifiedMod(), getExtraAttackFortifiedMod(), iFlavorOffense, mediumPriority);24585		}2458624587		if (iValue == 0)24588		{24589			iValue = GetPromotionValue(pkPromotionInfo->IsCanMoveAfterAttacking() ? 1 : 0, 0, iFlavorMobile, mediumPriority);24590		}2459124592		if (iValue == 0)24593		{24594			iValue = GetPromotionValue(pkPromotionInfo->GetNumInterceptionChange(), 0, iFlavorDefense, mediumPriority);24595		}2459624597		if (iValue == 0)24598		{24599			iValue = GetPromotionValue(getDomainType() == DOMAIN_AIR ? pkPromotionInfo->GetInterceptionDefenseDamageModifier() : 0, GetInterceptionDefenseDamageModifier(), iFlavorAir, mediumPriority);24600		}2460124602		if (iValue == 0)24603		{24604			iValue = GetPromotionValue(pkPromotionInfo->GetCargoChange(), 0, iFlavorNaval, mediumPriority);24605		}2460624607		if (iValue == 0)24608		{24609			iValue = GetPromotionValue(pkPromotionInfo->GetAttackMod(), getDomainType() == DOMAIN_SEA ? 1 : 0, iFlavorMobile, mediumPriority);24610		}2461124612		if (iValue == 0)24613		{24614			iValue = GetPromotionValue(pkPromotionInfo->GetRangedDefenseMod(), getExtraRangedDefenseModifier(), iFlavorDefense, mediumPriority);24615		}2461624617		// Low priority promotions2461824619		if (iValue == 0)24620		{24621			iValue = GetPromotionValue(pkPromotionInfo->GetCityAttackPercent(), getDomainType() == DOMAIN_SEA ? 1 : getExtraCityAttackPercent(), iFlavorOffense, lowPriority);24622		}2462324624		if (iValue == 0)24625		{24626			iValue = GetPromotionValue(pkPromotionInfo->GetCityDefensePercent(), getExtraCityDefensePercent(), iFlavorDefense, lowPriority);24627		}2462824629		if (iValue == 0)24630		{24631			iTemp = pkPromotionInfo->GetOpenAttackPercent() + pkPromotionInfo->GetOpenDefensePercent();24632			iValue = GetPromotionValue(iTemp, getExtraOpenAttackPercent() + getExtraOpenDefensePercent() + (canMoveAfterAttacking() ? 1 : 0), iFlavorOffDef, lowPriority);24633		}2463424635		if (iValue == 0)24636		{24637			iTemp = pkPromotionInfo->GetRoughAttackPercent() + pkPromotionInfo->GetRoughDefensePercent();24638			iValue = GetPromotionValue(iTemp, getExtraRoughAttackPercent() + getExtraRoughDefensePercent(), iFlavorOffDef, lowPriority);24639		}2464024641		if (iValue == 0)24642		{24643			iValue = GetPromotionValue(pkPromotionInfo->GetOpenRangedAttackMod(), getExtraOpenRangedAttackMod(), iFlavorRanged, lowPriority);24644		}2464524646		if (iValue == 0)24647		{24648			iValue = GetPromotionValue(pkPromotionInfo->GetRoughRangedAttackMod(), getExtraRoughRangedAttackMod(), iFlavorRanged, lowPriority);24649		}2465024651		if (iValue == 0)24652		{24653			iValue = GetPromotionValue(pkPromotionInfo->GetVisibilityChange(), 0, iFlavorRecon, lowPriority);24654		}2465524656		if (iValue == 0)24657		{24658			iValue = GetPromotionValue((pkPromotionInfo->IsAmphib() || pkPromotionInfo->IsRiver()) ? 1 : 0, 0, iFlavorOffense, lowPriority);24659		}2466024661		if (iValue == 0)24662		{24663			iValue = GetPromotionValue(pkPromotionInfo->GetDefenseMod(), getDefenseModifier(), iFlavorDefense, lowPriority);24664		}2466524666		if (iValue == 0)24667		{24668			iValue = GetPromotionValue(pkPromotionInfo->GetFlankAttackModifier(), maxMoves() > 2 ? 1 : 0, iFlavorMobile, lowPriority);24669		}2467024671		if (iValue == 0)24672		{24673			iTemp = (GC.getPromotionInfo(ePromotion)->IsHealOutsideFriendly() && getDomainType() == DOMAIN_SEA) ? 1 : 0;24674			iValue = GetPromotionValue(iTemp, 0, iFlavorNaval, mediumPriority);24675		}2467624677		if (iValue == 0)24678		{24679			iValue = GetPromotionValue(canAirPatrol(NULL) ? pkPromotionInfo->GetInterceptionCombatModifier() : 0, GetInterceptionCombatModifier(), iFlavorAir, lowPriority);24680		}2468124682		if (iValue == 0)24683		{24684			iValue = GetPromotionValue(canAirSweep() ? pkPromotionInfo->GetAirSweepCombatModifier() : 0, GetAirSweepCombatModifier(), iFlavorAir, lowPriority);24685		}2468624687		if (iValue == 0)24688		{24689			iTemp = 0;2469024691			for(iI = 0; iI < GC.getNumUnitCombatClassInfos(); iI++)24692			{24693				const UnitCombatTypes eUnitCombat = static_cast<UnitCombatTypes>(iI);24694				CvBaseInfo* pkUnitCombatInfo = GC.getUnitCombatClassInfo(eUnitCombat);2469524696				if(pkUnitCombatInfo)24697				{24698					iTemp += pkPromotionInfo->GetUnitCombatModifierPercent(iI);24699				}24700			}2470124702			iValue = GetPromotionValue(iTemp, 0, iFlavorOffDef, lowPriority);24703		}2470424705		if (iValue == 0)24706		{24707			iTemp = 0;2470824709			for(iI = 0; iI < NUM_DOMAIN_TYPES; iI++)24710			{24711				iTemp += pkPromotionInfo->GetDomainModifierPercent(iI);24712			}2471324714			iValue = GetPromotionValue(iTemp, getDomainType() == DOMAIN_SEA ? 1 : 0, iFlavorOffDef, lowPriority);24715		}2471624717		// Unknown promotion? Always give at least a random priority with some flavor24718		if (iValue == 0)24719		{24720			iTemp = lowPriority + GC.getGame().getJonRandNum(20, "AI Promote Unknown");24721			iValue = GetPromotionValue(1, 0, iFlavorOffDef, iTemp);2472224723			// Logging to keep track on promotions not handled on the script.24724			if(GC.getLogging() && GC.getAILogging())24725			{24726				CvString szMsg;24727				szMsg.Format("UNKNOWN PROMOTION %s.", getName().GetCString());24728				GET_PLAYER(m_eOwner).GetTacticalAI()->LogTacticalMessage(szMsg, true /*bSkipLogDominanceZone*/);24729			}24730		}2473124732		//AMS: Higher random from original 15 to 2524733		iValue += GC.getGame().getJonRandNum(25, "AI Promote");24734	}24735	else24736	{24737#endif24738	// If we are damaged, insta heal is the way to go24739	if(pkPromotionInfo->IsInstaHeal())24740	{24741		// Half health or less?24742		if(getDamage() >= (GetMaxHitPoints() / 2))24743		{24744			iValue += 1000;   // Enough to lock this one up24745		}24746	}2474724748	iTemp = pkPromotionInfo->GetOpenAttackPercent();24749	if(iTemp != 0)24750	{24751		iExtra = getExtraOpenAttackPercent();24752		iTemp *= (100 + iExtra * 2);24753		iTemp /= 100;24754		if(noDefensiveBonus())24755		{24756			iTemp *= 2;24757		}24758		iValue += iTemp + iFlavorOffense * 2;24759	}2476024761	iTemp = pkPromotionInfo->GetOpenDefensePercent();24762	if(iTemp != 0)24763	{24764		iExtra = getExtraOpenDefensePercent() * 2;24765		iTemp *= (100 + iExtra);24766		iTemp /= 100;24767		if(noDefensiveBonus())24768		{24769			iTemp *= 2;24770		}24771		iValue += iTemp + iFlavorDefense * 2;24772	}2477324774	iTemp = pkPromotionInfo->GetRoughAttackPercent();24775	if(iTemp != 0)24776	{24777		iExtra = getExtraRoughAttackPercent();24778		iTemp *= (100 + iExtra * 2);24779		iTemp /= 100;24780		if(!noDefensiveBonus())24781		{24782			iTemp *= 2;24783		}24784		iValue += iTemp + iFlavorOffense * 2;24785	}2478624787	iTemp = pkPromotionInfo->GetRoughDefensePercent();24788	if(iTemp != 0)24789	{24790		iExtra = getExtraRoughDefensePercent() * 2;24791		iTemp *= (100 + iExtra);24792		iTemp /= 100;24793		if(!noDefensiveBonus())24794		{24795			iTemp *= 2;24796		}24797		iValue += iTemp + iFlavorDefense * 2;24798	}2479924800	iTemp = pkPromotionInfo->GetOpenRangedAttackMod();24801	if(iTemp != 0 && isRanged())24802	{24803		iExtra = getExtraOpenRangedAttackMod();24804		iTemp *= (100 + iExtra * 2);24805		iTemp /= 100;24806		if(noDefensiveBonus())24807		{24808			iTemp *= 2;24809		}24810		iValue += iTemp + iFlavorRanged * 2;24811	}2481224813	iTemp = pkPromotionInfo->GetRoughRangedAttackMod();24814	if(iTemp != 0 && isRanged())24815	{24816		iExtra = getExtraRoughRangedAttackMod() * 2;24817		iTemp *= (100 + iExtra);24818		iTemp /= 100;24819		if(!noDefensiveBonus())24820		{24821			iTemp *= 2;24822		}24823		iValue += iTemp + iFlavorRanged * 2;24824	}2482524826	iTemp = pkPromotionInfo->GetVisibilityChange();24827	if((AI_getUnitAIType() == UNITAI_EXPLORE_SEA) ||24828	        (AI_getUnitAIType() == UNITAI_EXPLORE))24829	{24830		iValue += iTemp * (50 + iFlavorRecon * 2);24831	}24832	else24833	{24834		iValue += iTemp * (10 + iFlavorRecon * 2);24835	}2483624837	iTemp = pkPromotionInfo->GetCityAttackPercent();24838	if(iTemp != 0)24839	{24840		iExtra = getExtraCityAttackPercent();24841		iTemp *= (100 + iExtra * 2);24842		iTemp /= 100;24843		iValue += iTemp + iFlavorOffense * 2;24844		if(isRanged())24845		{24846			iValue += iFlavorRanged * 2;24847		}24848	}2484924850	iTemp = pkPromotionInfo->GetCityDefensePercent();24851	if(iTemp != 0)24852	{24853		iExtra = getExtraCityDefensePercent();24854		iTemp *= (100 + iExtra * 2);24855		iTemp /= 100;24856		iValue += iTemp + iFlavorDefense * 2;24857		if((AI_getUnitAIType() == UNITAI_DEFENSE) ||24858		        (AI_getUnitAIType() == UNITAI_COUNTER))24859		{24860			iValue *= 2;24861		}24862	}2486324864	iTemp = pkPromotionInfo->GetAttackFortifiedMod();24865	if(iTemp != 0 && isRanged())24866	{24867		iExtra = getExtraAttackFortifiedMod() * 2;24868		iTemp *= (100 + iExtra);24869		iTemp /= 100;24870		iValue += iTemp + (iFlavorOffense * iFlavorRanged) * 2;24871	}2487224873	iTemp = pkPromotionInfo->GetEnemyHealChange();24874	if((AI_getUnitAIType() == UNITAI_PARADROP) ||24875	        (AI_getUnitAIType() == UNITAI_PIRATE_SEA))24876	{24877		iValue += iTemp * (50 + iFlavorOffense * 2);24878	}24879	else24880	{24881		iValue += iTemp * (10 + iFlavorOffense * 2);24882	}2488324884	iTemp = pkPromotionInfo->GetNeutralHealChange();24885	if((AI_getUnitAIType() == UNITAI_EXPLORE) ||24886	        (AI_getUnitAIType() == UNITAI_EXPLORE_SEA))24887	{24888		iValue += iTemp * (40 + iFlavorRecon * 2);24889	}24890	else24891	{24892		iValue += iTemp * (10 + iFlavorRecon * 2);24893	}2489424895	iTemp = pkPromotionInfo->GetFriendlyHealChange();24896	if((AI_getUnitAIType() == UNITAI_DEFENSE) ||24897	        (AI_getUnitAIType() == UNITAI_COUNTER))24898	{24899		iValue += iTemp * (20 + iFlavorDefense * 2);24900	}24901	else24902	{24903		iValue += iTemp * (10 + iFlavorDefense * 2);24904	}2490524906	iTemp = pkPromotionInfo->GetAdjacentTileHealChange();24907	if((AI_getUnitAIType() == UNITAI_DEFENSE) ||24908	        (AI_getUnitAIType() == UNITAI_COUNTER))24909	{24910		iValue += iTemp * (40 + iFlavorDefense * 2);24911	}24912	else24913	{24914		iValue += iTemp * (10 + iFlavorDefense * 2);24915	}2491624917	if(pkPromotionInfo->IsAmphib())24918	{24919		if((AI_getUnitAIType() == UNITAI_FAST_ATTACK) ||24920		        (AI_getUnitAIType() == UNITAI_ATTACK))24921		{24922			iValue += 40 + iFlavorOffense * 2;24923		}24924		else24925		{24926			iValue += 10 + iFlavorOffense * 2;24927		}24928	}2492924930	if(pkPromotionInfo->IsRiver())24931	{24932		if((AI_getUnitAIType() == UNITAI_FAST_ATTACK) ||24933		        (AI_getUnitAIType() == UNITAI_ATTACK))24934		{24935			iValue += 40 + iFlavorOffense * 2;24936		}24937		else24938		{24939			iValue += 10 + iFlavorOffense * 2;24940		}24941	}2494224943	iTemp = pkPromotionInfo->GetRangedDefenseMod();24944	if(iTemp != 0)24945	{24946		iExtra = getExtraRangedDefenseModifier() * 2;24947		iTemp *= (100 + iExtra);24948		iTemp /= 100;24949		// likely not a ranged unit24950		if((AI_getUnitAIType() == UNITAI_DEFENSE) || (AI_getUnitAIType() == UNITAI_COUNTER) || (AI_getUnitAIType() == UNITAI_ATTACK))24951		{24952			iTemp *= 2;24953		}24954		// a slow unit24955		if (maxMoves() / GC.getMOVE_DENOMINATOR() <= 2)24956		{24957			iTemp *= 2;24958		}24959		iValue += iTemp + iFlavorDefense * 2;24960	}2496124962	if(pkPromotionInfo->IsRangeAttackIgnoreLOS() && isRanged())24963	{24964		iValue += 75 + iFlavorRanged * 2;24965	}2496624967	iTemp = pkPromotionInfo->GetAttackWoundedMod();24968	if(iTemp != 0 && isRanged())24969	{24970		iExtra = getExtraAttackWoundedMod() * 2;24971		iTemp *= (100 + iExtra);24972		iTemp /= 100;24973		iValue += iTemp + (iFlavorOffense * iFlavorRanged) * 2;24974	}2497524976	iTemp = pkPromotionInfo->GetFlankAttackModifier();24977	if(iTemp > 0)24978	{24979		iExtra = (2 * iFlavorOffense + iFlavorMobile) * maxMoves() / GC.getMOVE_DENOMINATOR();24980		iExtra *= iTemp;24981		iExtra /= 100;24982		iValue += iExtra;24983	}2498424985	if(GC.getPromotionInfo(ePromotion)->IsHealOutsideFriendly() && getDomainType() == DOMAIN_SEA)24986	{24987		iValue += 50 + iFlavorNaval * 2;24988	}2498924990	iTemp = pkPromotionInfo->GetMovesChange();24991	if((AI_getUnitAIType() == UNITAI_ATTACK_SEA) ||24992	        (AI_getUnitAIType() == UNITAI_PIRATE_SEA) ||24993	        (AI_getUnitAIType() == UNITAI_RESERVE_SEA) ||24994	        (AI_getUnitAIType() == UNITAI_ESCORT_SEA) ||24995	        (AI_getUnitAIType() == UNITAI_EXPLORE_SEA) ||24996	        (AI_getUnitAIType() == UNITAI_ASSAULT_SEA) ||24997	        (AI_getUnitAIType() == UNITAI_SETTLER_SEA) ||24998	        (AI_getUnitAIType() == UNITAI_FAST_ATTACK) ||24999	        (AI_getUnitAIType() == UNITAI_ATTACK) ||25000	        (AI_getUnitAIType() == UNITAI_PARADROP))25001	{25002		iValue += iTemp * (50 + iFlavorMobile * 2);25003	}25004	else25005	{25006		iValue += iTemp * (30 + iFlavorMobile * 2);25007	}2500825009	if(pkPromotionInfo->IsAlwaysHeal())25010	{25011		if((AI_getUnitAIType() == UNITAI_ATTACK) ||25012		        (AI_getUnitAIType() == UNITAI_CITY_BOMBARD) ||25013		        (AI_getUnitAIType() == UNITAI_FAST_ATTACK) ||25014		        (AI_getUnitAIType() == UNITAI_COUNTER) ||25015		        (AI_getUnitAIType() == UNITAI_ATTACK_SEA) ||25016		        (AI_getUnitAIType() == UNITAI_PIRATE_SEA) ||25017		        (AI_getUnitAIType() == UNITAI_ESCORT_SEA) ||25018		        (AI_getUnitAIType() == UNITAI_PARADROP))25019		{25020			iValue += 50 + iFlavorMobile * 2;25021		}25022		else25023		{25024			iValue += 30 + iFlavorMobile * 2;25025		}25026	}2502725028	if(pkPromotionInfo->IsBlitz())25029	{25030		if((AI_getUnitAIType() == UNITAI_ATTACK) ||25031		        (AI_getUnitAIType() == UNITAI_CITY_BOMBARD) ||25032		        (AI_getUnitAIType() == UNITAI_FAST_ATTACK) ||25033		        (AI_getUnitAIType() == UNITAI_COUNTER) ||25034		        (AI_getUnitAIType() == UNITAI_ATTACK_SEA) ||25035		        (AI_getUnitAIType() == UNITAI_PIRATE_SEA) ||25036		        (AI_getUnitAIType() == UNITAI_ESCORT_SEA) ||25037		        (AI_getUnitAIType() == UNITAI_PARADROP))25038		{25039			iValue += 50 + (iFlavorMobile + iFlavorOffense) * 2;25040		}25041		else25042		{25043			iValue += 20 + (iFlavorMobile + iFlavorOffense) * 2;25044		}25045	}2504625047	if(pkPromotionInfo->IsCanMoveAfterAttacking())25048	{25049		if((AI_getUnitAIType() == UNITAI_ATTACK) ||25050		        (AI_getUnitAIType() == UNITAI_CITY_BOMBARD) ||25051		        (AI_getUnitAIType() == UNITAI_FAST_ATTACK) ||25052		        (AI_getUnitAIType() == UNITAI_COUNTER) ||25053		        (AI_getUnitAIType() == UNITAI_ATTACK_SEA) ||25054		        (AI_getUnitAIType() == UNITAI_PIRATE_SEA) ||25055		        (AI_getUnitAIType() == UNITAI_ESCORT_SEA) ||25056		        (AI_getUnitAIType() == UNITAI_PARADROP))25057		{25058			iValue += 30 + (iFlavorMobile + iFlavorOffense) * 2;25059		}25060		else25061		{25062			iValue += 10 + (iFlavorMobile + iFlavorOffense) * 2;25063		}25064	}2506525066	iTemp = pkPromotionInfo->GetExtraAttacks();25067	if(iTemp != 0)25068	{25069		iValue += (iTemp * 200);25070	}2507125072	iTemp = pkPromotionInfo->GetRangeChange();25073	if(isRanged())25074	{25075		iValue += (iTemp * 200);25076	}2507725078	iTemp = pkPromotionInfo->GetInterceptionCombatModifier();25079	if(iTemp != 0 && canAirPatrol(NULL))25080	{25081		iExtra = GetInterceptionCombatModifier() * 2;25082		iTemp *= (100 + iExtra);25083		iTemp /= 100;25084		iValue += iTemp + iFlavorAir * 2;25085	}2508625087	iTemp = pkPromotionInfo->GetAirSweepCombatModifier();25088	if(iTemp != 0 && canAirSweep())25089	{25090		iExtra = GetAirSweepCombatModifier() * 2;25091		iTemp *= (100 + iExtra);25092		iTemp /= 100;25093		iValue += iTemp + iFlavorAir * 2;25094	}2509525096	iTemp = pkPromotionInfo->GetNumInterceptionChange();25097	if(iTemp != 0)25098	{25099		iValue += (iTemp * 200);25100	}2510125102	iTemp = pkPromotionInfo->GetInterceptionDefenseDamageModifier();25103	if(iTemp != 0 && getDomainType() == DOMAIN_AIR)25104	{25105		iExtra = GetInterceptionDefenseDamageModifier() * 2;25106		iTemp *= (100 + iExtra);25107		iTemp /= 100;25108		iValue += iTemp + iFlavorAir * 2;25109	}2511025111	iTemp = pkPromotionInfo->GetDefenseMod();25112	if(iTemp != 0)25113	{25114		iExtra = getDefenseModifier() * 2;25115		iTemp *= (100 + iExtra);25116		iTemp /= 100;25117		iValue += iTemp + iFlavorDefense * 2;25118	}2511925120	for(iI = 0; iI < GC.getNumTerrainInfos(); iI++)25121	{25122		const TerrainTypes eTerrain = static_cast<TerrainTypes>(iI);25123		CvTerrainInfo* pkTerrainInfo = GC.getTerrainInfo(eTerrain);25124		if(pkTerrainInfo)25125		{25126			iTemp = pkPromotionInfo->GetTerrainAttackPercent(iI);25127			if(iTemp != 0)25128			{25129				iExtra = getExtraTerrainAttackPercent(eTerrain);25130				iTemp *= (100 + iExtra * 2);25131				iTemp /= 100;25132				iValue += iTemp + iFlavorOffense * 2;25133				if((AI_getUnitAIType() == UNITAI_ATTACK) ||25134				        (AI_getUnitAIType() == UNITAI_FAST_ATTACK))25135				{25136					iValue *= 2;25137				}25138			}2513925140			iTemp = pkPromotionInfo->GetTerrainDefensePercent(iI);25141			if(iTemp != 0)25142			{25143				iExtra =  getExtraTerrainDefensePercent(eTerrain);25144				iTemp *= (100 + iExtra);25145				iTemp /= 100;25146				iValue += iTemp + iFlavorDefense * 2;25147				if((AI_getUnitAIType() == UNITAI_DEFENSE) ||25148				        (AI_getUnitAIType() == UNITAI_COUNTER))25149				{25150					iValue *= 2;25151				}25152			}2515325154			if(pkPromotionInfo->GetTerrainDoubleMove(iI))25155			{25156				if(AI_getUnitAIType() == UNITAI_EXPLORE)25157				{25158					iValue += 5 * (iFlavorRecon + iFlavorMobile);25159				}25160				else if((AI_getUnitAIType() == UNITAI_ATTACK) || (AI_getUnitAIType() == UNITAI_FAST_ATTACK))25161				{25162					iValue += 3 * (iFlavorOffense + iFlavorMobile);25163				}25164				else25165				{25166					iValue += 3 * iFlavorMobile;25167				}25168			}2516925170#if defined(MOD_PROMOTIONS_HALF_MOVE)25171			if(pkPromotionInfo->GetTerrainHalfMove(iI))25172			{25173				if(AI_getUnitAIType() == UNITAI_EXPLORE)25174				{25175					iValue -= 5 * (iFlavorRecon + iFlavorMobile);25176				}25177				else if((AI_getUnitAIType() == UNITAI_ATTACK) || (AI_getUnitAIType() == UNITAI_FAST_ATTACK))25178				{25179					iValue -= 3 * (iFlavorOffense + iFlavorMobile);25180				}25181				else25182				{25183					iValue -= 3 * iFlavorMobile;25184				}25185			}25186#endif25187		}25188	}2518925190	for(iI = 0; iI < GC.getNumFeatureInfos(); iI++)25191	{25192		const FeatureTypes eFeature = static_cast<FeatureTypes>(iI);25193		CvFeatureInfo* pkFeatureInfo = GC.getFeatureInfo(eFeature);25194		if(pkFeatureInfo)25195		{25196			iTemp = pkPromotionInfo->GetFeatureAttackPercent(iI);25197			if(iTemp != 0)25198			{25199				iExtra = getExtraFeatureAttackPercent(eFeature);25200				iTemp *= (100 + iExtra * 2);25201				iTemp /= 100;25202				iValue += iTemp + iFlavorOffense * 2;25203				if((AI_getUnitAIType() == UNITAI_ATTACK) ||25204				        (AI_getUnitAIType() == UNITAI_FAST_ATTACK))25205				{25206					iValue *= 2;25207				}25208			}2520925210			iTemp = pkPromotionInfo->GetFeatureDefensePercent(iI);;25211			if(iTemp != 0)25212			{25213				iExtra = getExtraFeatureDefensePercent(eFeature);25214				iTemp *= (100 + iExtra * 2);25215				iTemp /= 100;25216				iValue += iTemp + iFlavorDefense * 2;25217				if((AI_getUnitAIType() == UNITAI_DEFENSE) ||25218				        (AI_getUnitAIType() == UNITAI_COUNTER))25219				{25220					iValue *= 2;25221				}25222			}2522325224			if(pkPromotionInfo->GetFeatureDoubleMove(iI))25225			{25226				if(AI_getUnitAIType() == UNITAI_EXPLORE)25227				{25228					iValue += 5 * (iFlavorRecon + iFlavorMobile);25229				}25230				else if((AI_getUnitAIType() == UNITAI_ATTACK) || (AI_getUnitAIType() == UNITAI_FAST_ATTACK))25231				{25232					iValue += 3 * (iFlavorOffense + iFlavorMobile);25233				}25234				else25235				{25236					iValue += 3 * iFlavorMobile;25237				}25238			}2523925240#if defined(MOD_PROMOTIONS_HALF_MOVE)25241			if(pkPromotionInfo->GetFeatureHalfMove(iI))25242			{25243				if(AI_getUnitAIType() == UNITAI_EXPLORE)25244				{25245					iValue -= 5 * (iFlavorRecon + iFlavorMobile);25246				}25247				else if((AI_getUnitAIType() == UNITAI_ATTACK) || (AI_getUnitAIType() == UNITAI_FAST_ATTACK))25248				{25249					iValue -= 3 * (iFlavorOffense + iFlavorMobile);25250				}25251				else25252				{25253					iValue -= 3 * iFlavorMobile;25254				}25255			}25256#endif25257		}25258	}2525925260	int iOtherCombat = 0;25261	int iSameCombat = 0;2526225263	for(iI = 0; iI < GC.getNumUnitCombatClassInfos(); iI++)25264	{25265		const UnitCombatTypes eUnitCombat = static_cast<UnitCombatTypes>(iI);25266		CvBaseInfo* pkUnitCombatInfo = GC.getUnitCombatClassInfo(eUnitCombat);25267		if(pkUnitCombatInfo)25268		{25269			if(eUnitCombat == getUnitCombatType())25270			{25271				iSameCombat += unitCombatModifier(eUnitCombat);25272			}25273			else25274			{25275				iOtherCombat += unitCombatModifier(eUnitCombat);25276			}25277		}25278	}2527925280	for(iI = 0; iI < GC.getNumUnitCombatClassInfos(); iI++)25281	{25282		const UnitCombatTypes eUnitCombat = static_cast<UnitCombatTypes>(iI);25283		CvBaseInfo* pkUnitCombatInfo = GC.getUnitCombatClassInfo(eUnitCombat);25284		if(pkUnitCombatInfo)25285		{25286			iTemp = pkPromotionInfo->GetUnitCombatModifierPercent(iI);25287			int iCombatWeight = 0;25288			//Fighting their own kind25289			if((UnitCombatTypes)iI == getUnitCombatType())25290			{25291				if(iSameCombat >= iOtherCombat)25292				{25293					iCombatWeight = 70;//"axeman takes formation"25294				}25295				else25296				{25297					iCombatWeight = 30;25298				}25299			}25300			else25301			{25302				//fighting other kinds25303				if(unitCombatModifier(eUnitCombat) > 10)25304				{25305					iCombatWeight = 70;//"spearman takes formation"25306				}25307				else25308				{25309					iCombatWeight = 30;25310				}25311			}2531225313			if((AI_getUnitAIType() == UNITAI_COUNTER) || (AI_getUnitAIType() == UNITAI_RANGED))25314			{25315				iValue += (iTemp * iCombatWeight) / 25;25316			}25317			else if((AI_getUnitAIType() == UNITAI_ATTACK) ||25318			        (AI_getUnitAIType() == UNITAI_DEFENSE))25319			{25320				iValue += (iTemp * iCombatWeight) / 50;25321			}25322			else25323			{25324				iValue += (iTemp * iCombatWeight) / 100;25325			}25326		}25327	}2532825329	for(iI = 0; iI < NUM_DOMAIN_TYPES; iI++)25330	{25331		iTemp = pkPromotionInfo->GetDomainModifierPercent(iI);25332		if(AI_getUnitAIType() == UNITAI_COUNTER)25333		{25334			iValue += (iTemp * 2);25335		}25336		else if((AI_getUnitAIType() == UNITAI_ATTACK) ||25337		        (AI_getUnitAIType() == UNITAI_DEFENSE))25338		{25339			iValue += iTemp;25340		}25341		else25342		{25343			iValue += (iTemp / 2);25344		}25345	}2534625347	if(iValue > 0)25348	{25349		iValue += GC.getGame().getJonRandNum(15, "AI Promote");25350	}25351#if defined(MOD_AI_SMART_V3)25352	}25353#endif2535425355	return iValue;25356}

Calls

Called by