diff --git a/core/src/com/unciv/logic/automation/BattleHelper.kt b/core/src/com/unciv/logic/automation/BattleHelper.kt index 67842c5cdc..25d1df9c31 100644 --- a/core/src/com/unciv/logic/automation/BattleHelper.kt +++ b/core/src/com/unciv/logic/automation/BattleHelper.kt @@ -14,12 +14,12 @@ object BattleHelper { fun tryAttackNearbyEnemy(unit: MapUnit, stayOnTile: Boolean = false): Boolean { if (unit.hasUnique("Cannot attack")) return false val attackableEnemies = getAttackableEnemies(unit, unit.movement.getDistanceToTiles(), stayOnTile=stayOnTile) - // Only take enemies we can fight without dying - .filter { - BattleDamage.calculateDamageToAttacker(MapUnitCombatant(unit), - it.tileToAttackFrom, - Battle.getMapCombatantOfTile(it.tileToAttack)!!) < unit.health - } + // Only take enemies we can fight without dying + .filter { + BattleDamage.calculateDamageToAttacker(MapUnitCombatant(unit), + it.tileToAttackFrom, + Battle.getMapCombatantOfTile(it.tileToAttack)!!) < unit.health + } val enemyTileToAttack = chooseAttackTarget(unit, attackableEnemies) diff --git a/core/src/com/unciv/logic/automation/SpecificUnitAutomation.kt b/core/src/com/unciv/logic/automation/SpecificUnitAutomation.kt index e8a1072735..45cdab852b 100644 --- a/core/src/com/unciv/logic/automation/SpecificUnitAutomation.kt +++ b/core/src/com/unciv/logic/automation/SpecificUnitAutomation.kt @@ -331,7 +331,7 @@ object SpecificUnitAutomation { val tilesInRange = unit.currentTile.getTilesInDistance(unit.getRange()) for (tile in tilesInRange) { // For now AI will only use nukes against cities because in all honesty that's the best use for them. - if (tile.isCityCenter() && tile.getOwner()!!.isAtWarWith(unit.civInfo)) { + if (tile.isCityCenter() && tile.getOwner()!!.isAtWarWith(unit.civInfo) && Battle.mayUseNuke(MapUnitCombatant(unit), tile)) { Battle.NUKE(MapUnitCombatant(unit), tile) return } diff --git a/core/src/com/unciv/logic/battle/Battle.kt b/core/src/com/unciv/logic/battle/Battle.kt index fe98a49214..cce0c7fd88 100644 --- a/core/src/com/unciv/logic/battle/Battle.kt +++ b/core/src/com/unciv/logic/battle/Battle.kt @@ -11,6 +11,7 @@ import com.unciv.logic.map.TileInfo import com.unciv.models.AttackableTile import com.unciv.models.UnitActionType import com.unciv.models.ruleset.unique.Unique +import com.unciv.models.ruleset.unique.UniqueType import com.unciv.models.stats.Stat import com.unciv.models.stats.Stats import com.unciv.ui.utils.toPercent @@ -538,6 +539,28 @@ object Battle { attacker.popupAlerts.add(PopupAlert(AlertType.Defeated, attackedCiv.civName)) } } + + fun mayUseNuke(nuke: MapUnitCombatant, targetTile: TileInfo): Boolean { + val blastRadius = + if (!nuke.unit.hasUnique(UniqueType.BlastRadius)) 2 + else nuke.unit.getMatchingUniques(UniqueType.BlastRadius).first().params[0].toInt() + + var canNuke = true + val attackerCiv = nuke.getCivInfo() + for (tile in targetTile.getTilesInDistance(blastRadius)) { + val defendingTileCiv = tile.getCity()?.civInfo + if (defendingTileCiv != null && attackerCiv.knows(defendingTileCiv)) { + canNuke = canNuke && attackerCiv.getDiplomacyManager(defendingTileCiv).canAttack() + } + + val defender = getMapCombatantOfTile(tile) ?: continue + val defendingUnitCiv = defender.getCivInfo() + if (attackerCiv.knows(defendingUnitCiv)) { + canNuke = canNuke && attackerCiv.getDiplomacyManager(defendingUnitCiv).canAttack() + } + } + return canNuke + } @Suppress("FunctionName") // Yes we want this name to stand out fun NUKE(attacker: MapUnitCombatant, targetTile: TileInfo) { @@ -553,8 +576,8 @@ object Battle { } val blastRadius = - if (!attacker.unit.hasUnique("Blast radius []")) 2 - else attacker.unit.getMatchingUniques("Blast radius []").first().params[0].toInt() + if (!attacker.unit.hasUnique(UniqueType.BlastRadius)) 2 + else attacker.unit.getMatchingUniques(UniqueType.BlastRadius).first().params[0].toInt() val strength = when { (attacker.unit.hasUnique("Nuclear weapon of Strength []")) -> diff --git a/core/src/com/unciv/models/ruleset/unique/UniqueType.kt b/core/src/com/unciv/models/ruleset/unique/UniqueType.kt index 24e550d053..f3a2f05727 100644 --- a/core/src/com/unciv/models/ruleset/unique/UniqueType.kt +++ b/core/src/com/unciv/models/ruleset/unique/UniqueType.kt @@ -187,6 +187,7 @@ enum class UniqueType(val text:String, vararg targets: UniqueTarget) { @Deprecated("As of 3.17.5", ReplaceWith("[amount]% Spread Religion Strength "), DeprecationLevel.WARNING) SpreadReligionStrengthUnits("[amount]% Spread Religion Strength for [mapUnitFilter] units", UniqueTarget.Global), + BlastRadius("Blast radius [amount]", UniqueTarget.Unit), CarryAirUnits("Can carry [amount] [mapUnitFilter] units", UniqueTarget.Unit), CarryExtraAirUnits("Can carry [amount] extra [mapUnitFilter] units", UniqueTarget.Unit), diff --git a/core/src/com/unciv/ui/worldscreen/bottombar/BattleTable.kt b/core/src/com/unciv/ui/worldscreen/bottombar/BattleTable.kt index 4c57b85d72..2c43a87272 100644 --- a/core/src/com/unciv/ui/worldscreen/bottombar/BattleTable.kt +++ b/core/src/com/unciv/ui/worldscreen/bottombar/BattleTable.kt @@ -13,6 +13,7 @@ import com.unciv.logic.automation.UnitAutomation import com.unciv.logic.battle.* import com.unciv.logic.map.TileInfo import com.unciv.models.AttackableTile +import com.unciv.models.ruleset.unique.UniqueType import com.unciv.models.translations.tr import com.unciv.ui.utils.* import com.unciv.ui.worldscreen.WorldScreen @@ -228,31 +229,17 @@ class BattleTable(val worldScreen: WorldScreen): Table() { attackerNameWrapper.add(UnitGroup(attacker.unit,25f)).padRight(5f) attackerNameWrapper.add(attackerLabel) add(attackerNameWrapper) - var canNuke = true - val defenderNameWrapper = Table() + + val canNuke = Battle.mayUseNuke(attacker, targetTile) + val blastRadius = - if (!attacker.unit.hasUnique("Blast radius []")) 2 - else attacker.unit.getMatchingUniques("Blast radius []").first().params[0].toInt() + if (!attacker.unit.hasUnique(UniqueType.BlastRadius)) 2 + else attacker.unit.getMatchingUniques(UniqueType.BlastRadius).first().params[0].toInt() + + val defenderNameWrapper = Table() for (tile in targetTile.getTilesInDistance(blastRadius)) { - - //To make sure we dont nuke civilisations we cant declare war with - val attackerCiv = attacker.getCivInfo() - val defenderTileCiv = tile.getCity()?.civInfo - - if(defenderTileCiv != null && defenderTileCiv.knows(attackerCiv)) { - val canAttackDefenderCiv = attackerCiv.getDiplomacyManager(defenderTileCiv).canAttack() - canNuke = canNuke && canAttackDefenderCiv - } val defender = tryGetDefenderAtTile(tile, true) ?: continue - - val defenderUnitCiv = defender.getCivInfo() - - if( defenderUnitCiv.knows(attackerCiv)) - { - val canAttackDefenderUnitCiv = attackerCiv.getDiplomacyManager(defenderUnitCiv).canAttack() - canNuke = canNuke && canAttackDefenderUnitCiv - } - + val defenderLabel = Label(defender.getName().tr(), skin) when (defender) { is MapUnitCombatant -> @@ -271,7 +258,7 @@ class BattleTable(val worldScreen: WorldScreen): Table() { addSeparator().pad(0f) row().pad(5f) - val attackButton = "NUKE".toTextButton().apply { color= Color.RED } + val attackButton = "NUKE".toTextButton().apply { color = Color.RED } val canReach = attacker.unit.currentTile.getTilesInDistance(attacker.unit.getRange()).contains(targetTile)