From a737747284f3d13ea42453ebaa9be51e70370c08 Mon Sep 17 00:00:00 2001 From: SomeTroglodyte <63000004+SomeTroglodyte@users.noreply.github.com> Date: Mon, 10 Jul 2023 14:25:59 +0200 Subject: [PATCH] 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 --- .../jsons/translations/German.properties | 12 +++- .../jsons/translations/template.properties | 13 +++- core/src/com/unciv/logic/GameInfo.kt | 35 +++++++++- .../civilization/BarbarianAutomation.kt | 2 + .../civilization/NextTurnAutomation.kt | 24 ++++--- .../unciv/logic/civilization/Civilization.kt | 2 +- .../diplomacy/DiplomacyFunctions.kt | 16 +---- .../civilization/managers/TurnManager.kt | 9 ++- .../civilization/managers/VictoryManager.kt | 46 ++++++++++++- .../DiplomaticVotePickerScreen.kt | 46 ++++++++----- .../DiplomaticVoteResultScreen.kt | 69 ++++++++++++------- .../ui/screens/victoryscreen/VictoryScreen.kt | 4 +- 12 files changed, 201 insertions(+), 77 deletions(-) diff --git a/android/assets/jsons/translations/German.properties b/android/assets/jsons/translations/German.properties index 8de95c8ff7..53ec7537fa 100644 --- a/android/assets/jsons/translations/German.properties +++ b/android/assets/jsons/translations/German.properties @@ -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] 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 -Voted for = Abgestimmt für +Voted for = hat gestimmt für Vote for [civilizationName] = Abstimmen für [civilizationName] +Abstain = Enthalten Continue = Fortfahren Abstained = Enthalten 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 # 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. 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. - diff --git a/android/assets/jsons/translations/template.properties b/android/assets/jsons/translations/template.properties index 614bc25af6..e1d02fc680 100644 --- a/android/assets/jsons/translations/template.properties +++ b/android/assets/jsons/translations/template.properties @@ -1426,11 +1426,20 @@ Worst = Turns until the next\ndiplomacy victory vote: [amount] = Choose a civ to vote for = Choose who should become the world leader and win a Diplomatic Victory! = -Voted for = Vote for [civilizationName] = +Vote for World Leader = +Abstain = Continue = 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 = # Capturing a city diff --git a/core/src/com/unciv/logic/GameInfo.kt b/core/src/com/unciv/logic/GameInfo.kt index 71035b8ece..0c739457ad 100644 --- a/core/src/com/unciv/logic/GameInfo.kt +++ b/core/src/com/unciv/logic/GameInfo.kt @@ -1,6 +1,7 @@ package com.unciv.logic import com.unciv.Constants +import com.unciv.GUI import com.unciv.UncivGame import com.unciv.UncivGame.Version 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.nation.Difficulty import com.unciv.models.ruleset.unique.UniqueType +import com.unciv.models.translations.tr import com.unciv.ui.audio.MusicMood import com.unciv.ui.audio.MusicTrackChooserFlags import com.unciv.ui.screens.pickerscreens.Github.repoNameToFolderName @@ -109,8 +111,8 @@ class GameInfo : IsPartOfGameInfoSerialization, HasGameInfoSerializationVersion var victoryData:VictoryData? = null - // Maps a civ to the civ they voted for - var diplomaticVictoryVotesCast = HashMap() + /** Maps a civ to the civ they voted for - `null` on the value side means they abstained */ + var diplomaticVictoryVotesCast = HashMap() // Set to false whenever the results still need te be processed var diplomaticVictoryVotesProcessed = false @@ -228,6 +230,35 @@ class GameInfo : IsPartOfGameInfoSerialization, HasGameInfoSerializationVersion fun getAliveCityStates() = civilizations.filter { it.isAlive() && it.isCityState() } 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 { + 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 { 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 */ fun getSpectator(playerId: String): Civilization { val gameSpectatorCiv = civilizations.firstOrNull { diff --git a/core/src/com/unciv/logic/automation/civilization/BarbarianAutomation.kt b/core/src/com/unciv/logic/automation/civilization/BarbarianAutomation.kt index 0ba836a333..af0b7aedd5 100644 --- a/core/src/com/unciv/logic/automation/civilization/BarbarianAutomation.kt +++ b/core/src/com/unciv/logic/automation/civilization/BarbarianAutomation.kt @@ -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.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) { diff --git a/core/src/com/unciv/logic/automation/civilization/NextTurnAutomation.kt b/core/src/com/unciv/logic/automation/civilization/NextTurnAutomation.kt index 0172ddaccd..d6e6e06385 100644 --- a/core/src/com/unciv/logic/automation/civilization/NextTurnAutomation.kt +++ b/core/src/com/unciv/logic/automation/civilization/NextTurnAutomation.kt @@ -48,6 +48,7 @@ import com.unciv.ui.screens.victoryscreen.RankingType import java.util.SortedMap import java.util.TreeMap import kotlin.math.min +import kotlin.random.Random object NextTurnAutomation { @@ -1077,24 +1078,29 @@ object NextTurnAutomation { // 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. - private fun tryVoteForDiplomaticVictory(civInfo: Civilization) { - if (!civInfo.mayVoteForDiplomaticVictory()) return - val chosenCiv: String? = if (civInfo.isMajorCiv()) { + private fun tryVoteForDiplomaticVictory(civ: Civilization) { + if (!civ.mayVoteForDiplomaticVictory()) return - val knownMajorCivs = civInfo.getKnownCivs().filter { it.isMajorCiv() } + val chosenCiv: String? = if (civ.isMajorCiv()) { + + val knownMajorCivs = civ.getKnownCivs().filter { it.isMajorCiv() } val highestOpinion = knownMajorCivs .maxOfOrNull { - civInfo.getDiplomacyManager(it).opinionOfOtherCiv() + civ.getDiplomacyManager(it).opinionOfOtherCiv() } - if (highestOpinion == null) null - else knownMajorCivs.filter { civInfo.getDiplomacyManager(it).opinionOfOtherCiv() == highestOpinion}.toList().random().civName + if (highestOpinion == null) null // Abstain if we know nobody + 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 { - civInfo.getAllyCiv() + civ.getAllyCiv() } - civInfo.diplomaticVoteForCiv(chosenCiv) + civ.diplomaticVoteForCiv(chosenCiv) } private fun issueRequests(civInfo: Civilization) { diff --git a/core/src/com/unciv/logic/civilization/Civilization.kt b/core/src/com/unciv/logic/civilization/Civilization.kt index 3e8d56a52b..877c64aacd 100644 --- a/core/src/com/unciv/logic/civilization/Civilization.kt +++ b/core/src/com/unciv/logic/civilization/Civilization.kt @@ -703,7 +703,7 @@ class Civilization : IsPartOfGameInfoSerialization { && gameInfo.civilizations.any { it.isMajorCiv() && !it.isDefeated() && it != this } fun diplomaticVoteForCiv(chosenCivName: String?) { - if (chosenCivName != null) gameInfo.diplomaticVictoryVotesCast[civName] = chosenCivName + gameInfo.diplomaticVictoryVotesCast[civName] = chosenCivName } fun shouldShowDiplomaticVotingResults() = diff --git a/core/src/com/unciv/logic/civilization/diplomacy/DiplomacyFunctions.kt b/core/src/com/unciv/logic/civilization/diplomacy/DiplomacyFunctions.kt index d8783c0e45..5afe404dd9 100644 --- a/core/src/com/unciv/logic/civilization/diplomacy/DiplomacyFunctions.kt +++ b/core/src/com/unciv/logic/civilization/diplomacy/DiplomacyFunctions.kt @@ -17,19 +17,9 @@ class DiplomacyFunctions(val civInfo: Civilization){ /** A sorted Sequence of all other civs we know (excluding barbarians and spectators) */ fun getKnownCivsSorted(includeCityStates: Boolean = true, includeDefeated: Boolean = false) = - civInfo.gameInfo.civilizations.asSequence() - .filterNot { - it == civInfo || - it.isBarbarian() || - it.isSpectator() || - !civInfo.knows(it) || - !includeDefeated && it.isDefeated() || - !includeCityStates && it.isCityState() - } - .sortedWith( - compareByDescending { it.isMajorCiv() } - .thenBy (UncivGame.Current.settings.getCollatorFromLocale()) { it.civName.tr(hideIcons = true) } - ) + civInfo.gameInfo.getCivsSorted(includeCityStates, includeDefeated) { + it != civInfo && civInfo.knows(it) + } fun makeCivilizationsMeet(otherCiv: Civilization, warOnContact: Boolean = false) { diff --git a/core/src/com/unciv/logic/civilization/managers/TurnManager.kt b/core/src/com/unciv/logic/civilization/managers/TurnManager.kt index 071b1352db..6dfc661868 100644 --- a/core/src/com/unciv/logic/civilization/managers/TurnManager.kt +++ b/core/src/com/unciv/logic/civilization/managers/TurnManager.kt @@ -307,8 +307,13 @@ class TurnManager(val civInfo: Civilization) { civInfo.gameInfo.victoryData = VictoryData(civInfo.civName, victoryType, civInfo.gameInfo.turns) - for (civInfo in civInfo.gameInfo.civilizations) - civInfo.popupAlerts.add(PopupAlert(AlertType.GameHasBeenWon, civInfo.civName)) + // Notify other human players about this civInfo's victory + 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, "")) + } } } diff --git a/core/src/com/unciv/logic/civilization/managers/VictoryManager.kt b/core/src/com/unciv/logic/civilization/managers/VictoryManager.kt index ae15d7dc8b..0107c78331 100644 --- a/core/src/com/unciv/logic/civilization/managers/VictoryManager.kt +++ b/core/src/com/unciv/logic/civilization/managers/VictoryManager.kt @@ -6,7 +6,9 @@ import com.unciv.logic.civilization.Civilization import com.unciv.models.Counter import com.unciv.models.ruleset.Milestone import com.unciv.models.ruleset.Victory +import com.unciv.models.ruleset.unique.StateForConditionals import com.unciv.models.ruleset.unique.UniqueType +import com.unciv.models.translations.tr class VictoryManager : IsPartOfGameInfoSerialization { @Transient @@ -24,14 +26,29 @@ class VictoryManager : IsPartOfGameInfoSerialization { return toReturn } - private fun calculateDiplomaticVotingResults(votesCast: HashMap): Counter { + private fun calculateDiplomaticVotingResults(votesCast: HashMap): Counter { val results = Counter() - for (castVote in votesCast) { - results.add(castVote.value, 1) + // UN Owner gets 2 votes in G&K + 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 } + /** 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 = 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 { val civCount = civInfo.gameInfo.civilizations.count { !it.isDefeated() } @@ -56,6 +73,29 @@ class VictoryManager : IsPartOfGameInfoSerialization { 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() + 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? { if (!civInfo.isMajorCiv()) return null val enabledVictories = civInfo.gameInfo.gameParameters.victoryTypes diff --git a/core/src/com/unciv/ui/screens/pickerscreens/DiplomaticVotePickerScreen.kt b/core/src/com/unciv/ui/screens/pickerscreens/DiplomaticVotePickerScreen.kt index 2662407ac3..cc6328cff3 100644 --- a/core/src/com/unciv/ui/screens/pickerscreens/DiplomaticVotePickerScreen.kt +++ b/core/src/com/unciv/ui/screens/pickerscreens/DiplomaticVotePickerScreen.kt @@ -1,11 +1,13 @@ package com.unciv.ui.screens.pickerscreens +import com.badlogic.gdx.scenes.scene2d.Actor import com.unciv.UncivGame import com.unciv.logic.civilization.Civilization import com.unciv.models.UncivSound 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.onDoubleClick +import com.unciv.ui.images.ImageGetter class DiplomaticVotePickerScreen(private val votingCiv: Civilization) : PickerScreen() { 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()) - val choosableCivs = votingCiv.gameInfo.civilizations.filter { it.isMajorCiv() && it != votingCiv && !it.isDefeated() } - for (civ in choosableCivs) - { - val button = PickerPane.getPickerOptionButton( + val choosableCivs = votingCiv.diplomacyFunctions.getKnownCivsSorted(false) + for (civ in choosableCivs) { + addButton(civ.civName, "Vote for [${civ.civName}]", civ.civName, ImageGetter.getNationPortrait( civ.nation, PickerPane.pickerOptionIconSize - ), civ.civName + ) ) - button.pack() - button.onClick { - chosenCiv = civ.civName - pick("Vote for [${civ.civName}]".tr()) + } + addButton("Abstain", "Abstain", null, + ImageGetter.getImage("OtherIcons/Stop").apply { + setSize(PickerPane.pickerOptionIconSize, PickerPane.pickerOptionIconSize) } - topTable.add(button).pad(10f).row() - } + ) - rightSideButton.onClick(UncivSound.Chimes) { - votingCiv.diplomaticVoteForCiv(chosenCiv!!) - UncivGame.Current.popScreen() - } + rightSideButton.onClick(UncivSound.Chimes, ::voteAndClose) + } + private fun voteAndClose() { + votingCiv.diplomaticVoteForCiv(chosenCiv) + 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() } } diff --git a/core/src/com/unciv/ui/screens/pickerscreens/DiplomaticVoteResultScreen.kt b/core/src/com/unciv/ui/screens/pickerscreens/DiplomaticVoteResultScreen.kt index 51c689f7db..685f66e19d 100644 --- a/core/src/com/unciv/ui/screens/pickerscreens/DiplomaticVoteResultScreen.kt +++ b/core/src/com/unciv/ui/screens/pickerscreens/DiplomaticVoteResultScreen.kt @@ -1,55 +1,74 @@ 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.Civilization import com.unciv.models.UncivSound import com.unciv.models.translations.tr -import com.unciv.ui.images.ImageGetter 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.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, val viewingCiv: Civilization) : PickerScreen() { +class DiplomaticVoteResultScreen( + private val votesCast: HashMap, + viewingCiv: Civilization +) : PickerScreen() { val gameInfo = viewingCiv.gameInfo + private val constructionNameUN: String? + private val civOwningUN: String? init { 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 }) - addVote(civ.civName) - for (civ in gameInfo.civilizations.filter { it.isCityState() }) - addVote(civ.civName) + val orderedCivs = gameInfo.getCivsSorted(civToSortFirst = viewingCiv) + for (civ in orderedCivs) addVote(civ) - 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) - UncivGame.Current.popScreen() + game.popScreen() } + rightSideButton.keyShortcuts.add(KeyCharAndCode.BACK) + rightSideButton.keyShortcuts.add(KeyCharAndCode.SPACE) rightSideButton.enable() rightSideButton.setText("Continue".tr()) + bottomTable.cells[0].minWidth(rightSideButton.prefWidth + 20f) // center descriptionLabel } - private fun addVote(civName: String) { - val civ = gameInfo.civilizations.firstOrNull { it.civName == civName } - if (civ == null || civ.isDefeated()) return + private fun addVote(civ: Civilization) { + val civName = civ.civName topTable.add(ImageGetter.getNationPortrait(civ.nation, 30f)).pad(10f) - topTable.add(civName.toLabel()).pad(20f) - if (civName !in votesCast.keys) { - topTable.add("Abstained".toLabel()).row() - return + topTable.add(civName.toLabel(hideIcons = true)).pad(20f) + + if (civName == civOwningUN && constructionNameUN != null) { + 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] }!! - if (votedCiv.isDefeated()) { - topTable.add("Abstained".toLabel()).row() - return - } + fun abstained() = topTable.add("Abstained".toLabel()).colspan(3).row() + val votedCivName = votesCast[civName] + ?: return abstained() - 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(votedCiv.civName.toLabel()).row() + topTable.add(votedCiv.civName.toLabel(hideIcons = true)) + topTable.row() } } diff --git a/core/src/com/unciv/ui/screens/victoryscreen/VictoryScreen.kt b/core/src/com/unciv/ui/screens/victoryscreen/VictoryScreen.kt index c34a086fe4..5b0f563605 100644 --- a/core/src/com/unciv/ui/screens/victoryscreen/VictoryScreen.kt +++ b/core/src/com/unciv/ui/screens/victoryscreen/VictoryScreen.kt @@ -14,12 +14,12 @@ import com.unciv.models.ruleset.Victory import com.unciv.models.translations.tr import com.unciv.ui.audio.MusicMood import com.unciv.ui.audio.MusicTrackChooserFlags -import com.unciv.ui.components.input.KeyCharAndCode import com.unciv.ui.components.TabbedPager import com.unciv.ui.components.extensions.areSecretKeysPressed 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.input.KeyCharAndCode +import com.unciv.ui.components.input.onClick import com.unciv.ui.images.ImageGetter import com.unciv.ui.screens.basescreen.BaseScreen import com.unciv.ui.screens.basescreen.RecreateOnResize