mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-23 19:43:13 -04:00
Refactor Cannot Move Unique (#8168)
* Add buildCheck flags * Catch issues in Swap Units * Move all code to movement code * Add back in Red Attack Range for Air Units * Remove useless parameter Be more specific for Air Attack range highlight
This commit is contained in:
parent
62c03d9545
commit
b84290de1b
@ -428,6 +428,7 @@ object Battle {
|
||||
private fun postBattleMoveToAttackedTile(attacker: ICombatant, defender: ICombatant, attackedTile: TileInfo) {
|
||||
if (!attacker.isMelee()) return
|
||||
if (!defender.isDefeated() && defender.getCivInfo() != attacker.getCivInfo()) return
|
||||
if (attacker is MapUnitCombatant && attacker.hasUnique(UniqueType.CannotMove)) return
|
||||
|
||||
// This is so that if we attack e.g. a barbarian in enemy territory that we can't enter, we won't enter it
|
||||
if ((attacker as MapUnitCombatant).unit.movement.canMoveTo(attackedTile)) {
|
||||
@ -1015,6 +1016,7 @@ object Battle {
|
||||
if (attacker !is MapUnitCombatant) return false // allow simple access to unit property
|
||||
if (defender !is MapUnitCombatant) return false
|
||||
if (defender.unit.isEmbarked()) return false
|
||||
if (defender.hasUnique(UniqueType.CannotMove)) return false
|
||||
// Promotions have no effect as per what I could find in available documentation
|
||||
val attackBaseUnit = attacker.unit.baseUnit
|
||||
val defendBaseUnit = defender.unit.baseUnit
|
||||
|
@ -478,7 +478,6 @@ class MapUnit : IsPartOfGameInfoSerialization {
|
||||
}
|
||||
|
||||
fun getMaxMovementForAirUnits(): Int {
|
||||
if (hasUnique(UniqueType.CannotMove)) return getRange() // also used for marking attack range
|
||||
return getRange() * 2
|
||||
}
|
||||
|
||||
|
@ -189,6 +189,7 @@ class UnitMovementAlgorithms(val unit: MapUnit) {
|
||||
* Returns an empty list if there's no way to get to the destination.
|
||||
*/
|
||||
fun getShortestPath(destination: TileInfo, avoidDamagingTerrain: Boolean = false): List<TileInfo> {
|
||||
if (unit.hasUnique(UniqueType.CannotMove)) return listOf()
|
||||
// First try and find a path without damaging terrain
|
||||
if (!avoidDamagingTerrain && unit.civInfo.passThroughImpassableUnlocked && unit.baseUnit.isLandUnit()) {
|
||||
val damageFreePath = getShortestPath(destination, true)
|
||||
@ -328,12 +329,14 @@ class UnitMovementAlgorithms(val unit: MapUnit) {
|
||||
/** This is performance-heavy - use as last resort, only after checking everything else!
|
||||
* Also note that REACHABLE tiles are not necessarily tiles that the unit CAN ENTER */
|
||||
fun canReach(destination: TileInfo): Boolean {
|
||||
if (unit.hasUnique(UniqueType.CannotMove)) return false
|
||||
if (unit.baseUnit.movesLikeAirUnits() || unit.isPreparingParadrop())
|
||||
return canReachInCurrentTurn(destination)
|
||||
return getShortestPath(destination).any()
|
||||
}
|
||||
|
||||
private fun canReachInCurrentTurn(destination: TileInfo): Boolean {
|
||||
if (unit.hasUnique(UniqueType.CannotMove)) return false
|
||||
if (unit.baseUnit.movesLikeAirUnits())
|
||||
return unit.currentTile.aerialDistanceTo(destination) <= unit.getMaxMovementForAirUnits()
|
||||
if (unit.isPreparingParadrop())
|
||||
@ -343,6 +346,7 @@ class UnitMovementAlgorithms(val unit: MapUnit) {
|
||||
|
||||
fun getReachableTilesInCurrentTurn(): Sequence<TileInfo> {
|
||||
return when {
|
||||
unit.hasUnique(UniqueType.CannotMove) -> emptySequence()
|
||||
unit.baseUnit.movesLikeAirUnits() ->
|
||||
unit.getTile().getTilesInDistanceRange(IntRange(1, unit.getMaxMovementForAirUnits()))
|
||||
unit.isPreparingParadrop() ->
|
||||
@ -372,6 +376,7 @@ class UnitMovementAlgorithms(val unit: MapUnit) {
|
||||
if (unit.baseUnit.movesLikeAirUnits()) return false
|
||||
// We can't swap with ourself
|
||||
if (reachableTile == unit.getTile()) return false
|
||||
if (unit.hasUnique(UniqueType.CannotMove)) return false
|
||||
// Check whether the tile contains a unit of the same type as us that we own and that can
|
||||
// also reach our tile in its current turn.
|
||||
val otherUnit = (
|
||||
@ -381,7 +386,9 @@ class UnitMovementAlgorithms(val unit: MapUnit) {
|
||||
reachableTile.militaryUnit
|
||||
) ?: return false
|
||||
val ourPosition = unit.getTile()
|
||||
if (otherUnit.owner != unit.owner || !otherUnit.movement.canReachInCurrentTurn(ourPosition)) return false
|
||||
if (otherUnit.owner != unit.owner
|
||||
|| otherUnit.hasUnique(UniqueType.CannotMove)
|
||||
|| !otherUnit.movement.canReachInCurrentTurn(ourPosition)) return false
|
||||
// Check if we could enter their tile if they wouldn't be there
|
||||
otherUnit.removeFromTile()
|
||||
val weCanEnterTheirTile = canMoveTo(reachableTile)
|
||||
@ -623,7 +630,6 @@ class UnitMovementAlgorithms(val unit: MapUnit) {
|
||||
* DOES NOT designate whether we can reach that tile in the current turn
|
||||
*/
|
||||
fun canMoveTo(tile: TileInfo, assumeCanPassThrough: Boolean = false): Boolean {
|
||||
if (unit.hasUnique(UniqueType.CannotMove)) return false
|
||||
if (unit.baseUnit.movesLikeAirUnits())
|
||||
return canAirUnitMoveTo(tile, unit)
|
||||
|
||||
@ -642,7 +648,6 @@ class UnitMovementAlgorithms(val unit: MapUnit) {
|
||||
}
|
||||
|
||||
private fun canAirUnitMoveTo(tile: TileInfo, unit: MapUnit): Boolean {
|
||||
if (unit.hasUnique(UniqueType.CannotMove)) return false
|
||||
// landing in the city
|
||||
if (tile.isCityCenter()) {
|
||||
if (tile.airUnits.filter { !it.isTransported }.size < 6 && tile.getCity()?.civInfo == unit.civInfo)
|
||||
@ -675,7 +680,6 @@ class UnitMovementAlgorithms(val unit: MapUnit) {
|
||||
* because optimization on this function results in massive benefits!
|
||||
*/
|
||||
fun canPassThrough(tile: TileInfo): Boolean {
|
||||
if (unit.hasUnique(UniqueType.CannotMove)) return false
|
||||
if (tile.isImpassible()) {
|
||||
// special exception - ice tiles are technically impassible, but some units can move through them anyway
|
||||
// helicopters can pass through impassable tiles like mountains
|
||||
|
@ -30,6 +30,7 @@ import com.unciv.models.AttackableTile
|
||||
import com.unciv.models.UncivSound
|
||||
import com.unciv.models.helpers.MapArrowType
|
||||
import com.unciv.models.helpers.MiscArrowTypes
|
||||
import com.unciv.models.ruleset.unique.UniqueType
|
||||
import com.unciv.ui.UncivStage
|
||||
import com.unciv.ui.audio.SoundPlayer
|
||||
import com.unciv.ui.images.ImageGetter
|
||||
@ -672,6 +673,17 @@ class WorldMapHolder(
|
||||
}
|
||||
}
|
||||
|
||||
// Add back in the red markers for Air Unit Attack range since they can't move, but can still attack
|
||||
if (unit.hasUnique(UniqueType.CannotMove) && isAirUnit && !unit.isPreparingAirSweep()) {
|
||||
val tilesInAttackRange = unit.getTile().getTilesInDistanceRange(IntRange(1, unit.getRange()))
|
||||
for (tile in tilesInAttackRange) {
|
||||
for (tileToColor in tileGroups[tile]!!) {
|
||||
// The tile is within attack range
|
||||
tileToColor.showHighlight(Color.RED, 0.3f)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Movement paths
|
||||
if (unitMovementPaths.containsKey(unit)) {
|
||||
for (tile in unitMovementPaths[unit]!!) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user