I'm not sure of the details. It seems to take a while before you start getting unhappiness (and losing supply) from losses, as if the mechanic had a buffer. War Weariness seems to ramp relatively fast after a certain point, though, especially if the civ doesn't have war weariness reduction policies.
For detailed info on that, we're better ask someone that worked on that code. I'm interested as well.
Code:
/// What is our war weariness value?
int CvPlayerCulture::ComputeWarWeariness()
{
if (m_pPlayer->isMinorCiv() || m_pPlayer->isBarbarian())
return 0;
int iCurrentWeary = m_iRawWarWeariness;
if (iCurrentWeary == 0 && !m_pPlayer->IsAtWarAnyMajor())
return 0;
PlayerTypes eMostWarTurnsPlayer = NO_PLAYER;
int iMostWarTurns = -1;
int iLeastPeaceTurns = MAX_INT;
int iLeastWarTurns = MAX_INT;
int iHighestWarDamage = 0;
// Look at each civ and get longest war and shortest peace
for (int iLoopPlayer = 0; iLoopPlayer < MAX_MAJOR_CIVS; iLoopPlayer++)
{
CvPlayer &kPlayer = GET_PLAYER((PlayerTypes)iLoopPlayer);
if (iLoopPlayer != m_pPlayer->GetID() && kPlayer.isAlive() && !kPlayer.isMinorCiv() && !kPlayer.isBarbarian() && kPlayer.getNumCities() > 0)
{
if(GET_TEAM(kPlayer.getTeam()).isAtWar(m_pPlayer->getTeam()))
{
if (!GET_TEAM(m_pPlayer->getTeam()).canChangeWarPeace(kPlayer.getTeam()))
continue;
int iWarDamage = m_pPlayer->GetDiplomacyAI()->GetWarValueLost(kPlayer.GetID());
iWarDamage += kPlayer.GetDiplomacyAI()->GetWarValueLost(m_pPlayer->GetID()) / 2;
if (kPlayer.GetPlayerTraits()->GetEnemyWarWearinessModifier() != 0)
{
iWarDamage *= (100 + kPlayer.GetPlayerTraits()->GetEnemyWarWearinessModifier());
iWarDamage /= 100;
}
int iWarTurns = m_pPlayer->GetDiplomacyAI()->GetPlayerNumTurnsAtWar(kPlayer.GetID()) - GD_INT_GET(WAR_MAJOR_MINIMUM_TURNS);
if (iWarTurns <= 0)
continue;
if(iWarTurns > iMostWarTurns)
{
iMostWarTurns = iWarTurns;
eMostWarTurnsPlayer = kPlayer.GetID();
}
//Let's also get our most recent wars.
iLeastWarTurns = min(iLeastWarTurns, iWarTurns);
//Warscore matters.
iHighestWarDamage = max(iHighestWarDamage, iWarDamage);
}
else
{
int iPeaceTurns = m_pPlayer->GetDiplomacyAI()->GetPlayerNumTurnsAtPeace(kPlayer.GetID());
iLeastPeaceTurns = min(iLeastPeaceTurns, iPeaceTurns);
}
}
}
//by default, war weariness is slowly falling over time
int iFallingWarWeariness = 0;
int iRisingWarWeariness = 0;
int iOldWarWeariness = m_iRawWarWeariness;
if (iLeastPeaceTurns>1)
{
//apparently we made peace recently ... reduce the value step by step
int iReduction = max(1, GC.getGame().getSmallFakeRandNum( max(3, iLeastPeaceTurns/2), iHighestWarDamage));
iFallingWarWeariness = max(iOldWarWeariness-iReduction, 0);
}
else
{
//signed peace last turn - halve value for immediate relief
//if we eliminate another player, this won't apply!
iFallingWarWeariness = iOldWarWeariness/2;
}
//but if we have a war going, it will generate rising unhappiness
if(iMostWarTurns > 0)
{
int iInfluenceModifier = max(3, (GET_PLAYER(eMostWarTurnsPlayer).GetCulture()->GetInfluenceLevel(m_pPlayer->GetID()) - GetInfluenceLevel(eMostWarTurnsPlayer) * 2));
//War damage should influence this.
int iWarValue = (iHighestWarDamage * iInfluenceModifier) / 100;
int iTechProgress = (GET_TEAM(m_pPlayer->getTeam()).GetTeamTechs()->GetNumTechsKnown() * 100) / GC.getNumTechInfos();
iWarValue *= (100 + iTechProgress*2);
iWarValue /= 100;
iRisingWarWeariness = (iMostWarTurns * iWarValue) / 100;
//simple exponential smoothing
float fAlpha = 0.3f;
iRisingWarWeariness = int(0.5f + (iRisingWarWeariness * fAlpha) + (iOldWarWeariness * (1 - fAlpha)));
//at least one per turn
if (iRisingWarWeariness == iOldWarWeariness)
iRisingWarWeariness++;
//but never more than x% of pop...
iRisingWarWeariness = min(iRisingWarWeariness, m_pPlayer->getTotalPopulation() / 4);
}
//whichever is worse counts
m_iRawWarWeariness = max(iFallingWarWeariness,iRisingWarWeariness);
int iMod = m_pPlayer->GetWarWearinessModifier() + m_pPlayer->GetPlayerTraits()->GetWarWearinessModifier();
if (iMod > 100)
iMod = 100;
m_iRawWarWeariness *= (100 - iMod);
m_iRawWarWeariness /= 100;
if (GC.getLogging() && GC.getAILogging() && m_iRawWarWeariness > 0)
{
CvString strTemp;
CvString strFileName = "WarWearinessLog.csv";
FILogFile* pLog;
pLog = LOGFILEMGR.GetLog(strFileName, FILogFile::kDontTimeStamp);
CvString strPlayerName;
strPlayerName = m_pPlayer->getCivilizationShortDescription();
strTemp += strPlayerName;
strTemp += ", ";
CvString strTurn;
strTurn.Format("%d, ", GC.getGame().getGameTurn()); // turn
strTemp += strTurn;
CvString strData;
strData.Format(" --- War Weariness: %d. Longest War: %d. Shortest peace: %d. Rising: %d. Falling: %d. Current Supply Cap: %d",
m_iRawWarWeariness, iMostWarTurns, iLeastPeaceTurns, iRisingWarWeariness, iFallingWarWeariness, m_pPlayer->GetNumUnitsSupplied());
strTemp += strData;
pLog->Msg(strTemp);
}
return m_iRawWarWeariness;
}