// --------------------------------------------------------------------------------
#if defined(MOD_UNITS_XP_TIMES_100)
void CvUnit::changeExperienceTimes100(int iChangeTimes100, int iMax, bool bFromCombat, bool bInBorders, bool bUpdateGlobal)
#else
void CvUnit::changeExperience(int iChange, int iMax, bool bFromCombat, bool bInBorders, bool bUpdateGlobal)
#endif
{
VALIDATE_OBJECT
// Barbs don't get XP or Promotions
#if defined(MOD_UNITS_XP_TIMES_100)
if (isBarbarian() && iChangeTimes100 > 0)
#else
if (isBarbarian() && iChange > 0)
#endif
{
return;
}
if (MOD_BALANCE_CORE_SCALING_XP && !bFromCombat)
{
iChangeTimes100 *= GC.getGame().getGameSpeedInfo().getTrainPercent();
iChangeTimes100 /= 100;
}
#if defined(MOD_UNITS_XP_TIMES_100)
// Checking limits.h for the values of MAX_INT and MAX_LONG they are the same, so we need to use "long long" and hence MAX_LLONG
long long lMaxTimes100 = (iMax == -1) ? INT_MAX : (iMax * 100LL);
int iMaxTimes100 = (lMaxTimes100 > ((long long)INT_MAX)) ? INT_MAX : (int)lMaxTimes100;
int iUnitExperienceTimes100 = iChangeTimes100;
#else
int iUnitExperience = iChange;
#endif
PromotionTypes eNewPromotion = NO_PROMOTION;
if(bFromCombat)
{
CvPlayer& kPlayer = GET_PLAYER(getOwner());
// Promotion that changes after combat?
for (int iI = 0; iI < GC.getNumPromotionInfos(); iI++)
{
const PromotionTypes eLoopPromotion = static_cast<PromotionTypes>(iI);
CvPromotionEntry* pkPromotionInfo = GC.getPromotionInfo(eLoopPromotion);
if(pkPromotionInfo)
{
if (pkPromotionInfo->HasPostCombatPromotions() && m_Promotions.HasPromotion(eLoopPromotion))
{
eNewPromotion = m_Promotions.ChangePromotionAfterCombat(eLoopPromotion);
setHasPromotion(eLoopPromotion, false);
if (eNewPromotion != NO_PROMOTION)
{
setHasPromotion(eNewPromotion, true);
#if defined(MOD_EVENTS_UNIT_UPGRADES)
if (MOD_EVENTS_UNIT_UPGRADES) {
GAMEEVENTINVOKE_HOOK(GAMEEVENT_UnitPromoted, getOwner(), GetID(), eNewPromotion);
}
#endif
if (kPlayer.GetID() == GC.getGame().getActivePlayer())
{
CvPromotionEntry* pkNewPromotionInfo = GC.getPromotionInfo(eNewPromotion);
Localization::String localizedText = Localization::Lookup(pkNewPromotionInfo->GetDescriptionKey());
SHOW_PLOT_POPUP(plot(), getOwner(), localizedText.toUTF8());
}
}
}
}
}
// Player Great General/Admiral mod
int iCombatExperienceMod;
if (getDomainType() == DOMAIN_SEA)
{
iCombatExperienceMod = 100 + kPlayer.getGreatAdmiralRateModifier();
}
else
{
iCombatExperienceMod = 100 + kPlayer.getGreatGeneralRateModifier();
}
// Unit XP mod
#if defined(MOD_UNITS_XP_TIMES_100)
int iPlayerBonusXpTimes100 = (iChangeTimes100 * kPlayer.getExpModifier()) / 100;
if (!MOD_UNITS_XP_TIMES_100) {
// If NOT using XP times 100, remove any fractional part
iPlayerBonusXpTimes100 -= (iPlayerBonusXpTimes100 % 100);
}
iUnitExperienceTimes100 += iPlayerBonusXpTimes100;
if(MOD_BALANCE_CORE_RESOURCE_MONOPOLIES)
{
const std::vector<ResourceTypes>& vStrategicMonopolies = GET_PLAYER(getOwner()).GetStrategicMonopolies();
for (size_t iResourceLoop = 0; iResourceLoop < vStrategicMonopolies.size(); iResourceLoop++)
{
ResourceTypes eResourceLoop = vStrategicMonopolies[iResourceLoop];
CvResourceInfo* pInfo = GC.getResourceInfo(eResourceLoop);
if (pInfo && pInfo->getMonopolyXPBonus() > 0)
{
iUnitExperienceTimes100 += (pInfo->getMonopolyXPBonus() * 100);
}
}
}
#else
iUnitExperience += (iChange * kPlayer.getExpModifier()) / 100;
#if defined(MOD_BALANCE_CORE_RESOURCE_MONOPOLIES)
if(MOD_BALANCE_CORE_RESOURCE_MONOPOLIES)
{
const std::vector<ResourceTypes>& vStrategicMonopolies = GET_PLAYER(getOwner()).GetStrategicMonopolies();
for (size_t iResourceLoop = 0; iResourceLoop < vStrategicMonopolies.size(); iResourceLoop++)
{
ResourceTypes eResourceLoop = vStrategicMonopolies[iResourceLoop];
CvResourceInfo* pInfo = GC.getResourceInfo(eResourceLoop);
if (pInfo && pInfo->getMonopolyXPBonus() > 0)
{
iUnitExperience += pInfo->getMonopolyXPBonus();
}
}
}
#endif
#endif
// Great General & Unit XP mod in borders
if (bInBorders)
{
// In-borders GG mod
if (getDomainType() == DOMAIN_LAND)
{
iCombatExperienceMod += kPlayer.getDomesticGreatGeneralRateModifier();
}
int iBorderBonusXpTimes100 = (iChangeTimes100 * kPlayer.getExpInBorderModifier()) / 100;
if (!MOD_UNITS_XP_TIMES_100) {
// If NOT using XP times 100, remove any fractional part
iBorderBonusXpTimes100 -= (iBorderBonusXpTimes100 % 100);
}
iUnitExperienceTimes100 += iBorderBonusXpTimes100;
}
if(bUpdateGlobal)
{
// Add Unit GG mod
if (getDomainType() == DOMAIN_LAND)
{
iCombatExperienceMod += getGreatGeneralModifier();
}
if(iMax == -1)
{
if(getDomainType() == DOMAIN_SEA)
{
#if defined(MOD_GLOBAL_LOCAL_GENERALS)
#if defined(MOD_UNITS_XP_TIMES_100)
kPlayer.changeNavalCombatExperienceTimes100((iChangeTimes100 * iCombatExperienceMod) / 100, (MOD_GLOBAL_LOCAL_GENERALS ? this : NULL));
#else
kPlayer.changeNavalCombatExperience((iChange * iCombatExperienceMod) / 100, (MOD_GLOBAL_LOCAL_GENERALS ? this : NULL));
#endif
#else
#if defined(MOD_UNITS_XP_TIMES_100)
kPlayer.changeNavalCombatExperienceTimes100((iChangeTimes100 * iCombatExperienceMod) / 100);
#else
kPlayer.changeNavalCombatExperience((iChange * iCombatExperienceMod) / 100);
#endif
#endif
}
else
{
#if defined(MOD_GLOBAL_LOCAL_GENERALS)
#if defined(MOD_UNITS_XP_TIMES_100)
kPlayer.changeCombatExperienceTimes100((iChangeTimes100 * iCombatExperienceMod) / 100, (MOD_GLOBAL_LOCAL_GENERALS ? this : NULL));
#else
kPlayer.changeCombatExperience((iChange * iCombatExperienceMod) / 100, (MOD_GLOBAL_LOCAL_GENERALS ? this : NULL));
#endif
#else
#if defined(MOD_UNITS_XP_TIMES_100)
kPlayer.changeCombatExperienceTimes100((iChangeTimes100 * iCombatExperienceMod) / 100);
#else
kPlayer.changeCombatExperience((iChange * iCombatExperienceMod) / 100);
#endif
#endif
}
}
else
{
#if defined(MOD_UNITS_XP_TIMES_100)
int iModdedChangeTimes100 = min(iMaxTimes100 - m_iExperienceTimes100, iChangeTimes100);
if (iModdedChangeTimes100 > 0)
#else
int iModdedChange = min(iMax - m_iExperience, iChange);
if (iModdedChange > 0)
#endif
{
if(getDomainType() == DOMAIN_SEA)
{
#if defined(MOD_GLOBAL_LOCAL_GENERALS)
#if defined(MOD_UNITS_XP_TIMES_100)
kPlayer.changeNavalCombatExperienceTimes100((iModdedChangeTimes100 * iCombatExperienceMod) / 100, (MOD_GLOBAL_LOCAL_GENERALS ? this : NULL));
#else
kPlayer.changeNavalCombatExperience((iModdedChange * iCombatExperienceMod) / 100, (MOD_GLOBAL_LOCAL_GENERALS ? this : NULL));
#endif
#else
#if defined(MOD_UNITS_XP_TIMES_100)
kPlayer.changeNavalCombatExperienceTimes100((iModdedChangeTimes100 * iCombatExperienceMod) / 100);
#else
kPlayer.changeNavalCombatExperience((iModdedChange * iCombatExperienceMod) / 100);
#endif
#endif
}
else
{
#if defined(MOD_GLOBAL_LOCAL_GENERALS)
#if defined(MOD_UNITS_XP_TIMES_100)
kPlayer.changeCombatExperienceTimes100((iModdedChangeTimes100 * iCombatExperienceMod) / 100, (MOD_GLOBAL_LOCAL_GENERALS ? this : NULL));
#else
kPlayer.changeCombatExperience((iModdedChange * iCombatExperienceMod) / 100, (MOD_GLOBAL_LOCAL_GENERALS ? this : NULL));
#endif
#else
#if defined(MOD_UNITS_XP_TIMES_100)
kPlayer.changeCombatExperienceTimes100((iModdedChangeTimes100 * iCombatExperienceMod) / 100);
#else
kPlayer.changeCombatExperience((iModdedChange * iCombatExperienceMod) / 100);
#endif
#endif
}
}
}
}
if(getExperiencePercent() != 0)
{
#if defined(MOD_UNITS_XP_TIMES_100)
int iUnitBonusXpTimes100 = (iUnitExperienceTimes100 + getExperiencePercent()) / 100;
if (!MOD_UNITS_XP_TIMES_100) {
// If NOT using XP times 100, remove any fractional part
iUnitBonusXpTimes100 -= (iUnitBonusXpTimes100 % 100);
}
iUnitExperienceTimes100 += iUnitBonusXpTimes100;
#else
iUnitExperience *= 100 + getExperiencePercent();
iUnitExperience /= 100;
#endif
}
}
#if defined(MOD_UNITS_XP_TIMES_100)
setExperienceTimes100((getExperienceTimes100() + iUnitExperienceTimes100), iMax);
#else
setExperience((getExperience() + iUnitExperience), iMax);
#endif
}