Defeated civilizations don't use spies (#11785)

* Fixed a crash when rigging a city-state election the turn before meeting them

* Civilizations move their spies back to the hideout when defeated

* Players can't move spies when defeated

* Removed some weird indents
This commit is contained in:
Oskar Niesen
2024-06-19 09:23:42 -05:00
committed by GitHub
parent f52245865c
commit dff8133a7a
4 changed files with 34 additions and 23 deletions

View File

@ -909,6 +909,8 @@ class Civilization : IsPartOfGameInfoSerialization {
for (tradeRequest in diplomacyManager.otherCiv().tradeRequests.filter { it.requestingCiv == civName }) for (tradeRequest in diplomacyManager.otherCiv().tradeRequests.filter { it.requestingCiv == civName })
diplomacyManager.otherCiv().tradeRequests.remove(tradeRequest) // it would be really weird to get a trade request from a dead civ diplomacyManager.otherCiv().tradeRequests.remove(tradeRequest) // it would be really weird to get a trade request from a dead civ
} }
if (gameInfo.isEspionageEnabled())
espionageManager.removeAllSpies()
} }
fun updateProximity(otherCiv: Civilization, preCalculated: Proximity? = null): Proximity = cache.updateProximity(otherCiv, preCalculated) fun updateProximity(otherCiv: Civilization, preCalculated: Proximity? = null): Proximity = cache.updateProximity(otherCiv, preCalculated)

View File

@ -77,7 +77,7 @@ class CityStateFunctions(val civInfo: Civilization) {
fun getVotesFromSpy(spy: Spy?): Float { fun getVotesFromSpy(spy: Spy?): Float {
if (spy == null) return 20f if (spy == null) return 20f
var votes = (civInfo.getDiplomacyManager(spy.civInfo)!!.influence / 2) var votes = (civInfo.getDiplomacyManagerOrMeet(spy.civInfo).influence / 2)
votes += (spy.getSkillModifierPercent() * spy.getEfficiencyModifier()).toFloat() // ranges from 30 to 90 votes += (spy.getSkillModifierPercent() * spy.getEfficiencyModifier()).toFloat() // ranges from 30 to 90
return votes return votes
} }

View File

@ -45,7 +45,8 @@ class EspionageManager : IsPartOfGameInfoSerialization {
fun getSpyName(): String { fun getSpyName(): String {
val usedSpyNames = spyList.map { it.name }.toHashSet() val usedSpyNames = spyList.map { it.name }.toHashSet()
val validSpyNames = civInfo.nation.spyNames.filter { it !in usedSpyNames } val validSpyNames = civInfo.nation.spyNames.filter { it !in usedSpyNames }
return validSpyNames.randomOrNull() ?: "Spy ${spyList.size+1}" // +1 as non-programmers count from 1 return validSpyNames.randomOrNull()
?: "Spy ${spyList.size + 1}" // +1 as non-programmers count from 1
} }
fun addSpy(): Spy { fun addSpy(): Spy {
@ -100,4 +101,12 @@ class EspionageManager : IsPartOfGameInfoSerialization {
fun getIdleSpies(): List<Spy> { fun getIdleSpies(): List<Spy> {
return spyList.filterTo(mutableListOf()) { it.isIdle() } return spyList.filterTo(mutableListOf()) { it.isIdle() }
} }
/**
* Takes all spies away from their cities.
* Called when the civ is destroyed.
*/
fun removeAllSpies() {
spyList.forEach { it.moveTo(null) }
}
} }

View File

@ -85,9 +85,9 @@ class EspionageOverviewScreen(val civInfo: Civilization, val worldScreen: WorldS
spySelectionTable.add(spy.name.toLabel()) spySelectionTable.add(spy.name.toLabel())
spySelectionTable.add(spy.rank.toLabel()) spySelectionTable.add(spy.rank.toLabel())
spySelectionTable.add(spy.getLocationName().toLabel()) spySelectionTable.add(spy.getLocationName().toLabel())
val actionString = if (spy.action.showTurns) val actionString = if (spy.action.showTurns)
"[${spy.action.displayString}] ${spy.turnsRemainingForAction}${Fonts.turn}" "[${spy.action.displayString}] ${spy.turnsRemainingForAction}${Fonts.turn}"
else spy.action.displayString else spy.action.displayString
spySelectionTable.add(actionString.toLabel()) spySelectionTable.add(actionString.toLabel())
val moveSpyButton = "Move".toTextButton() val moveSpyButton = "Move".toTextButton()
@ -97,7 +97,7 @@ class EspionageOverviewScreen(val civInfo: Civilization, val worldScreen: WorldS
moveSpyButton.onRightClick { moveSpyButton.onRightClick {
onSpyRightClicked(spy) onSpyRightClicked(spy)
} }
if (!worldScreen.canChangeState || !spy.isAlive()) { if (!worldScreen.canChangeState || !spy.isAlive() || civInfo.isDefeated()) {
// Spectators aren't allowed to move the spies of the Civs they are viewing // Spectators aren't allowed to move the spies of the Civs they are viewing
moveSpyButton.disable() moveSpyButton.disable()
} }
@ -124,18 +124,18 @@ class EspionageOverviewScreen(val civInfo: Civilization, val worldScreen: WorldS
// Then add all cities // Then add all cities
val sortedCities = civInfo.gameInfo.getCities() val sortedCities = civInfo.gameInfo.getCities()
.filter { civInfo.hasExplored(it.getCenterTile()) } .filter { civInfo.hasExplored(it.getCenterTile()) }
.sortedWith( .sortedWith(
compareBy<City> { compareBy<City> {
it.civ != civInfo it.civ != civInfo
}.thenBy { }.thenBy {
it.civ.isCityState() it.civ.isCityState()
}.thenBy(collator) { }.thenBy(collator) {
it.civ.civName.tr(hideIcons = true) it.civ.civName.tr(hideIcons = true)
}.thenBy(collator) { }.thenBy(collator) {
it.name.tr(hideIcons = true) it.name.tr(hideIcons = true)
} }
) )
for (city in sortedCities) { for (city in sortedCities) {
addCityToSelectionTable(city) addCityToSelectionTable(city)
} }
@ -143,7 +143,7 @@ class EspionageOverviewScreen(val civInfo: Civilization, val worldScreen: WorldS
private fun addCityToSelectionTable(city: City) { private fun addCityToSelectionTable(city: City) {
citySelectionTable.add(ImageGetter.getNationPortrait(city.civ.nation, 30f)) citySelectionTable.add(ImageGetter.getNationPortrait(city.civ.nation, 30f))
.padLeft(20f) .padLeft(20f)
val label = city.name.toLabel(hideIcons = true) val label = city.name.toLabel(hideIcons = true)
label.onClick { label.onClick {
worldScreen.game.popScreen() // If a detour to this screen (i.e. not directly from worldScreen) is made possible, use resetToWorldScreen instead worldScreen.game.popScreen() // If a detour to this screen (i.e. not directly from worldScreen) is made possible, use resetToWorldScreen instead
@ -193,7 +193,7 @@ class EspionageOverviewScreen(val civInfo: Civilization, val worldScreen: WorldS
add(starTable).center().padLeft(-4f) add(starTable).center().padLeft(-4f)
// Spectators aren't allowed to move the spies of the Civs they are viewing // Spectators aren't allowed to move the spies of the Civs they are viewing
if (worldScreen.canChangeState && spy.isAlive()) { if (worldScreen.canChangeState && spy.isAlive() && !civInfo.isDefeated()) {
onClick { onClick {
onSpyClicked(moveSpyButtons[spy]!!, spy) onSpyClicked(moveSpyButtons[spy]!!, spy)
} }
@ -252,7 +252,7 @@ class EspionageOverviewScreen(val civInfo: Civilization, val worldScreen: WorldS
button.setDirection(Align.right) button.setDirection(Align.right)
} else { } else {
button.isVisible = city == null // hideout button.isVisible = city == null // hideout
|| !city.espionage.hasSpyOf(civInfo) || !city.espionage.hasSpyOf(civInfo)
button.setDirection(Align.left) button.setDirection(Align.left)
} }
} }
@ -285,9 +285,9 @@ class EspionageOverviewScreen(val civInfo: Civilization, val worldScreen: WorldS
val spy = selectedSpy!! val spy = selectedSpy!!
if (!isCurrentAction) { if (!isCurrentAction) {
ConfirmPopup(this@EspionageOverviewScreen, ConfirmPopup(this@EspionageOverviewScreen,
"Do you want to stage a coup in [${city.civ.civName}] with a " + "Do you want to stage a coup in [${city.civ.civName}] with a " +
"[${(selectedSpy!!.getCoupChanceOfSuccess(false) * 100f).toInt()}]% " + "[${(selectedSpy!!.getCoupChanceOfSuccess(false) * 100f).toInt()}]% " +
"chance of success?", "Stage Coup") { "chance of success?", "Stage Coup") {
spy.setAction(SpyAction.Coup, 1) spy.setAction(SpyAction.Coup, 1)
fist.color = Color.DARK_GRAY fist.color = Color.DARK_GRAY
update() update()