Typified Obsolete unique, made luxury resources obsoletable (#6129)

* Typified Obsolete unique, made luxury resources obsoletable
Things that were luxuries in the past become uninteresting as time goes on

* Unified obsolescence handling for buildings, improvements and resources

* Obsolete icons have their x's in the right place

* All images &c are done - we have the skeleton of the mod in place!

* Revert "All images &c are done - we have the skeleton of the mod in place!"

This reverts commit 61553c17
This commit is contained in:
Yair Morgenstern
2022-02-09 12:18:14 +02:00
committed by GitHub
parent 644c61a851
commit 03f7af4360
8 changed files with 48 additions and 23 deletions

View File

@ -240,9 +240,12 @@ class CivInfoStats(val civInfo: CivilizationInfo) {
val ownedLuxuries = civInfo.getCivResources().map { it.resource }
.filter { it.resourceType == ResourceType.Luxury }
statMap["Luxury resources"] = civInfo.getCivResources()
val relevantLuxuries = civInfo.getCivResources().asSequence()
.map { it.resource }
.count { it.resourceType === ResourceType.Luxury } * happinessPerUniqueLuxury
.count { it.resourceType == ResourceType.Luxury
&& it.getMatchingUniques(UniqueType.ObsoleteWith)
.none { unique -> civInfo.tech.isResearched(unique.params[0]) } }
statMap["Luxury resources"] = relevantLuxuries * happinessPerUniqueLuxury
val happinessBonusForCityStateProvidedLuxuries =
(

View File

@ -454,15 +454,14 @@ open class TileInfo {
&& neighbors.any { it.getOwner() == civInfo } && civInfo.cities.isNotEmpty()
)
) -> false
improvement.uniqueObjects.any {
it.placeholderText == "Obsolete with []" && civInfo.tech.isResearched(it.params[0])
improvement.getMatchingUniques(UniqueType.ObsoleteWith).any {
civInfo.tech.isResearched(it.params[0])
} -> return false
improvement.getMatchingUniques(UniqueType.CannotBuildOnTile, StateForConditionals(civInfo=civInfo)).any {
matchesTerrainFilter(it.params[0], civInfo)
} -> false
improvement.uniqueObjects.any {
it.isOfType(UniqueType.ConsumesResources)
&& civInfo.getCivResourcesByName()[it.params[1]]!! < it.params[0].toInt()
improvement.getMatchingUniques(UniqueType.ConsumesResources).any {
civInfo.getCivResourcesByName()[it.params[1]]!! < it.params[0].toInt()
} -> false
// Calling this function does double the check for 'cannot be build on tile', but this is unavoidable.
// Only in this function do we have the civInfo of the civ, so only here we can check whether

View File

@ -515,7 +515,7 @@ class Building : RulesetStatsObject(), INonPerpetualConstruction {
if (!cityConstructions.cityInfo.matchesFilter(unique.params[0]))
rejectionReasons.add(RejectionReason.CanOnlyBeBuiltInSpecificCities.apply { errorMessage = unique.text })
"Obsolete with []" ->
UniqueType.ObsoleteWith.placeholderText ->
if (civInfo.tech.isResearched(unique.params[0]))
rejectionReasons.add(RejectionReason.Obsoleted.apply { errorMessage = unique.text })

View File

@ -5,6 +5,7 @@ import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.models.ruleset.Building
import com.unciv.models.ruleset.Ruleset
import com.unciv.models.ruleset.RulesetObject
import com.unciv.models.ruleset.RulesetStatsObject
import com.unciv.models.ruleset.unique.UniqueFlag
import com.unciv.models.ruleset.unique.UniqueTarget
import com.unciv.models.ruleset.unique.UniqueType
@ -74,8 +75,8 @@ class Technology: RulesetObject() {
lineList += " * " + wonder.name.tr() + " (" + wonder.getShortDescription() + ")"
}
for (building in getObsoletedBuildings(viewingCiv))
lineList += "[${building.name}] obsoleted"
for (obj in getObsoletedObjects(viewingCiv))
lineList += "[${obj.name}] obsoleted"
for (resource in ruleset.tileResources.values.asSequence().filter { it.revealedBy == name }
.map { it.name })
@ -105,8 +106,13 @@ class Technology: RulesetObject() {
* nuclear weapons and religion settings, and without those expressly hidden from Civilopedia.
*/
// Used for Civilopedia, Alert and Picker, so if any of these decide to ignore the "Will not be displayed in Civilopedia" unique this needs refactoring
fun getObsoletedBuildings(civInfo: CivilizationInfo) = getFilteredBuildings(civInfo)
{ it.uniqueObjects.any { unique -> unique.placeholderText == "Obsolete with []" && unique.params[0] == name } }
fun getObsoletedObjects(civInfo: CivilizationInfo): Sequence<RulesetStatsObject> =
(getFilteredBuildings(civInfo){true}
+ civInfo.gameInfo.ruleSet.tileResources.values.asSequence()
+ civInfo.gameInfo.ruleSet.tileImprovements.values.filter {
it.uniqueTo==null || it.uniqueTo == civInfo.civName
}).filter { it.getMatchingUniques(UniqueType.ObsoleteWith).any { it.params[0] == name } }
// Helper: common filtering for both getEnabledBuildings and getObsoletedBuildings, difference via predicate parameter
private fun getFilteredBuildings(civInfo: CivilizationInfo, predicate: (Building)->Boolean): Sequence<Building> {
@ -241,10 +247,10 @@ class Technology: RulesetObject() {
lineList += FormattedLine(building.name.tr() + " (" + building.getShortDescription() + ")", link = building.makeLink())
}
val obsoletedBuildings = getObsoletedBuildings(viewingCiv)
if (obsoletedBuildings.any()) {
val obsoletedObjects = getObsoletedObjects(viewingCiv)
if (obsoletedObjects.any()) {
lineList += FormattedLine()
obsoletedBuildings.forEach {
obsoletedObjects.forEach {
lineList += FormattedLine("[${it.name}] obsoleted", link = it.makeLink())
}
}

View File

@ -330,6 +330,7 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags:
MustNotBeNextTo("Must not be next to [terrainFilter]", UniqueTarget.Building),
Unsellable("Unsellable", UniqueTarget.Building),
ObsoleteWith("Obsolete with [tech]", UniqueTarget.Building, UniqueTarget.Resource, UniqueTarget.Improvement),
RemoveAnnexUnhappiness("Remove extra unhappiness from annexed cities", UniqueTarget.Building),

View File

@ -2,10 +2,12 @@ package com.unciv.ui.pickerscreens
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.scenes.scene2d.Touchable
import com.badlogic.gdx.scenes.scene2d.ui.Button
import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.badlogic.gdx.utils.Align
import com.unciv.logic.civilization.TechManager
import com.unciv.models.ruleset.Building
import com.unciv.models.ruleset.tile.TileImprovement
import com.unciv.models.ruleset.tile.TileResource
import com.unciv.ui.utils.*
class TechButton(techName:String, private val techManager: TechManager, isWorldScreen: Boolean = true) : Table(BaseScreen.skin) {
@ -59,12 +61,21 @@ class TechButton(techName:String, private val techManager: TechManager, isWorldS
for (building in tech.getEnabledBuildings(techManager.civInfo))
techEnabledIcons.add(ImageGetter.getConstructionImage(building.name).surroundWithCircle(techIconSize))
for (building in tech.getObsoletedBuildings(techManager.civInfo))
techEnabledIcons.add(ImageGetter.getConstructionImage(building.name).surroundWithCircle(techIconSize).apply {
for (obj in tech.getObsoletedObjects(techManager.civInfo)) {
val obsoletedIcon = when {
obj is Building -> ImageGetter.getConstructionImage(obj.name)
.surroundWithCircle(techIconSize)
obj is TileResource -> ImageGetter.getResourceImage(obj.name, techIconSize)
obj is TileImprovement -> ImageGetter.getImprovementIcon(obj.name, techIconSize)
else -> continue
}.also {
val closeImage = ImageGetter.getRedCross(techIconSize / 2, 1f)
closeImage.center(this)
addActor(closeImage)
})
closeImage.center(it)
it.addActor(closeImage)
}
techEnabledIcons.add(obsoletedIcon)
}
for (improvement in ruleset.tileImprovements.values.asSequence()
.filter {

View File

@ -260,7 +260,7 @@ object ImageGetter {
}
fun getImprovementIcon(improvementName: String, size: Float = 20f): Actor {
fun getImprovementIcon(improvementName: String, size: Float = 20f): Group {
if (improvementName.startsWith(Constants.remove) || improvementName == Constants.cancelImprovementOrder)
return Table().apply { add(getImage("OtherIcons/Stop")).size(size) }
@ -333,7 +333,7 @@ object ImageGetter {
return redCross
}
fun getResourceImage(resourceName: String, size: Float): Actor {
fun getResourceImage(resourceName: String, size: Float): IconCircleGroup {
val iconGroup = getImage("ResourceIcons/$resourceName").surroundWithCircle(size)
val resource = ruleset.tileResources[resourceName]
?: return iconGroup // This is the result of a bad modding setup, just give em an empty circle. Their problem.