diff --git a/(1) Community Patch/Core Files/Core Tables/DifficultyTables.sql b/(1) Community Patch/Core Files/Core Tables/DifficultyTables.sql
index b0a7c2d20b..ee42fbf4e6 100644
--- a/(1) Community Patch/Core Files/Core Tables/DifficultyTables.sql
+++ b/(1) Community Patch/Core Files/Core Tables/DifficultyTables.sql
@@ -1,3 +1,7 @@
+-- Delete the data in the difficulty tables, replaced in DifficultyTables.xml
+DELETE FROM HandicapInfo_FreeTechs;
+DELETE FROM HandicapInfo_AIFreeTechs;
+DELETE FROM HandicapInfo_Goodies; -- This one is replaced at the end of this file instead
DELETE FROM HandicapInfos;
-- This code is necessary to avoid a UI glitch where difficulty levels do not display properly on game creation, do not remove it
@@ -226,3 +230,53 @@ VALUES
('GOODY_GOLDEN_AGE', 'TXT_KEY_GOODY_GOLDEN_AGE', 'TXT_KEY_GOODY_CHOOSE_GOLDEN_AGE', 0, 200, 0, 0),
('GOODY_TILES', 'TXT_KEY_GOODY_TILES', 'TXT_KEY_GOODY_CHOOSE_FREE_TILES', 0, 0, 4, 0),
('GOODY_SCIENCE', 'TXT_KEY_GOODY_SCIENCE', 'TXT_KEY_GOODY_CHOOSE_SCIENCE', 0, 0, 0, 35);
+
+-- Re-add Goody Hut rewards
+CREATE TEMP TABLE HandicapsList (
+ HandicapType text
+);
+
+INSERT INTO HandicapsList
+ (HandicapType)
+VALUES
+ ('HANDICAP_SETTLER'),
+ ('HANDICAP_CHIEFTAIN'),
+ ('HANDICAP_WARLORD'),
+ ('HANDICAP_PRINCE'),
+ ('HANDICAP_KING'),
+ ('HANDICAP_EMPEROR'),
+ ('HANDICAP_IMMORTAL'),
+ ('HANDICAP_DEITY'),
+ ('HANDICAP_AI_DEFAULT');
+
+CREATE TEMP TABLE GoodyHutRewards (
+ GoodyType text
+);
+
+INSERT INTO GoodyHutRewards
+ (GoodyType)
+VALUES
+ ('GOODY_POPULATION'),
+ ('GOODY_CULTURE'),
+ ('GOODY_PANTHEON_FAITH'),
+ ('GOODY_PROPHET_FAITH'),
+ ('GOODY_GOLD'),
+ ('GOODY_MAP'),
+ ('GOODY_TECH'),
+ ('GOODY_REVEAL_NEARBY_BARBS'),
+ ('GOODY_UPGRADE_UNIT');
+
+-- Settler-exclusive rewards
+INSERT INTO HandicapInfo_Goodies
+ ('HANDICAP_SETTLER', 'GOODY_WORKER'),
+ ('HANDICAP_SETTLER', 'GOODY_SETTLER');
+
+-- General rewards
+INSERT INTO HandicapInfo_Goodies
+ (HandicapType, GoodyType)
+SELECT
+ a.HandicapType, b.GoodyType
+FROM HandicapsList a, GoodyHutRewards b;
+
+DROP TABLE HandicapsList;
+DROP TABLE GoodyHutRewards;
\ No newline at end of file
diff --git a/(1) Community Patch/Core Files/Core Tables/DifficultyTables.xml b/(1) Community Patch/Core Files/Core Tables/DifficultyTables.xml
index f91da55ef2..a0b97c5ecf 100644
--- a/(1) Community Patch/Core Files/Core Tables/DifficultyTables.xml
+++ b/(1) Community Patch/Core Files/Core Tables/DifficultyTables.xml
@@ -1,6 +1,6 @@
-
0
@@ -1065,348 +847,224 @@
TECH_ARCHERY
-
-
-
- HANDICAP_SETTLER
- GOODY_POPULATION
-
-
- HANDICAP_SETTLER
- GOODY_CULTURE
-
-
- HANDICAP_SETTLER
- GOODY_PANTHEON_FAITH
-
-
- HANDICAP_SETTLER
- GOODY_PROPHET_FAITH
-
-
- HANDICAP_SETTLER
- GOODY_GOLD
-
-
- HANDICAP_SETTLER
- GOODY_MAP
-
-
- HANDICAP_SETTLER
- GOODY_TECH
-
-
- HANDICAP_SETTLER
- GOODY_REVEAL_NEARBY_BARBS
-
-
- HANDICAP_SETTLER
- GOODY_UPGRADE_UNIT
-
-
-
- HANDICAP_SETTLER
- GOODY_WORKER
-
-
- HANDICAP_SETTLER
- GOODY_SETTLER
-
-
-
- HANDICAP_CHIEFTAIN
- GOODY_POPULATION
-
-
- HANDICAP_CHIEFTAIN
- GOODY_CULTURE
-
-
- HANDICAP_CHIEFTAIN
- GOODY_PANTHEON_FAITH
-
-
- HANDICAP_CHIEFTAIN
- GOODY_PROPHET_FAITH
-
-
- HANDICAP_CHIEFTAIN
- GOODY_GOLD
-
-
- HANDICAP_CHIEFTAIN
- GOODY_MAP
-
-
- HANDICAP_CHIEFTAIN
- GOODY_TECH
-
-
- HANDICAP_CHIEFTAIN
- GOODY_REVEAL_NEARBY_BARBS
-
-
- HANDICAP_CHIEFTAIN
- GOODY_UPGRADE_UNIT
-
-
-
- HANDICAP_WARLORD
- GOODY_POPULATION
-
-
- HANDICAP_WARLORD
- GOODY_CULTURE
-
-
- HANDICAP_WARLORD
- GOODY_PANTHEON_FAITH
-
-
- HANDICAP_WARLORD
- GOODY_PROPHET_FAITH
-
-
- HANDICAP_WARLORD
- GOODY_GOLD
-
-
- HANDICAP_WARLORD
- GOODY_MAP
-
-
- HANDICAP_WARLORD
- GOODY_TECH
-
-
- HANDICAP_WARLORD
- GOODY_REVEAL_NEARBY_BARBS
-
-
- HANDICAP_WARLORD
- GOODY_UPGRADE_UNIT
-
-
-
- HANDICAP_PRINCE
- GOODY_POPULATION
-
-
- HANDICAP_PRINCE
- GOODY_CULTURE
-
-
- HANDICAP_PRINCE
- GOODY_PANTHEON_FAITH
-
-
- HANDICAP_PRINCE
- GOODY_PROPHET_FAITH
-
-
- HANDICAP_PRINCE
- GOODY_GOLD
-
-
- HANDICAP_PRINCE
- GOODY_MAP
-
-
- HANDICAP_PRINCE
- GOODY_TECH
-
-
- HANDICAP_PRINCE
- GOODY_REVEAL_NEARBY_BARBS
-
-
- HANDICAP_PRINCE
- GOODY_UPGRADE_UNIT
-
-
-
- HANDICAP_KING
- GOODY_POPULATION
-
-
- HANDICAP_KING
- GOODY_CULTURE
-
-
- HANDICAP_KING
- GOODY_PANTHEON_FAITH
-
-
- HANDICAP_KING
- GOODY_PROPHET_FAITH
-
-
- HANDICAP_KING
- GOODY_GOLD
-
-
- HANDICAP_KING
- GOODY_MAP
-
-
- HANDICAP_KING
- GOODY_TECH
-
-
- HANDICAP_KING
- GOODY_REVEAL_NEARBY_BARBS
-
-
- HANDICAP_KING
- GOODY_UPGRADE_UNIT
-
-
-
- HANDICAP_EMPEROR
- GOODY_POPULATION
-
-
- HANDICAP_EMPEROR
- GOODY_CULTURE
-
-
- HANDICAP_EMPEROR
- GOODY_PANTHEON_FAITH
-
-
- HANDICAP_EMPEROR
- GOODY_PROPHET_FAITH
-
-
- HANDICAP_EMPEROR
- GOODY_GOLD
-
-
- HANDICAP_EMPEROR
- GOODY_MAP
-
-
- HANDICAP_EMPEROR
- GOODY_TECH
-
-
- HANDICAP_EMPEROR
- GOODY_REVEAL_NEARBY_BARBS
-
-
- HANDICAP_EMPEROR
- GOODY_UPGRADE_UNIT
-
-
-
- HANDICAP_IMMORTAL
- GOODY_POPULATION
-
-
- HANDICAP_IMMORTAL
- GOODY_CULTURE
-
-
- HANDICAP_IMMORTAL
- GOODY_PANTHEON_FAITH
-
-
- HANDICAP_IMMORTAL
- GOODY_PROPHET_FAITH
-
-
- HANDICAP_IMMORTAL
- GOODY_GOLD
-
-
- HANDICAP_IMMORTAL
- GOODY_MAP
-
-
- HANDICAP_IMMORTAL
- GOODY_TECH
-
-
- HANDICAP_IMMORTAL
- GOODY_REVEAL_NEARBY_BARBS
-
-
- HANDICAP_IMMORTAL
- GOODY_UPGRADE_UNIT
-
-
-
- HANDICAP_DEITY
- GOODY_POPULATION
-
-
- HANDICAP_DEITY
- GOODY_CULTURE
-
-
- HANDICAP_DEITY
- GOODY_PANTHEON_FAITH
-
-
- HANDICAP_DEITY
- GOODY_PROPHET_FAITH
-
-
- HANDICAP_DEITY
- GOODY_GOLD
-
-
- HANDICAP_DEITY
- GOODY_MAP
-
-
- HANDICAP_DEITY
- GOODY_TECH
-
-
- HANDICAP_DEITY
- GOODY_REVEAL_NEARBY_BARBS
-
-
- HANDICAP_DEITY
- GOODY_UPGRADE_UNIT
-
-
-
- HANDICAP_AI_DEFAULT
- GOODY_POPULATION
-
-
- HANDICAP_AI_DEFAULT
- GOODY_CULTURE
-
-
- HANDICAP_AI_DEFAULT
- GOODY_PANTHEON_FAITH
-
-
- HANDICAP_AI_DEFAULT
- GOODY_PROPHET_FAITH
-
-
- HANDICAP_AI_DEFAULT
- GOODY_GOLD
-
-
- HANDICAP_AI_DEFAULT
- GOODY_MAP
-
-
- HANDICAP_AI_DEFAULT
- GOODY_TECH
-
-
- HANDICAP_AI_DEFAULT
- GOODY_REVEAL_NEARBY_BARBS
-
-
- HANDICAP_AI_DEFAULT
- GOODY_UPGRADE_UNIT
-
-
-
\ No newline at end of file
+
+
\ No newline at end of file
diff --git a/(1) Community Patch/Core Files/Core Values/CoreDefines.sql b/(1) Community Patch/Core Files/Core Values/CoreDefines.sql
index 8e3af5643b..e57cfa3cfd 100644
--- a/(1) Community Patch/Core Files/Core Values/CoreDefines.sql
+++ b/(1) Community Patch/Core Files/Core Values/CoreDefines.sql
@@ -1497,6 +1497,7 @@ INSERT INTO Defines (Name, Value) SELECT 'VASSALAGE_VASSAL_MASTER_CITY_PERCENT_T
INSERT INTO Defines (Name, Value) SELECT 'VASSALAGE_VASSAL_MASTER_POP_PERCENT_THRESHOLD', 60;
INSERT INTO Defines (Name, Value) SELECT 'VASSALAGE_CAPITULATE_BASE_THRESHOLD', 100; -- How likely is a vassal to voluntarily capitulate?
+INSERT INTO Defines (Name, Value) SELECT 'VASSALAGE_LIBERATE_BASE_THRESHOLD', 100; -- How likely is a master to voluntarily liberate a vassal?
-- Border growth tile selection
UPDATE Defines SET Value = 200 WHERE Name = 'PLOT_INFLUENCE_RING_COST';
diff --git a/(2) Vox Populi/Database Changes/Difficulty/DifficultyChanges.sql b/(2) Vox Populi/Database Changes/Difficulty/DifficultyChanges.sql
index bf778a7ee2..bbba135c28 100644
--- a/(2) Vox Populi/Database Changes/Difficulty/DifficultyChanges.sql
+++ b/(2) Vox Populi/Database Changes/Difficulty/DifficultyChanges.sql
@@ -1,3 +1,57 @@
+-- New Goody Hut rewards
+CREATE TEMP TABLE HandicapsList (
+ HandicapType text
+);
+
+INSERT INTO HandicapsList
+ (HandicapType)
+VALUES
+ ('HANDICAP_SETTLER'),
+ ('HANDICAP_CHIEFTAIN'),
+ ('HANDICAP_WARLORD'),
+ ('HANDICAP_PRINCE'),
+ ('HANDICAP_KING'),
+ ('HANDICAP_EMPEROR'),
+ ('HANDICAP_IMMORTAL'),
+ ('HANDICAP_DEITY'),
+ ('HANDICAP_AI_DEFAULT');
+
+CREATE TEMP TABLE GoodyHutRewards (
+ GoodyType text
+);
+
+INSERT INTO GoodyHutRewards
+ (GoodyType)
+VALUES
+ ('GOODY_POPULATION'),
+ ('GOODY_CULTURE'),
+ ('GOODY_PANTHEON_FAITH'),
+ ('GOODY_PROPHET_FAITH'),
+ ('GOODY_GOLD'),
+ ('GOODY_MAP'),
+ ('GOODY_UPGRADE_UNIT'),
+ ('GOODY_PRODUCTION'),
+ ('GOODY_GOLDEN_AGE'),
+ ('GOODY_TILES'),
+ ('GOODY_SCIENCE');
+
+-- Settler-exclusive rewards
+INSERT INTO HandicapInfo_Goodies
+ ('HANDICAP_SETTLER', 'GOODY_WORKER'),
+ ('HANDICAP_SETTLER', 'GOODY_SETTLER');
+
+-- General rewards
+INSERT INTO HandicapInfo_Goodies
+ (HandicapType, GoodyType)
+SELECT
+ a.HandicapType, b.GoodyType
+FROM HandicapsList a, GoodyHutRewards b;
+
+DROP TABLE HandicapsList;
+DROP TABLE GoodyHutRewards;
+
+
+
CREATE TEMP TABLE TriggerYields (
HistoricEventType text,
YieldType text
diff --git a/(2) Vox Populi/Database Changes/Difficulty/DifficultyChanges.xml b/(2) Vox Populi/Database Changes/Difficulty/DifficultyChanges.xml
index 7a84d3a84b..18d12c898a 100644
--- a/(2) Vox Populi/Database Changes/Difficulty/DifficultyChanges.xml
+++ b/(2) Vox Populi/Database Changes/Difficulty/DifficultyChanges.xml
@@ -1,6 +1,6 @@
@@ -958,420 +739,226 @@
100
-
-
-
- HANDICAP_SETTLER
- GOODY_POPULATION
-
-
- HANDICAP_SETTLER
- GOODY_CULTURE
-
-
- HANDICAP_SETTLER
- GOODY_PANTHEON_FAITH
-
-
- HANDICAP_SETTLER
- GOODY_PROPHET_FAITH
-
-
- HANDICAP_SETTLER
- GOODY_GOLD
-
-
- HANDICAP_SETTLER
- GOODY_MAP
-
-
- HANDICAP_SETTLER
- GOODY_UPGRADE_UNIT
-
-
- HANDICAP_SETTLER
- GOODY_PRODUCTION
-
-
- HANDICAP_SETTLER
- GOODY_GOLDEN_AGE
-
-
- HANDICAP_SETTLER
- GOODY_TILES
-
-
- HANDICAP_SETTLER
- GOODY_SCIENCE
-
-
-
- HANDICAP_SETTLER
- GOODY_WORKER
-
-
- HANDICAP_SETTLER
- GOODY_SETTLER
-
-
-
- HANDICAP_CHIEFTAIN
- GOODY_POPULATION
-
-
- HANDICAP_CHIEFTAIN
- GOODY_CULTURE
-
-
- HANDICAP_CHIEFTAIN
- GOODY_PANTHEON_FAITH
-
-
- HANDICAP_CHIEFTAIN
- GOODY_PROPHET_FAITH
-
-
- HANDICAP_CHIEFTAIN
- GOODY_GOLD
-
-
- HANDICAP_CHIEFTAIN
- GOODY_MAP
-
-
- HANDICAP_CHIEFTAIN
- GOODY_UPGRADE_UNIT
-
-
- HANDICAP_CHIEFTAIN
- GOODY_PRODUCTION
-
-
- HANDICAP_CHIEFTAIN
- GOODY_GOLDEN_AGE
-
-
- HANDICAP_CHIEFTAIN
- GOODY_TILES
-
-
- HANDICAP_CHIEFTAIN
- GOODY_SCIENCE
-
-
-
- HANDICAP_WARLORD
- GOODY_POPULATION
-
-
- HANDICAP_WARLORD
- GOODY_CULTURE
-
-
- HANDICAP_WARLORD
- GOODY_PANTHEON_FAITH
-
-
- HANDICAP_WARLORD
- GOODY_PROPHET_FAITH
-
-
- HANDICAP_WARLORD
- GOODY_GOLD
-
-
- HANDICAP_WARLORD
- GOODY_MAP
-
-
- HANDICAP_WARLORD
- GOODY_UPGRADE_UNIT
-
-
- HANDICAP_WARLORD
- GOODY_PRODUCTION
-
-
- HANDICAP_WARLORD
- GOODY_GOLDEN_AGE
-
-
- HANDICAP_WARLORD
- GOODY_TILES
-
-
- HANDICAP_WARLORD
- GOODY_SCIENCE
-
-
-
- HANDICAP_PRINCE
- GOODY_POPULATION
-
-
- HANDICAP_PRINCE
- GOODY_CULTURE
-
-
- HANDICAP_PRINCE
- GOODY_PANTHEON_FAITH
-
-
- HANDICAP_PRINCE
- GOODY_PROPHET_FAITH
-
-
- HANDICAP_PRINCE
- GOODY_GOLD
-
-
- HANDICAP_PRINCE
- GOODY_MAP
-
-
- HANDICAP_PRINCE
- GOODY_UPGRADE_UNIT
-
-
- HANDICAP_PRINCE
- GOODY_PRODUCTION
-
-
- HANDICAP_PRINCE
- GOODY_GOLDEN_AGE
-
-
- HANDICAP_PRINCE
- GOODY_TILES
-
-
- HANDICAP_PRINCE
- GOODY_SCIENCE
-
-
-
- HANDICAP_KING
- GOODY_POPULATION
-
-
- HANDICAP_KING
- GOODY_CULTURE
-
-
- HANDICAP_KING
- GOODY_PANTHEON_FAITH
-
-
- HANDICAP_KING
- GOODY_PROPHET_FAITH
-
-
- HANDICAP_KING
- GOODY_GOLD
-
-
- HANDICAP_KING
- GOODY_MAP
-
-
- HANDICAP_KING
- GOODY_UPGRADE_UNIT
-
-
- HANDICAP_KING
- GOODY_PRODUCTION
-
-
- HANDICAP_KING
- GOODY_GOLDEN_AGE
-
-
- HANDICAP_KING
- GOODY_TILES
-
-
- HANDICAP_KING
- GOODY_SCIENCE
-
-
-
- HANDICAP_EMPEROR
- GOODY_POPULATION
-
-
- HANDICAP_EMPEROR
- GOODY_CULTURE
-
-
- HANDICAP_EMPEROR
- GOODY_PANTHEON_FAITH
-
-
- HANDICAP_EMPEROR
- GOODY_PROPHET_FAITH
-
-
- HANDICAP_EMPEROR
- GOODY_GOLD
-
-
- HANDICAP_EMPEROR
- GOODY_MAP
-
-
- HANDICAP_EMPEROR
- GOODY_UPGRADE_UNIT
-
-
- HANDICAP_EMPEROR
- GOODY_PRODUCTION
-
-
- HANDICAP_EMPEROR
- GOODY_GOLDEN_AGE
-
-
- HANDICAP_EMPEROR
- GOODY_TILES
-
-
- HANDICAP_EMPEROR
- GOODY_SCIENCE
-
-
-
- HANDICAP_IMMORTAL
- GOODY_POPULATION
-
-
- HANDICAP_IMMORTAL
- GOODY_CULTURE
-
-
- HANDICAP_IMMORTAL
- GOODY_PANTHEON_FAITH
-
-
- HANDICAP_IMMORTAL
- GOODY_PROPHET_FAITH
-
-
- HANDICAP_IMMORTAL
- GOODY_GOLD
-
-
- HANDICAP_IMMORTAL
- GOODY_MAP
-
-
- HANDICAP_IMMORTAL
- GOODY_UPGRADE_UNIT
-
-
- HANDICAP_IMMORTAL
- GOODY_PRODUCTION
-
-
- HANDICAP_IMMORTAL
- GOODY_GOLDEN_AGE
-
-
- HANDICAP_IMMORTAL
- GOODY_TILES
-
-
- HANDICAP_IMMORTAL
- GOODY_SCIENCE
-
-
-
- HANDICAP_DEITY
- GOODY_POPULATION
-
-
- HANDICAP_DEITY
- GOODY_CULTURE
-
-
- HANDICAP_DEITY
- GOODY_PANTHEON_FAITH
-
-
- HANDICAP_DEITY
- GOODY_PROPHET_FAITH
-
-
- HANDICAP_DEITY
- GOODY_GOLD
-
-
- HANDICAP_DEITY
- GOODY_MAP
-
-
- HANDICAP_DEITY
- GOODY_UPGRADE_UNIT
-
-
- HANDICAP_DEITY
- GOODY_PRODUCTION
-
-
- HANDICAP_DEITY
- GOODY_GOLDEN_AGE
-
-
- HANDICAP_DEITY
- GOODY_TILES
-
-
- HANDICAP_DEITY
- GOODY_SCIENCE
-
-
-
- HANDICAP_AI_DEFAULT
- GOODY_POPULATION
-
-
- HANDICAP_AI_DEFAULT
- GOODY_CULTURE
-
-
- HANDICAP_AI_DEFAULT
- GOODY_PANTHEON_FAITH
-
-
- HANDICAP_AI_DEFAULT
- GOODY_PROPHET_FAITH
-
-
- HANDICAP_AI_DEFAULT
- GOODY_GOLD
-
-
- HANDICAP_AI_DEFAULT
- GOODY_MAP
-
-
- HANDICAP_AI_DEFAULT
- GOODY_UPGRADE_UNIT
-
-
- HANDICAP_AI_DEFAULT
- GOODY_PRODUCTION
-
-
- HANDICAP_AI_DEFAULT
- GOODY_GOLDEN_AGE
-
-
- HANDICAP_AI_DEFAULT
- GOODY_TILES
-
-
- HANDICAP_AI_DEFAULT
- GOODY_SCIENCE
-
-
-
\ No newline at end of file
+
+
\ No newline at end of file
diff --git a/(2) Vox Populi/Database Changes/Difficulty/PreDifficultyChanges.sql b/(2) Vox Populi/Database Changes/Difficulty/PreDifficultyChanges.sql
index f4395aa248..cab2e59c92 100644
--- a/(2) Vox Populi/Database Changes/Difficulty/PreDifficultyChanges.sql
+++ b/(2) Vox Populi/Database Changes/Difficulty/PreDifficultyChanges.sql
@@ -1,5 +1,7 @@
--- Delete the data in the difficulty tables, replaced in DifficultyChanges.xml
+-- Delete the data in the difficulty tables, replaced in DifficultyChanges.xml and GoodyHutChanges.sql
+DELETE FROM HandicapInfo_DifficultyBonus;
+DELETE FROM HandicapInfo_AIDifficultyBonus;
DELETE FROM HandicapInfo_FreeTechs;
DELETE FROM HandicapInfo_AIFreeTechs;
DELETE FROM HandicapInfo_Goodies;
-DELETE FROM HandicapInfos;
+DELETE FROM HandicapInfos;
\ No newline at end of file
diff --git a/CvGameCoreDLLUtil/include/CvDllInterfaces2.h b/CvGameCoreDLLUtil/include/CvDllInterfaces2.h
index 732c810d30..c34822ad7a 100644
--- a/CvGameCoreDLLUtil/include/CvDllInterfaces2.h
+++ b/CvGameCoreDLLUtil/include/CvDllInterfaces2.h
@@ -103,8 +103,7 @@ class ICvNetMessageHandler3 : public ICvNetMessageHandler2
virtual void DLLCALL ResponseGoodyChoice(PlayerTypes ePlayer, int iPlotX, int iPlotY, GoodyTypes eGoody, int iUnitID) = 0;
virtual void DLLCALL ResponseSetSwappableGreatWork(PlayerTypes ePlayer, int iWorkClass, int iWorkIndex) = 0;
virtual void DLLCALL ResponseSwapGreatWorks(PlayerTypes ePlayer1, int iWorkIndex1, PlayerTypes PlayerTypes2, int iWorkIndex2) = 0;
- virtual void DLLCALL ResponseMoveGreatWorks(PlayerTypes ePlayer, int iCity1, int iBuildingClass1, int iWorkIndex1,
- int iCity2, int iBuildingClass2, int iWorkIndex2) = 0;
+ virtual void DLLCALL ResponseMoveGreatWorks(PlayerTypes ePlayer, int iCity1, int iBuildingClass1, int iWorkIndex1, int iCity2, int iBuildingClass2, int iWorkIndex2) = 0;
virtual void DLLCALL ResponseChangeIdeology(PlayerTypes ePlayer) = 0;
};
diff --git a/CvGameCoreDLL_Expansion2/CvDiplomacyAI.cpp b/CvGameCoreDLL_Expansion2/CvDiplomacyAI.cpp
index d078484a83..aed1b9ebcc 100644
--- a/CvGameCoreDLL_Expansion2/CvDiplomacyAI.cpp
+++ b/CvGameCoreDLL_Expansion2/CvDiplomacyAI.cpp
@@ -398,6 +398,7 @@ void CvDiplomacyAI::Init(CvPlayer* pPlayer)
m_bAvoidDeals = false;
m_bIgnoreWarmonger = false;
+ m_eVassalPlayerToLiberate = NO_PLAYER;
m_aGreetPlayers.clear();
@@ -8840,6 +8841,17 @@ void CvDiplomacyAI::SetIgnoreWarmonger(bool bValue)
m_bIgnoreWarmonger = bValue;
}
+// Do we want to liberate this player on this turn? Temporary non-serialized value.
+PlayerTypes CvDiplomacyAI::GetVassalPlayerToLiberate() const
+{
+ return m_eVassalPlayerToLiberate;
+}
+
+void CvDiplomacyAI::SetVassalPlayerToLiberate(PlayerTypes ePlayer)
+{
+ m_eVassalPlayerToLiberate = ePlayer;
+}
+
/// Who was the last Minor ePlayer bullied that we were protecting?
PlayerTypes CvDiplomacyAI::GetOtherPlayerProtectedMinorBullied(PlayerTypes ePlayer) const
{
@@ -14232,7 +14244,7 @@ int CvDiplomacyAI::CalculateGoldPerTurnLostFromWar(PlayerTypes ePlayer)
// Vassal taxes?
if (IsMaster(ePlayer))
{
- iGPT += GetPlayer()->GetTreasury()->GetVassalTaxContributionTimes100(ePlayer);
+ iGPT += GetPlayer()->GetTreasury()->GetMyShareOfVassalTaxes(GET_PLAYER(ePlayer).getTeam());
}
vector vDefensiveWarAllies = GetDefensiveWarAllies(ePlayer, /*bIncludeMinors*/ true, /*bReverseMode*/ true, /*bNewWarsOnly*/ true);
@@ -29119,13 +29131,14 @@ bool CvDiplomacyAI::IsPotentialMilitaryTargetOrThreat(PlayerTypes ePlayer, bool
if (GET_PLAYER(*it).GetDiplomacyAI()->IsPlayerCapturedCapital(vMyTeam[i]) || GET_PLAYER(*it).GetDiplomacyAI()->IsPlayerCapturedHolyCity(vMyTeam[i]))
return true;
// Run these checks last because they're more expensive.
- if (GET_PLAYER(*it).GetNumOurCitiesOwnedBy(vMyTeam[i]) > 0)
- return true;
if (GET_PLAYER(*it).GetDiplomacyAI()->IsUntrustworthy(vMyTeam[i]))
return true;
if (bVassal && pDiplo->GetVassalTreatmentLevel(*it) <= VASSAL_TREATMENT_MISTREATED)
return true;
}
+
+ if (GET_PLAYER(*it).GetNumOurCitiesOwnedBy(GetID()) > 0)
+ return true;
}
}
}
@@ -32222,6 +32235,8 @@ void CvDiplomacyAI::DoMakePublicDeclaration(PublicDeclarationTypes eDeclaration,
/// Any Major Civs we want to chat with?
void CvDiplomacyAI::DoContactMajorCivs()
{
+ DetermineVassalToLiberate();
+
// NOTE: This function is broken up into two sections: AI contact opportunities, and then human contact opportunities
// This is to prevent a nasty bug where the AI will continue making decisions as the diplo screen is firing up. Making humans
// handled at the end prevents the Diplo AI from having this problem
@@ -55400,224 +55415,386 @@ void CvDiplomacyAI::DoLiberateMyVassalStatement(PlayerTypes ePlayer, DiploStatem
CvAssertMsg(ePlayer >= 0, "DIPLOMACY_AI: Invalid Player Index. Please send Jon this with your last 5 autosaves and what changelist # you're playing.");
CvAssertMsg(ePlayer < MAX_MAJOR_CIVS, "DIPLOMACY_AI: Invalid Player Index. Please send Jon this with your last 5 autosaves and what changelist # you're playing.");
- if(eStatement == NO_DIPLO_STATEMENT_TYPE)
+ if (eStatement == NO_DIPLO_STATEMENT_TYPE)
{
- // Has to be my vassal
- if(GET_PLAYER(ePlayer).GetDiplomacyAI()->IsVassal(GetID()))
+ if (GetVassalPlayerToLiberate() == ePlayer)
{
DiploStatementTypes eTempStatement = DIPLO_STATEMENT_LIBERATE_VASSAL;
- int iTurnsBetweenStatement = 25;
+ int iTurnsBetweenStatement = 1;
- if(IsWantToLiberateVassal(ePlayer))
+ if (GetNumTurnsSinceStatementSent(ePlayer, eTempStatement) >= iTurnsBetweenStatement)
{
- if(GetNumTurnsSinceStatementSent(ePlayer, eTempStatement) >= iTurnsBetweenStatement)
+ eStatement = eTempStatement;
+ }
+ }
+ }
+}
+
+void CvDiplomacyAI::DetermineVassalToLiberate()
+{
+ if (GC.getGame().isOption(GAMEOPTION_ALWAYS_WAR))
+ return;
+
+ // Humans make all the decisions!
+ if (m_pPlayer->IsAITeammateOfHuman())
+ {
+ SetVassalPlayerToLiberate(NO_PLAYER);
+ return;
+ }
+
+ // Only run this check if we're the team leader
+ PlayerTypes eMasterTeamLeader = GET_TEAM(GetTeam()).getLeaderID();
+ if (eMasterTeamLeader != GetID())
+ {
+ SetVassalPlayerToLiberate(NO_PLAYER);
+ return;
+ }
+
+ int iBestScoreForLiberate = INT_MIN;
+ PlayerTypes eBestCandidate = NO_PLAYER;
+ for (int iPlayerLoop = 0; iPlayerLoop < MAX_MAJOR_CIVS; iPlayerLoop++)
+ {
+ PlayerTypes eLoopPlayer = (PlayerTypes) iPlayerLoop;
+ if (!GET_PLAYER(eLoopPlayer).isAlive() || GET_PLAYER(eLoopPlayer).getNumCities() == 0)
+ continue;
+
+ if (GET_PLAYER(eLoopPlayer).IsAITeammateOfHuman())
+ continue;
+
+ // Must be either human or the team leader
+ TeamTypes eTeam = GET_PLAYER(eLoopPlayer).getTeam();
+ if (GET_TEAM(eTeam).getLeaderID() == eLoopPlayer || GET_PLAYER(eLoopPlayer).isHuman())
+ {
+ // If human, must be contactable
+ if (GET_PLAYER(eLoopPlayer).isHuman())
+ {
+ if (GC.getGame().IsAllDiploStatementsDisabled())
+ continue;
+
+ if (GC.getGame().isReallyNetworkMultiPlayer() && !MOD_ACTIVE_DIPLOMACY)
+ continue;
+ }
+
+ int iScoreForLiberate = 0;
+ if (IsWantToLiberateVassal(eLoopPlayer, iScoreForLiberate))
+ {
+ if (iScoreForLiberate > iBestScoreForLiberate)
{
- eStatement = eTempStatement;
+ eBestCandidate = eLoopPlayer;
+ iBestScoreForLiberate = iScoreForLiberate;
}
}
}
}
+
+ SetVassalPlayerToLiberate(eBestCandidate);
}
/// Do we want to liberate ePlayer's team?
-bool CvDiplomacyAI::IsWantToLiberateVassal(PlayerTypes ePlayer) const
+bool CvDiplomacyAI::IsWantToLiberateVassal(PlayerTypes ePlayer, int& iScoreForLiberate) const
{
- CvAssertMsg(ePlayer >= 0, "DIPLOMACY_AI: Invalid Player Index. Please send Jon this with your last 5 autosaves and what changelist # you're playing.");
- CvAssertMsg(ePlayer < MAX_MAJOR_CIVS, "DIPLOMACY_AI: Invalid Player Index. Please send Jon this with your last 5 autosaves and what changelist # you're playing.");
-
- TeamTypes eMyTeam = GetTeam();
- CvTeam& kMyTeam = GET_TEAM(eMyTeam);
+ if (ePlayer < 0 || ePlayer >= MAX_MAJOR_CIVS) UNREACHABLE();
+ // Can't liberate? Abort!
TeamTypes eVassalTeam = GET_PLAYER(ePlayer).getTeam();
- CvTeam& kVassalTeam = GET_TEAM(eVassalTeam);
+ if (!GET_TEAM(GetTeam()).CanLiberateVassal(eVassalTeam))
+ return false;
- // Can't liberate? Abort!
- if(!kMyTeam.CanLiberateVassal(eVassalTeam))
+ // Do not liberate if they have at least 90% of our population
+ int iNumPop = GET_TEAM(GetTeam()).getTotalPopulation();
+ int iNumVassalPop = GET_TEAM(eVassalTeam).getTotalPopulation();
+ if ((iNumVassalPop * 100) >= (iNumPop * 90))
return false;
- // Shadow AI can't make this decision for teammate
- if(kMyTeam.isHuman() && !m_pPlayer->isHuman())
+ // Do not liberate if they own other players' capitals
+ if (GET_PLAYER(ePlayer).GetNumCapitalCities() > 0)
return false;
- //World conqueror and this guy lost his capital? He's a perma-vassal.
- if (m_pPlayer->GetDiplomacyAI()->IsGoingForWorldConquest() && GET_PLAYER(ePlayer).IsHasLostCapital())
+ // Do not liberate if they own any of our cities
+ if (m_pPlayer->GetNumOurCitiesOwnedBy(ePlayer) > 0)
return false;
- std::vector m_Masters;
- std::vector m_Vassals;
+ // If someone else previously resurrected this vassal and that team is alive, don't liberate
+ // They will probably fly into the arms of their former protector and come after us for revenge!
+ TeamTypes eLiberatedByTeam = GET_TEAM(eVassalTeam).GetLiberatedByTeam();
+ if (eLiberatedByTeam != NO_TEAM && eLiberatedByTeam != GetTeam() && GET_TEAM(eLiberatedByTeam).isAlive())
+ return false;
- for (int iPlayerLoop = 0; iPlayerLoop < MAX_MAJOR_CIVS; iPlayerLoop++)
+ // Refuse if they aren't following the one true ideology
+ if (GetPlayer()->GetPlayerPolicies()->GetLateGamePolicyTree() != NO_POLICY_BRANCH_TYPE && !IsPlayerSameIdeology(ePlayer))
+ return false;
+
+ vector vMasterTeam = GET_TEAM(GetTeam()).getPlayers();
+ vector vVassalTeam = GET_TEAM(GET_PLAYER(ePlayer).getTeam()).getPlayers();
+
+ CivApproachTypes eWorstMasterApproach = NO_CIV_APPROACH;
+ int iWorstMasterOpinion = SHRT_MIN;
+ StrengthTypes eVassalStrength = NO_STRENGTH_VALUE;
+ StrengthTypes eVassalEcoStrength = NO_STRENGTH_VALUE;
+ InfluenceLevelTypes eMasterInfluence = NO_INFLUENCE_LEVEL;
+ InfluenceLevelTypes eVassalInfluence = NO_INFLUENCE_LEVEL;
+
+ ReligionTypes eMasterReligion = NO_RELIGION;
+ int iMostFollowers = 0;
+ for (size_t i=0; iGetOwnedReligion();
+ if (eReligion != NO_RELIGION)
{
- eLoopPlayer = (PlayerTypes) iPlayerLoop;
- if(GET_PLAYER(eLoopPlayer).getTeam() == eMyTeam)
- m_Masters.push_back(&GET_PLAYER(eLoopPlayer));
- if(GET_PLAYER(eLoopPlayer).getTeam() == eVassalTeam)
- m_Vassals.push_back(&GET_PLAYER(eLoopPlayer));
+ // Performance optimization - only consider followers if there's more than one person on the master team
+ if (iMostFollowers == 0 && i + 1 >= vMasterTeam.size())
+ {
+ eMasterReligion = eReligion;
+ continue;
+ }
+
+ int iFollowers = GC.getGame().GetGameReligions()->GetNumFollowers(eMasterReligion);
+ if (iFollowers > iMostFollowers)
+ {
+ eMasterReligion = eReligion;
+ iMostFollowers = iFollowers;
+ }
}
}
- CvAssertMsg(m_Masters.size() > 0, "master team expected to be greater than size 0");
- CvAssertMsg(m_Vassals.size() > 0, "vassal team expected to be greater than size 0");
+ for (size_t i=0; i::iterator it = m_Masters.begin(); it != m_Masters.end(); ++it)
- {
- CvPlayer* pMaster = (*it);
+ CvDiplomacyAI* pDiplo = GET_PLAYER(eMaster).GetDiplomacyAI();
- iTotalGPTTimes100 += pMaster->calculateGoldRateTimes100();
+ // Do not liberate if we're going for world conquest
+ if (pDiplo->IsGoingForWorldConquest() || GET_PLAYER(eMaster).GetNumCapitalCities() > 0)
+ return false;
- // How does one master see each vassal?
- int iAverageApproachForOneMaster = 0;
- int iAverageOpinionForOneMaster = 0;
- int iAverageStrengthScoreForOneMaster = 0;
- int iAverageEcoStrengthScoreForOneMaster = 0;
+ // If we're close to winning, now is not the time to be liberating vassals!
+ if (pDiplo->IsCloseToAnyVictoryCondition())
+ return false;
+
+ // Separate check for World Conquest if the game is already won, since IsCloseToAnyVictoryCondition() will return false
+ if (GC.getGame().getWinner() != NO_TEAM && pDiplo->IsCloseToWorldConquest())
+ return false;
- for(std::vector::iterator vIt = m_Vassals.begin(); vIt != m_Vassals.end(); vIt++)
+ for (size_t j=0; jGetDiplomacyAI()->IsDenouncedPlayer(pMaster->GetID()))
+ // Check opinion and approach - care only about the worst
+ // Only liberate if everyone on both teams has neutral and positive values towards each other
+ // If vassal hates the master (due to mistreatment), master will continue mistreating them
+ int iCachedOpinionWeight = pDiplo->GetCachedOpinionWeight(eVassal) - pDiplo->GetMasterScore(eVassal); // exclude the diplo bonus they have for just being our vassal
+ CivApproachTypes eApproach = pDiplo->GetCivApproach(eVassal);
+ CivApproachTypes eVisibleApproach = GET_PLAYER(eVassal).isHuman() ? CIV_APPROACH_NEUTRAL : pDiplo->GetVisibleApproachTowardsUs(eVassal);
+ if (eApproach <= CIV_APPROACH_AFRAID || eVisibleApproach <= CIV_APPROACH_GUARDED || iCachedOpinionWeight >= /*30*/ GD_INT_GET(OPINION_THRESHOLD_COMPETITOR))
+ return false;
+ if (eApproach < eWorstMasterApproach)
+ eWorstMasterApproach = eApproach;
+ if (iCachedOpinionWeight > iWorstMasterOpinion)
+ iWorstMasterOpinion = iCachedOpinionWeight;
+
+ // Check strength compared to us - care only about the highest
+ // Do not liberate if stronger than us - could be a threat
+ StrengthTypes eStrength = pDiplo->GetRawMilitaryStrengthComparedToUs(eVassal);
+ if (eVassal > STRENGTH_AVERAGE)
return false;
+ if (eStrength > eVassalStrength)
+ eVassalStrength = eStrength;
- // Did we denounce them?
- if(pMaster->GetDiplomacyAI()->IsDenouncedPlayer(pVassal->GetID()))
+ eStrength = pDiplo->GetEconomicStrengthComparedToUs(eVassal);
+ if (eVassal > STRENGTH_AVERAGE)
return false;
+ if (eStrength > eVassalEcoStrength)
+ eVassalEcoStrength = eStrength;
- iAverageApproachForOneMaster += (int) pMaster->GetDiplomacyAI()->GetCivApproach(pVassal->GetID());
- iAverageOpinionForOneMaster += (int) pMaster->GetDiplomacyAI()->GetCivOpinion(pVassal->GetID());
- iAverageStrengthScoreForOneMaster += (int) pMaster->GetDiplomacyAI()->GetMilitaryStrengthComparedToUs(pVassal->GetID());
- iAverageEcoStrengthScoreForOneMaster += (int) pMaster->GetDiplomacyAI()->GetEconomicStrengthComparedToUs(pVassal->GetID());
-
- // Only care about the highest
- InfluenceLevelTypes eMasterInfluenceOverVassal = pMaster->GetCulture()->GetInfluenceLevel(pVassal->GetID());
- if(eMasterInfluenceOverVassal > eMasterInfluence)
- eMasterInfluence = eMasterInfluenceOverVassal;
+ // Do not liberate if endgame aggressive
+ if (pDiplo->IsEndgameAggressiveTo(eVassal))
+ return false;
+
+ // Denouncement in either direction?
+ if (pDiplo->IsDenouncedPlayer(eVassal) || pDiplo->IsDenouncedByPlayer(eVassal))
+ return false;
+
+ // Refuse if it says they're a HERETIC!
+ if (eMasterReligion != NO_RELIGION && GET_PLAYER(eVassal).GetReligions()->GetStateReligion(false) != eMasterReligion)
+ return false;
- // Only care about the highest
- InfluenceLevelTypes eVassalInfluenceOverMaster = pVassal->GetCulture()->GetInfluenceLevel(pMaster->GetID());
- if(eVassalInfluenceOverMaster > eVassalInfluence)
+ // Check cultural influence - only care about the highest / lowest
+ InfluenceLevelTypes eVassalInfluenceOverMaster = GET_PLAYER(eVassal).GetCulture()->GetInfluenceLevel(eMaster);
+
+ // Don't liberate if influential or rising towards us - could be a threat
+ if (eVassalInfluenceOverMaster >= INFLUENCE_LEVEL_INFLUENTIAL || GET_PLAYER(eVassal).GetCulture()->GetInfluenceTrend(eMaster) == INFLUENCE_TREND_RISING)
+ return false;
+ if (eVassalInfluenceOverMaster > eVassalInfluence)
eVassalInfluence = eVassalInfluenceOverMaster;
- }
- iApproachScore += iAverageApproachForOneMaster;
- iApproachScore /= m_Vassals.size();
+ InfluenceLevelTypes eMasterInfluenceOverVassal = GET_PLAYER(eMaster).GetCulture()->GetInfluenceLevel(eVassal);
- iOpinionScore += iAverageOpinionForOneMaster;
- iOpinionScore /= m_Vassals.size();
+ // Don't liberate if not influential yet and going for Cultural Victory - we could use the Tourism boost
+ if (eMasterInfluenceOverVassal < INFLUENCE_LEVEL_INFLUENTIAL && (pDiplo->IsGoingForCultureVictory() || pDiplo->IsCloseToCultureVictory()))
+ return false;
+ if (eMasterInfluenceOverVassal < eMasterInfluence)
+ eMasterInfluence = eMasterInfluenceOverVassal;
+ }
+ }
- iStrengthScore += iAverageStrengthScoreForOneMaster;
- iStrengthScore /= m_Vassals.size();
+ // Do not liberate if it would cause unhappiness or financial problems!
+ int iTotalHappinessBoost = 0;
+ bool bGoodRevenueSource = false;
+ bool bNuclearGandhiException = false;
+ int iNecessaryRevenueSource = 0;
+ int iFinancialLiability = 0;
+ for (size_t i=0; i 0)
+ return false;
+ if (GET_PLAYER(eVassal).GetDiplomacyAI()->IsNuclearGandhi(true))
+ bNuclearGandhiException = true;
+
+ iTotalHappinessBoost += GetPlayer()->GetHappinessFromVassal(eVassal);
}
+ for (size_t i=0; i 0 && GET_PLAYER(eMaster).IsEmpireUnhappy())
+ return false;
- eMasterApproach = (CivApproachTypes) iApproachScore;
- eMasterOpinion = (CivOpinionTypes) iOpinionScore;
- eVassalStrength = (StrengthTypes) iStrengthScore;
- eVassalEcoStrength = (StrengthTypes) iEcoStrengthScore;
+ int iUnhappy = GET_PLAYER(eMaster).GetUnhappinessFromCitizenNeeds();
+ int iHappy = GET_PLAYER(eMaster).GetHappinessFromCitizenNeeds() - iTotalHappinessBoost;
+ if (((iHappy * 100) / max(1, iUnhappy) / 2) < /*50*/ GD_INT_GET(UNHAPPY_THRESHOLD))
+ return false;
- CvAssertMsg(eMasterApproach >= NO_CIV_APPROACH && eMasterApproach < NUM_CIV_APPROACHES, "Something went wrong with the evaluation for approaches.");
- CvAssertMsg(eMasterOpinion >= NO_CIV_OPINION && eMasterOpinion < NUM_CIV_OPINIONS, "Something went wrong with the evaluation for opinions.");
- CvAssertMsg(eVassalStrength >= NO_STRENGTH_VALUE && eVassalStrength < NUM_STRENGTH_VALUES, "Something went wrong with the evaluation for strengths.");
- CvAssertMsg(eMasterInfluence >= NO_INFLUENCE_LEVEL && eMasterInfluence < /* hard-coded */ 6, "Something went wrong with the evaluation for opinions.");
- CvAssertMsg(eVassalInfluence >= NO_INFLUENCE_LEVEL && eVassalInfluence < /* hard-coded */ 6, "Something went wrong with the evaluation for opinions.");
+ bool bSkip = false;
+ int iRevenue = GET_PLAYER(eMaster).GetTreasury()->GetMyShareOfVassalTaxes(eVassalTeam);
+ int iExpense = GET_PLAYER(eMaster).GetTreasury()->GetVassalGoldMaintenance(eVassalTeam);
+ if (iRevenue < iExpense)
+ {
+ // We're losing more than we're gaining from this vassal, and we're going bankrupt. Not good!
+ if (GET_PLAYER(eMaster).getTurnsToBankruptcy(0) != INT_MAX)
+ {
+ // Hmm...can we rectify the situation by raising taxes on them?
+ if (GET_TEAM(GetTeam()).GetVassalTax(ePlayer) < /*25*/ GD_INT_GET(VASSALAGE_VASSAL_TAX_PERCENT_MAXIMUM))
+ {
+ int iNewRevenue = GET_PLAYER(eMaster).GetTreasury()->GetMyShareOfVassalTaxes(eVassalTeam, /*25*/ GD_INT_GET(VASSALAGE_VASSAL_TAX_PERCENT_MAXIMUM));
+ int iDifference = iNewRevenue - iRevenue;
+ if (iNewRevenue >= iExpense || GET_PLAYER(eMaster).getTurnsToBankruptcy(-iDifference) != INT_MAX)
+ {
+ // If raising taxes would bring us out of bankruptcy or equalize the expenses, don't liberate
+ return false;
+ }
+ // No? Then this vassal's bad to keep.
+ else
+ {
+ iFinancialLiability++;
+ bSkip = true;
+ }
+ }
+ else
+ {
+ iFinancialLiability++;
+ bSkip = true;
+ }
+ }
+ }
+ if (!bSkip)
+ {
+ // Good revenue source?
+ int iGoldRate = GET_PLAYER(eMaster).calculateGoldRateTimes100();
+ if (iRevenue * 100 > iGoldRate * 20)
+ bGoodRevenueSource = true;
- // If team doesn't like them, don't consider it.
- if (eMasterApproach <= CIV_APPROACH_GUARDED)
- {
- return false;
+ // Necessary revenue source?
+ if (iGoldRate - iRevenue <= 0)
+ iNecessaryRevenueSource++;
+ }
}
- // Bad opinion?
- if (eMasterOpinion <= CIV_OPINION_COMPETITOR)
- {
+ if (iNecessaryRevenueSource > iFinancialLiability)
return false;
- }
- int iScoreForLiberate = 0;
-
- // Initial score based on remaining approach
- switch(eMasterApproach)
- {
- case CIV_APPROACH_AFRAID:
- iScoreForLiberate = 100;
- break;
- case CIV_APPROACH_FRIENDLY:
- iScoreForLiberate = 50;
- break;
- case CIV_APPROACH_NEUTRAL:
- iScoreForLiberate = 20;
- break;
- default:
- CvAssertMsg(false, "IsWantToLiberateVassal(): Something went terribly wrong");
- }
+ // Base liberation score is determined by approach - either FRIENDLY or NEUTRAL
+ iScoreForLiberate = eWorstMasterApproach == CIV_APPROACH_FRIENDLY ? 10 : 0;
+
+ // Mod based on opinion - usually the most important factor
+ CivOpinionTypes eWorstMasterOpinion = CIV_OPINION_ALLY;
+ if (iWorstMasterOpinion > /*-30*/ GD_INT_GET(OPINION_THRESHOLD_FAVORABLE))
+ eWorstMasterOpinion = CIV_OPINION_NEUTRAL;
+ else if (iWorstMasterOpinion > /*-80*/ GD_INT_GET(OPINION_THRESHOLD_FRIEND))
+ eWorstMasterOpinion = CIV_OPINION_FAVORABLE;
+ else if (iWorstMasterOpinion > /*-160*/ GD_INT_GET(OPINION_THRESHOLD_ALLY))
+ eWorstMasterOpinion = CIV_OPINION_FRIEND;
- // mod based on opinion
- switch(eMasterOpinion)
+ switch (eWorstMasterOpinion)
{
case CIV_OPINION_NEUTRAL:
iScoreForLiberate += 0;
break;
case CIV_OPINION_FAVORABLE:
- iScoreForLiberate += 10;
+ iScoreForLiberate += 5;
break;
case CIV_OPINION_FRIEND:
- iScoreForLiberate += 15;
+ iScoreForLiberate += 20;
break;
case CIV_OPINION_ALLY:
- iScoreForLiberate += 25;
+ iScoreForLiberate += 40;
break;
default:
- CvAssertMsg(false, "IsWantToLiberateVassal(): Something went terribly wrong");
+ UNREACHABLE();
}
- int iGoldFromTaxesTimes100 = 0;
- // Good source of revenue for us - not so likely to break off
- for(std::vector::iterator it = m_Vassals.begin(); it != m_Vassals.end(); ++it)
+ // Financial liability - go away
+ if (iFinancialLiability > 0 && iNecessaryRevenueSource == 0)
{
- iGoldFromTaxesTimes100 += (*it)->GetTreasury()->GetExpensePerTurnFromVassalTaxesTimes100();
+ iScoreForLiberate += 1000;
}
-
- // more than 20 percent of our net GPT - less likely
- if(iGoldFromTaxesTimes100 * 100 > iTotalGPTTimes100 * 20)
+ // But also a necessary revenue source? More likely, but not guaranteed.
+ else if (iFinancialLiability > 0 && iFinancialLiability >= iNecessaryRevenueSource)
{
- iScoreForLiberate *= 50;
+ iScoreForLiberate *= 200;
iScoreForLiberate /= 100;
}
-
- // don't liberate a strong vassal - he could be a threat
- if(eVassalStrength > STRENGTH_AVERAGE ||
- eVassalEcoStrength > STRENGTH_AVERAGE)
+ // Don't liberate voluntary vassals unless they're a financial liability - they can choose to leave on their own if they don't like us
+ // Also don't liberate Gandhi unless we need to or he can't go nuclear on our ass
+ else if (bNuclearGandhiException || IsVoluntaryVassalage(ePlayer))
+ {
+ iScoreForLiberate = 0;
return false;
+ }
+ // Good source of revenue for us - not so likely to break off
+ else if (bGoodRevenueSource)
+ {
+ iScoreForLiberate *= 50;
+ iScoreForLiberate /= 100;
+ }
- switch(eVassalStrength)
+ switch (eVassalStrength)
{
- case NO_STRENGTH_VALUE:
- UNREACHABLE(); // Strengths are supposed to have been evaluated by this point.
case STRENGTH_PATHETIC:
iScoreForLiberate *= 125;
iScoreForLiberate /= 100;
@@ -55634,16 +55811,12 @@ bool CvDiplomacyAI::IsWantToLiberateVassal(PlayerTypes ePlayer) const
iScoreForLiberate *= 90;
iScoreForLiberate /= 100;
break;
- case STRENGTH_STRONG:
- case STRENGTH_POWERFUL:
- case STRENGTH_IMMENSE:
- break; // Not applicable.
+ default:
+ UNREACHABLE();
}
- switch(eVassalEcoStrength)
+ switch (eVassalEcoStrength)
{
- case NO_STRENGTH_VALUE:
- UNREACHABLE(); // Strengths are supposed to have been evaluated by this point.
case STRENGTH_PATHETIC:
iScoreForLiberate *= 125;
iScoreForLiberate /= 100;
@@ -55660,14 +55833,12 @@ bool CvDiplomacyAI::IsWantToLiberateVassal(PlayerTypes ePlayer) const
iScoreForLiberate *= 90;
iScoreForLiberate /= 100;
break;
- case STRENGTH_STRONG:
- case STRENGTH_POWERFUL:
- case STRENGTH_IMMENSE:
- break; // Not applicable.
+ default:
+ UNREACHABLE();
}
// Mod based on proximity
- switch(m_pPlayer->GetProximityToPlayer(ePlayer))
+ switch (m_pPlayer->GetProximityToPlayer(ePlayer))
{
case NO_PLAYER_PROXIMITY:
case PLAYER_PROXIMITY_DISTANT:
@@ -55689,23 +55860,17 @@ bool CvDiplomacyAI::IsWantToLiberateVassal(PlayerTypes ePlayer) const
}
// City comparison modifier
- int iNumPop = kMyTeam.getTotalPopulation();
- int iNumVassalPop = kVassalTeam.getTotalPopulation();
-
- if(iNumVassalPop >= iNumPop)
- return false;
-
- if(iNumVassalPop * 100 > iNumPop * 75)
+ if (iNumVassalPop * 100 > iNumPop * 75)
{
iScoreForLiberate *= 75;
iScoreForLiberate /= 100;
}
- else if(iNumVassalPop * 100 > iNumPop * 50)
+ else if (iNumVassalPop * 100 > iNumPop * 50)
{
iScoreForLiberate *= 100;
iScoreForLiberate /= 100;
}
- else if(iNumVassalPop * 100 > iNumPop * 33)
+ else if (iNumVassalPop * 100 > iNumPop * 33)
{
iScoreForLiberate *= 125;
iScoreForLiberate /= 100;
@@ -55719,35 +55884,29 @@ bool CvDiplomacyAI::IsWantToLiberateVassal(PlayerTypes ePlayer) const
int iDominanceOverVassal = eMasterInfluence - eVassalInfluence;
// someone is pretty dominant over vassal (not too much of a modifier, but helps our chances of liberation)
- if(iDominanceOverVassal > 0)
+ if (iDominanceOverVassal > 0)
{
iScoreForLiberate *= 120;
iScoreForLiberate /= 100;
}
- else if(iDominanceOverVassal < 0)
+ else if (iDominanceOverVassal < 0)
{
iScoreForLiberate *= 50;
iScoreForLiberate /= 100;
}
- // Someone influential over one of our vassals
- if(eMasterInfluence >= INFLUENCE_LEVEL_INFLUENTIAL)
+ // We're influential over them
+ if (eMasterInfluence >= INFLUENCE_LEVEL_INFLUENTIAL)
{
iScoreForLiberate *= 150;
iScoreForLiberate /= 100;
}
- // A vassal is influential over us!!! Them being a vassal will be good for us
- if(eVassalInfluence >= INFLUENCE_LEVEL_INFLUENTIAL)
- {
- iScoreForLiberate *= 50;
- iScoreForLiberate /= 100;
- }
-
// The longer they've been our vassal, give a very small boost toward liberation
- iScoreForLiberate += 3 * (kVassalTeam.GetNumTurnsIsVassal() / 50); // 3% per 50 turns
+ iScoreForLiberate *= 100 + (GET_TEAM(eVassalTeam).GetNumTurnsIsVassal() * GC.getGame().getGameSpeedInfo().getTrainPercent() / 1000); // 1% per 10 turns (standard speed)
+ iScoreForLiberate /= 100;
- return iScoreForLiberate > 100;
+ return iScoreForLiberate > /*100*/ GD_INT_GET(VASSALAGE_LIBERATE_BASE_THRESHOLD);
}
/// Possible Contact Statement - Third-party offer for ePlayer to liberate their vassals
diff --git a/CvGameCoreDLL_Expansion2/CvDiplomacyAI.h b/CvGameCoreDLL_Expansion2/CvDiplomacyAI.h
index 28c8061914..823483ceb2 100644
--- a/CvGameCoreDLL_Expansion2/CvDiplomacyAI.h
+++ b/CvGameCoreDLL_Expansion2/CvDiplomacyAI.h
@@ -966,6 +966,9 @@ class CvDiplomacyAI
bool IsIgnoreWarmonger() const;
void SetIgnoreWarmonger(bool bValue);
+ PlayerTypes GetVassalPlayerToLiberate() const;
+ void SetVassalPlayerToLiberate(PlayerTypes ePlayer);
+
PlayerTypes GetOtherPlayerProtectedMinorBullied(PlayerTypes ePlayer) const;
void SetOtherPlayerProtectedMinorBullied(PlayerTypes ePlayer, PlayerTypes eBulliedPlayer);
@@ -1566,7 +1569,8 @@ class CvDiplomacyAI
VassalTreatmentTypes GetVassalTreatmentLevel(PlayerTypes ePlayer);
CvString GetVassalTreatmentToolTip(PlayerTypes ePlayer);
- bool IsWantToLiberateVassal(PlayerTypes ePlayer) const;
+ void DetermineVassalToLiberate();
+ bool IsWantToLiberateVassal(PlayerTypes ePlayer, int& iScoreForLiberate) const;
bool IsVassalageAcceptable(PlayerTypes ePlayer, bool bMasterEvaluation); // can be called in either direction, for the master or the vassal
bool IsCapitulationAcceptable(PlayerTypes ePlayer); // vassal only
@@ -1908,6 +1912,7 @@ class CvDiplomacyAI
// Other Global Memory
bool m_bAvoidDeals; // Not serialized!
bool m_bIgnoreWarmonger; // Not serialized!
+ PlayerTypes m_eVassalPlayerToLiberate; // Not serialized!
bool m_bWasHumanLastTurn;
bool m_bEndedFriendshipThisTurn;
bool m_bUpdatedWarProgressThisTurn;
diff --git a/CvGameCoreDLL_Expansion2/CvEspionageClasses.cpp b/CvGameCoreDLL_Expansion2/CvEspionageClasses.cpp
index 00580668b1..8e89eca8ef 100644
--- a/CvGameCoreDLL_Expansion2/CvEspionageClasses.cpp
+++ b/CvGameCoreDLL_Expansion2/CvEspionageClasses.cpp
@@ -9296,6 +9296,23 @@ std::vector CvEspionageAI::BuildMinorCityList(bool bLogAllChoice
if (pMinorCapital->IsRazing())
continue;
+ //Is there a proposal (not resolution) involving a Sphere of Influence or Open Door?
+ CvLeague* pLeague = GC.getGame().GetGameLeagues()->GetActiveLeague();
+ bool bBlockingProposal = false;
+ if (pLeague != NULL)
+ {
+ for (EnactProposalList::iterator it = pLeague->m_vEnactProposals.begin(); it != pLeague->m_vEnactProposals.end(); ++it)
+ {
+ if ((it->GetEffects()->bSphereOfInfluence || it->GetEffects()->bOpenDoor) && it->GetProposerDecision()->GetDecision() == eTargetPlayer)
+ {
+ bBlockingProposal = true;
+ break;
+ }
+ }
+ }
+ if (bBlockingProposal)
+ continue;
+
CivApproachTypes eApproach = pDiploAI->GetCivApproach(eTargetPlayer);
// how much influence for rigging an election (not taking into account streaks)
@@ -9776,6 +9793,28 @@ void CvEspionageAI::EvaluateMinorCivSpies(void)
pEspionage->LogEspionageMsg(strMsg);
}
}
+
+ //Is there a proposal (not resolution) involving a Sphere of Influence or Open Door?
+ CvLeague* pLeague = GC.getGame().GetGameLeagues()->GetActiveLeague();
+ if (pLeague != NULL)
+ {
+ for (EnactProposalList::iterator it = pLeague->m_vEnactProposals.begin(); it != pLeague->m_vEnactProposals.end(); ++it)
+ {
+ if ((it->GetEffects()->bSphereOfInfluence || it->GetEffects()->bOpenDoor) && it->GetProposerDecision()->GetDecision() == pCity->getOwner())
+ {
+ CvEspionageSpy* pSpy = &(pEspionage->m_aSpyList[ui]);
+ pSpy->m_bEvaluateReassignment = true;
+ if (GC.getLogging())
+ {
+ CvString strMsg;
+ strMsg.Format("Re-eval: SoI or Open Door resolution proposed, %d,", ui);
+ strMsg += GetLocalizedText(pCity->getNameKey());
+ pEspionage->LogEspionageMsg(strMsg);
+ }
+ break;
+ }
+ }
+ }
}
}
}
diff --git a/CvGameCoreDLL_Expansion2/CvGame.cpp b/CvGameCoreDLL_Expansion2/CvGame.cpp
index 0851d62542..18b72deaf9 100644
--- a/CvGameCoreDLL_Expansion2/CvGame.cpp
+++ b/CvGameCoreDLL_Expansion2/CvGame.cpp
@@ -6398,7 +6398,7 @@ bool CvGame::IsNuclearGandhiEnabled() const
if (isNoNukes())
return false;
- if (isOption(GAMEOPTION_RANDOM_PERSONALITIES) && GD_INT_GET(DIPLOAI_ENABLE_NUCLEAR_GANDHI) < 1)
+ if (isOption(GAMEOPTION_RANDOM_PERSONALITIES) && GD_INT_GET(DIPLOAI_ENABLE_NUCLEAR_GANDHI) < 2)
return false;
return GD_INT_GET(DIPLOAI_ENABLE_NUCLEAR_GANDHI) > 0;
diff --git a/CvGameCoreDLL_Expansion2/CvGlobals.cpp b/CvGameCoreDLL_Expansion2/CvGlobals.cpp
index 8dc78bcd79..9b9b6b4664 100644
--- a/CvGameCoreDLL_Expansion2/CvGlobals.cpp
+++ b/CvGameCoreDLL_Expansion2/CvGlobals.cpp
@@ -2240,6 +2240,7 @@ CvGlobals::CvGlobals() :
GD_INT_INIT(VASSALAGE_VASSAL_MASTER_CITY_PERCENT_THRESHOLD, 60),
GD_INT_INIT(VASSALAGE_VASSAL_MASTER_POP_PERCENT_THRESHOLD, 60),
GD_INT_INIT(VASSALAGE_CAPITULATE_BASE_THRESHOLD, 100),
+ GD_INT_INIT(VASSALAGE_LIBERATE_BASE_THRESHOLD, 100),
GD_INT_INIT(VASSALAGE_TREATMENT_THRESHOLD_DISAGREE, 1),
GD_INT_INIT(VASSALAGE_TREATMENT_THRESHOLD_MISTREATED, 25),
GD_INT_INIT(VASSALAGE_TREATMENT_THRESHOLD_UNHAPPY, 50),
@@ -7073,6 +7074,7 @@ void CvGlobals::cacheGlobals()
GD_INT_CACHE(VASSALAGE_VASSAL_MASTER_CITY_PERCENT_THRESHOLD);
GD_INT_CACHE(VASSALAGE_VASSAL_MASTER_POP_PERCENT_THRESHOLD);
GD_INT_CACHE(VASSALAGE_CAPITULATE_BASE_THRESHOLD);
+ GD_INT_CACHE(VASSALAGE_LIBERATE_BASE_THRESHOLD);
GD_INT_CACHE(VASSALAGE_TREATMENT_THRESHOLD_DISAGREE);
GD_INT_CACHE(VASSALAGE_TREATMENT_THRESHOLD_MISTREATED);
GD_INT_CACHE(VASSALAGE_TREATMENT_THRESHOLD_UNHAPPY);
diff --git a/CvGameCoreDLL_Expansion2/CvGlobals.h b/CvGameCoreDLL_Expansion2/CvGlobals.h
index 59c170a0ee..29fc980ef9 100644
--- a/CvGameCoreDLL_Expansion2/CvGlobals.h
+++ b/CvGameCoreDLL_Expansion2/CvGlobals.h
@@ -2831,6 +2831,7 @@ class CvGlobals
GD_INT_MEMBER(VASSALAGE_VASSAL_MASTER_CITY_PERCENT_THRESHOLD); // VP
GD_INT_MEMBER(VASSALAGE_VASSAL_MASTER_POP_PERCENT_THRESHOLD); // VP
GD_INT_MEMBER(VASSALAGE_CAPITULATE_BASE_THRESHOLD); // VP
+ GD_INT_MEMBER(VASSALAGE_LIBERATE_BASE_THRESHOLD); // VP
GD_INT_MEMBER(VASSALAGE_TREATMENT_THRESHOLD_DISAGREE); // VP
GD_INT_MEMBER(VASSALAGE_TREATMENT_THRESHOLD_MISTREATED); // VP
GD_INT_MEMBER(VASSALAGE_TREATMENT_THRESHOLD_UNHAPPY); // VP
diff --git a/CvGameCoreDLL_Expansion2/CvMinorCivAI.cpp b/CvGameCoreDLL_Expansion2/CvMinorCivAI.cpp
index 9af2a6f6c1..29bb80f28a 100644
--- a/CvGameCoreDLL_Expansion2/CvMinorCivAI.cpp
+++ b/CvGameCoreDLL_Expansion2/CvMinorCivAI.cpp
@@ -3618,8 +3618,9 @@ bool CvMinorCivQuest::DoCancelQuest()
bool bRevoked = IsRevoked();
bool bExpired = IsExpired();
- Localization::String strMessage;
- Localization::String strSummary;
+ // General "Quest Expired" catch statement, overridden below
+ Localization::String strMessage = Localization::Lookup("TXT_KEY_NOTIFICATION_QUEST_ENDED_OTHER");
+ Localization::String strSummary = Localization::Lookup("TXT_KEY_NOTIFICATION_SUMMARY_QUEST_ENDED_OTHER");
CivsList veNamesToShow;
// If quest was revoked due to bullying, notification is handled elsewhere (to allow condensing)
@@ -3762,12 +3763,17 @@ bool CvMinorCivQuest::DoCancelQuest()
case MINOR_CIV_QUEST_LIBERATION:
{
CvPlot* pPlot = GC.getMap().plot(m_iData1, m_iData2);
- const char* strTargetNameKey = pPlot->getPlotCity()->getNameKey();
+ PlayerTypes eTargetPlayer = (PlayerTypes)m_iData3;
+ CvCity* pCity = pPlot->getPlotCity();
+ if (pCity && pCity->getOriginalOwner() == eTargetPlayer)
+ {
+ const char* strTargetNameKey = pCity->getNameKey();
- strMessage = Localization::Lookup("TXT_KEY_NOTIFICATION_QUEST_ENDED_LIBERATION");
- strMessage << strTargetNameKey;
- strSummary = Localization::Lookup("TXT_KEY_NOTIFICATION_SUMMARY_QUEST_ENDED_LIBERATION");
- strSummary << strTargetNameKey;
+ strMessage = Localization::Lookup("TXT_KEY_NOTIFICATION_QUEST_ENDED_LIBERATION");
+ strMessage << strTargetNameKey;
+ strSummary = Localization::Lookup("TXT_KEY_NOTIFICATION_SUMMARY_QUEST_ENDED_LIBERATION");
+ strSummary << strTargetNameKey;
+ }
break;
}
case MINOR_CIV_QUEST_HORDE:
@@ -3853,13 +3859,8 @@ bool CvMinorCivQuest::DoCancelQuest()
break;
}
default:
- {
- // General "Quest Expired" catch statement
- strMessage = Localization::Lookup("TXT_KEY_NOTIFICATION_QUEST_ENDED_OTHER");
- strSummary = Localization::Lookup("TXT_KEY_NOTIFICATION_SUMMARY_QUEST_ENDED_OTHER");
break;
}
- }
strMessage << pMinor->getNameKey();
strSummary << pMinor->getNameKey();
diff --git a/CvGameCoreDLL_Expansion2/CvPlayer.cpp b/CvGameCoreDLL_Expansion2/CvPlayer.cpp
index fd58dc0b15..064d2ba006 100644
--- a/CvGameCoreDLL_Expansion2/CvPlayer.cpp
+++ b/CvGameCoreDLL_Expansion2/CvPlayer.cpp
@@ -10297,73 +10297,105 @@ void CvPlayer::doTurnPostDiplomacy()
// Compute the cost of policies for this turn
DoUpdateNextPolicyCost();
- // if this is the human player, have the popup come up so that he can choose a new policy
- if(isAlive() && isHuman() && getNumCities() > 0)
+ // Anarchy counter
+ if (GetAnarchyNumTurns() > 0)
+ ChangeAnarchyNumTurns(-1);
+
+ if (isAlive() && isMajorCiv() && getNumCities() > 0)
{
- if(!GC.GetEngineUserInterface()->IsPolicyNotificationSeen())
+ if (!isHuman())
{
- if(getNextPolicyCost() <= getJONSCulture() && GetPlayerPolicies()->GetNumPoliciesCanBeAdopted() > 0)
+ if (GetPlayerPolicies()->IsTimeToChooseIdeology() && GetPlayerPolicies()->GetLateGamePolicyTree() == NO_POLICY_BRANCH_TYPE)
{
- CvNotifications* pNotifications = GetNotifications();
- if(pNotifications)
+ if (GetPlayerTraits()->IsAdoptionFreeTech())
{
- CvString strBuffer;
-
- if(kGame.isOption(GAMEOPTION_POLICY_SAVING))
- strBuffer = GetLocalizedText("TXT_KEY_NOTIFICATION_ENOUGH_CULTURE_FOR_POLICY_DISMISS");
- else
- strBuffer = GetLocalizedText("TXT_KEY_NOTIFICATION_ENOUGH_CULTURE_FOR_POLICY");
-
- CvString strSummary = GetLocalizedText("TXT_KEY_NOTIFICATION_SUMMARY_ENOUGH_CULTURE_FOR_POLICY");
- pNotifications->Add(NOTIFICATION_POLICY, strBuffer, strSummary, -1, -1, -1);
+ AI_chooseFreeTech();
}
+
+ GetPlayerPolicies()->DoChooseIdeology();
}
- }
- if (GetPlayerPolicies()->IsTimeToChooseIdeology() && GetPlayerPolicies()->GetLateGamePolicyTree() == NO_POLICY_BRANCH_TYPE)
+ GetPlayerPolicies()->DoPolicyAI();
+ }
+ // if this is the human player, have the popup come up so that he can choose a new policy
+ else
{
- if(GetPlayerTraits()->IsAdoptionFreeTech())
+ if (!GC.GetEngineUserInterface()->IsPolicyNotificationSeen())
{
- CvString strBuffer = GetLocalizedText("TXT_KEY_MISC_CHOSE_IDEOLOGY_UA_CHOOSE_TECH");
- chooseTech(1, strBuffer.GetCString());
+ if (getNextPolicyCost() <= getJONSCulture() && GetPlayerPolicies()->GetNumPoliciesCanBeAdopted() > 0)
+ {
+ CvNotifications* pNotifications = GetNotifications();
+ if (pNotifications)
+ {
+ CvString strBuffer;
+
+ if (kGame.isOption(GAMEOPTION_POLICY_SAVING))
+ strBuffer = GetLocalizedText("TXT_KEY_NOTIFICATION_ENOUGH_CULTURE_FOR_POLICY_DISMISS");
+ else
+ strBuffer = GetLocalizedText("TXT_KEY_NOTIFICATION_ENOUGH_CULTURE_FOR_POLICY");
+
+ CvString strSummary = GetLocalizedText("TXT_KEY_NOTIFICATION_SUMMARY_ENOUGH_CULTURE_FOR_POLICY");
+ pNotifications->Add(NOTIFICATION_POLICY, strBuffer, strSummary, -1, -1, -1);
+ }
+ }
}
- CvNotifications* pNotifications = GetNotifications();
- if(pNotifications)
+ if (GetPlayerPolicies()->IsTimeToChooseIdeology() && GetPlayerPolicies()->GetLateGamePolicyTree() == NO_POLICY_BRANCH_TYPE)
{
- CvString strBuffer;
- if (GetCurrentEra() > /*INDUSTRIAL IN CP, MODERN IN VP*/ GD_INT_GET(IDEOLOGY_START_ERA))
+ // Vassals are forced to choose the master's ideology
+ bool bForcedIdeology = false;
+ TeamTypes eMasterTeam = GET_TEAM(getTeam()).GetMaster();
+ if (eMasterTeam != NO_TEAM)
{
- strBuffer = GetLocalizedText("TXT_KEY_NOTIFICATION_CHOOSE_IDEOLOGY_ERA");
+ vector vMasterTeam = GET_TEAM(eMasterTeam).getPlayers();
+ for (size_t i=0; i 0 cities is the one that counts
+ if (GET_PLAYER(eMaster).isAlive() && GET_PLAYER(eMaster).getNumCities() > 0)
+ {
+ if (GET_PLAYER(eMaster).GetPlayerPolicies()->GetLateGamePolicyTree() != NO_POLICY_BRANCH_TYPE)
+ {
+ GetPlayerPolicies()->SetPolicyBranchUnlocked(GET_PLAYER(eMaster).GetPlayerPolicies()->GetLateGamePolicyTree(), true, false);
+ bForcedIdeology = true;
+ break;
+ }
+ }
+ }
}
- else
+
+ if (GetPlayerTraits()->IsAdoptionFreeTech())
{
- strBuffer = GetLocalizedText("TXT_KEY_NOTIFICATION_CHOOSE_IDEOLOGY_FACTORIES");
+ CvString strBuffer = GetLocalizedText("TXT_KEY_MISC_CHOSE_IDEOLOGY_UA_CHOOSE_TECH");
+ chooseTech(1, strBuffer.GetCString());
}
- CvString strSummary = GetLocalizedText("TXT_KEY_NOTIFICATION_SUMMARY_CHOOSE_IDEOLOGY");
- pNotifications->Add(NOTIFICATION_CHOOSE_IDEOLOGY, strBuffer, strSummary, -1, -1, GetID());
- }
- }
- }
- if (isAlive() && getNumCities() > 0 && !isHuman() && !isMinorCiv())
- {
- if (GetPlayerPolicies()->IsTimeToChooseIdeology() && GetPlayerPolicies()->GetLateGamePolicyTree() == NO_POLICY_BRANCH_TYPE)
- {
- if(GetPlayerTraits()->IsAdoptionFreeTech())
- {
- AI_chooseFreeTech();
+ if (!bForcedIdeology)
+ {
+ CvNotifications* pNotifications = GetNotifications();
+ if (pNotifications)
+ {
+ CvString strBuffer;
+ if (GetCurrentEra() > /*INDUSTRIAL IN CP, MODERN IN VP*/ GD_INT_GET(IDEOLOGY_START_ERA))
+ {
+ strBuffer = GetLocalizedText("TXT_KEY_NOTIFICATION_CHOOSE_IDEOLOGY_ERA");
+ }
+ else
+ {
+ strBuffer = GetLocalizedText("TXT_KEY_NOTIFICATION_CHOOSE_IDEOLOGY_FACTORIES");
+ }
+ CvString strSummary = GetLocalizedText("TXT_KEY_NOTIFICATION_SUMMARY_CHOOSE_IDEOLOGY");
+ pNotifications->Add(NOTIFICATION_CHOOSE_IDEOLOGY, strBuffer, strSummary, -1, -1, GetID());
+ }
+ }
}
- GetPlayerPolicies()->DoChooseIdeology();
+ // Force an ideology update for human vassals, if applicable
+ GetPlayerPolicies()->DoPolicyAI();
}
}
- if (!isBarbarian() && !isHuman() && !isMinorCiv())
- {
- GetPlayerPolicies()->DoPolicyAI();
- }
-
// Science
doResearch();
@@ -10378,10 +10410,6 @@ void CvPlayer::doTurnPostDiplomacy()
// Leagues
CvGameLeagues* pGameLeagues = kGame.GetGameLeagues();
pGameLeagues->DoPlayerTurn(*this);
-
- // Anarchy counter
- if(GetAnarchyNumTurns() > 0)
- ChangeAnarchyNumTurns(-1);
}
const int iGameTurn = kGame.getGameTurn();
@@ -31339,7 +31367,8 @@ int CvPlayer::GetNumOurCitiesOwnedBy(PlayerTypes ePlayer)
int iCount = 0;
for (CvCity* pLoopCity = GET_PLAYER(ePlayer).firstCity(&iLoop); pLoopCity != NULL; pLoopCity = GET_PLAYER(ePlayer).nextCity(&iLoop))
{
- if (pLoopCity->getOriginalOwner() == m_eID)
+ PlayerTypes eOriginalOwner = pLoopCity->getOriginalOwner();
+ if (GET_PLAYER(eOriginalOwner).getTeam() == getTeam())
iCount++;
}
diff --git a/CvGameCoreDLL_Expansion2/CvPolicyAI.cpp b/CvGameCoreDLL_Expansion2/CvPolicyAI.cpp
index 7135fc0aac..f348a5cd40 100644
--- a/CvGameCoreDLL_Expansion2/CvPolicyAI.cpp
+++ b/CvGameCoreDLL_Expansion2/CvPolicyAI.cpp
@@ -290,30 +290,78 @@ void CvPolicyAI::DoChooseIdeology(CvPlayer *pPlayer)
return;
}
- if (GET_TEAM(pPlayer->getTeam()).IsVassalOfSomeone())
+ // Vassals are forced to choose the master's ideology
+ TeamTypes eMasterTeam = GET_TEAM(pPlayer->getTeam()).GetMaster();
+ if (eMasterTeam != NO_TEAM)
{
- TeamTypes eMasterTeam = GET_TEAM(pPlayer->getTeam()).GetMaster();
- if (eMasterTeam != NO_TEAM)
+ vector vMasterTeam = GET_TEAM(eMasterTeam).getPlayers();
+ for (size_t i=0; i 0 cities is the one that counts
+ if (GET_PLAYER(eMaster).isAlive() && GET_PLAYER(eMaster).getNumCities() > 0)
+ {
+ if (GET_PLAYER(eMaster).GetPlayerPolicies()->GetLateGamePolicyTree() != NO_POLICY_BRANCH_TYPE)
{
- if (GET_PLAYER(eMaster).GetPlayerPolicies()->GetLateGamePolicyTree() != NO_POLICY_BRANCH_TYPE)
- {
- pPlayer->GetPlayerPolicies()->SetPolicyBranchUnlocked(GET_PLAYER(eMaster).GetPlayerPolicies()->GetLateGamePolicyTree(), true, false);
- LogBranchChoice(GET_PLAYER(eMaster).GetPlayerPolicies()->GetLateGamePolicyTree());
- return;
- }
+ pPlayer->GetPlayerPolicies()->SetPolicyBranchUnlocked(GET_PLAYER(eMaster).GetPlayerPolicies()->GetLateGamePolicyTree(), true, false);
+ LogBranchChoice(GET_PLAYER(eMaster).GetPlayerPolicies()->GetLateGamePolicyTree());
+ return;
}
}
}
}
+ // Team Leader used FOLLOW ME!
+ TeamTypes eTeam = pPlayer->getTeam();
+ PlayerTypes eTeamLeader = pPlayer->GetID();
+ int iBestScore = 0;
+ int iMyScore = pPlayer->GetScore();
+ vector vMyTeam = GET_TEAM(eTeam).getPlayers();
+ for (size_t i=0; i iBestScore && iScore * 2 >= iMyScore * 3) // Must be at least 50% higher to justify this
+ {
+ eTeamLeader = eTeamMember;
+ iBestScore = iScore;
+ }
+ }
+ PolicyBranchTypes eLeaderIdeology = GET_PLAYER(eTeamLeader).GetPlayerPolicies()->GetLateGamePolicyTree();
+ if (eTeamLeader != pPlayer->GetID() && eLeaderIdeology != NO_POLICY_BRANCH_TYPE)
+ {
+ // Sanity check - don't adopt the leader's ideology if it would result in us losing cities
+ bool bFollowTheLeader = false;
+ int iExtraUnhappiness = pPlayer->GetCulture()->ComputeHypotheticalPublicOpinionUnhappiness(eLeaderIdeology);
+ if (!MOD_BALANCE_VP)
+ {
+ bFollowTheLeader = pPlayer->GetExcessHappiness() - iExtraUnhappiness > /*-8*/ GD_INT_GET(VERY_UNHAPPY_THRESHOLD) + 2; // Add some margin of error
+ }
+ else
+ {
+ int iUnhappy = pPlayer->GetUnhappinessFromCitizenNeeds() + iExtraUnhappiness;
+ int iHappy = pPlayer->GetHappinessFromCitizenNeeds();
+ bFollowTheLeader = ((iHappy * 100) / max(1, iUnhappy) / 2) >= /*40*/ GD_INT_GET(VERY_UNHAPPY_THRESHOLD) + 5; // Add some margin of error
+ }
+
+ if (bFollowTheLeader)
+ {
+ pPlayer->GetPlayerPolicies()->SetPolicyBranchUnlocked(eLeaderIdeology, true, false);
+ LogBranchChoice(eLeaderIdeology);
+ return;
+ }
+ }
+
// == Grand Strategy ==
int iDiploInterest = 0;
int iConquestInterest = 0;
@@ -690,6 +738,7 @@ void CvPolicyAI::DoChooseIdeology(CvPlayer *pPlayer)
}
/// Should the AI look at switching ideology branches?
+/// Humans also call this function to force a switch if they're a vassal.
void CvPolicyAI::DoConsiderIdeologySwitch(CvPlayer* pPlayer)
{
// Gather basic Ideology info
@@ -697,28 +746,32 @@ void CvPolicyAI::DoConsiderIdeologySwitch(CvPlayer* pPlayer)
if (eCurrentIdeology == NO_POLICY_BRANCH_TYPE)
return;
- bool bVUnhappy = pPlayer->IsEmpireVeryUnhappy();
- bool bSUnhappy = pPlayer->IsEmpireSuperUnhappy();
- int iPublicOpinionUnhappiness = pPlayer->GetCulture()->GetPublicOpinionUnhappiness();
- PolicyBranchTypes ePreferredIdeology = pPlayer->GetCulture()->GetPublicOpinionPreferredIdeology();
-
- if (GET_TEAM(pPlayer->getTeam()).IsVassalOfSomeone() && pPlayer->GetPlayerPolicies()->GetLateGamePolicyTree() != NO_POLICY_BRANCH_TYPE)
+ TeamTypes eMasterTeam = GET_TEAM(pPlayer->getTeam()).GetMaster();
+ if (eMasterTeam != NO_TEAM)
{
- TeamTypes eMasterTeam = GET_TEAM(pPlayer->getTeam()).GetMaster();
-
- // Loop through all players to see if they're on our team
- for (int iPlayerLoop = 0; iPlayerLoop < MAX_MAJOR_CIVS; iPlayerLoop++)
+ vector vMasterTeam = GET_TEAM(eMasterTeam).getPlayers();
+ for (size_t i=0; i 0 cities is the one that counts
+ if (GET_PLAYER(eMaster).isAlive() && GET_PLAYER(eMaster).getNumCities() > 0)
{
- if (GET_PLAYER(eMaster).GetPlayerPolicies()->GetLateGamePolicyTree() != NO_POLICY_BRANCH_TYPE && GET_PLAYER(eMaster).GetPlayerPolicies()->GetLateGamePolicyTree() != pPlayer->GetPlayerPolicies()->GetLateGamePolicyTree())
+ PolicyBranchTypes eMasterIdeology = GET_PLAYER(eMaster).GetPlayerPolicies()->GetLateGamePolicyTree();
+ if (eMasterIdeology != NO_POLICY_BRANCH_TYPE && eMasterIdeology != eCurrentIdeology)
{
+ if (MOD_API_ACHIEVEMENTS && eMasterIdeology == GD_INT_GET(POLICY_BRANCH_FREEDOM) && eCurrentIdeology == GD_INT_GET(POLICY_BRANCH_ORDER))
+ {
+ PlayerTypes eActivePlayer = GC.getGame().getActivePlayer();
+ if (GET_PLAYER(eActivePlayer).isAlive() && GET_PLAYER(eActivePlayer).isHuman() && GET_PLAYER(eActivePlayer).getTeam() == eMasterTeam)
+ {
+ gDLL->UnlockAchievement(ACHIEVEMENT_XP2_39);
+ }
+ }
+
// Cleared all obstacles -- REVOLUTION!
pPlayer->SetAnarchyNumTurns(/*2 in CP, 3 in VP*/ GD_INT_GET(SWITCH_POLICY_BRANCHES_ANARCHY_TURNS));
- pPlayer->GetPlayerPolicies()->DoSwitchIdeologies(GET_PLAYER(eMaster).GetPlayerPolicies()->GetLateGamePolicyTree());
+ pPlayer->GetPlayerPolicies()->DoSwitchIdeologies(eMasterIdeology);
Localization::String strSummary = Localization::Lookup("TXT_KEY_ANARCHY_BEGINS_SUMMARY");
Localization::String strMessage = Localization::Lookup("TXT_KEY_ANARCHY_BEGINS");
pPlayer->GetNotifications()->Add(NOTIFICATION_GENERIC, strMessage.toUTF8(), strSummary.toUTF8(), pPlayer->GetID(), /*2 in CP, 3 in VP*/ GD_INT_GET(SWITCH_POLICY_BRANCHES_ANARCHY_TURNS), -1);
@@ -728,22 +781,148 @@ void CvPolicyAI::DoConsiderIdeologySwitch(CvPlayer* pPlayer)
}
}
+ // Humans halt here!
+ if (pPlayer->isHuman())
+ return;
+
+ int iPublicOpinionUnhappiness = pPlayer->GetCulture()->GetPublicOpinionUnhappiness();
+ PolicyBranchTypes ePreferredIdeology = pPlayer->GetCulture()->GetPublicOpinionPreferredIdeology();
+
+ // Can't switch.
+ if (iPublicOpinionUnhappiness == 0 || ePreferredIdeology == NO_POLICY_BRANCH_TYPE || ePreferredIdeology == eCurrentIdeology)
+ return;
+
+ // Would switching cure our happiness problems?
+ bool bVUnhappy = pPlayer->IsEmpireVeryUnhappy();
+ bool bSUnhappy = pPlayer->IsEmpireSuperUnhappy();
+ if (bSUnhappy)
+ {
+ int iNewUnhappiness = pPlayer->GetCulture()->ComputeHypotheticalPublicOpinionUnhappiness(ePreferredIdeology);
+ if (!MOD_BALANCE_VP)
+ {
+ bSUnhappy = pPlayer->GetExcessHappiness() + iPublicOpinionUnhappiness - iNewUnhappiness > /*-20*/ GD_INT_GET(SUPER_UNHAPPY_THRESHOLD);
+ }
+ else
+ {
+ int iUnhappy = pPlayer->GetUnhappinessFromCitizenNeeds() - iPublicOpinionUnhappiness + iNewUnhappiness;
+ int iHappy = pPlayer->GetHappinessFromCitizenNeeds();
+ bSUnhappy = ((iHappy * 100) / max(1, iUnhappy) / 2) >= /*20*/ GD_INT_GET(SUPER_UNHAPPY_THRESHOLD);
+ }
+ }
+ else if (bVUnhappy)
+ {
+ int iNewUnhappiness = pPlayer->GetCulture()->ComputeHypotheticalPublicOpinionUnhappiness(ePreferredIdeology);
+ if (!MOD_BALANCE_VP)
+ {
+ bVUnhappy = pPlayer->GetExcessHappiness() + iPublicOpinionUnhappiness - iNewUnhappiness > /*-10*/ GD_INT_GET(VERY_UNHAPPY_THRESHOLD);
+ }
+ else
+ {
+ int iUnhappy = pPlayer->GetUnhappinessFromCitizenNeeds() - iPublicOpinionUnhappiness + iNewUnhappiness;
+ int iHappy = pPlayer->GetHappinessFromCitizenNeeds();
+ bVUnhappy = ((iHappy * 100) / max(1, iUnhappy) / 2) >= /*35*/ GD_INT_GET(VERY_UNHAPPY_THRESHOLD);
+ }
+ }
+
+ // Team Leader used FOLLOW ME!
+ TeamTypes eTeam = pPlayer->getTeam();
+ PlayerTypes eTeamLeader = pPlayer->GetID();
+ bool bTeamLeaderSwitchRequested = false;
+ bool bTeamLeaderSwitchAvoided = false;
+ if (!bSUnhappy)
+ {
+ int iBestScore = 0;
+ int iMyScore = pPlayer->GetScore();
+ vector vMyTeam = GET_TEAM(eTeam).getPlayers();
+ for (size_t i=0; i iBestScore && iScore * 2 >= iMyScore * 3) // Must be at least 50% higher to justify this
+ {
+ eTeamLeader = eTeamMember;
+ iBestScore = iScore;
+ }
+ }
+ if (eTeamLeader != pPlayer->GetID())
+ {
+ PolicyBranchTypes eTeamLeaderIdeology = GET_PLAYER(eTeamLeader).GetPlayerPolicies()->GetLateGamePolicyTree();
+ if (eTeamLeaderIdeology == ePreferredIdeology)
+ {
+ // Switch if we wouldn't lose cities to unhappiness
+ bTeamLeaderSwitchRequested = true;
+ }
+ else if (eTeamLeaderIdeology == eCurrentIdeology)
+ {
+ // Don't switch if we can avoid losing cities to unhappiness
+ bTeamLeaderSwitchAvoided = true;
+ }
+ }
+ }
+
// Possible enough that we need to look at this in detail?
- if (bSUnhappy && iPublicOpinionUnhappiness >= /*-20 in CP, 20 in VP*/ GD_INT_GET(SUPER_UNHAPPY_THRESHOLD))
+ if (bSUnhappy)
{
- //Sanity check - would a change to this branch simply make us unhappy in another way? If so, don't do it.
- if(ePreferredIdeology != NO_POLICY_BRANCH_TYPE)
+ //Final sanity check - are we flip-flopping?
+ if (!bTeamLeaderSwitchRequested && GC.getGame().getGameTurn() - pPlayer->GetCulture()->GetTurnIdeologySwitch() <= 30)
+ {
+ return;
+ }
+
+ if (MOD_API_ACHIEVEMENTS && ePreferredIdeology == GD_INT_GET(POLICY_BRANCH_FREEDOM) && eCurrentIdeology == GD_INT_GET(POLICY_BRANCH_ORDER))
{
- int iUnhappiness = pPlayer->GetCulture()->ComputeHypotheticalPublicOpinionUnhappiness(ePreferredIdeology);
- if(iUnhappiness >= iPublicOpinionUnhappiness)
+ PlayerTypes eMostPressure = pPlayer->GetCulture()->GetPublicOpinionBiggestInfluence();
+ if (eMostPressure != NO_PLAYER && GET_PLAYER(eMostPressure).GetID() == GC.getGame().getActivePlayer())
{
- return;
+ gDLL->UnlockAchievement(ACHIEVEMENT_XP2_39);
}
+ }
- //Final sanity check - are we flip-flopping?
- if (GC.getGame().getGameTurn() - pPlayer->GetCulture()->GetTurnIdeologySwitch() <= 30)
+ // Cleared all obstacles -- REVOLUTION!
+ pPlayer->SetAnarchyNumTurns(/*2 in CP, 3 in VP*/ GD_INT_GET(SWITCH_POLICY_BRANCHES_ANARCHY_TURNS));
+ pPlayer->GetPlayerPolicies()->DoSwitchIdeologies(ePreferredIdeology);
+ Localization::String strSummary = Localization::Lookup("TXT_KEY_ANARCHY_BEGINS_SUMMARY");
+ Localization::String strMessage = Localization::Lookup("TXT_KEY_ANARCHY_BEGINS");
+ pPlayer->GetNotifications()->Add(NOTIFICATION_GENERIC, strMessage.toUTF8(), strSummary.toUTF8(), pPlayer->GetID(), /*2 in CP, 3 in VP*/ GD_INT_GET(SWITCH_POLICY_BRANCHES_ANARCHY_TURNS), -1);
+ }
+ else if (bTeamLeaderSwitchAvoided)
+ {
+ return;
+ }
+ else if (bTeamLeaderSwitchRequested)
+ {
+ //Sanity check - would a change to this branch put us at risk of losing cities? If so, don't do it.
+ int iNewUnhappiness = pPlayer->GetCulture()->ComputeHypotheticalPublicOpinionUnhappiness(ePreferredIdeology);
+ bool bSwitch = false;
+ if (!MOD_BALANCE_VP)
+ {
+ bSwitch = pPlayer->GetExcessHappiness() + iPublicOpinionUnhappiness - iNewUnhappiness > /*-8*/ GD_INT_GET(VERY_UNHAPPY_THRESHOLD) + 2; // Add some margin of error
+ }
+ else
+ {
+ int iUnhappy = pPlayer->GetUnhappinessFromCitizenNeeds() - iPublicOpinionUnhappiness + iNewUnhappiness;
+ int iHappy = pPlayer->GetHappinessFromCitizenNeeds();
+ bSwitch = ((iHappy * 100) / max(1, iUnhappy) / 2) >= /*40*/ GD_INT_GET(VERY_UNHAPPY_THRESHOLD) + 5; // Add some margin of error
+ }
+
+ if (bSwitch)
+ {
+ if (MOD_API_ACHIEVEMENTS && ePreferredIdeology == GD_INT_GET(POLICY_BRANCH_FREEDOM) && eCurrentIdeology == GD_INT_GET(POLICY_BRANCH_ORDER))
{
- return;
+ PlayerTypes eMostPressure = pPlayer->GetCulture()->GetPublicOpinionBiggestInfluence();
+ if (eMostPressure != NO_PLAYER && GET_PLAYER(eMostPressure).GetID() == GC.getGame().getActivePlayer())
+ {
+ gDLL->UnlockAchievement(ACHIEVEMENT_XP2_39);
+ }
}
// Cleared all obstacles -- REVOLUTION!
@@ -754,8 +933,12 @@ void CvPolicyAI::DoConsiderIdeologySwitch(CvPlayer* pPlayer)
pPlayer->GetNotifications()->Add(NOTIFICATION_GENERIC, strMessage.toUTF8(), strSummary.toUTF8(), pPlayer->GetID(), /*2 in CP, 3 in VP*/ GD_INT_GET(SWITCH_POLICY_BRANCHES_ANARCHY_TURNS), -1);
}
}
- else if (bVUnhappy && iPublicOpinionUnhappiness >= /*-10 in CP, 35 in VP*/ GD_INT_GET(VERY_UNHAPPY_THRESHOLD))
+ else if (bVUnhappy)
{
+ // Only switch ideologies if we're about to lose a city.
+ if (pPlayer->GetCityRevoltCounter() <= 2 + /*2 in CP, 3 in VP*/ GD_INT_GET(SWITCH_POLICY_BRANCHES_ANARCHY_TURNS))
+ return;
+
// Does the switch fight against our clearly preferred victory path?
bool bDontSwitchFreedom = false;
bool bDontSwitchOrder = false;
@@ -784,66 +967,39 @@ void CvPolicyAI::DoConsiderIdeologySwitch(CvPlayer* pPlayer)
bDontSwitchAutocracy = true;
}
- //Sanity check - would a change to this branch simply make us unhappy in another way? If so, don't do it.
- if (ePreferredIdeology != NO_POLICY_BRANCH_TYPE)
+ if (bDontSwitchFreedom && ePreferredIdeology == GD_INT_GET(POLICY_BRANCH_FREEDOM))
{
- int iUnhappiness = pPlayer->GetCulture()->ComputeHypotheticalPublicOpinionUnhappiness(ePreferredIdeology);
- if (iUnhappiness >= iPublicOpinionUnhappiness)
- {
- return;
- }
- // Finally see what our friends (and enemies) have already chosen
- for (int iPlayerLoop = 0; iPlayerLoop < MAX_MAJOR_CIVS; iPlayerLoop++)
- {
- PlayerTypes eLoopPlayer = (PlayerTypes) iPlayerLoop;
- if (eLoopPlayer != pPlayer->GetID() && pPlayer->GetDiplomacyAI()->IsPlayerValid(eLoopPlayer))
- {
- CvPlayer &kOtherPlayer = GET_PLAYER(eLoopPlayer);
- PolicyBranchTypes eOtherPlayerIdeology;
- eOtherPlayerIdeology = kOtherPlayer.GetPlayerPolicies()->GetLateGamePolicyTree();
-
- if (pPlayer->GetDiplomacyAI()->GetCivApproach(eLoopPlayer) <= CIV_APPROACH_HOSTILE)
- {
- if (eOtherPlayerIdeology == ePreferredIdeology)
- return;
- }
- }
- }
-
- if (bDontSwitchFreedom && ePreferredIdeology == GD_INT_GET(POLICY_BRANCH_FREEDOM))
- {
- return;
- }
- if (bDontSwitchAutocracy && ePreferredIdeology == GD_INT_GET(POLICY_BRANCH_AUTOCRACY))
- {
- return;
- }
- if (bDontSwitchOrder && ePreferredIdeology == GD_INT_GET(POLICY_BRANCH_ORDER))
- {
- return;
- }
- //Final sanity check - are we flip-flopping?
- if(GC.getGame().getGameTurn() - pPlayer->GetCulture()->GetTurnIdeologySwitch() <= 30)
- {
- return;
- }
+ return;
+ }
+ if (bDontSwitchAutocracy && ePreferredIdeology == GD_INT_GET(POLICY_BRANCH_AUTOCRACY))
+ {
+ return;
+ }
+ if (bDontSwitchOrder && ePreferredIdeology == GD_INT_GET(POLICY_BRANCH_ORDER))
+ {
+ return;
+ }
+ //Sanity check - are we flip-flopping?
+ if (GC.getGame().getGameTurn() - pPlayer->GetCulture()->GetTurnIdeologySwitch() <= 30)
+ {
+ return;
+ }
- if (MOD_API_ACHIEVEMENTS && ePreferredIdeology == GD_INT_GET(POLICY_BRANCH_FREEDOM) && eCurrentIdeology == GD_INT_GET(POLICY_BRANCH_ORDER))
+ if (MOD_API_ACHIEVEMENTS && ePreferredIdeology == GD_INT_GET(POLICY_BRANCH_FREEDOM) && eCurrentIdeology == GD_INT_GET(POLICY_BRANCH_ORDER))
+ {
+ PlayerTypes eMostPressure = pPlayer->GetCulture()->GetPublicOpinionBiggestInfluence();
+ if (eMostPressure != NO_PLAYER && GET_PLAYER(eMostPressure).GetID() == GC.getGame().getActivePlayer())
{
- PlayerTypes eMostPressure = pPlayer->GetCulture()->GetPublicOpinionBiggestInfluence();
- if (eMostPressure != NO_PLAYER && GET_PLAYER(eMostPressure).GetID() == GC.getGame().getActivePlayer())
- {
- gDLL->UnlockAchievement(ACHIEVEMENT_XP2_39);
- }
+ gDLL->UnlockAchievement(ACHIEVEMENT_XP2_39);
}
-
- // Cleared all obstacles -- REVOLUTION!
- pPlayer->SetAnarchyNumTurns(/*2 in CP, 3 in VP*/ GD_INT_GET(SWITCH_POLICY_BRANCHES_ANARCHY_TURNS));
- pPlayer->GetPlayerPolicies()->DoSwitchIdeologies(ePreferredIdeology);
- Localization::String strSummary = Localization::Lookup("TXT_KEY_ANARCHY_BEGINS_SUMMARY");
- Localization::String strMessage = Localization::Lookup("TXT_KEY_ANARCHY_BEGINS");
- pPlayer->GetNotifications()->Add(NOTIFICATION_GENERIC, strMessage.toUTF8(), strSummary.toUTF8(), pPlayer->GetID(), /*2 in CP, 3 in VP*/ GD_INT_GET(SWITCH_POLICY_BRANCHES_ANARCHY_TURNS), -1);
}
+
+ // Cleared all obstacles -- REVOLUTION!
+ pPlayer->SetAnarchyNumTurns(/*2 in CP, 3 in VP*/ GD_INT_GET(SWITCH_POLICY_BRANCHES_ANARCHY_TURNS));
+ pPlayer->GetPlayerPolicies()->DoSwitchIdeologies(ePreferredIdeology);
+ Localization::String strSummary = Localization::Lookup("TXT_KEY_ANARCHY_BEGINS_SUMMARY");
+ Localization::String strMessage = Localization::Lookup("TXT_KEY_ANARCHY_BEGINS");
+ pPlayer->GetNotifications()->Add(NOTIFICATION_GENERIC, strMessage.toUTF8(), strSummary.toUTF8(), pPlayer->GetID(), /*2 in CP, 3 in VP*/ GD_INT_GET(SWITCH_POLICY_BRANCHES_ANARCHY_TURNS), -1);
}
}
diff --git a/CvGameCoreDLL_Expansion2/CvPolicyClasses.cpp b/CvGameCoreDLL_Expansion2/CvPolicyClasses.cpp
index f9bfb8ec4f..ff3ccbe713 100644
--- a/CvGameCoreDLL_Expansion2/CvPolicyClasses.cpp
+++ b/CvGameCoreDLL_Expansion2/CvPolicyClasses.cpp
@@ -6431,7 +6431,10 @@ void CvPlayerPolicies::DoPolicyAI()
{
CvString strBuffer;
+ // Force an ideology update for human vassals, if applicable
m_pPolicyAI->DoConsiderIdeologySwitch(m_pPlayer);
+ if (m_pPlayer->isHuman())
+ return;
// Do we have enough points to buy a new policy?
if (m_pPlayer->getNextPolicyCost() > 0 || m_pPlayer->GetNumFreePolicies() > 0 || m_pPlayer->GetNumFreeTenets() > 0)
diff --git a/CvGameCoreDLL_Expansion2/CvReligionClasses.cpp b/CvGameCoreDLL_Expansion2/CvReligionClasses.cpp
index ec28c476c8..9225a05ac6 100644
--- a/CvGameCoreDLL_Expansion2/CvReligionClasses.cpp
+++ b/CvGameCoreDLL_Expansion2/CvReligionClasses.cpp
@@ -1232,8 +1232,8 @@ void CvGameReligions::FoundReligion(PlayerTypes ePlayer, ReligionTypes eReligion
if (pLoopUnit->getUnitInfo().IsFoundReligion())
{
bool bSubtractOne = false;
- // If player is India, subtract one charge from the prophet who founded
- if (kPlayer.GetPlayerTraits()->IsProphetFervor() && pLoopUnit->GetReligionData() != NULL && pLoopUnit->GetReligionData()->GetSpreadsUsed() > 0)
+ // If player is India, subtract one charge from any prophets who used one (either by founding or by building a Holy Site)
+ if (kPlayer.GetPlayerTraits()->IsProphetFervor() && pLoopUnit->GetReligionData()->GetSpreadsUsed() > 0)
bSubtractOne = true;
pLoopUnit->GetReligionDataMutable()->SetFullStrength(kPlayer.GetID(), pLoopUnit->getUnitInfo(), eReligion);
@@ -1241,7 +1241,7 @@ void CvGameReligions::FoundReligion(PlayerTypes ePlayer, ReligionTypes eReligion
if (bSubtractOne)
{
pLoopUnit->GetReligionDataMutable()->IncrementSpreadsUsed();
- if (pLoopUnit->GetReligionData() != NULL && pLoopUnit->GetReligionData()->GetSpreadsLeft(pLoopUnit) <= 0)
+ if (pLoopUnit->GetReligionData()->GetSpreadsLeft(pLoopUnit) <= 0)
{
kPlayer.DoGreatPersonExpended(pLoopUnit->getUnitType(), pLoopUnit);
pLoopUnit->kill(true);
@@ -7011,8 +7011,8 @@ bool CvReligionAI::DoFaithPurchases()
int iLoop = 0;
for (CvUnit* pLoopUnit = m_pPlayer->firstUnit(&iLoop); pLoopUnit != NULL; pLoopUnit = m_pPlayer->nextUnit(&iLoop))
{
- if (pLoopUnit->GetReligionData() != NULL && pLoopUnit->GetReligionData()->GetSpreadsLeft(pLoopUnit) > 0)
- if ( pLoopUnit->GetReligionData()->GetReligion() == eReligionWeFounded || pLoopUnit->GetReligionData()->GetReligion() == eReligionToSpread)
+ if (pLoopUnit->GetReligionData()->GetSpreadsLeft(pLoopUnit) > 0)
+ if (pLoopUnit->GetReligionData()->GetReligion() == eReligionWeFounded || pLoopUnit->GetReligionData()->GetReligion() == eReligionToSpread)
iNumMissionaries++;
}
@@ -8173,6 +8173,9 @@ int CvReligionAI::ScoreBeliefAtPlot(CvBeliefEntry* pEntry, CvPlot* pPlot, bool b
int CvReligionAI::ScorePantheonBeliefAtCity(CvBeliefEntry* pEntry, CvCity* pCity) const
{
+ if (m_pPlayer->getCapitalCity() == NULL)
+ return 0;
+
// the different yield types are valued using ScoreYieldForReligionTimes100
// happiness is valued with iHappinessNeedFactor (see below)
// great person points are valued with iGPValue (see below)
@@ -8637,6 +8640,9 @@ int CvReligionAI::ScorePantheonBeliefAtCity(CvBeliefEntry* pEntry, CvCity* pCity
/// AI's evaluation of this belief's usefulness at this city
int CvReligionAI::ScoreBeliefAtCity(CvBeliefEntry* pEntry, CvCity* pCity) const
{
+ if (m_pPlayer->getCapitalCity() == NULL)
+ return 0;
+
int iRtnValue = 0;
int iTempValue = 0;
int iMinPop = 0;
diff --git a/CvGameCoreDLL_Expansion2/CvTreasury.cpp b/CvGameCoreDLL_Expansion2/CvTreasury.cpp
index ba6db88ee4..c2e81c0020 100644
--- a/CvGameCoreDLL_Expansion2/CvTreasury.cpp
+++ b/CvGameCoreDLL_Expansion2/CvTreasury.cpp
@@ -977,35 +977,64 @@ int CvTreasury::GetContractGoldMaintenance()
#endif
// What are our gold maintenance costs because of Vassals?
-int CvTreasury::GetVassalGoldMaintenance() const
+int CvTreasury::GetVassalGoldMaintenance(TeamTypes eTeam) const
{
- int iRtnValue = 0;
- // We have a vassal
- for(int iI = 0; iI < MAX_MAJOR_CIVS; iI++)
+ int iNumTeamMembers = GET_TEAM(m_pPlayer->getTeam()).getAliveCount();
+ if (iNumTeamMembers == 0)
+ return 0;
+
+ int iTotalExpense = 0;
+ int iTotalExpenseOtherVassals = 0;
+ for (int iPlayerLoop = 0; iPlayerLoop < MAX_MAJOR_CIVS; iPlayerLoop++)
{
- if(!GET_PLAYER((PlayerTypes)iI).isMinorCiv()
- && !GET_PLAYER((PlayerTypes)iI).isBarbarian()
- && GET_PLAYER((PlayerTypes)iI).isAlive())
+ PlayerTypes eLoopPlayer = (PlayerTypes) iPlayerLoop;
+ TeamTypes eLoopTeam = GET_PLAYER(eLoopPlayer).getTeam();
+ if (GET_TEAM(eLoopTeam).GetMaster() != m_pPlayer->getTeam())
+ continue;
+
+ int iLoop = 0;
+ if (eTeam == NO_TEAM || eTeam == eLoopTeam)
{
- int iLoop = 0;
- int iCityPop = 0;
- // This player is our vassal
- if(GET_TEAM(GET_PLAYER((PlayerTypes)iI).getTeam()).IsVassal(m_pPlayer->getTeam()))
+ int iExpense = 0;
+ // Loop through our vassal's cities
+ for (CvCity* pLoopCity = GET_PLAYER(eLoopPlayer).firstCity(&iLoop); pLoopCity != NULL; pLoopCity = GET_PLAYER(eLoopPlayer).nextCity(&iLoop))
{
- // Loop through our vassal's cities
- for(CvCity* pLoopCity = GET_PLAYER((PlayerTypes)iI).firstCity(&iLoop); pLoopCity != NULL; pLoopCity = GET_PLAYER((PlayerTypes)iI).nextCity(&iLoop))
- {
- iCityPop = pLoopCity->getPopulation();
- iRtnValue += std::max(0, (int)(pow((double)iCityPop, (double) /*0.8f*/ GD_FLOAT_GET(VASSALAGE_VASSAL_CITY_POP_EXPONENT))));
- }
+ int iCityPop = pLoopCity->getPopulation();
+ iExpense += std::max(0, (int)(pow((double)iCityPop, (double) /*0.8f*/ GD_FLOAT_GET(VASSALAGE_VASSAL_CITY_POP_EXPONENT))));
+ }
- iRtnValue += std::max(0, (GET_PLAYER((PlayerTypes)iI).GetTreasury()->GetExpensePerTurnUnitMaintenance() * /*10*/ GD_INT_GET(VASSALAGE_VASSAL_UNIT_MAINT_COST_PERCENT) / 100));
+ iExpense += std::max(0, GET_PLAYER(eLoopPlayer).GetTreasury()->GetExpensePerTurnUnitMaintenance() * /*10*/ GD_INT_GET(VASSALAGE_VASSAL_UNIT_MAINT_COST_PERCENT) / 100);
+ iTotalExpense += iExpense;
+ }
+ else
+ {
+ int iExpense = 0;
+ // Loop through our vassal's cities
+ for (CvCity* pLoopCity = GET_PLAYER(eLoopPlayer).firstCity(&iLoop); pLoopCity != NULL; pLoopCity = GET_PLAYER(eLoopPlayer).nextCity(&iLoop))
+ {
+ int iCityPop = pLoopCity->getPopulation();
+ iExpense += std::max(0, (int)(pow((double)iCityPop, (double) /*0.8f*/ GD_FLOAT_GET(VASSALAGE_VASSAL_CITY_POP_EXPONENT))));
}
+
+ iExpense += std::max(0, GET_PLAYER(eLoopPlayer).GetTreasury()->GetExpensePerTurnUnitMaintenance() * /*10*/ GD_INT_GET(VASSALAGE_VASSAL_UNIT_MAINT_COST_PERCENT) / 100);
+ iTotalExpenseOtherVassals += iExpense;
}
}
+ // What is my share of this maintenance?
+ int iRtnValue = iTotalExpense / iNumTeamMembers;
+
+ // Team leader gets any remainder
+ if (GET_TEAM(m_pPlayer->getTeam()).getLeaderID() == m_pPlayer->GetID())
+ {
+ if (eTeam == NO_TEAM)
+ iRtnValue += iTotalExpense % iNumTeamMembers;
+ else
+ iRtnValue += (iTotalExpense + iTotalExpenseOtherVassals) % iNumTeamMembers;
+ }
+
// Modifier for vassal maintenance?
- iRtnValue *= (100 + m_pPlayer->GetVassalGoldMaintenanceMod());
+ iRtnValue *= 100 + m_pPlayer->GetVassalGoldMaintenanceMod();
iRtnValue /= 100;
return iRtnValue;
@@ -1026,6 +1055,18 @@ void CvTreasury::CalculateExpensePerTurnFromVassalTaxes()
SetExpensePerTurnFromVassalTaxesTimes100(iTax);
}
+/// How much would we owe if our tax rate increased?
+int CvTreasury::CalculateProjectedExpensePerTurnFromVassalTaxes(int iProjectedTaxRate)
+{
+ TeamTypes eMaster = GET_TEAM(m_pPlayer->getTeam()).GetMaster();
+ if (eMaster == NO_TEAM)
+ return 0;
+
+ int iNet = CalculateGrossGoldTimes100();
+ int iTax = iNet * iProjectedTaxRate / 100;
+ return iTax;
+}
+
// Set how much we owe this turn due to taxes
void CvTreasury::SetExpensePerTurnFromVassalTaxesTimes100(int iValue)
{
@@ -1045,42 +1086,66 @@ int CvTreasury::GetExpensePerTurnFromVassalTaxes() const
}
// What percent of vassal taxes am I owed?
-int CvTreasury::GetMyShareOfVassalTaxes() const
+int CvTreasury::GetMyShareOfVassalTaxes(TeamTypes eTeam, int iProjectedTaxRate) const
{
int iNumTeamMembers = GET_TEAM(m_pPlayer->getTeam()).getAliveCount();
- if(iNumTeamMembers == 0)
+ if (iNumTeamMembers == 0)
return 0;
int iTotalTaxes = 0;
- PlayerTypes eLoopPlayer;
- for(int iPlayerLoop = 0; iPlayerLoop < MAX_MAJOR_CIVS; iPlayerLoop++)
+ int iTotalTaxesOtherVassals = 0;
+ for (int iPlayerLoop = 0; iPlayerLoop < MAX_MAJOR_CIVS; iPlayerLoop++)
{
- eLoopPlayer = (PlayerTypes) iPlayerLoop;
- if(GET_TEAM(GET_PLAYER(eLoopPlayer).getTeam()).GetMaster() == m_pPlayer->getTeam())
+ PlayerTypes eLoopPlayer = (PlayerTypes) iPlayerLoop;
+ TeamTypes eLoopTeam = GET_PLAYER(eLoopPlayer).getTeam();
+ if (GET_TEAM(eLoopTeam).GetMaster() != m_pPlayer->getTeam())
+ continue;
+
+ if (eTeam == NO_TEAM || eTeam == eLoopTeam)
{
- iTotalTaxes += GET_PLAYER(eLoopPlayer).GetTreasury()->GetExpensePerTurnFromVassalTaxesTimes100();
+ if (iProjectedTaxRate == -1)
+ iTotalTaxes += GET_PLAYER(eLoopPlayer).GetTreasury()->GetExpensePerTurnFromVassalTaxesTimes100();
+ else
+ iTotalTaxes += GET_PLAYER(eLoopPlayer).GetTreasury()->CalculateProjectedExpensePerTurnFromVassalTaxes(iProjectedTaxRate);
+ }
+ else
+ {
+ iTotalTaxesOtherVassals += GET_PLAYER(eLoopPlayer).GetTreasury()->GetExpensePerTurnFromVassalTaxesTimes100();
}
}
// What is my share of these taxes?
- return (iTotalTaxes / iNumTeamMembers);
+ int iRtnValue = iTotalTaxes / iNumTeamMembers;
+
+ // Team leader gets any remainder
+ if (GET_TEAM(m_pPlayer->getTeam()).getLeaderID() == m_pPlayer->GetID())
+ {
+ if (eTeam == NO_TEAM)
+ iRtnValue += iTotalTaxes % iNumTeamMembers;
+ else
+ iRtnValue += (iTotalTaxes + iTotalTaxesOtherVassals) % iNumTeamMembers;
+ }
+
+ return iRtnValue;
}
// How much is ePlayer contributing to my vassal tax revenue (note: this doesn't actually set anything, for pure UI purposes)
int CvTreasury::GetVassalTaxContributionTimes100(PlayerTypes ePlayer) const
{
- int iNumTeamMembers = GET_TEAM(m_pPlayer->getTeam()).getAliveCount();
- if(iNumTeamMembers == 0)
+ TeamTypes eTeam = GET_PLAYER(ePlayer).getTeam();
+ int iNumTeamMembers = GET_TEAM(eTeam).getAliveCount();
+ if (iNumTeamMembers == 0)
return 0;
- int iAmount = 0;
-
- if(GET_TEAM(GET_PLAYER(ePlayer).getTeam()).GetMaster() == m_pPlayer->getTeam())
- {
- iAmount += GET_PLAYER(ePlayer).GetTreasury()->GetExpensePerTurnFromVassalTaxesTimes100();
- }
+ int iMyShare = GetMyShareOfVassalTaxes(eTeam);
+ int iRtnValue = iMyShare / iNumTeamMembers;
- return iAmount / iNumTeamMembers;
+ // If they're the team leader, attribute any remainder to them
+ // Not a perfect solution, but good enough
+ if (GET_TEAM(eTeam).getLeaderID() == ePlayer)
+ iRtnValue += iMyShare % iNumTeamMembers;
+
+ return iRtnValue;
}
int CvTreasury::GetVassalTaxContribution(PlayerTypes ePlayer) const
diff --git a/CvGameCoreDLL_Expansion2/CvTreasury.h b/CvGameCoreDLL_Expansion2/CvTreasury.h
index d845038483..08c822c89a 100644
--- a/CvGameCoreDLL_Expansion2/CvTreasury.h
+++ b/CvGameCoreDLL_Expansion2/CvTreasury.h
@@ -103,13 +103,14 @@ class CvTreasury
int AverageIncome100(int iTurns);
void LogExpenditure(const CvString& strExpenditure, int iAmount, int iColumn);
- int GetVassalGoldMaintenance() const;
+ int GetVassalGoldMaintenance(TeamTypes eTeam = NO_TEAM) const;
- int GetMyShareOfVassalTaxes() const;
+ int GetMyShareOfVassalTaxes(TeamTypes eTeam = NO_TEAM, int iProjectedTaxRate = -1) const;
int GetVassalTaxContributionTimes100(PlayerTypes ePlayer) const;
int GetVassalTaxContribution(PlayerTypes ePlayer) const;
void CalculateExpensePerTurnFromVassalTaxes();
+ int CalculateProjectedExpensePerTurnFromVassalTaxes(int iProjectedTaxRate);
int GetExpensePerTurnFromVassalTaxesTimes100() const;
int GetExpensePerTurnFromVassalTaxes() const;
diff --git a/CvGameCoreDLL_Expansion2/CvUnit.cpp b/CvGameCoreDLL_Expansion2/CvUnit.cpp
index b77735a1af..8ba0ec767c 100644
--- a/CvGameCoreDLL_Expansion2/CvUnit.cpp
+++ b/CvGameCoreDLL_Expansion2/CvUnit.cpp
@@ -10737,6 +10737,12 @@ bool CvUnit::CanFoundReligion(const CvPlot* pPlot) const
return false;
}
+ // If prophet has started spreading religion, can't do other functions (possible with India)
+ if (m_pUnitInfo->IsSpreadReligion() && GetReligionData()->GetSpreadsUsed()>0)
+ {
+ return false;
+ }
+
if(GET_PLAYER(getOwner()).GetReligions()->IsFoundingReligion())
{
return false;
@@ -10916,7 +10922,7 @@ bool CvUnit::CanEnhanceReligion(const CvPlot* pPlot) const
}
// If prophet has started spreading religion, can't do other functions
- if(m_pUnitInfo->IsSpreadReligion() && GetReligionData()->GetSpreadsUsed()>0)
+ if (m_pUnitInfo->IsSpreadReligion() && GetReligionData()->GetSpreadsUsed()>0)
{
return false;
}
@@ -12810,8 +12816,8 @@ bool CvUnit::canGoldenAge(const CvPlot* pPlot, bool bTestVisible) const
return false;
}
- // If prophet has started spreading religion, can't do other functions
- if(m_pUnitInfo->IsSpreadReligion() && GetReligionData()->GetSpreadsUsed()>0)
+ // If prophet has started spreading religion, can't do other functions
+ if (m_pUnitInfo->IsSpreadReligion() && GetReligionData()->GetSpreadsUsed()>0)
{
return false;
}
@@ -12974,8 +12980,8 @@ bool CvUnit::canGivePolicies(const CvPlot* /*pPlot*/, bool /*bTestVisible*/) con
return false;
}
- // If prophet has started spreading religion, can't do other functions
- if(m_pUnitInfo->IsSpreadReligion() && GetReligionData()->GetSpreadsUsed()>0)
+ // If prophet has started spreading religion, can't do other functions
+ if (m_pUnitInfo->IsSpreadReligion() && GetReligionData()->GetSpreadsUsed()>0)
{
return false;
}
@@ -13366,13 +13372,8 @@ bool CvUnit::canBuild(const CvPlot* pPlot, BuildTypes eBuild, bool bTestVisible,
return false;
// If prophet has started spreading religion, can't do other functions
- if (m_pUnitInfo->IsSpreadReligion())
- {
- if (GetReligionData()->GetReligion() != NO_RELIGION && GetReligionData()->GetSpreadsUsed() > 0)
- {
- return false;
- }
- }
+ if (m_pUnitInfo->IsSpreadReligion() && GetReligionData()->GetSpreadsUsed() > 0)
+ return false;
if (!pPlot)
return true;
@@ -13576,11 +13577,12 @@ bool CvUnit::build(BuildTypes eBuild)
}
bool bIndiaException = false;
- ImprovementTypes eHolySite = (ImprovementTypes)GC.getInfoTypeForString("IMPROVEMENT_HOLY_SITE");
- if (eImprovement == eHolySite && GET_PLAYER(getOwner()).GetPlayerTraits()->IsProphetFervor())
+ if (m_pUnitInfo->IsFoundReligion() && GET_PLAYER(getOwner()).GetPlayerTraits()->IsProphetFervor())
{
GetReligionDataMutable()->IncrementSpreadsUsed();
- if (GetReligionData()->GetSpreadsLeft(this) > 0)
+
+ // Test for > 1 total spreads here, not spreads left, because it's possible to create a Holy Site before founding a religion
+ if (getUnitInfo().GetReligionSpreads() > 1)
bIndiaException = true;
if (bIndiaException && pPlot->isActiveVisible())
diff --git a/CvGameCoreDLL_Expansion2/Lua/CvLuaPlayer.cpp b/CvGameCoreDLL_Expansion2/Lua/CvLuaPlayer.cpp
index 9e960d0af6..b8b5d6e9c4 100644
--- a/CvGameCoreDLL_Expansion2/Lua/CvLuaPlayer.cpp
+++ b/CvGameCoreDLL_Expansion2/Lua/CvLuaPlayer.cpp
@@ -16613,7 +16613,7 @@ int CvLuaPlayer::lGetVassalGoldMaintenance(lua_State* L)
{
CvPlayerAI* pkPlayer = GetInstance(L);
- const int iResult = pkPlayer->GetTreasury()->GetVassalGoldMaintenance();
+ const int iResult = pkPlayer->GetTreasury()->GetVassalGoldMaintenance(NO_TEAM);
lua_pushinteger(L, iResult);
return 1;
}
@@ -16683,7 +16683,7 @@ int CvLuaPlayer::lGetMyShareOfVassalTaxes(lua_State* L)
{
CvPlayerAI* pkPlayer = GetInstance(L);
- lua_pushinteger(L, pkPlayer->GetTreasury()->GetMyShareOfVassalTaxes());
+ lua_pushinteger(L, pkPlayer->GetTreasury()->GetMyShareOfVassalTaxes(NO_TEAM, -1));
return 1;
}