Map size will modify policy cost, techUniques is initialized by UniqueMap(), Replace "effect" with "uniques" in UnitPromotions.json (#4507)

* Map size will modify policy cost, techUniques is initialized by UniqueMap()

* Replace "effect" with "uniques" in UnitPromotions.json
This commit is contained in:
lishaoxia1985 2021-08-03 00:17:26 +08:00 committed by GitHub
parent c9fa68f8ea
commit e993f507aa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 102 additions and 95 deletions

View File

@ -9,130 +9,130 @@
// Ranged+Siege
{
"name": "Accuracy I",
"effect": "+[15]% Strength in [Open terrain]",
"uniques": ["+[15]% Strength in [Open terrain]"],
"unitTypes": ["Siege","Ranged"]
},
{
"name": "Accuracy II",
"prerequisites": ["Accuracy I"],
"effect": "+[15]% Strength in [Open terrain]",
"uniques": ["+[15]% Strength in [Open terrain]"],
"unitTypes": ["Siege","Ranged"]
},
{
"name": "Accuracy III",
"prerequisites": ["Accuracy II"],
"effect": "+[15]% Strength in [Open terrain]",
"uniques": ["+[15]% Strength in [Open terrain]"],
"unitTypes": ["Siege","Ranged"]
},
{
"name": "Barrage I",
"effect": "+[15]% Strength in [Rough terrain]",
"uniques": ["+[15]% Strength in [Rough terrain]"],
"unitTypes": ["Siege","Ranged"]
},
{
"name": "Barrage II",
"prerequisites": ["Barrage I"],
"effect": "+[15]% Strength in [Rough terrain]",
"uniques": ["+[15]% Strength in [Rough terrain]"],
"unitTypes": ["Siege","Ranged"]
},
{
"name": "Barrage III",
"prerequisites": ["Barrage II"],
"effect": "+[15]% Strength in [Rough terrain]",
"uniques": ["+[15]% Strength in [Rough terrain]"],
"unitTypes": ["Siege","Ranged"]
},
{
"name": "Volley",
"prerequisites": ["Accuracy I","Barrage I"],
"effect": "+[50]% Strength vs [City]",
"uniques": ["+[50]% Strength vs [City]"],
"unitTypes": ["Ranged","Siege"]
},
{
"name": "Extended Range",
"prerequisites": ["Accuracy III","Barrage III","Targeting II","Bombardment II", "Wolfpack II"],
"effect": "[+1] Range",
"uniques": ["[+1] Range"],
"unitTypes": ["Ranged","Siege","WaterRanged","WaterSubmarine"]
},
{
"name": "Indirect Fire",
"prerequisites": ["Accuracy III", "Barrage III", "Bombardment II", "Targeting II"],
"effect": "Ranged attacks may be performed over obstacles",
"uniques": ["Ranged attacks may be performed over obstacles"],
"unitTypes": ["Ranged","Siege","WaterRanged"]
},
// Melee, Mounted+Armor
{
"name": "Shock I",
"effect": "+[15]% Strength in [Open terrain]",
"uniques": ["+[15]% Strength in [Open terrain]"],
"unitTypes": ["Melee","Mounted","Armor"]
},
{
"name": "Shock II",
"prerequisites": ["Shock I"],
"effect": "+[15]% Strength in [Open terrain]",
"uniques": ["+[15]% Strength in [Open terrain]"],
"unitTypes": ["Melee","Mounted","Armor"]
},
{
"name": "Shock III",
"prerequisites": ["Shock II"],
"effect": "+[15]% Strength in [Open terrain]",
"uniques": ["+[15]% Strength in [Open terrain]"],
"unitTypes": ["Melee","Mounted","Armor"]
},
{
"name": "Drill I",
"effect": "+[15]% Strength in [Rough terrain]",
"uniques": ["+[15]% Strength in [Rough terrain]"],
"unitTypes": ["Melee","Mounted","Armor"]
},
{
"name": "Drill II",
"prerequisites": ["Drill I"],
"effect": "+[15]% Strength in [Rough terrain]",
"uniques": ["+[15]% Strength in [Rough terrain]"],
"unitTypes": ["Melee","Mounted","Armor"]
},
{
"name": "Drill III",
"prerequisites": ["Drill II"],
"effect": "+[15]% Strength in [Rough terrain]",
"uniques": ["+[15]% Strength in [Rough terrain]"],
"unitTypes": ["Melee","Mounted","Armor"]
},
{
"name": "Charge",
"prerequisites": ["Shock II","Drill II"],
"effect": "+[33]% Strength vs [wounded units]",
"uniques": ["+[33]% Strength vs [wounded units]"],
"unitTypes": ["Mounted","Armor"]
},
{
"name": "Besiege", // Not called "Siege" in order to not conflict with siege type units for translations
"prerequisites": ["Shock II","Drill II"],
"effect": "+[50]% Strength vs [City]",
"uniques": ["+[50]% Strength vs [City]"],
"unitTypes": ["Melee"]
},
{
"name": "Formation I",
"prerequisites": ["Shock II","Drill II"], // G&K also has Accuracy II & Barrage II as possible prerequisites for this, but I couldn't find a source for the unittypes
"effect": "+[33]% Strength vs [Mounted]",
"uniques": ["+[33]% Strength vs [Mounted]"],
"unitTypes": ["Melee","Mounted"]
},
{
"name": "Formation II",
"prerequisites": ["Formation I"],
"effect": "+[33]% Strength vs [Mounted]",
"uniques": ["+[33]% Strength vs [Mounted]"],
"unitTypes": ["Melee","Mounted"]
},
{
"name": "Blitz",
"prerequisites": ["Shock III","Drill III"],
"effect": "[1] additional attacks per turn",
"uniques": ["[1] additional attacks per turn"],
"unitTypes": ["Melee","Mounted","Armor"]
},
{
"name": "Woodsman",
"prerequisites": ["Shock III","Drill III"],
"effect": "Double movement rate through Forest and Jungle",
"uniques": ["Double movement rate through Forest and Jungle"],
// This could be generalized: ["-[50]% movement costs through [Forest] tiles", "-[50]% movement costs through [Jungle] tiles"],
// but with how getMovementCostBetweenAdjacentTiles() is optimized, that's difficult to implement.
"unitTypes": ["Melee"]
@ -159,19 +159,19 @@
// Scout
{
"name": "Scouting I",
"effect": "[+1] Visibility Range",
"uniques": ["[+1] Visibility Range"],
"unitTypes": ["Scout"]
},
{
"name": "Scouting II",
"prerequisites": ["Scouting I"],
"effect": "[+1] Visibility Range",
"uniques": ["[+1] Visibility Range"],
"unitTypes": ["Scout"]
},
{
"name": "Scouting III",
"prerequisites": ["Scouting II"],
"effect": "[+1] Movement",
"uniques": ["[+1] Movement"],
"unitTypes": ["Scout"]
},
{
@ -196,19 +196,19 @@
// Water melee
{
"name": "Boarding Party I",
"effect": "+[15]% Strength vs [water units]",
"uniques": ["+[15]% Strength vs [water units]"],
"unitTypes": ["WaterMelee"]
},
{
"name": "Boarding Party II",
"prerequisites": ["Boarding Party I"],
"effect": "+[15]% Strength vs [water units]",
"uniques": ["+[15]% Strength vs [water units]"],
"unitTypes": ["WaterMelee"]
},
{
"name": "Boarding Party III",
"prerequisites": ["Boarding Party II"],
"effect": "+[15]% Strength vs [water units]",
"uniques": ["+[15]% Strength vs [water units]"],
"unitTypes": ["WaterMelee"]
},
@ -233,74 +233,74 @@
// Water Ranged
{
"name": "Targeting I",
"effect": "+[15]% Strength vs [water units]",
"uniques": ["+[15]% Strength vs [water units]"],
"unitTypes": ["WaterRanged"]
},
{
"name": "Targeting II",
"prerequisites": ["Targeting I"],
"effect": "+[15]% Strength vs [water units]",
"uniques": ["+[15]% Strength vs [water units]"],
"unitTypes": ["WaterRanged"]
},
{
"name": "Targeting III",
"prerequisites": ["Targeting II"],
"effect": "+[15]% Strength vs [water units]",
"uniques": ["+[15]% Strength vs [water units]"],
"unitTypes": ["WaterRanged"]
},
// Submarine
{
"name": "Wolfpack I",
"effect": "+[25]% Strength when attacking",
"uniques": ["+[25]% Strength when attacking"],
"unitTypes": ["WaterSubmarine"]
},
{
"name": "Wolfpack II",
"prerequisites": ["Wolfpack I"],
"effect": "+[25]% Strength when attacking",
"uniques": ["+[25]% Strength when attacking"],
"unitTypes": ["WaterSubmarine"]
},
{
"name": "Wolfpack III",
"prerequisites": ["Wolfpack II"],
"effect": "+[25]% Strength when attacking",
"uniques": ["+[25]% Strength when attacking"],
"unitTypes": ["WaterSubmarine"]
},
// Aircraft Carrier
{
"name": "Armor Plating I",
"effect": "+[25]% Strength when defending",
"uniques": ["+[25]% Strength when defending"],
"unitTypes": ["WaterAircraftCarrier"]
},
{
"name": "Armor Plating II",
"prerequisites": ["Armor Plating I"],
"effect": "+[25]% Strength when defending",
"uniques": ["+[25]% Strength when defending"],
"unitTypes": ["WaterAircraftCarrier"]
},
{
"name": "Armor Plating III",
"prerequisites": ["Armor Plating II"],
"effect": "+[25]% Strength when defending",
"uniques": ["+[25]% Strength when defending"],
"unitTypes": ["WaterAircraftCarrier"]
},
{
"name": "Flight Deck I",
"effect": "Can carry [1] extra [Air] units",
"uniques": ["Can carry [1] extra [Air] units"],
"unitTypes": ["WaterAircraftCarrier"]
},
{
"name": "Flight Deck II",
"prerequisites": ["Flight Deck I"],
"effect": "Can carry [1] extra [Air] units",
"uniques": ["Can carry [1] extra [Air] units"],
"unitTypes": ["WaterAircraftCarrier"]
},
{
"name": "Flight Deck III",
"prerequisites": ["Flight Deck II"],
"effect": "Can carry [1] extra [Air] units",
"uniques": ["Can carry [1] extra [Air] units"],
"unitTypes": ["WaterAircraftCarrier"]
},
@ -315,62 +315,62 @@
// Bomber
{
"name": "Siege I",
"effect": "+[33]% Strength vs [City]",
"uniques": ["+[33]% Strength vs [City]"],
"unitTypes": ["Bomber"]
},
{
"name": "Siege II",
"prerequisites": ["Siege I"],
"effect": "+[33]% Strength vs [City]",
"uniques": ["+[33]% Strength vs [City]"],
"unitTypes": ["Bomber"]
},
{
"name": "Siege III",
"prerequisites": ["Siege II"],
"effect": "+[34]% Strength vs [City]",
"uniques": ["+[34]% Strength vs [City]"],
"unitTypes": ["Bomber"]
},
{
"name": "Evasion",
"prerequisites": ["Siege II", "Bombardment II"],
"effect": "Damage taken from interception reduced by [50]%",
"uniques": ["Damage taken from interception reduced by [50]%"],
"unitTypes": ["Bomber"]
},
// Fighter
{
"name": "Interception I",
"effect": "[+33]% Damage when intercepting",
"uniques": ["[+33]% Damage when intercepting"],
"unitTypes": ["Fighter"]
},
{
"name": "Interception II",
"prerequisites": ["Interception I"],
"effect": "[+33]% Damage when intercepting",
"uniques": ["[+33]% Damage when intercepting"],
"unitTypes": ["Fighter"]
},
{
"name": "Interception III",
"prerequisites": ["Interception II"],
"effect": "[+34]% Damage when intercepting",
"uniques": ["[+34]% Damage when intercepting"],
"unitTypes": ["Fighter"]
},
/*
{
"name": "Dogfighting I",
"effect": "Bonus when performing air sweep [33]%", // todo
"uniques": ["Bonus when performing air sweep [33]%"], // todo
"unitTypes": ["Fighter"]
},
{
"name": "Dogfighting II",
"prerequisites": ["Dogfighting I"],
"effect": "Bonus when performing air sweep [33]%",
"uniques": ["Bonus when performing air sweep [33]%"],
"unitTypes": ["Fighter"]
},
{
"name": "Dogfighting III",
"prerequisites": ["Dogfighting II"],
"effect": "Bonus when performing air sweep [34]%",
"uniques": ["Bonus when performing air sweep [34]%"],
"unitTypes": ["Fighter"]
}
*/
@ -378,33 +378,33 @@
{
"name": "Air Targeting I",
"prerequisites": ["Interception I","Dogfighting I", "Siege I","Bombardment I"],
"effect": "+[33]% Strength vs [water units]",
"uniques": ["+[33]% Strength vs [water units]"],
"unitTypes": ["Fighter","Bomber"]
},
{
"name": "Air Targeting II",
"prerequisites": ["Air Targeting I"],
"effect": "+[33]% Strength vs [water units]",
"uniques": ["+[33]% Strength vs [water units]"],
"unitTypes": ["Fighter","Bomber"]
},
{
"name": "Sortie",
"prerequisites": ["Interception II", "Dogfighting II"],
"effect": "[1] extra interceptions may be made per turn",
"uniques": ["[1] extra interceptions may be made per turn"],
"unitTypes": ["Fighter"]
},
{
"name": "Operational Range",
"prerequisites": ["Interception I", /*"Dogfighting I",*/ "Siege I", "Bombardment I"],
"effect": "[+2] Range",
"uniques": ["[+2] Range"],
"unitTypes": ["Fighter","Bomber"]
},
{
"name": "Air Repair",
"prerequisites": ["Interception II", /*"Dogfighting II",*/ "Siege II", "Bombardment II"],
"effect": "Unit will heal every turn, even if it performs an action",
"uniques": ["Unit will heal every turn, even if it performs an action"],
"unitTypes": ["Fighter","Bomber"]
},
@ -424,39 +424,39 @@
{
"name": "March",
"prerequisites": ["Accuracy II","Barrage II","Shock III","Drill III"],
"effect": "Unit will heal every turn, even if it performs an action",
"uniques": ["Unit will heal every turn, even if it performs an action"],
"unitTypes": ["Melee","Ranged","Siege","Mounted"]
},
{
"name": "Mobility",
"prerequisites": ["Shock II","Drill II","Targeting I",
"Bombardment I","Boarding Party I", "Coastal Raider I", "Wolfpack I"],
"effect": "[+1] Movement",
"uniques": ["[+1] Movement"],
"unitTypes": ["Mounted","WaterMelee","WaterRanged","Armor","WaterSubmarine"]
},
{
"name": "Sentry",
"prerequisites": ["Accuracy I","Barrage I","Shock II","Drill II","Bombardment I","Targeting I","Boarding Party I","Coastal Raider I"],
"effect": "[+1] Visibility Range",
"uniques": ["[+1] Visibility Range"],
"unitTypes": ["Melee","Mounted","WaterRanged","Armor","WaterMelee"]
},
{
"name": "Logistics",
"prerequisites": ["Accuracy III","Barrage III","Targeting III", "Wolfpack III",
"Bombardment III", "Coastal Raider III","Boarding Party III","Siege III"],
"effect": "[1] additional attacks per turn",
"uniques": ["[1] additional attacks per turn"],
"unitTypes": ["Ranged","Siege","WaterMelee","WaterRanged","WaterSubmarine","Fighter","Bomber"]
},
{
"name": "Ambush I",
"effect": "+[33]% Strength vs [Armor]",
"uniques": ["+[33]% Strength vs [Armor]"],
"unitTypes": ["Melee","Fighter","Bomber"]
},
{
"name": "Ambush II",
"prerequisites": ["Ambush I"],
"effect": "+[33]% Strength vs [Armor]",
"uniques": ["+[33]% Strength vs [Armor]"],
"unitTypes": ["Melee","Fighter","Bomber"]
},
@ -464,49 +464,49 @@
// Water ranged and air units
{
"name": "Bombardment I",
"effect": "+[33]% Strength vs [land units]",
"uniques": ["+[33]% Strength vs [land units]"],
"unitTypes": ["WaterRanged","Fighter","Bomber"]
},
{
"name": "Bombardment II",
"prerequisites": ["Bombardment I"],
"effect": "+[33]% Strength vs [land units]",
"uniques": ["+[33]% Strength vs [land units]"],
"unitTypes": ["WaterRanged","Fighter","Bomber"]
},
{
"name": "Bombardment III",
"prerequisites": ["Bombardment II"],
"effect": "+[34]% Strength vs [land units]",
"uniques": ["+[34]% Strength vs [land units]"],
"unitTypes": ["WaterRanged","Fighter","Bomber"]
},
// Uniques
{
"name": "Morale", // Heroic Epic
"effect": "+[15]% Combat Strength"
"uniques": ["+[15]% Combat Strength"]
},
{
"name": "Great Generals I", // only for Companion Cavalry, Keshik and their subsequent upgrades
"effect": "[Great General] is earned [50]% faster"
"uniques": ["[Great General] is earned [50]% faster"]
},
{
"name": "Great Generals II", // only for Samurai and subsequent upgrades
"effect": "[Great General] is earned [100]% faster"
"uniques": ["[Great General] is earned [100]% faster"]
},
{
"name": "Quick Study", // only for Keshik and subsequent upgrades
"effect": "[50]% Bonus XP gain"
"uniques": ["[50]% Bonus XP gain"]
},
{
"name": "Haka War Dance", // only for Maori Warrior and subsequent upgrades
"effect": "[-10]% Strength for enemy [Military] units in adjacent [All] tiles"
"uniques": ["[-10]% Strength for enemy [Military] units in adjacent [All] tiles"]
},
{
"name": "Rejuvenation", // only for Units that have been close to Natural Wonder Fountain of Youth
"effect": "All healing effects doubled"
"uniques": ["All healing effects doubled"]
},
{
"name": "Slinger Withdraw", // only for Slinger and subsequent upgrades
"effect": "May withdraw before melee ([80]%)"
"uniques": ["May withdraw before melee ([80]%)"]
}
]

View File

@ -253,8 +253,8 @@ class CivilizationInfo {
city -> city.getMatchingUniquesWithNonLocalEffects(uniqueTemplate)
} +
policies.policyUniques.getUniques(uniqueTemplate) +
tech.getTechUniques().filter { it.placeholderText == uniqueTemplate } +
temporaryUniques.asSequence().filter { it.first.placeholderText == uniqueTemplate }.map { it.first }
tech.techUniques.getUniques(uniqueTemplate) +
temporaryUniques.filter { it.first.placeholderText == uniqueTemplate }.map { it.first }
}
//region Units

View File

@ -1,5 +1,6 @@
package com.unciv.logic.civilization
import com.unciv.logic.map.MapSize
import com.unciv.models.ruleset.Policy
import com.unciv.models.ruleset.UniqueMap
import com.unciv.models.ruleset.UniqueTriggerActivation
@ -89,7 +90,15 @@ class PolicyManager {
// round down to nearest 5
fun getCultureNeededForNextPolicy(): Int {
var policyCultureCost = 25 + (numberOfAdoptedPolicies * 6).toDouble().pow(1.7)
var cityModifier = 0.3f * (civInfo.cities.count { !it.isPuppet } - 1)
// https://civilization.fandom.com/wiki/Map_(Civ5)
val worldSizeModifier = with (civInfo.gameInfo.tileMap.mapParameters.mapSize) {
when {
radius >= MapSize.Huge.radius -> 0.05f
radius >= MapSize.Large.radius -> 0.075f
else -> 0.1f
}
}
var cityModifier = worldSizeModifier * (civInfo.cities.count { !it.isPuppet } - 1)
for (unique in civInfo.getMatchingUniques("Each city founded increases culture cost of policies []% less than normal"))
cityModifier *= 1 - unique.params[0].toFloat() / 100
@ -128,9 +137,8 @@ class PolicyManager {
if (freePolicies == 0 && storedCulture < getCultureNeededForNextPolicy())
return false
val hasAdoptablePolicies = civInfo.gameInfo.ruleSet.policies.values
.any { civInfo.policies.isAdoptable(it) }
return hasAdoptablePolicies
//Return true if there is a policy to adopt, else return false
return civInfo.gameInfo.ruleSet.policies.values.any { civInfo.policies.isAdoptable(it) }
}
fun adopt(policy: Policy, branchCompletion: Boolean = false) {
@ -157,11 +165,8 @@ class PolicyManager {
}
for (unique in policy.uniques) {
if (unique == "Triggers a global alert") {
triggerGlobalAlerts(policy)
} else if (unique.equalsPlaceholderText("Triggers the following global alert: []")) {
if (unique.equalsPlaceholderText("Triggers the following global alert: []"))
triggerGlobalAlerts(policy, unique.getPlaceholderParameters()[0])
}
}
for (unique in policy.uniqueObjects)
@ -196,7 +201,7 @@ class PolicyManager {
}
for (city in candidateCities) {
val builtBuilding = city.cityConstructions.addCultureBuilding()
if (builtBuilding != null) cultureBuildingsAdded[city.id] = builtBuilding!!
if (builtBuilding != null) cultureBuildingsAdded[city.id] = builtBuilding
}
}

View File

@ -4,7 +4,7 @@ import com.unciv.logic.city.CityInfo
import com.unciv.logic.map.MapSize
import com.unciv.logic.map.RoadStatus
import com.unciv.logic.map.TileInfo
import com.unciv.models.ruleset.Unique
import com.unciv.models.ruleset.UniqueMap
import com.unciv.models.ruleset.UniqueTriggerActivation
import com.unciv.models.ruleset.tech.Technology
import com.unciv.models.ruleset.unit.BaseUnit
@ -23,7 +23,7 @@ class TechManager {
@Transient
var researchedTechnologies = ArrayList<Technology>()
@Transient
private var researchedTechUniques = ArrayList<Unique>()
internal var techUniques = UniqueMap()
// MapUnit.canPassThrough is the most called function in the game, and having these extremely specific booleans is or way of improving the time cost
@Transient
@ -84,11 +84,11 @@ class TechManager {
.count { it.isMajorCiv() && !it.isDefeated() }
// https://forums.civfanatics.com/threads/the-mechanics-of-overflow-inflation.517970/
techCost /= 1 + techsResearchedKnownCivs / undefeatedCivs.toFloat() * 0.3f
// http://www.civclub.net/bbs/forum.php?mod=viewthread&tid=123976
// https://civilization.fandom.com/wiki/Map_(Civ5)
val worldSizeModifier = with (civInfo.gameInfo.tileMap.mapParameters.mapSize) {
when {
radius >= MapSize.Huge.radius -> floatArrayOf(1.3f, 0.02f)
radius >= MapSize.Large.radius -> floatArrayOf(1.2f, 0.03f)
radius >= MapSize.Huge.radius -> floatArrayOf(1.3f, 0.025f)
radius >= MapSize.Large.radius -> floatArrayOf(1.2f, 0.0375f)
radius >= MapSize.Medium.radius -> floatArrayOf(1.1f, 0.05f)
else -> floatArrayOf(1f, 0.05f)
}
@ -128,8 +128,6 @@ class TechManager {
return tech.prerequisites.all { isResearched(it) }
}
fun getTechUniques() = researchedTechUniques.asSequence()
//endregion
fun getRequiredTechsToDestination(destinationTech: Technology): List<Technology> {
@ -238,8 +236,8 @@ class TechManager {
if (!newTech.isContinuallyResearchable())
techsToResearch.remove(techName)
researchedTechnologies = researchedTechnologies.withItem(newTech)
addTechToTransients(newTech)
for (unique in newTech.uniqueObjects) {
researchedTechUniques = researchedTechUniques.withItem(unique)
UniqueTriggerActivation.triggerCivwideUnique(unique, civInfo)
}
updateTransientBooleans()
@ -312,6 +310,11 @@ class TechManager {
}
}
fun addTechToTransients(tech: Technology) {
for (unique in tech.uniqueObjects)
techUniques.addUnique(unique)
}
private fun notifyRevealedResources(techName: String) {
data class CityTileAndDistance(val city: CityInfo, val tile: TileInfo, val distance: Int)
@ -354,7 +357,7 @@ class TechManager {
fun setTransients() {
researchedTechnologies.addAll(techsResearched.map { getRuleset().technologies[it]!! })
researchedTechUniques.addAll(researchedTechnologies.asSequence().flatMap { it.uniqueObjects.asSequence() })
researchedTechnologies.forEach { addTechToTransients(it) }
updateTransientBooleans()
}

View File

@ -172,7 +172,7 @@ class Nation : INamed, ICivilopediaText {
for (unique in originalUnit.uniques.filterNot { it in unit.uniques })
textList += " " + "Lost ability".tr() + "(" + "vs [${originalUnit.name}]".tr() + "): " + unique.tr()
for (promotion in unit.promotions.filter { it !in originalUnit.promotions })
textList += " " + promotion.tr() + " (" + ruleset.unitPromotions[promotion]!!.effect.tr() + ")"
textList += " " + promotion.tr() + " (" + ruleset.unitPromotions[promotion]!!.uniquesWithEffect().joinToString(",") { it.tr() } + ")"
} else if (unit.replaces != null) {
textList += unit.name.tr() + " - " + "Replaces [${unit.replaces}], which is not found in the ruleset!".tr()
} else {
@ -305,11 +305,10 @@ class Nation : INamed, ICivilopediaText {
textList += FormattedLine("Lost ability".tr() + " (" + "vs [${originalUnit.name}]".tr() + "): " +
unique.tr(), indent=1)
for (promotion in unit.promotions.filter { it !in originalUnit.promotions }) {
val effect = ruleset.unitPromotions[promotion]!!.effect
val effect = ruleset.unitPromotions[promotion]!!.uniquesWithEffect()
// "{$promotion} ({$effect})" won't work as effect may contain [] and tr() does not support that kind of nesting
textList += FormattedLine(
if (effect.isEmpty()) promotion
else "${promotion.tr()} (${effect.tr()})",
"${promotion.tr()} (${effect.joinToString(",") { it.tr() }})",
link = "Promotion/$promotion", indent = 1 )
}
} else if (unit.replaces != null) {

View File

@ -15,7 +15,7 @@ class Promotion : INamed, ICivilopediaText {
var unitTypes = listOf<String>() // The json parser wouldn't agree to deserialize this as a list of UnitTypes. =(
var uniques = ArrayList<String>()
private fun uniquesWithEffect() = sequence {
fun uniquesWithEffect() = sequence {
if (effect.isNotEmpty()) yield(effect)
yieldAll(uniques)
}