mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-26 07:39:44 +07:00
Submarines are now visible to adjacent units, and once turned visible, can be attacked by all enemy units (#5001)
* Submarines are now visible to adjacent units, and once turned visible, can attack be all enemy units * Deprecation & translation of unique saving
This commit is contained in:
@ -169,7 +169,7 @@ class GameInfo {
|
||||
it.militaryUnit != null && it.militaryUnit!!.civInfo != thisPlayer
|
||||
&& thisPlayer.isAtWarWith(it.militaryUnit!!.civInfo)
|
||||
&& (it.getOwner() == thisPlayer || it.neighbors.any { neighbor -> neighbor.getOwner() == thisPlayer }
|
||||
&& (!it.militaryUnit!!.isInvisible() || viewableInvisibleTiles.contains(it.position)))
|
||||
&& (!it.militaryUnit!!.isInvisible(thisPlayer) || viewableInvisibleTiles.contains(it.position)))
|
||||
}
|
||||
|
||||
// enemy units ON our territory
|
||||
|
@ -95,15 +95,11 @@ object BattleHelper {
|
||||
)
|
||||
return false
|
||||
|
||||
//only submarine and destroyer can attack submarine
|
||||
//garrisoned submarine can be attacked by anyone, or the city will be in invincible
|
||||
if (tileCombatant.isInvisible() && !tile.isCityCenter()) {
|
||||
if (combatant is MapUnitCombatant
|
||||
&& combatant.unit.hasUnique("Can attack submarines")
|
||||
&& combatant.getCivInfo().viewableInvisibleUnitsTiles.map { it.position }.contains(tile.position)) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
// Only units with the right unique can view submarines (or other invisible units) from more then one tile away.
|
||||
// Garrisoned invisible units can be attacked by anyone, as else the city will be in invincible.
|
||||
if (tileCombatant.isInvisible(combatant.getCivInfo()) && !tile.isCityCenter()) {
|
||||
return combatant is MapUnitCombatant
|
||||
&& combatant.getCivInfo().viewableInvisibleUnitsTiles.map { it.position }.contains(tile.position)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ class CityCombatant(val city: CityInfo) : ICombatant {
|
||||
override fun getTile(): TileInfo = city.getCenterTile()
|
||||
override fun getName(): String = city.name
|
||||
override fun isDefeated(): Boolean = city.health == 1
|
||||
override fun isInvisible(): Boolean = false
|
||||
override fun isInvisible(to: CivilizationInfo): Boolean = false
|
||||
override fun canAttack(): Boolean = city.canBombard()
|
||||
override fun matchesCategory(category: String) = category == "City" || category == "All"
|
||||
override fun getAttackSound() = UncivSound.Bombard
|
||||
|
@ -5,7 +5,7 @@ import com.unciv.logic.map.TileInfo
|
||||
import com.unciv.models.UncivSound
|
||||
import com.unciv.models.ruleset.unit.UnitType
|
||||
|
||||
interface ICombatant{
|
||||
interface ICombatant {
|
||||
fun getName(): String
|
||||
fun getHealth():Int
|
||||
fun getMaxHealth():Int
|
||||
@ -16,7 +16,7 @@ interface ICombatant{
|
||||
fun isDefeated():Boolean
|
||||
fun getCivInfo(): CivilizationInfo
|
||||
fun getTile(): TileInfo
|
||||
fun isInvisible(): Boolean
|
||||
fun isInvisible(to: CivilizationInfo): Boolean
|
||||
fun canAttack(): Boolean
|
||||
fun matchesCategory(category:String): Boolean
|
||||
fun getAttackSound(): UncivSound
|
||||
|
@ -13,7 +13,7 @@ class MapUnitCombatant(val unit: MapUnit) : ICombatant {
|
||||
override fun getTile(): TileInfo = unit.getTile()
|
||||
override fun getName(): String = unit.name
|
||||
override fun isDefeated(): Boolean = unit.health <= 0
|
||||
override fun isInvisible(): Boolean = unit.isInvisible()
|
||||
override fun isInvisible(to: CivilizationInfo): Boolean = unit.isInvisible(to)
|
||||
override fun canAttack(): Boolean = unit.canAttack()
|
||||
override fun matchesCategory(category:String) = unit.matchesFilter(category)
|
||||
override fun getAttackSound() = unit.baseUnit.attackSound.let {
|
||||
@ -36,7 +36,7 @@ class MapUnitCombatant(val unit: MapUnit) : ICombatant {
|
||||
}
|
||||
|
||||
override fun getUnitType(): UnitType {
|
||||
return unit.type!!
|
||||
return unit.type
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
|
@ -12,12 +12,28 @@ class CivInfoTransientUpdater(val civInfo: CivilizationInfo) {
|
||||
|
||||
val newViewableInvisibleTiles = HashSet<TileInfo>()
|
||||
newViewableInvisibleTiles.addAll(civInfo.getCivUnits()
|
||||
.filter { it.hasUnique("Can attack submarines") }
|
||||
.flatMap { it.viewableTiles.asSequence() })
|
||||
// "Can attack submarines" unique deprecated since 3.16.9
|
||||
.filter { attacker -> attacker.hasUnique("Can see invisible [] units") || attacker.hasUnique("Can attack submarines") }
|
||||
.flatMap { attacker ->
|
||||
attacker.viewableTiles
|
||||
.asSequence()
|
||||
.filter { tile ->
|
||||
( tile.militaryUnit != null
|
||||
&& attacker.getMatchingUniques("Can see invisible [] units")
|
||||
.any { unique -> tile.militaryUnit!!.matchesFilter(unique.params[0]) }
|
||||
) || (
|
||||
tile.militaryUnit != null
|
||||
// "Can attack submarines" unique deprecated since 3.16.9
|
||||
&& attacker.hasUnique("Can attack submarines")
|
||||
&& tile.militaryUnit!!.matchesFilter("Submarine")
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
civInfo.viewableInvisibleUnitsTiles = newViewableInvisibleTiles
|
||||
|
||||
|
||||
// updating the viewable tiles also affects the explored tiles, obvs
|
||||
// updating the viewable tiles also affects the explored tiles, obviously.
|
||||
// So why don't we play switcharoo with the explored tiles as well?
|
||||
// Well, because it gets REALLY LARGE so it's a lot of memory space,
|
||||
// and we never actually iterate on the explored tiles (only check contains()),
|
||||
|
@ -354,9 +354,13 @@ class MapUnit {
|
||||
return currentTile.isWater
|
||||
}
|
||||
|
||||
fun isInvisible(): Boolean {
|
||||
fun isInvisible(to: CivilizationInfo): Boolean {
|
||||
if (hasUnique("Invisible to others"))
|
||||
return true
|
||||
if (hasUnique("Invisible to non-adjacent units"))
|
||||
return getTile().getTilesInDistance(1).none {
|
||||
it.getOwner() == to || it.getUnits().any { unit -> unit.owner == to.civName }
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
|
@ -637,7 +637,7 @@ open class TileInfo {
|
||||
val unitsInTile = getUnits()
|
||||
if (unitsInTile.none()) return false
|
||||
if (unitsInTile.first().civInfo != viewingCiv &&
|
||||
unitsInTile.firstOrNull { it.isInvisible() } != null) {
|
||||
unitsInTile.firstOrNull { it.isInvisible(viewingCiv) } != null) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
@ -74,20 +74,20 @@ class BattleTable(val worldScreen: WorldScreen): Table() {
|
||||
val attackerCiv = worldScreen.viewingCiv
|
||||
val defender: ICombatant? = Battle.getMapCombatantOfTile(selectedTile)
|
||||
|
||||
if(defender==null ||
|
||||
!includeFriendly && defender.getCivInfo()==attackerCiv )
|
||||
if (defender == null || (!includeFriendly && defender.getCivInfo() == attackerCiv))
|
||||
return null // no enemy combatant in tile
|
||||
|
||||
val canSeeDefender = if(UncivGame.Current.viewEntireMapForDebug) true
|
||||
else {
|
||||
when {
|
||||
defender.isInvisible() -> attackerCiv.viewableInvisibleUnitsTiles.contains(selectedTile)
|
||||
defender.isCity() -> attackerCiv.exploredTiles.contains(selectedTile.position)
|
||||
else -> attackerCiv.viewableTiles.contains(selectedTile)
|
||||
val canSeeDefender =
|
||||
if (UncivGame.Current.viewEntireMapForDebug) true
|
||||
else {
|
||||
when {
|
||||
defender.isInvisible(attackerCiv) -> attackerCiv.viewableInvisibleUnitsTiles.contains(selectedTile)
|
||||
defender.isCity() -> attackerCiv.exploredTiles.contains(selectedTile.position)
|
||||
else -> attackerCiv.viewableTiles.contains(selectedTile)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!canSeeDefender) return null
|
||||
if (!canSeeDefender) return null
|
||||
|
||||
return defender
|
||||
}
|
||||
@ -97,14 +97,14 @@ class BattleTable(val worldScreen: WorldScreen): Table() {
|
||||
|
||||
val attackerNameWrapper = Table()
|
||||
val attackerLabel = attacker.getName().toLabel()
|
||||
if(attacker is MapUnitCombatant)
|
||||
if (attacker is MapUnitCombatant)
|
||||
attackerNameWrapper.add(UnitGroup(attacker.unit,25f)).padRight(5f)
|
||||
attackerNameWrapper.add(attackerLabel)
|
||||
add(attackerNameWrapper)
|
||||
|
||||
val defenderNameWrapper = Table()
|
||||
val defenderLabel = Label(defender.getName().tr(), skin)
|
||||
if(defender is MapUnitCombatant)
|
||||
if (defender is MapUnitCombatant)
|
||||
defenderNameWrapper.add(UnitGroup(defender.unit,25f)).padRight(5f)
|
||||
defenderNameWrapper.add(defenderLabel)
|
||||
add(defenderNameWrapper).row()
|
||||
|
Reference in New Issue
Block a user