mirror of
https://github.com/yairm210/Unciv.git
synced 2025-01-25 10:26:05 +07:00
Conditional for building in amount of cities (#11101)
* Conditional for building in amount of cities * fix order of operations * Deprecate old require in amount cities uniques * import * Fix referring to the unique instead of the conditional * Fix yield message * I have no clue how this isn't imported, but I'mma assume this translates fine anyways * Rename text for unique * revert unique text * Whoops * Remove unnecessary puppet check * Move additional description to it own function * Split missing city text into its own function * Move ToDo comment * flip to be easier to read * Move onlyAvailable rejections to its own function to be easier to work with * Add in the word "of"
This commit is contained in:
parent
df7072b550
commit
5730d1b80a
@ -252,7 +252,7 @@
|
||||
"happiness": 5,
|
||||
"culture": 1,
|
||||
"isNationalWonder": true,
|
||||
"uniques": ["Requires a [Colosseum] in all cities", "Cost increases by [30] per owned city"],
|
||||
"uniques": ["Only available <if [Colosseum] is constructed in all [non-[Puppeted]] cities>", "Cost increases by [30] per owned city"],
|
||||
"requiredTech": "Horseback Riding"
|
||||
},
|
||||
{
|
||||
@ -328,7 +328,7 @@
|
||||
"culture": 1,
|
||||
"isNationalWonder": true,
|
||||
"percentStatBonus": {"science": 50},
|
||||
"uniques": ["Requires a [Library] in all cities", "Cost increases by [30] per owned city"],
|
||||
"uniques": ["Only available <if [Library] is constructed in all [non-[Puppeted]] cities>", "Cost increases by [30] per owned city"],
|
||||
"requiredTech": "Philosophy"
|
||||
},
|
||||
{
|
||||
@ -355,7 +355,7 @@
|
||||
"cost": 125,
|
||||
"culture": 1,
|
||||
"isNationalWonder": true,
|
||||
"uniques": ["Requires a [Monument] in all cities", "[+25]% Great Person generation [in this city]", "Cost increases by [30] per owned city"],
|
||||
"uniques": ["Only available <if [Monument] is constructed in all [non-[Puppeted]] cities>", "[+25]% Great Person generation [in this city]", "Cost increases by [30] per owned city"],
|
||||
"requiredTech": "Drama and Poetry"
|
||||
},
|
||||
{
|
||||
@ -417,7 +417,7 @@
|
||||
"cost": 125,
|
||||
"culture": 1,
|
||||
"isNationalWonder": true,
|
||||
"uniques": ["Requires a [Barracks] in all cities", "All newly-trained [non-[Air]] units [in this city] receive the [Morale] promotion",
|
||||
"uniques": ["Only available <if [Barracks] is constructed in all [non-[Puppeted]] cities>", "All newly-trained [non-[Air]] units [in this city] receive the [Morale] promotion",
|
||||
"Cost increases by [30] per owned city"],
|
||||
"requiredTech": "Iron Working"
|
||||
},
|
||||
@ -468,7 +468,7 @@
|
||||
"cost": 125,
|
||||
"culture": 1,
|
||||
"faith": 8,
|
||||
"uniques": ["Requires a [Temple] in all cities", "Cost increases by [30] per owned city",
|
||||
"uniques": ["Only available <if [Temple] is constructed in all [non-[Puppeted]] cities>", "Cost increases by [30] per owned city",
|
||||
"[+100]% Natural religion spread [in this city]", "Hidden when religion is disabled", "Can only be built [in holy cities]"],
|
||||
"requiredTech": "Theology",
|
||||
"isNationalWonder": true
|
||||
@ -489,7 +489,7 @@
|
||||
"gold": 8,
|
||||
"culture": 1,
|
||||
"isNationalWonder": true,
|
||||
"uniques": ["Requires a [Market] in all cities", "Cost increases by [30] per owned city"],
|
||||
"uniques": ["Only available <if [Market] is constructed in all [non-[Puppeted]] cities>", "Cost increases by [30] per owned city"],
|
||||
"requiredTech": "Guilds"
|
||||
},
|
||||
{
|
||||
@ -572,7 +572,7 @@
|
||||
"science": 3,
|
||||
"culture": 1,
|
||||
"isNationalWonder": true,
|
||||
"uniques": ["Requires a [University] in all cities", "Free Technology", "Cost increases by [30] per owned city"],
|
||||
"uniques": ["Only available <if [University] is constructed in all [non-[Puppeted]] cities>", "Free Technology", "Cost increases by [30] per owned city"],
|
||||
"requiredTech": "Education"
|
||||
},
|
||||
{
|
||||
@ -623,7 +623,7 @@
|
||||
"production": 8,
|
||||
"culture": 1,
|
||||
"isNationalWonder": true,
|
||||
"uniques": ["Requires a [Workshop] in all cities", "Cost increases by [30] per owned city"],
|
||||
"uniques": ["Only available <if [Workshop] is constructed in all [non-[Puppeted]] cities>", "Cost increases by [30] per owned city"],
|
||||
"requiredTech": "Machinery"
|
||||
},
|
||||
{
|
||||
@ -774,7 +774,7 @@
|
||||
"percentStatBonus": {"culture": 50},
|
||||
"culture": 5,
|
||||
"isNationalWonder": true,
|
||||
"uniques": ["Requires a [Opera House] in all cities", "Cost increases by [30] per owned city"],
|
||||
"uniques": ["Only available <if [Opera House] is constructed in all [non-[Puppeted]] cities>", "Cost increases by [30] per owned city"],
|
||||
"requiredTech": "Architecture"
|
||||
},
|
||||
{
|
||||
|
@ -246,7 +246,7 @@
|
||||
"happiness": 5,
|
||||
"culture": 1,
|
||||
"isNationalWonder": true,
|
||||
"uniques": ["Requires a [Colosseum] in all cities", "Cost increases by [30] per owned city"],
|
||||
"uniques": ["Only available <if [Colosseum] is constructed in all [non-[Puppeted]] cities>", "Cost increases by [30] per owned city"],
|
||||
"requiredTech": "Construction"
|
||||
},
|
||||
{
|
||||
@ -300,7 +300,7 @@
|
||||
"culture": 1,
|
||||
"isNationalWonder": true,
|
||||
"percentStatBonus": {"science": 50},
|
||||
"uniques": ["Requires a [Library] in all cities", "Cost increases by [30] per owned city"],
|
||||
"uniques": ["Only available <if [Library] is constructed in all [non-[Puppeted]] cities>", "Cost increases by [30] per owned city"],
|
||||
"requiredTech": "Philosophy"
|
||||
},
|
||||
{
|
||||
@ -317,7 +317,7 @@
|
||||
"cost": 125,
|
||||
"culture": 1,
|
||||
"isNationalWonder": true,
|
||||
"uniques": ["Requires a [Monument] in all cities", "[+25]% Great Person generation [in this city]", "Cost increases by [30] per owned city"],
|
||||
"uniques": ["Only available <if [Monument] is constructed in all [non-[Puppeted]] cities>", "[+25]% Great Person generation [in this city]", "Cost increases by [30] per owned city"],
|
||||
"requiredTech": "Philosophy"
|
||||
},
|
||||
{
|
||||
@ -360,7 +360,7 @@
|
||||
"cost": 125,
|
||||
"culture": 1,
|
||||
"isNationalWonder": true,
|
||||
"uniques": ["Requires a [Barracks] in all cities", "All newly-trained [non-[Air]] units [in this city] receive the [Morale] promotion",
|
||||
"uniques": ["Only available <if [Barracks] is constructed in all [non-[Puppeted]] cities>", "All newly-trained [non-[Air]] units [in this city] receive the [Morale] promotion",
|
||||
"Cost increases by [30] per owned city"],
|
||||
"requiredTech": "Iron Working"
|
||||
},
|
||||
@ -426,7 +426,7 @@
|
||||
"gold": 8,
|
||||
"culture": 1,
|
||||
"isNationalWonder": true,
|
||||
"uniques": ["Requires a [Market] in all cities", "Cost increases by [30] per owned city"],
|
||||
"uniques": ["Only available <if [Market] is constructed in all [non-[Puppeted]] cities>", "Cost increases by [30] per owned city"],
|
||||
"requiredTech": "Currency"
|
||||
},
|
||||
{
|
||||
@ -509,7 +509,7 @@
|
||||
"science": 3,
|
||||
"culture": 1,
|
||||
"isNationalWonder": true,
|
||||
"uniques": ["Requires a [University] in all cities", "Free Technology", "Cost increases by [30] per owned city"],
|
||||
"uniques": ["Only available <if [University] is constructed in all [non-[Puppeted]] cities>", "Free Technology", "Cost increases by [30] per owned city"],
|
||||
"requiredTech": "Education"
|
||||
},
|
||||
{
|
||||
@ -559,7 +559,7 @@
|
||||
"production": 8,
|
||||
"culture": 1,
|
||||
"isNationalWonder": true,
|
||||
"uniques": ["Requires a [Workshop] in all cities", "Cost increases by [30] per owned city"],
|
||||
"uniques": ["Only available <if [Workshop] is constructed in all [non-[Puppeted]] cities>", "Cost increases by [30] per owned city"],
|
||||
"requiredTech": "Machinery"
|
||||
},
|
||||
{
|
||||
@ -656,7 +656,7 @@
|
||||
"percentStatBonus": {"culture": 50},
|
||||
"culture": 5,
|
||||
"isNationalWonder": true,
|
||||
"uniques": ["Requires a [Opera House] in all cities", "Cost increases by [30] per owned city"],
|
||||
"uniques": ["Only available <if [Opera House] is constructed in all [non-[Puppeted]] cities>", "Cost increases by [30] per owned city"],
|
||||
"requiredTech": "Acoustics"
|
||||
},
|
||||
{
|
||||
|
@ -8,6 +8,7 @@ import com.unciv.logic.civilization.Civilization
|
||||
import com.unciv.models.Counter
|
||||
import com.unciv.models.ruleset.tile.ResourceType
|
||||
import com.unciv.models.ruleset.tile.TileImprovement
|
||||
import com.unciv.models.ruleset.unique.Conditionals
|
||||
import com.unciv.models.ruleset.unique.LocalUniqueCache
|
||||
import com.unciv.models.ruleset.unique.StateForConditionals
|
||||
import com.unciv.models.ruleset.unique.Unique
|
||||
@ -256,8 +257,7 @@ class Building : RulesetStatsObject(), INonPerpetualConstruction {
|
||||
yield(RejectionReasonType.Unbuildable.toInstance())
|
||||
|
||||
UniqueType.OnlyAvailable ->
|
||||
if (!unique.conditionalsApply(civ, cityConstructions.city))
|
||||
yield(RejectionReasonType.ShouldNotBeDisplayed.toInstance())
|
||||
yieldAll(onlyAvailableRejections(unique, cityConstructions))
|
||||
|
||||
UniqueType.Unavailable ->
|
||||
yield(RejectionReasonType.ShouldNotBeDisplayed.toInstance())
|
||||
@ -428,6 +428,43 @@ class Building : RulesetStatsObject(), INonPerpetualConstruction {
|
||||
}
|
||||
}
|
||||
|
||||
private fun onlyAvailableRejections(unique: Unique, cityConstructions: CityConstructions): Sequence<RejectionReason> = sequence {
|
||||
val civ = cityConstructions.city.civ
|
||||
for (conditional in unique.conditionals) {
|
||||
if (Conditionals.conditionalApplies(unique, conditional, StateForConditionals(civ, cityConstructions.city)))
|
||||
continue
|
||||
when (conditional.type) {
|
||||
UniqueType.ConditionalBuildingBuiltAmount -> {
|
||||
val building = civ.getEquivalentBuilding(conditional.params[0]).name
|
||||
val amount = conditional.params[1].toInt()
|
||||
val cityFilter = conditional.params[2]
|
||||
val numberOfCities = civ.cities.count {
|
||||
it.cityConstructions.containsBuildingOrEquivalent(building) && it.matchesFilter(cityFilter)
|
||||
}
|
||||
if (numberOfCities < amount)
|
||||
{
|
||||
yield(RejectionReasonType.RequiresBuildingInSomeCities.toInstance(
|
||||
"Requires a [$building] in at least [$amount] cities" +
|
||||
" ($numberOfCities/$numberOfCities)"))
|
||||
}
|
||||
}
|
||||
UniqueType.ConditionalBuildingBuiltAll -> {
|
||||
val building = civ.getEquivalentBuilding(conditional.params[0]).name
|
||||
val cityFilter = conditional.params[1]
|
||||
if(civ.cities.any { it.matchesFilter(cityFilter)
|
||||
!it.isPuppet && !it.cityConstructions.containsBuildingOrEquivalent(building)
|
||||
}) {
|
||||
yield(RejectionReasonType.RequiresBuildingInAllCities.toInstance(
|
||||
"Requires a [${building}] in all cities"))
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
yield(RejectionReasonType.ShouldNotBeDisplayed.toInstance())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun isBuildable(cityConstructions: CityConstructions): Boolean =
|
||||
getRejectionReasons(cityConstructions).none()
|
||||
|
||||
|
@ -165,6 +165,12 @@ object Conditionals {
|
||||
|
||||
UniqueType.ConditionalBuildingBuilt ->
|
||||
checkOnCiv { cities.any { it.cityConstructions.containsBuildingOrEquivalent(condition.params[0]) } }
|
||||
UniqueType.ConditionalBuildingBuiltAll ->
|
||||
checkOnCiv { cities.filter { it.matchesFilter(condition.params[1]) }.all {
|
||||
it.cityConstructions.containsBuildingOrEquivalent(condition.params[0]) } }
|
||||
UniqueType.ConditionalBuildingBuiltAmount ->
|
||||
checkOnCiv { cities.count { it.cityConstructions.containsBuildingOrEquivalent(condition.params[0])
|
||||
&& it.matchesFilter(condition.params[2]) } >= condition.params[1].toInt() }
|
||||
UniqueType.ConditionalBuildingBuiltByAnybody ->
|
||||
checkOnGameInfo { getCities().any { it.cityConstructions.containsBuildingOrEquivalent(condition.params[0]) } }
|
||||
|
||||
|
@ -283,8 +283,10 @@ enum class UniqueType(
|
||||
CostIncreasesPerCity("Cost increases by [amount] per owned city", UniqueTarget.Building, UniqueTarget.Unit),
|
||||
CostIncreasesWhenBuilt("Cost increases by [amount] when built", UniqueTarget.Building, UniqueTarget.Unit),
|
||||
|
||||
@Deprecated("as of 4.10.17", ReplaceWith("Only available <if [buildingFilter] is constructed in all [non-[Puppeted]] cities>"))
|
||||
RequiresBuildingInAllCities("Requires a [buildingFilter] in all cities", UniqueTarget.Building),
|
||||
RequiresBuildingInSomeCities("Requires a [buildingFilter] in at least [amount] cities", UniqueTarget.Building),
|
||||
@Deprecated("as of 4.10.17", ReplaceWith("Only available <if [buildingFilter] is constructed in at least [positiveAmount] of [All] cities>"))
|
||||
RequiresBuildingInSomeCities("Requires a [buildingFilter] in at least [positiveAmount] cities", UniqueTarget.Building),
|
||||
CanOnlyBeBuiltInCertainCities("Can only be built [cityFilter]", UniqueTarget.Building),
|
||||
|
||||
MustHaveOwnedWithinTiles("Must have an owned [tileFilter] within [amount] tiles", UniqueTarget.Building),
|
||||
@ -642,6 +644,8 @@ enum class UniqueType(
|
||||
ConditionalAfterGeneratingGreatProphet("after generating a Great Prophet", UniqueTarget.Conditional),
|
||||
|
||||
ConditionalBuildingBuilt("if [buildingFilter] is constructed", UniqueTarget.Conditional),
|
||||
ConditionalBuildingBuiltAll("if [buildingFilter] is constructed in all [cityFilter] cities", UniqueTarget.Conditional),
|
||||
ConditionalBuildingBuiltAmount("if [buildingFilter] is constructed in at least [positiveAmount] of [cityFilter] cities", UniqueTarget.Conditional),
|
||||
ConditionalBuildingBuiltByAnybody("if [buildingFilter] is constructed by anybody", UniqueTarget.Conditional),
|
||||
|
||||
ConditionalWithResource("with [resource]", UniqueTarget.Conditional),
|
||||
|
@ -45,7 +45,6 @@ object BuildingDescriptions {
|
||||
val isFree = city.civ.civConstructions.hasFreeBuilding(city, this)
|
||||
if (uniqueTo != null) translatedLines += if (replaces == null) "Unique to [$uniqueTo]".tr()
|
||||
else "Unique to [$uniqueTo], replaces [$replaces]".tr()
|
||||
val missingUnique = getMatchingUniques(UniqueType.RequiresBuildingInAllCities).firstOrNull()
|
||||
if (isWonder) translatedLines += "Wonder".tr()
|
||||
if (isNationalWonder) translatedLines += "National Wonder".tr()
|
||||
if (!isFree) {
|
||||
@ -59,21 +58,9 @@ object BuildingDescriptions {
|
||||
}
|
||||
}
|
||||
|
||||
// Inefficient in theory. In practice, buildings seem to have only a small handful of uniques.
|
||||
val missingCities = if (missingUnique != null)
|
||||
// TODO: Unify with rejection reasons?
|
||||
city.civ.cities.filterNot {
|
||||
it.isPuppet
|
||||
|| it.cityConstructions.containsBuildingOrEquivalent(missingUnique.params[0])
|
||||
}
|
||||
else listOf()
|
||||
if (uniques.isNotEmpty()) {
|
||||
if (replacementTextForUniques.isNotEmpty()) translatedLines += replacementTextForUniques.tr()
|
||||
else translatedLines += getUniquesStringsWithoutDisablers(
|
||||
filterUniques = if (missingCities.isEmpty()) null
|
||||
else { unique -> unique.type != 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.
|
||||
).map { it.tr() }
|
||||
else translatedLines += getUniquesStringsWithoutDisablers().map { it.tr() }
|
||||
}
|
||||
if (!stats.isEmpty())
|
||||
translatedLines += stats.toString()
|
||||
@ -93,16 +80,38 @@ object BuildingDescriptions {
|
||||
if (cityStrength != 0) translatedLines += "{City strength} +$cityStrength".tr()
|
||||
if (cityHealth != 0) translatedLines += "{City health} +$cityHealth".tr()
|
||||
if (maintenance != 0 && !isFree) translatedLines += "{Maintenance cost}: $maintenance {Gold}".tr()
|
||||
if (showAdditionalInfo && missingCities.isNotEmpty()) {
|
||||
// Could be red. But IMO that should be done by enabling GDX's ColorMarkupLanguage globally instead of adding a separate label.
|
||||
translatedLines += "\n" +
|
||||
"[${city.civ.getEquivalentBuilding(missingUnique!!.params[0])}] required:".tr() +
|
||||
" " + missingCities.joinToString(", ") { it.name.tr(hideIcons = true) }
|
||||
// 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.
|
||||
}
|
||||
if (showAdditionalInfo) additionalDecription(building, city, translatedLines)
|
||||
return translatedLines.joinToString("\n").trim()
|
||||
}
|
||||
|
||||
fun additionalDecription (building: Building, city: City, lines: ArrayList<String>) {
|
||||
// Inefficient in theory. In practice, buildings seem to have only a small handful of uniques.
|
||||
for (unique in building.uniqueObjects) {
|
||||
if (unique.type == UniqueType.RequiresBuildingInAllCities) {
|
||||
missingCityText(unique.params[0], city, "non-[Puppeted]", lines)
|
||||
}
|
||||
|
||||
else if (unique.type == UniqueType.OnlyAvailable)
|
||||
for (conditional in unique.conditionals) {
|
||||
if (conditional.type == UniqueType.ConditionalBuildingBuiltAll) {
|
||||
missingCityText(conditional.params[0], city, conditional.params[1], lines)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Unify with rejection reasons?
|
||||
fun missingCityText (building: String, city: City, filter: String, lines: ArrayList<String>) {
|
||||
val missingCities = city.civ.cities.filter {
|
||||
it.matchesFilter(filter) && !it.cityConstructions.containsBuildingOrEquivalent(building)
|
||||
}
|
||||
// Could be red. But IMO that should be done by enabling GDX's ColorMarkupLanguage globally instead of adding a separate label.
|
||||
if (missingCities.isNotEmpty()) lines += "\n" +
|
||||
"[${city.civ.getEquivalentBuilding(building)}] required:".tr() +
|
||||
" " + missingCities.joinToString(", ") { it.name.tr(hideIcons = true) }
|
||||
// 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.
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists differences: how a nation-unique Building compares to its replacement.
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user