diff --git a/(1) Community Patch/Core Files/Text/CoreText_en_US.xml b/(1) Community Patch/Core Files/Text/CoreText_en_US.xml index 62cc9e1cd6..b1737c4193 100644 --- a/(1) Community Patch/Core Files/Text/CoreText_en_US.xml +++ b/(1) Community Patch/Core Files/Text/CoreText_en_US.xml @@ -5,6 +5,15 @@ What do you think of... + + Ask the leader to remove their troops from your border. If the leader agrees to your request, [COLOR_WARNING_TEXT]both of you[ENDCOLOR] will promise not to declare war on each other for 20 turns. If you break this promise, other leaders might view you as a backstabber![NEWLINE][NEWLINE]If the leader rejects your request, they may choose to declare war on you, so be careful! + + + Please move your troops from our borders. + + + Going to attack us, swine? + As you wish, I shall move my troops from your border. My apologies for any trouble caused by this incident. @@ -2961,7 +2970,13 @@ - This Promise will last for [COLOR_POSITIVE_TEXT]{1_Num}[ENDCOLOR] Turns. If you violate this Promise during this time, this player will feel betrayed! + This Promise will last for [COLOR_POSITIVE_TEXT]{1_Num}[ENDCOLOR] {1_Num: plural 1?Turn; other?Turns;}. If you violate this Promise during this time, this player will feel betrayed! + + + Selecting this option creates a [COLOR_WARNING_TEXT]mutual[ENDCOLOR] promise not to declare war on each other for [COLOR_POSITIVE_TEXT]{1_Num}[ENDCOLOR] {1_Num: plural 1?Turn; other?Turns;}. If you break this promise, other leaders might view you as a backstabber! + + + This Promise [COLOR_WARNING_TEXT]does not expire[ENDCOLOR]. If you violate this Promise, other leaders might view you as a backstabber! diff --git a/(1) Community Patch/LUA/DiscussionDialog.lua b/(1) Community Patch/LUA/DiscussionDialog.lua index 9892b47ce1..b279e1fe37 100644 --- a/(1) Community Patch/LUA/DiscussionDialog.lua +++ b/(1) Community Patch/LUA/DiscussionDialog.lua @@ -486,6 +486,10 @@ function LeaderMessageHandler( iPlayer, iDiploUIState, szLeaderMessage, iAnimati elseif (g_DiploUIState == DiploUIStateTypes.DIPLO_UI_STATE_DISCUSS_AGGRESSIVE_MILITARY_WARNING) then strButton1Text = Locale.ConvertTextKey( "TXT_KEY_DIPLO_DISCUSS_WE_MEAN_NO_HARM" ); strButton2Text = Locale.ConvertTextKey( "TXT_KEY_DIPLO_DISCUSS_TIME_TO_DIE" ); +-- CBP + local iTimeOutTurns = Game:GetMilitaryPromiseDuration(); + strButton1Tooltip = Locale.ConvertTextKey("TXT_KEY_DIPLO_DURATION_MILITARY_PROMISE", iTimeOutTurns); +-- END bHideBackButton = true; -- AI attacked a Minor the Human is friends with elseif (g_DiploUIState == DiploUIStateTypes.DIPLO_UI_STATE_DISCUSS_I_ATTACKED_YOUR_MINOR_CIV) then @@ -513,6 +517,7 @@ function LeaderMessageHandler( iPlayer, iDiploUIState, szLeaderMessage, iAnimati elseif (g_DiploUIState == DiploUIStateTypes.DIPLO_UI_STATE_DISCUSS_YOU_ATTACKED_MINOR_CIV) then strButton1Text = Locale.ConvertTextKey( "TXT_KEY_DIPLO_DISCUSS_NOT_YOUR_BUSINESS" ); strButton2Text = Locale.ConvertTextKey( "TXT_KEY_DIPLO_DISCUSS_WILL_WITHDRAW" ); + strButton2Tooltip = Locale.ConvertTextKey( "TXT_KEY_DIPLO_DURATION_ATTACK_MINOR_PROMISE" ); bHideBackButton = true; -- Human killed a Protected Minor --elseif (g_DiploUIState == DiploUIStateTypes.DIPLO_UI_STATE_DISCUSS_YOU_KILLED_MINOR_CIV) then @@ -534,7 +539,7 @@ function LeaderMessageHandler( iPlayer, iDiploUIState, szLeaderMessage, iAnimati strButton1Text = Locale.ConvertTextKey( "TXT_KEY_DIPLO_DISCUSS_SETTLE_WHAT_WE_PLEASE") ; strButton2Text = Locale.ConvertTextKey( "TXT_KEY_DIPLO_DISCUSS_SORRY_FOR_SETTLING") ; -- CBP - local iTimeOutTurns = Game:GetPromiseDuration(); + local iTimeOutTurns = Game:GetExpansionPromiseDuration(); strButton2Tooltip = Locale.ConvertTextKey("TXT_KEY_DIPLO_DURATION_PROMISE", iTimeOutTurns); -- END bHideBackButton = true; @@ -548,7 +553,7 @@ function LeaderMessageHandler( iPlayer, iDiploUIState, szLeaderMessage, iAnimati strButton1Text = Locale.ConvertTextKey( "TXT_KEY_DIPLO_DISCUSS_NOT_YOUR_BUSINESS" ); strButton2Text = Locale.ConvertTextKey( "TXT_KEY_DIPLO_DISCUSS_SORRY_FOR_CLAIMING" ); -- CBP - local iTimeOutTurns = Game:GetPromiseDuration(); + local iTimeOutTurns = Game:GetBorderPromiseDuration(); strButton2Tooltip = Locale.ConvertTextKey("TXT_KEY_DIPLO_DURATION_PROMISE", iTimeOutTurns); -- END bHideBackButton = true; diff --git a/(2) Vox Populi/Core Files/Overrides/DiscussionDialog.lua b/(2) Vox Populi/Core Files/Overrides/DiscussionDialog.lua index 025271a120..1e6006af0c 100644 --- a/(2) Vox Populi/Core Files/Overrides/DiscussionDialog.lua +++ b/(2) Vox Populi/Core Files/Overrides/DiscussionDialog.lua @@ -483,6 +483,10 @@ function LeaderMessageHandler( iPlayer, iDiploUIState, szLeaderMessage, iAnimati elseif (g_DiploUIState == DiploUIStateTypes.DIPLO_UI_STATE_DISCUSS_AGGRESSIVE_MILITARY_WARNING) then strButton1Text = Locale.ConvertTextKey( "TXT_KEY_DIPLO_DISCUSS_WE_MEAN_NO_HARM" ); strButton2Text = Locale.ConvertTextKey( "TXT_KEY_DIPLO_DISCUSS_TIME_TO_DIE" ); +-- CBP + local iTimeOutTurns = Game:GetMilitaryPromiseDuration(); + strButton1Tooltip = Locale.ConvertTextKey("TXT_KEY_DIPLO_DURATION_MILITARY_PROMISE", iTimeOutTurns); +-- END bHideBackButton = true; -- AI attacked a Minor the Human is friends with elseif (g_DiploUIState == DiploUIStateTypes.DIPLO_UI_STATE_DISCUSS_I_ATTACKED_YOUR_MINOR_CIV) then @@ -510,6 +514,7 @@ function LeaderMessageHandler( iPlayer, iDiploUIState, szLeaderMessage, iAnimati elseif (g_DiploUIState == DiploUIStateTypes.DIPLO_UI_STATE_DISCUSS_YOU_ATTACKED_MINOR_CIV) then strButton1Text = Locale.ConvertTextKey( "TXT_KEY_DIPLO_DISCUSS_NOT_YOUR_BUSINESS" ); strButton2Text = Locale.ConvertTextKey( "TXT_KEY_DIPLO_DISCUSS_WILL_WITHDRAW" ); + strButton2Tooltip = Locale.ConvertTextKey( "TXT_KEY_DIPLO_DURATION_ATTACK_MINOR_PROMISE" ); bHideBackButton = true; -- Human killed a Protected Minor --elseif (g_DiploUIState == DiploUIStateTypes.DIPLO_UI_STATE_DISCUSS_YOU_KILLED_MINOR_CIV) then @@ -531,7 +536,7 @@ function LeaderMessageHandler( iPlayer, iDiploUIState, szLeaderMessage, iAnimati strButton1Text = Locale.ConvertTextKey( "TXT_KEY_DIPLO_DISCUSS_SETTLE_WHAT_WE_PLEASE") ; strButton2Text = Locale.ConvertTextKey( "TXT_KEY_DIPLO_DISCUSS_SORRY_FOR_SETTLING") ; -- CBP - local iTimeOutTurns = Game:GetPromiseDuration(); + local iTimeOutTurns = Game:GetExpansionPromiseDuration(); strButton2Tooltip = Locale.ConvertTextKey("TXT_KEY_DIPLO_DURATION_PROMISE", iTimeOutTurns); -- END bHideBackButton = true; @@ -545,7 +550,7 @@ function LeaderMessageHandler( iPlayer, iDiploUIState, szLeaderMessage, iAnimati strButton1Text = Locale.ConvertTextKey( "TXT_KEY_DIPLO_DISCUSS_NOT_YOUR_BUSINESS" ); strButton2Text = Locale.ConvertTextKey( "TXT_KEY_DIPLO_DISCUSS_SORRY_FOR_CLAIMING" ); -- CBP - local iTimeOutTurns = Game:GetPromiseDuration(); + local iTimeOutTurns = Game:GetBorderPromiseDuration(); strButton2Tooltip = Locale.ConvertTextKey("TXT_KEY_DIPLO_DURATION_PROMISE", iTimeOutTurns); -- END bHideBackButton = true; diff --git a/(2) Vox Populi/Database Changes/Text/en_US/UI/NewUIText.xml b/(2) Vox Populi/Database Changes/Text/en_US/UI/NewUIText.xml index d8e8a38ec2..f34da06fd9 100644 --- a/(2) Vox Populi/Database Changes/Text/en_US/UI/NewUIText.xml +++ b/(2) Vox Populi/Database Changes/Text/en_US/UI/NewUIText.xml @@ -1886,15 +1886,6 @@ - - Ask the leader to remove their troops from your border. If the leader rejects your request, they may choose to declare war on you, so be careful! - - - Please move your troops from our borders. - - - Going to attack us, swine? - It's time you learned some respect. (DECLARE WAR!) diff --git a/CvGameCoreDLL_Expansion2/CvDiplomacyAI.cpp b/CvGameCoreDLL_Expansion2/CvDiplomacyAI.cpp index 2ddf1c6694..cd09c2e4cc 100644 --- a/CvGameCoreDLL_Expansion2/CvDiplomacyAI.cpp +++ b/CvGameCoreDLL_Expansion2/CvDiplomacyAI.cpp @@ -8983,6 +8983,10 @@ bool CvDiplomacyAI::IsTooSoonForMoveTroopsRequest(PlayerTypes ePlayer) const if (!GET_TEAM(GetTeam()).canDeclareWar(GET_PLAYER(ePlayer).getTeam(), GetID())) return true; + // Exploit avoidance: No giving humans indirect backstabbing penalties + if (GetPlayer()->IsAITeammateOfHuman()) + return true; + return false; } @@ -30007,14 +30011,17 @@ void CvDiplomacyAI::DoSendStatementToPlayer(PlayerTypes ePlayer, DiploStatementT if (!GET_TEAM(GET_PLAYER(ePlayer).getTeam()).canDeclareWar(GetTeam())) { SetPlayerMilitaryPromiseState(ePlayer, PROMISE_STATE_MADE); + GET_PLAYER(ePlayer).GetDiplomacyAI()->SetPlayerMilitaryPromiseState(GetID(), PROMISE_STATE_MADE); } else { - if (GET_PLAYER(ePlayer).getFirstOffensiveAIOperation(GetID()) != NULL || GET_PLAYER(ePlayer).GetDiplomacyAI()->AvoidExchangesWithPlayer(GetID(), /*bWarOnly*/ true)) + MoveTroopsResponseTypes eResponse = GET_PLAYER(ePlayer).GetDiplomacyAI()->GetMoveTroopsRequestResponse(GetID(), /*bJustChecking*/ false); + if (eResponse == MOVE_TROOPS_RESPONSE_REFUSE) { if (!GET_PLAYER(ePlayer).GetDiplomacyAI()->DeclareWar(GetTeam())) { SetPlayerMilitaryPromiseState(ePlayer, PROMISE_STATE_MADE); + GET_PLAYER(ePlayer).GetDiplomacyAI()->SetPlayerMilitaryPromiseState(GetID(), PROMISE_STATE_MADE); } else { @@ -30024,6 +30031,7 @@ void CvDiplomacyAI::DoSendStatementToPlayer(PlayerTypes ePlayer, DiploStatementT else { SetPlayerMilitaryPromiseState(ePlayer, PROMISE_STATE_MADE); + GET_PLAYER(ePlayer).GetDiplomacyAI()->SetPlayerMilitaryPromiseState(GetID(), PROMISE_STATE_MADE); } } } @@ -33784,6 +33792,18 @@ void CvDiplomacyAI::DoAggressiveMilitaryStatement(PlayerTypes ePlayer, DiploStat if (GetMilitaryAggressivePosture(ePlayer) < AGGRESSIVE_POSTURE_HIGH) return; + // AI teammates of humans can't send this, otherwise the humans on our team might get a backstabbing penalty for something they weren't aware of + if (GetPlayer()->IsAITeammateOfHuman()) + return; + + // Don't send this to AI teammates of humans, otherwise the humans on their team might get a backstabbing penalty for something they weren't aware of + if (GET_PLAYER(ePlayer).IsAITeammateOfHuman()) + return; + + // This promise is mutual, so don't send the statement if we (or our teammates) are planning war + if (AvoidExchangesWithPlayer(ePlayer, /*bWarOnly*/ true)) + return; + // Check other player status for (int iThirdPartyLoop = 0; iThirdPartyLoop < MAX_MAJOR_CIVS; iThirdPartyLoop++) { @@ -33854,6 +33874,10 @@ void CvDiplomacyAI::DoAttackedCityStateStatement(PlayerTypes ePlayer, DiploState if (!GET_TEAM(GET_PLAYER(ePlayer).getTeam()).canDeclareWar(GetTeam(), ePlayer)) return; + // Don't send this to AI teammates of humans, otherwise the humans on their team might get a backstabbing penalty for something they weren't aware of + if (GET_PLAYER(ePlayer).IsAITeammateOfHuman()) + return; + if (GetOtherPlayerAttackedProtectedMinorTurn(ePlayer) == GC.getGame().getGameTurn()) { DiploStatementTypes eTempStatement = DIPLO_STATEMENT_ATTACKED_PROTECTED_CITY_STATE; @@ -38898,6 +38922,7 @@ void CvDiplomacyAI::DoFromUIDiploEvent(PlayerTypes eFromPlayer, FromUIDiploEvent if (iArg1 == 1) { SetPlayerMilitaryPromiseState(eFromPlayer, PROMISE_STATE_MADE); + GET_PLAYER(eFromPlayer).GetDiplomacyAI()->SetPlayerMilitaryPromiseState(GetID(), PROMISE_STATE_MADE); if (bActivePlayer) { @@ -40499,11 +40524,13 @@ void CvDiplomacyAI::DoFromUIDiploEvent(PlayerTypes eFromPlayer, FromUIDiploEvent // Make sure all players on this team get this check, so that teammates don't screw each other over. for (int iI=0; iI < MAX_MAJOR_CIVS; iI++) { - TeamTypes eLoopTeam = GET_PLAYER((PlayerTypes)iI).getTeam(); + PlayerTypes eTeammate = (PlayerTypes)iI; + TeamTypes eLoopTeam = GET_PLAYER(eTeammate).getTeam(); if (eLoopTeam == GetTeam()) { - GET_PLAYER((PlayerTypes)iI).GetDiplomacyAI()->SetPlayerMoveTroopsRequestAccepted(eFromPlayer, true); - GET_PLAYER(eFromPlayer).GetDiplomacyAI()->SetPlayerMilitaryPromiseState((PlayerTypes)iI, PROMISE_STATE_MADE); + GET_PLAYER(eTeammate).GetDiplomacyAI()->SetPlayerMoveTroopsRequestAccepted(eFromPlayer, true); + GET_PLAYER(eFromPlayer).GetDiplomacyAI()->SetPlayerMilitaryPromiseState(eTeammate, PROMISE_STATE_MADE); + GET_PLAYER(eTeammate).GetDiplomacyAI()->SetPlayerMilitaryPromiseState(eFromPlayer, PROMISE_STATE_MADE); } } @@ -40530,10 +40557,12 @@ void CvDiplomacyAI::DoFromUIDiploEvent(PlayerTypes eFromPlayer, FromUIDiploEvent // Make sure all players on this team get this check, so that teammates don't screw each other over. for (int iI=0; iI < MAX_MAJOR_CIVS; iI++) { - TeamTypes eLoopTeam = GET_PLAYER((PlayerTypes)iI).getTeam(); + PlayerTypes eTeammate = (PlayerTypes)iI; + TeamTypes eLoopTeam = GET_PLAYER(eTeammate).getTeam(); if (eLoopTeam == GetTeam()) { - GET_PLAYER(eFromPlayer).GetDiplomacyAI()->SetPlayerMilitaryPromiseState((PlayerTypes)iI, PROMISE_STATE_MADE); + GET_PLAYER(eFromPlayer).GetDiplomacyAI()->SetPlayerMilitaryPromiseState(eTeammate, PROMISE_STATE_MADE); + GET_PLAYER(eTeammate).GetDiplomacyAI()->SetPlayerMilitaryPromiseState(eFromPlayer, PROMISE_STATE_MADE); } } @@ -40547,6 +40576,7 @@ void CvDiplomacyAI::DoFromUIDiploEvent(PlayerTypes eFromPlayer, FromUIDiploEvent else if (eResponse == MOVE_TROOPS_RESPONSE_REFUSE) { // Declare war on human! + bool bWasDeceptive = GetCivApproach(eFromPlayer) == CIV_APPROACH_DECEPTIVE || (GetCivApproach(eFromPlayer) == CIV_APPROACH_WAR && GetSurfaceApproach(eFromPlayer) == CIV_APPROACH_FRIENDLY); if (DeclareWar(eFromTeam)) { GET_PLAYER(eFromPlayer).GetDiplomacyAI()->SetPlayerMilitaryPromiseState(eMyPlayer, PROMISE_STATE_IGNORED); @@ -40558,7 +40588,7 @@ void CvDiplomacyAI::DoFromUIDiploEvent(PlayerTypes eFromPlayer, FromUIDiploEvent strText = GetDiploStringForMessage(DIPLO_MESSAGE_MOVE_TROOPS_REJECT_CONQUEST); } // Was deceptive - else if (GetCivApproach(eFromPlayer) == CIV_APPROACH_DECEPTIVE) + else if (bWasDeceptive) { strText = GetDiploStringForMessage(DIPLO_MESSAGE_MOVE_TROOPS_REJECT_DECEPTIVE); } @@ -40576,10 +40606,12 @@ void CvDiplomacyAI::DoFromUIDiploEvent(PlayerTypes eFromPlayer, FromUIDiploEvent // AI agrees not to attack for (int iI = 0; iI < MAX_MAJOR_CIVS; iI++) { - TeamTypes eLoopTeam = GET_PLAYER((PlayerTypes)iI).getTeam(); + PlayerTypes eTeammate = (PlayerTypes)iI; + TeamTypes eLoopTeam = GET_PLAYER(eTeammate).getTeam(); if (eLoopTeam == GetTeam()) { - GET_PLAYER(eFromPlayer).GetDiplomacyAI()->SetPlayerMilitaryPromiseState((PlayerTypes)iI, PROMISE_STATE_MADE); + GET_PLAYER(eFromPlayer).GetDiplomacyAI()->SetPlayerMilitaryPromiseState(eTeammate, PROMISE_STATE_MADE); + GET_PLAYER(eTeammate).GetDiplomacyAI()->SetPlayerMilitaryPromiseState(eFromPlayer, PROMISE_STATE_MADE); } } @@ -58151,7 +58183,6 @@ MoveTroopsResponseTypes CvDiplomacyAI::GetMoveTroopsRequestResponse(PlayerTypes // Prevent human from abusing AI to declare war on a human if(!bJustChecking) { - MoveTroopsResponseTypes eTeammateResponse; int iYes = 0; int iNeutral = 0; int iNo = 0; @@ -58164,7 +58195,7 @@ MoveTroopsResponseTypes CvDiplomacyAI::GetMoveTroopsRequestResponse(PlayerTypes if(IsTeammate(eLoopPlayer)) { // bJustChecking = true to prevent infinite loop - eTeammateResponse = GET_PLAYER(eLoopPlayer).GetDiplomacyAI()->GetMoveTroopsRequestResponse(ePlayer, /*bJustChecking*/ true); + MoveTroopsResponseTypes eTeammateResponse = GET_PLAYER(eLoopPlayer).GetDiplomacyAI()->GetMoveTroopsRequestResponse(ePlayer, /*bJustChecking*/ true); switch (eTeammateResponse) { diff --git a/CvGameCoreDLL_Expansion2/Lua/CvLuaGame.cpp b/CvGameCoreDLL_Expansion2/Lua/CvLuaGame.cpp index dc0e53e319..3b4508487e 100644 --- a/CvGameCoreDLL_Expansion2/Lua/CvLuaGame.cpp +++ b/CvGameCoreDLL_Expansion2/Lua/CvLuaGame.cpp @@ -341,7 +341,9 @@ void CvLuaGame::RegisterMembers(lua_State* L) Method(GetScienceMedianModifierBuildingGlobal); Method(GetCultureMedianModifierBuildingGlobal); Method(GetReligiousUnrestModifierBuildingGlobal); - Method(GetPromiseDuration); + Method(GetMilitaryPromiseDuration); + Method(GetExpansionPromiseDuration); + Method(GetBorderPromiseDuration); Method(GetCorporationFounder); Method(GetCorporationHeadquarters); Method(GetNumCorporationsFounded); @@ -2531,12 +2533,25 @@ int CvLuaGame::lGetBuildingCorporateGPChange(lua_State* L) lua_pushinteger(L, iYieldChange); return 1; } -int CvLuaGame::lGetPromiseDuration(lua_State* L) +int CvLuaGame::lGetMilitaryPromiseDuration(lua_State* L) +{ + // This promise does not scale with game speed! + int iTimeOutTurns = /*20*/ GD_INT_GET(MOVE_TROOPS_MEMORY_TURN_EXPIRATION); + lua_pushinteger(L, iTimeOutTurns); + return 1; +} +int CvLuaGame::lGetExpansionPromiseDuration(lua_State* L) { int iTimeOutTurns = (/*50*/ GD_INT_GET(EXPANSION_PROMISE_TURNS_EFFECTIVE) * GC.getGame().getGameSpeedInfo().getOpinionDurationPercent()) / 100; lua_pushinteger(L, iTimeOutTurns); return 1; } +int CvLuaGame::lGetBorderPromiseDuration(lua_State* L) +{ + int iTimeOutTurns = (/*50*/ GD_INT_GET(BORDER_PROMISE_TURNS_EFFECTIVE) * GC.getGame().getGameSpeedInfo().getOpinionDurationPercent()) / 100; + lua_pushinteger(L, iTimeOutTurns); + return 1; +} int CvLuaGame::lGetCorporationFounder(lua_State* L) { diff --git a/CvGameCoreDLL_Expansion2/Lua/CvLuaGame.h b/CvGameCoreDLL_Expansion2/Lua/CvLuaGame.h index 074d26bd60..b36f58e0a6 100644 --- a/CvGameCoreDLL_Expansion2/Lua/CvLuaGame.h +++ b/CvGameCoreDLL_Expansion2/Lua/CvLuaGame.h @@ -325,7 +325,9 @@ class CvLuaGame : public CvLuaStaticInstance static int lGetCultureMedianModifierBuildingGlobal(lua_State* L); static int lGetReligiousUnrestModifierBuildingGlobal(lua_State* L); static int lGetBuildingCorporateGPChange(lua_State* L); - static int lGetPromiseDuration(lua_State* L); + static int lGetMilitaryPromiseDuration(lua_State* L); + static int lGetExpansionPromiseDuration(lua_State* L); + static int lGetBorderPromiseDuration(lua_State* L); static int lGetCorporationFounder(lua_State* L); static int lGetCorporationHeadquarters(lua_State* L); static int lGetNumCorporationsFounded(lua_State* L);