std::vector<PromotionTypes> aAttackerAvailablePromotions;
std::vector<PromotionTypes> aDefenderAvailablePromotions;
int iI;
for (iI = 0; iI < GC.getNumPromotionInfos(); iI++) //loop through promotions
{
if (pDefender->isDead() || bDefenderWithdrawn)
{
//* defender withdrawn, give him withdrawal promo
if (bDefenderWithdrawn && GC.getPromotionInfo((PromotionTypes)iI).getWithdrawalChange() > 0 &&
pDefender->canAcquirePromotion((PromotionTypes)iI))
{
aDefenderAvailablePromotions.push_back((PromotionTypes)iI);
}
if (!canAcquirePromotion((PromotionTypes)iI)) //attacker can not acquire this promotion
{
continue;
}
//* attacker was crossing river
if (GC.getPromotionInfo((PromotionTypes)iI).isRiver() && cdDefenderDetails.iRiverAttackModifier != 0) //this bonus is being applied to defender
{
aAttackerAvailablePromotions.push_back((PromotionTypes)iI);
}
//* attack from water
else if (GC.getPromotionInfo((PromotionTypes)iI).isAmphib() && cdDefenderDetails.iAmphibAttackModifier != 0)
{
aAttackerAvailablePromotions.push_back((PromotionTypes)iI);
}
//* attack terrain
else if (GC.getPromotionInfo((PromotionTypes)iI).getTerrainAttackPercent((int)pPlot->getTerrainType()) > 0)
{
aAttackerAvailablePromotions.push_back((PromotionTypes)iI);
}
//* attack feature
else if (pPlot->getFeatureType() != NO_FEATURE &&
GC.getPromotionInfo((PromotionTypes)iI).getFeatureAttackPercent((int)pPlot->getFeatureType()) > 0)
{
aAttackerAvailablePromotions.push_back((PromotionTypes)iI);
}
//* attack hills
else if (GC.getPromotionInfo((PromotionTypes)iI).getHillsAttackPercent() > 0 && pPlot->isHills())
{
aAttackerAvailablePromotions.push_back((PromotionTypes)iI);
}
//* attack city
else if (GC.getPromotionInfo((PromotionTypes)iI).getCityAttackPercent() > 0 && pPlot->isCity(true)) //count forts too
{
aAttackerAvailablePromotions.push_back((PromotionTypes)iI);
}
//* first strikes/chanses promotions
else if ((GC.getPromotionInfo((PromotionTypes)iI).getFirstStrikesChange() > 0 ||
GC.getPromotionInfo((PromotionTypes)iI).getChanceFirstStrikesChange() > 0) && (firstStrikes() > 0 || chanceFirstStrikes() > 0) )
{
aAttackerAvailablePromotions.push_back((PromotionTypes)iI);
}
//* unit combat mod
else if (GC.getPromotionInfo((PromotionTypes)iI).getUnitCombatModifierPercent((int)pDefender->getUnitCombatType()) > 0)
{
aAttackerAvailablePromotions.push_back((PromotionTypes)iI);
}
//* combat strength promotions
else if (GC.getPromotionInfo((PromotionTypes)iI).getCombatPercent() > 0)
{
aAttackerAvailablePromotions.push_back((PromotionTypes)iI);
}
//* domain mod
else if (GC.getPromotionInfo((PromotionTypes)iI).getDomainModifierPercent((int)pDefender->getDomainType()))
{
aAttackerAvailablePromotions.push_back((PromotionTypes)iI);
}
//* blitz
else if (GC.getPromotionInfo((PromotionTypes)iI).isBlitz() && bAttackerHasLostNoHP)
{
aAttackerAvailablePromotions.push_back((PromotionTypes)iI);
}
} //if defender is dead or withdrawn
else //attacker is dead or withdrawn
{
//* attacker withdrawn
if (bAttackerWithdrawn && GC.getPromotionInfo((PromotionTypes)iI).getWithdrawalChange() > 0 && canAcquirePromotion((PromotionTypes)iI))
{
aAttackerAvailablePromotions.push_back((PromotionTypes)iI);
}
if (!pDefender->canAcquirePromotion((PromotionTypes)iI))
{
continue;
}
//* defend terrain
if (GC.getPromotionInfo((PromotionTypes)iI).getTerrainDefensePercent((int)pPlot->getTerrainType()) > 0)
{
aDefenderAvailablePromotions.push_back((PromotionTypes)iI);
}
//* defend feature
else if (pPlot->getFeatureType() != NO_FEATURE &&
GC.getPromotionInfo((PromotionTypes)iI).getFeatureDefensePercent((int)pPlot->getFeatureType()) > 0)
{
aDefenderAvailablePromotions.push_back((PromotionTypes)iI);
}
//* defend hills
else if (GC.getPromotionInfo((PromotionTypes)iI).getHillsDefensePercent() > 0 && pPlot->isHills())
{
aDefenderAvailablePromotions.push_back((PromotionTypes)iI);
}
//* defend city
else if (GC.getPromotionInfo((PromotionTypes)iI).getCityDefensePercent() > 0 && pPlot->isCity(true)) //count forts too
{
aDefenderAvailablePromotions.push_back((PromotionTypes)iI);
}
//* first strikes/chanses promotions
else if ((GC.getPromotionInfo((PromotionTypes)iI).getFirstStrikesChange() > 0 ||
GC.getPromotionInfo((PromotionTypes)iI).getChanceFirstStrikesChange() > 0) &&
(pDefender->firstStrikes() > 0 || pDefender->chanceFirstStrikes() > 0))
{
aDefenderAvailablePromotions.push_back((PromotionTypes)iI);
}
//* unit combat mod vs attacker unit type
else if (GC.getPromotionInfo((PromotionTypes)iI).getUnitCombatModifierPercent((int)getUnitCombatType()) > 0)
{
aDefenderAvailablePromotions.push_back((PromotionTypes)iI);
}
//* combat strength promotions
else if (GC.getPromotionInfo((PromotionTypes)iI).getCombatPercent() > 0)
{
aDefenderAvailablePromotions.push_back((PromotionTypes)iI);
}
//* domain mod
else if (GC.getPromotionInfo((PromotionTypes)iI).getDomainModifierPercent((int)getDomainType()))
{
aDefenderAvailablePromotions.push_back((PromotionTypes)iI);
}
} //if attacker withdrawn
} //end promotion types cycle
//promote attacker:
if (!isDead() && aAttackerAvailablePromotions.size() > 0)
{
int iHealthPercent = (maxHitPoints() - getDamage()) * 100 / (maxHitPoints() - iAttackerInitialDamage);
int iPromotionChanseModifier = iHealthPercent * iHealthPercent / maxHitPoints();
int iPromotionChanse = (GC.getDefineINT("COMBAT_DIE_SIDES") - iWinningOdds) * (100 + iPromotionChanseModifier) / 100;
if (GC.getGameINLINE().getSorenRandNum(GC.getDefineINT("COMBAT_DIE_SIDES"), "Occasional Promotion") < iPromotionChanse)
{
//select random promotion from available
PromotionTypes ptPromotion = aAttackerAvailablePromotions[
GC.getGameINLINE().getSorenRandNum(aAttackerAvailablePromotions.size(), "Select Promotion Type")];
//promote
setHasPromotion(ptPromotion, true);
//show message
CvWString szBuffer = gDLL->getText("TXT_KEY_MISC_YOUR_UNIT_PROMOTED_IN_BATTLE", getNameKey(), GC.getPromotionInfo(ptPromotion).getText());
gDLL->getInterfaceIFace()->addMessage(
getOwnerINLINE(), false, GC.getEVENT_MESSAGE_TIME(), szBuffer,
GC.getPromotionInfo((PromotionTypes)0).getSound(), MESSAGE_TYPE_INFO, NULL,
(ColorTypes)GC.getInfoTypeForString("COLOR_GREEN"), this->plot()->getX_INLINE(), this->plot()->getY_INLINE());
}
}
//promote defender:
if (!pDefender->isDead() && aDefenderAvailablePromotions.size() > 0)
{
int iHealthPercent = (maxHitPoints() - pDefender->getDamage()) * 100 / (maxHitPoints() - iDefenderInitialDamage);
int iPromotionChanseModifier = iHealthPercent * iHealthPercent / maxHitPoints();
int iPromotionChanse = iWinningOdds * (100 + iPromotionChanseModifier) / 100;
if (GC.getGameINLINE().getSorenRandNum(GC.getDefineINT("COMBAT_DIE_SIDES"), "Occasional Promotion") < iPromotionChanse)
{
//select random promotion from available
PromotionTypes ptPromotion = aDefenderAvailablePromotions[
GC.getGameINLINE().getSorenRandNum(aDefenderAvailablePromotions.size(), "Select Promotion Type")];
//promote
pDefender->setHasPromotion(ptPromotion, true);
//show message
CvWString szBuffer = gDLL->getText("TXT_KEY_MISC_YOUR_UNIT_PROMOTED_IN_BATTLE", pDefender->getNameKey(),
GC.getPromotionInfo(ptPromotion).getText());
gDLL->getInterfaceIFace()->addMessage(
pDefender->getOwnerINLINE(), false, GC.getEVENT_MESSAGE_TIME(), szBuffer,
GC.getPromotionInfo((PromotionTypes)0).getSound(), MESSAGE_TYPE_INFO, NULL,
(ColorTypes)GC.getInfoTypeForString("COLOR_GREEN"), pPlot->getX_INLINE(), pPlot->getY_INLINE());
}
}