mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-06 08:21:36 +07:00
Melee Escort Attacking Fix (#11310)
* Added a test * Fixed melee units attack moving into tiles that the escorting unit can't move to * Added tests * Update core/src/com/unciv/logic/battle/TargetHelper.kt --------- Co-authored-by: Yair Morgenstern <yairm210@hotmail.com>
This commit is contained in:
@ -25,11 +25,18 @@ object TargetHelper {
|
||||
val tilesWithEnemies: HashSet<Tile> = HashSet()
|
||||
val tilesWithoutEnemies: HashSet<Tile> = HashSet()
|
||||
for ((reachableTile, movementLeft) in tilesToAttackFrom) { // tiles we'll still have energy after we reach there
|
||||
// If we are a melee unit that is escorting, we only want to be able to attack from this
|
||||
// tile if the escorted unit can also move into the tile we are attacking if we kill the enemy unit.
|
||||
if (unit.baseUnit.isMelee() && unit.isEscorting()) {
|
||||
val escortingUnit = unit.getOtherEscortUnit()!!
|
||||
if (!escortingUnit.movement.canReachInCurrentTurn(reachableTile)
|
||||
|| escortingUnit.currentMovement - escortingUnit.movement.getDistanceToTiles()[reachableTile]!!.totalDistance <= 0f)
|
||||
continue
|
||||
}
|
||||
val tilesInAttackRange =
|
||||
if (unit.hasUnique(UniqueType.IndirectFire) || unit.baseUnit.movesLikeAirUnits())
|
||||
reachableTile.getTilesInDistance(rangeOfAttack)
|
||||
else reachableTile.tileMap.getViewableTiles(reachableTile.position, rangeOfAttack, true).asSequence()
|
||||
|
||||
for (tile in tilesInAttackRange) {
|
||||
when {
|
||||
// Since military units can technically enter tiles with enemy civilians,
|
||||
|
@ -2,9 +2,15 @@ package com.unciv.logic.map
|
||||
|
||||
import com.badlogic.gdx.math.Vector2
|
||||
import com.unciv.Constants
|
||||
import com.unciv.logic.battle.Battle
|
||||
import com.unciv.logic.battle.MapUnitCombatant
|
||||
import com.unciv.logic.battle.TargetHelper
|
||||
import com.unciv.logic.civilization.Civilization
|
||||
import com.unciv.testing.GdxTestRunner
|
||||
import com.unciv.testing.TestGame
|
||||
import com.unciv.utils.DebugUtils
|
||||
import org.junit.After
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
@ -20,6 +26,11 @@ internal class UnitFormationTests {
|
||||
civInfo = testGame.addCiv()
|
||||
}
|
||||
|
||||
@After
|
||||
fun wrapUp() {
|
||||
DebugUtils.VISIBLE_MAP = false
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `basic formation functionality civilian`() {
|
||||
setUp(1)
|
||||
@ -195,4 +206,74 @@ internal class UnitFormationTests {
|
||||
civilianDistanceToTiles = civilianUnit.movement.getDistanceToTiles()
|
||||
assertFalse(militaryUnit.movement.getDistanceToTiles().any { !civilianDistanceToTiles.contains(it.key) })
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test escort attack and move civilian unit`() {
|
||||
setUp(3)
|
||||
val enemyCiv = testGame.addCiv()
|
||||
civInfo.diplomacyFunctions.makeCivilizationsMeet(enemyCiv)
|
||||
civInfo.getDiplomacyManager(enemyCiv).declareWar()
|
||||
val centerTile = testGame.getTile(Vector2(0f,0f))
|
||||
val enemyTile = testGame.getTile(Vector2(2f,2f))
|
||||
val scout = testGame.addUnit("Warrior", civInfo, centerTile)
|
||||
val civilianUnit = testGame.addUnit("Worker", civInfo, centerTile)
|
||||
val enemyUnit = testGame.addUnit("Warrior", enemyCiv , enemyTile)
|
||||
enemyUnit.health = 1 // Needs to be killable by the scout
|
||||
scout.startEscorting()
|
||||
assertTrue(scout.isEscorting())
|
||||
assertTrue(civilianUnit.isEscorting())
|
||||
|
||||
assertEquals(1, TargetHelper.getAttackableEnemies(scout, scout.movement.getDistanceToTiles()).count())
|
||||
Battle.attack(MapUnitCombatant(scout), MapUnitCombatant(enemyUnit))
|
||||
assertEquals(0, enemyUnit.health)
|
||||
assertEquals(enemyTile, scout.getTile())
|
||||
assertEquals(enemyTile, civilianUnit.getTile())
|
||||
assertTrue(scout.isEscorting())
|
||||
assertTrue(civilianUnit.isEscorting())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test escort attack with ranged unit`() {
|
||||
setUp(3)
|
||||
val enemyCiv = testGame.addCiv()
|
||||
DebugUtils.VISIBLE_MAP = true
|
||||
civInfo.diplomacyFunctions.makeCivilizationsMeet(enemyCiv)
|
||||
civInfo.getDiplomacyManager(enemyCiv).declareWar()
|
||||
val centerTile = testGame.getTile(Vector2(0f,0f))
|
||||
val enemyTile = testGame.getTile(Vector2(3f,3f))
|
||||
val archer = testGame.addUnit("Archer", civInfo, centerTile)
|
||||
val civilianUnit = testGame.addUnit("Worker", civInfo, centerTile)
|
||||
val enemyUnit = testGame.addUnit("Warrior", enemyCiv , enemyTile)
|
||||
enemyUnit.health = 1 // Needs to be killable by the scout
|
||||
archer.startEscorting()
|
||||
assertTrue(archer.isEscorting())
|
||||
assertTrue(civilianUnit.isEscorting())
|
||||
|
||||
assertEquals(1, TargetHelper.getAttackableEnemies(archer, archer.movement.getDistanceToTiles()).count())
|
||||
Battle.attack(MapUnitCombatant(archer), MapUnitCombatant(enemyUnit))
|
||||
assertEquals(0, enemyUnit.health)
|
||||
assertTrue(archer.isEscorting())
|
||||
assertTrue(civilianUnit.isEscorting())
|
||||
assertEquals(archer.getTile(), civilianUnit.getTile())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test escort attack with military unit having ignoreTerrainCost`() {
|
||||
setUp(3)
|
||||
val enemyCiv = testGame.addCiv()
|
||||
civInfo.diplomacyFunctions.makeCivilizationsMeet(enemyCiv)
|
||||
civInfo.getDiplomacyManager(enemyCiv).declareWar()
|
||||
val centerTile = testGame.getTile(Vector2(0f,0f))
|
||||
val forestTile = testGame.getTile(Vector2(1f,1f))
|
||||
val enemyTile = testGame.getTile(Vector2(2f,2f))
|
||||
val scout = testGame.addUnit("Warrior", civInfo, centerTile)
|
||||
val civilianUnit = testGame.addUnit("Worker", civInfo, centerTile)
|
||||
val enemyUnit = testGame.addUnit("Warrior", enemyCiv , enemyTile)
|
||||
enemyUnit.health = 1 // Needs to be killable by the scout
|
||||
forestTile.addTerrainFeature("Forest")
|
||||
scout.startEscorting()
|
||||
assertTrue(scout.isEscorting())
|
||||
assertTrue(civilianUnit.isEscorting())
|
||||
assertTrue(TargetHelper.getAttackableEnemies(scout, scout.movement.getDistanceToTiles()).isEmpty())
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user