diff --git a/core/src/com/unciv/logic/automation/civilization/NextTurnAutomation.kt b/core/src/com/unciv/logic/automation/civilization/NextTurnAutomation.kt index 26322c7660..72665f00a8 100644 --- a/core/src/com/unciv/logic/automation/civilization/NextTurnAutomation.kt +++ b/core/src/com/unciv/logic/automation/civilization/NextTurnAutomation.kt @@ -796,7 +796,7 @@ object NextTurnAutomation { // Default setting is 5, this will be changed according to different civ. if ((1..10).random() > 5) continue val tradeLogic = TradeLogic(civInfo, otherCiv) - val cost = civInfo.diplomacyFunctions.getResearchAgreementCost() + val cost = civInfo.diplomacyFunctions.getResearchAgreementCost(otherCiv) tradeLogic.currentTrade.ourOffers.add(TradeOffer(Constants.researchAgreement, TradeType.Treaty, cost)) tradeLogic.currentTrade.theirOffers.add(TradeOffer(Constants.researchAgreement, TradeType.Treaty, cost)) diff --git a/core/src/com/unciv/logic/civilization/diplomacy/DiplomacyFunctions.kt b/core/src/com/unciv/logic/civilization/diplomacy/DiplomacyFunctions.kt index 0bcbac801d..b079290cbf 100644 --- a/core/src/com/unciv/logic/civilization/diplomacy/DiplomacyFunctions.kt +++ b/core/src/com/unciv/logic/civilization/diplomacy/DiplomacyFunctions.kt @@ -11,6 +11,7 @@ import com.unciv.logic.map.tile.Tile import com.unciv.models.ruleset.unique.UniqueType import com.unciv.models.stats.Stat import com.unciv.models.stats.Stats +import kotlin.math.max class DiplomacyFunctions(val civInfo: Civilization){ @@ -93,22 +94,26 @@ class DiplomacyFunctions(val civInfo: Civilization){ .none { civInfo.tech.canBeResearched(it.name) && !civInfo.tech.isResearched(it.name) }) return false return true } - - fun canSignResearchAgreementsWith(otherCiv: Civilization): Boolean { + + fun canSignResearchAgreementNoCostWith (otherCiv: Civilization): Boolean { val diplomacyManager = civInfo.getDiplomacyManager(otherCiv) - val cost = getResearchAgreementCost() return canSignResearchAgreement() && otherCiv.diplomacyFunctions.canSignResearchAgreement() - && diplomacyManager.hasFlag(DiplomacyFlags.DeclarationOfFriendship) - && !diplomacyManager.hasFlag(DiplomacyFlags.ResearchAgreement) - && !diplomacyManager.otherCivDiplomacy().hasFlag(DiplomacyFlags.ResearchAgreement) - && civInfo.gold >= cost && otherCiv.gold >= cost + && diplomacyManager.hasFlag(DiplomacyFlags.DeclarationOfFriendship) + && !diplomacyManager.hasFlag(DiplomacyFlags.ResearchAgreement) + && !diplomacyManager.otherCivDiplomacy().hasFlag(DiplomacyFlags.ResearchAgreement) } - fun getResearchAgreementCost(): Int { + fun canSignResearchAgreementsWith(otherCiv: Civilization): Boolean { + val cost = getResearchAgreementCost(otherCiv) + return canSignResearchAgreementNoCostWith(otherCiv) + && civInfo.gold >= cost && otherCiv.gold >= cost + } + + fun getResearchAgreementCost(otherCiv: Civilization): Int { // https://forums.civfanatics.com/resources/research-agreements-bnw.25568/ - return ( - civInfo.getEra().researchAgreementCost * civInfo.gameInfo.speed.goldCostModifier - ).toInt() + return ( max(civInfo.getEra().researchAgreementCost, otherCiv.getEra().researchAgreementCost) + * civInfo.gameInfo.speed.goldCostModifier + ).toInt() } fun canSignDefensivePact(): Boolean { diff --git a/core/src/com/unciv/logic/trade/TradeLogic.kt b/core/src/com/unciv/logic/trade/TradeLogic.kt index 9392532768..3cda0987bd 100644 --- a/core/src/com/unciv/logic/trade/TradeLogic.kt +++ b/core/src/com/unciv/logic/trade/TradeLogic.kt @@ -32,8 +32,8 @@ class TradeLogic(val ourCivilization:Civilization, val otherCivilization: Civili offers.add(TradeOffer(Constants.openBorders, TradeType.Agreement)) } - if (civInfo.diplomacyFunctions.canSignResearchAgreementsWith(otherCivilization)) - offers.add(TradeOffer(Constants.researchAgreement, TradeType.Treaty, civInfo.diplomacyFunctions.getResearchAgreementCost())) + if (civInfo.diplomacyFunctions.canSignResearchAgreementNoCostWith(otherCivilization)) + offers.add(TradeOffer(Constants.researchAgreement, TradeType.Treaty, civInfo.diplomacyFunctions.getResearchAgreementCost(otherCivilization))) if (civInfo.diplomacyFunctions.canSignDefensivePactWith(otherCivilization)) offers.add(TradeOffer(Constants.defensivePact, TradeType.Treaty)) diff --git a/core/src/com/unciv/ui/screens/diplomacyscreen/OfferColumnsTable.kt b/core/src/com/unciv/ui/screens/diplomacyscreen/OfferColumnsTable.kt index 3a1a6497e7..45f80d539b 100644 --- a/core/src/com/unciv/ui/screens/diplomacyscreen/OfferColumnsTable.kt +++ b/core/src/com/unciv/ui/screens/diplomacyscreen/OfferColumnsTable.kt @@ -18,10 +18,12 @@ import com.unciv.ui.screens.basescreen.BaseScreen class OfferColumnsTable( private val tradeLogic: TradeLogic, private val screen: DiplomacyScreen, + private val ourCiv: Civilization, + private val theirCiv: Civilization, private val onChange: () -> Unit ): Table(BaseScreen.skin) { - private fun addOffer(offer: TradeOffer, offerList: TradeOffersList, correspondingOfferList: TradeOffersList) { + fun addOffer(offer: TradeOffer, offerList: TradeOffersList, correspondingOfferList: TradeOffersList) { offerList.add(offer.copy()) if (offer.type == TradeType.Treaty) correspondingOfferList.add(offer.copy()) onChange() @@ -104,10 +106,10 @@ class OfferColumnsTable( .removeAll(Constants.tradable) val theirUntradables = tradeLogic.otherCivilization.getCivResourcesWithOriginsForTrade() .removeAll(Constants.tradable) - ourAvailableOffersTable.update(ourFilteredOffers, tradeLogic.theirAvailableOffers, ourUntradables) - ourOffersTable.update(tradeLogic.currentTrade.ourOffers, tradeLogic.theirAvailableOffers) - theirOffersTable.update(tradeLogic.currentTrade.theirOffers, tradeLogic.ourAvailableOffers) - theirAvailableOffersTable.update(theirFilteredOffers, tradeLogic.ourAvailableOffers, theirUntradables) + ourAvailableOffersTable.update(ourFilteredOffers, tradeLogic.theirAvailableOffers, ourUntradables, ourCiv, theirCiv) + ourOffersTable.update(tradeLogic.currentTrade.ourOffers, tradeLogic.theirAvailableOffers, ourCiv = ourCiv, theirCiv = theirCiv) + theirOffersTable.update(tradeLogic.currentTrade.theirOffers, tradeLogic.ourAvailableOffers, ourCiv = ourCiv, theirCiv = theirCiv) + theirAvailableOffersTable.update(theirFilteredOffers, tradeLogic.ourAvailableOffers, theirUntradables, ourCiv, theirCiv) } private fun openGoldSelectionPopup(offer: TradeOffer, ourOffers: TradeOffersList, maxGold: Int) { diff --git a/core/src/com/unciv/ui/screens/diplomacyscreen/OffersListScroll.kt b/core/src/com/unciv/ui/screens/diplomacyscreen/OffersListScroll.kt index 0375535c66..ff91dfa61f 100644 --- a/core/src/com/unciv/ui/screens/diplomacyscreen/OffersListScroll.kt +++ b/core/src/com/unciv/ui/screens/diplomacyscreen/OffersListScroll.kt @@ -5,6 +5,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.Table import com.badlogic.gdx.utils.Align import com.unciv.Constants import com.unciv.UncivGame +import com.unciv.logic.civilization.Civilization import com.unciv.logic.trade.TradeOffer import com.unciv.logic.trade.TradeOffersList import com.unciv.logic.trade.TradeType @@ -52,7 +53,9 @@ class OffersListScroll( fun update( offersToDisplay: TradeOffersList, otherOffers: TradeOffersList, - untradableOffers: ResourceSupplyList = ResourceSupplyList.emptyList + untradableOffers: ResourceSupplyList = ResourceSupplyList.emptyList, + ourCiv: Civilization, + theirCiv: Civilization ) { table.clear() expanderTabs.clear() @@ -109,7 +112,10 @@ class OffersListScroll( else -> 1 } - if (offer.isTradable() && offer.name != Constants.peaceTreaty) { // can't disable peace treaty! + if (offer.isTradable() && offer.name != Constants.peaceTreaty // can't disable peace treaty! + && (offer.name != Constants.researchAgreement // If we have a research agreement make sure the total gold of both Civs is higher than the total cost + // If both civs combined can pay for the research agreement, don't disable it. One can offer the other it's gold. + || (ourCiv.gold + theirCiv.gold > ourCiv.diplomacyFunctions.getResearchAgreementCost(theirCiv) * 2))) { // highlight unique suggestions if (offerType in listOf(Luxury_Resource, Strategic_Resource) diff --git a/core/src/com/unciv/ui/screens/diplomacyscreen/TradeTable.kt b/core/src/com/unciv/ui/screens/diplomacyscreen/TradeTable.kt index b074d9318a..49c0b1f9aa 100644 --- a/core/src/com/unciv/ui/screens/diplomacyscreen/TradeTable.kt +++ b/core/src/com/unciv/ui/screens/diplomacyscreen/TradeTable.kt @@ -1,9 +1,11 @@ package com.unciv.ui.screens.diplomacyscreen import com.badlogic.gdx.scenes.scene2d.ui.Table +import com.unciv.Constants import com.unciv.logic.civilization.Civilization import com.unciv.logic.trade.TradeLogic import com.unciv.logic.trade.TradeRequest +import com.unciv.logic.trade.TradeType import com.unciv.models.translations.tr import com.unciv.ui.screens.basescreen.BaseScreen import com.unciv.ui.components.extensions.isEnabled @@ -16,7 +18,7 @@ class TradeTable( ): Table(BaseScreen.skin) { private val currentPlayerCiv = otherCivilization.gameInfo.getCurrentPlayerCivilization() internal val tradeLogic = TradeLogic(currentPlayerCiv, otherCivilization) - internal val offerColumnsTable = OfferColumnsTable(tradeLogic, diplomacyScreen) { onChange() } + internal val offerColumnsTable = OfferColumnsTable(tradeLogic, diplomacyScreen , currentPlayerCiv, otherCivilization) { onChange() } // This is so that after a trade has been traded, we can switch out the offersToDisplay to start anew - this is the easiest way private val offerColumnsTableWrapper = Table() private val offerButton = "Offer trade".toTextButton() @@ -49,6 +51,26 @@ class TradeTable( retractOffer() return@onClick } + // If there is a research agreement trade, make sure both civilizations should be able to pay for it. + // If not lets add an extra gold offer to satisfy this. + // There must be enough gold to add to the offer to satisfy this, otherwise the research agreement button would be disabled + if (tradeLogic.currentTrade.ourOffers.any { it.name == Constants.researchAgreement}) { + val researchCost = currentPlayerCiv.diplomacyFunctions.getResearchAgreementCost(otherCivilization) + val currentPlayerOfferedGold = tradeLogic.currentTrade.ourOffers.firstOrNull { it.type == TradeType.Gold }?.amount ?: 0 + val otherCivOfferedGold = tradeLogic.currentTrade.theirOffers.firstOrNull { it.type == TradeType.Gold }?.amount ?: 0 + val newCurrentPlayerGold = currentPlayerCiv.gold + otherCivOfferedGold - researchCost + val newOtherCivGold = otherCivilization.gold + currentPlayerOfferedGold - researchCost + // Check if we require more gold from them + if (newCurrentPlayerGold < 0) { + offerColumnsTable.addOffer( tradeLogic.theirAvailableOffers.first { it.type == TradeType.Gold } + .copy(amount = -newCurrentPlayerGold), tradeLogic.currentTrade.theirOffers, tradeLogic.currentTrade.ourOffers) + } + // Check if they require more gold from us + if (newOtherCivGold < 0) { + offerColumnsTable.addOffer( tradeLogic.ourAvailableOffers.first { it.type == TradeType.Gold } + .copy(amount = -newOtherCivGold), tradeLogic.currentTrade.ourOffers, tradeLogic.currentTrade.theirOffers) + } + } otherCivilization.tradeRequests.add(TradeRequest(currentPlayerCiv.civName, tradeLogic.currentTrade.reverse())) currentPlayerCiv.cache.updateCivResources()