mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-04 07:17:50 +07:00
Show notification to cycle through visible resources when clicking on resource icon in Resource Overview. (#5603)
* Show notif to cycle through resource tiles when tapping on icon in Resource Overview. * Make resource reveal notification more configurable, and move completely to `GameInfo`. * Make resource reveal notification loop through all explored tiles, instead of just visible tiles. * Have resource discovery notif cycle through matching CS centers for CS-only Luxuries. * Remove commented lines. * Remove extra comma. * Use Sequence in resource notif.
This commit is contained in:
@ -7,6 +7,7 @@ import com.unciv.logic.BackwardCompatibility.replaceDiplomacyFlag
|
||||
import com.unciv.logic.automation.NextTurnAutomation
|
||||
import com.unciv.logic.civilization.*
|
||||
import com.unciv.logic.civilization.diplomacy.DiplomacyFlags
|
||||
import com.unciv.logic.city.CityInfo
|
||||
import com.unciv.logic.map.TileInfo
|
||||
import com.unciv.logic.map.TileMap
|
||||
import com.unciv.models.Religion
|
||||
@ -16,6 +17,7 @@ import com.unciv.models.ruleset.Difficulty
|
||||
import com.unciv.models.ruleset.ModOptionsConstants
|
||||
import com.unciv.models.ruleset.Ruleset
|
||||
import com.unciv.models.ruleset.RulesetCache
|
||||
import com.unciv.models.ruleset.unique.UniqueType
|
||||
import com.unciv.ui.audio.MusicMood
|
||||
import com.unciv.ui.audio.MusicTrackChooserFlags
|
||||
import java.util.*
|
||||
@ -292,6 +294,57 @@ class GameInfo {
|
||||
}
|
||||
}
|
||||
|
||||
fun notifyExploredResources(civInfo: CivilizationInfo, resourceName: String, maxDistance: Int, showForeign: Boolean) {
|
||||
// Calling with `maxDistance = 0` removes distance limitation.
|
||||
data class CityTileAndDistance(val city: CityInfo, val tile: TileInfo, val distance: Int)
|
||||
|
||||
var exploredRevealTiles:Sequence<TileInfo>
|
||||
|
||||
if (ruleSet.tileResources[resourceName]!!.hasUnique(UniqueType.CityStateOnlyResource)) {
|
||||
// Look for matching mercantile CS centers
|
||||
exploredRevealTiles = getAliveCityStates()
|
||||
.asSequence()
|
||||
.filter { it.cityStateResource == resourceName }
|
||||
.map { it.getCapital().getCenterTile() }
|
||||
} else {
|
||||
exploredRevealTiles = tileMap.values
|
||||
.asSequence()
|
||||
.filter { it.resource == resourceName }
|
||||
}
|
||||
|
||||
val exploredRevealInfo = exploredRevealTiles
|
||||
.filter { it.position in civInfo.exploredTiles }
|
||||
.flatMap { tile -> civInfo.cities.asSequence()
|
||||
.map {
|
||||
// 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()))
|
||||
}
|
||||
}
|
||||
.filter { (maxDistance == 0 || it.distance <= maxDistance) && (showForeign || it.tile.getOwner() == null || it.tile.getOwner() == civInfo) }
|
||||
.sortedWith ( compareBy { it.distance } )
|
||||
.distinctBy { it.tile }
|
||||
|
||||
val chosenCity = exploredRevealInfo.firstOrNull()?.city ?: return
|
||||
val positions = exploredRevealInfo
|
||||
// re-sort to a more pleasant display order
|
||||
.sortedWith(compareBy{ it.tile.aerialDistanceTo(chosenCity.getCenterTile()) })
|
||||
.map { it.tile.position }
|
||||
.toList() // explicit materialization of sequence to satisfy addNotification overload
|
||||
|
||||
val text = if(positions.size==1)
|
||||
"[$resourceName] revealed near [${chosenCity.name}]"
|
||||
else
|
||||
"[${positions.size}] sources of [$resourceName] revealed, e.g. near [${chosenCity.name}]"
|
||||
|
||||
civInfo.addNotification(
|
||||
text,
|
||||
LocationAction(positions),
|
||||
"ResourceIcons/$resourceName"
|
||||
)
|
||||
}
|
||||
|
||||
// All cross-game data which needs to be altered (e.g. when removing or changing a name of a building/tech)
|
||||
// will be done here, and not in CivInfo.setTransients or CityInfo
|
||||
fun setTransients() {
|
||||
|
@ -262,7 +262,11 @@ class TechManager {
|
||||
}
|
||||
}
|
||||
|
||||
if (civInfo.playerType == PlayerType.Human) notifyRevealedResources(techName)
|
||||
if (civInfo.playerType == PlayerType.Human) {
|
||||
for (revealedResource in getRuleset().tileResources.values.filter { techName == it.revealedBy }) {
|
||||
civInfo.gameInfo.notifyExploredResources(civInfo, revealedResource.name, 5, false)
|
||||
}
|
||||
}
|
||||
|
||||
val obsoleteUnits = getRuleset().units.values.filter { it.obsoleteTech == techName }.map { it.name }
|
||||
val unitUpgrades = HashMap<String, ArrayList<CityInfo>>()
|
||||
@ -323,46 +327,6 @@ class TechManager {
|
||||
techUniques.addUnique(unique)
|
||||
}
|
||||
|
||||
private fun notifyRevealedResources(techName: String) {
|
||||
data class CityTileAndDistance(val city: CityInfo, val tile: TileInfo, val distance: Int)
|
||||
|
||||
for (revealedResource in getRuleset().tileResources.values.filter { techName == it.revealedBy }) {
|
||||
val revealedName = revealedResource.name
|
||||
|
||||
val visibleRevealTiles = civInfo.viewableTiles.asSequence()
|
||||
.filter { it.resource == revealedName }
|
||||
.flatMap { tile -> civInfo.cities.asSequence()
|
||||
.map {
|
||||
// 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()))
|
||||
}
|
||||
}
|
||||
.filter { it.distance <= 5 && (it.tile.getOwner() == null || it.tile.getOwner() == civInfo) }
|
||||
.sortedWith ( compareBy { it.distance } )
|
||||
.distinctBy { it.tile }
|
||||
|
||||
val chosenCity = visibleRevealTiles.firstOrNull()?.city ?: continue
|
||||
val positions = visibleRevealTiles
|
||||
// re-sort to a more pleasant display order
|
||||
.sortedWith(compareBy{ it.tile.aerialDistanceTo(chosenCity.getCenterTile()) })
|
||||
.map { it.tile.position }
|
||||
.toList() // explicit materialization of sequence to satisfy addNotification overload
|
||||
|
||||
val text = if(positions.size==1)
|
||||
"[$revealedName] revealed near [${chosenCity.name}]"
|
||||
else
|
||||
"[${positions.size}] sources of [$revealedName] revealed, e.g. near [${chosenCity.name}]"
|
||||
|
||||
civInfo.addNotification(
|
||||
text,
|
||||
LocationAction(positions),
|
||||
"ResourceIcons/$revealedName"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun setTransients() {
|
||||
researchedTechnologies.addAll(techsResearched.map { getRuleset().technologies[it]!! })
|
||||
researchedTechnologies.forEach { addTechToTransients(it) }
|
||||
|
@ -31,25 +31,20 @@ class ResourcesOverviewTable (
|
||||
.filter { it.resourceType != ResourceType.Bonus }.distinct()
|
||||
.sortedWith(compareBy({ it.resourceType }, { it.name.tr() }))
|
||||
|
||||
var visibleLabel: Label? = null
|
||||
for (resource in resources) {
|
||||
// Create a group of label and icon for each resource.
|
||||
val resourceImage = ImageGetter.getResourceImage(resource.name, 50f)
|
||||
val resourceLabel = resource.name.toLabel()
|
||||
val labelPadding = 10f
|
||||
// Using a table here leads to spacing issues
|
||||
// due to different label lengths.
|
||||
val holder = Group()
|
||||
resourceImage.onClick {
|
||||
if (visibleLabel != null)
|
||||
visibleLabel!!.isVisible = false
|
||||
resourceLabel.isVisible = true
|
||||
visibleLabel = resourceLabel
|
||||
viewingPlayer.gameInfo.notifyExploredResources(viewingPlayer, resource.name, 0, true)
|
||||
overviewScreen.game.setWorldScreen()
|
||||
}
|
||||
holder.addActor(resourceImage)
|
||||
holder.addActor(resourceLabel)
|
||||
holder.setSize(resourceImage.width,
|
||||
resourceImage.height + resourceLabel.height + labelPadding)
|
||||
resourceImage.height + labelPadding)
|
||||
// Center-align all labels, but right-align the last couple resources' labels
|
||||
// because they may get clipped otherwise. The leftmost label should be fine
|
||||
// center-aligned (if there are more than 2 resources), because the left side
|
||||
@ -58,9 +53,6 @@ class ResourcesOverviewTable (
|
||||
(resources.indexOf(resource) + 2 >= resources.count()) -> 1
|
||||
else -> 2
|
||||
}
|
||||
resourceLabel.moveBy((resourceImage.width - resourceLabel.width) / alignFactor,
|
||||
resourceImage.height + labelPadding)
|
||||
resourceLabel.isVisible = false
|
||||
add(holder)
|
||||
}
|
||||
addSeparator()
|
||||
|
Reference in New Issue
Block a user