/// Add appropriate items to pDeal based on what type of PeaceTreaty eTreaty is
void CvDealAI::DoAddItemsToDealForPeaceTreaty(PlayerTypes eOtherPlayer, CvDeal* pDeal, PeaceTreatyTypes eTreaty, bool bMeSurrendering)
{
if(eTreaty < PEACE_TREATY_ARMISTICE)
{
return;
}
int iDuration = GC.getGame().GetDealDuration();
PlayerTypes eLosingPlayer = bMeSurrendering ? GetPlayer()->GetID() : eOtherPlayer;
CvPlayer* pLosingPlayer = &GET_PLAYER(eLosingPlayer);
PlayerTypes eWinningPlayer = bMeSurrendering ? eOtherPlayer : GetPlayer()->GetID();
pDeal->SetSurrenderingPlayer(eLosingPlayer);
int iWarScore = pLosingPlayer->GetDiplomacyAI()->GetWarScore(eWinningPlayer);
#if defined(MOD_DIPLOMACY_CIV4_FEATURES)
bool bBecomeMyVassal = pLosingPlayer->GetDiplomacyAI()->IsVassalageAcceptable(eWinningPlayer, true);
bool bRevokeMyVassals = false;
// Reduce war score if losing player wants to become winning player's vassal
if(MOD_DIPLOMACY_CIV4_FEATURES && bBecomeMyVassal)
{
iWarScore /= 2;
}
// Is losing player willing to revoke his vassals?
if(MOD_DIPLOMACY_CIV4_FEATURES && iWarScore <= -85 && GET_TEAM(pLosingPlayer->getTeam()).GetNumVassals() > 0)
{
//If we're willing to do this, give less below.
bRevokeMyVassals = true;
iWarScore /= max(2, GET_TEAM(pLosingPlayer->getTeam()).GetNumVassals());
}
if(iWarScore < 0)
{
iWarScore *= -1;
}
#endif
//strategic warscore adjustment
if (!pLosingPlayer->HasCityInDanger(false,0))
iWarScore = max(0, iWarScore - 10);
int iPercentGoldToGive = iWarScore;
int iPercentGPTToGive = (iWarScore / 2);
bool bGiveUpCities = (iWarScore > 60);
int iPercentCitiesGiveUp = (iWarScore / 5);
bool bGiveUpStratResources = (iWarScore > 35);
bool bGiveUpLuxuryResources = (iWarScore > 15);
int iGiveUpLuxResources = iWarScore;
int iGiveUpStratResources = (iWarScore / 4);
pDeal->AddPeaceTreaty(eWinningPlayer, GC.getGame().getGameSpeedInfo().getPeaceDealDuration());
pDeal->AddPeaceTreaty(eLosingPlayer, GC.getGame().getGameSpeedInfo().getPeaceDealDuration());
DoAddPlayersAlliesToTreaty(eOtherPlayer, pDeal);
CvCity* pLoopCity;
int iCityLoop;
// If the player only has one city then we can't get any more from him
if (bGiveUpCities && iPercentCitiesGiveUp > 0 && pLosingPlayer->getNumCities() > 1)
{
int iTotalCityValue = 0;
// Create vector of the losing players' Cities so we can see which are the closest to the winner
CvWeightedVector<int> viCityValue;
// Loop through all of the loser's Cities, looking only at valid ones.
for(pLoopCity = pLosingPlayer->firstCity(&iCityLoop); pLoopCity != NULL; pLoopCity = pLosingPlayer->nextCity(&iCityLoop))
{
//do this from the winner's perspective!
int iCurrentCityValue = GetCityValueForBuyer(pLoopCity, eLosingPlayer, eWinningPlayer, true);
if (iCurrentCityValue == INT_MAX)
continue;
//add up total city value of the loser (before danger and damage adjustment)
iTotalCityValue += iCurrentCityValue;
//Remember for later
viCityValue.push_back(pLoopCity->GetID(), iCurrentCityValue);
}
// Sort the vector based on distance from winner's capital
viCityValue.SortItems();
int iSortedCityID;
// Determine the value of Cities to be given up
int iCityValueToSurrender = iTotalCityValue * iPercentCitiesGiveUp / 100;
// Loop through sorted Cities and add them to the deal if they're under the amount to give up
// Start from the back of the list, because that's where the cheapest cities are
for(int iSortedCityIndex = viCityValue.size() - 1; iSortedCityIndex > -1 ; iSortedCityIndex--)
{
iSortedCityID = viCityValue.GetElement(iSortedCityIndex);
pLoopCity = pLosingPlayer->getCity(iSortedCityID);
int iCurrentCityValue = GetCityValueForBuyer(pLoopCity, eLosingPlayer, eWinningPlayer, true);
if (iCurrentCityValue == INT_MAX)
continue;
// City is worth less than what is left to be added to the deal, so add it
if (iCurrentCityValue < iCityValueToSurrender && iCurrentCityValue > 0)
{
pDeal->AddCityTrade(eLosingPlayer, iSortedCityID);
iCityValueToSurrender -= iCurrentCityValue;
//Frontline cities count more than they're worth. Ideally they should satisfy the winner?
iCityValueToSurrender -= (pLoopCity->getDamage() * 10);
if (pLosingPlayer->GetPlotDanger(pLoopCity) > GC.getCITY_HIT_POINTS_HEALED_PER_TURN())
iCityValueToSurrender -= iCurrentCityValue / 10;
}
}
}
// Gold
int iGold = 0;
if (iPercentGoldToGive > 0)
{
iGold = pDeal->GetGoldAvailable(eLosingPlayer, TRADE_ITEM_GOLD);
iGold = iGold * iPercentGoldToGive / 100;
if(iGold > 0)
{
pDeal->AddGoldTrade(eLosingPlayer, iGold);
}
}
// Gold per turn
int iGPT = 0;
if (iPercentGPTToGive > 0)
{
iGPT = pLosingPlayer->calculateGoldRate();
int iGPTToGive = ((iGPT * iPercentGPTToGive) / 100);
if (iGPTToGive >= iGPT-2)
{
iGPTToGive -= 2;
}
if (iGPTToGive > 0)
{
pDeal->AddGoldPerTurnTrade(eLosingPlayer, iGPTToGive, iDuration);
}
}
// precalculate, it's expensive
int iCurrentNetGoldOfReceivingPlayer = GET_PLAYER(eOtherPlayer).GetTreasury()->CalculateBaseNetGold();
// Luxury Resources
if(bGiveUpLuxuryResources && iGiveUpLuxResources > 0)
{
ResourceUsageTypes eUsage;
ResourceTypes eResource;
int iResourceQuantity = 1;
int iTotalResourceValue = 0;
CvWeightedVector<int> viResourceValue;
for(int iResourceLoop = 0; iResourceLoop < GC.getNumResourceInfos(); iResourceLoop++)
{
eResource = (ResourceTypes) iResourceLoop;
const CvResourceInfo* pkResourceInfo = GC.getResourceInfo(eResource);
if (pkResourceInfo == NULL)
continue;
eUsage = pkResourceInfo->getResourceUsage();
// Can't trade bonus Resources
if (eUsage != RESOURCEUSAGE_LUXURY)
{
continue;
}
iResourceQuantity = pLosingPlayer->getNumResourceAvailable(eResource, false);
// Don't bother looking at this Resource if the other player doesn't even have any of it
if (iResourceQuantity == 0)
{
continue;
}
// Can only get 1 copy of a Luxury
if (eUsage == RESOURCEUSAGE_LUXURY)
{
iResourceQuantity = 1;
}
int iCurrentResourceValue = GetResourceValue(eResource, iResourceQuantity, GC.getGame().GetDealDuration(), true, eOtherPlayer, iCurrentNetGoldOfReceivingPlayer);
if(iCurrentResourceValue == INT_MAX)
continue;
if(iCurrentResourceValue > 0)
{
// Get total city value of the loser
iTotalResourceValue += iCurrentResourceValue;
viResourceValue.push_back(eResource, iCurrentResourceValue);
}
}
// Determine the value of Cities to be given up
int iResourceValueToSurrender = (iTotalResourceValue * iGiveUpLuxResources) / 100;
// Sort the vector based on value
viResourceValue.SortItems();
if(viResourceValue.size() > 0)
{
// Loop through sorted Cities and add them to the deal if they're under the amount to give up - start from the back of the list, because that's where the CLOSEST cities are
for(int iSortedResourceIndex = 0; iSortedResourceIndex < viResourceValue.size(); iSortedResourceIndex++)
{
ResourceTypes eResourceList = (ResourceTypes)viResourceValue.GetElement(iSortedResourceIndex);
int iCurrentResourceValue = GetResourceValue(eResourceList, 1, GC.getGame().GetDealDuration(), true, eOtherPlayer, iCurrentNetGoldOfReceivingPlayer);
if(iCurrentResourceValue == INT_MAX)
continue;
// City is worth less than what is left to be added to the deal, so add it
if(iCurrentResourceValue <= iResourceValueToSurrender && iCurrentResourceValue > 0)
{
pDeal->AddResourceTrade(eLosingPlayer, eResourceList, 1, GC.getGame().GetDealDuration());
iResourceValueToSurrender -= iCurrentResourceValue;
}
}
}
}
// Strategic Resources
if(bGiveUpStratResources && iGiveUpStratResources > 0)
{
ResourceUsageTypes eUsage;
ResourceTypes eResource;
int iResourceQuantity = 1;
int iTotalResourceValue = 0;
CvWeightedVector<int> viResourceValue;
for(int iResourceLoop = 0; iResourceLoop < GC.getNumResourceInfos(); iResourceLoop++)
{
eResource = (ResourceTypes) iResourceLoop;
const CvResourceInfo* pkResourceInfo = GC.getResourceInfo(eResource);
if (pkResourceInfo == NULL)
continue;
eUsage = pkResourceInfo->getResourceUsage();
// Can't trade bonus Resources
if (eUsage != RESOURCEUSAGE_STRATEGIC)
{
continue;
}
iResourceQuantity = pLosingPlayer->getNumResourceAvailable(eResource, false);
// Don't bother looking at this Resource if the other player doesn't even have any of it
if (iResourceQuantity == 0)
{
continue;
}
if (iResourceQuantity > 3)
{
iResourceQuantity = 3;
}
int iCurrentResourceValue = GetResourceValue(eResource, iResourceQuantity, GC.getGame().GetDealDuration(), true, eOtherPlayer, iCurrentNetGoldOfReceivingPlayer);
if(iCurrentResourceValue == INT_MAX)
continue;
if(iCurrentResourceValue > 0)
{
// Get total city value of the loser
iTotalResourceValue += iCurrentResourceValue;
viResourceValue.push_back(eResource, iCurrentResourceValue);
}
}
// Determine the value of Cities to be given up
int iResourceValueToSurrender = (iTotalResourceValue * iGiveUpStratResources) / 100;
// Sort the vector based on distance from winner's capital
viResourceValue.SortItems();
if(viResourceValue.size() > 0)
{
// Loop through sorted Cities and add them to the deal if they're under the amount to give up - start from the back of the list, because that's where the CLOSEST cities are
for(int iSortedResourceIndex = 0; iSortedResourceIndex < viResourceValue.size(); iSortedResourceIndex++)
{
ResourceTypes eResourceList = (ResourceTypes)viResourceValue.GetElement(iSortedResourceIndex);
iResourceQuantity = pLosingPlayer->getNumResourceAvailable(eResourceList, false);
if (iResourceQuantity > 3)
{
iResourceQuantity = 3;
}
int iCurrentResourceValue = GetResourceValue(eResourceList, iResourceQuantity, GC.getGame().GetDealDuration(), true, eOtherPlayer, iCurrentNetGoldOfReceivingPlayer);
if(iCurrentResourceValue == INT_MAX)
continue;
// City is worth less than what is left to be added to the deal, so add it
if(iCurrentResourceValue < iResourceValueToSurrender && iCurrentResourceValue > 0)
{
pDeal->AddResourceTrade(eLosingPlayer, eResourceList, iResourceQuantity, GC.getGame().GetDealDuration());
iResourceValueToSurrender -= iCurrentResourceValue;
}
}
}
}
#if defined(MOD_DIPLOMACY_CIV4_FEATURES)
if(MOD_DIPLOMACY_CIV4_FEATURES && bBecomeMyVassal)
{
pDeal->AddVassalageTrade(eLosingPlayer);
}
if(MOD_DIPLOMACY_CIV4_FEATURES && bRevokeMyVassals)
{
pDeal->AddRevokeVassalageTrade(eLosingPlayer);
}
#endif
}