mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-27 22:06:05 -04: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:
parent
644c61a851
commit
03f7af4360
@ -240,9 +240,12 @@ class CivInfoStats(val civInfo: CivilizationInfo) {
|
|||||||
val ownedLuxuries = civInfo.getCivResources().map { it.resource }
|
val ownedLuxuries = civInfo.getCivResources().map { it.resource }
|
||||||
.filter { it.resourceType == ResourceType.Luxury }
|
.filter { it.resourceType == ResourceType.Luxury }
|
||||||
|
|
||||||
statMap["Luxury resources"] = civInfo.getCivResources()
|
val relevantLuxuries = civInfo.getCivResources().asSequence()
|
||||||
.map { it.resource }
|
.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 =
|
val happinessBonusForCityStateProvidedLuxuries =
|
||||||
(
|
(
|
||||||
|
@ -454,15 +454,14 @@ open class TileInfo {
|
|||||||
&& neighbors.any { it.getOwner() == civInfo } && civInfo.cities.isNotEmpty()
|
&& neighbors.any { it.getOwner() == civInfo } && civInfo.cities.isNotEmpty()
|
||||||
)
|
)
|
||||||
) -> false
|
) -> false
|
||||||
improvement.uniqueObjects.any {
|
improvement.getMatchingUniques(UniqueType.ObsoleteWith).any {
|
||||||
it.placeholderText == "Obsolete with []" && civInfo.tech.isResearched(it.params[0])
|
civInfo.tech.isResearched(it.params[0])
|
||||||
} -> return false
|
} -> return false
|
||||||
improvement.getMatchingUniques(UniqueType.CannotBuildOnTile, StateForConditionals(civInfo=civInfo)).any {
|
improvement.getMatchingUniques(UniqueType.CannotBuildOnTile, StateForConditionals(civInfo=civInfo)).any {
|
||||||
matchesTerrainFilter(it.params[0], civInfo)
|
matchesTerrainFilter(it.params[0], civInfo)
|
||||||
} -> false
|
} -> false
|
||||||
improvement.uniqueObjects.any {
|
improvement.getMatchingUniques(UniqueType.ConsumesResources).any {
|
||||||
it.isOfType(UniqueType.ConsumesResources)
|
civInfo.getCivResourcesByName()[it.params[1]]!! < it.params[0].toInt()
|
||||||
&& civInfo.getCivResourcesByName()[it.params[1]]!! < it.params[0].toInt()
|
|
||||||
} -> false
|
} -> false
|
||||||
// Calling this function does double the check for 'cannot be build on tile', but this is unavoidable.
|
// 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
|
// 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]))
|
if (!cityConstructions.cityInfo.matchesFilter(unique.params[0]))
|
||||||
rejectionReasons.add(RejectionReason.CanOnlyBeBuiltInSpecificCities.apply { errorMessage = unique.text })
|
rejectionReasons.add(RejectionReason.CanOnlyBeBuiltInSpecificCities.apply { errorMessage = unique.text })
|
||||||
|
|
||||||
"Obsolete with []" ->
|
UniqueType.ObsoleteWith.placeholderText ->
|
||||||
if (civInfo.tech.isResearched(unique.params[0]))
|
if (civInfo.tech.isResearched(unique.params[0]))
|
||||||
rejectionReasons.add(RejectionReason.Obsoleted.apply { errorMessage = unique.text })
|
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.Building
|
||||||
import com.unciv.models.ruleset.Ruleset
|
import com.unciv.models.ruleset.Ruleset
|
||||||
import com.unciv.models.ruleset.RulesetObject
|
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.UniqueFlag
|
||||||
import com.unciv.models.ruleset.unique.UniqueTarget
|
import com.unciv.models.ruleset.unique.UniqueTarget
|
||||||
import com.unciv.models.ruleset.unique.UniqueType
|
import com.unciv.models.ruleset.unique.UniqueType
|
||||||
@ -74,8 +75,8 @@ class Technology: RulesetObject() {
|
|||||||
lineList += " * " + wonder.name.tr() + " (" + wonder.getShortDescription() + ")"
|
lineList += " * " + wonder.name.tr() + " (" + wonder.getShortDescription() + ")"
|
||||||
}
|
}
|
||||||
|
|
||||||
for (building in getObsoletedBuildings(viewingCiv))
|
for (obj in getObsoletedObjects(viewingCiv))
|
||||||
lineList += "[${building.name}] obsoleted"
|
lineList += "[${obj.name}] obsoleted"
|
||||||
|
|
||||||
for (resource in ruleset.tileResources.values.asSequence().filter { it.revealedBy == name }
|
for (resource in ruleset.tileResources.values.asSequence().filter { it.revealedBy == name }
|
||||||
.map { it.name })
|
.map { it.name })
|
||||||
@ -105,8 +106,13 @@ class Technology: RulesetObject() {
|
|||||||
* nuclear weapons and religion settings, and without those expressly hidden from Civilopedia.
|
* 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
|
// 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
|
// Helper: common filtering for both getEnabledBuildings and getObsoletedBuildings, difference via predicate parameter
|
||||||
private fun getFilteredBuildings(civInfo: CivilizationInfo, predicate: (Building)->Boolean): Sequence<Building> {
|
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())
|
lineList += FormattedLine(building.name.tr() + " (" + building.getShortDescription() + ")", link = building.makeLink())
|
||||||
}
|
}
|
||||||
|
|
||||||
val obsoletedBuildings = getObsoletedBuildings(viewingCiv)
|
val obsoletedObjects = getObsoletedObjects(viewingCiv)
|
||||||
if (obsoletedBuildings.any()) {
|
if (obsoletedObjects.any()) {
|
||||||
lineList += FormattedLine()
|
lineList += FormattedLine()
|
||||||
obsoletedBuildings.forEach {
|
obsoletedObjects.forEach {
|
||||||
lineList += FormattedLine("[${it.name}] obsoleted", link = it.makeLink())
|
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),
|
MustNotBeNextTo("Must not be next to [terrainFilter]", UniqueTarget.Building),
|
||||||
|
|
||||||
Unsellable("Unsellable", 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),
|
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.graphics.Color
|
||||||
import com.badlogic.gdx.scenes.scene2d.Touchable
|
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.scenes.scene2d.ui.Table
|
||||||
import com.badlogic.gdx.utils.Align
|
import com.badlogic.gdx.utils.Align
|
||||||
import com.unciv.logic.civilization.TechManager
|
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.*
|
import com.unciv.ui.utils.*
|
||||||
|
|
||||||
class TechButton(techName:String, private val techManager: TechManager, isWorldScreen: Boolean = true) : Table(BaseScreen.skin) {
|
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))
|
for (building in tech.getEnabledBuildings(techManager.civInfo))
|
||||||
techEnabledIcons.add(ImageGetter.getConstructionImage(building.name).surroundWithCircle(techIconSize))
|
techEnabledIcons.add(ImageGetter.getConstructionImage(building.name).surroundWithCircle(techIconSize))
|
||||||
|
|
||||||
for (building in tech.getObsoletedBuildings(techManager.civInfo))
|
for (obj in tech.getObsoletedObjects(techManager.civInfo)) {
|
||||||
techEnabledIcons.add(ImageGetter.getConstructionImage(building.name).surroundWithCircle(techIconSize).apply {
|
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)
|
val closeImage = ImageGetter.getRedCross(techIconSize / 2, 1f)
|
||||||
closeImage.center(this)
|
closeImage.center(it)
|
||||||
addActor(closeImage)
|
it.addActor(closeImage)
|
||||||
})
|
}
|
||||||
|
techEnabledIcons.add(obsoletedIcon)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
for (improvement in ruleset.tileImprovements.values.asSequence()
|
for (improvement in ruleset.tileImprovements.values.asSequence()
|
||||||
.filter {
|
.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)
|
if (improvementName.startsWith(Constants.remove) || improvementName == Constants.cancelImprovementOrder)
|
||||||
return Table().apply { add(getImage("OtherIcons/Stop")).size(size) }
|
return Table().apply { add(getImage("OtherIcons/Stop")).size(size) }
|
||||||
|
|
||||||
@ -333,7 +333,7 @@ object ImageGetter {
|
|||||||
return redCross
|
return redCross
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getResourceImage(resourceName: String, size: Float): Actor {
|
fun getResourceImage(resourceName: String, size: Float): IconCircleGroup {
|
||||||
val iconGroup = getImage("ResourceIcons/$resourceName").surroundWithCircle(size)
|
val iconGroup = getImage("ResourceIcons/$resourceName").surroundWithCircle(size)
|
||||||
val resource = ruleset.tileResources[resourceName]
|
val resource = ruleset.tileResources[resourceName]
|
||||||
?: return iconGroup // This is the result of a bad modding setup, just give em an empty circle. Their problem.
|
?: return iconGroup // This is the result of a bad modding setup, just give em an empty circle. Their problem.
|
||||||
|
@ -769,6 +769,11 @@ Applicable to: Building
|
|||||||
#### Unsellable
|
#### Unsellable
|
||||||
Applicable to: Building
|
Applicable to: Building
|
||||||
|
|
||||||
|
#### Obsolete with [tech]
|
||||||
|
Example: "Obsolete with [Agriculture]"
|
||||||
|
|
||||||
|
Applicable to: Building, Improvement, Resource
|
||||||
|
|
||||||
#### Remove extra unhappiness from annexed cities
|
#### Remove extra unhappiness from annexed cities
|
||||||
Applicable to: Building
|
Applicable to: Building
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user