diff --git a/core/src/com/unciv/logic/automation/WorkerAutomation.kt b/core/src/com/unciv/logic/automation/WorkerAutomation.kt index 8844413e59..6fe026e907 100644 --- a/core/src/com/unciv/logic/automation/WorkerAutomation.kt +++ b/core/src/com/unciv/logic/automation/WorkerAutomation.kt @@ -438,7 +438,7 @@ class WorkerAutomation( if (closeTile.isCityCenter()) return false // don't build forts too close to other forts if (closeTile.improvement != null - && closeTile.getTileImprovement()!!.uniqueObjects.any { it.placeholderText == "Gives a defensive bonus of []%" } + && closeTile.getTileImprovement()!!.hasUnique("Gives a defensive bonus of []%") || closeTile.improvementInProgress != Constants.fort) return false // there is another better tile for the fort if (!tile.isHill() && closeTile.isHill() && diff --git a/core/src/com/unciv/logic/city/CityConstructions.kt b/core/src/com/unciv/logic/city/CityConstructions.kt index 121d0fee08..dc284228c5 100644 --- a/core/src/com/unciv/logic/city/CityConstructions.kt +++ b/core/src/com/unciv/logic/city/CityConstructions.kt @@ -391,7 +391,7 @@ class CityConstructions { private fun constructionBegun(construction: IConstruction) { if (construction !is Building) return - if (construction.uniqueObjects.none { it.placeholderText == "Triggers a global alert upon build start" }) return + if (construction.hasUnique("Triggers a global alert upon build start")) return val buildingIcon = "BuildingIcons/${construction.name}" for (otherCiv in cityInfo.civInfo.gameInfo.civilizations) { if (otherCiv == cityInfo.civInfo) continue @@ -432,7 +432,10 @@ class CityConstructions { cityInfo.civInfo.addNotification("[${construction.name}] has been built in [" + cityInfo.name + "]", cityInfo.location, NotificationIcon.Construction, icon) } - if (construction is Building && construction.uniqueObjects.any { it.placeholderText == "Triggers a global alert upon completion" } ) { + + if (construction is Building && construction.hasUnique("Triggers a global alert upon completion", + StateForConditionals(cityInfo.civInfo, cityInfo) + )) { for (otherCiv in cityInfo.civInfo.gameInfo.civilizations) { // No need to notify ourself, since we already got the building notification anyway if (otherCiv == cityInfo.civInfo) continue diff --git a/core/src/com/unciv/logic/civilization/CivilizationInfo.kt b/core/src/com/unciv/logic/civilization/CivilizationInfo.kt index c15524a99b..3e936f07aa 100644 --- a/core/src/com/unciv/logic/civilization/CivilizationInfo.kt +++ b/core/src/com/unciv/logic/civilization/CivilizationInfo.kt @@ -405,7 +405,7 @@ class CivilizationInfo { } fun getMatchingUniques(uniqueTemplate: String, cityToIgnore: CityInfo? = null) = sequence { - yieldAll(nation.uniqueObjects.asSequence().filter { it.placeholderText == uniqueTemplate }) + yieldAll(nation.getMatchingUniques(uniqueTemplate)) yieldAll(cities.asSequence() .filter { it != cityToIgnore } .flatMap { city -> city.getMatchingUniquesWithNonLocalEffects(uniqueTemplate) } diff --git a/core/src/com/unciv/logic/map/TileInfo.kt b/core/src/com/unciv/logic/map/TileInfo.kt index 16a297c92d..f90ddf1830 100644 --- a/core/src/com/unciv/logic/map/TileInfo.kt +++ b/core/src/com/unciv/logic/map/TileInfo.kt @@ -538,7 +538,7 @@ open class TileInfo { improvement.hasUnique(UniqueType.ImprovementBuildableByFreshWater) && isAdjacentToFreshwater -> true // If an unique of this type exists, we want all to match (e.g. Hill _and_ Forest would be meaningful). - improvement.uniqueObjects.filter { it.placeholderText == "Can only be built on [] tiles" }.let { + improvement.getMatchingUniques("Can only be built on [] tiles").let { it.any() && it.all { unique -> matchesTerrainFilter(unique.params[0]) } } -> true diff --git a/core/src/com/unciv/logic/map/UnitPromotions.kt b/core/src/com/unciv/logic/map/UnitPromotions.kt index d898467f60..40e8a414d5 100644 --- a/core/src/com/unciv/logic/map/UnitPromotions.kt +++ b/core/src/com/unciv/logic/map/UnitPromotions.kt @@ -68,7 +68,7 @@ class UnitPromotions { val promotion = ruleset.unitPromotions[promotionName]!! doDirectPromotionEffects(promotion) - if (promotion.uniqueObjects.none { it.placeholderText == "Doing so will consume this opportunity to choose a Promotion" }) + if (!promotion.hasUnique("Doing so will consume this opportunity to choose a Promotion")) promotions.add(promotionName) unit.updateUniques(ruleset) diff --git a/core/src/com/unciv/logic/trade/TradeEvaluation.kt b/core/src/com/unciv/logic/trade/TradeEvaluation.kt index 4dc8f2113d..06aad197a8 100644 --- a/core/src/com/unciv/logic/trade/TradeEvaluation.kt +++ b/core/src/com/unciv/logic/trade/TradeEvaluation.kt @@ -277,7 +277,7 @@ class TradeEvaluation { } private fun introductionValue(ruleSet: Ruleset): Int { - val unique = ruleSet.modOptions.uniqueObjects.firstOrNull{ it.placeholderText == ModOptionsConstants.tradeCivIntroductions } + val unique = ruleSet.modOptions.getMatchingUniques(ModOptionsConstants.tradeCivIntroductions).firstOrNull() if (unique == null) return 0 return unique.params[0].toInt() } diff --git a/core/src/com/unciv/logic/trade/TradeLogic.kt b/core/src/com/unciv/logic/trade/TradeLogic.kt index 6dd2da6e9c..ffc52c950b 100644 --- a/core/src/com/unciv/logic/trade/TradeLogic.kt +++ b/core/src/com/unciv/logic/trade/TradeLogic.kt @@ -48,7 +48,7 @@ class TradeLogic(val ourCivilization:CivilizationInfo, val otherCivilization: Ci val otherCivsWeKnow = civInfo.getKnownCivs() .filter { it.civName != otherCivilization.civName && it.isMajorCiv() && !it.isDefeated() } - if (civInfo.gameInfo.ruleSet.modOptions.uniqueObjects.any{ it.placeholderText == ModOptionsConstants.tradeCivIntroductions }) { + if (civInfo.gameInfo.ruleSet.modOptions.hasUnique(ModOptionsConstants.tradeCivIntroductions)) { val civsWeKnowAndTheyDont = otherCivsWeKnow .filter { !otherCivilization.diplomacy.containsKey(it.civName) && !it.isDefeated() } for (thirdCiv in civsWeKnowAndTheyDont) { @@ -57,7 +57,7 @@ class TradeLogic(val ourCivilization:CivilizationInfo, val otherCivilization: Ci } if (!civInfo.isCityState() && !otherCivilization.isCityState() - && !civInfo.gameInfo.ruleSet.modOptions.uniques.contains(ModOptionsConstants.diplomaticRelationshipsCannotChange)) { + && !civInfo.gameInfo.ruleSet.modOptions.hasUnique(ModOptionsConstants.diplomaticRelationshipsCannotChange)) { val civsWeBothKnow = otherCivsWeKnow .filter { otherCivilization.diplomacy.containsKey(it.civName) } val civsWeArentAtWarWith = civsWeBothKnow diff --git a/core/src/com/unciv/models/ruleset/Building.kt b/core/src/com/unciv/models/ruleset/Building.kt index d1a59d2684..cca9db3eba 100644 --- a/core/src/com/unciv/models/ruleset/Building.kt +++ b/core/src/com/unciv/models/ruleset/Building.kt @@ -763,9 +763,8 @@ class Building : RulesetStatsObject(), INonPerpetualConstruction { } fun getImprovement(ruleset: Ruleset): TileImprovement? { - val improvementUnique = uniqueObjects - .firstOrNull { it.placeholderText == "Creates a [] improvement on a specific tile" } - ?: return null + val improvementUnique = getMatchingUniques("Creates a [] improvement on a specific tile") + .firstOrNull() ?: return null return ruleset.tileImprovements[improvementUnique.params[0]] } diff --git a/core/src/com/unciv/models/ruleset/Ruleset.kt b/core/src/com/unciv/models/ruleset/Ruleset.kt index 8a56530e7c..14aa198342 100644 --- a/core/src/com/unciv/models/ruleset/Ruleset.kt +++ b/core/src/com/unciv/models/ruleset/Ruleset.kt @@ -575,8 +575,8 @@ class Ruleset { if (building.requiredBuildingInAllCities != null) lines.add("${building.name} contains 'requiredBuildingInAllCities' - please convert to a \"" + UniqueType.RequiresBuildingInAllCities.text.fillPlaceholders(building.requiredBuildingInAllCities!!)+"\" unique", RulesetErrorSeverity.Warning) - for (unique in building.uniqueObjects) - if (unique.placeholderText == "Creates a [] improvement on a specific tile" && !tileImprovements.containsKey(unique.params[0])) + for (unique in building.getMatchingUniques("Creates a [] improvement on a specific tile")) + if (!tileImprovements.containsKey(unique.params[0])) lines += "${building.name} creates a ${unique.params[0]} improvement which does not exist!" checkUniques(building, lines, rulesetSpecific, forOptionsPopup) } diff --git a/core/src/com/unciv/models/ruleset/tech/Technology.kt b/core/src/com/unciv/models/ruleset/tech/Technology.kt index 489606d087..d8147905b5 100644 --- a/core/src/com/unciv/models/ruleset/tech/Technology.kt +++ b/core/src/com/unciv/models/ruleset/tech/Technology.kt @@ -138,7 +138,7 @@ class Technology: RulesetObject() { .filter { it.requiredTech == name && (it.uniqueTo == civInfo.civName || it.uniqueTo==null && civInfo.getEquivalentUnit(it) == it) - && (nuclearWeaponsEnabled || it.uniqueObjects.none { unique -> unique.placeholderText == "Nuclear weapon of Strength []" }) + && (nuclearWeaponsEnabled || !it.hasUnique("Nuclear weapon of Strength []")) && (religionEnabled || !it.hasUnique(UniqueType.HiddenWithoutReligion)) && !it.hasUnique(UniqueType.HiddenFromCivilopedia) } diff --git a/core/src/com/unciv/models/ruleset/unique/UniqueTriggerActivation.kt b/core/src/com/unciv/models/ruleset/unique/UniqueTriggerActivation.kt index 627172360f..9af6153160 100644 --- a/core/src/com/unciv/models/ruleset/unique/UniqueTriggerActivation.kt +++ b/core/src/com/unciv/models/ruleset/unique/UniqueTriggerActivation.kt @@ -125,20 +125,16 @@ object UniqueTriggerActivation { OneTimeFreeGreatPerson, MayanGainGreatPerson -> { if (civInfo.isSpectator()) return false val greatPeople = civInfo.getGreatPeople() - if (unique.type == MayanGainGreatPerson) { - if (civInfo.greatPeople.longCountGPPool.isEmpty()) - // replenish maya GP pool when dry - civInfo.greatPeople.longCountGPPool = greatPeople.map { it.name }.toHashSet() - } + if (unique.type == MayanGainGreatPerson && civInfo.greatPeople.longCountGPPool.isEmpty()) + civInfo.greatPeople.longCountGPPool = greatPeople.map { it.name }.toHashSet() if (civInfo.isPlayerCivilization()) { civInfo.greatPeople.freeGreatPeople++ + // Anyone an idea for a good icon? if (unique.type == MayanGainGreatPerson) { civInfo.greatPeople.mayaLimitedFreeGP++ civInfo.addNotification(notification!!, MayaLongCountAction(), MayaCalendar.notificationIcon) - } else { - if (notification != null) - civInfo.addNotification(notification) // Anyone an idea for a good icon? - } + } else if (notification != null) + civInfo.addNotification(notification) return true } else { if (unique.type == MayanGainGreatPerson) @@ -147,6 +143,7 @@ object UniqueTriggerActivation { var greatPerson = greatPeople.random() val preferredVictoryType = civInfo.victoryType() + if (preferredVictoryType == VictoryType.Cultural) { val culturalGP = greatPeople.firstOrNull { it.uniques.contains("Great Person - [Culture]") } diff --git a/core/src/com/unciv/models/ruleset/unit/BaseUnit.kt b/core/src/com/unciv/models/ruleset/unit/BaseUnit.kt index 22c2f4447e..34417905d3 100644 --- a/core/src/com/unciv/models/ruleset/unit/BaseUnit.kt +++ b/core/src/com/unciv/models/ruleset/unit/BaseUnit.kt @@ -557,9 +557,9 @@ class BaseUnit : RulesetObject(), INonPerpetualConstruction { } } - fun isGreatPerson() = uniqueObjects.any { it.placeholderText == "Great Person - []" } + fun isGreatPerson() = hasUnique("Great Person - []") - fun isNuclearWeapon() = uniqueObjects.any { it.placeholderText == "Nuclear weapon of Strength []" } + fun isNuclearWeapon() = hasUnique("Nuclear weapon of Strength []") fun movesLikeAirUnits() = getType().getMovementType() == UnitMovementType.Air @@ -568,9 +568,8 @@ class BaseUnit : RulesetObject(), INonPerpetualConstruction { private val resourceRequirementsInternal: HashMap by lazy { val resourceRequirements = HashMap() if (requiredResource != null) resourceRequirements[requiredResource!!] = 1 - for (unique in uniqueObjects) - if (unique.isOfType(UniqueType.ConsumesResources)) - resourceRequirements[unique.params[1]] = unique.params[0].toInt() + for (unique in getMatchingUniques(UniqueType.ConsumesResources)) + resourceRequirements[unique.params[1]] = unique.params[0].toInt() resourceRequirements } @@ -629,7 +628,7 @@ class BaseUnit : RulesetObject(), INonPerpetualConstruction { if (hasUnique(UniqueType.SelfDestructs)) power /= 2 - if (uniqueObjects.any { it.placeholderText =="Nuclear weapon of Strength []" } ) + if (isNuclearWeapon()) power += 4000 // Uniques diff --git a/core/src/com/unciv/models/ruleset/unit/Promotion.kt b/core/src/com/unciv/models/ruleset/unit/Promotion.kt index e7a3c6a205..1b5cc69073 100644 --- a/core/src/com/unciv/models/ruleset/unit/Promotion.kt +++ b/core/src/com/unciv/models/ruleset/unit/Promotion.kt @@ -101,13 +101,11 @@ class Promotion : RulesetObject() { } val grantors = ruleset.buildings.values.filter { - building -> building.uniqueObjects.any { - it.placeholderText == "All newly-trained [] units [] receive the [] promotion" - && it.params[2] == name - } + building -> building.getMatchingUniques("All newly-trained [] units [] receive the [] promotion") + .any { it.params[2] == name } } + ruleset.terrains.values.filter { - terrain -> terrain.uniqueObjects.any { - it.isOfType(UniqueType.TerrainGrantsPromotion) && name == it.params[0] + terrain -> terrain.getMatchingUniques(UniqueType.TerrainGrantsPromotion).any { + name == it.params[0] } } if (grantors.isNotEmpty()) {