AI can now offer you trades - this is a big step towards proper diplomacy relations!

As of now they only offer luxury-to-luxury trades
This commit is contained in:
Yair Morgenstern 2019-04-23 17:07:01 +03:00
parent 046fe1088f
commit 5d8d7ca89b
14 changed files with 314 additions and 157 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 968 KiB

After

Width:  |  Height:  |  Size: 966 KiB

View file

@ -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

View file

@ -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<Trade> {
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<Trade>()
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 {

View file

@ -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<MapUnit>()
@Transient var viewableTiles = HashSet<TileInfo>()
@Transient var viewableInvisibleUnitsTiles = HashSet<TileInfo>()
@Transient private var units=listOf<MapUnit>()
@Transient var viewableTiles = setOf<TileInfo>()
@Transient var viewableInvisibleUnitsTiles = setOf<TileInfo>()
// 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<String, DiplomacyManager>()
var notifications = ArrayList<Notification>()
val popupAlerts = ArrayList<PopupAlert>()
val tradeRequests = ArrayList<TradeRequest>()
// 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<String, Stats> {
val statMap = HashMap<String,Stats>()

View file

@ -16,6 +16,8 @@ class DiplomacyManager() {
lateinit var otherCivName:String
var trades = ArrayList<Trade>()
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<String,Int>()
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(){

View file

@ -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)
}
}

View file

@ -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)
}
}

View file

@ -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<String>()
var neutralYes = ArrayList<String>()

View file

@ -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()

View file

@ -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<TradeType, ExpanderTab>()
@ -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

View file

@ -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
}
}

View file

@ -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()
}
}

View file

@ -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
}
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
}
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")
}
}

View file

@ -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<TextButton> {
val button = TextButton(text.tr(), skin).apply { color= ImageGetter.getBlue() }
button.onClick(action)
add(button).row()
return add(button).apply { row() }
}
}