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.getCivInfo()==combatant.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)
).filter { // Ignore units that would 1-shot you if you attacked
BattleDamage().calculateDamageToAttacker(MapUnitCombatant(unit),
Battle(unit.civInfo.gameInfo).getMapCombatantOfTile(it.tileToAttack)!!) < unit.health
Battle.getMapCombatantOfTile(it.tileToAttack)!!) < unit.health
}
if(unit.type.isRanged())
@ -383,7 +383,7 @@ class UnitAutomation{
// Only take enemies we can fight without dying
.filter {
BattleDamage().calculateDamageToAttacker(MapUnitCombatant(unit),
Battle(unit.civInfo.gameInfo).getMapCombatantOfTile(it.tileToAttack)!!) < unit.health
Battle.getMapCombatantOfTile(it.tileToAttack)!!) < unit.health
}
.filter {it.tileToAttackFrom.isLand}
@ -401,13 +401,13 @@ class UnitAutomation{
// Only take enemies we can fight without dying
.filter {
BattleDamage().calculateDamageToAttacker(MapUnitCombatant(unit),
Battle(unit.civInfo.gameInfo).getMapCombatantOfTile(it.tileToAttack)!!) < unit.health
Battle.getMapCombatantOfTile(it.tileToAttack)!!) < unit.health
}
val enemyTileToAttack = chooseAttackTarget(unit, attackableEnemies)
if (enemyTileToAttack != null) {
Battle(unit.civInfo.gameInfo).moveAndAttack(MapUnitCombatant(unit), enemyTileToAttack)
Battle.moveAndAttack(MapUnitCombatant(unit), enemyTileToAttack)
return true
}
return false
@ -417,8 +417,8 @@ class UnitAutomation{
if (!city.attackedThisTurn) {
val target = chooseBombardTarget(city)
if (target == null) return false
val enemy = Battle(city.civInfo.gameInfo).getMapCombatantOfTile(target)!!
Battle(city.civInfo.gameInfo).attack(CityCombatant(city), enemy)
val enemy = Battle.getMapCombatantOfTile(target)!!
Battle.attack(CityCombatant(city), enemy)
return true
}
return false
@ -439,7 +439,7 @@ class UnitAutomation{
enemyTileToAttack = capturableCity // enter it quickly, top priority!
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
@ -450,14 +450,14 @@ class UnitAutomation{
var targets = getBombardTargets(city)
if (targets.isEmpty()) return null
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
else{
val rangedUnits = targets
.filter { Battle(city.civInfo.gameInfo).getMapCombatantOfTile(it)!!.getUnitType().isRanged() }
.filter { Battle.getMapCombatantOfTile(it)!!.getUnitType().isRanged() }
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 {

View File

@ -3,7 +3,6 @@ package com.unciv.logic.battle
import com.badlogic.gdx.graphics.Color
import com.unciv.Constants
import com.unciv.UncivGame
import com.unciv.logic.GameInfo
import com.unciv.logic.automation.UnitAutomation
import com.unciv.logic.city.CityInfo
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
*/
class Battle(val gameInfo:GameInfo) {
object Battle {
fun moveAndAttack(attacker: ICombatant, attackableTile: UnitAutomation.AttackableTile){
if (attacker is MapUnitCombatant) {
@ -286,7 +285,7 @@ class Battle(val gameInfo:GameInfo) {
defender.getCivInfo().destroy()
attacker.getCivInfo().popupAlerts.add(PopupAlert(AlertType.Defeated,defender.getCivInfo().civName))
}
val capturedUnit = (defender as MapUnitCombatant).unit
capturedUnit.civInfo.addNotification("An enemy ["+attacker.getName()+"] has captured our ["+defender.getName()+"]",
defender.getTile().position, Color.RED)

View File

@ -150,19 +150,22 @@ class TileMap {
}
fun getViewableTiles(position: Vector2, sightDistance: Int, ignoreCurrentTileHeight:Boolean=false): MutableList<TileInfo> {
val viewableTiles = getTilesInDistance(position, 1).toMutableList()
val currentTileHeight = if(ignoreCurrentTileHeight) 0 else get(position).getHeight()
fun getViewableTiles(position: Vector2, sightDistance: Int, ignoreCurrentTileHeight: Boolean = false): MutableList<TileInfo> {
if (ignoreCurrentTileHeight) {
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,
// 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
val tilesToAddInDistanceI = ArrayList<TileInfo>()
for (i in 1..sightDistance) { // in each layer,
// 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
val tilesToAddInDistanceI = ArrayList<TileInfo>()
for (tile in getTilesAtDistance(position, i)) { // for each tile in that layer,
val targetTileHeight = tile.getHeight()
for (tile in getTilesAtDistance(position, i)) { // for each tile in that layer,
val targetTileHeight = tile.getHeight()
/*
/*
Okay so, if we're looking at a tile from a to c with b in the middle,
we have several scenarios:
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 "
*/
val containsViewableNeighborThatCanSeeOver = tile.neighbors.any {
val neighborHeight = it.getHeight()
viewableTiles.contains(it) && (
currentTileHeight > neighborHeight // a>b
|| targetTileHeight > neighborHeight // c>b
|| neighborHeight == 0) // b==0
val containsViewableNeighborThatCanSeeOver = tile.neighbors.any {
val neighborHeight = it.getHeight()
viewableTiles.contains(it) && (
currentTileHeight > neighborHeight // a>b
|| targetTileHeight > neighborHeight // c>b
|| 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) {

View File

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