diff --git a/core/src/com/unciv/logic/city/CityInfo.kt b/core/src/com/unciv/logic/city/CityInfo.kt index a59737a83f..5fc33eb6c0 100644 --- a/core/src/com/unciv/logic/city/CityInfo.kt +++ b/core/src/com/unciv/logic/city/CityInfo.kt @@ -8,10 +8,9 @@ import com.unciv.logic.civilization.diplomacy.DiplomacyFlags import com.unciv.logic.map.RoadStatus import com.unciv.logic.map.TileInfo import com.unciv.logic.map.TileMap -import com.unciv.models.Counter import com.unciv.models.gamebasics.GameBasics +import com.unciv.models.gamebasics.tile.ResourceSupplyList import com.unciv.models.gamebasics.tile.ResourceType -import com.unciv.models.gamebasics.tile.TileResource import com.unciv.models.stats.Stats import com.unciv.ui.utils.withoutItem import kotlin.math.min @@ -108,8 +107,8 @@ class CityInfo { fun getTiles(): List = tiles.map { tileMap[it] } fun getTilesInRange(): List = getCenterTile().getTilesInDistance( 3) - fun getCityResources(): Counter { - val cityResources = Counter() + fun getCityResources(): ResourceSupplyList { + val cityResources = ResourceSupplyList() for (tileInfo in getTiles().filter { it.resource != null }) { val resource = tileInfo.getTileResource() @@ -128,14 +127,15 @@ class CityInfo { if(resource.resourceType == ResourceType.Luxury && getBuildingUniques().contains("Provides 1 extra copy of each improved luxury resource near this City")) amountToAdd*=2 - cityResources.add(resource, amountToAdd) + + cityResources.add(resource, amountToAdd, "Tiles") } } for (building in cityConstructions.getBuiltBuildings().filter { it.requiredResource != null }) { val resource = GameBasics.TileResources[building.requiredResource]!! - cityResources.add(resource, -1) + cityResources.add(resource, -1, "Buildings") } return cityResources diff --git a/core/src/com/unciv/logic/civilization/CivilizationInfo.kt b/core/src/com/unciv/logic/civilization/CivilizationInfo.kt index 03151e3680..3263293588 100644 --- a/core/src/com/unciv/logic/civilization/CivilizationInfo.kt +++ b/core/src/com/unciv/logic/civilization/CivilizationInfo.kt @@ -15,11 +15,10 @@ 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.* import com.unciv.models.gamebasics.tech.TechEra +import com.unciv.models.gamebasics.tile.ResourceSupplyList import com.unciv.models.gamebasics.tile.ResourceType -import com.unciv.models.gamebasics.tile.TileResource import com.unciv.models.stats.Stat import com.unciv.models.stats.Stats import java.util.* @@ -227,7 +226,7 @@ class CivilizationInfo { var happinessPerUniqueLuxury = 5f if (policies.isAdopted("Protectionism")) happinessPerUniqueLuxury += 1 - statMap["Luxury resources"]= getCivResources().keys + statMap["Luxury resources"]= getCivResources().map { it.resource } .count { it.resourceType === ResourceType.Luxury } * happinessPerUniqueLuxury for(city in cities.toList()){ @@ -259,14 +258,22 @@ class CivilizationInfo { } /** - * Returns a counter of non-zero resources that the civ has + * Returns list of all resources and their origin - for most usages you'll want getCivResources().totalSupply(), + * which unifies al the different sources */ - fun getCivResources(): Counter { - val civResources = Counter() + fun getCivResources(): ResourceSupplyList { + val newResourceSupplyList=ResourceSupplyList() + for(resourceSupply in getDetailedCivResources()) + newResourceSupplyList.add(resourceSupply.resource,resourceSupply.amount,"All") + return newResourceSupplyList + } + + fun getDetailedCivResources(): ResourceSupplyList { + val civResources = ResourceSupplyList() for (city in cities) civResources.add(city.getCityResources()) for (dip in diplomacy.values) civResources.add(dip.resourcesFromTrade()) for(resource in getCivUnits().mapNotNull { it.baseUnit.requiredResource }.map { GameBasics.TileResources[it]!! }) - civResources.add(resource,-1) + civResources.add(resource,-1,"Units") return civResources } @@ -276,7 +283,8 @@ class CivilizationInfo { fun getCivResourcesByName():HashMap{ val hashMap = HashMap() for(resource in GameBasics.TileResources.keys) hashMap[resource]=0 - for(entry in getCivResources()) hashMap[entry.key.name] = entry.value + for(entry in getCivResources()) + hashMap[entry.resource.name] = entry.amount return hashMap } diff --git a/core/src/com/unciv/logic/civilization/diplomacy/DiplomacyManager.kt b/core/src/com/unciv/logic/civilization/diplomacy/DiplomacyManager.kt index 5c64687f64..6d8b98f80c 100644 --- a/core/src/com/unciv/logic/civilization/diplomacy/DiplomacyManager.kt +++ b/core/src/com/unciv/logic/civilization/diplomacy/DiplomacyManager.kt @@ -7,9 +7,8 @@ import com.unciv.logic.civilization.CivilizationInfo import com.unciv.logic.civilization.PopupAlert import com.unciv.logic.trade.Trade import com.unciv.logic.trade.TradeType -import com.unciv.models.Counter import com.unciv.models.gamebasics.GameBasics -import com.unciv.models.gamebasics.tile.TileResource +import com.unciv.models.gamebasics.tile.ResourceSupplyList import com.unciv.models.gamebasics.tr enum class RelationshipLevel{ @@ -159,20 +158,20 @@ class DiplomacyManager() { return goldPerTurnForUs } - fun resourcesFromTrade(): Counter { - val counter = Counter() + fun resourcesFromTrade(): ResourceSupplyList { + val counter = ResourceSupplyList() for(trade in trades){ for(offer in trade.ourOffers) if(offer.type== TradeType.Strategic_Resource || offer.type== TradeType.Luxury_Resource) - counter.add(GameBasics.TileResources[offer.name]!!,-offer.amount) + counter.add(GameBasics.TileResources[offer.name]!!,-offer.amount,"Trade") for(offer in trade.theirOffers) if(offer.type== TradeType.Strategic_Resource || offer.type== TradeType.Luxury_Resource) - counter.add(GameBasics.TileResources[offer.name]!!,offer.amount) + counter.add(GameBasics.TileResources[offer.name]!!,offer.amount,"Trade") } 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) + counter.add(GameBasics.TileResources[offer.name]!!,-offer.amount,"Trade") } return counter } @@ -180,7 +179,9 @@ class DiplomacyManager() { //region state-changing functions fun removeUntenebleTrades(){ - val negativeCivResources = civInfo.getCivResources().filter { it.value<0 }.map { it.key.name } + val negativeCivResources = civInfo.getCivResources() + .filter { it.amount<0 }.map { it.resource.name } + for(trade in trades.toList()) { for (offer in trade.ourOffers) { if (offer.type in listOf(TradeType.Luxury_Resource, TradeType.Strategic_Resource) diff --git a/core/src/com/unciv/logic/trade/TradeEvaluation.kt b/core/src/com/unciv/logic/trade/TradeEvaluation.kt index 1c153006fc..0a8ea993ee 100644 --- a/core/src/com/unciv/logic/trade/TradeEvaluation.kt +++ b/core/src/com/unciv/logic/trade/TradeEvaluation.kt @@ -44,12 +44,12 @@ class TradeEvaluation{ val civsWhoWillTradeUsForTheLux = civInfo.diplomacy.values.map { it.civInfo } // secondly - should we buy this in order to resell it? .filter { it != tradePartner } .filter { !it.hasResource(offer.name) } //they don't have - val ourResourceNames = civInfo.getCivResources().map { it.key.name } + val ourResourceNames = civInfo.getCivResources().map { it.resource.name } val civsWithLuxToTrade = civsWhoWillTradeUsForTheLux.filter { // these are other civs who we could trade this lux away to, in order to get a different lux it.getCivResources().any { - it.value > 1 && it.key.resourceType == ResourceType.Luxury //they have a lux we don't and will be willing to trade it - && !ourResourceNames.contains(it.key.name) + it.amount > 1 && it.resource.resourceType == ResourceType.Luxury //they have a lux we don't and will be willing to trade it + && !ourResourceNames.contains(it.resource.name) } } var numberOfCivsWhoWouldTradeUsForTheLux = civsWithLuxToTrade.count() diff --git a/core/src/com/unciv/logic/trade/TradeLogic.kt b/core/src/com/unciv/logic/trade/TradeLogic.kt index 932f6e5b13..88d91392b5 100644 --- a/core/src/com/unciv/logic/trade/TradeLogic.kt +++ b/core/src/com/unciv/logic/trade/TradeLogic.kt @@ -30,10 +30,11 @@ class TradeLogic(val ourCivilization:CivilizationInfo, val otherCivilization: Ci offers.add(TradeOffer("Open Borders", TradeType.Agreement, 30)) } - for(entry in civInfo.getCivResources().filterNot { it.key.resourceType == ResourceType.Bonus }) { - val resourceTradeType = if(entry.key.resourceType== ResourceType.Luxury) TradeType.Luxury_Resource + for(entry in civInfo.getCivResources() + .filterNot { it.resource.resourceType == ResourceType.Bonus }) { + val resourceTradeType = if(entry.resource.resourceType== ResourceType.Luxury) TradeType.Luxury_Resource else TradeType.Strategic_Resource - offers.add(TradeOffer(entry.key.name, resourceTradeType, 30, entry.value)) + offers.add(TradeOffer(entry.resource.name, resourceTradeType, 30, entry.amount)) } if (!civInfo.isCityState() && !otherCivilization.isCityState()) { for (entry in civInfo.tech.techsResearched diff --git a/core/src/com/unciv/models/gamebasics/tile/TileResource.kt b/core/src/com/unciv/models/gamebasics/tile/TileResource.kt index a7ecfdc2b9..027874b0da 100644 --- a/core/src/com/unciv/models/gamebasics/tile/TileResource.kt +++ b/core/src/com/unciv/models/gamebasics/tile/TileResource.kt @@ -40,3 +40,20 @@ class TileResource : NamedStats(), ICivilopedia { } } +data class ResourceSupply(val resource:TileResource,var amount:Int, val origin:String) + +class ResourceSupplyList:ArrayList(){ + fun add(resource: TileResource, amount: Int, origin: String){ + val existingResourceSupply=firstOrNull{it.resource==resource && it.origin==origin} + if(existingResourceSupply!=null) { + existingResourceSupply.amount += amount + if(existingResourceSupply.amount==0) remove(existingResourceSupply) + } + else add(ResourceSupply(resource,amount,origin)) + } + + fun add(resourceSupplyList: ResourceSupplyList){ + for(resourceSupply in resourceSupplyList) + add(resourceSupply.resource,resourceSupply.amount,resourceSupply.origin) + } +} \ No newline at end of file diff --git a/core/src/com/unciv/ui/EmpireOverviewScreen.kt b/core/src/com/unciv/ui/EmpireOverviewScreen.kt index 69eb6751d1..9c5ecd92e4 100644 --- a/core/src/com/unciv/ui/EmpireOverviewScreen.kt +++ b/core/src/com/unciv/ui/EmpireOverviewScreen.kt @@ -19,6 +19,7 @@ import kotlin.math.roundToInt class EmpireOverviewScreen : CameraStageBaseScreen(){ val currentPlayerCivInfo = UnCivGame.Current.gameInfo.getCurrentPlayerCivilization() + init { onBackButtonClicked { UnCivGame.Current.setWorldScreen() } val topTable = Table().apply { defaults().pad(10f) } @@ -73,10 +74,18 @@ class EmpireOverviewScreen : CameraStageBaseScreen(){ val setDiplomacyButton = TextButton("Diplomacy".tr(),skin) setDiplomacyButton.onClick { centerTable.clear() - centerTable.add(createDiplomacyGroup()).height(stage.height*0.8f) + centerTable.add(getDiplomacyGroup()).height(stage.height*0.8f) centerTable.pack() } - topTable.add(setDiplomacyButton ) + topTable.add(setDiplomacyButton) + + val setResourcesButton = TextButton("Resources".tr(),skin) + setResourcesButton.onClick { + centerTable.clear() + centerTable.add(getResourcesTable()).height(stage.height*0.8f) + centerTable.pack() + } + topTable.add(setResourcesButton) topTable.pack() @@ -88,6 +97,7 @@ class EmpireOverviewScreen : CameraStageBaseScreen(){ } + private fun getTradesTable(): Table { val tradesTable = Table().apply { defaults().pad(10f) } for(diplomacy in currentPlayerCivInfo.diplomacy.values) @@ -292,7 +302,7 @@ class EmpireOverviewScreen : CameraStageBaseScreen(){ fun playerKnows(civ:CivilizationInfo) = civ==currentPlayerCivInfo || currentPlayerCivInfo.diplomacy.containsKey(civ.civName) - fun createDiplomacyGroup(): Group { + fun getDiplomacyGroup(): Group { val relevantCivs = currentPlayerCivInfo.gameInfo.civilizations.filter { !it.isBarbarianCivilization() && !it.isCityState() } val groupSize = 500f val group = Group() @@ -349,4 +359,36 @@ class EmpireOverviewScreen : CameraStageBaseScreen(){ return group } + + + private fun getResourcesTable(): Table { + val resourcesTable=Table().apply { defaults().pad(10f) } + val resourceDrilldown = currentPlayerCivInfo.getDetailedCivResources() + + // First row of table has all the icons + resourcesTable.add() + val resources = resourceDrilldown.map { it.resource }.distinct() + for(resource in resources) + resourcesTable.add(ImageGetter.getResourceImage(resource.name,30f)) + resourcesTable.addSeparator() + + val origins = resourceDrilldown.map { it.origin }.distinct() + for(origin in origins){ + resourcesTable.add(origin.toLabel()) + for(resource in resources){ + val resourceSupply = resourceDrilldown.firstOrNull { it.resource==resource && it.origin==origin } + if(resourceSupply==null) resourcesTable.add() + else resourcesTable.add(resourceSupply.amount.toString().toLabel()) + } + resourcesTable.row() + } + + resourcesTable.add("Total".toLabel()) + for(resource in resources){ + val sum = resourceDrilldown.filter { it.resource==resource }.sumBy { it.amount } + resourcesTable.add(sum.toString().toLabel()) + } + + return resourcesTable + } } \ 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 d645d58efc..47ba517ab3 100644 --- a/core/src/com/unciv/ui/worldscreen/WorldScreen.kt +++ b/core/src/com/unciv/ui/worldscreen/WorldScreen.kt @@ -340,8 +340,8 @@ class WorldScreen : CameraStageBaseScreen() { 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(resources.any { it.resource.resourceType==ResourceType.Luxury }) displayTutorials("LuxuryResource") + if(resources.any { it.resource.resourceType==ResourceType.Strategic}) displayTutorials("StrategicResource") if("EnemyCity" !in shownTutorials && currentPlayerCiv.exploredTiles.asSequence().map { gameInfo.tileMap[it] } .any { it.isCityCenter() && it.getOwner()!=currentPlayerCiv }) diff --git a/core/src/com/unciv/ui/worldscreen/WorldScreenTopBar.kt b/core/src/com/unciv/ui/worldscreen/WorldScreenTopBar.kt index f806cc86c8..a381075ebb 100644 --- a/core/src/com/unciv/ui/worldscreen/WorldScreenTopBar.kt +++ b/core/src/com/unciv/ui/worldscreen/WorldScreenTopBar.kt @@ -110,8 +110,8 @@ class WorldScreenTopBar(val screen: WorldScreen) : Table() { val isRevealed = civInfo.tech.isResearched(resource.revealedBy!!) resourceLabels[resource.name]!!.isVisible = isRevealed resourceImages[resource.name]!!.isVisible = isRevealed - if (!civResources.containsKey(resource)) resourceLabels[resource.name]!!.setText("0") - else resourceLabels[resource.name]!!.setText(civResources[resource]!!.toString()) + if (!civResources.any { it.resource==resource}) resourceLabels[resource.name]!!.setText("0") + else resourceLabels[resource.name]!!.setText(civResources.first { it.resource==resource }.amount.toString()) } val turns = civInfo.gameInfo.turns