mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-26 07:39:44 +07:00
Fix issue when city can not bombard enemy (#1644)
This commit is contained in:

committed by
Yair Morgenstern

parent
857763654f
commit
fd5d38fb01
@ -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 {
|
||||||
|
@ -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)
|
||||||
|
@ -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) {
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user