Fix issue when city can not bombard enemy (#1644)

This commit is contained in:
Vladimir Tanakov
2020-01-11 23:11:20 +03:00
committed by Yair Morgenstern
parent 857763654f
commit fd5d38fb01
4 changed files with 39 additions and 37 deletions

View File

@ -186,7 +186,7 @@ class UnitAutomation{
} }
} }
val tileCombatant = Battle(combatant.getCivInfo().gameInfo).getMapCombatantOfTile(tile) val tileCombatant = Battle.getMapCombatantOfTile(tile)
if(tileCombatant==null) return false if(tileCombatant==null) return false
if(tileCombatant.getCivInfo()==combatant.getCivInfo() ) return false if(tileCombatant.getCivInfo()==combatant.getCivInfo() ) return false
if(!combatant.getCivInfo().isAtWarWith(tileCombatant.getCivInfo())) return false if(!combatant.getCivInfo().isAtWarWith(tileCombatant.getCivInfo())) return false
@ -269,7 +269,7 @@ class UnitAutomation{
tilesToCheck = unit.getTile().getTilesInDistance(CLOSE_ENEMY_TILES_AWAY_LIMIT) tilesToCheck = unit.getTile().getTilesInDistance(CLOSE_ENEMY_TILES_AWAY_LIMIT)
).filter { // Ignore units that would 1-shot you if you attacked ).filter { // Ignore units that would 1-shot you if you attacked
BattleDamage().calculateDamageToAttacker(MapUnitCombatant(unit), BattleDamage().calculateDamageToAttacker(MapUnitCombatant(unit),
Battle(unit.civInfo.gameInfo).getMapCombatantOfTile(it.tileToAttack)!!) < unit.health Battle.getMapCombatantOfTile(it.tileToAttack)!!) < unit.health
} }
if(unit.type.isRanged()) if(unit.type.isRanged())
@ -383,7 +383,7 @@ class UnitAutomation{
// 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),
Battle(unit.civInfo.gameInfo).getMapCombatantOfTile(it.tileToAttack)!!) < unit.health Battle.getMapCombatantOfTile(it.tileToAttack)!!) < unit.health
} }
.filter {it.tileToAttackFrom.isLand} .filter {it.tileToAttackFrom.isLand}
@ -401,13 +401,13 @@ class UnitAutomation{
// 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),
Battle(unit.civInfo.gameInfo).getMapCombatantOfTile(it.tileToAttack)!!) < unit.health Battle.getMapCombatantOfTile(it.tileToAttack)!!) < unit.health
} }
val enemyTileToAttack = chooseAttackTarget(unit, attackableEnemies) val enemyTileToAttack = chooseAttackTarget(unit, attackableEnemies)
if (enemyTileToAttack != null) { if (enemyTileToAttack != null) {
Battle(unit.civInfo.gameInfo).moveAndAttack(MapUnitCombatant(unit), enemyTileToAttack) Battle.moveAndAttack(MapUnitCombatant(unit), enemyTileToAttack)
return true return true
} }
return false return false
@ -417,8 +417,8 @@ class UnitAutomation{
if (!city.attackedThisTurn) { if (!city.attackedThisTurn) {
val target = chooseBombardTarget(city) val target = chooseBombardTarget(city)
if (target == null) return false if (target == null) return false
val enemy = Battle(city.civInfo.gameInfo).getMapCombatantOfTile(target)!! val enemy = Battle.getMapCombatantOfTile(target)!!
Battle(city.civInfo.gameInfo).attack(CityCombatant(city), enemy) Battle.attack(CityCombatant(city), enemy)
return true return true
} }
return false return false
@ -439,7 +439,7 @@ class UnitAutomation{
enemyTileToAttack = capturableCity // enter it quickly, top priority! enemyTileToAttack = capturableCity // enter it quickly, top priority!
else if (nonCityTilesToAttack.isNotEmpty()) // second priority, units else if (nonCityTilesToAttack.isNotEmpty()) // second priority, units
enemyTileToAttack = nonCityTilesToAttack.minBy { Battle(unit.civInfo.gameInfo).getMapCombatantOfTile(it.tileToAttack)!!.getHealth() } enemyTileToAttack = nonCityTilesToAttack.minBy { Battle.getMapCombatantOfTile(it.tileToAttack)!!.getHealth() }
else if (cityWithHealthLeft!=null) enemyTileToAttack = cityWithHealthLeft// third priority, city else if (cityWithHealthLeft!=null) enemyTileToAttack = cityWithHealthLeft// third priority, city
@ -450,14 +450,14 @@ class UnitAutomation{
var targets = getBombardTargets(city) var targets = getBombardTargets(city)
if (targets.isEmpty()) return null if (targets.isEmpty()) return null
val siegeUnits = targets val siegeUnits = targets
.filter { Battle(city.civInfo.gameInfo).getMapCombatantOfTile(it)!!.getUnitType()==UnitType.Siege } .filter { Battle.getMapCombatantOfTile(it)!!.getUnitType()==UnitType.Siege }
if(siegeUnits.any()) targets = siegeUnits if(siegeUnits.any()) targets = siegeUnits
else{ else{
val rangedUnits = targets val rangedUnits = targets
.filter { Battle(city.civInfo.gameInfo).getMapCombatantOfTile(it)!!.getUnitType().isRanged() } .filter { Battle.getMapCombatantOfTile(it)!!.getUnitType().isRanged() }
if(rangedUnits.any()) targets=rangedUnits if(rangedUnits.any()) targets=rangedUnits
} }
return targets.minBy { Battle(city.civInfo.gameInfo).getMapCombatantOfTile(it)!!.getHealth() } return targets.minBy { Battle.getMapCombatantOfTile(it)!!.getHealth() }
} }
private fun tryGarrisoningUnit(unit: MapUnit): Boolean { private fun tryGarrisoningUnit(unit: MapUnit): Boolean {

View File

@ -3,7 +3,6 @@ package com.unciv.logic.battle
import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.graphics.Color
import com.unciv.Constants import com.unciv.Constants
import com.unciv.UncivGame import com.unciv.UncivGame
import com.unciv.logic.GameInfo
import com.unciv.logic.automation.UnitAutomation import com.unciv.logic.automation.UnitAutomation
import com.unciv.logic.city.CityInfo import com.unciv.logic.city.CityInfo
import com.unciv.logic.civilization.AlertType import com.unciv.logic.civilization.AlertType
@ -18,7 +17,7 @@ import kotlin.math.max
/** /**
* Damage calculations according to civ v wiki and https://steamcommunity.com/sharedfiles/filedetails/?id=170194443 * Damage calculations according to civ v wiki and https://steamcommunity.com/sharedfiles/filedetails/?id=170194443
*/ */
class Battle(val gameInfo:GameInfo) { object Battle {
fun moveAndAttack(attacker: ICombatant, attackableTile: UnitAutomation.AttackableTile){ fun moveAndAttack(attacker: ICombatant, attackableTile: UnitAutomation.AttackableTile){
if (attacker is MapUnitCombatant) { if (attacker is MapUnitCombatant) {
@ -286,7 +285,7 @@ class Battle(val gameInfo:GameInfo) {
defender.getCivInfo().destroy() defender.getCivInfo().destroy()
attacker.getCivInfo().popupAlerts.add(PopupAlert(AlertType.Defeated,defender.getCivInfo().civName)) attacker.getCivInfo().popupAlerts.add(PopupAlert(AlertType.Defeated,defender.getCivInfo().civName))
} }
val capturedUnit = (defender as MapUnitCombatant).unit val capturedUnit = (defender as MapUnitCombatant).unit
capturedUnit.civInfo.addNotification("An enemy ["+attacker.getName()+"] has captured our ["+defender.getName()+"]", capturedUnit.civInfo.addNotification("An enemy ["+attacker.getName()+"] has captured our ["+defender.getName()+"]",
defender.getTile().position, Color.RED) defender.getTile().position, Color.RED)

View File

@ -150,19 +150,22 @@ class TileMap {
} }
fun getViewableTiles(position: Vector2, sightDistance: Int, ignoreCurrentTileHeight:Boolean=false): MutableList<TileInfo> { fun getViewableTiles(position: Vector2, sightDistance: Int, ignoreCurrentTileHeight: Boolean = false): MutableList<TileInfo> {
val viewableTiles = getTilesInDistance(position, 1).toMutableList() if (ignoreCurrentTileHeight) {
val currentTileHeight = if(ignoreCurrentTileHeight) 0 else get(position).getHeight() return getTilesInDistance(position, sightDistance).toMutableList()
} else {
val viewableTiles = getTilesInDistance(position, 1).toMutableList()
val currentTileHeight = get(position).getHeight()
for (i in 1..sightDistance) { // in each layer, for (i in 1..sightDistance) { // in each layer,
// This is so we don't use tiles in the same distance to "see over", // This is so we don't use tiles in the same distance to "see over",
// that is to say, the "viewableTiles.contains(it) check will return false for neighbors from the same distance // that is to say, the "viewableTiles.contains(it) check will return false for neighbors from the same distance
val tilesToAddInDistanceI = ArrayList<TileInfo>() val tilesToAddInDistanceI = ArrayList<TileInfo>()
for (tile in getTilesAtDistance(position, i)) { // for each tile in that layer, for (tile in getTilesAtDistance(position, i)) { // for each tile in that layer,
val targetTileHeight = tile.getHeight() val targetTileHeight = tile.getHeight()
/* /*
Okay so, if we're looking at a tile from a to c with b in the middle, Okay so, if we're looking at a tile from a to c with b in the middle,
we have several scenarios: we have several scenarios:
1. a>b - - I can see everything, b does not hide c 1. a>b - - I can see everything, b does not hide c
@ -177,19 +180,20 @@ class TileMap {
This can all be summed up as "I can see c if a>b || c>b || b==0 " This can all be summed up as "I can see c if a>b || c>b || b==0 "
*/ */
val containsViewableNeighborThatCanSeeOver = tile.neighbors.any { val containsViewableNeighborThatCanSeeOver = tile.neighbors.any {
val neighborHeight = it.getHeight() val neighborHeight = it.getHeight()
viewableTiles.contains(it) && ( viewableTiles.contains(it) && (
currentTileHeight > neighborHeight // a>b currentTileHeight > neighborHeight // a>b
|| targetTileHeight > neighborHeight // c>b || targetTileHeight > neighborHeight // c>b
|| neighborHeight == 0) // b==0 || neighborHeight == 0) // b==0
}
if (containsViewableNeighborThatCanSeeOver) tilesToAddInDistanceI.add(tile)
} }
if (containsViewableNeighborThatCanSeeOver) tilesToAddInDistanceI.add(tile) viewableTiles.addAll(tilesToAddInDistanceI)
} }
viewableTiles.addAll(tilesToAddInDistanceI)
}
return viewableTiles return viewableTiles
}
} }
fun setTransients(ruleset: Ruleset) { fun setTransients(ruleset: Ruleset) {

View File

@ -20,7 +20,6 @@ import kotlin.math.max
class BattleTable(val worldScreen: WorldScreen): Table() { class BattleTable(val worldScreen: WorldScreen): Table() {
private val battle = Battle(worldScreen.viewingCiv.gameInfo)
init{ init{
isVisible = false isVisible = false
skin = CameraStageBaseScreen.skin skin = CameraStageBaseScreen.skin
@ -64,7 +63,7 @@ class BattleTable(val worldScreen: WorldScreen): Table() {
if (worldScreen.mapHolder.selectedTile == null) return null // no selected tile if (worldScreen.mapHolder.selectedTile == null) return null // no selected tile
val selectedTile = worldScreen.mapHolder.selectedTile!! val selectedTile = worldScreen.mapHolder.selectedTile!!
val defender: ICombatant? = Battle(worldScreen.gameInfo).getMapCombatantOfTile(selectedTile) val defender: ICombatant? = Battle.getMapCombatantOfTile(selectedTile)
if(defender==null || if(defender==null ||
defender.getCivInfo()==attackerCiv) defender.getCivInfo()==attackerCiv)
@ -196,7 +195,7 @@ class BattleTable(val worldScreen: WorldScreen): Table() {
else { else {
attackButton.onClick { attackButton.onClick {
try { try {
battle.moveAndAttack(attacker, attackableEnemy) Battle.moveAndAttack(attacker, attackableEnemy)
worldScreen.mapHolder.unitActionOverlay?.remove() // the overlay was one of attacking worldScreen.mapHolder.unitActionOverlay?.remove() // the overlay was one of attacking
worldScreen.shouldUpdate = true worldScreen.shouldUpdate = true
} }