Finally changed unit uniques to Unique!

This commit is contained in:
Yair Morgenstern 2020-08-23 22:53:38 +03:00
parent 8203549aea
commit d4b8aae84a
8 changed files with 45 additions and 42 deletions

View File

@ -195,8 +195,8 @@ object SpecificUnitAutomation {
fun automateImprovementPlacer(unit: MapUnit) { fun automateImprovementPlacer(unit: MapUnit) {
if (unit.getTile().militaryUnit == null) return // Don't move until you're accompanied by a military unit if (unit.getTile().militaryUnit == null) return // Don't move until you're accompanied by a military unit
val improvementName = unit.getUniques().first { it.equalsPlaceholderText("Can construct []") } val improvementName = unit.getUniques().first { it.placeholderText == "Can construct []" }
.getPlaceholderParameters()[0] .params[0]
val improvement = unit.civInfo.gameInfo.ruleSet.tileImprovements[improvementName]!! val improvement = unit.civInfo.gameInfo.ruleSet.tileImprovements[improvementName]!!
val relatedStat = improvement.toHashMap().maxBy { it.value }!!.key val relatedStat = improvement.toHashMap().maxBy { it.value }!!.key

View File

@ -103,7 +103,7 @@ object UnitAutomation {
if (unit.name == Constants.greatGeneral || unit.baseUnit.replaces == Constants.greatGeneral) if (unit.name == Constants.greatGeneral || unit.baseUnit.replaces == Constants.greatGeneral)
return SpecificUnitAutomation.automateGreatGeneral(unit) return SpecificUnitAutomation.automateGreatGeneral(unit)
if (unit.getUniques().any { it.equalsPlaceholderText("Can construct []") }) if (unit.getUniques().any { it.placeholderText == "Can construct []" })
return SpecificUnitAutomation.automateImprovementPlacer(unit) // includes great people plus moddable units return SpecificUnitAutomation.automateImprovementPlacer(unit) // includes great people plus moddable units
return // The AI doesn't know how to handle unknown civilian units return // The AI doesn't know how to handle unknown civilian units

View File

@ -12,8 +12,6 @@ import com.unciv.logic.map.RoadStatus
import com.unciv.logic.map.TileInfo import com.unciv.logic.map.TileInfo
import com.unciv.models.AttackableTile import com.unciv.models.AttackableTile
import com.unciv.models.ruleset.unit.UnitType import com.unciv.models.ruleset.unit.UnitType
import com.unciv.models.translations.equalsPlaceholderText
import com.unciv.models.translations.getPlaceholderParameters
import java.util.* import java.util.*
import kotlin.math.max import kotlin.math.max
@ -51,8 +49,8 @@ object Battle {
// Withdraw from melee ability // Withdraw from melee ability
if (attacker is MapUnitCombatant && attacker.isMelee() && defender is MapUnitCombatant ) { if (attacker is MapUnitCombatant && attacker.isMelee() && defender is MapUnitCombatant ) {
val withdraw = defender.unit.getUniques().firstOrNull { it.startsWith("May withdraw before melee")} val withdraw = defender.unit.getUniques().firstOrNull { it.text.startsWith("May withdraw before melee")}
if (withdraw != null && doWithdrawFromMeleeAbility(attacker, defender, withdraw)) return if (withdraw != null && doWithdrawFromMeleeAbility(attacker, defender, withdraw.text)) return
} }
val isAlreadyDefeatedCity = defender is CityCombatant && defender.isDefeated() val isAlreadyDefeatedCity = defender is CityCombatant && defender.isDefeated()
@ -149,8 +147,8 @@ object Battle {
&& defender is MapUnitCombatant && defender is MapUnitCombatant
&& attacker is MapUnitCombatant) { && attacker is MapUnitCombatant) {
for (unique in attacker.unit.getUniques()) { for (unique in attacker.unit.getUniques()) {
if(unique.equalsPlaceholderText("Heals [] damage if it kills a unit")){ if(unique.placeholderText == "Heals [] damage if it kills a unit"){
val amountToHeal = unique.getPlaceholderParameters()[0].toInt() val amountToHeal = unique.params[0].toInt()
attacker.unit.healBy(amountToHeal) attacker.unit.healBy(amountToHeal)
} }
} }

View File

@ -25,7 +25,7 @@ object BattleDamage {
val modifiers = mutableListOf<BattleDamageModifier>() val modifiers = mutableListOf<BattleDamageModifier>()
for (ability in unit.getUniques()) { for (ability in unit.getUniques()) {
// This beut allows us to have generic unit uniques: "Bonus vs City 75%", "Penatly vs Mounted 25%" etc. // This beut allows us to have generic unit uniques: "Bonus vs City 75%", "Penatly vs Mounted 25%" etc.
val regexResult = Regex(BONUS_VS_UNIT_TYPE).matchEntire(ability) val regexResult = Regex(BONUS_VS_UNIT_TYPE).matchEntire(ability.text)
if (regexResult == null) continue if (regexResult == null) continue
val vs = regexResult.groups[2]!!.value val vs = regexResult.groups[2]!!.value
val modificationAmount = regexResult.groups[3]!!.value.toFloat() / 100 // if it says 15%, that's 0.15f in modification val modificationAmount = regexResult.groups[3]!!.value.toFloat() / 100 // if it says 15%, that's 0.15f in modification
@ -114,8 +114,8 @@ object BattleDamage {
modifiers.putAll(getTileSpecificModifiers(attacker, defender.getTile())) modifiers.putAll(getTileSpecificModifiers(attacker, defender.getTile()))
for (ability in attacker.unit.getUniques()) { for (ability in attacker.unit.getUniques()) {
if(ability.equalsPlaceholderText("Bonus as Attacker []%")) { if(ability.placeholderText == "Bonus as Attacker []%") {
val bonus = ability.getPlaceholderParameters()[0].toFloat() / 100 val bonus = ability.params[0].toFloat() / 100
if (modifiers.containsKey("Attacker Bonus")) if (modifiers.containsKey("Attacker Bonus"))
modifiers["Attacker Bonus"] = modifiers["Attacker Bonus"]!! + bonus modifiers["Attacker Bonus"] = modifiers["Attacker Bonus"]!! + bonus
else modifiers["Attacker Bonus"] = bonus else modifiers["Attacker Bonus"] = bonus
@ -182,11 +182,11 @@ object BattleDamage {
} }
if(attacker.isRanged()) { if(attacker.isRanged()) {
val defenceVsRanged = 0.25f * defender.unit.getUniques().count { it == "+25% Defence against ranged attacks" } val defenceVsRanged = 0.25f * defender.unit.getUniques().count { it.text == "+25% Defence against ranged attacks" }
if (defenceVsRanged > 0) modifiers["defence vs ranged"] = defenceVsRanged if (defenceVsRanged > 0) modifiers["defence vs ranged"] = defenceVsRanged
} }
val carrierDefenceBonus = 0.25f * defender.unit.getUniques().count { it == "+25% Combat Bonus when defending" } val carrierDefenceBonus = 0.25f * defender.unit.getUniques().count { it.text == "+25% Combat Bonus when defending" }
if (carrierDefenceBonus > 0) modifiers["Armor Plating"] = carrierDefenceBonus if (carrierDefenceBonus > 0) modifiers["Armor Plating"] = carrierDefenceBonus

View File

@ -10,6 +10,7 @@ import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.logic.map.action.MapUnitAction import com.unciv.logic.map.action.MapUnitAction
import com.unciv.logic.map.action.StringAction import com.unciv.logic.map.action.StringAction
import com.unciv.models.ruleset.Ruleset import com.unciv.models.ruleset.Ruleset
import com.unciv.models.ruleset.Unique
import com.unciv.models.ruleset.unit.BaseUnit import com.unciv.models.ruleset.unit.BaseUnit
import com.unciv.models.ruleset.unit.UnitType import com.unciv.models.ruleset.unit.UnitType
import java.text.DecimalFormat import java.text.DecimalFormat
@ -99,7 +100,7 @@ class MapUnit {
if (isEmbarked()) return getEmbarkedMovement() if (isEmbarked()) return getEmbarkedMovement()
var movement = baseUnit.movement var movement = baseUnit.movement
movement += getUniques().count { it == "+1 Movement" } movement += getUniques().count { it.text == "+1 Movement" }
if (type.isWaterUnit() && !type.isCivilian() if (type.isWaterUnit() && !type.isCivilian()
&& civInfo.hasUnique("All military naval units receive +1 movement and +1 sight")) && civInfo.hasUnique("All military naval units receive +1 movement and +1 sight"))
@ -121,31 +122,31 @@ class MapUnit {
// This SHOULD NOT be a hashset, because if it is, then promotions with the same text (e.g. barrage I, barrage II) // This SHOULD NOT be a hashset, because if it is, then promotions with the same text (e.g. barrage I, barrage II)
// will not get counted twice! // will not get counted twice!
@Transient var tempUniques= ArrayList<String>() @Transient var tempUniques= ArrayList<Unique>()
fun getUniques(): ArrayList<String> { fun getUniques(): ArrayList<Unique> {
return tempUniques return tempUniques
} }
fun updateUniques(){ fun updateUniques(){
val uniques = ArrayList<String>() val uniques = ArrayList<Unique>()
val baseUnit = baseUnit() val baseUnit = baseUnit()
uniques.addAll(baseUnit.uniques) uniques.addAll(baseUnit.uniqueObjects)
uniques.addAll(promotions.promotions.map { currentTile.tileMap.gameInfo.ruleSet.unitPromotions[it]!!.effect }) uniques.addAll(promotions.promotions.map { currentTile.tileMap.gameInfo.ruleSet.unitPromotions[it]!!.unique })
tempUniques = uniques tempUniques = uniques
ignoresTerrainCost = ("Ignores terrain cost" in uniques) ignoresTerrainCost = hasUnique("Ignores terrain cost")
roughTerrainPenalty = ("Rough terrain penalty" in uniques) roughTerrainPenalty = hasUnique("Rough terrain penalty")
doubleMovementInCoast = ("Double movement in coast" in uniques) doubleMovementInCoast = hasUnique("Double movement in coast")
doubleMovementInForestAndJungle = ("Double movement rate through Forest and Jungle" in uniques) doubleMovementInForestAndJungle = hasUnique("Double movement rate through Forest and Jungle")
doubleMovementInSnowTundraAndHills = ("Double movement in Snow, Tundra and Hills" in uniques) doubleMovementInSnowTundraAndHills = hasUnique("Double movement in Snow, Tundra and Hills")
canEnterIceTiles = ("Can enter ice tiles" in uniques) canEnterIceTiles = hasUnique("Can enter ice tiles")
cannotEnterOceanTiles = ("Cannot enter ocean tiles" in uniques) cannotEnterOceanTiles = hasUnique("Cannot enter ocean tiles")
cannotEnterOceanTilesUntilAstronomy = ("Cannot enter ocean tiles until Astronomy" in uniques) cannotEnterOceanTilesUntilAstronomy = hasUnique("Cannot enter ocean tiles until Astronomy")
} }
fun hasUnique(unique:String): Boolean { fun hasUnique(unique:String): Boolean {
return getUniques().contains(unique) return getUniques().any { it.text == unique }
} }
fun updateVisibleTiles() { fun updateVisibleTiles() {
@ -156,7 +157,7 @@ class MapUnit {
} }
else { else {
var visibilityRange = 2 var visibilityRange = 2
visibilityRange += getUniques().count { it == "+1 Visibility Range" } visibilityRange += getUniques().count { it.text == "+1 Visibility Range" }
if (hasUnique("+2 Visibility Range")) visibilityRange += 2 // This shouldn't be stackable if (hasUnique("+2 Visibility Range")) visibilityRange += 2 // This shouldn't be stackable
if (hasUnique("Limited Visibility")) visibilityRange -= 1 if (hasUnique("Limited Visibility")) visibilityRange -= 1
if (civInfo.hasUnique("+1 Sight for all land military units")) if (civInfo.hasUnique("+1 Sight for all land military units"))
@ -439,7 +440,7 @@ class MapUnit {
fun endTurn() { fun endTurn() {
doPostTurnAction() doPostTurnAction()
if (currentMovement == getMaxMovement().toFloat() // didn't move this turn if (currentMovement == getMaxMovement().toFloat() // didn't move this turn
|| getUniques().contains("Unit will heal every turn, even if it performs an action")){ || hasUnique("Unit will heal every turn, even if it performs an action")){
heal() heal()
} }
if(action != null && health > 99) if(action != null && health > 99)
@ -631,15 +632,15 @@ class MapUnit {
fun interceptChance():Int{ fun interceptChance():Int{
val interceptUnique = getUniques() val interceptUnique = getUniques()
.firstOrNull { it.endsWith(CHANCE_TO_INTERCEPT_AIR_ATTACKS) } .firstOrNull { it.text.endsWith(CHANCE_TO_INTERCEPT_AIR_ATTACKS) }
if(interceptUnique==null) return 0 if(interceptUnique==null) return 0
val percent = Regex("\\d+").find(interceptUnique)!!.value.toInt() val percent = Regex("\\d+").find(interceptUnique.text)!!.value.toInt()
return percent return percent
} }
fun isTransportTypeOf(mapUnit: MapUnit): Boolean { fun isTransportTypeOf(mapUnit: MapUnit): Boolean {
val isAircraftCarrier = getUniques().contains("Can carry 2 aircraft") val isAircraftCarrier = hasUnique("Can carry 2 aircraft")
val isMissileCarrier = getUniques().contains("Can carry 2 missiles") val isMissileCarrier = hasUnique("Can carry 2 missiles")
if(!isMissileCarrier && !isAircraftCarrier) if(!isMissileCarrier && !isAircraftCarrier)
return false return false
if(!mapUnit.type.isAirUnit()) return false if(!mapUnit.type.isAirUnit()) return false
@ -655,7 +656,7 @@ class MapUnit {
if (owner != mapUnit.owner) return false if (owner != mapUnit.owner) return false
var unitCapacity = 2 var unitCapacity = 2
unitCapacity += getUniques().count { it == "Can carry 1 extra air unit" } unitCapacity += getUniques().count { it.text == "Can carry 1 extra air unit" }
if (currentTile.airUnits.filter { it.isTransported }.size >= unitCapacity) return false if (currentTile.airUnits.filter { it.isTransported }.size >= unitCapacity) return false
@ -664,8 +665,8 @@ class MapUnit {
fun interceptDamagePercentBonus():Int{ fun interceptDamagePercentBonus():Int{
var sum=0 var sum=0
for(unique in getUniques().filter { it.startsWith(BONUS_WHEN_INTERCEPTING) }){ for(unique in getUniques().filter { it.text.startsWith(BONUS_WHEN_INTERCEPTING) }){
val percent = Regex("\\d+").find(unique)!!.value.toInt() val percent = Regex("\\d+").find(unique.text)!!.value.toInt()
sum += percent sum += percent
} }
return sum return sum

View File

@ -6,6 +6,7 @@ import com.unciv.logic.city.IConstruction
import com.unciv.logic.civilization.CivilizationInfo import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.logic.map.MapUnit import com.unciv.logic.map.MapUnit
import com.unciv.models.ruleset.Ruleset import com.unciv.models.ruleset.Ruleset
import com.unciv.models.ruleset.Unique
import com.unciv.models.translations.Translations import com.unciv.models.translations.Translations
import com.unciv.models.translations.tr import com.unciv.models.translations.tr
import com.unciv.models.stats.INamed import com.unciv.models.stats.INamed
@ -29,6 +30,7 @@ class BaseUnit : INamed, IConstruction {
var requiredTech:String? = null var requiredTech:String? = null
var requiredResource:String? = null var requiredResource:String? = null
var uniques =HashSet<String>() var uniques =HashSet<String>()
val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it) } }
var promotions =HashSet<String>() var promotions =HashSet<String>()
var obsoleteTech:String?=null var obsoleteTech:String?=null
var upgradesTo:String? = null var upgradesTo:String? = null

View File

@ -1,6 +1,7 @@
package com.unciv.models.ruleset.unit package com.unciv.models.ruleset.unit
import com.unciv.models.ruleset.Ruleset import com.unciv.models.ruleset.Ruleset
import com.unciv.models.ruleset.Unique
import com.unciv.models.stats.INamed import com.unciv.models.stats.INamed
import com.unciv.models.translations.Translations import com.unciv.models.translations.Translations
import com.unciv.models.translations.tr import com.unciv.models.translations.tr
@ -9,6 +10,7 @@ class Promotion : INamed{
override lateinit var name: String override lateinit var name: String
var prerequisites = listOf<String>() var prerequisites = listOf<String>()
lateinit var effect:String lateinit var effect:String
val unique:Unique by lazy { Unique(effect) }
var unitTypes = listOf<String>() // The json parser wouldn't agree to deserialize this as a list of UnitTypes. =( var unitTypes = listOf<String>() // The json parser wouldn't agree to deserialize this as a list of UnitTypes. =(
fun getDescription(promotionsForUnitType: Collection<Promotion>, forCivilopedia:Boolean=false, ruleSet:Ruleset? = null):String { fun getDescription(promotionsForUnitType: Collection<Promotion>, forCivilopedia:Boolean=false, ruleSet:Ruleset? = null):String {

View File

@ -351,8 +351,8 @@ object UnitActions {
if (unit.civInfo.hasUnique("Double gold from Great Merchant trade missions")) if (unit.civInfo.hasUnique("Double gold from Great Merchant trade missions"))
goldEarned *= 2 goldEarned *= 2
unit.civInfo.gold += goldEarned.toInt() unit.civInfo.gold += goldEarned.toInt()
val relevantUnique = unit.getUniques().first { it.startsWith(CAN_UNDERTAKE) } val relevantUnique = unit.getUniques().first { it.text.startsWith(CAN_UNDERTAKE) }
val influenceEarned = Regex("\\d+").find(relevantUnique)!!.value.toInt() val influenceEarned = Regex("\\d+").find(relevantUnique.text)!!.value.toInt()
tile.owningCity!!.civInfo.getDiplomacyManager(unit.civInfo).influence += influenceEarned tile.owningCity!!.civInfo.getDiplomacyManager(unit.civInfo).influence += influenceEarned
unit.civInfo.addNotification("Your trade mission to [${tile.owningCity!!.civInfo}] has earned you [${goldEarned.toInt()}] gold and [$influenceEarned] influence!", null, Color.GOLD) unit.civInfo.addNotification("Your trade mission to [${tile.owningCity!!.civInfo}] has earned you [${goldEarned.toInt()}] gold and [$influenceEarned] influence!", null, Color.GOLD)
addGoldPerGreatPersonUsage(unit.civInfo) addGoldPerGreatPersonUsage(unit.civInfo)
@ -364,8 +364,8 @@ object UnitActions {
fun getImprovementConstructionActions(unit: MapUnit, tile: TileInfo): ArrayList<UnitAction> { fun getImprovementConstructionActions(unit: MapUnit, tile: TileInfo): ArrayList<UnitAction> {
val finalActions = ArrayList<UnitAction>() val finalActions = ArrayList<UnitAction>()
for (unique in unit.getUniques().filter { it.equalsPlaceholderText("Can construct []") }) { for (unique in unit.getUniques().filter { it.placeholderText == "Can construct []" }) {
val improvementName = unique.getPlaceholderParameters()[0] val improvementName = unique.params[0]
finalActions += UnitAction( finalActions += UnitAction(
type = UnitActionType.Create, type = UnitActionType.Create,
title = "Create [$improvementName]", title = "Create [$improvementName]",