diff --git a/android/assets/jsons/Civ V - Vanilla/Policies.json b/android/assets/jsons/Civ V - Vanilla/Policies.json index b55081d44a..af77c06b14 100644 --- a/android/assets/jsons/Civ V - Vanilla/Policies.json +++ b/android/assets/jsons/Civ V - Vanilla/Policies.json @@ -346,7 +346,7 @@ { "name": "Rationalism Complete", "effect": "+1 gold from all science buildings", - "unique": ["[+1 Gold] from all [Science] buildings"] + "uniques": ["[+1 Gold] from all [Science] buildings"] } ] }, @@ -397,7 +397,7 @@ "name": "Freedom", "era": "Renaissance era", "effect": "+25% great people rate", - "unique": "+[25]% great person generation in all cities", + "uniques": ["+[25]% great person generation in all cities"], "policies": [ { "name": "Constitution", @@ -416,6 +416,7 @@ { "name": "Civil Society", "effect": "-50% food consumption by specialists", + "uniques": ["-50% food consumption by specialists"], "row": 1, "column": 5 }, @@ -430,13 +431,15 @@ { "name": "Democracy", "effect": "Specialists produce half normal unhappiness", + "uniques": ["Specialists produce half normal unhappiness"], "requires": ["Civil Society"], "row": 2, "column": 5 }, { "name": "Freedom Complete", - "effect": "Tile yield from great improvement +100%, golden ages increase by 50%" + "effect": "Tile yield from great improvement +100%, golden ages increase by 50%", + "uniques": ["Tile yield from Great Improvements +100%", "Golden Age length increases +50%"] } ] }, @@ -444,22 +447,26 @@ "name": "Autocracy", "era": "Industrial era", "effect": "-33% unit upkeep costs", + "uniques": ["-33% unit upkeep costs"], "policies": [ { "name": "Populism", "effect": "Wounded military units deal +25% damage", + "uniques": ["Wounded military units deal +25% damage"], "row": 1, "column": 1 }, { "name": "Militarism", "effect": "Gold cost of purchasing units -33%", + "uniques": ["Gold cost of purchasing units -33%"], "row": 1, "column": 5 }, { "name": "Fascism", "effect": "Quantity of strategic resources produced by the empire increased by 100%", + "uniques": ["Quantity of strategic resources produced by the empire increased by 100%"], "requires": ["Populism","Militarism"], "row": 2, "column": 3 @@ -467,6 +474,7 @@ { "name": "Police State", "effect": "+3 Happiness from every Courthouse. Build Courthouses in half the usual time.", + "uniques": ["[+3 Happiness] from every [Courthouse]", "+[100]% Production when constructing [Courthouse]"], "requires": ["Militarism"], "row": 2, "column": 5 @@ -474,6 +482,7 @@ { "name": "Total War", "effect": "+15% production when building military units and new military units start with 15 Experience", + "uniques": ["+[15]% Production when constructing [military units]", "New military units start with [15] Experience"], "requires": ["Police State","Fascism"], "row": 3, "column": 4 @@ -481,6 +490,7 @@ { "name": "Autocracy Complete", "effect": "+20% attack bonus to all Military Units for 30 turns" + "uniques": ["+20% attack bonus to all Military Units for 30 turns"] } ] } diff --git a/core/src/com/unciv/logic/battle/BattleDamage.kt b/core/src/com/unciv/logic/battle/BattleDamage.kt index c2218f1235..2f6f3bb6e6 100644 --- a/core/src/com/unciv/logic/battle/BattleDamage.kt +++ b/core/src/com/unciv/logic/battle/BattleDamage.kt @@ -67,8 +67,8 @@ object BattleDamage { if (civHappiness < 0) modifiers["Unhappiness"] = max(0.02f * civHappiness, -0.9f) // otherwise it could exceed -100% and start healing enemy units... - if (civInfo.policies.hasEffect("Wounded military units deal +25% damage") && combatant.getHealth() < 100) { - modifiers["Populism"] = 0.25f + if (civInfo.hasUnique("Wounded military units deal +25% damage") && combatant.getHealth() < 100) { + modifiers["Wounded unit"] = 0.25f } if (civInfo.hasUnique("+15% combat strength for melee units which have another military unit in an adjacent tile") @@ -103,7 +103,7 @@ object BattleDamage { if (enemy.getCivInfo().isBarbarian()) { modifiers["Difficulty"] = civInfo.gameInfo.getDifficulty().barbarianBonus - if (civInfo.policies.hasEffect("+25% bonus vs Barbarians")) + if (civInfo.hasUnique("+25% bonus vs Barbarians")) modifiers["vs Barbarians"] = 0.25f } diff --git a/core/src/com/unciv/logic/city/CityConstructions.kt b/core/src/com/unciv/logic/city/CityConstructions.kt index f96b067036..864ae937f8 100644 --- a/core/src/com/unciv/logic/city/CityConstructions.kt +++ b/core/src/com/unciv/logic/city/CityConstructions.kt @@ -76,7 +76,7 @@ class CityConstructions { fun getMaintenanceCosts(): Int { var maintenanceCost = getBuiltBuildings().sumBy { it.maintenance } val policyManager = cityInfo.civInfo.policies - if (policyManager.isAdopted("Legalism") && cityInfo.id in policyManager.legalismState) { + if (cityInfo.id in policyManager.legalismState) { val buildingName = policyManager.legalismState[cityInfo.id] maintenanceCost -= cityInfo.getRuleset().buildings[buildingName]!!.maintenance } diff --git a/core/src/com/unciv/logic/city/CityInfo.kt b/core/src/com/unciv/logic/city/CityInfo.kt index d9a5ca7989..e34ea70aec 100644 --- a/core/src/com/unciv/logic/city/CityInfo.kt +++ b/core/src/com/unciv/logic/city/CityInfo.kt @@ -197,7 +197,7 @@ class CityInfo { var amountToAdd = 1 if(resource.resourceType == ResourceType.Strategic) { amountToAdd = 2 - if (civInfo.policies.hasEffect("Quantity of strategic resources produced by the empire increased by 100%")) + if (civInfo.hasUnique("Quantity of strategic resources produced by the empire increased by 100%")) amountToAdd *= 2 if (civInfo.nation.unique == UniqueAbility.SIBERIAN_RICHES && resource.name in listOf("Horses", "Iron", "Uranium")) amountToAdd *= 2 diff --git a/core/src/com/unciv/logic/city/CityStats.kt b/core/src/com/unciv/logic/city/CityStats.kt index 33874c3784..6f6ffa412a 100644 --- a/core/src/com/unciv/logic/city/CityStats.kt +++ b/core/src/com/unciv/logic/city/CityStats.kt @@ -4,8 +4,6 @@ import com.unciv.Constants import com.unciv.UncivGame import com.unciv.UniqueAbility import com.unciv.logic.civilization.CityStateType -import com.unciv.logic.civilization.CivilizationInfo -import com.unciv.logic.civilization.PolicyManager import com.unciv.logic.civilization.diplomacy.RelationshipLevel import com.unciv.logic.map.RoadStatus import com.unciv.models.ruleset.Building @@ -195,7 +193,7 @@ class CityStats { newHappinessList["Cities"] = unhappinessFromCity * unhappinessModifier var unhappinessFromCitizens = cityInfo.population.population.toFloat() - if (civInfo.policies.hasEffect("Specialists produce half normal unhappiness")) + if (civInfo.hasUnique("Specialists produce half normal unhappiness")) unhappinessFromCitizens -= cityInfo.population.getNumberOfSpecialists() * 0.5f if (cityInfo.isPuppet) @@ -249,7 +247,7 @@ class CityStats { return !cityInfo.containsBuildingUnique("Remove extra unhappiness from annexed cities") } - fun getStatsOfSpecialist(stat: Stat, policies: HashSet): Stats { + fun getStatsOfSpecialist(stat: Stat): Stats { val stats = Stats() if (stat == Stat.Culture || stat == Stat.Science) stats.add(stat, 3f) else stats.add(stat, 2f) // science and gold specialists @@ -266,14 +264,14 @@ class CityStats { private fun getStatsFromSpecialists(specialists: Stats, policies: HashSet): Stats { val stats = Stats() for (entry in specialists.toHashMap().filter { it.value > 0 }) - stats.add(getStatsOfSpecialist(entry.key, policies) * entry.value) + stats.add(getStatsOfSpecialist(entry.key) * entry.value) return stats } - private fun getStatsFromUniques(uniques: Sequence):Stats{ + private fun getStatsFromUniques(uniques: Sequence):Stats { val stats = Stats() - for(unique in uniques) { + for (unique in uniques) { val placeholderText = unique.getPlaceholderText() if ((placeholderText == "[] in capital" && cityInfo.isCapital()) || placeholderText == "[] in all cities" @@ -284,24 +282,14 @@ class CityStats { val amountOfEffects = (cityInfo.population.population / placeholderParams[1].toInt()).toFloat() stats.add(Stats.parse(placeholderParams[0]).times(amountOfEffects)) } + if (unique == "+1 gold and -1 unhappiness for every 2 citizens in capital" && cityInfo.isCapital()) + stats.gold += (cityInfo.population.population / 2).toFloat() } - return stats - } - - private fun getStatsFromPolicies(adoptedPolicies: PolicyManager): Stats { - val stats = Stats() - stats.add(getStatsFromUniques(adoptedPolicies.policyEffects.asSequence())) - - if (adoptedPolicies.hasEffect("+1 gold and -1 unhappiness for every 2 citizens in capital") && cityInfo.isCapital()) - stats.gold += (cityInfo.population.population / 2).toFloat() - if (adoptedPolicies.hasEffect("+1 production in every city, +5% production when constructing buildings")) - stats.production += 1f - if (adoptedPolicies.hasEffect("+1 culture for every 2 citizens")) - stats.culture += (cityInfo.population.population / 2).toFloat() return stats } + private fun getStatPercentBonusesFromGoldenAge(isGoldenAge: Boolean): Stats { val stats = Stats() if (isGoldenAge) { @@ -363,9 +351,13 @@ class CityStats { stats.production += placeholderParams[0].toInt() } - if (currentConstruction is Building && currentConstruction.name == "Courthouse" - && cityInfo.civInfo.policies.hasEffect("+3 Happiness from every Courthouse. Build Courthouses in half the usual time.")) - stats.production += 100 + for(unique in cityInfo.civInfo.getMatchingUniques("+[]% Production when constructing []")) { + val placeholderParams = unique.getPlaceholderParameters() + val filter = placeholderParams[1] + if (currentConstruction.name == filter + || (filter=="military units" && currentConstruction is BaseUnit && !currentConstruction.unitType.isCivilian())) + stats.production += placeholderParams[0].toInt() + } if (cityConstructions.getBuiltBuildings().any { it.isWonder } && cityInfo.civInfo.hasUnique("+33% culture in all cities with a world wonder")) @@ -374,8 +366,6 @@ class CityStats { stats.gold += 25f if (cityInfo.civInfo.getHappiness() >= 0 && cityInfo.civInfo.hasUnique("+15% science while empire is happy")) stats.science += 15f - if (policies.contains("Total War") && currentConstruction is BaseUnit && !currentConstruction.unitType.isCivilian()) - stats.production += 15f if (cityInfo.civInfo.hasUnique("+15% production when constructing wonders") && currentConstruction is Building && currentConstruction.isWonder) @@ -405,7 +395,7 @@ class CityStats { newBaseStatList["Specialists"] = getStatsFromSpecialists(cityInfo.population.specialists, civInfo.policies.adoptedPolicies) newBaseStatList["Trade routes"] = getStatsFromTradeRoute() newBaseStatList["Buildings"] = cityInfo.cityConstructions.getStats() - newBaseStatList["Policies"] = getStatsFromPolicies(civInfo.policies) + newBaseStatList["Policies"] = getStatsFromUniques(civInfo.policies.policyEffects.asSequence()) newBaseStatList["National ability"] = getStatsFromNationUnique() newBaseStatList["Wonders"] = getStatsFromUniques(civInfo.cities.asSequence().flatMap { it.getBuildingUniques() }) newBaseStatList["City-States"] = getStatsFromCityStates() @@ -414,24 +404,24 @@ class CityStats { } - fun updateStatPercentBonusList(){ - val newStatPercentBonusList = LinkedHashMap() - newStatPercentBonusList["Golden Age"]=getStatPercentBonusesFromGoldenAge(cityInfo.civInfo.goldenAges.isGoldenAge()) - newStatPercentBonusList["Policies"]=getStatPercentBonusesFromPolicies(cityInfo.civInfo.policies.adoptedPolicies, cityInfo.cityConstructions) - newStatPercentBonusList["Buildings"]=getStatPercentBonusesFromBuildings() - newStatPercentBonusList["Railroad"]=getStatPercentBonusesFromRailroad() - newStatPercentBonusList["Marble"]=getStatPercentBonusesFromMarble() - newStatPercentBonusList["Computers"]=getStatPercentBonusesFromComputers() - newStatPercentBonusList["National ability"]=getStatPercentBonusesFromNationUnique() - newStatPercentBonusList["Puppet City"]=getStatPercentBonusesFromPuppetCity() + fun updateStatPercentBonusList() { + val newStatPercentBonusList = LinkedHashMap() + newStatPercentBonusList["Golden Age"] = getStatPercentBonusesFromGoldenAge(cityInfo.civInfo.goldenAges.isGoldenAge()) + newStatPercentBonusList["Policies"] = getStatPercentBonusesFromPolicies(cityInfo.civInfo.policies.adoptedPolicies, cityInfo.cityConstructions) + newStatPercentBonusList["Buildings"] = getStatPercentBonusesFromBuildings() + newStatPercentBonusList["Railroad"] = getStatPercentBonusesFromRailroad() + newStatPercentBonusList["Marble"] = getStatPercentBonusesFromMarble() + newStatPercentBonusList["Computers"] = getStatPercentBonusesFromComputers() + newStatPercentBonusList["National ability"] = getStatPercentBonusesFromNationUnique() + newStatPercentBonusList["Puppet City"] = getStatPercentBonusesFromPuppetCity() - if(UncivGame.Current.superchargedForDebug) { + if (UncivGame.Current.superchargedForDebug) { val stats = Stats() - for(stat in Stat.values()) stats.add(stat,10000f) + for (stat in Stat.values()) stats.add(stat, 10000f) newStatPercentBonusList["Supercharged"] = stats } - statPercentBonusList=newStatPercentBonusList + statPercentBonusList = newStatPercentBonusList } fun update() { @@ -526,7 +516,7 @@ class CityStats { private fun updateFoodEaten() { foodEaten = (cityInfo.population.population * 2).toFloat() - if (cityInfo.civInfo.policies.hasEffect("Specialists produce half normal unhappiness")) + if (cityInfo.civInfo.hasUnique("-50% food consumption by specialists")) foodEaten -= cityInfo.population.getNumberOfSpecialists() } diff --git a/core/src/com/unciv/logic/city/PopulationManager.kt b/core/src/com/unciv/logic/city/PopulationManager.kt index b5ac6d680a..af50e83466 100644 --- a/core/src/com/unciv/logic/city/PopulationManager.kt +++ b/core/src/com/unciv/logic/city/PopulationManager.kt @@ -7,7 +7,6 @@ import com.unciv.models.stats.Stat import com.unciv.models.stats.Stats import com.unciv.ui.utils.withItem import com.unciv.ui.utils.withoutItem -import kotlin.math.roundToInt class PopulationManager { @Transient @@ -86,14 +85,13 @@ class PopulationManager { //evaluate specialists val maxSpecialistsMap = getMaxSpecialists().toHashMap() - val policies = cityInfo.civInfo.policies.adoptedPolicies val bestJob: Stat? = specialists.toHashMap() .filter { maxSpecialistsMap.containsKey(it.key) && it.value < maxSpecialistsMap[it.key]!! } .map { it.key } - .maxBy { Automation.rankSpecialist(cityInfo.cityStats.getStatsOfSpecialist(it, policies), cityInfo) } + .maxBy { Automation.rankSpecialist(cityInfo.cityStats.getStatsOfSpecialist(it), cityInfo) } var valueBestSpecialist = 0f if (bestJob != null) { - val specialistStats = cityInfo.cityStats.getStatsOfSpecialist(bestJob, policies) + val specialistStats = cityInfo.cityStats.getStatsOfSpecialist(bestJob) valueBestSpecialist = Automation.rankSpecialist(specialistStats, cityInfo) } @@ -137,10 +135,10 @@ class PopulationManager { val worstJob: Stat? = specialists.toHashMap() .filter { it.value > 0 } .map {it.key} - .minBy { Automation.rankSpecialist(cityInfo.cityStats.getStatsOfSpecialist(it, policies), cityInfo) } + .minBy { Automation.rankSpecialist(cityInfo.cityStats.getStatsOfSpecialist(it), cityInfo) } var valueWorstSpecialist = 0f if (worstJob != null) - valueWorstSpecialist = Automation.rankSpecialist(cityInfo.cityStats.getStatsOfSpecialist(worstJob, policies), cityInfo) + valueWorstSpecialist = Automation.rankSpecialist(cityInfo.cityStats.getStatsOfSpecialist(worstJob), cityInfo) //un-assign population if ((worstWorkedTile != null && valueWorstTile < valueWorstSpecialist) diff --git a/core/src/com/unciv/logic/civilization/CivInfoStats.kt b/core/src/com/unciv/logic/civilization/CivInfoStats.kt index 7a3554d39a..517d4fd7f7 100644 --- a/core/src/com/unciv/logic/civilization/CivInfoStats.kt +++ b/core/src/com/unciv/logic/civilization/CivInfoStats.kt @@ -38,7 +38,7 @@ class CivInfoStats(val civInfo: CivilizationInfo){ cost = cost.pow(1+gameProgress/3) // Why 3? To spread 1 to 1.33 if(!civInfo.isPlayerCivilization()) cost *= civInfo.gameInfo.getDifficulty().aiUnitMaintenanceModifier - if(civInfo.policies.hasEffect("-33% unit upkeep costs")) cost *= 0.66f + if(civInfo.hasUnique("-33% unit upkeep costs")) cost *= 0.66f return cost.toInt() } diff --git a/core/src/com/unciv/logic/civilization/GoldenAgeManager.kt b/core/src/com/unciv/logic/civilization/GoldenAgeManager.kt index f5ef5c83ec..3326f617d1 100644 --- a/core/src/com/unciv/logic/civilization/GoldenAgeManager.kt +++ b/core/src/com/unciv/logic/civilization/GoldenAgeManager.kt @@ -27,10 +27,10 @@ class GoldenAgeManager{ fun enterGoldenAge() { var turnsToGoldenAge = 10.0 - if (civInfo.hasUnique("Golden Age length increases +50%")) turnsToGoldenAge *= 1.5 + for(unique in civInfo.getMatchingUniques("Golden Age length increases +50%")) + turnsToGoldenAge *= 1.5 if(civInfo.nation.unique == UniqueAbility.ACHAEMENID_LEGACY ) turnsToGoldenAge*=1.5 - if (civInfo.policies.isAdopted("Freedom Complete")) turnsToGoldenAge *= 1.5 turnsToGoldenAge *= civInfo.gameInfo.gameParameters.gameSpeed.modifier turnsLeftForCurrentGoldenAge += turnsToGoldenAge.toInt() civInfo.addNotification("You have entered a golden age!", null, Color.GOLD) diff --git a/core/src/com/unciv/logic/civilization/PolicyManager.kt b/core/src/com/unciv/logic/civilization/PolicyManager.kt index ea23a0de84..42bd8f7370 100644 --- a/core/src/com/unciv/logic/civilization/PolicyManager.kt +++ b/core/src/com/unciv/logic/civilization/PolicyManager.kt @@ -43,9 +43,8 @@ class PolicyManager { fun getPolicyByName(name:String): Policy = getAllPolicies().first { it.name==name } fun setTransients(){ - val effectsOfCurrentPolicies = adoptedPolicies.map { getPolicyByName(it).effect } - policyEffects.addAll(effectsOfCurrentPolicies) - adoptedPolicies.map { getPolicyByName(it).uniques }.forEach { policyEffects.addAll(it) } + for(policy in adoptedPolicies) + policyEffects.addAll(getPolicyByName(policy).uniques) } private fun getAllPolicies() = civInfo.gameInfo.ruleSet.policyBranches.values.asSequence() @@ -118,7 +117,6 @@ class PolicyManager { } adoptedPolicies.add(policy.name) - policyEffects.add(policy.effect) policyEffects.addAll(policy.uniques) if (!branchCompletion) { @@ -130,7 +128,7 @@ class PolicyManager { val hasCapital = civInfo.cities.any { it.isCapital() } - for(effect in policy.uniques.withItem(policy.effect)) + for(effect in policy.uniques) when (effect.getPlaceholderText()) { "Free [] appears" -> { val unitName = effect.getPlaceholderParameters()[0] diff --git a/core/src/com/unciv/logic/map/TileInfo.kt b/core/src/com/unciv/logic/map/TileInfo.kt index 0f8d2e31fb..69f49da9c3 100644 --- a/core/src/com/unciv/logic/map/TileInfo.kt +++ b/core/src/com/unciv/logic/map/TileInfo.kt @@ -262,7 +262,7 @@ open class TileInfo { stats.science += 1f if (containsGreatImprovement() - && observingCiv.policies.hasEffect("Tile yield from great improvement +100%, golden ages increase by 50%")) + && observingCiv.hasUnique("Tile yield from Great Improvements +100%")) stats.add(improvement) // again, for the double effect if (containsGreatImprovement() && city != null && city.civInfo.nation.unique == UniqueAbility.SCHOLARS_OF_THE_JADE_HALL) stats.science += 2 diff --git a/core/src/com/unciv/models/ruleset/unit/BaseUnit.kt b/core/src/com/unciv/models/ruleset/unit/BaseUnit.kt index 6599442d09..fa8a02b41e 100644 --- a/core/src/com/unciv/models/ruleset/unit/BaseUnit.kt +++ b/core/src/com/unciv/models/ruleset/unit/BaseUnit.kt @@ -103,7 +103,7 @@ class BaseUnit : INamed, IConstruction { override fun getGoldCost(civInfo: CivilizationInfo): Int { var cost = getBaseGoldCost() - if (civInfo.policies.adoptedPolicies.contains("Militarism")) cost *= 0.66f + if (civInfo.hasUnique("Gold cost of purchasing units -33%")) cost *= 0.66f for(unique in civInfo.getMatchingUniques("Cost of purchasing items in cities reduced by []%")) cost *= 1-(unique.getPlaceholderParameters()[0].toFloat()) return (cost / 10).toInt() * 10 // rounded down o nearest ten @@ -159,7 +159,8 @@ class BaseUnit : INamed, IConstruction { if (this.unitType.isCivilian()) return true // tiny optimization makes save files a few bytes smaller var XP = construction.getBuiltBuildings().sumBy { it.xpForNewUnits } - if (construction.cityInfo.civInfo.policies.isAdopted("Total War")) XP += 15 + for (unique in construction.cityInfo.civInfo.getMatchingUniques("New military units start with [] Experience")) + XP += unique.getPlaceholderParameters()[0].toInt() unit.promotions.XP = XP if (unit.type in listOf(UnitType.Melee,UnitType.Mounted,UnitType.Armor) diff --git a/core/src/com/unciv/ui/cityscreen/SpecialistAllocationTable.kt b/core/src/com/unciv/ui/cityscreen/SpecialistAllocationTable.kt index 3ac4aad360..0441f02d1a 100644 --- a/core/src/com/unciv/ui/cityscreen/SpecialistAllocationTable.kt +++ b/core/src/com/unciv/ui/cityscreen/SpecialistAllocationTable.kt @@ -76,7 +76,7 @@ class SpecialistAllocationTable(val cityScreen: CityScreen): Table(CameraStageBa private fun getSpecialistStatsTable(stat: Stat): Table { val specialistStatTable = Table().apply { defaults().pad(5f) } - val specialistStats = cityInfo.cityStats.getStatsOfSpecialist(stat, cityInfo.civInfo.policies.adoptedPolicies).toHashMap() + val specialistStats = cityInfo.cityStats.getStatsOfSpecialist(stat).toHashMap() for (entry in specialistStats) { if (entry.value == 0f) continue specialistStatTable.add(ImageGetter.getStatIcon(entry.key.toString())).size(20f)