mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-13 17:28:57 +07:00
Likely fixed a bug where AI nukes could hit nations they had a peace treaty with (#5449)
* Likely fixed a bug where AI nukes could hit players they had a peace treaty with * Typefied blast radius unique
This commit is contained in:
@ -14,12 +14,12 @@ object BattleHelper {
|
|||||||
fun tryAttackNearbyEnemy(unit: MapUnit, stayOnTile: Boolean = false): Boolean {
|
fun tryAttackNearbyEnemy(unit: MapUnit, stayOnTile: Boolean = false): Boolean {
|
||||||
if (unit.hasUnique("Cannot attack")) return false
|
if (unit.hasUnique("Cannot attack")) return false
|
||||||
val attackableEnemies = getAttackableEnemies(unit, unit.movement.getDistanceToTiles(), stayOnTile=stayOnTile)
|
val attackableEnemies = getAttackableEnemies(unit, unit.movement.getDistanceToTiles(), stayOnTile=stayOnTile)
|
||||||
// Only take enemies we can fight without dying
|
// Only take enemies we can fight without dying
|
||||||
.filter {
|
.filter {
|
||||||
BattleDamage.calculateDamageToAttacker(MapUnitCombatant(unit),
|
BattleDamage.calculateDamageToAttacker(MapUnitCombatant(unit),
|
||||||
it.tileToAttackFrom,
|
it.tileToAttackFrom,
|
||||||
Battle.getMapCombatantOfTile(it.tileToAttack)!!) < unit.health
|
Battle.getMapCombatantOfTile(it.tileToAttack)!!) < unit.health
|
||||||
}
|
}
|
||||||
|
|
||||||
val enemyTileToAttack = chooseAttackTarget(unit, attackableEnemies)
|
val enemyTileToAttack = chooseAttackTarget(unit, attackableEnemies)
|
||||||
|
|
||||||
|
@ -331,7 +331,7 @@ object SpecificUnitAutomation {
|
|||||||
val tilesInRange = unit.currentTile.getTilesInDistance(unit.getRange())
|
val tilesInRange = unit.currentTile.getTilesInDistance(unit.getRange())
|
||||||
for (tile in tilesInRange) {
|
for (tile in tilesInRange) {
|
||||||
// For now AI will only use nukes against cities because in all honesty that's the best use for them.
|
// 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)
|
Battle.NUKE(MapUnitCombatant(unit), tile)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ import com.unciv.logic.map.TileInfo
|
|||||||
import com.unciv.models.AttackableTile
|
import com.unciv.models.AttackableTile
|
||||||
import com.unciv.models.UnitActionType
|
import com.unciv.models.UnitActionType
|
||||||
import com.unciv.models.ruleset.unique.Unique
|
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.Stat
|
||||||
import com.unciv.models.stats.Stats
|
import com.unciv.models.stats.Stats
|
||||||
import com.unciv.ui.utils.toPercent
|
import com.unciv.ui.utils.toPercent
|
||||||
@ -538,6 +539,28 @@ object Battle {
|
|||||||
attacker.popupAlerts.add(PopupAlert(AlertType.Defeated, attackedCiv.civName))
|
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
|
@Suppress("FunctionName") // Yes we want this name to stand out
|
||||||
fun NUKE(attacker: MapUnitCombatant, targetTile: TileInfo) {
|
fun NUKE(attacker: MapUnitCombatant, targetTile: TileInfo) {
|
||||||
@ -553,8 +576,8 @@ object Battle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val blastRadius =
|
val blastRadius =
|
||||||
if (!attacker.unit.hasUnique("Blast radius []")) 2
|
if (!attacker.unit.hasUnique(UniqueType.BlastRadius)) 2
|
||||||
else attacker.unit.getMatchingUniques("Blast radius []").first().params[0].toInt()
|
else attacker.unit.getMatchingUniques(UniqueType.BlastRadius).first().params[0].toInt()
|
||||||
|
|
||||||
val strength = when {
|
val strength = when {
|
||||||
(attacker.unit.hasUnique("Nuclear weapon of Strength []")) ->
|
(attacker.unit.hasUnique("Nuclear weapon of Strength []")) ->
|
||||||
|
@ -187,6 +187,7 @@ enum class UniqueType(val text:String, vararg targets: UniqueTarget) {
|
|||||||
@Deprecated("As of 3.17.5", ReplaceWith("[amount]% Spread Religion Strength <for [mapUnitFilter] units>"), DeprecationLevel.WARNING)
|
@Deprecated("As of 3.17.5", ReplaceWith("[amount]% Spread Religion Strength <for [mapUnitFilter] units>"), DeprecationLevel.WARNING)
|
||||||
SpreadReligionStrengthUnits("[amount]% Spread Religion Strength for [mapUnitFilter] units", UniqueTarget.Global),
|
SpreadReligionStrengthUnits("[amount]% Spread Religion Strength for [mapUnitFilter] units", UniqueTarget.Global),
|
||||||
|
|
||||||
|
BlastRadius("Blast radius [amount]", UniqueTarget.Unit),
|
||||||
|
|
||||||
CarryAirUnits("Can carry [amount] [mapUnitFilter] units", UniqueTarget.Unit),
|
CarryAirUnits("Can carry [amount] [mapUnitFilter] units", UniqueTarget.Unit),
|
||||||
CarryExtraAirUnits("Can carry [amount] extra [mapUnitFilter] units", UniqueTarget.Unit),
|
CarryExtraAirUnits("Can carry [amount] extra [mapUnitFilter] units", UniqueTarget.Unit),
|
||||||
|
@ -13,6 +13,7 @@ import com.unciv.logic.automation.UnitAutomation
|
|||||||
import com.unciv.logic.battle.*
|
import com.unciv.logic.battle.*
|
||||||
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.unique.UniqueType
|
||||||
import com.unciv.models.translations.tr
|
import com.unciv.models.translations.tr
|
||||||
import com.unciv.ui.utils.*
|
import com.unciv.ui.utils.*
|
||||||
import com.unciv.ui.worldscreen.WorldScreen
|
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(UnitGroup(attacker.unit,25f)).padRight(5f)
|
||||||
attackerNameWrapper.add(attackerLabel)
|
attackerNameWrapper.add(attackerLabel)
|
||||||
add(attackerNameWrapper)
|
add(attackerNameWrapper)
|
||||||
var canNuke = true
|
|
||||||
val defenderNameWrapper = Table()
|
val canNuke = Battle.mayUseNuke(attacker, targetTile)
|
||||||
|
|
||||||
val blastRadius =
|
val blastRadius =
|
||||||
if (!attacker.unit.hasUnique("Blast radius []")) 2
|
if (!attacker.unit.hasUnique(UniqueType.BlastRadius)) 2
|
||||||
else attacker.unit.getMatchingUniques("Blast radius []").first().params[0].toInt()
|
else attacker.unit.getMatchingUniques(UniqueType.BlastRadius).first().params[0].toInt()
|
||||||
|
|
||||||
|
val defenderNameWrapper = Table()
|
||||||
for (tile in targetTile.getTilesInDistance(blastRadius)) {
|
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 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)
|
val defenderLabel = Label(defender.getName().tr(), skin)
|
||||||
when (defender) {
|
when (defender) {
|
||||||
is MapUnitCombatant ->
|
is MapUnitCombatant ->
|
||||||
@ -271,7 +258,7 @@ class BattleTable(val worldScreen: WorldScreen): Table() {
|
|||||||
addSeparator().pad(0f)
|
addSeparator().pad(0f)
|
||||||
row().pad(5f)
|
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)
|
val canReach = attacker.unit.currentTile.getTilesInDistance(attacker.unit.getRange()).contains(targetTile)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user