Removed Unique.isOfType() + general code cleanup

This commit is contained in:
Yair Morgenstern 2024-01-25 23:18:42 +02:00
parent 8aab8f71e4
commit e0c7741480
17 changed files with 41 additions and 45 deletions

View File

@ -534,7 +534,7 @@ class City : IsPartOfGameInfoSerialization {
fun getLocalMatchingUniques(uniqueType: UniqueType, stateForConditionals: StateForConditionals = StateForConditionals(civ, this)): Sequence<Unique> {
return (
cityConstructions.builtBuildingUniqueMap.getUniques(uniqueType).filter { it.isLocalEffect }
+ religion.getUniques().filter { it.isOfType(uniqueType) }
+ religion.getUniques().filter { it.type == uniqueType }
).filter {
it.conditionalsApply(stateForConditionals)
}
@ -543,7 +543,7 @@ class City : IsPartOfGameInfoSerialization {
// Uniques coming from only this city
fun getMatchingLocalOnlyUniques(uniqueType: UniqueType, stateForConditionals: StateForConditionals): Sequence<Unique> {
val uniques = cityConstructions.builtBuildingUniqueMap.getUniques(uniqueType).filter { it.isLocalEffect } +
religion.getUniques().filter { it.isOfType(uniqueType) }
religion.getUniques().filter { it.type == uniqueType }
return if (uniques.any()) uniques.filter { it.conditionalsApply(stateForConditionals) }
else uniques
}

View File

@ -475,7 +475,7 @@ class Civilization : IsPartOfGameInfoSerialization {
yieldAll(cityStateFunctions.getUniquesProvidedByCityStates(uniqueType, stateForConditionals))
if (religionManager.religion != null)
yieldAll(religionManager.religion!!.getFounderUniques()
.filter { it.isOfType(uniqueType) && it.conditionalsApply(stateForConditionals) })
.filter { it.type == uniqueType && it.conditionalsApply(stateForConditionals) })
yieldAll(getCivResourceSupply().asSequence()
.filter { it.amount > 0 }

View File

@ -84,7 +84,7 @@ class UnitManager(val civInfo:Civilization) {
if (!unique.hasTriggerConditional() && unique.conditionalsApply(StateForConditionals(civInfo, unit = unit)))
UniqueTriggerActivation.triggerUnitwideUnique(unique, unit, triggerNotificationText = triggerNotificationText)
for (unique in civInfo.getTriggeredUniques(UniqueType.TriggerUponGainingUnit))
if (unique.conditionals.any { it.isOfType(UniqueType.TriggerUponGainingUnit) &&
if (unique.conditionals.any { it.type == UniqueType.TriggerUponGainingUnit &&
unit.matchesFilter(it.params[0]) })
UniqueTriggerActivation.triggerCivwideUnique(unique, civInfo, triggerNotificationText = triggerNotificationText)
if (unit.getResourceRequirementsPerTurn().isNotEmpty())

View File

@ -285,13 +285,13 @@ class CivInfoStatsForNextTurn(val civInfo: Civilization) {
val statMap = StatMap()
if (civInfo.religionManager.religion != null) {
for (unique in civInfo.religionManager.religion!!.getFounderUniques()) {
if (unique.isOfType(UniqueType.StatsFromGlobalCitiesFollowingReligion)) {
if (unique.type == UniqueType.StatsFromGlobalCitiesFollowingReligion) {
statMap.add(
"Religion",
unique.stats * civInfo.religionManager.numberOfCitiesFollowingThisReligion()
)
}
if (unique.isOfType(UniqueType.StatsFromGlobalFollowers))
if (unique.type == UniqueType.StatsFromGlobalFollowers)
statMap.add(
"Religion",
unique.stats * civInfo.religionManager.numberOfFollowersFollowingThisReligion(

View File

@ -26,8 +26,7 @@ object LuxuryResourcePlacementLogic {
// If there are any weightings defined in json, assume they are complete. If there are none, use flat weightings instead
val fallbackWeightings = ruleset.tileResources.values.none {
it.resourceType == ResourceType.Luxury &&
(it.uniqueObjects.any { unique -> unique.isOfType(UniqueType.ResourceWeighting) } || it.hasUnique(
UniqueType.LuxuryWeightingForCityStates)) }
(it.hasUnique(UniqueType.ResourceWeighting) || it.hasUnique(UniqueType.LuxuryWeightingForCityStates)) }
val maxRegionsWithLuxury = when {
regions.size > 12 -> 3

View File

@ -679,8 +679,8 @@ class MapRegions (val ruleset: Ruleset) {
// As usual, if there are any relevant json definitions, assume they are complete
val fallbackStrategic = ruleset.tileResources.values.none {
it.resourceType == ResourceType.Strategic &&
it.uniqueObjects.any { unique -> unique.isOfType(UniqueType.ResourceWeighting) } ||
it.uniqueObjects.any { unique -> unique.isOfType(UniqueType.MinorDepositWeighting) }
it.hasUnique(UniqueType.ResourceWeighting) ||
it.hasUnique(UniqueType.MinorDepositWeighting)
}
/* There are a couple competing/complementary distribution systems at work here. First, major
deposits are placed according to a frequency defined in the terrains themselves, for each
@ -710,15 +710,16 @@ class MapRegions (val ruleset: Ruleset) {
for (resource in ruleset.tileResources.values.filter {
it.resourceType == ResourceType.Strategic ||
it.resourceType == ResourceType.Bonus }) {
for (rule in resource.uniqueObjects.filter { unique ->
unique.isOfType(UniqueType.ResourceFrequency) ||
unique.isOfType(UniqueType.ResourceWeighting) ||
unique.isOfType(UniqueType.MinorDepositWeighting) }) {
unique.type == UniqueType.ResourceFrequency ||
unique.type == UniqueType.ResourceWeighting ||
unique.type == UniqueType.MinorDepositWeighting }) {
// Weed out some clearly impossible rules straight away to save time later
if (rule.conditionals.any { conditional ->
(conditional.isOfType(UniqueType.ConditionalOnWaterMaps) && !usingArchipelagoRegions) ||
(conditional.isOfType(UniqueType.ConditionalInRegionOfType) && regions.none { region -> region.type == conditional.params[0] }) ||
(conditional.isOfType(UniqueType.ConditionalInRegionExceptOfType) && regions.all { region -> region.type == conditional.params[0] })
(conditional.type == UniqueType.ConditionalOnWaterMaps && !usingArchipelagoRegions) ||
(conditional.type == UniqueType.ConditionalInRegionOfType && regions.none { region -> region.type == conditional.params[0] }) ||
(conditional.type == UniqueType.ConditionalInRegionExceptOfType && regions.all { region -> region.type == conditional.params[0] })
} )
continue
val simpleRule = anonymizeUnique(rule)

View File

@ -105,7 +105,7 @@ class Building : RulesetStatsObject(), INonPerpetualConstruction {
override fun getProductionCost(civInfo: Civilization): Int {
var productionCost = cost.toFloat()
for (unique in uniqueObjects.filter { it.isOfType(UniqueType.CostIncreasesPerCity) })
for (unique in getMatchingUniques(UniqueType.CostIncreasesPerCity, StateForConditionals(civInfo)))
productionCost += civInfo.cities.size * unique.params[0].toInt()
if (civInfo.isCityState())

View File

@ -38,8 +38,8 @@ open class Policy : RulesetObject() {
return (if (policyBranchType == PolicyBranchType.Member) name.tr() + "\n" else "") +
uniqueObjects.filterNot {
it.isHiddenToUsers()
|| it.isOfType(UniqueType.OnlyAvailable)
|| it.isOfType(UniqueType.OneTimeGlobalAlert)
|| it.type == UniqueType.OnlyAvailable
|| it.type == UniqueType.OneTimeGlobalAlert
}
.joinToString("\n") { "${it.text.tr()}" }
}

View File

@ -164,7 +164,7 @@ class Nation : RulesetObject() {
textList += FormattedLine("{$header:} ")
for (unique in bonuses) {
textList += FormattedLine(unique, indent = 1)
if (unique.isOfType(UniqueType.CityStateUniqueLuxury)) showResources = true
if (unique.type == UniqueType.CityStateUniqueLuxury) showResources = true
}
}

View File

@ -57,8 +57,6 @@ class Unique(val text: String, val sourceObjectType: UniqueTarget? = null, val s
}
}
fun isOfType(uniqueType: UniqueType) = uniqueType == type
fun conditionalsApply(civInfo: Civilization? = null, city: City? = null): Boolean {
return conditionalsApply(StateForConditionals(civInfo, city))
}
@ -66,7 +64,7 @@ class Unique(val text: String, val sourceObjectType: UniqueTarget? = null, val s
fun conditionalsApply(state: StateForConditionals = StateForConditionals()): Boolean {
if (state.ignoreConditionals) return true
// Always allow Timed conditional uniques. They are managed elsewhere
if (conditionals.any { it.isOfType(UniqueType.ConditionalTimedUnique) }) return true
if (conditionals.any { it.type == UniqueType.ConditionalTimedUnique }) return true
for (condition in conditionals) {
if (!conditionalApplies(condition, state)) return false
}
@ -490,7 +488,7 @@ class UniqueMap: HashMap<String, ArrayList<Unique>>() {
class TemporaryUnique() : IsPartOfGameInfoSerialization {
constructor(uniqueObject: Unique, turns: Int) : this() {
val turnsText = uniqueObject.conditionals.first { it.isOfType(UniqueType.ConditionalTimedUnique) }.text
val turnsText = uniqueObject.conditionals.first { it.type == UniqueType.ConditionalTimedUnique }.text
unique = uniqueObject.text.replaceFirst("<$turnsText>", "")
sourceObjectType = uniqueObject.sourceObjectType
sourceObjectName = uniqueObject.sourceObjectName
@ -519,5 +517,5 @@ fun ArrayList<TemporaryUnique>.endTurn() {
fun ArrayList<TemporaryUnique>.getMatchingUniques(uniqueType: UniqueType, stateForConditionals: StateForConditionals): Sequence<Unique> {
return this.asSequence()
.map { it.uniqueObject }
.filter { it.isOfType(uniqueType) && it.conditionalsApply(stateForConditionals) }
.filter { it.type == uniqueType && it.conditionalsApply(stateForConditionals) }
}

View File

@ -604,7 +604,6 @@ enum class UniqueType(
ConditionalChance("with [amount]% chance", UniqueTarget.Conditional),
ConditionalEveryTurns("every [positiveAmount] turns", UniqueTarget.Conditional),
ConditionalBeforeTurns("before [amount] turns", UniqueTarget.Conditional),
ConditionalAfterTurns("after [amount] turns", UniqueTarget.Conditional),
@ -795,7 +794,7 @@ enum class UniqueType(
UniqueTarget.Unit, UniqueTarget.Building, UniqueTarget.Ruins, UniqueTarget.Tutorial,
flags = UniqueFlag.setOfHiddenToUsers),
@Deprecated("as of 4.9.0", ReplaceWith("Unavailable <after generating a Great Prophet>"))
@Deprecated("as of 4.10.3", ReplaceWith("Unavailable <after generating a Great Prophet>"))
HiddenAfterGreatProphet("Hidden after generating a Great Prophet", UniqueTarget.Ruins),
HiddenWithoutVictoryType("Hidden when [victoryType] Victory is disabled", UniqueTarget.Building, UniqueTarget.Unit, flags = UniqueFlag.setOfHiddenToUsers),
HiddenFromCivilopedia("Will not be displayed in Civilopedia", *UniqueTarget.Displayable, flags = UniqueFlag.setOfHiddenToUsers),

View File

@ -420,14 +420,14 @@ class BaseUnit : RulesetObject(), INonPerpetualConstruction {
when (unique.type) {
UniqueType.Strength -> {
if (unique.params[0].toInt() <= 0) continue
if (unique.conditionals.any { it.isOfType(UniqueType.ConditionalVsUnits) }) { // Bonus vs some units - a quarter of the bonus
if (unique.conditionals.any { it.type == UniqueType.ConditionalVsUnits }) { // Bonus vs some units - a quarter of the bonus
power *= (unique.params[0].toInt() / 4f).toPercent()
} else if (
unique.conditionals.any {
it.isOfType(UniqueType.ConditionalVsCity) // City Attack - half the bonus
|| it.isOfType(UniqueType.ConditionalAttacking) // Attack - half the bonus
|| it.isOfType(UniqueType.ConditionalDefending) // Defense - half the bonus
|| it.isOfType(UniqueType.ConditionalFightingInTiles)
it.type == UniqueType.ConditionalVsCity // City Attack - half the bonus
|| it.type == UniqueType.ConditionalAttacking // Attack - half the bonus
|| it.type == UniqueType.ConditionalDefending // Defense - half the bonus
|| it.type == UniqueType.ConditionalFightingInTiles
} // Bonus in terrain or feature - half the bonus
) {
power *= (unique.params[0].toInt() / 2f).toPercent()

View File

@ -58,7 +58,7 @@ object BaseUnitDescriptions {
lines += "$strengthLine${baseUnit.movement}${Fonts.movement}"
if (baseUnit.replacementTextForUniques != "") lines += baseUnit.replacementTextForUniques
else baseUnit.uniquesToDescription(lines) { isOfType(UniqueType.Unbuildable) }
else baseUnit.uniquesToDescription(lines) { type == UniqueType.Unbuildable }
if (baseUnit.promotions.isNotEmpty()) {
val prefix = "Free promotion${if (baseUnit.promotions.size == 1) "" else "s"}:".tr() + " "

View File

@ -71,7 +71,7 @@ object BuildingDescriptions {
if (replacementTextForUniques.isNotEmpty()) translatedLines += replacementTextForUniques.tr()
else translatedLines += getUniquesStringsWithoutDisablers(
filterUniques = if (missingCities.isEmpty()) null
else { unique -> !unique.isOfType(UniqueType.RequiresBuildingInAllCities) }
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() }
}
@ -259,7 +259,7 @@ object BuildingDescriptions {
private fun Building.getUniquesStrings(filterUniques: ((Unique) -> Boolean)? = null) = sequence {
val tileBonusHashmap = HashMap<String, ArrayList<String>>()
for (unique in uniqueObjects) if (filterUniques == null || filterUniques(unique)) when {
unique.isOfType(UniqueType.StatsFromTiles) && unique.params[2] == "in this city" -> {
unique.type == UniqueType.StatsFromTiles && unique.params[2] == "in this city" -> {
val stats = unique.params[0]
if (!tileBonusHashmap.containsKey(stats)) tileBonusHashmap[stats] = ArrayList()
tileBonusHashmap[stats]!!.add(unique.params[1])

View File

@ -47,7 +47,7 @@ fun IHasUniques.uniquesToCivilopediaTextLines(
// Optionally special-case ConsumesResources to give it a reddish color. Also ensures link always points to the resource
// (the other constructor guesses the first object by name in the Unique parameters).
yield(
if (colorConsumesResources && unique.isOfType(UniqueType.ConsumesResources))
if (colorConsumesResources && unique.type == UniqueType.ConsumesResources)
FormattedLine(unique.text, link = "Resources/${unique.params[1]}", color = "#F42")
else FormattedLine(unique)
)

View File

@ -146,7 +146,7 @@ object TechnologyDescriptions {
for (unique in tech.uniqueObjects) {
yield(
when {
unique.isOfType(UniqueType.EnablesCivWideStatProduction) ->
unique.type == UniqueType.EnablesCivWideStatProduction ->
ImageGetter.getConstructionPortrait(unique.params[0], techIconSize)
else ->
ImageGetter.getUniquePortrait(unique.text, techIconSize)
@ -344,15 +344,15 @@ object TechnologyDescriptions {
/** Tests whether a Unique means bonus Stats enabled by [techName] */
private fun Unique.isImprovementStatsEnabledByTech(techName: String) =
(isOfType(UniqueType.Stats) || isOfType(UniqueType.ImprovementStatsOnTile)) &&
(type == UniqueType.Stats || type == UniqueType.ImprovementStatsOnTile) &&
conditionals.any {
it.isOfType(UniqueType.ConditionalTech) && it.params[0] == techName
it.type == UniqueType.ConditionalTech && it.params[0] == techName
}
/** Tests whether a Unique Conditional is enabling or disabling its parent by a tech */
private fun Unique.isTechConditional() =
isOfType(UniqueType.ConditionalTech) ||
isOfType(UniqueType.ConditionalNoTech)
type == UniqueType.ConditionalTech ||
type == UniqueType.ConditionalNoTech
/** Tests whether a Unique is enabled or disabled by [techName] */
private fun Unique.isRelatedToTech(techName: String) =
@ -363,7 +363,7 @@ object TechnologyDescriptions {
/** Used by [getAffectedImprovements] only */
private data class ImprovementAndUnique(val improvement: TileImprovement, val unique: Unique) {
fun getText() = "[${unique.params[0]}] from every [${improvement.name}]" +
(if (unique.isOfType(UniqueType.Stats)) "" else " on [${unique.params[1]}] tiles")
(if (unique.type == UniqueType.Stats) "" else " on [${unique.params[1]}] tiles")
}
/** Yields Improvements with bonus Stats enabled by [techName] including the Unique doing it */

View File

@ -170,7 +170,7 @@ object UnitActionsFromUniques {
if (!unique.conditionalsApply(StateForConditionals(civInfo = unit.civ, unit = unit, tile = unit.currentTile))) continue
if (!UnitActionModifiers.canUse(unit, unique)) continue
val baseTitle = if (unique.isOfType(UniqueType.OneTimeEnterGoldenAgeTurns))
val baseTitle = if (unique.type == UniqueType.OneTimeEnterGoldenAgeTurns)
unique.placeholderText.fillPlaceholders(
unit.civ.goldenAges.calculateGoldenAgeLength(
unique.params[0].toInt()).toString())
@ -236,8 +236,7 @@ object UnitActionsFromUniques {
if (tile.improvementFunctions.getImprovementBuildingProblems(improvement, unit.civ).any { it.permanent })
continue
val resourcesAvailable = improvement.uniqueObjects.none { improvementUnique ->
improvementUnique.isOfType(UniqueType.ConsumesResources) &&
val resourcesAvailable = improvement.getMatchingUniques(UniqueType.ConsumesResources).none { improvementUnique ->
(civResources[improvementUnique.params[1]] ?: 0) < improvementUnique.params[0].toInt()
}