mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-25 12:54:06 -04:00
Further Espionage Implementation (#11077)
* Added getSpiesInCity method in EspionageManager * Expanded stealing technology code * Spies can now die and revive * Added basic rigging elections * Spies rigging elections can now be caught * Added spy rank * Players can now move spies to city-states * Spies at a higher rank steal tech quicker * EspionageAutomation now sends spies to city-states and to do counter intelligence * Fixed some EspionageAutomation logic * Fixed EspionageAutomation error * Spy.location is now stored as a vector2 * Accounted for the only able to be one spy of a civ in each city * Spies level up when successfully stealing tech. * Increased tech steal rate by spy rank * Increased influence gained by rigging elections * Added a spy level cap * Spies no longer get stuck on counter-intelligence action * Spy automation no longer tries to rig elections in city states that it is at war with * canMoveTo now checks if the city tile is visible * Added espionage translations * Changed automateSpySteal/Rig/Counter intelligence return types * Simplifies automateSpies in EspionageAutomation * Added blank lines before titles * Improved spy being found and killed message phrasing
This commit is contained in:
parent
ed7fd447c2
commit
ccea2c88d3
@ -1729,14 +1729,28 @@ Move =
|
||||
|
||||
After an unknown civilization entered the [eraName], we have recruited [spyName] as a spy! =
|
||||
We have recruited [spyName] as a spy! =
|
||||
A spy from [civilization] stole the Technology [techName] from [cityName]! =
|
||||
An unidentified spy stole the Technology [techName] from [cityName]! =
|
||||
Your spy [name] stole the Technology [techName] from [cityName]! =
|
||||
Your spy [name] cannot steal any more techs from [civilization] as we've already researched all the technology they know! =
|
||||
Your spy [spyName] has leveled up! =
|
||||
Your spy [spyName] cannot steal any more techs from [civName] as we've already researched all the technology they know! =
|
||||
|
||||
# Stealing Technology defending civ
|
||||
An unidentified spy stole the Technology [techName] from [cityName]! =
|
||||
A spy from [civName] stole the Technology [techName] from [cityName]! =
|
||||
A spy from [civName] was found and killed trying to steal Technology in [cityName]! =
|
||||
A spy from [civName] was found and killed by [spyName] trying to steal Technology in [cityName]! =
|
||||
|
||||
# Stealing Technology offending civ
|
||||
Your spy [spyName] stole the Technology [techName] from [cityName]! =
|
||||
Your spy [spyName] was killed trying to steal Technology in [cityName]! =
|
||||
|
||||
# Rigging elections
|
||||
A spy from [civName] tried to rig elections and was found and killed in [cityName] by [spyName]! =
|
||||
Your spy [spyName] was killed trying to rig the election in [cityName]! =
|
||||
Your spy successfully rigged the election in [cityName]! =
|
||||
|
||||
# Spy fleeing city
|
||||
After the city of [cityName] was destroyed, your spy [spyName] has fled back to our hideout. =
|
||||
After the city of [cityName] was conquered, your spy [spyName] has fled back to our hideout. =
|
||||
Due to the chaos ensuing in [cityName], your spy [spyname] has fled back to our hideout. =
|
||||
Due to the chaos ensuing in [cityName], your spy [spyName] has fled back to our hideout. =
|
||||
|
||||
# Promotions
|
||||
|
||||
|
@ -76,7 +76,7 @@ object NextTurnAutomation {
|
||||
}
|
||||
if (civInfo.gameInfo.isEspionageEnabled()) {
|
||||
// Do after cities are conquered
|
||||
EspionageAutomation.automateSpies(civInfo)
|
||||
EspionageAutomation(civInfo).automateSpies()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,33 +1,80 @@
|
||||
package com.unciv.logic.automation.unit
|
||||
|
||||
import com.unciv.logic.city.City
|
||||
import com.unciv.logic.civilization.Civilization
|
||||
import com.unciv.models.Spy
|
||||
import com.unciv.models.SpyAction
|
||||
import kotlin.random.Random
|
||||
|
||||
object EspionageAutomation {
|
||||
class EspionageAutomation(val civInfo: Civilization) {
|
||||
private val civsToStealFrom: List<Civilization> by lazy {
|
||||
civInfo.getKnownCivs().filter {otherCiv -> otherCiv.isMajorCiv() && otherCiv.cities.any { it.getCenterTile().isVisible(civInfo) }
|
||||
&& civInfo.espionageManager.getTechsToSteal(otherCiv).isNotEmpty() }.toList()
|
||||
}
|
||||
|
||||
fun automateSpies(civInfo: Civilization) {
|
||||
val civsToStealFrom: List<Civilization> by lazy {
|
||||
civInfo.getKnownCivs().filter {otherCiv -> otherCiv.isMajorCiv() && otherCiv.cities.any { it.getCenterTile().isVisible(civInfo) }
|
||||
&& civInfo.espionageManager.getTechsToSteal(otherCiv).isNotEmpty() }.toList()
|
||||
}
|
||||
private val getCivsToStealFromSorted: List<Civilization> =
|
||||
civsToStealFrom.sortedBy { otherCiv -> civInfo.espionageManager.spyList
|
||||
.count { it.isDoingWork() && it.getLocation()?.civ == otherCiv }
|
||||
}.toList()
|
||||
|
||||
val getCivsToStealFromSorted: List<Civilization> =
|
||||
civsToStealFrom.sortedBy { otherCiv -> civInfo.espionageManager.spyList
|
||||
.count { it.isDoingWork() && it.getLocation()?.civ == otherCiv }
|
||||
}.toList()
|
||||
private val cityStatesToRig: List<Civilization> by lazy {
|
||||
civInfo.getKnownCivs().filter { otherCiv -> otherCiv.isMinorCiv() && otherCiv.knows(civInfo) && !civInfo.isAtWarWith(otherCiv) }.toList()
|
||||
}
|
||||
|
||||
for (spy in civInfo.espionageManager.spyList) {
|
||||
if (spy.isDoingWork()) continue
|
||||
if (civsToStealFrom.isNotEmpty()) {
|
||||
// We want to move the spy to the city with the highest science generation
|
||||
// Players can't usually figure this out so lets do highest population instead
|
||||
spy.moveTo(getCivsToStealFromSorted.first().cities.filter { it.getCenterTile().isVisible(civInfo) }.maxByOrNull { it.population.population })
|
||||
fun automateSpies() {
|
||||
val spies = civInfo.espionageManager.spyList
|
||||
val spiesToMove = spies.filter { it.isAlive() && !it.isDoingWork() }
|
||||
for (spy in spiesToMove) {
|
||||
val randomSeed = spies.size + spies.indexOf(spy) + civInfo.gameInfo.turns
|
||||
val randomAction = Random(randomSeed).nextInt(10)
|
||||
|
||||
// Try each operation based on the random value and the success rate
|
||||
// If an operation was not successfull try the next one
|
||||
if (randomAction <= 7 && automateSpyStealTech(spy)) {
|
||||
continue
|
||||
} else if (randomAction <= 9 && automateSpyRigElection(spy)) {
|
||||
continue
|
||||
} else if (automateSpyCounterInteligence(spy)) {
|
||||
continue
|
||||
} else if (spy.isDoingWork()) {
|
||||
continue // We might have been doing counter intelligence and wanted to look for something better
|
||||
} else {
|
||||
// Retry all of the operations one more time
|
||||
if (automateSpyStealTech(spy)) continue
|
||||
if (automateSpyRigElection(spy)) continue
|
||||
if(automateSpyCounterInteligence(spy)) continue
|
||||
}
|
||||
if (spy.action == SpyAction.None) {
|
||||
spy.moveTo(civInfo.getKnownCivs().filter { otherCiv -> otherCiv.isMajorCiv() && otherCiv.cities.any { it.getCenterTile().isVisible(civInfo) }}
|
||||
.toList().randomOrNull()?.cities?.filter { it.getCenterTile().isVisible(civInfo) }?.randomOrNull())
|
||||
}
|
||||
// There is nothing for our spy to do, put it in a random city
|
||||
val randomCity = civInfo.gameInfo.getCities().filter { spy.canMoveTo(it) }.toList().randomOrNull()
|
||||
spy.moveTo(randomCity)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the spy to a city that we can steal a tech from
|
||||
*/
|
||||
fun automateSpyStealTech(spy: Spy): Boolean {
|
||||
if (civsToStealFrom.isEmpty()) return false
|
||||
// We want to move the spy to the city with the highest science generation
|
||||
// Players can't usually figure this out so lets do highest population instead
|
||||
spy.moveTo(getCivsToStealFromSorted.first().cities.filter { spy.canMoveTo(it) }.maxByOrNull { it.population.population })
|
||||
return spy.action == SpyAction.StealingTech
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the spy to a random city-state
|
||||
*/
|
||||
private fun automateSpyRigElection(spy: Spy): Boolean {
|
||||
val potentialCities = cityStatesToRig.flatMap { it.cities }.filter { !it.isBeingRazed && spy.canMoveTo(it) }
|
||||
spy.moveTo(potentialCities.randomOrNull())
|
||||
return spy.action == SpyAction.RiggingElections
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the spy to a random city of ours
|
||||
*/
|
||||
private fun automateSpyCounterInteligence(spy: Spy): Boolean {
|
||||
spy.moveTo(civInfo.cities.filter { spy.canMoveTo(it) }.randomOrNull())
|
||||
return spy.action == SpyAction.CounterIntelligence
|
||||
}
|
||||
}
|
||||
|
@ -26,13 +26,11 @@ class CityEspionageManager : IsPartOfGameInfoSerialization {
|
||||
}
|
||||
|
||||
fun hasSpyOf(civInfo: Civilization): Boolean {
|
||||
return civInfo.espionageManager.spyList.any { it.location == city.id }
|
||||
return civInfo.espionageManager.spyList.any { it.getLocation() == city }
|
||||
}
|
||||
|
||||
private fun getAllStationedSpies(): List<Spy> {
|
||||
return city.civ.gameInfo.civilizations.flatMap { civ ->
|
||||
civ.espionageManager.spyList.filter { it.location == city.id }
|
||||
}
|
||||
return city.civ.gameInfo.civilizations.flatMap { it.espionageManager.getSpiesInCity(city) }
|
||||
}
|
||||
|
||||
fun removeAllPresentSpies(reason: SpyFleeReason) {
|
||||
@ -44,7 +42,7 @@ class CityEspionageManager : IsPartOfGameInfoSerialization {
|
||||
else -> "Due to the chaos ensuing in [${city.name}], your spy [${spy.name}] has fled back to our hideout."
|
||||
}
|
||||
owningCiv.addNotification(notificationString, city.location, NotificationCategory.Espionage, NotificationIcon.Spy)
|
||||
spy.location = null
|
||||
spy.moveTo(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.unciv.logic.civilization.managers
|
||||
|
||||
import com.unciv.logic.IsPartOfGameInfoSerialization
|
||||
import com.unciv.logic.city.City
|
||||
import com.unciv.logic.civilization.Civilization
|
||||
import com.unciv.logic.map.tile.Tile
|
||||
import com.unciv.models.Spy
|
||||
@ -33,7 +34,7 @@ class EspionageManager : IsPartOfGameInfoSerialization {
|
||||
spy.endTurn()
|
||||
}
|
||||
|
||||
private fun getSpyName(): String {
|
||||
fun getSpyName(): String {
|
||||
val usedSpyNames = spyList.map { it.name }.toHashSet()
|
||||
val validSpyNames = civInfo.nation.spyNames.filter { it !in usedSpyNames }
|
||||
if (validSpyNames.isEmpty()) { return "Spy ${spyList.size+1}" } // +1 as non-programmers count from 1
|
||||
@ -64,4 +65,10 @@ class EspionageManager : IsPartOfGameInfoSerialization {
|
||||
}
|
||||
return techsToSteal
|
||||
}
|
||||
|
||||
fun getSpiesInCity(city: City): MutableList<Spy> {
|
||||
return spyList.filter { it.getLocation() == city }.toMutableList()
|
||||
}
|
||||
|
||||
fun getSpyAssignedToCity(city: City): Spy? = spyList.firstOrNull {it.getLocation() == city}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.unciv.models
|
||||
|
||||
import com.badlogic.gdx.math.Vector2
|
||||
import com.unciv.Constants
|
||||
import com.unciv.logic.IsPartOfGameInfoSerialization
|
||||
import com.unciv.logic.city.City
|
||||
@ -17,16 +18,18 @@ enum class SpyAction(val displayString: String) {
|
||||
Surveillance("Observing City"),
|
||||
StealingTech("Stealing Tech"),
|
||||
RiggingElections("Rigging Elections"),
|
||||
CounterIntelligence("Conducting Counter-intelligence")
|
||||
CounterIntelligence("Conducting Counter-intelligence"),
|
||||
Dead("Dead")
|
||||
}
|
||||
|
||||
|
||||
class Spy() : IsPartOfGameInfoSerialization {
|
||||
// `location == null` means that the spy is in its hideout
|
||||
var location: String? = null
|
||||
private var location: Vector2? = null
|
||||
lateinit var name: String
|
||||
var action = SpyAction.None
|
||||
private set
|
||||
var rank: Int = 1
|
||||
var turnsRemainingForAction = 0
|
||||
private set
|
||||
private var progressTowardsStealingTech = 0
|
||||
@ -72,8 +75,10 @@ class Spy() : IsPartOfGameInfoSerialization {
|
||||
val location = getLocation()!! // This should never throw an exception, as going to the hideout sets your action to None.
|
||||
if (location.civ.isCityState()) {
|
||||
action = SpyAction.RiggingElections
|
||||
turnsRemainingForAction = 10
|
||||
} else if (location.civ == civInfo) {
|
||||
action = SpyAction.CounterIntelligence
|
||||
turnsRemainingForAction = 10
|
||||
} else {
|
||||
startStealingTech()
|
||||
}
|
||||
@ -95,12 +100,36 @@ class Spy() : IsPartOfGameInfoSerialization {
|
||||
return
|
||||
}
|
||||
val techStealCost = stealableTechs.maxOfOrNull { civInfo.gameInfo.ruleset.technologies[it]!!.cost }!!
|
||||
val progressThisTurn = getLocation()!!.cityStats.currentCityStats.science
|
||||
// 33% spy bonus for each level
|
||||
val progressThisTurn = getLocation()!!.cityStats.currentCityStats.science * (rank + 2f) / 3f
|
||||
progressTowardsStealingTech += progressThisTurn.toInt()
|
||||
if (progressTowardsStealingTech > techStealCost) {
|
||||
stealTech()
|
||||
}
|
||||
}
|
||||
SpyAction.RiggingElections -> {
|
||||
--turnsRemainingForAction
|
||||
if (turnsRemainingForAction > 0) return
|
||||
|
||||
rigElection()
|
||||
}
|
||||
SpyAction.Dead -> {
|
||||
--turnsRemainingForAction
|
||||
if (turnsRemainingForAction > 0) return
|
||||
|
||||
val oldSpyName = name
|
||||
name = espionageManager.getSpyName()
|
||||
action = SpyAction.None
|
||||
civInfo.addNotification("We have recruited a new spy name [$name] after [$oldSpyName] was killed.",
|
||||
NotificationCategory.Espionage, NotificationIcon.Spy)
|
||||
}
|
||||
SpyAction.CounterIntelligence -> {
|
||||
// Counter inteligence spies don't do anything here
|
||||
// However the AI will want to keep track of how long a spy has been doing counter intelligence for
|
||||
// Once turnRemainingForAction is <= 0 the spy won't be considered to be doing work any more
|
||||
--turnsRemainingForAction
|
||||
return
|
||||
}
|
||||
else -> return // Not implemented yet, so don't do anything
|
||||
}
|
||||
}
|
||||
@ -121,47 +150,138 @@ class Spy() : IsPartOfGameInfoSerialization {
|
||||
if (stolenTech != null) {
|
||||
civInfo.tech.addTechnology(stolenTech)
|
||||
}
|
||||
// Lower is better
|
||||
var spyResult = Random(randomSeed.toInt()).nextInt(300)
|
||||
// Add our spies experience
|
||||
spyResult -= getSkillModifier()
|
||||
// Subtract the experience of the counter inteligence spies
|
||||
val defendingSpy = city.civ.espionageManager.getSpyAssignedToCity(city)
|
||||
spyResult += defendingSpy?.getSkillModifier() ?: 0
|
||||
//TODO: Add policies modifier here
|
||||
|
||||
val spyDetected = Random(randomSeed.toInt()).nextInt(3)
|
||||
val detectionString = when (spyDetected) {
|
||||
0 -> "A spy from [${civInfo.civName}] stole the Technology [$stolenTech] from [$city]!"
|
||||
1 -> "An unidentified spy stole the Technology [$stolenTech] from [$city]!"
|
||||
else -> null // Not detected
|
||||
val detectionString = when {
|
||||
spyResult < 0 -> null // Not detected
|
||||
spyResult < 100 -> "An unidentified spy stole the Technology [$stolenTech] from [$city]!"
|
||||
spyResult < 200 -> "A spy from [${civInfo.civName}] stole the Technology [$stolenTech] from [$city]!"
|
||||
else -> { // The spy was killed in the attempt
|
||||
if (defendingSpy == null) "A spy from [${civInfo.civName}] was found and killed trying to steal Technology in [$city]!"
|
||||
else "A spy from [${civInfo.civName}] was found and killed by [${defendingSpy.name}] trying to steal Technology in [$city]!"
|
||||
}
|
||||
}
|
||||
if (detectionString != null)
|
||||
otherCiv.addNotification(detectionString, city.location, NotificationCategory.Espionage, NotificationIcon.Spy)
|
||||
|
||||
civInfo.addNotification("Your spy [$name] stole the Technology [$stolenTech] from [$city]!", city.location,
|
||||
NotificationCategory.Espionage,
|
||||
NotificationIcon.Spy
|
||||
)
|
||||
if (spyResult < 200) {
|
||||
civInfo.addNotification("Your spy [$name] stole the Technology [$stolenTech] from [$city]!", city.location,
|
||||
NotificationCategory.Espionage, NotificationIcon.Spy)
|
||||
startStealingTech()
|
||||
levelUpSpy()
|
||||
} else {
|
||||
civInfo.addNotification("Your spy [$name] was killed trying to steal Technology in [$city]!", city.location,
|
||||
NotificationCategory.Espionage, NotificationIcon.Spy)
|
||||
defendingSpy?.levelUpSpy()
|
||||
killSpy()
|
||||
}
|
||||
|
||||
|
||||
startStealingTech()
|
||||
}
|
||||
|
||||
private fun rigElection() {
|
||||
val city = getLocation()!!
|
||||
val cityStateCiv = city.civ
|
||||
// TODO: Simple implementation, please implement this in the future. This is a guess.
|
||||
turnsRemainingForAction = 10
|
||||
|
||||
if (cityStateCiv.getAllyCiv() != null && cityStateCiv.getAllyCiv() != civInfo.civName) {
|
||||
val allyCiv = civInfo.gameInfo.getCivilization(cityStateCiv.getAllyCiv()!!)
|
||||
val defendingSpy = allyCiv.espionageManager.getSpyAssignedToCity(getLocation()!!)
|
||||
if (defendingSpy != null) {
|
||||
val randomSeed = city.location.x * city.location.y + 123f * civInfo.gameInfo.turns
|
||||
var spyResult = Random(randomSeed.toInt()).nextInt(120)
|
||||
spyResult -= getSkillModifier()
|
||||
spyResult += defendingSpy.getSkillModifier()
|
||||
if (spyResult > 100) {
|
||||
// The Spy was killed
|
||||
allyCiv.addNotification("A spy from [${civInfo.civName}] tried to rig elections and was found and killed in [${city}] by [${defendingSpy.name}]!",
|
||||
getLocation()!!.location, NotificationCategory.Espionage, NotificationIcon.Spy)
|
||||
civInfo.addNotification("Your spy [$name] was killed trying to rig the election in [$city]!", city.location,
|
||||
NotificationCategory.Espionage, NotificationIcon.Spy)
|
||||
killSpy()
|
||||
defendingSpy.levelUpSpy()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
// Starts at 10 influence and increases by 3 for each extra rank.
|
||||
cityStateCiv.getDiplomacyManager(civInfo).addInfluence(7f + getSpyRank() * 3)
|
||||
civInfo.addNotification("Your spy successfully rigged the election in [$city]!", city.location,
|
||||
NotificationCategory.Espionage, NotificationIcon.Spy)
|
||||
}
|
||||
|
||||
fun moveTo(city: City?) {
|
||||
location = city?.id
|
||||
if (city == null) { // Moving to spy hideout
|
||||
location = null
|
||||
action = SpyAction.None
|
||||
turnsRemainingForAction = 0
|
||||
return
|
||||
}
|
||||
location = city.location
|
||||
action = SpyAction.Moving
|
||||
turnsRemainingForAction = 1
|
||||
}
|
||||
|
||||
fun canMoveTo(city: City): Boolean {
|
||||
if (getLocation() == city) return true
|
||||
if (!city.getCenterTile().isVisible(civInfo)) return false
|
||||
return espionageManager.getSpyAssignedToCity(city) == null
|
||||
}
|
||||
|
||||
fun isSetUp() = action !in listOf(SpyAction.Moving, SpyAction.None, SpyAction.EstablishNetwork)
|
||||
|
||||
// Only returns true if the spy is doing a helpful and implemented action
|
||||
fun isDoingWork() = action == SpyAction.StealingTech || action == SpyAction.EstablishNetwork
|
||||
fun isDoingWork(): Boolean {
|
||||
if (action == SpyAction.StealingTech || action == SpyAction.EstablishNetwork || action == SpyAction.Moving) return true
|
||||
if (action == SpyAction.RiggingElections && !civInfo.isAtWarWith(getLocation()!!.civ)) return true
|
||||
if (action == SpyAction.CounterIntelligence && turnsRemainingForAction > 0) return true
|
||||
else return false
|
||||
}
|
||||
|
||||
fun getLocation(): City? {
|
||||
return civInfo.gameInfo.getCities().firstOrNull { it.id == location }
|
||||
if (location == null) return null
|
||||
return civInfo.gameInfo.tileMap[location!!].getCity()
|
||||
}
|
||||
|
||||
fun getLocationName(): String {
|
||||
return getLocation()?.name ?: Constants.spyHideout
|
||||
}
|
||||
|
||||
fun getSpyRank(): Int {
|
||||
return rank
|
||||
}
|
||||
|
||||
fun levelUpSpy() {
|
||||
//TODO: Make the spy level cap dependent on some unique
|
||||
if (rank >= 3) return
|
||||
if (getLocation() != null) {
|
||||
civInfo.addNotification("Your spy [$name] has leveled up!", getLocation()!!.location,
|
||||
NotificationCategory.Espionage, NotificationIcon.Spy)
|
||||
} else {
|
||||
civInfo.addNotification("Your spy [$name] has leveled up!",
|
||||
NotificationCategory.Espionage, NotificationIcon.Spy)
|
||||
}
|
||||
rank++
|
||||
}
|
||||
|
||||
fun getSkillModifier(): Int {
|
||||
return getSpyRank() * 30
|
||||
}
|
||||
|
||||
fun killSpy() {
|
||||
// We don't actually remove this spy object, we set them as dead and let them revive
|
||||
moveTo(null)
|
||||
action = SpyAction.Dead
|
||||
turnsRemainingForAction = 5
|
||||
rank = 1
|
||||
}
|
||||
|
||||
fun isAlive(): Boolean = action != SpyAction.Dead
|
||||
}
|
||||
|
@ -77,10 +77,8 @@ class EspionageOverviewScreen(val civInfo: Civilization, val worldScreen: WorldS
|
||||
spySelectionTable.add(spy.getLocationName().toLabel())
|
||||
val actionString =
|
||||
when (spy.action) {
|
||||
SpyAction.None, SpyAction.StealingTech, SpyAction.Surveillance -> spy.action.displayString
|
||||
SpyAction.Moving, SpyAction.EstablishNetwork -> "[${spy.action.displayString}] ${spy.turnsRemainingForAction}${Fonts.turn}"
|
||||
SpyAction.RiggingElections -> TODO()
|
||||
SpyAction.CounterIntelligence -> TODO()
|
||||
SpyAction.None, SpyAction.StealingTech, SpyAction.Surveillance, SpyAction.CounterIntelligence -> spy.action.displayString
|
||||
SpyAction.Moving, SpyAction.EstablishNetwork, SpyAction.Dead, SpyAction.RiggingElections -> "[${spy.action.displayString}] ${spy.turnsRemainingForAction}${Fonts.turn}"
|
||||
}
|
||||
spySelectionTable.add(actionString.toLabel())
|
||||
|
||||
@ -95,14 +93,10 @@ class EspionageOverviewScreen(val civInfo: Civilization, val worldScreen: WorldS
|
||||
selectedSpy = spy
|
||||
selectedSpyButton!!.label.setText(Constants.cancel.tr())
|
||||
for ((button, city) in moveSpyHereButtons) {
|
||||
// For now, only allow spies to be sent to cities of other major civs and their hideout
|
||||
// Not own cities as counterintelligence isn't implemented
|
||||
// Not city-state civs as rigging elections isn't implemented
|
||||
button.isVisible = city == null // hideout
|
||||
|| (city.civ.isMajorCiv()
|
||||
&& city.civ != civInfo
|
||||
&& !city.espionage.hasSpyOf(civInfo)
|
||||
)
|
||||
|| (city.civ != civInfo && !city.espionage.hasSpyOf(civInfo))
|
||||
}
|
||||
}
|
||||
if (!worldScreen.canChangeState) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user