diff --git a/android/assets/game.png b/android/assets/game.png index 984ebe86eb..ac45c40d50 100644 Binary files a/android/assets/game.png and b/android/assets/game.png differ diff --git a/android/build.gradle b/android/build.gradle index 1fc029f903..341d7ae9b8 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -21,8 +21,8 @@ android { applicationId "com.unciv.app" minSdkVersion 14 targetSdkVersion 28 - versionCode 229 - versionName "2.14.9" + versionCode 230 + versionName "2.14.10" } // Had to add this crap for Travis to build, it wanted to sign the app diff --git a/core/src/com/unciv/logic/automation/NextTurnAutomation.kt b/core/src/com/unciv/logic/automation/NextTurnAutomation.kt index 917bb699f4..f5ad93cc29 100644 --- a/core/src/com/unciv/logic/automation/NextTurnAutomation.kt +++ b/core/src/com/unciv/logic/automation/NextTurnAutomation.kt @@ -2,12 +2,10 @@ package com.unciv.logic.automation import com.unciv.logic.civilization.CivilizationInfo import com.unciv.logic.civilization.PlayerType +import com.unciv.logic.civilization.TradeRequest import com.unciv.logic.civilization.diplomacy.DiplomaticStatus import com.unciv.logic.map.MapUnit -import com.unciv.logic.trade.TradeEvaluation -import com.unciv.logic.trade.TradeLogic -import com.unciv.logic.trade.TradeOffer -import com.unciv.logic.trade.TradeType +import com.unciv.logic.trade.* import com.unciv.models.gamebasics.GameBasics import com.unciv.models.gamebasics.tech.Technology import com.unciv.models.gamebasics.tr @@ -115,30 +113,62 @@ class NextTurnAutomation{ } } + fun potentialLuxuryTrades(civInfo:CivilizationInfo, otherCivInfo:CivilizationInfo): ArrayList { + val tradeLogic = TradeLogic(civInfo, otherCivInfo) + val ourTradableLuxuryResources = tradeLogic.ourAvailableOffers + .filter { it.type == TradeType.Luxury_Resource && it.amount > 1 } + val theirTradableLuxuryResources = tradeLogic.theirAvailableOffers + .filter { it.type == TradeType.Luxury_Resource && it.amount > 1 } + val weHaveTheyDont = ourTradableLuxuryResources + .filter { resource -> + tradeLogic.theirAvailableOffers + .none { it.name == resource.name && it.type == TradeType.Luxury_Resource } + } + val theyHaveWeDont = theirTradableLuxuryResources + .filter { resource -> + tradeLogic.ourAvailableOffers + .none { it.name == resource.name && it.type == TradeType.Luxury_Resource } + } + val trades = ArrayList() + for(i in 0..min(weHaveTheyDont.lastIndex, theyHaveWeDont.lastIndex)){ + val trade = Trade() + trade.ourOffers.add(weHaveTheyDont[i].copy(amount = 1)) + trade.theirOffers.add(theyHaveWeDont[i].copy(amount = 1)) + trades.add(trade) + } + return trades + } + private fun exchangeLuxuries(civInfo: CivilizationInfo) { - for (otherCiv in civInfo.diplomacy.values.map { it.otherCiv() }.filterNot { it.isPlayerCivilization() }) { - val tradeLogic = TradeLogic(civInfo, otherCiv) - val ourTradableLuxuryResources = tradeLogic.ourAvailableOffers - .filter { it.type == TradeType.Luxury_Resource && it.amount > 1 } - val theirTradableLuxuryResources = tradeLogic.theirAvailableOffers - .filter { it.type == TradeType.Luxury_Resource && it.amount > 1 } - val weHaveTheyDont = ourTradableLuxuryResources - .filter { resource -> - tradeLogic.theirAvailableOffers - .none { it.name == resource.name && it.type == TradeType.Luxury_Resource } - } - val theyHaveWeDont = theirTradableLuxuryResources - .filter { resource -> - tradeLogic.ourAvailableOffers - .none { it.name == resource.name && it.type == TradeType.Luxury_Resource } - } - val numberOfTrades = min(weHaveTheyDont.size, theyHaveWeDont.size) - if (numberOfTrades > 0) { - tradeLogic.currentTrade.ourOffers.addAll(weHaveTheyDont.take(numberOfTrades).map { it.copy(amount = 1) }) - tradeLogic.currentTrade.theirOffers.addAll(theyHaveWeDont.take(numberOfTrades).map { it.copy(amount = 1) }) + val knownCivs = civInfo.diplomacy.values.map { it.otherCiv() } + + // Player trades are... more complicated. + // When the AI offers a trade, it's not immediately accepted, + // so what if it thinks that it has a spare luxury and offers it to two human players? + // What's to stop the AI "nagging" the player to accept a luxury trade? + // We should A. add some sort of timer (20? 30 turns?) between luxury trade requests if they're denied + // B. have a way for the AI to keep track of the "pending offers" - see DiplomacyManager.resourcesFromTrade + + for (otherCiv in knownCivs.filter { it.isPlayerCivilization() }) { + val trades = potentialLuxuryTrades(civInfo,otherCiv) + for(trade in trades){ + val tradeRequest = TradeRequest(civInfo.civName, trade.reverse()) + otherCiv.tradeRequests.add(tradeRequest) + } + } + + // AI trades are automatically accepted + for (otherCiv in knownCivs.filterNot { it.isPlayerCivilization() }) { + val trades = potentialLuxuryTrades(civInfo,otherCiv) + for(trade in trades){ + val tradeLogic = TradeLogic(civInfo,otherCiv) + tradeLogic.currentTrade.ourOffers.addAll(trade.ourOffers) + tradeLogic.currentTrade.theirOffers.addAll(trade.theirOffers) tradeLogic.acceptTrade() } } + + } fun getMinDistanceBetweenCities(civ1: CivilizationInfo, civ2: CivilizationInfo): Int { diff --git a/core/src/com/unciv/logic/civilization/CivilizationInfo.kt b/core/src/com/unciv/logic/civilization/CivilizationInfo.kt index b3a6318dd1..7261d971ad 100644 --- a/core/src/com/unciv/logic/civilization/CivilizationInfo.kt +++ b/core/src/com/unciv/logic/civilization/CivilizationInfo.kt @@ -12,6 +12,7 @@ import com.unciv.logic.map.BFS import com.unciv.logic.map.MapUnit import com.unciv.logic.map.RoadStatus import com.unciv.logic.map.TileInfo +import com.unciv.logic.trade.Trade import com.unciv.models.Counter import com.unciv.models.gamebasics.Difficulty import com.unciv.models.gamebasics.GameBasics @@ -33,18 +34,23 @@ enum class PlayerType{ Human } +class TradeRequest(val requestingCiv:String, + /** Their offers are what they offer us, and our offers are what they want in return */ + val trade: Trade){ +} + class CivilizationInfo { @Transient lateinit var gameInfo: GameInfo /** - * never add or remove from here directly, could cause comodification problems. - * Instead, create a copy list with the change, and replace this list. + * We never add or remove from here directly, could cause comodification problems. + * Instead, we create a copy list with the change, and replace this list. * The other solution, casting toList() every "get", has a performance cost */ - @Transient private var units=ArrayList() - @Transient var viewableTiles = HashSet() - @Transient var viewableInvisibleUnitsTiles = HashSet() + @Transient private var units=listOf() + @Transient var viewableTiles = setOf() + @Transient var viewableInvisibleUnitsTiles = setOf() - // This is for performance since every movement calculation depends on this, see MapUnit comment + /** This is for performance since every movement calculation depends on this, see MapUnit comment */ @Transient var hasActiveGreatWall = false var gold = 0 @@ -61,6 +67,7 @@ class CivilizationInfo { var diplomacy = HashMap() var notifications = ArrayList() val popupAlerts = ArrayList() + val tradeRequests = ArrayList() // if we only use lists, and change the list each time the cities are changed, // we won't get concurrent modification exceptions. @@ -79,14 +86,14 @@ class CivilizationInfo { fun clone(): CivilizationInfo { val toReturn = CivilizationInfo() toReturn.gold = gold - toReturn.happiness=happiness - toReturn.playerType=playerType - toReturn.civName=civName + toReturn.happiness = happiness + toReturn.playerType = playerType + toReturn.civName = civName toReturn.tech = tech.clone() toReturn.policies = policies.clone() toReturn.goldenAges = goldenAges.clone() - toReturn.greatPeople=greatPeople.clone() - toReturn.victoryManager=victoryManager.clone() + toReturn.greatPeople = greatPeople.clone() + toReturn.victoryManager = victoryManager.clone() toReturn.diplomacy.putAll(diplomacy.values.map { it.clone() }.associateBy { it.otherCivName }) toReturn.cities = cities.map { it.clone() } toReturn.exploredTiles.addAll(exploredTiles) @@ -116,10 +123,7 @@ class CivilizationInfo { fun isPlayerCivilization() = playerType==PlayerType.Human fun isCurrentPlayer() = gameInfo.getCurrentPlayerCivilization()==this fun isBarbarianCivilization() = gameInfo.getBarbarianCivilization()==this - - fun getStatsForNextTurn():Stats{ - return getStatMapForNextTurn().values.toList().reduce{a,b->a+b} - } + fun getStatsForNextTurn():Stats = getStatMapForNextTurn().values.toList().reduce{a,b->a+b} fun getStatMapForNextTurn(): HashMap { val statMap = HashMap() diff --git a/core/src/com/unciv/logic/civilization/diplomacy/DiplomacyManager.kt b/core/src/com/unciv/logic/civilization/diplomacy/DiplomacyManager.kt index 51761c6fc7..c8aba47f1a 100644 --- a/core/src/com/unciv/logic/civilization/diplomacy/DiplomacyManager.kt +++ b/core/src/com/unciv/logic/civilization/diplomacy/DiplomacyManager.kt @@ -16,6 +16,8 @@ class DiplomacyManager() { lateinit var otherCivName:String var trades = ArrayList() var diplomaticStatus = DiplomaticStatus.War + /** Contains various flags (declared war, promised to not settle, declined luxury trade) and the number of turns in which they will expire */ + var flagsCountdown = HashMap() fun clone(): DiplomacyManager { val toReturn = DiplomacyManager() @@ -63,6 +65,11 @@ class DiplomacyManager() { if(offer.type== TradeType.Strategic_Resource || offer.type== TradeType.Luxury_Resource) counter.add(GameBasics.TileResources[offer.name]!!,offer.amount) } + for(tradeRequest in otherCiv().tradeRequests.filter { it.requestingCiv==civInfo.civName }){ + for(offer in tradeRequest.trade.theirOffers) // "theirOffers" in the other civ's trade request, is actually out civ's offers + if(offer.type== TradeType.Strategic_Resource || offer.type== TradeType.Luxury_Resource) + counter.add(GameBasics.TileResources[offer.name]!!,-offer.amount) + } return counter } //endregion @@ -95,6 +102,12 @@ class DiplomacyManager() { } } removeUntenebleTrades() + + for(flag in flagsCountdown.keys.toList()) { + flagsCountdown[flag] = flagsCountdown[flag]!! - 1 + if(flagsCountdown[flag]==0) flagsCountdown.remove(flag) + } + } fun declareWar(){ diff --git a/core/src/com/unciv/logic/trade/Trade.kt b/core/src/com/unciv/logic/trade/Trade.kt index d27a25b68d..bd471584e7 100644 --- a/core/src/com/unciv/logic/trade/Trade.kt +++ b/core/src/com/unciv/logic/trade/Trade.kt @@ -31,4 +31,11 @@ class Trade{ toReturn.ourOffers.addAll(ourOffers) return toReturn } + + fun set(trade: Trade) { + ourOffers.clear() + ourOffers.addAll(trade.ourOffers) + theirOffers.clear() + theirOffers.addAll(trade.theirOffers) + } } \ No newline at end of file diff --git a/core/src/com/unciv/logic/trade/TradeOffer.kt b/core/src/com/unciv/logic/trade/TradeOffer.kt index c27c5fc267..f872ea97ef 100644 --- a/core/src/com/unciv/logic/trade/TradeOffer.kt +++ b/core/src/com/unciv/logic/trade/TradeOffer.kt @@ -1,5 +1,7 @@ package com.unciv.logic.trade +import com.unciv.models.gamebasics.tr + data class TradeOffer(var name:String, var type: TradeType, var duration:Int, var amount:Int=1) { constructor() : this("", TradeType.Gold,0,0) // so that the json deserializer can work @@ -9,4 +11,18 @@ data class TradeOffer(var name:String, var type: TradeType, var duration:Int, va && offer.type==type && offer.amount==amount } + + + fun getOfferText(): String { + var offerText = name.tr() + if (type !in tradesToNotHaveNumbers) offerText += " (" + amount + ")" + if (duration > 1) offerText += "\n" + duration + " {turns}".tr() + return offerText + } + + private companion object{ + val tradesToNotHaveNumbers = listOf(TradeType.Technology, TradeType.City, + TradeType.Introduction, TradeType.Treaty, TradeType.WarDeclaration) + } + } \ No newline at end of file diff --git a/core/src/com/unciv/models/gamebasics/Nation.kt b/core/src/com/unciv/models/gamebasics/Nation.kt index abaf0425a3..29e1a62b47 100644 --- a/core/src/com/unciv/models/gamebasics/Nation.kt +++ b/core/src/com/unciv/models/gamebasics/Nation.kt @@ -12,12 +12,13 @@ class Nation : INamed { else return name } - lateinit var leaderName: String + var leaderName="" - lateinit var declaringWar:String - lateinit var attacked:String - lateinit var defeated:String - lateinit var introduction:String + var declaringWar="" + var attacked="" + var defeated="" + var introduction="" + var tradeRequest="" var neutralLetsHearIt = ArrayList() var neutralYes = ArrayList() diff --git a/core/src/com/unciv/ui/trade/DiplomacyScreen.kt b/core/src/com/unciv/ui/trade/DiplomacyScreen.kt index 40e904d6a1..fdbbacab18 100644 --- a/core/src/com/unciv/ui/trade/DiplomacyScreen.kt +++ b/core/src/com/unciv/ui/trade/DiplomacyScreen.kt @@ -7,6 +7,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.Table import com.badlogic.gdx.scenes.scene2d.ui.TextButton import com.unciv.UnCivGame import com.unciv.logic.civilization.CivilizationInfo +import com.unciv.logic.trade.TradeLogic import com.unciv.models.gamebasics.tr import com.unciv.ui.utils.* import com.unciv.ui.worldscreen.optionstable.PopupTable @@ -59,6 +60,13 @@ class DiplomacyScreen:CameraStageBaseScreen() { } } + fun setTrade(civ: CivilizationInfo): TradeTable { + rightSideTable.clear() + val tradeTable =TradeTable(civ, stage) { updateLeftSideTable() } + rightSideTable.add(tradeTable) + return tradeTable + } + private fun getDiplomacyTable(civ: CivilizationInfo): Table { val diplomacyTable = Table() diplomacyTable.defaults().pad(10f) @@ -67,10 +75,7 @@ class DiplomacyScreen:CameraStageBaseScreen() { diplomacyTable.addSeparator() val tradeButton = TextButton("Trade".tr(), skin) - tradeButton.onClick { - rightSideTable.clear() - rightSideTable.add(TradeTable(civ, stage) { updateLeftSideTable() }) - } + tradeButton.onClick { setTrade(civ) } diplomacyTable.add(tradeButton).row() val currentPlayerCiv = UnCivGame.Current.gameInfo.getCurrentPlayerCivilization() diff --git a/core/src/com/unciv/ui/trade/OffersListScroll.kt b/core/src/com/unciv/ui/trade/OffersListScroll.kt index ba65ad49ca..d6729a2048 100644 --- a/core/src/com/unciv/ui/trade/OffersListScroll.kt +++ b/core/src/com/unciv/ui/trade/OffersListScroll.kt @@ -7,7 +7,6 @@ import com.unciv.logic.trade.TradeOffer import com.unciv.logic.trade.TradeOffersList import com.unciv.logic.trade.TradeType import com.unciv.logic.trade.TradeType.* -import com.unciv.models.gamebasics.tr import com.unciv.ui.cityscreen.ExpanderTab import com.unciv.ui.utils.CameraStageBaseScreen import com.unciv.ui.utils.disable @@ -16,8 +15,7 @@ import kotlin.math.min class OffersListScroll(val onOfferClicked: (TradeOffer) -> Unit) : ScrollPane(null) { val table = Table(CameraStageBaseScreen.skin).apply { defaults().pad(5f) } - val tradesToNotHaveNumbers = listOf(Technology, City, - Introduction, Treaty, WarDeclaration) + val expanderTabs = HashMap() @@ -50,10 +48,7 @@ class OffersListScroll(val onOfferClicked: (TradeOffer) -> Unit) : ScrollPane(nu } for (offer in offersOfType) { - var buttonText = offer.name.tr() - if (offer.type !in tradesToNotHaveNumbers) buttonText += " (" + offer.amount + ")" - if (offer.duration > 1) buttonText += "\n" + offer.duration + " {turns}".tr() - val tradeButton = TextButton(buttonText, CameraStageBaseScreen.skin) + val tradeButton = TextButton(offer.getOfferText(), CameraStageBaseScreen.skin) val amountPerClick = if (offer.type == Gold) 50 else 1 diff --git a/core/src/com/unciv/ui/worldscreen/AlertPopup.kt b/core/src/com/unciv/ui/worldscreen/AlertPopup.kt new file mode 100644 index 0000000000..57e54fde36 --- /dev/null +++ b/core/src/com/unciv/ui/worldscreen/AlertPopup.kt @@ -0,0 +1,74 @@ +package com.unciv.ui.worldscreen + +import com.badlogic.gdx.scenes.scene2d.ui.Table +import com.badlogic.gdx.scenes.scene2d.ui.TextButton +import com.unciv.logic.civilization.AlertType +import com.unciv.logic.civilization.PopupAlert +import com.unciv.models.gamebasics.Nation +import com.unciv.models.gamebasics.tr +import com.unciv.ui.utils.addSeparator +import com.unciv.ui.utils.onClick +import com.unciv.ui.utils.toLabel +import com.unciv.ui.worldscreen.optionstable.PopupTable + +class AlertPopup(val worldScreen: WorldScreen, val popupAlert: PopupAlert): PopupTable(worldScreen){ + fun getCloseButton(text:String): TextButton { + val button = TextButton(text.tr(), skin) + button.onClick { close() } + return button + } + + fun addLeaderName(translatedNation: Nation){ + val otherCivLeaderName = "[${translatedNation.leaderName}] of [${translatedNation.getNameTranslation()}]".tr() + add(otherCivLeaderName.toLabel()) + addSeparator() + } + + init { + + when(popupAlert.type){ + AlertType.WarDeclaration -> { + val translatedNation = worldScreen.gameInfo.getCivilization(popupAlert.value).getTranslatedNation() + addLeaderName(translatedNation) + addGoodSizedLabel(translatedNation.declaringWar).row() + val responseTable = Table() + responseTable.add(getCloseButton("You'll pay for this!")) + responseTable.add(getCloseButton("Very well.")) + add(responseTable) + } + AlertType.Defeated -> { + val translatedNation = worldScreen.gameInfo.getCivilization(popupAlert.value).getTranslatedNation() + addLeaderName(translatedNation) + addGoodSizedLabel(translatedNation.defeated).row() + add(getCloseButton("Farewell.")) + } + AlertType.FirstContact -> { + val translatedNation = worldScreen.gameInfo.getCivilization(popupAlert.value).getTranslatedNation() + addLeaderName(translatedNation) + addGoodSizedLabel(translatedNation.introduction).row() + add(getCloseButton("A pleasure to meet you.")) + } + AlertType.CityConquered -> { + addGoodSizedLabel("What would you like to do with the city?").row() + add(getCloseButton("Annex")).row() + add(TextButton("Raze", skin).onClick { + worldScreen.currentPlayerCiv.cities.first { it.name==popupAlert.value }.isBeingRazed=true + worldScreen.shouldUpdate=true + close() + }) + } + } + open() + isOpen = true + } + + fun close(){ + worldScreen.currentPlayerCiv.popupAlerts.remove(popupAlert) + isOpen = false + remove() + } + + companion object { + var isOpen = false + } +} \ No newline at end of file diff --git a/core/src/com/unciv/ui/worldscreen/TradePopup.kt b/core/src/com/unciv/ui/worldscreen/TradePopup.kt new file mode 100644 index 0000000000..e880b7d033 --- /dev/null +++ b/core/src/com/unciv/ui/worldscreen/TradePopup.kt @@ -0,0 +1,74 @@ +package com.unciv.ui.worldscreen + +import com.badlogic.gdx.scenes.scene2d.ui.Table +import com.unciv.logic.trade.TradeLogic +import com.unciv.models.gamebasics.tr +import com.unciv.ui.trade.DiplomacyScreen +import com.unciv.ui.utils.addSeparator +import com.unciv.ui.utils.toLabel +import com.unciv.ui.worldscreen.optionstable.PopupTable +import kotlin.math.max + +class TradePopup(worldScreen: WorldScreen): PopupTable(worldScreen){ + init{ + val currentPlayerCiv = worldScreen.currentPlayerCiv + val tradeRequest = currentPlayerCiv.tradeRequests.first() + + val requestingCiv = worldScreen.gameInfo.getCivilization(tradeRequest.requestingCiv) + val translatedNation = requestingCiv.getTranslatedNation() + val otherCivLeaderName = "[${translatedNation.leaderName}] of [${translatedNation.getNameTranslation()}]".tr() + + add(otherCivLeaderName.toLabel()) + addSeparator() + + val trade = tradeRequest.trade + val tradeOffersTable = Table().apply { defaults().pad(10f) } + for(i in 0..max(trade.theirOffers.lastIndex, trade.ourOffers.lastIndex)){ + if(trade.theirOffers.lastIndex>=i) tradeOffersTable.add(trade.theirOffers[i].getOfferText().toLabel()) + else tradeOffersTable.add() + if(trade.ourOffers.lastIndex>=i) tradeOffersTable.add(trade.ourOffers[i].getOfferText().toLabel()) + else tradeOffersTable.add() + tradeOffersTable.row() + } + add(tradeOffersTable).row() + + addGoodSizedLabel(translatedNation.tradeRequest).colspan(columns).row() + + addButton("Sounds good!".tr()){ + val tradeLogic = TradeLogic(currentPlayerCiv, requestingCiv) + tradeLogic.currentTrade.set(trade) + tradeLogic.acceptTrade() + currentPlayerCiv.tradeRequests.remove(tradeRequest) + remove() + PopupTable(worldScreen).apply { + add(otherCivLeaderName.toLabel()).colspan(2) + addSeparator() + addGoodSizedLabel("Excellent!").row() + addButton("Goodbye."){ + this.remove() + worldScreen.shouldUpdate=true + // in all cases, worldScreen.shouldUpdate should be set to true when we remove the last of the popups + // in order for the next trade to appear immediately + } + open() + } + } + addButton("Not this time.".tr()){ + currentPlayerCiv.tradeRequests.remove(tradeRequest) + remove() + worldScreen.shouldUpdate=true + } + addButton("How about something else...".tr()){ + currentPlayerCiv.tradeRequests.remove(tradeRequest) + remove() + + val diplomacyScreen= DiplomacyScreen() + val tradeTable = diplomacyScreen.setTrade(requestingCiv) + tradeTable.tradeLogic.currentTrade.set(trade) + tradeTable.offerColumnsTable.update() + worldScreen.game.screen=diplomacyScreen + worldScreen.shouldUpdate=true + } + open() + } +} \ No newline at end of file diff --git a/core/src/com/unciv/ui/worldscreen/WorldScreen.kt b/core/src/com/unciv/ui/worldscreen/WorldScreen.kt index 5265f98af2..061fcebd05 100644 --- a/core/src/com/unciv/ui/worldscreen/WorldScreen.kt +++ b/core/src/com/unciv/ui/worldscreen/WorldScreen.kt @@ -8,12 +8,9 @@ import com.badlogic.gdx.scenes.scene2d.ui.Table import com.badlogic.gdx.scenes.scene2d.ui.TextButton import com.unciv.UnCivGame import com.unciv.logic.GameSaver -import com.unciv.logic.civilization.AlertType import com.unciv.logic.civilization.CivilizationInfo -import com.unciv.logic.civilization.PopupAlert import com.unciv.logic.civilization.diplomacy.DiplomaticStatus import com.unciv.models.gamebasics.GameBasics -import com.unciv.models.gamebasics.Nation import com.unciv.models.gamebasics.tile.ResourceType import com.unciv.models.gamebasics.tr import com.unciv.models.gamebasics.unit.UnitType @@ -26,7 +23,6 @@ import com.unciv.ui.trade.DiplomacyScreen import com.unciv.ui.utils.* import com.unciv.ui.worldscreen.bottombar.BattleTable import com.unciv.ui.worldscreen.bottombar.WorldScreenBottomBar -import com.unciv.ui.worldscreen.optionstable.PopupTable import com.unciv.ui.worldscreen.unit.UnitActionsTable class WorldScreen : CameraStageBaseScreen() { @@ -167,13 +163,16 @@ class WorldScreen : CameraStageBaseScreen() { notificationsScroll.setPosition(stage.width - notificationsScroll.width - 5f, nextTurnButton.y - notificationsScroll.height - 5f) - if(!gameInfo.oneMoreTurnMode && currentPlayerCiv.victoryManager.hasWon()) game.screen = VictoryScreen() - else if(currentPlayerCiv.policies.freePolicies>0) game.screen = PolicyPickerScreen(currentPlayerCiv) - else if(currentPlayerCiv.greatPeople.freeGreatPeople>0) game.screen = GreatPersonPickerScreen() - - if(game.screen==this && !tutorials.isTutorialShowing - && currentPlayerCiv.popupAlerts.any() && !AlertPopup.isOpen){ - AlertPopup(this,currentPlayerCiv.popupAlerts.first()) + when { + !gameInfo.oneMoreTurnMode && currentPlayerCiv.victoryManager.hasWon() -> game.screen = VictoryScreen() + currentPlayerCiv.policies.freePolicies>0 -> game.screen = PolicyPickerScreen(currentPlayerCiv) + currentPlayerCiv.greatPeople.freeGreatPeople>0 -> game.screen = GreatPersonPickerScreen() + currentPlayerCiv.tradeRequests.isNotEmpty() ->{ + TradePopup(this) + } + !tutorials.isTutorialShowing + && currentPlayerCiv.popupAlerts.any() && !AlertPopup.isOpen -> + AlertPopup(this,currentPlayerCiv.popupAlerts.first()) } } @@ -222,10 +221,10 @@ class WorldScreen : CameraStageBaseScreen() { } private fun createNextTurnButton(): TextButton { - val nextTurnButton = TextButton("Next turn".tr(), CameraStageBaseScreen.skin) + val nextTurnButton = TextButton("Next turn".tr(), skin) nextTurnButton.onClick { if(currentPlayerCiv.policies.shouldOpenPolicyPicker && !currentPlayerCiv.policies.canAdoptPolicy()) - currentPlayerCiv.policies.shouldOpenPolicyPicker = false // something has chanhed and we can no longer adopt the policy, e.g. we conquered another city + currentPlayerCiv.policies.shouldOpenPolicyPicker = false // something has changed and we can no longer adopt the policy, e.g. we conquered another city if (currentPlayerCiv.tech.freeTechs != 0) { game.screen = TechPickerScreen(true, currentPlayerCiv) @@ -281,7 +280,6 @@ class WorldScreen : CameraStageBaseScreen() { } override fun resize(width: Int, height: Int) { - if (stage.viewport.screenWidth != width || stage.viewport.screenHeight != height) { super.resize(width, height) game.worldScreen = WorldScreen() // start over. @@ -299,95 +297,35 @@ class WorldScreen : CameraStageBaseScreen() { // otherwise images will not load properly! update() - - val shownTutorials = UnCivGame.Current.settings.tutorialsShown - displayTutorials("NextTurn") - if("BarbarianEncountered" !in shownTutorials - && currentPlayerCiv.viewableTiles.any { it.getUnits().any { unit -> unit.civInfo.isBarbarianCivilization() } }) - displayTutorials("BarbarianEncountered") - if(currentPlayerCiv.cities.size > 2) displayTutorials("SecondCity") - if(currentPlayerCiv.happiness < 0) displayTutorials("Unhappiness") - if(currentPlayerCiv.goldenAges.isGoldenAge()) displayTutorials("GoldenAge") - if(gameInfo.turns >= 100) displayTutorials("ContactMe") - val resources = currentPlayerCiv.getCivResources() - if(resources.keys.any { it.resourceType==ResourceType.Luxury }) displayTutorials("LuxuryResource") - if(resources.keys.any { it.resourceType==ResourceType.Strategic}) displayTutorials("StrategicResource") - if("EnemyCity" !in shownTutorials - && currentPlayerCiv.exploredTiles.asSequence().map { gameInfo.tileMap[it] } - .any { it.isCityCenter() && it.getOwner()!=currentPlayerCiv }) - displayTutorials("EnemyCity") - if("Enables construction of Spaceship parts" in currentPlayerCiv.getBuildingUniques()) - displayTutorials("ApolloProgram") - if(currentPlayerCiv.getCivUnits().any { it.type == UnitType.Siege }) - displayTutorials("SiegeUnitTrained") - if(currentPlayerCiv.tech.getUniques().contains("Enables embarkation for land units")) - displayTutorials("CanEmbark") - + showTutorialsOnNextTurn() shouldUpdate=false } super.render(delta) } -} - -class AlertPopup(val worldScreen: WorldScreen, val popupAlert: PopupAlert):PopupTable(worldScreen){ - fun getCloseButton(text:String): TextButton { - val button = TextButton(text.tr(), skin) - button.onClick { close() } - return button + private fun showTutorialsOnNextTurn(){ + val shownTutorials = UnCivGame.Current.settings.tutorialsShown + displayTutorials("NextTurn") + if("BarbarianEncountered" !in shownTutorials + && currentPlayerCiv.viewableTiles.any { it.getUnits().any { unit -> unit.civInfo.isBarbarianCivilization() } }) + displayTutorials("BarbarianEncountered") + if(currentPlayerCiv.cities.size > 2) displayTutorials("SecondCity") + if(currentPlayerCiv.happiness < 0) displayTutorials("Unhappiness") + if(currentPlayerCiv.goldenAges.isGoldenAge()) displayTutorials("GoldenAge") + if(gameInfo.turns >= 100) displayTutorials("ContactMe") + val resources = currentPlayerCiv.getCivResources() + if(resources.keys.any { it.resourceType==ResourceType.Luxury }) displayTutorials("LuxuryResource") + if(resources.keys.any { it.resourceType==ResourceType.Strategic}) displayTutorials("StrategicResource") + if("EnemyCity" !in shownTutorials + && currentPlayerCiv.exploredTiles.asSequence().map { gameInfo.tileMap[it] } + .any { it.isCityCenter() && it.getOwner()!=currentPlayerCiv }) + displayTutorials("EnemyCity") + if("Enables construction of Spaceship parts" in currentPlayerCiv.getBuildingUniques()) + displayTutorials("ApolloProgram") + if(currentPlayerCiv.getCivUnits().any { it.type == UnitType.Siege }) + displayTutorials("SiegeUnitTrained") + if(currentPlayerCiv.tech.getUniques().contains("Enables embarkation for land units")) + displayTutorials("CanEmbark") } - fun addLeaderName(translatedNation:Nation){ - val otherCivLeaderName = "[${translatedNation.leaderName}] of [${translatedNation.getNameTranslation()}]".tr() - add(otherCivLeaderName.toLabel()) - addSeparator() - } - - init { - - when(popupAlert.type){ - AlertType.WarDeclaration -> { - val translatedNation = worldScreen.gameInfo.getCivilization(popupAlert.value).getTranslatedNation() - addLeaderName(translatedNation) - addGoodSizedLabel(translatedNation.declaringWar).row() - val responseTable = Table() - responseTable.add(getCloseButton("You'll pay for this!")) - responseTable.add(getCloseButton("Very well.")) - add(responseTable) - } - AlertType.Defeated -> { - val translatedNation = worldScreen.gameInfo.getCivilization(popupAlert.value).getTranslatedNation() - addLeaderName(translatedNation) - addGoodSizedLabel(translatedNation.defeated).row() - add(getCloseButton("Farewell.")) - } - AlertType.FirstContact -> { - val translatedNation = worldScreen.gameInfo.getCivilization(popupAlert.value).getTranslatedNation() - addLeaderName(translatedNation) - addGoodSizedLabel(translatedNation.introduction).row() - add(getCloseButton("A pleasure to meet you.")) - } - AlertType.CityConquered -> { - addGoodSizedLabel("What would you like to do with the city?").row() - add(getCloseButton("Annex")).row() - add(TextButton("Raze",skin).onClick { - worldScreen.currentPlayerCiv.cities.first { it.name==popupAlert.value }.isBeingRazed=true - worldScreen.shouldUpdate=true - close() - }) - } - } - open() - isOpen = true - } - - fun close(){ - worldScreen.currentPlayerCiv.popupAlerts.remove(popupAlert) - isOpen = false - remove() - } - - companion object { - var isOpen = false - } } \ No newline at end of file diff --git a/core/src/com/unciv/ui/worldscreen/optionstable/PopupTable.kt b/core/src/com/unciv/ui/worldscreen/optionstable/PopupTable.kt index 277662b041..fb9422e5a1 100644 --- a/core/src/com/unciv/ui/worldscreen/optionstable/PopupTable.kt +++ b/core/src/com/unciv/ui/worldscreen/optionstable/PopupTable.kt @@ -32,10 +32,10 @@ open class PopupTable(val screen: CameraStageBaseScreen): Table(CameraStageBaseS return add(label).width(screen.stage.width/2) } - fun addButton(text:String, action:()->Unit){ + fun addButton(text:String, action:()->Unit): Cell { val button = TextButton(text.tr(), skin).apply { color= ImageGetter.getBlue() } button.onClick(action) - add(button).row() + return add(button).apply { row() } } }