Little Diplomatic Victory makeover (#9756)

* Linting and give two votes to UN owner

* Allow human player to abstain, show UN 2 votes

* More info on voting results

* AI won't vote for hated enemies

* Improve PopupAlert handling

* Translation templates

* One missing template
This commit is contained in:
SomeTroglodyte
2023-07-10 14:25:59 +02:00
committed by GitHub
parent 8f761642f6
commit a737747284
12 changed files with 201 additions and 77 deletions

View File

@ -1426,11 +1426,20 @@ Worst = Schlechtester
Turns until the next\ndiplomacy victory vote: [amount] = Runden bis zur nächsten Abstimmung\nüber den Diplomatiesieg: [amount] Turns until the next\ndiplomacy victory vote: [amount] = Runden bis zur nächsten Abstimmung\nüber den Diplomatiesieg: [amount]
Choose a civ to vote for = Wähle eine Zivilisation, für die du abstimmen möchtest Choose a civ to vote for = Wähle eine Zivilisation, für die du abstimmen möchtest
Choose who should become the world leader and win a Diplomatic Victory! = Wähle, wer der Anführer der Welt werden und somit den Diplomatiesieg erhalten soll Choose who should become the world leader and win a Diplomatic Victory! = Wähle, wer der Anführer der Welt werden und somit den Diplomatiesieg erhalten soll
Voted for = Abgestimmt für Voted for = hat gestimmt für
Vote for [civilizationName] = Abstimmen für [civilizationName] Vote for [civilizationName] = Abstimmen für [civilizationName]
Abstain = Enthalten
Continue = Fortfahren Continue = Fortfahren
Abstained = Enthalten Abstained = Enthalten
Vote for World Leader = Stimme für den Anführer der Welt ab Vote for World Leader = Stimme für den Anführer der Welt ab
[number] votes = [number] Stimmen
[number] vote = [number] Stimme
No valid votes were cast. = Es wurden keine gültigen Stimmen abgegeben.
Minimum votes for electing a world leader: [number] = Ein Anführer der Welt benötigt mindestens [number] Stimmen, um gewählt zu werden
Tied in first position: [civNames] = Gleichstand auf dem ersten Platz: [civNames]
No world leader was elected. = Es wurde kein Anführer der Welt gewählt.
You have been elected world leader! = Du wurdest zum Anführer der Welt gewählt!
[leaderName] of [civ] has been elected world leader! = [leaderName] von [civ] wurde zum Anführer der Welt gewählt!
Replay = Wiederholung Replay = Wiederholung
# Capturing a city # Capturing a city
@ -6477,4 +6486,3 @@ However, it will reflect the mods you are playing! The combination of base rules
If you opened the Civilopedia from the main menu, the "Ruleset" will be that of the last game you started. = Wenn du die Zivilopädie vom Hauptmenü öffnest, wird das "Regelwerk" des letzten gestarteten Spiels ausschlaggebend sein. If you opened the Civilopedia from the main menu, the "Ruleset" will be that of the last game you started. = Wenn du die Zivilopädie vom Hauptmenü öffnest, wird das "Regelwerk" des letzten gestarteten Spiels ausschlaggebend sein.
Letters can select categories, and when there are multiple categories matching the same letter, you can press that repeatedly to cycle between these. = Buchstaben können Kategorien auswählen. Wenn mehrere Kategorien mit dem gleichen Buchstaben anfangen, kannst du den Buchstaben wiederholt drücken, um durch diese durchzuwechseln. (Aktuell werden die Buchstaben aus der englischen Version verwendet.) Letters can select categories, and when there are multiple categories matching the same letter, you can press that repeatedly to cycle between these. = Buchstaben können Kategorien auswählen. Wenn mehrere Kategorien mit dem gleichen Buchstaben anfangen, kannst du den Buchstaben wiederholt drücken, um durch diese durchzuwechseln. (Aktuell werden die Buchstaben aus der englischen Version verwendet.)
The arrow keys allow navigation as well - left/right for categories, up/down for entries. = Die Pfeiltasten können auch zur Navigation verwendet werden. - Links/rechts für Kategorien, hoch/runter für Einträge. The arrow keys allow navigation as well - left/right for categories, up/down for entries. = Die Pfeiltasten können auch zur Navigation verwendet werden. - Links/rechts für Kategorien, hoch/runter für Einträge.

View File

@ -1426,11 +1426,20 @@ Worst =
Turns until the next\ndiplomacy victory vote: [amount] = Turns until the next\ndiplomacy victory vote: [amount] =
Choose a civ to vote for = Choose a civ to vote for =
Choose who should become the world leader and win a Diplomatic Victory! = Choose who should become the world leader and win a Diplomatic Victory! =
Voted for =
Vote for [civilizationName] = Vote for [civilizationName] =
Vote for World Leader =
Abstain =
Continue = Continue =
Abstained = Abstained =
Vote for World Leader = Voted for =
[number] votes =
[number] vote =
No valid votes were cast. =
Minimum votes for electing a world leader: [number] =
Tied in first position: [civNames] =
No world leader was elected. =
You have been elected world leader! =
[leaderName] of [civ] has been elected world leader! =
Replay = Replay =
# Capturing a city # Capturing a city

View File

@ -1,6 +1,7 @@
package com.unciv.logic package com.unciv.logic
import com.unciv.Constants import com.unciv.Constants
import com.unciv.GUI
import com.unciv.UncivGame import com.unciv.UncivGame
import com.unciv.UncivGame.Version import com.unciv.UncivGame.Version
import com.unciv.json.json import com.unciv.json.json
@ -35,6 +36,7 @@ import com.unciv.models.ruleset.RulesetCache
import com.unciv.models.ruleset.Speed import com.unciv.models.ruleset.Speed
import com.unciv.models.ruleset.nation.Difficulty import com.unciv.models.ruleset.nation.Difficulty
import com.unciv.models.ruleset.unique.UniqueType import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.models.translations.tr
import com.unciv.ui.audio.MusicMood import com.unciv.ui.audio.MusicMood
import com.unciv.ui.audio.MusicTrackChooserFlags import com.unciv.ui.audio.MusicTrackChooserFlags
import com.unciv.ui.screens.pickerscreens.Github.repoNameToFolderName import com.unciv.ui.screens.pickerscreens.Github.repoNameToFolderName
@ -109,8 +111,8 @@ class GameInfo : IsPartOfGameInfoSerialization, HasGameInfoSerializationVersion
var victoryData:VictoryData? = null var victoryData:VictoryData? = null
// Maps a civ to the civ they voted for /** Maps a civ to the civ they voted for - `null` on the value side means they abstained */
var diplomaticVictoryVotesCast = HashMap<String, String>() var diplomaticVictoryVotesCast = HashMap<String, String?>()
// Set to false whenever the results still need te be processed // Set to false whenever the results still need te be processed
var diplomaticVictoryVotesProcessed = false var diplomaticVictoryVotesProcessed = false
@ -228,6 +230,35 @@ class GameInfo : IsPartOfGameInfoSerialization, HasGameInfoSerializationVersion
fun getAliveCityStates() = civilizations.filter { it.isAlive() && it.isCityState() } fun getAliveCityStates() = civilizations.filter { it.isAlive() && it.isCityState() }
fun getAliveMajorCivs() = civilizations.filter { it.isAlive() && it.isMajorCiv() } fun getAliveMajorCivs() = civilizations.filter { it.isAlive() && it.isMajorCiv() }
/** Gets civilizations in their commonly used order - City-states last,
* otherwise alphabetically by culture and translation. [civToSortFirst] can be used to force
* a specific Civilization to be listed first.
*
* Barbarians and Spectators always excluded, other filter criteria are [includeCityStates],
* [includeDefeated] and optionally an [additionalFilter].
*/
fun getCivsSorted(
includeCityStates: Boolean = true,
includeDefeated: Boolean = false,
civToSortFirst: Civilization? = null,
additionalFilter: ((Civilization) -> Boolean)? = null
): Sequence<Civilization> {
val collator = GUI.getSettings().getCollatorFromLocale()
return civilizations.asSequence()
.filterNot {
it.isBarbarian() ||
it.isSpectator() ||
!includeDefeated && it.isDefeated() ||
!includeCityStates && it.isCityState() ||
additionalFilter?.invoke(it) == false
}
.sortedWith(
compareBy<Civilization> { it != civToSortFirst }
.thenByDescending { it.isMajorCiv() }
.thenBy(collator) { it.civName.tr(hideIcons = true) }
)
}
/** Returns the first spectator for a [playerId] or creates one if none found */ /** Returns the first spectator for a [playerId] or creates one if none found */
fun getSpectator(playerId: String): Civilization { fun getSpectator(playerId: String): Civilization {
val gameSpectatorCiv = civilizations.firstOrNull { val gameSpectatorCiv = civilizations.firstOrNull {

View File

@ -13,6 +13,8 @@ class BarbarianAutomation(val civInfo: Civilization) {
civInfo.units.getCivUnits().filter { it.baseUnit.isRanged() }.forEach { automateUnit(it) } civInfo.units.getCivUnits().filter { it.baseUnit.isRanged() }.forEach { automateUnit(it) }
civInfo.units.getCivUnits().filter { it.baseUnit.isMelee() }.forEach { automateUnit(it) } civInfo.units.getCivUnits().filter { it.baseUnit.isMelee() }.forEach { automateUnit(it) }
civInfo.units.getCivUnits().filter { !it.baseUnit.isRanged() && !it.baseUnit.isMelee() }.forEach { automateUnit(it) } civInfo.units.getCivUnits().filter { !it.baseUnit.isRanged() && !it.baseUnit.isMelee() }.forEach { automateUnit(it) }
// fix buildup of alerts - to shrink saves and ease debugging
civInfo.popupAlerts.clear()
} }
private fun automateUnit(unit: MapUnit) { private fun automateUnit(unit: MapUnit) {

View File

@ -48,6 +48,7 @@ import com.unciv.ui.screens.victoryscreen.RankingType
import java.util.SortedMap import java.util.SortedMap
import java.util.TreeMap import java.util.TreeMap
import kotlin.math.min import kotlin.math.min
import kotlin.random.Random
object NextTurnAutomation { object NextTurnAutomation {
@ -1077,24 +1078,29 @@ object NextTurnAutomation {
// Technically, this function should also check for civs that have liberated one or more cities // Technically, this function should also check for civs that have liberated one or more cities
// However, that can be added in another update, this PR is large enough as it is. // However, that can be added in another update, this PR is large enough as it is.
private fun tryVoteForDiplomaticVictory(civInfo: Civilization) { private fun tryVoteForDiplomaticVictory(civ: Civilization) {
if (!civInfo.mayVoteForDiplomaticVictory()) return if (!civ.mayVoteForDiplomaticVictory()) return
val chosenCiv: String? = if (civInfo.isMajorCiv()) {
val knownMajorCivs = civInfo.getKnownCivs().filter { it.isMajorCiv() } val chosenCiv: String? = if (civ.isMajorCiv()) {
val knownMajorCivs = civ.getKnownCivs().filter { it.isMajorCiv() }
val highestOpinion = knownMajorCivs val highestOpinion = knownMajorCivs
.maxOfOrNull { .maxOfOrNull {
civInfo.getDiplomacyManager(it).opinionOfOtherCiv() civ.getDiplomacyManager(it).opinionOfOtherCiv()
} }
if (highestOpinion == null) null if (highestOpinion == null) null // Abstain if we know nobody
else knownMajorCivs.filter { civInfo.getDiplomacyManager(it).opinionOfOtherCiv() == highestOpinion}.toList().random().civName else if (highestOpinion < -80 || highestOpinion < -40 && highestOpinion + Random.Default.nextInt(40) < -40)
null // Abstain if we hate everybody (proportional chance in the RelationshipLevel.Enemy range - lesser evil)
else knownMajorCivs
.filter { civ.getDiplomacyManager(it).opinionOfOtherCiv() == highestOpinion }
.toList().random().civName
} else { } else {
civInfo.getAllyCiv() civ.getAllyCiv()
} }
civInfo.diplomaticVoteForCiv(chosenCiv) civ.diplomaticVoteForCiv(chosenCiv)
} }
private fun issueRequests(civInfo: Civilization) { private fun issueRequests(civInfo: Civilization) {

View File

@ -703,7 +703,7 @@ class Civilization : IsPartOfGameInfoSerialization {
&& gameInfo.civilizations.any { it.isMajorCiv() && !it.isDefeated() && it != this } && gameInfo.civilizations.any { it.isMajorCiv() && !it.isDefeated() && it != this }
fun diplomaticVoteForCiv(chosenCivName: String?) { fun diplomaticVoteForCiv(chosenCivName: String?) {
if (chosenCivName != null) gameInfo.diplomaticVictoryVotesCast[civName] = chosenCivName gameInfo.diplomaticVictoryVotesCast[civName] = chosenCivName
} }
fun shouldShowDiplomaticVotingResults() = fun shouldShowDiplomaticVotingResults() =

View File

@ -17,19 +17,9 @@ class DiplomacyFunctions(val civInfo: Civilization){
/** A sorted Sequence of all other civs we know (excluding barbarians and spectators) */ /** A sorted Sequence of all other civs we know (excluding barbarians and spectators) */
fun getKnownCivsSorted(includeCityStates: Boolean = true, includeDefeated: Boolean = false) = fun getKnownCivsSorted(includeCityStates: Boolean = true, includeDefeated: Boolean = false) =
civInfo.gameInfo.civilizations.asSequence() civInfo.gameInfo.getCivsSorted(includeCityStates, includeDefeated) {
.filterNot { it != civInfo && civInfo.knows(it)
it == civInfo ||
it.isBarbarian() ||
it.isSpectator() ||
!civInfo.knows(it) ||
!includeDefeated && it.isDefeated() ||
!includeCityStates && it.isCityState()
} }
.sortedWith(
compareByDescending<Civilization> { it.isMajorCiv() }
.thenBy (UncivGame.Current.settings.getCollatorFromLocale()) { it.civName.tr(hideIcons = true) }
)
fun makeCivilizationsMeet(otherCiv: Civilization, warOnContact: Boolean = false) { fun makeCivilizationsMeet(otherCiv: Civilization, warOnContact: Boolean = false) {

View File

@ -307,8 +307,13 @@ class TurnManager(val civInfo: Civilization) {
civInfo.gameInfo.victoryData = civInfo.gameInfo.victoryData =
VictoryData(civInfo.civName, victoryType, civInfo.gameInfo.turns) VictoryData(civInfo.civName, victoryType, civInfo.gameInfo.turns)
for (civInfo in civInfo.gameInfo.civilizations) // Notify other human players about this civInfo's victory
civInfo.popupAlerts.add(PopupAlert(AlertType.GameHasBeenWon, civInfo.civName)) for (otherCiv in civInfo.gameInfo.civilizations) {
// Skip winner, displaying VictoryScreen is handled separately in WorldScreen.update
// by checking `viewingCiv.isDefeated() || gameInfo.checkForVictory()`
if (otherCiv.playerType != PlayerType.Human || otherCiv == civInfo) continue
otherCiv.popupAlerts.add(PopupAlert(AlertType.GameHasBeenWon, ""))
}
} }
} }

View File

@ -6,7 +6,9 @@ import com.unciv.logic.civilization.Civilization
import com.unciv.models.Counter import com.unciv.models.Counter
import com.unciv.models.ruleset.Milestone import com.unciv.models.ruleset.Milestone
import com.unciv.models.ruleset.Victory import com.unciv.models.ruleset.Victory
import com.unciv.models.ruleset.unique.StateForConditionals
import com.unciv.models.ruleset.unique.UniqueType import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.models.translations.tr
class VictoryManager : IsPartOfGameInfoSerialization { class VictoryManager : IsPartOfGameInfoSerialization {
@Transient @Transient
@ -24,14 +26,29 @@ class VictoryManager : IsPartOfGameInfoSerialization {
return toReturn return toReturn
} }
private fun calculateDiplomaticVotingResults(votesCast: HashMap<String, String>): Counter<String> { private fun calculateDiplomaticVotingResults(votesCast: HashMap<String, String?>): Counter<String> {
val results = Counter<String>() val results = Counter<String>()
for (castVote in votesCast) { // UN Owner gets 2 votes in G&K
results.add(castVote.value, 1) val (_, civOwningUN) = getUNBuildingAndOwnerNames()
for ((voter, votedFor) in votesCast) {
if (votedFor == null) continue // null means Abstained
results.add(votedFor, if (voter == civOwningUN) 2 else 1)
} }
return results return results
} }
/** Finds the Building and Owner of the United Nations (or whatever the Mod called it)
* - if it's built at all and only if the owner is alive
* @return `first`: Building name, `second`: Owner civ name; both null if not found
*/
fun getUNBuildingAndOwnerNames(): Pair<String?, String?> = civInfo.gameInfo.civilizations.asSequence()
.filterNot { it.isBarbarian() || it.isSpectator() || it.isDefeated() }
.flatMap { civ -> civ.cities.asSequence()
.flatMap { it.cityConstructions.getBuiltBuildings() }
.filter { it.hasUnique(UniqueType.OneTimeTriggerVoting, stateForConditionals = StateForConditionals.IgnoreConditionals) }
.map { it.name to civ.civName }
}.firstOrNull() ?: (null to null)
private fun votesNeededForDiplomaticVictory(): Int { private fun votesNeededForDiplomaticVictory(): Int {
val civCount = civInfo.gameInfo.civilizations.count { !it.isDefeated() } val civCount = civInfo.gameInfo.civilizations.count { !it.isDefeated() }
@ -56,6 +73,29 @@ class VictoryManager : IsPartOfGameInfoSerialization {
return (results.none { it != bestCiv && it.value == bestCiv.value }) return (results.none { it != bestCiv && it.value == bestCiv.value })
} }
fun getDiplomaticVictoryVoteBreakdown(): String {
val results = calculateDiplomaticVotingResults(civInfo.gameInfo.diplomaticVictoryVotesCast)
val (voteCount, winnerList) = results.asSequence()
.groupBy({ it.value }, { it.key }).asSequence()
.sortedByDescending { it.key } // key is vote count here
.firstOrNull()
?: return "No valid votes were cast."
val lines = arrayListOf<String>()
val minVotes = votesNeededForDiplomaticVictory()
if (voteCount < minVotes)
lines += "Minimum votes for electing a world leader: [$minVotes]"
if (winnerList.size > 1)
lines += "Tied in first position: [${winnerList.joinToString { it.tr() }}]" // Yes with icons
val winnerCiv = civInfo.gameInfo.getCivilization(winnerList.first())
lines += when {
lines.isNotEmpty() -> "No world leader was elected."
winnerCiv == civInfo -> "You have been elected world leader!"
else -> "${civInfo.nation.getLeaderDisplayName()} has been elected world leader!"
}
return lines.joinToString("\n") { "{$it}" }
}
fun getVictoryTypeAchieved(): String? { fun getVictoryTypeAchieved(): String? {
if (!civInfo.isMajorCiv()) return null if (!civInfo.isMajorCiv()) return null
val enabledVictories = civInfo.gameInfo.gameParameters.victoryTypes val enabledVictories = civInfo.gameInfo.gameParameters.victoryTypes

View File

@ -1,11 +1,13 @@
package com.unciv.ui.screens.pickerscreens package com.unciv.ui.screens.pickerscreens
import com.badlogic.gdx.scenes.scene2d.Actor
import com.unciv.UncivGame import com.unciv.UncivGame
import com.unciv.logic.civilization.Civilization import com.unciv.logic.civilization.Civilization
import com.unciv.models.UncivSound import com.unciv.models.UncivSound
import com.unciv.models.translations.tr import com.unciv.models.translations.tr
import com.unciv.ui.images.ImageGetter
import com.unciv.ui.components.input.onClick import com.unciv.ui.components.input.onClick
import com.unciv.ui.components.input.onDoubleClick
import com.unciv.ui.images.ImageGetter
class DiplomaticVotePickerScreen(private val votingCiv: Civilization) : PickerScreen() { class DiplomaticVotePickerScreen(private val votingCiv: Civilization) : PickerScreen() {
private var chosenCiv: String? = null private var chosenCiv: String? = null
@ -16,27 +18,39 @@ class DiplomaticVotePickerScreen(private val votingCiv: Civilization) : PickerSc
descriptionLabel.setText("Choose who should become the world leader and win a Diplomatic Victory!".tr()) descriptionLabel.setText("Choose who should become the world leader and win a Diplomatic Victory!".tr())
val choosableCivs = votingCiv.gameInfo.civilizations.filter { it.isMajorCiv() && it != votingCiv && !it.isDefeated() } val choosableCivs = votingCiv.diplomacyFunctions.getKnownCivsSorted(false)
for (civ in choosableCivs) for (civ in choosableCivs) {
{ addButton(civ.civName, "Vote for [${civ.civName}]", civ.civName,
val button = PickerPane.getPickerOptionButton(
ImageGetter.getNationPortrait( ImageGetter.getNationPortrait(
civ.nation, civ.nation,
PickerPane.pickerOptionIconSize PickerPane.pickerOptionIconSize
), civ.civName
) )
button.pack() )
button.onClick {
chosenCiv = civ.civName
pick("Vote for [${civ.civName}]".tr())
} }
topTable.add(button).pad(10f).row() addButton("Abstain", "Abstain", null,
ImageGetter.getImage("OtherIcons/Stop").apply {
setSize(PickerPane.pickerOptionIconSize, PickerPane.pickerOptionIconSize)
}
)
rightSideButton.onClick(UncivSound.Chimes, ::voteAndClose)
} }
rightSideButton.onClick(UncivSound.Chimes) { private fun voteAndClose() {
votingCiv.diplomaticVoteForCiv(chosenCiv!!) votingCiv.diplomaticVoteForCiv(chosenCiv)
UncivGame.Current.popScreen() UncivGame.Current.popScreen()
} }
private fun addButton(caption: String, pickText: String, choice: String?, icon: Actor) {
val button = PickerPane.getPickerOptionButton(icon, caption)
button.onClick {
chosenCiv = choice
pick(pickText.tr())
}
button.onDoubleClick(UncivSound.Chimes) {
chosenCiv = choice
voteAndClose()
}
topTable.add(button).fillX().pad(10f).row()
} }
} }

View File

@ -1,55 +1,74 @@
package com.unciv.ui.screens.pickerscreens package com.unciv.ui.screens.pickerscreens
import com.unciv.UncivGame import com.badlogic.gdx.utils.Align
import com.unciv.logic.civilization.CivFlags import com.unciv.logic.civilization.CivFlags
import com.unciv.logic.civilization.Civilization import com.unciv.logic.civilization.Civilization
import com.unciv.models.UncivSound import com.unciv.models.UncivSound
import com.unciv.models.translations.tr import com.unciv.models.translations.tr
import com.unciv.ui.images.ImageGetter
import com.unciv.ui.components.extensions.enable import com.unciv.ui.components.extensions.enable
import com.unciv.ui.components.input.onClick
import com.unciv.ui.components.extensions.toLabel import com.unciv.ui.components.extensions.toLabel
import com.unciv.ui.components.input.KeyCharAndCode
import com.unciv.ui.components.input.keyShortcuts
import com.unciv.ui.components.input.onActivation
import com.unciv.ui.images.ImageGetter
class DiplomaticVoteResultScreen(val votesCast: HashMap<String, String>, val viewingCiv: Civilization) : PickerScreen() { class DiplomaticVoteResultScreen(
private val votesCast: HashMap<String, String?>,
viewingCiv: Civilization
) : PickerScreen() {
val gameInfo = viewingCiv.gameInfo val gameInfo = viewingCiv.gameInfo
private val constructionNameUN: String?
private val civOwningUN: String?
init { init {
closeButton.remove() closeButton.remove()
addVote(viewingCiv.civName) val findUN = viewingCiv.victoryManager.getUNBuildingAndOwnerNames()
constructionNameUN = findUN.first
civOwningUN = findUN.second
for (civ in gameInfo.civilizations.filter { it.isMajorCiv() && it != viewingCiv }) val orderedCivs = gameInfo.getCivsSorted(civToSortFirst = viewingCiv)
addVote(civ.civName) for (civ in orderedCivs) addVote(civ)
for (civ in gameInfo.civilizations.filter { it.isCityState() })
addVote(civ.civName)
rightSideButton.onClick(UncivSound.Click) { val result = viewingCiv.victoryManager.getDiplomaticVictoryVoteBreakdown()
descriptionLabel.setAlignment(Align.center)
descriptionLabel.setText(result.tr())
rightSideButton.onActivation(UncivSound.Click) {
viewingCiv.addFlag(CivFlags.ShowDiplomaticVotingResults.name, -1) viewingCiv.addFlag(CivFlags.ShowDiplomaticVotingResults.name, -1)
UncivGame.Current.popScreen() game.popScreen()
} }
rightSideButton.keyShortcuts.add(KeyCharAndCode.BACK)
rightSideButton.keyShortcuts.add(KeyCharAndCode.SPACE)
rightSideButton.enable() rightSideButton.enable()
rightSideButton.setText("Continue".tr()) rightSideButton.setText("Continue".tr())
bottomTable.cells[0].minWidth(rightSideButton.prefWidth + 20f) // center descriptionLabel
} }
private fun addVote(civName: String) { private fun addVote(civ: Civilization) {
val civ = gameInfo.civilizations.firstOrNull { it.civName == civName } val civName = civ.civName
if (civ == null || civ.isDefeated()) return
topTable.add(ImageGetter.getNationPortrait(civ.nation, 30f)).pad(10f) topTable.add(ImageGetter.getNationPortrait(civ.nation, 30f)).pad(10f)
topTable.add(civName.toLabel()).pad(20f) topTable.add(civName.toLabel(hideIcons = true)).pad(20f)
if (civName !in votesCast.keys) {
topTable.add("Abstained".toLabel()).row() if (civName == civOwningUN && constructionNameUN != null) {
return topTable.add(ImageGetter.getConstructionPortrait(constructionNameUN, 30f))
.pad(10f)
topTable.add("[2] votes".toLabel())
} else {
topTable.add("[1] vote".toLabel()).colspan(2)
} }
val votedCiv = gameInfo.civilizations.firstOrNull { it.civName == votesCast[civName] }!! fun abstained() = topTable.add("Abstained".toLabel()).colspan(3).row()
if (votedCiv.isDefeated()) { val votedCivName = votesCast[civName]
topTable.add("Abstained".toLabel()).row() ?: return abstained()
return
}
topTable.add("Voted for".toLabel()).pad(20f) val votedCiv = gameInfo.getCivilization(votedCivName)
if (votedCiv.isDefeated()) return abstained()
topTable.add("Voted for".toLabel()).pad(20f).padRight(0f)
topTable.add(ImageGetter.getNationPortrait(votedCiv.nation, 30f)).pad(10f) topTable.add(ImageGetter.getNationPortrait(votedCiv.nation, 30f)).pad(10f)
topTable.add(votedCiv.civName.toLabel()).row() topTable.add(votedCiv.civName.toLabel(hideIcons = true))
topTable.row()
} }
} }

View File

@ -14,12 +14,12 @@ import com.unciv.models.ruleset.Victory
import com.unciv.models.translations.tr import com.unciv.models.translations.tr
import com.unciv.ui.audio.MusicMood import com.unciv.ui.audio.MusicMood
import com.unciv.ui.audio.MusicTrackChooserFlags import com.unciv.ui.audio.MusicTrackChooserFlags
import com.unciv.ui.components.input.KeyCharAndCode
import com.unciv.ui.components.TabbedPager import com.unciv.ui.components.TabbedPager
import com.unciv.ui.components.extensions.areSecretKeysPressed import com.unciv.ui.components.extensions.areSecretKeysPressed
import com.unciv.ui.components.extensions.enable import com.unciv.ui.components.extensions.enable
import com.unciv.ui.components.input.onClick
import com.unciv.ui.components.extensions.toLabel import com.unciv.ui.components.extensions.toLabel
import com.unciv.ui.components.input.KeyCharAndCode
import com.unciv.ui.components.input.onClick
import com.unciv.ui.images.ImageGetter import com.unciv.ui.images.ImageGetter
import com.unciv.ui.screens.basescreen.BaseScreen import com.unciv.ui.screens.basescreen.BaseScreen
import com.unciv.ui.screens.basescreen.RecreateOnResize import com.unciv.ui.screens.basescreen.RecreateOnResize