Wake up units when enemy sighted or displaced or attacked (#4145)

Co-authored-by: Yair Morgenstern <yairm210@hotmail.com>
This commit is contained in:
SomeTroglodyte 2021-06-18 08:40:07 +02:00 committed by GitHub
parent d7865f4a81
commit 87810b8ce8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 51 additions and 16 deletions

View File

@ -64,6 +64,10 @@ object Battle {
if (defender.isDefeated() && defender is CityCombatant && attacker is MapUnitCombatant && attacker.isMelee() && !attacker.unit.hasUnique("Unable to capture cities"))
conquerCity(defender.city, attacker)
// Exploring units surviving an attack should "wake up"
if (!defender.isDefeated() && defender is MapUnitCombatant && defender.unit.action == Constants.unitActionExplore)
defender.unit.action = null
// we're a melee unit and we destroyed\captured an enemy unit
postBattleMoveToAttackedTile(attacker, defender, attackedTile)

View File

@ -107,6 +107,11 @@ class CityExpansionManager {
return null
}
/**
* Removes one tile from this city's owned tiles, unconditionally, and updates dependent
* things like worked tiles, locked tiles, and stats.
* @param tileInfo The tile to relinquish
*/
fun relinquishOwnership(tileInfo: TileInfo) {
cityInfo.tiles = cityInfo.tiles.withoutItem(tileInfo.position)
for (city in cityInfo.civInfo.cities) {
@ -124,6 +129,14 @@ class CityExpansionManager {
cityInfo.cityStats.update()
}
/**
* Takes one tile into possession of this city, either unowned or owned by any other city.
*
* Also manages consequences like auto population reassign, stats, and displacing units
* that are no longer allowed on that tile.
*
* @param tileInfo The tile to take over
*/
fun takeOwnership(tileInfo: TileInfo) {
if (tileInfo.isCityCenter()) throw Exception("What?!")
if (tileInfo.getCity() != null)

View File

@ -198,15 +198,11 @@ class MapUnit {
return getUniques().any { it.placeholderText == unique }
}
fun updateVisibleTiles() {
if (type.isAirUnit()) {
viewableTiles = if (hasUnique("6 tiles in every direction always visible"))
getTile().getTilesInDistance(6).toList() // it's that simple
else listOf() // bomber units don't do recon
civInfo.updateViewableTiles() // for the civ
return
}
/**
* Determines this (land or sea) unit's current maximum vision range from unit properties, civ uniques and terrain.
* @return Maximum distance of tiles this unit may possibly see
*/
private fun getVisibilityRange(): Int {
var visibilityRange = 2
visibilityRange += getUniques().count { it.text == "+1 Visibility Range" }
for (unique in civInfo.getMatchingUniques("+[] Sight for all [] units"))
@ -223,13 +219,25 @@ class MapUnit {
visibilityRange += 1
//
val tile = getTile()
for (unique in tile.getAllTerrains().flatMap { it.uniqueObjects })
for (unique in getTile().getAllTerrains().flatMap { it.uniqueObjects })
if (unique.placeholderText == "[] Sight for [] units" && matchesFilter(unique.params[1]))
visibilityRange += unique.params[0].toInt()
viewableTiles = tile.getViewableTilesList(visibilityRange)
return visibilityRange
}
/**
* Update this unit's cache of viewable tiles and its civ's as well.
*/
fun updateVisibleTiles() {
if (type.isAirUnit()) {
viewableTiles = if (hasUnique("6 tiles in every direction always visible"))
getTile().getTilesInDistance(6).toList() // it's that simple
else listOf() // bomber units don't do recon
civInfo.updateViewableTiles() // for the civ
return
}
viewableTiles = getTile().getViewableTilesList(getVisibilityRange())
civInfo.updateViewableTiles() // for the civ
}
@ -570,9 +578,10 @@ class MapUnit {
attacksThisTurn = 0
due = true
// Wake sleeping units if there's an enemy nearby and civilian is not protected
// Wake sleeping units if there's an enemy in vision range:
// Military units always but civilians only if not protected.
if (isSleeping() && (!type.isCivilian() || currentTile.militaryUnit == null) &&
currentTile.getTilesInDistance(2).any {
this.viewableTiles.any {
it.militaryUnit != null && it.militaryUnit!!.civInfo.isAtWarWith(civInfo)
}
)

View File

@ -284,7 +284,12 @@ class UnitMovementAlgorithms(val unit:MapUnit) {
return true
}
/**
* Displace a unit - choose a viable tile close by if possible and 'teleport' the unit there.
* This will not use movement points or check for a possible route.
* It is used e.g. if an enemy city expands its borders, or trades or diplomacy change a unit's
* allowed position.
*/
fun teleportToClosestMoveableTile() {
var allowedTile: TileInfo? = null
var distance = 0
@ -304,8 +309,12 @@ class UnitMovementAlgorithms(val unit:MapUnit) {
}
}
unit.removeFromTile() // we "teleport" them away
if (allowedTile != null) // it's possible that there is no close tile, and all the guy's cities are full. Screw him then.
if (allowedTile != null) { // it's possible that there is no close tile, and all the guy's cities are full. Screw him then.
unit.putInTile(allowedTile)
// Cancel sleep or fortification if forcibly displaced - for now, leave movement / auto / explore orders
if (unit.isSleeping() || unit.isFortified())
unit.action = null
}
}
fun moveToTile(destination: TileInfo) {