diff --git a/core/src/com/unciv/logic/city/CityStats.kt b/core/src/com/unciv/logic/city/CityStats.kt index 51884f43b2..0153683bf1 100644 --- a/core/src/com/unciv/logic/city/CityStats.kt +++ b/core/src/com/unciv/logic/city/CityStats.kt @@ -96,9 +96,9 @@ class CityStats { // needs to be a separate function because we need to know the global happiness state // in order to determine how much food is produced in a city! // -3 happiness per city - fun getCityHappiness(): Float { + fun getCityHappiness(): LinkedHashMap { + happinessList["Cities"] = -3f val civInfo = cityInfo.civInfo - var happiness = -3f var unhappinessFromCitizens = cityInfo.population.population.toFloat() if (civInfo.policies.isAdopted("Democracy")) unhappinessFromCitizens -= cityInfo.population.getNumberOfSpecialists() * 0.5f @@ -108,7 +108,6 @@ class CityStats { unhappinessFromCitizens *= 0.95f happinessList["Population"]=-unhappinessFromCitizens - happiness -= unhappinessFromCitizens var happinessFromPolicies = 0f if (civInfo.policies.isAdopted("Aristocracy")) @@ -119,13 +118,11 @@ class CityStats { happinessFromPolicies += 1f happinessList["Policies"] = happinessFromPolicies - happiness += happinessFromPolicies val happinessFromBuildings = cityInfo.cityConstructions.getStats().happiness.toInt().toFloat() happinessList["Buildings"] =happinessFromBuildings - happiness += happinessFromBuildings - return happiness + return happinessList } private fun getStatsFromSpecialists(specialists: Stats, policies: HashSet): Stats { diff --git a/core/src/com/unciv/logic/civilization/CivilizationInfo.kt b/core/src/com/unciv/logic/civilization/CivilizationInfo.kt index 6da4bb47d8..fd21d9a0ab 100644 --- a/core/src/com/unciv/logic/civilization/CivilizationInfo.kt +++ b/core/src/com/unciv/logic/civilization/CivilizationInfo.kt @@ -7,12 +7,12 @@ import com.unciv.logic.city.CityInfo import com.unciv.logic.map.MapUnit import com.unciv.logic.map.RoadStatus import com.unciv.logic.map.TileInfo +import com.unciv.models.Counter import com.unciv.models.gamebasics.Civilization import com.unciv.models.gamebasics.GameBasics 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.Counter import com.unciv.models.stats.Stats import com.unciv.ui.utils.getRandom import kotlin.math.max @@ -46,27 +46,41 @@ class CivilizationInfo { // negative gold hurts science - fun getStatsForNextTurn(): Stats { - val statsForTurn = Stats() - for (city in cities) statsForTurn.add(city.cityStats.currentCityStats) - statsForTurn.happiness = getHappinessForNextTurn().toFloat() + fun getStatsForNextTurn(): HashMap { + val statMap = HashMap() + for (city in cities){ + for(entry in city.cityStats.baseStatList){ + if(statMap.containsKey(entry.key)) + statMap[entry.key] = statMap[entry.key]!! + entry.value + else statMap[entry.key] = entry.value + } + } - val transportationUpkeep = getTransportationUpkeep() - statsForTurn.gold -= transportationUpkeep + for (entry in getHappinessForNextTurn()) { + if (!statMap.containsKey(entry.key)) + statMap[entry.key] = Stats() + statMap[entry.key]!!.happiness += entry.value + } - val unitUpkeep = getUnitUpkeep() - statsForTurn.gold -= unitUpkeep + statMap.put("Transportation upkeep",Stats().apply { gold=- getTransportationUpkeep().toFloat()}) + statMap.put("Unit upkeep",Stats().apply { gold=- getUnitUpkeep().toFloat()}) if (policies.isAdopted("Mandate Of Heaven")) - statsForTurn.culture += statsForTurn.happiness / 2 - if (statsForTurn.gold < 0) statsForTurn.science += statsForTurn.gold + if (!statMap.containsKey("Policies")) + statMap["Policies"] = Stats() + statMap["Policies"]!!.culture += statMap.values.map { it.happiness }.sum()/ 2 + // if we have - or 0, then the techs will never be complete and the tech button // will show a negative number of turns and int.max, respectively - if(statsForTurn.science<1) statsForTurn.science=1f + if (statMap.values.map { it.gold }.sum() < 0) { + val scienceDeficit = max(statMap.values.map { it.gold }.sum(), + 1 - statMap.values.map { it.science }.sum())// Leave at least 1 + statMap["Treasury deficit"] = Stats().apply { science = scienceDeficit } + } - return statsForTurn + return statMap } private fun getUnitUpkeep(): Int { @@ -94,16 +108,27 @@ class CivilizationInfo { } // base happiness - fun getHappinessForNextTurn(): Int { - var happiness = 15 + fun getHappinessForNextTurn(): HashMap { + val statMap = HashMap() + statMap["Base happiness"] = 15 + var happinessPerUniqueLuxury = 5 if (policies.isAdopted("Protectionism")) happinessPerUniqueLuxury += 1 - happiness += getCivResources().keys + statMap["Luxury resources"]= getCivResources().keys .count { it.resourceType === ResourceType.Luxury } * happinessPerUniqueLuxury - happiness += cities.sumBy { it.cityStats.getCityHappiness().toInt() } + + for(city in cities){ + for(keyvalue in city.cityStats.getCityHappiness()){ + if(statMap.containsKey(keyvalue.key)) + statMap[keyvalue.key] = statMap[keyvalue.key]!!+keyvalue.value.toInt() + else statMap[keyvalue.key] = keyvalue.value.toInt() + } + } + if (buildingUniques.contains("Provides 1 happiness per social policy")) - happiness += policies.getAdoptedPolicies().count { !it.endsWith("Complete") } - return happiness + statMap["Policies"] = policies.getAdoptedPolicies().count { !it.endsWith("Complete") } + + return statMap } fun getCivResources(): Counter { @@ -143,14 +168,15 @@ class CivilizationInfo { } } - fun addCity(location: Vector2) { val newCity = CityInfo(this, location) newCity.cityConstructions.chooseNextConstruction() } fun endTurn() { - val nextTurnStats = getStatsForNextTurn() + val nextTurnStats = Stats() + for(stat in getStatsForNextTurn().values) nextTurnStats.add(stat) + policies.endTurn(nextTurnStats.culture.toInt()) gold += nextTurnStats.gold.toInt() @@ -175,7 +201,7 @@ class CivilizationInfo { getViewableTiles() // adds explored tiles so that the units will be able to perform automated actions better for (city in cities) city.cityStats.update() - happiness = getHappinessForNextTurn() + happiness = getHappinessForNextTurn().values.sum() getCivUnits().forEach { it.startTurn() } } diff --git a/core/src/com/unciv/logic/civilization/TechManager.kt b/core/src/com/unciv/logic/civilization/TechManager.kt index e6f61a2290..f2ce2b273f 100644 --- a/core/src/com/unciv/logic/civilization/TechManager.kt +++ b/core/src/com/unciv/logic/civilization/TechManager.kt @@ -37,7 +37,7 @@ class TechManager { fun turnsToTech(TechName: String): Int { return Math.ceil(((GameBasics.Technologies[TechName]!!.cost - researchOfTech(TechName)) - / civInfo.getStatsForNextTurn().science).toDouble()).toInt() + / civInfo.getStatsForNextTurn().values.sumByDouble { it.science.toDouble()})).toInt() } fun isResearched(TechName: String): Boolean = techsResearched.contains(TechName) diff --git a/core/src/com/unciv/models/stats/Stats.kt b/core/src/com/unciv/models/stats/Stats.kt index 62e1374ec7..b69a6d2d3d 100644 --- a/core/src/com/unciv/models/stats/Stats.kt +++ b/core/src/com/unciv/models/stats/Stats.kt @@ -25,6 +25,7 @@ open class Stats() { happiness += other.happiness } + fun add(stat:Stat, value:Float): Stats { val hashMap = toHashMap() hashMap[stat] = hashMap[stat]!!+value @@ -32,6 +33,12 @@ open class Stats() { return this } + operator fun plus(stat: Stats): Stats { + val clone = clone() + clone.add(stat) + return clone + } + fun clone(): Stats { val stats = Stats() stats.add(this) diff --git a/core/src/com/unciv/ui/LoadScreen.kt b/core/src/com/unciv/ui/LoadScreen.kt index 5a3e4e6d77..d5cf33963b 100644 --- a/core/src/com/unciv/ui/LoadScreen.kt +++ b/core/src/com/unciv/ui/LoadScreen.kt @@ -9,10 +9,12 @@ import com.badlogic.gdx.utils.Json import com.unciv.UnCivGame import com.unciv.logic.GameInfo import com.unciv.logic.GameSaver +import com.unciv.logic.civilization.CivilizationInfo import com.unciv.ui.pickerscreens.PickerScreen import com.unciv.ui.utils.* import java.text.SimpleDateFormat import java.util.* +import kotlin.math.roundToInt class LoadScreen : PickerScreen() { lateinit var selectedSave:String @@ -82,4 +84,89 @@ class LoadScreen : PickerScreen() { } +} + +class EmpireOverviewScreen : CameraStageBaseScreen(){ + init { + val civInfo = UnCivGame.Current.gameInfo.getPlayerCivilization() + + val closeButton =TextButton("Close".tr(),skin) + closeButton.addClickListener { UnCivGame.Current.setWorldScreen() } + closeButton.y = stage.height - closeButton.height - 5 + stage.addActor(closeButton) + + addCityInfoTable(civInfo) + addHappinessTable(civInfo) + addGoldTable(civInfo) + } + + private fun addHappinessTable(civInfo: CivilizationInfo) { + val happinessTable = Table(skin) + happinessTable.defaults().pad(5f) + happinessTable.add(Label("Happiness", skin).setFont(24)).colspan(2).row() + for (entry in civInfo.getHappinessForNextTurn()) { + happinessTable.add(entry.key) + happinessTable.add(entry.value.toString()).row() + } + happinessTable.add("Total") + happinessTable.add(civInfo.getHappinessForNextTurn().values.sum().toString()) + happinessTable.pack() + stage.addActor(happinessTable) + } + + private fun addGoldTable(civInfo: CivilizationInfo) { + val goldTable = Table(skin) + goldTable.defaults().pad(5f) + goldTable.add(Label("Gold", skin).setFont(24)).colspan(2).row() + var total=0f + for (entry in civInfo.getStatsForNextTurn()) { + if(entry.value.gold==0f) continue + goldTable.add(entry.key) + goldTable.add(entry.value.gold.toString()).row() + total += entry.value.gold + } + goldTable.add("Total") + goldTable.add(total.toString()) + goldTable.pack() + goldTable.y = stage.height/2 + stage.addActor(goldTable) + } + + private fun addCityInfoTable(civInfo: CivilizationInfo) { + val cityInfotable = Table() + cityInfotable.skin = skin + cityInfotable.defaults().pad(5f) + cityInfotable.add(Label("Cities", skin).setFont(24)).colspan(8).row() + cityInfotable.add() + cityInfotable.add(ImageGetter.getStatIcon("Population")).size(20f) + cityInfotable.add(ImageGetter.getStatIcon("Food")).size(20f) + cityInfotable.add(ImageGetter.getStatIcon("Gold")).size(20f) + cityInfotable.add(ImageGetter.getStatIcon("Science")).size(20f) + cityInfotable.add(ImageGetter.getStatIcon("Production")).size(20f) + cityInfotable.add(ImageGetter.getStatIcon("Culture")).size(20f) + cityInfotable.add(ImageGetter.getStatIcon("Happiness")).size(20f).row() + + for (city in civInfo.cities) { + cityInfotable.add(city.name) + cityInfotable.add(city.population.population.toString()) + cityInfotable.add(city.cityStats.currentCityStats.food.roundToInt().toString()) + cityInfotable.add(city.cityStats.currentCityStats.gold.roundToInt().toString()) + cityInfotable.add(city.cityStats.currentCityStats.science.roundToInt().toString()) + cityInfotable.add(city.cityStats.currentCityStats.production.roundToInt().toString()) + cityInfotable.add(city.cityStats.currentCityStats.culture.roundToInt().toString()) + cityInfotable.add(city.cityStats.currentCityStats.happiness.roundToInt().toString()).row() + } + cityInfotable.add("Total") + cityInfotable.add(civInfo.cities.sumBy { it.population.population }.toString()) + cityInfotable.add("") + cityInfotable.add(civInfo.cities.sumBy { it.cityStats.currentCityStats.gold.toInt() }.toString()) + cityInfotable.add(civInfo.cities.sumBy { it.cityStats.currentCityStats.science.toInt() }.toString()) + cityInfotable.add("") + cityInfotable.add(civInfo.cities.sumBy { it.cityStats.currentCityStats.culture.toInt() }.toString()) + cityInfotable.add(civInfo.cities.sumBy { it.cityStats.currentCityStats.happiness.toInt() }.toString()) + + cityInfotable.pack() + cityInfotable.setPosition(stage.width / 2, stage.height / 3) + stage.addActor(cityInfotable) + } } \ No newline at end of file diff --git a/core/src/com/unciv/ui/cityscreen/CityStatsTable.kt b/core/src/com/unciv/ui/cityscreen/CityStatsTable.kt index f0e6d1145d..a7a4b95c99 100644 --- a/core/src/com/unciv/ui/cityscreen/CityStatsTable.kt +++ b/core/src/com/unciv/ui/cityscreen/CityStatsTable.kt @@ -30,12 +30,12 @@ class CityStatsTable(val cityScreen: CityScreen) : Table(){ cityStatsValues["Production"] = Math.round(stats.production).toString() + city.cityConstructions.getAmountConstructedText() cityStatsValues["Food"] = (Math.round(stats.food).toString() + " (" + city.population.foodStored + "/" + city.population.getFoodToNextPopulation() + ")") - cityStatsValues["Gold"] = Math.round(stats.gold).toString() + "" - cityStatsValues["Science"] = Math.round(stats.science).toString() + "" + cityStatsValues["Gold"] = Math.round(stats.gold).toString() + cityStatsValues["Science"] = Math.round(stats.science).toString() cityStatsValues["Culture"] = (Math.round(stats.culture).toString() + " (" + city.expansion.cultureStored + "/" + city.expansion.getCultureToNextTile() + ")") cityStatsValues["Population"] = city.population.getFreePopulation().toString() + "/" + city.population.population - cityStatsValues["Happiness"] = city.cityStats.getCityHappiness().toInt().toString() + cityStatsValues["Happiness"] = city.cityStats.getCityHappiness().values.sum().toInt().toString() for (key in cityStatsValues.keys) { add(ImageGetter.getStatIcon(key)).align(Align.right) diff --git a/core/src/com/unciv/ui/worldscreen/WorldScreenTopBar.kt b/core/src/com/unciv/ui/worldscreen/WorldScreenTopBar.kt index 0023ed1f13..76426d0f19 100644 --- a/core/src/com/unciv/ui/worldscreen/WorldScreenTopBar.kt +++ b/core/src/com/unciv/ui/worldscreen/WorldScreenTopBar.kt @@ -121,7 +121,8 @@ class WorldScreenTopBar(val screen: WorldScreen) : Table() { turnsLabel.setText("Turn".tr()+" " + civInfo.gameInfo.turns + " | "+ abs(year)+(if (year<0) " BCE" else " CE")) - val nextTurnStats = civInfo.getStatsForNextTurn() + val nextTurnStats = Stats() + for(stat in civInfo.getStatsForNextTurn().values) nextTurnStats.add(stat) val goldPerTurn = "(" + (if (nextTurnStats.gold > 0) "+" else "") + Math.round(nextTurnStats.gold) + ")" goldLabel.setText("" + Math.round(civInfo.gold.toFloat()) + goldPerTurn) diff --git a/core/src/com/unciv/ui/worldscreen/optionstable/WorldScreenOptionsTable.kt b/core/src/com/unciv/ui/worldscreen/optionstable/WorldScreenOptionsTable.kt index 63db586379..3815352a36 100644 --- a/core/src/com/unciv/ui/worldscreen/optionstable/WorldScreenOptionsTable.kt +++ b/core/src/com/unciv/ui/worldscreen/optionstable/WorldScreenOptionsTable.kt @@ -14,6 +14,11 @@ class WorldScreenOptionsTable internal constructor() : OptionsTable() { remove() } + addButton("Overview".tr()){ + UnCivGame.Current.screen = EmpireOverviewScreen() + remove() + } + addButton("Load game".tr()){ UnCivGame.Current.screen = LoadScreen() remove()