From 2986052397a7faec22a8ea0993672f322609feb2 Mon Sep 17 00:00:00 2001 From: Xander Lenstra <71121390+xlenstra@users.noreply.github.com> Date: Fri, 14 Jan 2022 18:44:53 +0100 Subject: [PATCH] Typed all tech uniques (#5967) --- core/src/com/unciv/logic/GameStarter.kt | 2 +- .../src/com/unciv/logic/city/IConstruction.kt | 4 +-- .../logic/civilization/CityStateFunctions.kt | 2 +- .../unciv/logic/civilization/TechManager.kt | 8 +++--- core/src/com/unciv/logic/trade/TradeLogic.kt | 5 ++-- .../unciv/models/ruleset/tech/Technology.kt | 2 +- .../unciv/models/ruleset/unique/UniqueType.kt | 27 ++++++++++++++----- .../com/unciv/ui/worldscreen/WorldScreen.kt | 3 ++- 8 files changed, 35 insertions(+), 18 deletions(-) diff --git a/core/src/com/unciv/logic/GameStarter.kt b/core/src/com/unciv/logic/GameStarter.kt index a3f003875f..ee075689df 100644 --- a/core/src/com/unciv/logic/GameStarter.kt +++ b/core/src/com/unciv/logic/GameStarter.kt @@ -188,7 +188,7 @@ object GameStarter { availableCivNames.removeAll(newGameParameters.players.map { it.chosenCiv }) availableCivNames.remove(Constants.barbarians) - val startingTechs = ruleset.technologies.values.filter { it.uniques.contains("Starting tech") } + val startingTechs = ruleset.technologies.values.filter { it.hasUnique(UniqueType.StartingTech) } if (!newGameParameters.noBarbarians && ruleset.nations.containsKey(Constants.barbarians)) { val barbarianCivilization = CivilizationInfo(Constants.barbarians) diff --git a/core/src/com/unciv/logic/city/IConstruction.kt b/core/src/com/unciv/logic/city/IConstruction.kt index beaf1ef21b..a3b75d11a9 100644 --- a/core/src/com/unciv/logic/city/IConstruction.kt +++ b/core/src/com/unciv/logic/city/IConstruction.kt @@ -195,7 +195,7 @@ open class PerpetualConstruction(override var name: String, val description: Str const val CONVERSION_RATE: Int = 4 val science = object : PerpetualConstruction("Science", "Convert production to science at a rate of [rate] to 1") { override fun isBuildable(cityConstructions: CityConstructions): Boolean { - return cityConstructions.cityInfo.civInfo.hasUnique("Enables conversion of city production to science") + return cityConstructions.cityInfo.civInfo.hasUnique(UniqueType.EnablesScienceProduction) } override fun getProductionTooltip(cityInfo: CityInfo): String { return "\r\n${(cityInfo.cityStats.currentCityStats.production / getConversionRate(cityInfo)).roundToInt()}/${Fonts.turn}" @@ -204,7 +204,7 @@ open class PerpetualConstruction(override var name: String, val description: Str } val gold = object : PerpetualConstruction("Gold", "Convert production to gold at a rate of $CONVERSION_RATE to 1") { override fun isBuildable(cityConstructions: CityConstructions): Boolean { - return cityConstructions.cityInfo.civInfo.hasUnique("Enables conversion of city production to gold") + return cityConstructions.cityInfo.civInfo.hasUnique(UniqueType.EnablesGoldProduction) } } val idle = object : PerpetualConstruction("Nothing", "The city will not produce anything.") { diff --git a/core/src/com/unciv/logic/civilization/CityStateFunctions.kt b/core/src/com/unciv/logic/civilization/CityStateFunctions.kt index 3d1494117d..31cb7e4daa 100644 --- a/core/src/com/unciv/logic/civilization/CityStateFunctions.kt +++ b/core/src/com/unciv/logic/civilization/CityStateFunctions.kt @@ -24,7 +24,7 @@ class CityStateFunctions(val civInfo: CivilizationInfo) { val cityStateType = ruleset.nations[civInfo.civName]?.cityStateType ?: return false - val startingTechs = ruleset.technologies.values.filter { it.uniques.contains("Starting tech") } + val startingTechs = ruleset.technologies.values.filter { it.hasUnique(UniqueType.StartingTech) } for (tech in startingTechs) civInfo.tech.techsResearched.add(tech.name) // can't be .addTechnology because the civInfo isn't assigned yet diff --git a/core/src/com/unciv/logic/civilization/TechManager.kt b/core/src/com/unciv/logic/civilization/TechManager.kt index 49374be2f6..afcb427a9a 100644 --- a/core/src/com/unciv/logic/civilization/TechManager.kt +++ b/core/src/com/unciv/logic/civilization/TechManager.kt @@ -340,12 +340,12 @@ class TechManager { private fun updateTransientBooleans() { wayfinding = civInfo.hasUnique("Can embark and move over Coasts and Oceans immediately") - unitsCanEmbark = wayfinding || civInfo.hasUnique("Enables embarkation for land units") + unitsCanEmbark = wayfinding || civInfo.hasUnique(UniqueType.LandUnitEmbarkation) - embarkedUnitsCanEnterOcean = wayfinding || civInfo.hasUnique("Enables embarked units to enter ocean tiles") - movementSpeedOnRoads = if (civInfo.hasUnique("Improves movement speed on roads")) + embarkedUnitsCanEnterOcean = wayfinding || civInfo.hasUnique(UniqueType.EmbarkedUnitsMayEnterOcean) + movementSpeedOnRoads = if (civInfo.hasUnique(UniqueType.RoadMovementSpeed)) RoadStatus.Road.movementImproved else RoadStatus.Road.movement - roadsConnectAcrossRivers = civInfo.hasUnique("Roads connect tiles across rivers") + roadsConnectAcrossRivers = civInfo.hasUnique(UniqueType.RoadsConnectAcrossRivers) } fun getBestRoadAvailable(): RoadStatus { diff --git a/core/src/com/unciv/logic/trade/TradeLogic.kt b/core/src/com/unciv/logic/trade/TradeLogic.kt index 2cb0887a4d..022cd89a79 100644 --- a/core/src/com/unciv/logic/trade/TradeLogic.kt +++ b/core/src/com/unciv/logic/trade/TradeLogic.kt @@ -5,6 +5,7 @@ import com.unciv.logic.civilization.CivilizationInfo import com.unciv.logic.civilization.diplomacy.DiplomacyFlags import com.unciv.models.ruleset.ModOptionsConstants import com.unciv.models.ruleset.tile.ResourceType +import com.unciv.models.ruleset.unique.UniqueType class TradeLogic(val ourCivilization:CivilizationInfo, val otherCivilization: CivilizationInfo) { @@ -21,8 +22,8 @@ class TradeLogic(val ourCivilization:CivilizationInfo, val otherCivilization: Ci if (!otherCivilization.getDiplomacyManager(civInfo).hasOpenBorders && !otherCivilization.isCityState() - && civInfo.hasUnique("Enables Open Borders agreements") - && otherCivilization.hasUnique("Enables Open Borders agreements")) { + && civInfo.hasUnique(UniqueType.EnablesOpenBorders) + && otherCivilization.hasUnique(UniqueType.EnablesOpenBorders)) { offers.add(TradeOffer(Constants.openBorders, TradeType.Agreement)) } diff --git a/core/src/com/unciv/models/ruleset/tech/Technology.kt b/core/src/com/unciv/models/ruleset/tech/Technology.kt index 5c62aa3e61..a6e0b395c3 100644 --- a/core/src/com/unciv/models/ruleset/tech/Technology.kt +++ b/core/src/com/unciv/models/ruleset/tech/Technology.kt @@ -27,7 +27,7 @@ class Technology: RulesetObject() { fun era(): String = column!!.era - fun isContinuallyResearchable() = uniques.contains("Can be continually researched") + fun isContinuallyResearchable() = hasUnique(UniqueType.ResearchableMultipleTimes) /** diff --git a/core/src/com/unciv/models/ruleset/unique/UniqueType.kt b/core/src/com/unciv/models/ruleset/unique/UniqueType.kt index 872fe94373..896d29f13b 100644 --- a/core/src/com/unciv/models/ruleset/unique/UniqueType.kt +++ b/core/src/com/unciv/models/ruleset/unique/UniqueType.kt @@ -153,8 +153,8 @@ enum class UniqueType(val text:String, vararg targets: UniqueTarget, val flags: UnhappinessFromPopulationPercentageChange("[amount]% unhappiness from population [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief), UnhappinessFromSpecialistsPercentageChange("[amount]% unhappiness from specialists [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief), - FoodConsumptionBySpecialists("[amount]% food consumption by specialists [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief), - @Deprecated("As of 3.18.2", ReplaceWith("[-amount]% food consumption by specialists [cityFilter]"), DeprecationLevel.WARNING) + FoodConsumptionBySpecialists("[amount]% Food consumption by specialists [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief), + @Deprecated("As of 3.18.2", ReplaceWith("[-amount]% Food consumption by specialists [cityFilter]"), DeprecationLevel.WARNING) FoodConsumptionBySpecialistsDeprecated("-[amount]% food consumption by specialists [cityFilter]", UniqueTarget.Global), ExcessHappinessToGlobalStat("[amount]% of excess happiness converted to [stat]", UniqueTarget.Global), @@ -176,12 +176,21 @@ enum class UniqueType(val text:String, vararg targets: UniqueTarget, val flags: @Deprecated("As of 3.17.9", ReplaceWith ("May buy [baseUnitFilter] units for [amount] [stat] [cityFilter] at an increasing price ([amount]) ")) BuyUnitsIncreasingCostEra("May buy [baseUnitFilter] units for [amount] [stat] [cityFilter] starting from the [era] at an increasing price ([amount])", UniqueTarget.Global), + // ToDo: Unify + EnablesGoldProduction("Enables conversion of city production to gold", UniqueTarget.Global), + EnablesScienceProduction("Enables conversion of city production to science", UniqueTarget.Global), + BuyItemsDiscount("[stat] cost of purchasing items in cities [amount]%", UniqueTarget.Global, UniqueTarget.FollowerBelief), BuyBuildingsDiscount("[stat] cost of purchasing [buildingFilter] buildings [amount]%", UniqueTarget.Global, UniqueTarget.FollowerBelief), BuyUnitsDiscount("[stat] cost of purchasing [baseUnitFilter] units in cities [amount]%", UniqueTarget.Global, UniqueTarget.FollowerBelief), - RoadMaintenance("[amount]% maintenance on road & railroads", UniqueTarget.Global), // Should be replaced with moddable improvements when roads become moddable + + // Should be replaced with moddable improvements when roads become moddable + RoadMovementSpeed("Improves movement speed on roads",UniqueTarget.Global), + RoadsConnectAcrossRivers("Roads connect tiles across rivers", UniqueTarget.Global), + RoadMaintenance("[amount]% maintenance on road & railroads", UniqueTarget.Global), @Deprecated("As of 3.18.17", ReplaceWith("[-amount]% maintenance on road & railroads")) DecreasedRoadMaintenanceDeprecated("Maintenance on roads & railroads reduced by [amount]%", UniqueTarget.Global), + BuildingMaintenance("[amount]% maintenance cost for buildings [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief), @Deprecated("As of 3.18.17", ReplaceWith("[-amount]% maintenace cost for buildings [cityFilter]")) DecrasedBuildingMaintenanceDeprecated("-[amount]% maintenance cost for buildings [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief), @@ -199,6 +208,7 @@ enum class UniqueType(val text:String, vararg targets: UniqueTarget, val flags: @Deprecated("As of 3.18.17", ReplaceWith("[amount]% Culture cost of adopting new policies")) LessPolicyCostDeprecated("Culture cost of adopting new Policies reduced by [amount]%", UniqueTarget.Global), + EnablesOpenBorders("Enables Open Borders agreements", UniqueTarget.Global), // Should the 'R' in 'Research agreements' be capitalized? EnablesResearchAgreements("Enables Research agreements", UniqueTarget.Global), ScienceFromResearchAgreements("Science gained from research agreements [amount]%", UniqueTarget.Global), @@ -220,8 +230,6 @@ enum class UniqueType(val text:String, vararg targets: UniqueTarget, val flags: ReducedUpgradingGoldCost("Gold cost of upgrading [baseUnitFilter] units reduced by [amount]%", UniqueTarget.Unit, UniqueTarget.Global), @Deprecated("As of 3.18.17", ReplaceWith("[+100]% Gold from Great Merchant trade missions")) DoubleGoldFromTradeMissions("Double gold from Great Merchant trade missions", UniqueTarget.Global), - - IncompatibleWith("Incompatible with [policy/tech/promotion]", UniqueTarget.Policy, UniqueTarget.Tech, UniqueTarget.Promotion), GoldenAgeLength("[amount]% Golden Age length", UniqueTarget.Global), @Deprecated("As of 3.18.17", ReplaceWith("[+amount]% Golden Age length")) @@ -234,9 +242,16 @@ enum class UniqueType(val text:String, vararg targets: UniqueTarget, val flags: StrengthForCitiesAttacking("[amount]% Attacking Strength for cities", UniqueTarget.Global), UnitStartingExperience("New [baseUnitFilter] units start with [amount] Experience [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief), + // ToDo: make per unit and use unit filters? + LandUnitEmbarkation("Enables embarkation for land units", UniqueTarget.Global), + EmbarkedUnitsMayEnterOcean("Enables embarked units to enter ocean tiles", UniqueTarget.Global), + + IncompatibleWith("Incompatible with [policy/tech/promotion]", UniqueTarget.Policy, UniqueTarget.Tech, UniqueTarget.Promotion), + StartingTech("Starting tech", UniqueTarget.Tech), + ResearchableMultipleTimes("Can be continually researched", UniqueTarget.Global), + //endregion Global uniques - ///////////////////////////////////////// region CONSTRUCTION UNIQUES ///////////////////////////////////////// Unbuildable("Unbuildable", UniqueTarget.Building, UniqueTarget.Unit), diff --git a/core/src/com/unciv/ui/worldscreen/WorldScreen.kt b/core/src/com/unciv/ui/worldscreen/WorldScreen.kt index 4f379baf16..008df3580c 100644 --- a/core/src/com/unciv/ui/worldscreen/WorldScreen.kt +++ b/core/src/com/unciv/ui/worldscreen/WorldScreen.kt @@ -24,6 +24,7 @@ import com.unciv.logic.trade.TradeEvaluation import com.unciv.models.Tutorial import com.unciv.models.UncivSound import com.unciv.models.ruleset.tile.ResourceType +import com.unciv.models.ruleset.unique.UniqueType import com.unciv.models.translations.tr import com.unciv.ui.cityscreen.CityScreen import com.unciv.ui.civilopedia.CivilopediaScreen @@ -853,7 +854,7 @@ class WorldScreen(val gameInfo: GameInfo, val viewingCiv:CivilizationInfo) : Bas } displayTutorial(Tutorial.ApolloProgram) { viewingCiv.hasUnique("Enables construction of Spaceship parts") } displayTutorial(Tutorial.SiegeUnits) { viewingCiv.getCivUnits().any { it.baseUnit.isProbablySiegeUnit() } } - displayTutorial(Tutorial.Embarking) { viewingCiv.hasUnique("Enables embarkation for land units") } + displayTutorial(Tutorial.Embarking) { viewingCiv.hasUnique(UniqueType.LandUnitEmbarkation) } displayTutorial(Tutorial.NaturalWonders) { viewingCiv.naturalWonders.size > 0 } displayTutorial(Tutorial.WeLoveTheKingDay) { viewingCiv.cities.any { it.demandedResource != "" } } }