Fixed a bug where 'requires a [buildingName] in this city' would not work (#5754)

This commit is contained in:
Xander Lenstra 2021-12-05 11:55:46 +01:00 committed by GitHub
parent 936a32300b
commit b6ce8b2aac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 32 additions and 16 deletions

View File

@ -127,6 +127,8 @@ class RejectionReasons: HashSet<RejectionReason>() {
}
// TODO: Put a wrapper class around this containing the errorMessage, so that we don't
// change the value of a enum constant sometimes.
enum class RejectionReason(val shouldShow: Boolean, var errorMessage: String) {
AlreadyBuilt(false, "Building already built in this city"),
Unbuildable(false, "Unbuildable"),

View File

@ -122,13 +122,13 @@ class Building : RulesetStatsObject(), INonPerpetualConstruction {
else (name in cityInfo.civInfo.civConstructions.getFreeBuildings(cityInfo.id))
if (uniqueTo != null) lines += if (replaces == null) "Unique to [$uniqueTo]"
else "Unique to [$uniqueTo], replaces [$replaces]"
val missingunique = uniqueObjects.firstOrNull{ it.placeholderText == "Requires a [] in all cities" }
val missingUnique = getMatchingUniques(UniqueType.RequiresBuildingInAllCities).firstOrNull()
// Inefficient in theory. In practice, buildings seem to have only a small handful of uniques.
val missingcities = if (cityInfo != null && missingunique != null)
val missingCities = if (cityInfo != null && missingUnique != null)
// TODO: Unify with rejection reasons?
cityInfo.civInfo.cities.filterNot {
it.isPuppet
|| it.cityConstructions.containsBuildingOrEquivalent(missingunique.params[0])
|| it.cityConstructions.containsBuildingOrEquivalent(missingUnique.params[0])
}
else listOf<CityInfo>()
if (isWonder) lines += "Wonder"
@ -142,8 +142,8 @@ class Building : RulesetStatsObject(), INonPerpetualConstruction {
if (uniques.isNotEmpty()) {
if (replacementTextForUniques != "") lines += replacementTextForUniques
else lines += getUniquesStringsWithoutDisablers(
filterUniques=if (missingcities.isEmpty()) null
else { unique -> unique.placeholderText != "Requires a [] in all cities" }
filterUniques=if (missingCities.isEmpty()) null
else { unique -> !unique.isOfType(UniqueType.RequiresBuildingInAllCities) }
// Filter out the "Requires a [] in all cities" unique if any cities are still missing the required building, since in that case the list of cities will be appended at the end.
)
}
@ -165,9 +165,11 @@ class Building : RulesetStatsObject(), INonPerpetualConstruction {
if (cityStrength != 0) lines += "{City strength} +$cityStrength"
if (cityHealth != 0) lines += "{City health} +$cityHealth"
if (maintenance != 0 && !isFree) lines += "{Maintenance cost}: $maintenance {Gold}"
if (!missingcities.isEmpty()) {
if (missingCities.isNotEmpty()) {
// Could be red. But IMO that should be done by enabling GDX's ColorMarkupLanguage globally instead of adding a separate label.
lines += "\n" + "[${cityInfo?.civInfo?.getEquivalentBuilding(missingunique!!.params[0])}] required:".tr() + " " + missingcities.map{ "{${it.name}}" }.joinToString(", ")
lines += "\n" +
"[${cityInfo?.civInfo?.getEquivalentBuilding(missingUnique!!.params[0])}] required:".tr() +
" " + missingCities.joinToString(", ") { "{${it.name}}" }
// Can't nest square bracket placeholders inside curlies, and don't see any way to define wildcard placeholders. So run translation explicitly on base text.
}
return lines.joinToString("\n") { it.tr() }.trim()
@ -637,8 +639,8 @@ class Building : RulesetStatsObject(), INonPerpetualConstruction {
rejectionReasons.add(RejectionReason.ReachedBuildCap)
}
for (unique in uniqueObjects) when (unique.placeholderText) {
UniqueType.RequiresAnotherBuilding.text -> {
for (unique in uniqueObjects) when (unique.type) {
UniqueType.RequiresAnotherBuilding -> {
val filter = unique.params[0]
if (civInfo.gameInfo.ruleSet.buildings.containsKey(filter) && !cityConstructions.containsBuildingOrEquivalent(filter))
rejectionReasons.add(
@ -647,7 +649,7 @@ class Building : RulesetStatsObject(), INonPerpetualConstruction {
)
}
"Requires a [] in all cities" -> {
UniqueType.RequiresBuildingInAllCities -> {
val filter = unique.params[0]
if (civInfo.gameInfo.ruleSet.buildings.containsKey(filter)
&& civInfo.cities.any {
@ -663,11 +665,11 @@ class Building : RulesetStatsObject(), INonPerpetualConstruction {
}
}
"Hidden until [] social policy branches have been completed" -> {
UniqueType.HiddenBeforeAmountPolicies -> {
if (cityConstructions.cityInfo.civInfo.getCompletedPolicyBranchesCount() < unique.params[0].toInt())
rejectionReasons.add(RejectionReason.MorePolicyBranches.apply { errorMessage = unique.text })
}
"Hidden when [] Victory is disabled" -> {
UniqueType.HiddenWithoutVictoryType -> {
if (!civInfo.gameInfo.gameParameters.victoryTypes.contains(VictoryType.valueOf(unique.params[0])))
rejectionReasons.add(RejectionReason.HiddenWithoutVictory.apply { errorMessage = unique.text })
}

View File

@ -2,6 +2,7 @@ package com.unciv.models.ruleset.unique
import com.unciv.models.ruleset.BeliefType
import com.unciv.models.ruleset.Ruleset
import com.unciv.models.ruleset.VictoryType
import com.unciv.models.ruleset.tile.ResourceType
import com.unciv.models.ruleset.tile.TerrainType
import com.unciv.models.stats.Stat
@ -254,6 +255,15 @@ enum class UniqueParameterType(val parameterName:String) {
}
}
},
VictoryT("victoryType") {
override fun getErrorSeverity(
parameterText: String,
ruleset: Ruleset
): UniqueType.UniqueComplianceErrorSeverity? {
return if (parameterText in VictoryType.values().map { it.name }) null
else UniqueType.UniqueComplianceErrorSeverity.RulesetInvariant
}
},
/** Behaves like [Unknown], but states explicitly the parameter is OK and its contents are ignored */
Comment("comment") {
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):

View File

@ -186,6 +186,7 @@ enum class UniqueType(val text:String, vararg targets: UniqueTarget, val flags:
CanBePurchasedWithStat("Can be purchased with [stat] [cityFilter]", UniqueTarget.Building, UniqueTarget.Unit),
CanBePurchasedForAmountStat("Can be purchased for [amount] [stat] [cityFilter]", UniqueTarget.Building, UniqueTarget.Unit),
MaxNumberBuildable("Limited to [amount] per Civilization", UniqueTarget.Building, UniqueTarget.Unit),
HiddenBeforeAmountPolicies("Hidden until [amount] social policy branches have been completed", UniqueTarget.Building, UniqueTarget.Unit),
//endregion
@ -196,6 +197,7 @@ enum class UniqueType(val text:String, vararg targets: UniqueTarget, val flags:
CostIncreasesPerCity("Cost increases by [amount] per owned city", UniqueTarget.Building),
CannotBeBuiltWith("Cannot be built with [buildingName]", UniqueTarget.Building),
RequiresAnotherBuilding("Requires a [buildingName] in this city", UniqueTarget.Building),
RequiresBuildingInAllCities("Requires a [buildingName] in all cities", UniqueTarget.Building),
NotDisplayedWithout("Not displayed as an available construction without [buildingName/tech/resource/policy]", UniqueTarget.Building, UniqueTarget.Unit),
//UniqueType added in 3.18.4
@ -444,6 +446,7 @@ enum class UniqueType(val text:String, vararg targets: UniqueTarget, val flags:
HiddenAfterPantheon("Hidden after founding a Pantheon", UniqueTarget.Ruins),
HiddenAfterGreatProphet("Hidden after generating a Great Prophet", UniqueTarget.Ruins),
AvailableAfterCertainTurns("Only available after [amount] turns", UniqueTarget.Ruins),
HiddenWithoutVictoryType("Hidden when [victoryType] Victory is disabled", UniqueTarget.Building, UniqueTarget.Unit),
// region DEPRECATED AND REMOVED

View File

@ -88,9 +88,8 @@ class WonderOverviewTable(
Constants.hideFromCivilopediaUnique in wonder.uniques -> false
wonder.hasUnique(UniqueType.HiddenWithoutReligion) && hideReligionItems -> false
wonder.name in startingObsolete -> false
wonder.uniqueObjects.filter { unique ->
unique.placeholderText == "Hidden when [] Victory is disabled"
}.any { unique ->
wonder.getMatchingUniques(UniqueType.HiddenWithoutVictoryType)
.any { unique ->
!gameInfo.gameParameters.victoryTypes.contains(VictoryType.valueOf(unique.params[0]))
} -> false
else -> wonderEra <= viewerEra