Add additional cityFilters (#11047)

* Add additional cityFilters

* Maybe viewingCiv shouldn't be null

* Studio complains it is unnecessary now

* I'm doomed to forget imports

* Ignore this

* typo
This commit is contained in:
SeventhM 2024-01-30 10:06:36 -08:00 committed by GitHub
parent 5fb3ab268b
commit f7702bd71a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 68 additions and 35 deletions

View File

@ -3,6 +3,7 @@ package com.unciv.logic.city
import com.badlogic.gdx.math.Vector2
import com.unciv.GUI
import com.unciv.logic.IsPartOfGameInfoSerialization
import com.unciv.logic.MultiFilter
import com.unciv.logic.city.managers.CityConquestFunctions
import com.unciv.logic.city.managers.CityEspionageManager
import com.unciv.logic.city.managers.CityExpansionManager
@ -480,17 +481,22 @@ class City : IsPartOfGameInfoSerialization {
}
/** Implements [UniqueParameterType.CityFilter][com.unciv.models.ruleset.unique.UniqueParameterType.CityFilter] */
fun matchesFilter(filter: String, viewingCiv: Civilization = civ): Boolean {
fun matchesFilter(filter: String, viewingCiv: Civilization? = civ): Boolean {
return MultiFilter.multiFilter(filter, { matchesSingleFilter(it, viewingCiv) })
}
private fun matchesSingleFilter(filter: String, viewingCiv: Civilization? = civ): Boolean {
return when (filter) {
"in this city" -> true // Filtered by the way uniques are found
"in all cities" -> true
"in all coastal cities" -> isCoastal()
"in capital" -> isCapital()
"in all non-occupied cities" -> !cityStats.hasExtraAnnexUnhappiness() || isPuppet
"in all cities", "All" -> true
"in your cities", "Your" -> viewingCiv == civ
"in all coastal cities", "Coastal" -> isCoastal()
"in capital", "Capital" -> isCapital()
"in all non-occupied cities", "Non-occupied" -> !cityStats.hasExtraAnnexUnhappiness() || isPuppet
"in all cities with a world wonder" -> cityConstructions.getBuiltBuildings()
.any { it.isWonder }
"in all cities connected to capital" -> isConnectedToCapital()
"in all cities with a garrison" -> isGarrisoned()
"in all cities with a garrison", "Garrisoned" -> isGarrisoned()
"in all cities in which the majority religion is a major religion" ->
religion.getMajorityReligionName() != null
&& religion.getMajorityReligion()!!.isMajorReligion()
@ -498,18 +504,20 @@ class City : IsPartOfGameInfoSerialization {
religion.getMajorityReligionName() != null
&& religion.getMajorityReligion()!!.isEnhancedReligion()
"in non-enemy foreign cities" ->
viewingCiv != civ
viewingCiv != null && viewingCiv != civ
&& !civ.isAtWarWith(viewingCiv)
"in foreign cities" -> viewingCiv != civ
"in annexed cities" -> foundingCiv != civ.civName && !isPuppet
"in puppeted cities" -> isPuppet
"in holy cities" -> isHolyCity()
"in enemy cities", "Enemy" -> civ.isAtWarWith(viewingCiv ?: civ)
"in foreign cities", "Foreign" -> viewingCiv != null && viewingCiv != civ
"in annexed cities", "Annexed" -> foundingCiv != civ.civName && !isPuppet
"in puppeted cities", "Puppeted" -> isPuppet
"in holy cities", "Holy" -> isHolyCity()
"in City-State cities" -> civ.isCityState()
// This is only used in communication to the user indicating that only in cities with this
// religion a unique is active. However, since religion uniques only come from the city itself,
// this will always be true when checked.
"in cities following this religion" -> true
else -> false
"in cities following our religion" -> viewingCiv?.religionManager?.religion == religion.getMajorityReligion()
else -> civ.matchesFilter(filter)
}
}

View File

@ -169,7 +169,15 @@ object Conditionals {
checkOnGameInfo { getCities().any { it.cityConstructions.containsBuildingOrEquivalent(condition.params[0]) } }
// Filtered via city.getMatchingUniques
UniqueType.ConditionalInThisCity -> true
UniqueType.ConditionalInThisCity -> relevantCity != null
UniqueType.ConditionalCityFilter -> checkOnCity { matchesFilter(condition.params[0], relevantCiv) }
UniqueType.ConditionalCityConnected -> checkOnCity { isConnectedToCapital() }
UniqueType.ConditionalCityMajorReligion -> checkOnCity {
religion.getMajorityReligion()?.isMajorReligion() == true }
UniqueType.ConditionalCityEnhancedReligion -> checkOnCity {
religion.getMajorityReligion()?.isEnhancedReligion() == true }
UniqueType.ConditionalCityThisReligion -> checkOnCity {
religion.getMajorityReligion() == relevantCiv?.religionManager?.religion }
UniqueType.ConditionalWLTKD -> checkOnCity { isWeLoveTheKingDayActive() }
UniqueType.ConditionalCityWithBuilding ->
checkOnCity { cityConstructions.containsBuildingOrEquivalent(condition.params[0]) }

View File

@ -236,33 +236,42 @@ enum class UniqueParameterType(
/** Implemented by [City.matchesFilter][com.unciv.logic.city.City.matchesFilter] */
CityFilter("cityFilter", "in all cities", null, "City filters") {
private val cityFilterStrings = setOf(
private val knownValues = setOf(
"in this city",
"in all cities",
"in all coastal cities",
"in capital",
"in all non-occupied cities",
"in all cities", "All",
"in your cities", "Your",
"in all coastal cities", "Coastal",
"in capital", "Capital",
"in all non-occupied cities", "Non-occupied",
"in all cities with a world wonder",
"in all cities connected to capital",
"in all cities with a garrison",
"in all cities with a garrison", "Garrisoned",
"in all cities in which the majority religion is a major religion",
"in all cities in which the majority religion is an enhanced religion",
"in non-enemy foreign cities",
"in foreign cities",
"in annexed cities",
"in puppeted cities",
"in holy cities",
"in enemy cities", "Enemy",
"in foreign cities", "Foreign",
"in annexed cities", "Annexed",
"in puppeted cities", "Puppeted",
"in holy cities", "Holy",
"in City-State cities",
"in cities following this religion",
"in cities following our religion",
)
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueParameterErrorSeverity? {
if (parameterText in cityFilterStrings) return null
if (parameterText in knownValues) return null
return UniqueType.UniqueParameterErrorSeverity.RulesetInvariant
}
override fun getTranslationWriterStringsForOutput() = cityFilterStrings
override fun isKnownValue(parameterText: String, ruleset: Ruleset): Boolean {
if (parameterText in knownValues) return true
if (CityFilter.isKnownValue(parameterText, ruleset)) return true
return false
}
override fun getTranslationWriterStringsForOutput() = knownValues
},
/** Used by [BuildingFilter] and e.g. [UniqueType.ConditionalCityWithBuilding] */

View File

@ -655,6 +655,11 @@ enum class UniqueType(
/////// city conditionals
ConditionalInThisCity("in this city", UniqueTarget.Conditional),
ConditionalCityFilter("in [cityFilter] cities", UniqueTarget.Conditional),
ConditionalCityConnected("in cities connected to the capital", UniqueTarget.Conditional),
ConditionalCityMajorReligion("in cities with a major religion", UniqueTarget.Conditional),
ConditionalCityEnhancedReligion("in cities with an enhanced religion", UniqueTarget.Conditional),
ConditionalCityThisReligion("in cities following our religion", UniqueTarget.Conditional),
ConditionalCityWithBuilding("in cities with a [buildingFilter]", UniqueTarget.Conditional),
ConditionalCityWithoutBuilding("in cities without a [buildingFilter]", UniqueTarget.Conditional),
ConditionalPopulationFilter("in cities with at least [amount] [populationFilter]", UniqueTarget.Conditional),

View File

@ -11,7 +11,7 @@ Note that all of these are case-sensitive!
## General Filter Rules
All filters except for `cityFilter` and `populationFilter` accept multiple values in the format: `{A} {B} {C}` etc, meaning "the object must match ALL of these filters"
All filters except for `populationFilter` accept multiple values in the format: `{A} {B} {C}` etc, meaning "the object must match ALL of these filters"
> Example: `[{Military} {Water}] units`, `[{Wounded} {Armor}] units`, etc.
@ -111,22 +111,25 @@ cityFilters allow us to choose the range of cities affected by this unique:
- `in this city`
- `in all cities`
- `in other cities`
- `in all coastal cities`
- `in capital`
- `in all non-occupied cities` - all cities that are not puppets and don't have extra unhappiness from being recently conquered
- `in your cities`, `Your`
- `in all coastal cities`, `Coastal`
- `in capital`, `Capital`
- `in all non-occupied cities`, `Non-occupied` - all cities that are not puppets and don't have extra unhappiness from being recently conquered
- `in all cities with a world wonder`
- `in all cities connected to capital`
- `in all cities with a garrison`
- `in all cities with a garrison`, `Garrisoned`
- `in non-enemy foreign cities` - In all cities owned by civs other than you that you are not at war with
- `in foreign cities`
- `in annexed cities`
- `in puppeted cities`
- `in holy cities`
- `in enemy cities`, `Enemy`
- `in foreign cities`, `Foreign`
- `in annexed cities`, `Annexed`
- `in puppeted cities`, `Puppeted`
- `in holy cities`, `Holy`
- `in City-State cities`
- `in cities following this religion` - Should only be used in pantheon/follower uniques for religions
- `in cities following our religion`
- `in all cities in which the majority religion is a major religion`
- `in all cities in which the majority religion is an enhanced religion`
- [civFilter]
## improvementFilter