Simplified combat uniques further (#5361)

* Simplified combat uniques further

* Reviews & translations

* UniqueType > placeHolderText

* I can't math
This commit is contained in:
Xander Lenstra
2021-10-03 23:29:46 +02:00
committed by GitHub
parent edfc66aa2f
commit 07822de375
8 changed files with 115 additions and 70 deletions

View File

@ -174,13 +174,13 @@
}, },
{ {
"name": "Survivalism I", "name": "Survivalism I",
"uniques": ["[+5] HP when healing in [Foreign Land] tiles", "+[25]% Strength when defending"], "uniques": ["[+5] HP when healing in [Foreign Land] tiles", "[+25]% Strength <when defending>"],
"unitTypes": ["Scout"] "unitTypes": ["Scout"]
}, },
{ {
"name": "Survivalism II", "name": "Survivalism II",
"prerequisites": ["Survivalism I"], "prerequisites": ["Survivalism I"],
"uniques": ["[+5] HP when healing in [Foreign Land] tiles", "+[25]% Strength when defending"], "uniques": ["[+5] HP when healing in [Foreign Land] tiles", "[+25]% Strength <when defending>"],
"unitTypes": ["Scout"] "unitTypes": ["Scout"]
}, },
{ {
@ -250,38 +250,38 @@
// Submarine // Submarine
{ {
"name": "Wolfpack I", "name": "Wolfpack I",
"uniques": ["+[25]% Strength when attacking"], "uniques": ["[+25]% Strength <when attacking>"],
"unitTypes": ["Submarine"] "unitTypes": ["Submarine"]
}, },
{ {
"name": "Wolfpack II", "name": "Wolfpack II",
"prerequisites": ["Wolfpack I"], "prerequisites": ["Wolfpack I"],
"uniques": ["+[25]% Strength when attacking"], "uniques": ["[+25]% Strength <when attacking>"],
"unitTypes": ["Submarine"] "unitTypes": ["Submarine"]
}, },
{ {
"name": "Wolfpack III", "name": "Wolfpack III",
"prerequisites": ["Wolfpack II"], "prerequisites": ["Wolfpack II"],
"uniques": ["+[25]% Strength when attacking"], "uniques": ["[+25]% Strength <when attacking>"],
"unitTypes": ["Submarine"] "unitTypes": ["Submarine"]
}, },
// Aircraft Carrier // Aircraft Carrier
{ {
"name": "Armor Plating I", "name": "Armor Plating I",
"uniques": ["+[25]% Strength when defending"], "uniques": ["[+25]% Strength <when defending>"],
"unitTypes": ["Aircraft Carrier"] "unitTypes": ["Aircraft Carrier"]
}, },
{ {
"name": "Armor Plating II", "name": "Armor Plating II",
"prerequisites": ["Armor Plating I"], "prerequisites": ["Armor Plating I"],
"uniques": ["+[25]% Strength when defending"], "uniques": ["[+25]% Strength <when defending>"],
"unitTypes": ["Aircraft Carrier"] "unitTypes": ["Aircraft Carrier"]
}, },
{ {
"name": "Armor Plating III", "name": "Armor Plating III",
"prerequisites": ["Armor Plating II"], "prerequisites": ["Armor Plating II"],
"uniques": ["+[25]% Strength when defending"], "uniques": ["[+25]% Strength <when defending>"],
"unitTypes": ["Aircraft Carrier"] "unitTypes": ["Aircraft Carrier"]
}, },
{ {
@ -433,13 +433,13 @@
// Mixed // Mixed
{ {
"name": "Cover I", "name": "Cover I",
"uniques": ["[+33]% Strength when defending vs [Ranged] units"], "uniques": ["[+33]% Strength <vs [Ranged] units> <when defending>"],
"unitTypes": ["Sword","Gunpowder","Archery","Ranged Gunpowder","Siege"] "unitTypes": ["Sword","Gunpowder","Archery","Ranged Gunpowder","Siege"]
}, },
{ {
"name": "Cover II", "name": "Cover II",
"prerequisites": ["Cover I"], "prerequisites": ["Cover I"],
"uniques": ["[+33]% Strength when defending vs [Ranged] units"], "uniques": ["[+33]% Strength <vs [Ranged] units> <when defending>"],
"unitTypes": ["Sword","Gunpowder","Archery","Ranged Gunpowder","Siege"] "unitTypes": ["Sword","Gunpowder","Archery","Ranged Gunpowder","Siege"]
}, },

View File

@ -315,7 +315,7 @@
"requiredTech": "Bronze Working", "requiredTech": "Bronze Working",
"obsoleteTech": "Physics", "obsoleteTech": "Physics",
"upgradesTo": "Trebuchet", "upgradesTo": "Trebuchet",
"uniques": ["[+300]% Strength <vs cities>", "No defensive terrain bonus", "+[-33]% Strength when defending", "uniques": ["[+300]% Strength <vs cities>", "No defensive terrain bonus", "[-33]% Strength <when defending>",
"-[1] Visibility Range", "Can only attack [City] units"], "-[1] Visibility Range", "Can only attack [City] units"],
"promotions": ["Cover I"], "promotions": ["Cover I"],
"attackSound": "throw" "attackSound": "throw"
@ -838,7 +838,7 @@
"requiredTech": "Gunpowder", "requiredTech": "Gunpowder",
"upgradesTo": "Rifleman", "upgradesTo": "Rifleman",
"obsoleteTech": "Rifling", "obsoleteTech": "Rifling",
"uniques": ["Heals [50] damage if it kills a unit", "+[25]% Strength when attacking"], "uniques": ["Heals [50] damage if it kills a unit", "[+25]% Strength <when attacking>"],
"attackSound": "shot" "attackSound": "shot"
}, },
{ {
@ -1132,7 +1132,7 @@
"cost": 325, "cost": 325,
"requiredTech": "Refrigeration", "requiredTech": "Refrigeration",
"upgradesTo": "Nuclear Submarine", "upgradesTo": "Nuclear Submarine",
"uniques": ["+[75]% Strength when attacking", "Can only attack [Water] tiles"], "uniques": ["[+75]% Strength <when attacking>", "Can only attack [Water] tiles"],
"attackSound": "torpedo" "attackSound": "torpedo"
}, },
{ {
@ -1490,7 +1490,7 @@
"rangedStrength": 85, "rangedStrength": 85,
"cost": 425, "cost": 425,
"requiredTech": "Telecommunications", "requiredTech": "Telecommunications",
"uniques": ["+[75]% Strength when attacking", "Can only attack [Water] tiles", "[+1] Visibility Range", "Can carry [2] [Missile] units"], "uniques": ["[+75]% Strength <when attacking>", "Can only attack [Water] tiles", "[+1] Visibility Range", "Can carry [2] [Missile] units"],
"attackSound": "torpedo" "attackSound": "torpedo"
}, },
{ {

View File

@ -814,6 +814,9 @@ defence vs [unitType] =
Defensive Bonus = Defensive Bonus =
Stacked with [unitType] = Stacked with [unitType] =
Unit ability =
National ability =
The following improvements [stats]: = The following improvements [stats]: =
The following improvements on [tileType] tiles [stats]: = The following improvements on [tileType] tiles [stats]: =
@ -1302,6 +1305,10 @@ Invisible to others =
when not at war = when not at war =
when at war = when at war =
if this city has at least [amount] specialists = if this city has at least [amount] specialists =
vs cities =
vs [mapUnitFilter] units =
when attacking =
when defending =
# In English we just paste all these conditionals at the end of each unique, but in your language that # In English we just paste all these conditionals at the end of each unique, but in your language that
# may not turn into valid sentences. Therefore we have the following two translations to determine # may not turn into valid sentences. Therefore we have the following two translations to determine

View File

@ -3,6 +3,8 @@ package com.unciv.logic.battle
import com.unciv.logic.map.TileInfo import com.unciv.logic.map.TileInfo
import com.unciv.models.Counter import com.unciv.models.Counter
import com.unciv.models.ruleset.unique.StateForConditionals import com.unciv.models.ruleset.unique.StateForConditionals
import com.unciv.models.ruleset.unique.Unique
import com.unciv.models.ruleset.unique.UniqueTarget
import com.unciv.models.ruleset.unique.UniqueType import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.ui.utils.toPercent import com.unciv.ui.utils.toPercent
import java.util.* import java.util.*
@ -17,17 +19,25 @@ class BattleDamageModifier(val vs:String, val modificationAmount:Float){
} }
object BattleDamage { object BattleDamage {
private fun getModifierStringFromUnique(unique: Unique): String {
return when (unique.sourceObjectType) {
UniqueTarget.Unit -> "Unit ability"
UniqueTarget.Nation -> "National ability"
else -> "[${unique.sourceObjectName}] ([${unique.sourceObjectType?.name}])"
}
}
private fun getGeneralModifiers(combatant: ICombatant, enemy: ICombatant): Counter<String> { private fun getGeneralModifiers(combatant: ICombatant, enemy: ICombatant, combatAction: CombatAction): Counter<String> {
val modifiers = Counter<String>() val modifiers = Counter<String>()
val civInfo = combatant.getCivInfo() val civInfo = combatant.getCivInfo()
if (combatant is MapUnitCombatant) { if (combatant is MapUnitCombatant) {
for (unique in combatant.unit.getMatchingUniques( for (unique in combatant.unit.getMatchingUniques(
UniqueType.Strength, UniqueType.Strength,
StateForConditionals(civInfo, defender = enemy)) StateForConditionals(civInfo, defender = enemy, combatAction = combatAction))
) { ) {
modifiers.add("${unique.sourceObjectName} (${unique.sourceObjectType})", unique.params[0].toInt()) modifiers.add(getModifierStringFromUnique(unique), unique.params[0].toInt())
} }
// Deprecated since 3.17.3 // Deprecated since 3.17.3
@ -124,14 +134,16 @@ object BattleDamage {
attacker: ICombatant, attacker: ICombatant,
defender: ICombatant defender: ICombatant
): Counter<String> { ): Counter<String> {
val modifiers = getGeneralModifiers(attacker, defender) val modifiers = getGeneralModifiers(attacker, defender, CombatAction.Attack)
if (attacker is MapUnitCombatant) { if (attacker is MapUnitCombatant) {
modifiers.add(getTileSpecificModifiers(attacker, defender.getTile())) modifiers.add(getTileSpecificModifiers(attacker, defender.getTile()))
for (unique in attacker.unit.getMatchingUniques("+[]% Strength when attacking")) { // Deprecated since 3.17.4
modifiers.add("Attacker Bonus", unique.params[0].toInt()) for (unique in attacker.unit.getMatchingUniques(UniqueType.StrengthAttacking)) {
} modifiers.add("Attacker Bonus", unique.params[0].toInt())
}
//
if (attacker.unit.isEmbarked() && !attacker.unit.hasUnique("Eliminates combat penalty for attacking from the sea")) if (attacker.unit.isEmbarked() && !attacker.unit.hasUnique("Eliminates combat penalty for attacking from the sea"))
modifiers["Landing"] = -50 modifiers["Landing"] = -50
@ -192,7 +204,7 @@ object BattleDamage {
} }
fun getDefenceModifiers(attacker: ICombatant, defender: ICombatant): Counter<String> { fun getDefenceModifiers(attacker: ICombatant, defender: ICombatant): Counter<String> {
val modifiers = getGeneralModifiers(defender, attacker) val modifiers = getGeneralModifiers(defender, attacker, CombatAction.Defend)
val tile = defender.getTile() val tile = defender.getTile()
if (defender is MapUnitCombatant) { if (defender is MapUnitCombatant) {
@ -215,14 +227,16 @@ object BattleDamage {
) )
modifiers["Tile"] = (tileDefenceBonus * 100).toInt() modifiers["Tile"] = (tileDefenceBonus * 100).toInt()
for (unique in defender.unit.getMatchingUniques("[]% Strength when defending vs [] units")) { // Deprecated since 3.17.4
if (attacker.matchesCategory(unique.params[1])) for (unique in defender.unit.getMatchingUniques(UniqueType.StrengthDefendingUnitFilter)) {
modifiers.add("defence vs [${unique.params[1]}] ", unique.params[0].toInt()) if (attacker.matchesCategory(unique.params[1]))
} modifiers.add("defence vs [${unique.params[1]}] ", unique.params[0].toInt())
}
for (unique in defender.unit.getMatchingUniques("+[]% Strength when defending")) {
modifiers.add("Defender Bonus", unique.params[0].toInt()) for (unique in defender.unit.getMatchingUniques(UniqueType.StrengthDefending)) {
} modifiers.add("Defender Bonus", unique.params[0].toInt())
}
//
for (unique in defender.unit.getMatchingUniques("+[]% defence in [] tiles")) { for (unique in defender.unit.getMatchingUniques("+[]% defence in [] tiles")) {
if (tile.matchesFilter(unique.params[1])) if (tile.matchesFilter(unique.params[1]))
@ -341,4 +355,10 @@ object BattleDamage {
val randomCenteredAround30 = 24 + 12 * Random().nextFloat() val randomCenteredAround30 = 24 + 12 * Random().nextFloat()
return randomCenteredAround30 * ratioModifier return randomCenteredAround30 * ratioModifier
} }
}
enum class CombatAction {
Attack,
Defend,
Intercept,
} }

View File

@ -1,5 +1,6 @@
package com.unciv.models.ruleset.unique package com.unciv.models.ruleset.unique
import com.unciv.logic.battle.CombatAction
import com.unciv.logic.battle.ICombatant import com.unciv.logic.battle.ICombatant
import com.unciv.logic.city.CityInfo import com.unciv.logic.city.CityInfo
import com.unciv.logic.civilization.CivilizationInfo import com.unciv.logic.civilization.CivilizationInfo
@ -8,14 +9,8 @@ import com.unciv.logic.map.TileInfo
data class StateForConditionals( data class StateForConditionals(
val civInfo: CivilizationInfo? = null, val civInfo: CivilizationInfo? = null,
val cityInfo: CityInfo? = null, val cityInfo: CityInfo? = null,
val defender: ICombatant? = null,
// val attacker: ICombatant? = null, // val attacker: ICombatant? = null,
val defender: ICombatant? = null,
// val attackedTile: TileInfo? = null, // val attackedTile: TileInfo? = null,
// val combatAction: CombatAction? = null, val combatAction: CombatAction? = null,
) )
//enum class CombatAction() {
// Attack,
// Defend,
// Intercept,
//}

View File

@ -1,5 +1,6 @@
package com.unciv.models.ruleset.unique package com.unciv.models.ruleset.unique
import com.unciv.logic.battle.CombatAction
import com.unciv.logic.city.CityInfo import com.unciv.logic.city.CityInfo
import com.unciv.models.stats.Stats import com.unciv.models.stats.Stats
import com.unciv.models.translations.* import com.unciv.models.translations.*
@ -54,6 +55,8 @@ class Unique(val text: String, val sourceObjectType: UniqueTarget? = null, val s
state.defender != null && state.defender.matchesCategory("City") state.defender != null && state.defender.matchesCategory("City")
UniqueType.ConditionalVsUnits -> UniqueType.ConditionalVsUnits ->
state.defender != null && state.defender.matchesCategory(condition.params[0]) state.defender != null && state.defender.matchesCategory(condition.params[0])
UniqueType.ConditionalAttacking -> state.combatAction == CombatAction.Attack
UniqueType.ConditionalDefending -> state.combatAction == CombatAction.Defend
UniqueType.ConditionalNeighborTiles -> UniqueType.ConditionalNeighborTiles ->
state.cityInfo != null && state.cityInfo != null &&
state.cityInfo.getCenterTile().neighbors.count { state.cityInfo.getCenterTile().neighbors.count {

View File

@ -123,12 +123,18 @@ enum class UniqueType(val text:String, vararg targets: UniqueTarget) {
StrengthPlus("+[amount]% Strength", UniqueTarget.Unit), StrengthPlus("+[amount]% Strength", UniqueTarget.Unit),
@Deprecated("As of 3.17.3", ReplaceWith("[amount]% Strength"), DeprecationLevel.WARNING) @Deprecated("As of 3.17.3", ReplaceWith("[amount]% Strength"), DeprecationLevel.WARNING)
StrengthMin("-[amount]% Strength", UniqueTarget.Unit), StrengthMin("-[amount]% Strength", UniqueTarget.Unit),
@Deprecated("As of 3.17.3", ReplaceWith("[amount]% Strength <vs [unitFilter] units> OR [amount]% Strength <vs cities>"), DeprecationLevel.WARNING) @Deprecated("As of 3.17.3", ReplaceWith("[amount]% Strength <vs [mapUnitFilter] units> OR [amount]% Strength <vs cities>"), DeprecationLevel.WARNING)
StrengthPlusVs("+[amount]% Strength vs [combatantFilter]", UniqueTarget.Unit), StrengthPlusVs("+[amount]% Strength vs [combatantFilter]", UniqueTarget.Unit),
@Deprecated("As of 3.17.3", ReplaceWith("[amount]% Strength <vs [unitFilter] units> OR [amount]% Strength <vs cities>"), DeprecationLevel.WARNING) @Deprecated("As of 3.17.3", ReplaceWith("[amount]% Strength <vs [mapUnitFilter] units> OR [amount]% Strength <vs cities>"), DeprecationLevel.WARNING)
StrengthMinVs("-[amount]% Strength vs [combatantFilter]", UniqueTarget.Unit), StrengthMinVs("-[amount]% Strength vs [combatantFilter]", UniqueTarget.Unit),
@Deprecated("As of 3.17.3", ReplaceWith("[amount]% Strength"), DeprecationLevel.WARNING) @Deprecated("As of 3.17.3", ReplaceWith("[amount]% Strength"), DeprecationLevel.WARNING)
CombatBonus("+[amount]% Combat Strength", UniqueTarget.Unit), CombatBonus("+[amount]% Combat Strength", UniqueTarget.Unit),
@Deprecated("As of 3.17.5", ReplaceWith("[amount]% Strength <when attacking>"), DeprecationLevel.WARNING)
StrengthAttacking("+[amount]% Strength when attacking", UniqueTarget.Unit),
@Deprecated("As of 3.17.5", ReplaceWith("[amount]% Strength <shen defending>"), DeprecationLevel.WARNING)
StrengthDefending("+[amount]% Strength when defending", UniqueTarget.Unit),
@Deprecated("As of 3.17.5", ReplaceWith("[amount]% Strength <when defending> <vs [mapUnitFilter] units>"), DeprecationLevel.WARNING)
StrengthDefendingUnitFilter("[amount]% Strength when defending vs [mapUnitFilter] units", UniqueTarget.Unit),
// The following block gets cached in MapUnit for faster getMovementCostBetweenAdjacentTiles // The following block gets cached in MapUnit for faster getMovementCostBetweenAdjacentTiles
DoubleMovementOnTerrain("Double movement in [terrainFilter]", UniqueTarget.Unit), DoubleMovementOnTerrain("Double movement in [terrainFilter]", UniqueTarget.Unit),
@ -175,10 +181,10 @@ enum class UniqueType(val text:String, vararg targets: UniqueTarget) {
ConditionalHappy("while the empire is happy", UniqueTarget.Conditional), ConditionalHappy("while the empire is happy", UniqueTarget.Conditional),
ConditionalVsCity("vs cities", UniqueTarget.Conditional), ConditionalVsCity("vs cities", UniqueTarget.Conditional),
ConditionalVsUnits("vs [mapUnitFilter] units", UniqueTarget.Conditional), ConditionalVsUnits("vs [mapUnitFilter] units", UniqueTarget.Conditional),
// ConditionalInTiles("fighting in [tileFilter] tiles", UniqueTarget.Conditional), ConditionalAttacking("when attacking", UniqueTarget.Conditional),
// ConditionalAttacking("when attacking", UniqueTarget.Conditional), ConditionalDefending("when defending", UniqueTarget.Conditional),
// ConditionalDefending("when defending", UniqueTarget.Conditional),
// ConditionalIntercepting("when intercepting", UniqueTarget.Conditional), // ConditionalIntercepting("when intercepting", UniqueTarget.Conditional),
// ConditionalInTiles("fighting in [tileFilter] tiles", UniqueTarget.Conditional),
ConditionalNeighborTiles("with [amount] to [amount] neighboring [tileFilter] tiles", UniqueTarget.Conditional), ConditionalNeighborTiles("with [amount] to [amount] neighboring [tileFilter] tiles", UniqueTarget.Conditional),
ConditionalNeighborTilesAnd("with [amount] to [amount] neighboring [tileFilter] [tileFilter] tiles", UniqueTarget.Conditional), ConditionalNeighborTilesAnd("with [amount] to [amount] neighboring [tileFilter] [tileFilter] tiles", UniqueTarget.Conditional),

View File

@ -573,8 +573,8 @@ class BaseUnit : RulesetObject(), INonPerpetualConstruction {
return return
} }
var power = strength.toFloat().pow(1.5f).toInt() var power = strength.toFloat().pow(1.5f)
var rangedPower = rangedStrength.toFloat().pow(1.45f).toInt() var rangedPower = rangedStrength.toFloat().pow(1.45f)
// Value ranged naval units less // Value ranged naval units less
if (isWaterUnit()) { if (isWaterUnit()) {
@ -585,7 +585,7 @@ class BaseUnit : RulesetObject(), INonPerpetualConstruction {
// Replicates the formula from civ V, which is a lower multiplier than probably intended, because math // Replicates the formula from civ V, which is a lower multiplier than probably intended, because math
// They did fix it in BNW so it was completely bugged and always 1, again math // They did fix it in BNW so it was completely bugged and always 1, again math
power = (power * movement.toFloat().pow(0.3f)).toInt() power = (power * movement.toFloat().pow(0.3f))
if (uniqueObjects.any { it.placeholderText =="Self-destructs when attacking" } ) if (uniqueObjects.any { it.placeholderText =="Self-destructs when attacking" } )
power /= 2 power /= 2
@ -597,21 +597,28 @@ class BaseUnit : RulesetObject(), INonPerpetualConstruction {
when { when {
unique.isOfType(UniqueType.Strength) && unique.params[0].toInt() > 0 -> { unique.isOfType(UniqueType.Strength) && unique.params[0].toInt() > 0 -> {
if (unique.conditionals.any { it.isOfType(UniqueType.ConditionalVsCity) }) if (unique.conditionals.any { it.isOfType(UniqueType.ConditionalVsUnits) } ) { // Bonus vs some units - a quarter of the bonus
power += (power * unique.params[0].toInt()) / 200 power *= (unique.params[0].toInt() / 4f).toPercent()
else if (unique.conditionals.any { it.isOfType(UniqueType.ConditionalVsUnits) }) } else if (
power += (power * unique.params[0].toInt()) / 400 unique.conditionals.any { it.isOfType(UniqueType.ConditionalVsCity) } || // City Attack - half the bonus
unique.conditionals.any { it.isOfType(UniqueType.ConditionalAttacking) } || // Attack - half the bonus
unique.conditionals.any { it.isOfType(UniqueType.ConditionalDefending) } // Defense - half the bonus
) {
power *= (unique.params[0].toInt() / 2f).toPercent()
}
} }
// Deprecated since 3.17.3 // Deprecated since 3.17.3
unique.placeholderText == "+[]% Strength vs []" && unique.params[1] == "City" // City Attack - half the bonus unique.isOfType(UniqueType.StrengthPlusVs) && unique.params[1] == "City" // City Attack - half the bonus
-> power += (power * unique.params[0].toInt()) / 200 -> power += (power * unique.params[0].toInt()) / 200
unique.placeholderText == "+[]% Strength vs []" && unique.params[1] != "City" // Bonus vs something else - a quarter of the bonus unique.isOfType(UniqueType.StrengthPlusVs) && unique.params[1] != "City" // Bonus vs something else - a quarter of the bonus
-> power += (power * unique.params[0].toInt()) / 400 -> power += (power * unique.params[0].toInt()) / 400
// //
unique.placeholderText == "+[]% Strength when attacking" // Attack - half the bonus // Deprecated since 3.17.4
-> power += (power * unique.params[0].toInt()) / 200 unique.isOfType(UniqueType.StrengthAttacking) // Attack - half the bonus
unique.placeholderText == "+[]% Strength when defending" // Defense - half the bonus -> power += (power * unique.params[0].toInt()) / 200
-> power += (power * unique.params[0].toInt()) / 200 unique.isOfType(UniqueType.StrengthDefending) // Defense - half the bonus
-> power += (power * unique.params[0].toInt()) / 200
//
unique.placeholderText == "May Paradrop up to [] tiles from inside friendly territory" // Paradrop - 25% bonus unique.placeholderText == "May Paradrop up to [] tiles from inside friendly territory" // Paradrop - 25% bonus
-> power += power / 4 -> power += power / 4
unique.placeholderText == "Must set up to ranged attack" // Must set up - 20 % penalty unique.placeholderText == "Must set up to ranged attack" // Must set up - 20 % penalty
@ -626,21 +633,28 @@ class BaseUnit : RulesetObject(), INonPerpetualConstruction {
for (unique in ruleset.unitPromotions[promotionName]!!.uniqueObjects) { for (unique in ruleset.unitPromotions[promotionName]!!.uniqueObjects) {
when { when {
unique.isOfType(UniqueType.Strength) && unique.params[0].toInt() > 0 -> { unique.isOfType(UniqueType.Strength) && unique.params[0].toInt() > 0 -> {
if (unique.conditionals.any { it.isOfType(UniqueType.ConditionalVsCity) }) if (unique.conditionals.any { it.isOfType(UniqueType.ConditionalVsUnits) } ) { // Bonus vs some units - a quarter of the bonus
power += (power * unique.params[0].toInt()) / 200 power *= (unique.params[0].toInt() / 4f).toPercent()
else if (unique.conditionals.any { it.isOfType(UniqueType.ConditionalVsUnits) }) } else if (
power += (power * unique.params[0].toInt()) / 400 unique.conditionals.any { it.isOfType(UniqueType.ConditionalVsCity) } || // City Attack - half the bonus
unique.conditionals.any { it.isOfType(UniqueType.ConditionalAttacking) } || // Attack - half the bonus
unique.conditionals.any { it.isOfType(UniqueType.ConditionalDefending) } // Defense - half the bonus
) {
power *= (unique.params[0].toInt() / 2f).toPercent()
}
} }
// Deprecated since 3.17.3 // Deprecated since 3.17.3
unique.placeholderText == "+[]% Strength vs []" && unique.params[1] == "City" // City Attack - half the bonus unique.isOfType(UniqueType.StrengthPlusVs) && unique.params[1] == "City" // City Attack - half the bonus
-> power += (power * unique.params[0].toInt()) / 200 -> power += (power * unique.params[0].toInt()) / 200
unique.placeholderText == "+[]% Strength vs []" && unique.params[1] != "City" // Bonus vs something else - a quarter of the bonus unique.isOfType(UniqueType.StrengthPlusVs) && unique.params[1] != "City" // Bonus vs something else - a quarter of the bonus
-> power += (power * unique.params[0].toInt()) / 400 -> power += (power * unique.params[0].toInt()) / 400
//
// Deprecated since 3.17.4
unique.isOfType(UniqueType.StrengthAttacking) // Attack - half the bonus
-> power += (power * unique.params[0].toInt()) / 200
unique.isOfType(UniqueType.StrengthDefending) // Defense - half the bonus
-> power += (power * unique.params[0].toInt()) / 200
// //
unique.placeholderText == "+[]% Strength when attacking" // Attack - half the bonus
-> power += (power * unique.params[0].toInt()) / 200
unique.placeholderText == "+[]% Strength when defending" // Defense - half the bonus
-> power += (power * unique.params[0].toInt()) / 200
unique.placeholderText == "[] additional attacks per turn" // Extra attacks - 20% bonus per extra attack unique.placeholderText == "[] additional attacks per turn" // Extra attacks - 20% bonus per extra attack
-> power += (power * unique.params[0].toInt()) / 5 -> power += (power * unique.params[0].toInt()) / 5
unique.placeholderText == "+[]% Strength in []" // Bonus in terrain or feature - half the bonus unique.placeholderText == "+[]% Strength in []" // Bonus in terrain or feature - half the bonus
@ -649,6 +663,6 @@ class BaseUnit : RulesetObject(), INonPerpetualConstruction {
} }
} }
cachedForceEvaluation = power cachedForceEvaluation = power.toInt()
} }
} }