From f2333b58394ebd1d29bf7728b028c62e867d98be Mon Sep 17 00:00:00 2001 From: Duan Tao Date: Wed, 1 May 2019 00:33:32 +0800 Subject: [PATCH] Added City states (#681) * Add Milan as 1st city state. Choose box for number of city states. * City states don't get settlers. * Added diplomancy relationship. Now increase by gift and decreases every turn. * Friendly culture city states provides culture bonus. * 0 city states by default. * Disable many trade items for city states. * Fix part 1. * Fix diplomacy screen and pop-ups. * City state doesn't build world wonders. * City states destroy city when conquering. * Fixed : Trying to move into border of uncountered civs caused crash. * City states don't exchange tech or declare war on others. * Fix a very strange problem : you could trade introduction of AI to itself. * City states automatically get all invented techs. * Pops defeat msg before AI founds any city. * Fix conquest victory with city states. * Fixed : AI city under seige change production every turn. --- android/assets/jsons/Nations.json | 63 +++++++++++++++++++ core/src/com/unciv/GameStarter.kt | 12 +++- .../logic/automation/NextTurnAutomation.kt | 12 ++++ core/src/com/unciv/logic/battle/Battle.kt | 7 ++- .../logic/civilization/CivilizationInfo.kt | 18 ++++++ .../logic/civilization/VictoryManager.kt | 2 +- .../diplomacy/DiplomacyManager.kt | 12 +++- core/src/com/unciv/logic/map/MapUnit.kt | 6 +- core/src/com/unciv/logic/trade/TradeLogic.kt | 61 ++++++++++++------ .../com/unciv/models/gamebasics/Building.kt | 3 + .../src/com/unciv/models/gamebasics/Nation.kt | 3 +- .../unciv/models/gamebasics/unit/BaseUnit.kt | 1 + core/src/com/unciv/ui/EmpireOverviewScreen.kt | 6 +- core/src/com/unciv/ui/NewGameScreen.kt | 20 +++++- core/src/com/unciv/ui/VictoryScreen.kt | 2 +- .../src/com/unciv/ui/trade/DiplomacyScreen.kt | 10 ++- 16 files changed, 199 insertions(+), 39 deletions(-) diff --git a/android/assets/jsons/Nations.json b/android/assets/jsons/Nations.json index 6d5e9a38f0..47f0f5a65b 100644 --- a/android/assets/jsons/Nations.json +++ b/android/assets/jsons/Nations.json @@ -1,5 +1,6 @@ [ { + //nations name:"Babylon", leaderName:"Nebuchadnezzar II", adjective:["Babylonian"], @@ -919,6 +920,68 @@ cities:["Moson Kahni","Te-Moak","Agaidika","Goshute","Pohokwi","Washakie","Timbisha","Hukandeka","Duckwater","Tukudeka","Kuchundeka","Yomba","Kamudeka","Ely","Yambadeka","Tetadeka","Deheyaeka","Pengwideka","Winnemucca","Skull Valley","Big Pine","Duck Valley","Nampa","Bannock","Yahandeka"] }, */ + + //City states + { + name:"Milan", + adjective:["Milan"], + cityStateType:"Cultured", + startBias:["Coast"], + + //TO DO : better dialogs + declaringWar:"Declare war.", + attacked:"Let's fight.", + defeated:"GoodBye.", + introduction:"Hi.", + + neutralHello:"Greetings.", + neutralLetsHearIt:["I'm listening.","What do you want?"], + neutralNo:["No!","Certainly not.","Unacceptable!"], + neutralYes:["Completed!","Yes!","Agreed!"], + + hateHello:"What do YOU want?!", + hateLetsHearIt:["I'm certainly listening.","I'm listening!"], + hateNo:["No!","Certainly not!","Unacceptable!"], + hateYes:["Yes!"], + + afterPeace:"Peace then.", + tradeRequest:"Trade?", + + mainColor:[0,100,0], + secondaryColor:[213,249,255], + cities:["Milan"] + }, + { + name:"Florence", + adjective:["Florence"], + cityStateType:"Cultured", + startBias:["Coast"], + + //TO DO : better dialogs + declaringWar:"Declare war.", + attacked:"Let's fight.", + defeated:"GoodBye.", + introduction:"Hi.", + + neutralHello:"Greetings.", + neutralLetsHearIt:["I'm listening.","What do you want?"], + neutralNo:["No!","Certainly not.","Unacceptable!"], + neutralYes:["Completed!","Yes!","Agreed!"], + + hateHello:"What do YOU want?!", + hateLetsHearIt:["I'm certainly listening.","I'm listening!"], + hateNo:["No!","Certainly not!","Unacceptable!"], + hateYes:["Yes!"], + + afterPeace:"Peace then.", + tradeRequest:"Trade?", + + mainColor:[255, 250, 240], + secondaryColor:[238, 44, 44], + cities:["Florence"] + } + + //Barbarian { name:"Barbarians", mainColor:[0,0,0], diff --git a/core/src/com/unciv/GameStarter.kt b/core/src/com/unciv/GameStarter.kt index a07117c383..e8e2d6fdcd 100644 --- a/core/src/com/unciv/GameStarter.kt +++ b/core/src/com/unciv/GameStarter.kt @@ -18,6 +18,7 @@ class GameParameters{ var numberOfHumanPlayers=1 var humanNations=ArrayList().apply { add("Babylon") } var numberOfEnemies=3 + var numberOfCityStates=0 var mapType= MapType.Perlin var noBarbarians=false var mapFileName :String?=null @@ -31,12 +32,15 @@ class GameStarter{ gameInfo.tileMap = TileMap(newGameParameters) gameInfo.tileMap.gameInfo = gameInfo // need to set this transient before placing units in the map val startingLocations = getStartingLocations( - newGameParameters.numberOfEnemies+newGameParameters.numberOfHumanPlayers, gameInfo.tileMap) + newGameParameters.numberOfEnemies+newGameParameters.numberOfHumanPlayers+newGameParameters.numberOfCityStates, + gameInfo.tileMap) val availableCivNames = Stack() - availableCivNames.addAll(GameBasics.Nations.keys.shuffled()) + availableCivNames.addAll(GameBasics.Nations.filter { !it.value.isCityState() }.keys.shuffled()) availableCivNames.removeAll(newGameParameters.humanNations) availableCivNames.remove("Barbarians") + val availableCityStatesNames = Stack() + availableCityStatesNames.addAll(GameBasics.Nations.filter { it.value.isCityState() }.keys.shuffled()) for(nation in newGameParameters.humanNations) { val playerCiv = CivilizationInfo(nation) @@ -53,6 +57,10 @@ class GameStarter{ gameInfo.civilizations.add(civ) } + for (cityStateName in availableCityStatesNames.take(newGameParameters.numberOfCityStates)) { + val civ = CivilizationInfo(cityStateName) + gameInfo.civilizations.add(civ) + } gameInfo.setTransients() // needs to be before placeBarbarianUnit because it depends on the tilemap having its gameinfo set diff --git a/core/src/com/unciv/logic/automation/NextTurnAutomation.kt b/core/src/com/unciv/logic/automation/NextTurnAutomation.kt index e558d2cf44..aecc7e8cc4 100644 --- a/core/src/com/unciv/logic/automation/NextTurnAutomation.kt +++ b/core/src/com/unciv/logic/automation/NextTurnAutomation.kt @@ -44,6 +44,16 @@ class NextTurnAutomation{ private fun exchangeTechs(civInfo: CivilizationInfo) { if(!civInfo.gameInfo.getDifficulty().aisExchangeTechs) return + if (civInfo.isCityState()) { //City states automatically get all invented techs + for (otherCiv in civInfo.getKnownCivs().filterNot { it.isCityState() }) { + for (entry in otherCiv.tech.techsResearched + .filterNot { civInfo.tech.isResearched(it) } + .filter { civInfo.tech.canBeResearched(it) }) { + civInfo.tech.addTechnology(entry) + } + } + return + } val otherCivList = civInfo.getKnownCivs() .filter { it.playerType == PlayerType.AI && !it.isBarbarianCivilization() } @@ -227,6 +237,7 @@ class NextTurnAutomation{ } private fun declareWar(civInfo: CivilizationInfo) { + if (civInfo.isCityState()) return if (civInfo.cities.isNotEmpty() && civInfo.diplomacy.isNotEmpty()) { val ourMilitaryUnits = civInfo.getCivUnits().filter { !it.type.isCivilian() }.size if (!civInfo.isAtWar() && civInfo.happiness > 0 @@ -295,6 +306,7 @@ class NextTurnAutomation{ } private fun trainSettler(civInfo: CivilizationInfo) { + if(civInfo.isCityState()) return if(civInfo.isAtWar()) return // don't train settlers when you could be training troops. if (civInfo.cities.any() && civInfo.happiness > civInfo.cities.size + 5 diff --git a/core/src/com/unciv/logic/battle/Battle.kt b/core/src/com/unciv/logic/battle/Battle.kt index d8c8c4d431..99dc22ab57 100644 --- a/core/src/com/unciv/logic/battle/Battle.kt +++ b/core/src/com/unciv/logic/battle/Battle.kt @@ -169,7 +169,7 @@ class Battle(val gameInfo:GameInfo) { if(civilianUnit!=null) captureCivilianUnit(attacker,MapUnitCombatant(civilianUnit!!)) } - if (attacker.getCivInfo().isBarbarianCivilization()){ + if (attacker.getCivInfo().isBarbarianCivilization() || attacker.getCivInfo().isCityState()){ city.destroyCity() } else { @@ -219,7 +219,10 @@ class Battle(val gameInfo:GameInfo) { defender.takeDamage(100) return } // barbarians don't capture civilians! - + if (attacker.getCivInfo().isCityState() && defender.getName() == "Settler") { + defender.takeDamage(100) + return + } if (defender.getCivInfo().isDefeated()) {//Last settler captured defender.getCivInfo().destroy() attacker.getCivInfo().popupAlerts.add(PopupAlert(AlertType.Defeated,defender.getCivInfo().civName)) diff --git a/core/src/com/unciv/logic/civilization/CivilizationInfo.kt b/core/src/com/unciv/logic/civilization/CivilizationInfo.kt index 3cac2b5e14..7a8d4a1359 100644 --- a/core/src/com/unciv/logic/civilization/CivilizationInfo.kt +++ b/core/src/com/unciv/logic/civilization/CivilizationInfo.kt @@ -21,6 +21,7 @@ import com.unciv.models.gamebasics.tech.TechEra import com.unciv.models.gamebasics.tile.ResourceType import com.unciv.models.gamebasics.tile.TileResource import com.unciv.models.gamebasics.tr +import com.unciv.models.stats.Stat import com.unciv.models.stats.Stats import java.util.* import kotlin.collections.ArrayList @@ -57,6 +58,7 @@ class CivilizationInfo { @Deprecated("As of 2.11.1") var difficulty = "Chieftain" var playerType = PlayerType.AI var civName = "" + var cityStateType = "" var tech = TechManager() var policies = PolicyManager() var goldenAges = GoldenAgeManager() @@ -80,6 +82,7 @@ class CivilizationInfo { constructor(civName: String) { this.civName = civName tech.techsResearched.add("Agriculture") // can't be .addTechnology because the civInfo isn't assigned yet + cityStateType = GameBasics.Nations[civName]!!.cityStateType } fun clone(): CivilizationInfo { @@ -98,6 +101,7 @@ class CivilizationInfo { toReturn.exploredTiles.addAll(exploredTiles) toReturn.notifications.addAll(notifications) toReturn.citiesCreated = citiesCreated + toReturn.cityStateType = cityStateType return toReturn } @@ -118,6 +122,7 @@ class CivilizationInfo { return translatedNation } + fun isCityState(): Boolean = (cityStateType != "") fun getDiplomacyManager(civInfo: CivilizationInfo) = diplomacy[civInfo.civName]!! fun getKnownCivs() = diplomacy.values.map { it.otherCiv() } @@ -137,6 +142,19 @@ class CivilizationInfo { } } + //City states culture bonus + for (otherCivName in diplomacy.keys) { + val otherCiv = gameInfo.getCivilization(otherCivName) + if (otherCiv.isCityState() && otherCiv.diplomacy[civName]!!.attitude > 60) { + var cultureBonus = Stats() + cultureBonus.add(Stat.Culture, 5.0f * getEra().ordinal) + if (statMap.containsKey("City States")) + statMap["City States"] = statMap["City States"]!! + cultureBonus + else + statMap["City States"] = cultureBonus + } + } + for (entry in getHappinessForNextTurn()) { if (!statMap.containsKey(entry.key)) statMap[entry.key] = Stats() diff --git a/core/src/com/unciv/logic/civilization/VictoryManager.kt b/core/src/com/unciv/logic/civilization/VictoryManager.kt index a1d3af53c0..dc6fb92d3c 100644 --- a/core/src/com/unciv/logic/civilization/VictoryManager.kt +++ b/core/src/com/unciv/logic/civilization/VictoryManager.kt @@ -31,7 +31,7 @@ class VictoryManager { fun hasWonCulturalVictory() = civInfo.policies.adoptedPolicies.count{it.endsWith("Complete")} > 3 - fun hasWonConquestVictory() = civInfo.gameInfo.civilizations.all { it==civInfo || it.isDefeated() } + fun hasWonConquestVictory() = civInfo.gameInfo.civilizations.all { it==civInfo || it.isDefeated() || it.isCityState() } fun hasWon() = hasWonConquestVictory() || hasWonCulturalVictory() || hasWonScientificVictory() } diff --git a/core/src/com/unciv/logic/civilization/diplomacy/DiplomacyManager.kt b/core/src/com/unciv/logic/civilization/diplomacy/DiplomacyManager.kt index cf85e75687..8b0e26d494 100644 --- a/core/src/com/unciv/logic/civilization/diplomacy/DiplomacyManager.kt +++ b/core/src/com/unciv/logic/civilization/diplomacy/DiplomacyManager.kt @@ -28,12 +28,14 @@ class DiplomacyManager() { * The JSON serialize/deserialize REFUSES to deserialize hashmap keys as Enums, so I'm forced to use strings instead =( * This is so sad Alexa play Despacito */ var flagsCountdown = HashMap() + var attitude: Float = 0f //positive means our civ is friendly to the other civ fun clone(): DiplomacyManager { val toReturn = DiplomacyManager() toReturn.otherCivName=otherCivName toReturn.diplomaticStatus=diplomaticStatus toReturn.trades.addAll(trades.map { it.clone() }) + toReturn.attitude = attitude toReturn.flagsCountdown.putAll(flagsCountdown) toReturn.hasOpenBorders=hasOpenBorders return toReturn @@ -143,6 +145,14 @@ class DiplomacyManager() { if(flagsCountdown[flag]==0) flagsCountdown.remove(flag) } + if (attitude > 1f) { + attitude -= 1f + } else if (attitude < -1f) { + attitude += 1f + } else { + attitude = 0f + } + } fun declareWar(){ @@ -173,4 +183,4 @@ class DiplomacyManager() { otherCiv.getDiplomacyManager(civInfo).flagsCountdown[DiplomacyFlags.DeclinedPeace.toString()]=10 } //endregion -} \ No newline at end of file +} diff --git a/core/src/com/unciv/logic/map/MapUnit.kt b/core/src/com/unciv/logic/map/MapUnit.kt index 2a15f004f1..aba649ab0d 100644 --- a/core/src/com/unciv/logic/map/MapUnit.kt +++ b/core/src/com/unciv/logic/map/MapUnit.kt @@ -438,8 +438,10 @@ class MapUnit { actions.add { val chosenUnit = listOf("Settler","Worker","Warrior").random() - civInfo.placeUnitNearTile(currentTile.position,chosenUnit) - civInfo.addNotification("A [$chosenUnit] has joined us!",currentTile.position, Color.BROWN) + if (!civInfo.isCityState() || chosenUnit != "Settler") { //City states don't get settler from ruins + civInfo.placeUnitNearTile(currentTile.position, chosenUnit) + civInfo.addNotification("A [$chosenUnit] has joined us!", currentTile.position, Color.BROWN) + } } if(!type.isCivilian()) diff --git a/core/src/com/unciv/logic/trade/TradeLogic.kt b/core/src/com/unciv/logic/trade/TradeLogic.kt index 28c55ece15..2ccb1b3fac 100644 --- a/core/src/com/unciv/logic/trade/TradeLogic.kt +++ b/core/src/com/unciv/logic/trade/TradeLogic.kt @@ -14,10 +14,12 @@ class TradeLogic(val ourCivilization:CivilizationInfo, val otherCivilization: Ci fun getAvailableOffers(civInfo: CivilizationInfo, otherCivilization: CivilizationInfo): TradeOffersList { val offers = TradeOffersList() + if (civInfo.isCityState() && otherCivilization.isCityState()) return offers if(civInfo.isAtWarWith(otherCivilization)) offers.add(TradeOffer("Peace Treaty", TradeType.Treaty, 20)) if(!otherCivilization.getDiplomacyManager(civInfo).hasOpenBorders + && !otherCivilization.isCityState() && civInfo.tech.getTechUniques().contains("Enables Open Borders agreements") && otherCivilization.tech.getTechUniques().contains("Enables Open Borders agreements")) offers.add(TradeOffer("Open Borders", TradeType.Agreement, 30)) @@ -27,30 +29,40 @@ class TradeLogic(val ourCivilization:CivilizationInfo, val otherCivilization: Ci else TradeType.Strategic_Resource offers.add(TradeOffer(entry.key.name, resourceTradeType, 30, entry.value)) } - for(entry in civInfo.tech.techsResearched - .filterNot { otherCivilization.tech.isResearched(it) } - .filter { otherCivilization.tech.canBeResearched(it) }){ - offers.add(TradeOffer(entry, TradeType.Technology, 0)) + if (!civInfo.isCityState() && !otherCivilization.isCityState()) { + for (entry in civInfo.tech.techsResearched + .filterNot { otherCivilization.tech.isResearched(it) } + .filter { otherCivilization.tech.canBeResearched(it) }) { + offers.add(TradeOffer(entry, TradeType.Technology, 0)) + } } + offers.add(TradeOffer("Gold".tr(), TradeType.Gold, 0, civInfo.gold)) offers.add(TradeOffer("Gold per turn".tr(), TradeType.Gold_Per_Turn, 30, civInfo.getStatsForNextTurn().gold.toInt())) - for(city in civInfo.cities.filterNot { it.isCapital() }) - offers.add(TradeOffer(city.name, TradeType.City, 0)) - - val otherCivsWeKnow = civInfo.getKnownCivs() - .filter { it != otherCivilization && !it.isBarbarianCivilization() && !it.isDefeated() } - val civsWeKnowAndTheyDont = otherCivsWeKnow - .filter { !otherCivilization.diplomacy.containsKey(it.civName) && !it.isDefeated() } - for(thirdCiv in civsWeKnowAndTheyDont){ - offers.add(TradeOffer("Introduction to " + thirdCiv.civName, TradeType.Introduction, 0)) + if (!civInfo.isCityState() && !otherCivilization.isCityState()) { + for (city in civInfo.cities.filterNot { it.isCapital() }) + offers.add(TradeOffer(city.name, TradeType.City, 0)) } - val civsWeBothKnow = otherCivsWeKnow - .filter { otherCivilization.diplomacy.containsKey(it.civName) } - val civsWeArentAtWarWith = civsWeBothKnow - .filter { civInfo.getDiplomacyManager(it).diplomaticStatus== DiplomaticStatus.Peace } - for(thirdCiv in civsWeArentAtWarWith){ - offers.add(TradeOffer("Declare war on "+thirdCiv.civName,TradeType.WarDeclaration,0)) + val otherCivsWeKnow = civInfo.getKnownCivs() + .filter { it.civName != otherCivilization.civName && !it.isBarbarianCivilization() && !it.isDefeated() } + val civsWeKnowAndTheyDont = otherCivsWeKnow + .filter { !otherCivilization.diplomacy.containsKey(it.civName) && !it.isDefeated() } + + if (!otherCivilization.isCityState()) { + for (thirdCiv in civsWeKnowAndTheyDont) { + offers.add(TradeOffer("Introduction to " + thirdCiv.civName, TradeType.Introduction, 0)) + } + } + + if (!civInfo.isCityState() && !otherCivilization.isCityState()) { + val civsWeBothKnow = otherCivsWeKnow + .filter { otherCivilization.diplomacy.containsKey(it.civName) } + val civsWeArentAtWarWith = civsWeBothKnow + .filter { civInfo.getDiplomacyManager(it).diplomaticStatus == DiplomaticStatus.Peace } + for (thirdCiv in civsWeArentAtWarWith) { + offers.add(TradeOffer("Declare war on " + thirdCiv.civName, TradeType.WarDeclaration, 0)) + } } return offers @@ -103,6 +115,17 @@ class TradeLogic(val ourCivilization:CivilizationInfo, val otherCivilization: Ci transferTrade(ourCivilization,otherCivilization,currentTrade) transferTrade(otherCivilization,ourCivilization,currentTrade.reverse()) + //Buy friendship with gold. + if (currentTrade.theirOffers.isEmpty()) { + for (trade in currentTrade.ourOffers) { + if (trade.type == TradeType.Gold) { + otherCivilization.getDiplomacyManager(ourCivilization).attitude += trade.amount / 10 + } + if (trade.type == TradeType.Gold_Per_Turn) { + otherCivilization.getDiplomacyManager(ourCivilization).attitude += trade.amount * trade.duration / 10 + } + } + } } } diff --git a/core/src/com/unciv/models/gamebasics/Building.kt b/core/src/com/unciv/models/gamebasics/Building.kt index 0cdee62508..8a36d368aa 100644 --- a/core/src/com/unciv/models/gamebasics/Building.kt +++ b/core/src/com/unciv/models/gamebasics/Building.kt @@ -208,6 +208,9 @@ class Building : NamedStats(), IConstruction{ if(civInfo.cities.any { it!=construction.cityInfo && it.cityConstructions.isBeingConstructed(name) }) return "Wonder is being built elsewhere" + + if(civInfo.isCityState()) + return "No world wonders for city state" } diff --git a/core/src/com/unciv/models/gamebasics/Nation.kt b/core/src/com/unciv/models/gamebasics/Nation.kt index 29e1a62b47..c19a390af8 100644 --- a/core/src/com/unciv/models/gamebasics/Nation.kt +++ b/core/src/com/unciv/models/gamebasics/Nation.kt @@ -13,7 +13,7 @@ class Nation : INamed { } var leaderName="" - + var cityStateType="" var declaringWar="" var attacked="" var defeated="" @@ -34,5 +34,6 @@ class Nation : INamed { if(secondaryColor==null) return Color.BLACK return colorFromRGB(secondaryColor!![0], secondaryColor!![1], secondaryColor!![2]) } + fun isCityState(): Boolean = (cityStateType != "") lateinit var cities: List } diff --git a/core/src/com/unciv/models/gamebasics/unit/BaseUnit.kt b/core/src/com/unciv/models/gamebasics/unit/BaseUnit.kt index 2fa8d9d8c7..c47e53d125 100644 --- a/core/src/com/unciv/models/gamebasics/unit/BaseUnit.kt +++ b/core/src/com/unciv/models/gamebasics/unit/BaseUnit.kt @@ -131,6 +131,7 @@ class BaseUnit : INamed, IConstruction, ICivilopedia { if (uniqueTo!=null && uniqueTo!=civInfo.civName) return "Unique to $uniqueTo" if (GameBasics.Units.values.any { it.uniqueTo==civInfo.civName && it.replaces==name }) return "Our unique unit replaces this" if (requiredResource!=null && !civInfo.hasResource(requiredResource!!)) return "Requires $requiredResource" + if (name == "Settler" && civInfo.isCityState()) return "No settler for city state" return "" } diff --git a/core/src/com/unciv/ui/EmpireOverviewScreen.kt b/core/src/com/unciv/ui/EmpireOverviewScreen.kt index 356b8fc5d9..c6c641d0d9 100644 --- a/core/src/com/unciv/ui/EmpireOverviewScreen.kt +++ b/core/src/com/unciv/ui/EmpireOverviewScreen.kt @@ -289,15 +289,13 @@ class EmpireOverviewScreen : CameraStageBaseScreen(){ currentPlayerCivInfo.diplomacy.containsKey(civ.civName) fun createDiplomacyGroup(): Group { - val relevantCivs = currentPlayerCivInfo.gameInfo.civilizations.filter { !it.isBarbarianCivilization() } + val relevantCivs = currentPlayerCivInfo.gameInfo.civilizations.filter { !it.isBarbarianCivilization() && !it.isCityState() } val groupSize = 500f val group = Group() group.setSize(groupSize,groupSize) val civGroups = HashMap() for(i in 0..relevantCivs.lastIndex){ val civ = relevantCivs[i] - - val civGroup = Table() val civGroupBackground = ImageGetter.getDrawable("OtherIcons/civTableBackground.png") @@ -328,7 +326,6 @@ class EmpireOverviewScreen : CameraStageBaseScreen(){ group.addActor(civGroup) } - for(civ in relevantCivs.filter { playerKnows(it) && !it.isDefeated() }) for(diplomacy in civ.diplomacy.values.filter { !it.otherCiv().isBarbarianCivilization() && playerKnows(it.otherCiv()) && !it.otherCiv().isDefeated()}){ val civGroup = civGroups[civ.civName]!! @@ -344,7 +341,6 @@ class EmpireOverviewScreen : CameraStageBaseScreen(){ statusLine.toBack() } - return group } } \ No newline at end of file diff --git a/core/src/com/unciv/ui/NewGameScreen.kt b/core/src/com/unciv/ui/NewGameScreen.kt index 38c66335e1..72205b86f0 100644 --- a/core/src/com/unciv/ui/NewGameScreen.kt +++ b/core/src/com/unciv/ui/NewGameScreen.kt @@ -35,7 +35,7 @@ class NewGameScreen: PickerScreen(){ val mainTable = Table() mainTable.add(getOptionsTable()) - for(nation in GameBasics.Nations.values.filterNot { it.name == "Barbarians" }){ + for(nation in GameBasics.Nations.values.filterNot { it.name == "Barbarians" || it.isCityState() }){ val nationTable = NationTable(nation,newGameParameters,skin,stage.width/3 ){updateNationTables()} nationTables.add(nationTable) civPickerTable.add(nationTable).row() @@ -162,7 +162,7 @@ class NewGameScreen: PickerScreen(){ newGameOptionsTable.add("{Number of human players}:".tr()) val humanPlayers = SelectBox(skin) val humanPlayersArray = Array() - (1..GameBasics.Nations.size).forEach { humanPlayersArray.add(it) } + (1..GameBasics.Nations.filter{ !it.value.isCityState() }.size).forEach { humanPlayersArray.add(it) } humanPlayers.items = humanPlayersArray humanPlayers.selected = newGameParameters.numberOfHumanPlayers newGameOptionsTable.add(humanPlayers).pad(10f).row() @@ -171,11 +171,19 @@ class NewGameScreen: PickerScreen(){ newGameOptionsTable.add("{Number of enemies}:".tr()) val enemiesSelectBox = SelectBox(skin) val enemiesArray = Array() - (0..GameBasics.Nations.size - 1).forEach { enemiesArray.add(it) } + (0..GameBasics.Nations.filter{ !it.value.isCityState() }.size - 1).forEach { enemiesArray.add(it) } enemiesSelectBox.items = enemiesArray enemiesSelectBox.selected = newGameParameters.numberOfEnemies newGameOptionsTable.add(enemiesSelectBox).pad(10f).row() + newGameOptionsTable.add("{Number of city states}:".tr()) + val cityStatesSelectBox = SelectBox(skin) + val cityStatesArray = Array() + (0..GameBasics.Nations.filter{ it.value.isCityState() }.size).forEach { cityStatesArray.add(it) } + cityStatesSelectBox.items = cityStatesArray + cityStatesSelectBox.selected = newGameParameters.numberOfCityStates + newGameOptionsTable.add(cityStatesSelectBox).pad(10f).row() + humanPlayers.addListener(object : ChangeListener() { override fun changed(event: ChangeEvent?, actor: Actor?) { newGameParameters.numberOfHumanPlayers = humanPlayers.selected @@ -193,6 +201,12 @@ class NewGameScreen: PickerScreen(){ removeExtraHumanNations(humanPlayers) } }) + + cityStatesSelectBox.addListener(object : ChangeListener() { + override fun changed(event: ChangeEvent?, actor: Actor?) { + newGameParameters.numberOfCityStates = cityStatesSelectBox.selected + } + }) } private fun addDifficultySelectBox(newGameOptionsTable: Table) { diff --git a/core/src/com/unciv/ui/VictoryScreen.kt b/core/src/com/unciv/ui/VictoryScreen.kt index 5e3042c0fe..da9e33d994 100644 --- a/core/src/com/unciv/ui/VictoryScreen.kt +++ b/core/src/com/unciv/ui/VictoryScreen.kt @@ -87,7 +87,7 @@ class VictoryScreen : PickerScreen() { val table=Table() table.defaults().pad(5f) for (civ in playerCivInfo.gameInfo.civilizations) { - if (civ.isPlayerCivilization() || civ.isBarbarianCivilization()) continue + if (civ.isPlayerCivilization() || civ.isBarbarianCivilization() || civ.isCityState()) continue val civName = if (playerCivInfo.diplomacy.containsKey(civ.civName)) civ.civName else "???" diff --git a/core/src/com/unciv/ui/trade/DiplomacyScreen.kt b/core/src/com/unciv/ui/trade/DiplomacyScreen.kt index 4f7642b43d..8122414717 100644 --- a/core/src/com/unciv/ui/trade/DiplomacyScreen.kt +++ b/core/src/com/unciv/ui/trade/DiplomacyScreen.kt @@ -68,9 +68,16 @@ class DiplomacyScreen:CameraStageBaseScreen() { } private fun getDiplomacyTable(civ: CivilizationInfo): Table { + val currentPlayerCiv = UnCivGame.Current.gameInfo.getCurrentPlayerCivilization() val diplomacyTable = Table() diplomacyTable.defaults().pad(10f) - val leaderName = "[" + civ.getNation().leaderName + "] of [" + civ.civName + "]" + var leaderName: String + if (civ.isCityState()) { + leaderName = "City State [" + civ.civName + "]" + } else { + leaderName = "[" + civ.getNation().leaderName + "] of [" + civ.civName + "]" + } + leaderName = leaderName + " : Attitude " + civ.getDiplomacyManager(currentPlayerCiv).attitude.toInt().toString() diplomacyTable.add(leaderName.toLabel()) diplomacyTable.addSeparator() @@ -78,7 +85,6 @@ class DiplomacyScreen:CameraStageBaseScreen() { tradeButton.onClick { setTrade(civ) } diplomacyTable.add(tradeButton).row() - val currentPlayerCiv = UnCivGame.Current.gameInfo.getCurrentPlayerCivilization() val civDiplomacy = currentPlayerCiv.getDiplomacyManager(civ) if (!currentPlayerCiv.isAtWarWith(civ)) {