From 09fdd8b8e24d49362a3ea1ae032b8d888bfe77bf Mon Sep 17 00:00:00 2001 From: dHannasch Date: Sat, 25 Nov 2023 23:48:09 -0700 Subject: [PATCH] Wrap INonPerpetualConstruction.requiredTech into function (#10585) * Update IConstruction.kt * Update Building.kt * Update BaseUnit.kt * Update BaseUnit.kt * Update Building.kt * Update IConstruction.kt * Update IConstruction.kt * Update IConstruction.kt * Update CityStateFunctions.kt * Update Building.kt * Update IConstruction.kt * Update IConstruction.kt * Update BaseUnit.kt * Update RulesetValidator.kt * Update TechnologyDescriptions.kt * Update CityStateDiplomacyTable.kt * Update CityStateDiplomacyTable.kt --- .../diplomacy/CityStateFunctions.kt | 2 +- core/src/com/unciv/models/ruleset/Building.kt | 6 +++-- .../com/unciv/models/ruleset/IConstruction.kt | 5 ++++ .../com/unciv/models/ruleset/unit/BaseUnit.kt | 9 ++++--- .../ruleset/validation/RulesetValidator.kt | 27 ++++++++++--------- .../TechnologyDescriptions.kt | 4 +-- .../CityStateDiplomacyTable.kt | 6 +++-- 7 files changed, 37 insertions(+), 22 deletions(-) diff --git a/core/src/com/unciv/logic/civilization/diplomacy/CityStateFunctions.kt b/core/src/com/unciv/logic/civilization/diplomacy/CityStateFunctions.kt index dc32408554..0b520cd75d 100644 --- a/core/src/com/unciv/logic/civilization/diplomacy/CityStateFunctions.kt +++ b/core/src/com/unciv/logic/civilization/diplomacy/CityStateFunctions.kt @@ -51,7 +51,7 @@ class CityStateFunctions(val civInfo: Civilization) { // Unique unit for militaristic city-states if (uniqueTypes.contains(UniqueType.CityStateMilitaryUnits)) { - val possibleUnits = ruleset.units.values.filter { it.requiredTech != null + val possibleUnits = ruleset.units.values.filter { it.requiredTechs().any() && ruleset.eras[ruleset.technologies[it.requiredTech!!]!!.era()]!!.eraNumber > ruleset.eras[startingEra]!!.eraNumber // Not from the start era or before && it.uniqueTo != null && it.uniqueTo in unusedMajorCivs // Must be from a major civ not in the game && ruleset.unitTypes[it.unitType]!!.isLandUnit() && ( it.strength > 0 || it.rangedStrength > 0 ) } // Must be a land military unit diff --git a/core/src/com/unciv/models/ruleset/Building.kt b/core/src/com/unciv/models/ruleset/Building.kt index dfe2112a77..df53e7b3ec 100644 --- a/core/src/com/unciv/models/ruleset/Building.kt +++ b/core/src/com/unciv/models/ruleset/Building.kt @@ -22,6 +22,7 @@ import com.unciv.ui.objectdescriptions.BuildingDescriptions class Building : RulesetStatsObject(), INonPerpetualConstruction { + @Deprecated("The functionality provided by the requiredTech field is provided by the OnlyAvailableWhen unique.") override var requiredTech: String? = null override var cost: Int = -1 @@ -360,8 +361,9 @@ class Building : RulesetStatsObject(), INonPerpetualConstruction { if (civ.cache.uniqueBuildings.any { it.replaces == name }) yield(RejectionReasonType.ReplacedByOurUnique.toInstance()) - if (requiredTech != null && !civ.tech.isResearched(requiredTech!!)) - yield(RejectionReasonType.RequiresTech.toInstance("$requiredTech not researched!")) + for (requiredTech: String in requiredTechs()) + if (!civ.tech.isResearched(requiredTech)) + yield(RejectionReasonType.RequiresTech.toInstance("$requiredTech not researched!")) // Regular wonders if (isWonder) { diff --git a/core/src/com/unciv/models/ruleset/IConstruction.kt b/core/src/com/unciv/models/ruleset/IConstruction.kt index 867fbeaa92..19bcf9ef37 100644 --- a/core/src/com/unciv/models/ruleset/IConstruction.kt +++ b/core/src/com/unciv/models/ruleset/IConstruction.kt @@ -29,8 +29,13 @@ interface IConstruction : INamed { interface INonPerpetualConstruction : IConstruction, INamed, IHasUniques { var cost: Int val hurryCostModifier: Int + // Future development should not increase the role of requiredTech, and should reduce it when possible. + // https://yairm210.github.io/Unciv/Developers/Translations%2C-mods%2C-and-modding-freedom-in-Open-Source#filters + @Deprecated("The functionality provided by the requiredTech field is provided by the OnlyAvailableWhen unique.") var requiredTech: String? + fun requiredTechs(): Sequence = if (requiredTech == null) sequenceOf() else sequenceOf(requiredTech!!) + fun getProductionCost(civInfo: Civilization): Int fun getStatBuyCost(city: City, stat: Stat): Int? fun getRejectionReasons(cityConstructions: CityConstructions): Sequence diff --git a/core/src/com/unciv/models/ruleset/unit/BaseUnit.kt b/core/src/com/unciv/models/ruleset/unit/BaseUnit.kt index 6362dec7a3..cf2c71cedc 100644 --- a/core/src/com/unciv/models/ruleset/unit/BaseUnit.kt +++ b/core/src/com/unciv/models/ruleset/unit/BaseUnit.kt @@ -39,6 +39,7 @@ class BaseUnit : RulesetObject(), INonPerpetualConstruction { var unitType: String = "" val type by lazy { ruleset.unitTypes[unitType]!! } + @Deprecated("The functionality provided by the requiredTech field is provided by the OnlyAvailableWhen unique.") override var requiredTech: String? = null var requiredResource: String? = null @@ -155,8 +156,9 @@ class BaseUnit : RulesetObject(), INonPerpetualConstruction { city: City? = null, additionalResources: Counter = Counter.ZERO ): Sequence = sequence { - if (requiredTech != null && !civ.tech.isResearched(requiredTech!!)) - yield(RejectionReasonType.RequiresTech.toInstance("$requiredTech not researched")) + for (requiredTech: String in requiredTechs()) + if (!civ.tech.isResearched(requiredTech)) + yield(RejectionReasonType.RequiresTech.toInstance("$requiredTech not researched")) if (obsoleteTech != null && civ.tech.isResearched(obsoleteTech!!)) yield(RejectionReasonType.Obsoleted.toInstance("Obsolete by $obsoleteTech")) @@ -289,7 +291,8 @@ class BaseUnit : RulesetObject(), INonPerpetualConstruction { else -> { if (type.matchesFilter(filter)) return true - if (requiredTech != null && ruleset.technologies[requiredTech]?.matchesFilter(filter) == true) return true + for (requiredTech: String in requiredTechs()) + if (ruleset.technologies[requiredTech]?.matchesFilter(filter) == true) return true if ( // Uniques using these kinds of filters should be deprecated and replaced with adjective-only parameters filter.endsWith(" units") diff --git a/core/src/com/unciv/models/ruleset/validation/RulesetValidator.kt b/core/src/com/unciv/models/ruleset/validation/RulesetValidator.kt index f774a68f74..647d589f01 100644 --- a/core/src/com/unciv/models/ruleset/validation/RulesetValidator.kt +++ b/core/src/com/unciv/models/ruleset/validation/RulesetValidator.kt @@ -433,8 +433,9 @@ class RulesetValidator(val ruleset: Ruleset) { for (building in ruleset.buildings.values) { addBuildingErrorRulesetInvariant(building, lines) - if (building.requiredTech != null && !ruleset.technologies.containsKey(building.requiredTech!!)) - lines += "${building.name} requires tech ${building.requiredTech} which does not exist!" + for (requiredTech: String in building.requiredTechs()) + if (!ruleset.technologies.containsKey(requiredTech)) + lines += "${building.name} requires tech ${requiredTech} which does not exist!" for (specialistName in building.specialistSlots.keys) if (!ruleset.specialists.containsKey(specialistName)) lines += "${building.name} provides specialist $specialistName which does not exist!" @@ -575,7 +576,7 @@ class RulesetValidator(val ruleset: Ruleset) { } private fun addBuildingErrorRulesetInvariant(building: Building, lines: RulesetErrorList) { - if (building.requiredTech == null && building.cost == -1 && !building.hasUnique( + if (building.requiredTechs().none() && building.cost == -1 && !building.hasUnique( UniqueType.Unbuildable ) ) @@ -653,8 +654,9 @@ class RulesetValidator(val ruleset: Ruleset) { /** Collects all RulesetSpecific checks for a BaseUnit */ private fun checkUnitRulesetSpecific(unit: BaseUnit, lines: RulesetErrorList) { - if (unit.requiredTech != null && !ruleset.technologies.containsKey(unit.requiredTech!!)) - lines += "${unit.name} requires tech ${unit.requiredTech} which does not exist!" + for (requiredTech: String in unit.requiredTechs()) + if (!ruleset.technologies.containsKey(requiredTech)) + lines += "${unit.name} requires tech ${requiredTech} which does not exist!" if (unit.obsoleteTech != null && !ruleset.technologies.containsKey(unit.obsoleteTech!!)) lines += "${unit.name} obsoletes at tech ${unit.obsoleteTech} which does not exist!" if (unit.upgradesTo != null && !ruleset.units.containsKey(unit.upgradesTo!!)) @@ -664,14 +666,15 @@ class RulesetValidator(val ruleset: Ruleset) { if (unit.upgradesTo!=null && ruleset.units.containsKey(unit.upgradesTo!!) && unit.obsoleteTech!=null && ruleset.technologies.containsKey(unit.obsoleteTech!!)) { val upgradedUnit = ruleset.units[unit.upgradesTo!!]!! - if (upgradedUnit.requiredTech != null && upgradedUnit.requiredTech != unit.obsoleteTech - && !getPrereqTree(unit.obsoleteTech!!).contains(upgradedUnit.requiredTech) - ) - lines.add( - "${unit.name} obsoletes at tech ${unit.obsoleteTech}," + - " and therefore ${upgradedUnit.requiredTech} for its upgrade ${upgradedUnit.name} may not yet be researched!", - RulesetErrorSeverity.Warning + for (requiredTech: String in upgradedUnit.requiredTechs()) + if (requiredTech != unit.obsoleteTech + && !getPrereqTree(unit.obsoleteTech!!).contains(requiredTech) ) + lines.add( + "${unit.name} obsoletes at tech ${unit.obsoleteTech}," + + " and therefore ${requiredTech} for its upgrade ${upgradedUnit.name} may not yet be researched!", + RulesetErrorSeverity.Warning + ) } for (resource in unit.getResourceRequirementsPerTurn(StateForConditionals.IgnoreConditionals).keys) diff --git a/core/src/com/unciv/ui/objectdescriptions/TechnologyDescriptions.kt b/core/src/com/unciv/ui/objectdescriptions/TechnologyDescriptions.kt index 0802ce1e4a..406a2d0e90 100644 --- a/core/src/com/unciv/ui/objectdescriptions/TechnologyDescriptions.kt +++ b/core/src/com/unciv/ui/objectdescriptions/TechnologyDescriptions.kt @@ -272,7 +272,7 @@ object TechnologyDescriptions { */ // Used for Civilopedia, Alert and Picker, so if any of these decide to ignore the "Will not be displayed in Civilopedia" unique this needs refactoring private fun getEnabledBuildings(techName: String, ruleset: Ruleset, civInfo: Civilization?) = - getFilteredBuildings(ruleset, civInfo) { it.requiredTech == techName } + getFilteredBuildings(ruleset, civInfo) { it.requiredTechs().contains(techName) } /** * Returns a Sequence of [RulesetStatsObject]s obsoleted by this Technology, filtered for [civInfo]'s uniques, @@ -334,7 +334,7 @@ object TechnologyDescriptions { val (nuclearWeaponsEnabled, religionEnabled) = getNukeAndReligionSwitches(civInfo) return ruleset.units.values.asSequence() .filter { - it.requiredTech == techName + it.requiredTechs().contains(techName) && (it.uniqueTo == civInfo?.civName || it.uniqueTo == null && civInfo?.getEquivalentUnit(it) == it) && (nuclearWeaponsEnabled || !it.isNuclearWeapon()) && (religionEnabled || !it.hasUnique(UniqueType.HiddenWithoutReligion)) diff --git a/core/src/com/unciv/ui/screens/diplomacyscreen/CityStateDiplomacyTable.kt b/core/src/com/unciv/ui/screens/diplomacyscreen/CityStateDiplomacyTable.kt index 36f8d33a69..011baaa8bd 100644 --- a/core/src/com/unciv/ui/screens/diplomacyscreen/CityStateDiplomacyTable.kt +++ b/core/src/com/unciv/ui/screens/diplomacyscreen/CityStateDiplomacyTable.kt @@ -196,8 +196,10 @@ class CityStateDiplomacyTable(private val diplomacyScreen: DiplomacyScreen) { if (otherCiv.cityStateUniqueUnit != null) { val unitName = otherCiv.cityStateUniqueUnit - val techName = viewingCiv.gameInfo.ruleset.units[otherCiv.cityStateUniqueUnit]!!.requiredTech - diplomacyTable.add("[${otherCiv.civName}] is able to provide [${unitName}] once [${techName}] is researched.".toLabel(fontSize = Constants.defaultFontSize)).row() + val techNames = viewingCiv.gameInfo.ruleset.units[otherCiv.cityStateUniqueUnit]!!.requiredTechs() + val techAndTech = techNames.joinToString(" and ") + val isOrAre = if (techNames.count() == 1) "is" else "are" + diplomacyTable.add("[${otherCiv.civName}] is able to provide [${unitName}] once [${techAndTech}] [${isOrAre}] researched.".toLabel(fontSize = Constants.defaultFontSize)).row() } return diplomacyTable