Resource Overview: Info on unavailable strategic and unimproved by allies (#11571)

* Resource Overview: Info on unavailable strategic and unimproved by allies

* Update tutorial
This commit is contained in:
SomeTroglodyte
2024-05-11 20:36:17 +02:00
committed by GitHub
parent 628bd71830
commit a485510faf
3 changed files with 46 additions and 15 deletions

View File

@ -504,7 +504,7 @@
{},
{"text":"Reveal known resources on world screen","header":5,"color":"#fa0"},
{"text":"In the Resources overview, click on a resource icon to center the world screen on tiles already discovered and providing this resource."},
{"text":"Alternatively, click on the \"Unimproved\" number to center the world screen only on owned tiles where the resource is not improved."},
{"text":"Alternatively, click on the \"Unimproved\" number to center the world screen only on owned (by you or your allied City-states) tiles where the resource is not improved."},
{"text":"If more than one tile is available, click repeatedly on the notification to cycle through all of them."},
{},
{"text":"Show diagram line colors","header":5,"color":"#fa0"},

View File

@ -539,13 +539,20 @@ class GameInfo : IsPartOfGameInfoSerialization, HasGameInfoSerializationVersion
* @see notifyExploredResources
*/
fun getExploredResourcesNotification(
civInfo: Civilization,
civ: Civilization,
resourceName: String,
maxDistance: Int = Int.MAX_VALUE,
filter: (Tile) -> Boolean = { true }
): Notification? {
data class CityTileAndDistance(val city: City, val tile: Tile, val distance: Int)
// Include your city-state allies' cities with your own for the purpose of showing the closest city
val relevantCities: Sequence<City> = civ.cities.asSequence() +
civ.getKnownCivs()
.filter { it.isCityState() && it.getAllyCiv() == civ.civName }
.flatMap { it.cities }
// All sources of the resource on the map, using a city-state's capital center tile for the CityStateOnlyResource types
val exploredRevealTiles: Sequence<Tile> =
if (ruleset.tileResources[resourceName]!!.hasUnique(UniqueType.CityStateOnlyResource)) {
// Look for matching mercantile CS centers
@ -559,15 +566,15 @@ class GameInfo : IsPartOfGameInfoSerialization, HasGameInfoSerializationVersion
.filter { it.resource == resourceName }
}
// Apply all filters to the above collection and sort them by distance to closest city
val exploredRevealInfo = exploredRevealTiles
.filter { civInfo.hasExplored(it) }
.filter { civ.hasExplored(it) }
.flatMap { tile ->
civInfo.cities.asSequence()
.map {
relevantCities
.map { city ->
// build a full cross join all revealed tiles * civ's cities (should rarely surpass a few hundred)
// cache distance for each pair as sort will call it ~ 2n log n times
// should still be cheaper than looking up 'the' closest city per reveal tile before sorting
city ->
CityTileAndDistance(city, tile, tile.aerialDistanceTo(city.getCenterTile()))
}
}

View File

@ -5,6 +5,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.Label
import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.badlogic.gdx.utils.Align
import com.unciv.UncivGame
import com.unciv.logic.city.City
import com.unciv.logic.civilization.Civilization
import com.unciv.logic.map.tile.Tile
import com.unciv.logic.trade.TradeType
@ -76,14 +77,17 @@ class ResourcesOverviewTab(
.mapNotNull { ExtraInfoOrigin.safeValueOf(it.origin) }.distinct().toList()
private fun ResourceSupplyList.getLabel(resource: TileResource, origin: String): Label? {
fun isAlliedAndUnimproved(tile: Tile): Boolean {
val owner = tile.getOwner() ?: return false
if (owner != viewingPlayer && !(owner.isCityState() && owner.getAllyCiv() == viewingPlayer.civName)) return false
return tile.countAsUnimproved()
}
val amount = get(resource, origin)?.amount ?: return null
val label = if (resource.isStockpiled() && amount > 0) "+$amount".toLabel()
else amount.toLabel()
if (origin == ExtraInfoOrigin.Unimproved.name)
label.onClick { overviewScreen.showOneTimeNotification(
gameInfo.getExploredResourcesNotification(viewingPlayer, resource.name) {
it.getOwner() == viewingPlayer && it.countAsUnimproved()
}
gameInfo.getExploredResourcesNotification(viewingPlayer, resource.name, filter = ::isAlliedAndUnimproved)
) }
return label
}
@ -244,7 +248,15 @@ class ResourcesOverviewTab(
!providesResources(viewingPlayer)
private fun getExtraDrilldown(): ResourceSupplyList {
val newResourceSupplyList = ResourceSupplyList()
val newResourceSupplyList = ResourceSupplyList(keepZeroAmounts = true)
fun City.addUnimproved() {
for (tile in getTiles())
if (tile.countAsUnimproved())
newResourceSupplyList.add(tile.tileResource, ExtraInfoOrigin.Unimproved.name)
}
// Show resources relevant to WTLK day and/or needing improvement
for (city in viewingPlayer.cities) {
if (city.demandedResource.isNotEmpty()) {
val wltkResource = gameInfo.ruleset.tileResources[city.demandedResource]!!
@ -254,16 +266,28 @@ class ResourcesOverviewTab(
newResourceSupplyList.add(wltkResource, ExtraInfoOrigin.DemandingWLTK.name)
}
}
for (tile in city.getTiles())
if (tile.countAsUnimproved())
newResourceSupplyList.add(tile.tileResource, ExtraInfoOrigin.Unimproved.name)
city.addUnimproved()
}
for (otherCiv in viewingPlayer.getKnownCivs())
for (otherCiv in viewingPlayer.getKnownCivs()) {
// Show resources received through trade
for (trade in otherCiv.tradeRequests.filter { it.requestingCiv == viewingPlayer.civName })
for (offer in trade.trade.theirOffers.filter{it.type == TradeType.Strategic_Resource || it.type == TradeType.Luxury_Resource})
for (offer in trade.trade.theirOffers.filter { it.type == TradeType.Strategic_Resource || it.type == TradeType.Luxury_Resource })
newResourceSupplyList.add(gameInfo.ruleset.tileResources[offer.name]!!, ExtraInfoOrigin.TradeOffer.name, offer.amount)
// Show resources your city-state allies have left unimproved
if (!otherCiv.isCityState() || otherCiv.getAllyCiv() != viewingPlayer.civName) continue
for (city in otherCiv.cities)
city.addUnimproved()
}
/** Show unlocked **strategic** resources even if you have no access at all */
for (resource in viewingPlayer.gameInfo.ruleset.tileResources.values) {
if (resource.resourceType != ResourceType.Strategic) continue
if (resource.revealedBy == null || viewingPlayer.tech.isResearched(resource.revealedBy!!))
newResourceSupplyList.add(resource, "No source", 0)
}
return newResourceSupplyList
}
}