mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-22 13:49:54 +07:00
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:
@ -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 =
|
||||
(
|
||||
|
@ -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
|
||||
|
@ -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 })
|
||||
|
||||
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
@ -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),
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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.
|
||||
|
Reference in New Issue
Block a user