From 18f4d4e53e6565f2321fceeea762ce7565f0981b Mon Sep 17 00:00:00 2001 From: Yair Morgenstern Date: Thu, 28 Jan 2021 14:26:42 +0200 Subject: [PATCH] Added city filter, and gerenicised several uniques to work with the city filter. Deleted some deprecated uniques --- .../jsons/Civ V - Vanilla/Buildings.json | 15 ++--- .../jsons/Civ V - Vanilla/Policies.json | 6 +- core/src/com/unciv/logic/city/CityInfo.kt | 15 ++++- core/src/com/unciv/logic/city/CityStats.kt | 56 ++++++++++++------- .../logic/civilization/CivilizationInfo.kt | 11 +++- .../logic/civilization/GoldenAgeManager.kt | 5 -- .../com/unciv/models/ruleset/unit/BaseUnit.kt | 3 +- 7 files changed, 72 insertions(+), 39 deletions(-) diff --git a/android/assets/jsons/Civ V - Vanilla/Buildings.json b/android/assets/jsons/Civ V - Vanilla/Buildings.json index 16bfcce3cf..0483b447ec 100644 --- a/android/assets/jsons/Civ V - Vanilla/Buildings.json +++ b/android/assets/jsons/Civ V - Vanilla/Buildings.json @@ -209,7 +209,7 @@ "requiredNearbyImprovedResources": ["Horses","Sheep","Cattle"], "resourceBonusStats": {"production": 1}, "hurryCostModifier": 25, - "uniques": ["+[15]% production when building [mounted units] in this city"], + "uniques": ["+[15]% Production when constructing [Mounted] units [in this city]"] "requiredTech": "Horseback Riding" }, { @@ -463,7 +463,8 @@ "requiredNearbyImprovedResources": ["Iron"], "resourceBonusStats": {"production": 1}, "requiredTech": "Metal Casting", - "uniques": ["+[15]% production when building [land units] in this city", "+[15]% production when building [Spaceship part] in this city"] + "uniques": ["+[15]% Production when constructing [Spaceship part] units [in this city]", + "+[15]% Production when constructing [Land] units [in this city]"] }, { "name": "Harbor", @@ -599,7 +600,7 @@ "culture": 1, "isWonder": true, "greatPersonPoints": {"culture": 2}, - "uniques": ["+[25]% [Culture] in all cities"], + "uniques": ["+[25]% [Culture] [in all cities]"], "requiredTech": "Acoustics", "quote": "'I live and love in God's peculiar light.' - Michelangelo Buonarroti" }, @@ -707,7 +708,7 @@ "maintenance": 3, "requiredBuilding": "Harbor", "uniques": ["[+1 Production, +1 Gold] from [Water resource] tiles in this city", - "Must be next to [Coast]", "+[15]% production when building [naval units] in this city"], + "Must be next to [Coast]", "+[15]% Production when constructing [Water] units [in this city]"] "requiredTech": "Navigation" }, { @@ -735,7 +736,7 @@ "specialistSlots": {"Engineer": 1}, "hurryCostModifier": 25, "maintenance": 2, - "uniques": ["Must not be on [Hill]", "+[10]% production when building [Buildings] in this city"], + "uniques": ["Must not be on [Hill]", "+[10]% Production when constructing [Buildings] [in this city]"], "requiredTech": "Economics" }, @@ -996,7 +997,7 @@ "requiredResource": "Aluminum", "cost": 360, "requiredBuilding": "Factory", - "uniques": ["+[50]% production when building [Spaceship part] in this city"], + "uniques": ["+[50]% Production when constructing [Spaceship part] units [in this city]"], "requiredTech": "Robotics" }, { @@ -1022,7 +1023,7 @@ "greatPersonPoints": {"science": 1}, "providesFreeBuilding": "Spaceship Factory", "uniques": ["[2] free [Great Scientist] units appear", - "+[25]% production when building [Spaceship part] in this city"], + "+[25]% Production when constructing [Spaceship part] units [in this city]"], "requiredTech": "Satellites", "quote": "'The wonder is, not that the field of stars is so vast, but that man has measured it.' - Anatole France" // will be introduced in G&K expansion pack diff --git a/android/assets/jsons/Civ V - Vanilla/Policies.json b/android/assets/jsons/Civ V - Vanilla/Policies.json index a7a65a5af4..d92c1e8687 100644 --- a/android/assets/jsons/Civ V - Vanilla/Policies.json +++ b/android/assets/jsons/Civ V - Vanilla/Policies.json @@ -49,7 +49,7 @@ "policies": [ { "name": "Collective Rule", - "uniques": ["Training of settlers increased +50% in capital", "Free [Settler] appears"], + "uniques": ["+[50]% Production when constructing [Settler] units [in capital]", "Free [Settler] appears"], "row": 1, "column": 1 }, @@ -156,7 +156,7 @@ }, { "name": "Reformation", - "uniques": ["+33% culture in all cities with a world wonder", "Empire enters golden age"], + "uniques": ["+[33]% [Culture] [in all cities with a world wonder]", "Empire enters golden age"], "requires": ["Organized Religion"], "row": 2, "column": 3 @@ -213,7 +213,7 @@ },*/ { "name": "Commerce", - "uniques": ["+25% gold in capital"], + "uniques": ["+[25]% [Gold] [in capital]"], "era": "Medieval era", "policies": [ { diff --git a/core/src/com/unciv/logic/city/CityInfo.kt b/core/src/com/unciv/logic/city/CityInfo.kt index 5f17377b9b..2330c2f76d 100644 --- a/core/src/com/unciv/logic/city/CityInfo.kt +++ b/core/src/com/unciv/logic/city/CityInfo.kt @@ -99,8 +99,7 @@ class CityInfo { for (unique in civInfo.getMatchingUniques("Gain a free [] []")) { val freeBuildingName = unique.params[0] - val cityFilter = unique.params[1] - if (cityFilter == "in every city" || (cityFilter == "in every coastal city" && getCenterTile().isCoastalTile())) { + if (matchesFilter(unique.params[1])) { if (!cityConstructions.isBuilt(freeBuildingName)) cityConstructions.addBuilding(freeBuildingName) } @@ -648,5 +647,17 @@ class CityInfo { } return true } + + fun matchesFilter(filter: String): Boolean { + return when { + filter == "in this city" -> true + filter == "in all cities" -> true + filter == "in all coastal cities" && getCenterTile().isCoastalTile() -> true + filter == "in capital" && isCapital() -> true + filter == "in all cities with a world wonder" && cityConstructions.getBuiltBuildings().any { it.isWonder } -> true + else -> false + } + } + //endregion } \ No newline at end of file diff --git a/core/src/com/unciv/logic/city/CityStats.kt b/core/src/com/unciv/logic/city/CityStats.kt index 939726f607..39cd34256c 100644 --- a/core/src/com/unciv/logic/city/CityStats.kt +++ b/core/src/com/unciv/logic/city/CityStats.kt @@ -89,7 +89,7 @@ class CityStats { return stats } - private fun getStatPercentBonusesFromMarble(construction: IConstruction): Stats { + private fun getStatPercentBonusesFromResources(construction: IConstruction): Stats { val stats = Stats() if (construction is Building @@ -101,17 +101,6 @@ class CityStats { return stats } - private fun getStatPercentBonusesFromComputers(): Stats { - val stats = Stats() - - if (cityInfo.civInfo.hasUnique("+10% science and production in all cities")) { - stats.production += 10f - stats.science += 10f - } - - return stats - } - private fun getStatsFromNationUnique(): Stats { val stats = Stats() @@ -224,7 +213,7 @@ class CityStats { newHappinessList["National ability"] = getStatsFromUniques(cityInfo.civInfo.nation.uniqueObjects.asSequence()).happiness - newHappinessList["Wonders"] = getStatsFromUniques(civInfo.getBuildingUniques()).happiness + newHappinessList["Wonders"] = getStatsFromUniques(civInfo.getCivWideBuildingUniques()).happiness newHappinessList["Tile yields"] = getStatsFromTiles().happiness @@ -289,6 +278,7 @@ class CityStats { private fun getStatPercentBonusesFromBuildings(currentConstruction: IConstruction): Stats { val stats = cityInfo.cityConstructions.getStatPercentBonuses() + // Deprecated as of 3.12.11 - replaces with "+[amount]% Production when constructing [unitFilter] units [in this city]" for (unique in cityInfo.cityConstructions.builtBuildingUniqueMap.getUniques("+[]% production when building [] in this city")) { if (constructionMatchesFilter(currentConstruction, unique.params[1])) stats.production += unique.params[0].toInt() @@ -303,6 +293,7 @@ class CityStats { // Since this is sometimes run from a different thread (getConstructionButtonDTOs), // this helps mitigate concurrency problems. + // Deprecated as of 3.12.10 - changed to "+[50]% Production when constructing [Settler] units [in capital]" if (currentConstruction.name == Constants.settler && cityInfo.isCapital() && uniques.any { it.text == "Training of settlers increased +50% in capital" }) stats.production += 50f @@ -314,30 +305,54 @@ class CityStats { stats.production += unique.params[0].toInt() } + // For instance "+[50]% [Production] for (unique in uniques.filter { it.placeholderText == "+[]% [] in all cities"}) stats.add(Stat.valueOf(unique.params[1]), unique.params[0].toFloat()) + // Params: "+[amount]% [Stat] [cityFilter]", pretty crazy amirite + // For instance "+[50]% [Production] [in all cities] + for (unique in uniques.filter { it.placeholderText == "+[]% [] []"}) + if (cityInfo.matchesFilter(unique.params[2])) + stats.add(Stat.valueOf(unique.params[1]), unique.params[0].toFloat()) + for (unique in uniques.filter { it.placeholderText == "+[]% Production when constructing []" }) { if (constructionMatchesFilter(currentConstruction, unique.params[1])) stats.production += unique.params[0].toInt() } + // "+[amount]% Production when constructing [constructionFilter] [cityFilter]" + for (unique in uniques.filter { it.placeholderText == "+[]% Production when constructing [] []" }) { + if (constructionMatchesFilter(currentConstruction, unique.params[1]) && cityInfo.matchesFilter(unique.params[2])) + stats.production += unique.params[0].toInt() + } + + // Deprecated as of 3.12.10 - changed to "+[amount]% Production when constructing [unitFilter] units [in all cities]" for (unique in uniques.filter { it.placeholderText == "+[]% Production when constructing [] units" }) { if (currentConstruction is BaseUnit && currentConstruction.matchesFilter(unique.params[1])) stats.production += unique.params[0].toInt() } + // "+[amount]% Production when constructing [unitFilter] units [cityFilter]" + for (unique in uniques.filter { it.placeholderText == "+[]% Production when constructing [] units []" }) { + if (currentConstruction is BaseUnit && currentConstruction.matchesFilter(unique.params[1]) + && cityInfo.matchesFilter(unique.params[2])) + stats.production += unique.params[0].toInt() + } + + // Deprecated as of 3.12.10 - changed to "+[33]% [Culture] [in all cities with a world wonder]" if (cityInfo.cityConstructions.getBuiltBuildings().any { it.isWonder } && uniques.any { it.text == "+33% culture in all cities with a world wonder" }) stats.culture += 33f + // Deprecated as of 3.12.10 - changed to "+[25]% [Gold] [in capital]" (Commerce policy) if (uniques.any { it.text == "+25% gold in capital" } && cityInfo.isCapital()) stats.gold += 25f if (cityInfo.civInfo.getHappiness() >= 0 && uniques.any { it.text == "+15% science while empire is happy" }) stats.science += 15f + // Deprecated as of 3.12.10 - changed to "+[25]% [Culture] [in all cities]" (Sistine Chapel) if (uniques.any { it.text == "Culture in all cities increased by 25%" }) stats.culture += 25f @@ -389,15 +404,15 @@ class CityStats { } - fun updateStatPercentBonusList(currentConstruction:IConstruction) { + fun updateStatPercentBonusList(currentConstruction: IConstruction, citySpecificUniques: Sequence) { val newStatPercentBonusList = LinkedHashMap() newStatPercentBonusList["Golden Age"] = getStatPercentBonusesFromGoldenAge(cityInfo.civInfo.goldenAges.isGoldenAge()) newStatPercentBonusList["Policies"] = getStatPercentBonusesFromUniques(currentConstruction, cityInfo.civInfo.policies.policyUniques.getAllUniques()) - newStatPercentBonusList["Buildings"] = getStatPercentBonusesFromBuildings(currentConstruction) - newStatPercentBonusList["Wonders"] = getStatPercentBonusesFromUniques(currentConstruction, cityInfo.civInfo.getBuildingUniques()) + newStatPercentBonusList["Buildings"] = getStatPercentBonusesFromUniques(currentConstruction, citySpecificUniques) + .plus(getStatPercentBonusesFromBuildings(currentConstruction)) // This function is to be deprecated but it'll take a while. + newStatPercentBonusList["Wonders"] = getStatPercentBonusesFromUniques(currentConstruction, cityInfo.civInfo.getCivWideBuildingUniques()) newStatPercentBonusList["Railroad"] = getStatPercentBonusesFromRailroad() - newStatPercentBonusList["Marble"] = getStatPercentBonusesFromMarble(currentConstruction) - newStatPercentBonusList["Computers"] = getStatPercentBonusesFromComputers() + newStatPercentBonusList["Resources"] = getStatPercentBonusesFromResources(currentConstruction) newStatPercentBonusList["National ability"] = getStatPercentBonusesFromNationUnique(currentConstruction) newStatPercentBonusList["Puppet City"] = getStatPercentBonusesFromPuppetCity() @@ -411,10 +426,13 @@ class CityStats { } fun update(currentConstruction: IConstruction = cityInfo.cityConstructions.getCurrentConstruction()) { + + val citySpecificUniques: Sequence = cityInfo.cityConstructions.builtBuildingUniqueMap.getAllUniques() + .filter { it.params.size>0 && it.params.last()=="in this city" } // We need to compute Tile yields before happiness updateBaseStatList() updateCityHappiness() - updateStatPercentBonusList(currentConstruction) + updateStatPercentBonusList(currentConstruction, citySpecificUniques) updateFinalStatList(currentConstruction) // again, we don't edit the existing currentCityStats directly, in order to avoid concurrency exceptions diff --git a/core/src/com/unciv/logic/civilization/CivilizationInfo.kt b/core/src/com/unciv/logic/civilization/CivilizationInfo.kt index 78fdab918b..8d743ceabd 100644 --- a/core/src/com/unciv/logic/civilization/CivilizationInfo.kt +++ b/core/src/com/unciv/logic/civilization/CivilizationInfo.kt @@ -218,13 +218,20 @@ class CivilizationInfo { fun hasResource(resourceName: String): Boolean = getCivResourcesByName()[resourceName]!! > 0 - fun getBuildingUniques(): Sequence = cities.asSequence().flatMap { it.cityConstructions.builtBuildingUniqueMap.getAllUniques() } + fun getCivWideBuildingUniques(): Sequence = cities.asSequence().flatMap { + it.cityConstructions.builtBuildingUniqueMap.getAllUniques() + .filter { it.params.isEmpty() || it.params.last() != "in this city" } + } fun hasUnique(unique: String) = getMatchingUniques(unique).any() + // Does not return local uniques, only global ones. fun getMatchingUniques(uniqueTemplate: String): Sequence { return nation.uniqueObjects.asSequence().filter { it.placeholderText == uniqueTemplate } + - cities.asSequence().flatMap { it.cityConstructions.builtBuildingUniqueMap.getUniques(uniqueTemplate).asSequence() } + + cities.asSequence().flatMap { + it.cityConstructions.builtBuildingUniqueMap.getUniques(uniqueTemplate).asSequence() + .filter { it.params.isEmpty() || it.params.last() != "in this city" } + } + policies.policyUniques.getUniques(uniqueTemplate) + tech.getTechUniques().filter { it.placeholderText == uniqueTemplate } } diff --git a/core/src/com/unciv/logic/civilization/GoldenAgeManager.kt b/core/src/com/unciv/logic/civilization/GoldenAgeManager.kt index 7d87e20d34..d2ba2557a5 100644 --- a/core/src/com/unciv/logic/civilization/GoldenAgeManager.kt +++ b/core/src/com/unciv/logic/civilization/GoldenAgeManager.kt @@ -26,11 +26,6 @@ class GoldenAgeManager{ fun enterGoldenAge(unmodifiedNumberOfTurns: Int = 10) { var turnsToGoldenAge = unmodifiedNumberOfTurns.toFloat() - - // as of 3.10.7 This is to be deprecated and converted to "Golden Age length increased by []%" - keeping it here to that mods with this can still work for now - for(unique in civInfo.getMatchingUniques("Golden Age length increases +50%")) - turnsToGoldenAge *= 1.5f - for(unique in civInfo.getMatchingUniques("Golden Age length increased by []%")) turnsToGoldenAge *= (unique.params[0].toFloat()/100 + 1) turnsToGoldenAge *= civInfo.gameInfo.gameParameters.gameSpeed.modifier diff --git a/core/src/com/unciv/models/ruleset/unit/BaseUnit.kt b/core/src/com/unciv/models/ruleset/unit/BaseUnit.kt index 6001328f5e..98c668643d 100644 --- a/core/src/com/unciv/models/ruleset/unit/BaseUnit.kt +++ b/core/src/com/unciv/models/ruleset/unit/BaseUnit.kt @@ -191,7 +191,8 @@ class BaseUnit : INamed, IConstruction { val filter = unique.params[0] val promotion = unique.params[1] - if (unit.matchesFilter(filter) || (filter == "relevant" && civInfo.gameInfo.ruleSet.unitPromotions.values.any { unit.type.toString() in it.unitTypes && it.name == promotion })) + if (unit.matchesFilter(filter) || (filter == "relevant" && civInfo.gameInfo.ruleSet.unitPromotions.values + .any { unit.type.name in it.unitTypes && it.name == promotion })) unit.promotions.addPromotion(promotion, isFree = true) }