From 0500f73770d91b571dce5cb22f9bc6d9d810d20b Mon Sep 17 00:00:00 2001 From: SomeTroglodyte <63000004+SomeTroglodyte@users.noreply.github.com> Date: Thu, 13 Apr 2023 10:54:11 +0200 Subject: [PATCH] Victory screen and victory detection use VictoryData (#9175) * VictoryScreen uses VictoryData * Victory detection no longer circumvents VictoryData --- core/src/com/unciv/logic/GameInfo.kt | 11 ++++ .../civilization/managers/TurnManager.kt | 2 +- core/src/com/unciv/ui/audio/MusicMood.kt | 1 + .../ui/screens/victoryscreen/VictoryScreen.kt | 60 +++++++++---------- .../ui/screens/worldscreen/WorldScreen.kt | 2 +- docs/Modders/Images-and-Audio.md | 36 +++++------ 6 files changed, 61 insertions(+), 51 deletions(-) diff --git a/core/src/com/unciv/logic/GameInfo.kt b/core/src/com/unciv/logic/GameInfo.kt index ff618228fe..11ffe231fd 100644 --- a/core/src/com/unciv/logic/GameInfo.kt +++ b/core/src/com/unciv/logic/GameInfo.kt @@ -18,6 +18,7 @@ import com.unciv.logic.civilization.NotificationIcon import com.unciv.logic.civilization.PlayerType import com.unciv.logic.civilization.managers.TechManager import com.unciv.logic.civilization.managers.TurnManager +import com.unciv.logic.civilization.managers.VictoryManager import com.unciv.logic.map.CityDistanceData import com.unciv.logic.map.TileMap import com.unciv.logic.map.tile.Tile @@ -397,6 +398,16 @@ class GameInfo : IsPartOfGameInfoSerialization, HasGameInfoSerializationVersion diplomaticVictoryVotesProcessed = true } + /** @return `true` if someone has won - checks existing [victoryData] and each civ's [VictoryManager.getVictoryTypeAchieved] */ + fun checkForVictory(): Boolean { + if (victoryData != null) return true + for (civ in civilizations) { + TurnManager(civ).updateWinningCiv() + if (victoryData != null) return true + } + return false + } + private fun addEnemyUnitNotification(thisPlayer: Civilization, tiles: List, inOrNear: String) { // don't flood the player with similar messages. instead cycle through units by clicking the message multiple times. if (tiles.size < 3) { diff --git a/core/src/com/unciv/logic/civilization/managers/TurnManager.kt b/core/src/com/unciv/logic/civilization/managers/TurnManager.kt index 8c1b8d9656..f704a80652 100644 --- a/core/src/com/unciv/logic/civilization/managers/TurnManager.kt +++ b/core/src/com/unciv/logic/civilization/managers/TurnManager.kt @@ -291,7 +291,7 @@ class TurnManager(val civInfo: Civilization) { updateWinningCiv() // Maybe we did something this turn to win } - private fun updateWinningCiv(){ + fun updateWinningCiv(){ if (civInfo.gameInfo.victoryData != null) return // Game already won val victoryType = civInfo.victoryManager.getVictoryTypeAchieved() diff --git a/core/src/com/unciv/ui/audio/MusicMood.kt b/core/src/com/unciv/ui/audio/MusicMood.kt index f4433365ea..714e84a489 100644 --- a/core/src/com/unciv/ui/audio/MusicMood.kt +++ b/core/src/com/unciv/ui/audio/MusicMood.kt @@ -10,6 +10,7 @@ object MusicMood { const val Golden = "Golden" const val Wonder = "Wonder" const val Researched = "Researched" + const val Victory = "Victory" val themeOrPeace = listOf(Theme, Peace) fun peaceOrWar(isAtWar: Boolean) = if (isAtWar) War else Peace diff --git a/core/src/com/unciv/ui/screens/victoryscreen/VictoryScreen.kt b/core/src/com/unciv/ui/screens/victoryscreen/VictoryScreen.kt index 5cf7b9d969..37f8908cbe 100644 --- a/core/src/com/unciv/ui/screens/victoryscreen/VictoryScreen.kt +++ b/core/src/com/unciv/ui/screens/victoryscreen/VictoryScreen.kt @@ -7,10 +7,13 @@ import com.badlogic.gdx.scenes.scene2d.ui.VerticalGroup import com.badlogic.gdx.utils.Align import com.unciv.Constants import com.unciv.UncivGame +import com.unciv.logic.VictoryData import com.unciv.logic.civilization.Civilization import com.unciv.models.metadata.GameSetupInfo 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.KeyCharAndCode import com.unciv.ui.components.TabbedPager import com.unciv.ui.components.extensions.areSecretKeysPressed @@ -23,14 +26,13 @@ import com.unciv.ui.screens.basescreen.RecreateOnResize import com.unciv.ui.screens.newgamescreen.NewGameScreen import com.unciv.ui.screens.pickerscreens.PickerScreen import com.unciv.ui.screens.worldscreen.WorldScreen - -//TODO someoneHasWon should look at gameInfo.victoryData +import java.util.EnumSet class VictoryScreen( private val worldScreen: WorldScreen, pageNumber: Int = 0 ) : PickerScreen(), RecreateOnResize { - + private val music get() = UncivGame.Current.musicController private val gameInfo = worldScreen.gameInfo private val playerCiv = worldScreen.viewingCiv private val tabs = TabbedPager(separatorColor = Color.WHITE, shortcutScreen = this) @@ -96,27 +98,17 @@ class VictoryScreen( tabs.selectPage(pageNumber) //**************** Set up bottom area - buttons and description label **************** - rightSideButton.isVisible = false - - var someoneHasWon = false - - val playerVictoryType = playerCiv.victoryManager.getVictoryTypeAchieved() - if (playerVictoryType != null) { - someoneHasWon = true - wonOrLost("You have won a [$playerVictoryType] Victory!", playerVictoryType, true) - } - for (civ in gameInfo.civilizations.filter { it.isMajorCiv() && it != playerCiv }) { - val civVictoryType = civ.victoryManager.getVictoryTypeAchieved() - if (civVictoryType != null) { - someoneHasWon = true - wonOrLost("[${civ.civName}] has won a [$civVictoryType] Victory!", civVictoryType, false) + when { + gameInfo.victoryData != null -> + displayWinner(gameInfo.victoryData!!) + playerCiv.isDefeated() -> { + displayWonOrLost(Victory().defeatString) + music.chooseTrack(playerCiv.civName, MusicMood.Defeat, EnumSet.of(MusicTrackChooserFlags.SuffixMustMatch)) + } + else -> { + rightSideButton.isVisible = false + setDefaultCloseAction() } - } - - if (playerCiv.isDefeated()) { - wonOrLost("", null, false) - } else if (!someoneHasWon) { - setDefaultCloseAction() } //**************** Set up floating info panels **************** @@ -146,18 +138,24 @@ class VictoryScreen( } } - private fun wonOrLost(description: String, victoryType: String?, hasWon: Boolean) { - val victory = playerCiv.gameInfo.ruleset.victories[victoryType] + private fun displayWinner(victoryData: VictoryData) { + // We could add `, victoryTurn` to the left side - undecided how to display + val (winningCiv, victoryType) = victoryData + val victory = gameInfo.ruleset.victories[victoryType] ?: Victory() // This contains our default victory/defeat texts - val endGameMessage = when { - hasWon -> victory.victoryString - else -> victory.defeatString - } + if (winningCiv == playerCiv.civName) { + displayWonOrLost("You have won a [$victoryType] Victory!", victory.victoryString) + music.chooseTrack(playerCiv.civName, listOf(MusicMood.Victory, MusicMood.Theme), EnumSet.of(MusicTrackChooserFlags.SuffixMustMatch)) + } else { + displayWonOrLost("[$winningCiv] has won a [$victoryType] Victory!", victory.defeatString) + music.chooseTrack(playerCiv.civName, MusicMood.Defeat, EnumSet.of(MusicTrackChooserFlags.SuffixMustMatch)) + } + } - descriptionLabel.setText(description.tr() + "\n" + endGameMessage.tr()) + private fun displayWonOrLost(vararg descriptions: String) { + descriptionLabel.setText(descriptions.joinToString("\n") { it.tr() }) rightSideButton.setText("Start new game".tr()) - rightSideButton.isVisible = true rightSideButton.enable() rightSideButton.onClick { val newGameSetupInfo = GameSetupInfo(gameInfo) diff --git a/core/src/com/unciv/ui/screens/worldscreen/WorldScreen.kt b/core/src/com/unciv/ui/screens/worldscreen/WorldScreen.kt index 81df8859ac..eea4972206 100644 --- a/core/src/com/unciv/ui/screens/worldscreen/WorldScreen.kt +++ b/core/src/com/unciv/ui/screens/worldscreen/WorldScreen.kt @@ -377,7 +377,7 @@ class WorldScreen( when { viewingCiv.shouldShowDiplomaticVotingResults() -> UncivGame.Current.pushScreen(DiplomaticVoteResultScreen(gameInfo.diplomaticVictoryVotesCast, viewingCiv)) - !gameInfo.oneMoreTurnMode && (viewingCiv.isDefeated() || gameInfo.civilizations.any { it.victoryManager.hasWon() }) -> + !gameInfo.oneMoreTurnMode && (viewingCiv.isDefeated() || gameInfo.checkForVictory()) -> game.pushScreen(VictoryScreen(this)) viewingCiv.greatPeople.freeGreatPeople > 0 -> game.pushScreen(GreatPersonPickerScreen(viewingCiv)) diff --git a/docs/Modders/Images-and-Audio.md b/docs/Modders/Images-and-Audio.md index 29849fcdeb..8830dc597c 100644 --- a/docs/Modders/Images-and-Audio.md +++ b/docs/Modders/Images-and-Audio.md @@ -94,23 +94,24 @@ Triggers indicate context (call it intent, mood, whatever, it doesn't matter) by The current list of triggers is as follows: -| Description | Prefix | [^M] | Suffix | [^X] | Flags | -| ----------- |:------ |:----:| ------:|:----:|:-----:| -| Automatic next-track[^0] | | | Ambient | | | -| Launch game[^1] | | | Menu | | | -| Every 10th turn | (player civ name) | [^M] | Peace or War[^2] | | [^F] | -| New game: Select a mod | (mod name) | [^M] | Theme | | [^S] | -| New game: Pick a nation for a player | (nation name) | [^M] | Theme or Peace | | [^S] | -| Diplomacy: Select player | (nation name) | [^M] | Peace or War[^3] | | [^S] | -| First contact[^4] | (civ name) | [^M] | Theme or Peace | [^X] | | -| War declaration[^5] | (civ name) | [^M] | War | [^X] | | -| Civ defeated | (civ name) | | Defeat | [^X] | | -| Golden Age | (civ name) | [^M] | Golden | [^X] | | -| Wonder built | (wonder name) | [^M] | Wonder | [^X] | | -| Tech researched | (tech name) | [^M] | Researched | [^X] | | -| Map editor: Select nation start location | (nation name) | [^M] | Theme | | [^S] | -| Options: Volume slider or Default track downloaded | | | | | [^D] | -| Options: Click currently playing label[^6] | | [^M] | Ambient | | [^S] | +| Description | Prefix | [^M] | Suffix | [^X] | Flags | +|----------------------------------------------------|:------------------|:----:|-----------------:|:-----:|:-----:| +| Automatic next-track[^0] | | | Ambient | | | +| Launch game[^1] | | | Menu | | | +| Every 10th turn | (player civ name) | [^M] | Peace or War[^2] | | [^F] | +| New game: Select a mod | (mod name) | [^M] | Theme | | [^S] | +| New game: Pick a nation for a player | (nation name) | [^M] | Theme or Peace | | [^S] | +| Diplomacy: Select player | (nation name) | [^M] | Peace or War[^3] | | [^S] | +| First contact[^4] | (civ name) | [^M] | Theme or Peace | [^X] | | +| War declaration[^5] | (civ name) | [^M] | War | [^X] | | +| Civ defeated | (civ name) | | Defeat | [^X] | | +| Player wins | (civ name) | | Victory | [^X] | | +| Golden Age | (civ name) | [^M] | Golden | [^X] | | +| Wonder built | (wonder name) | [^M] | Wonder | [^X] | | +| Tech researched | (tech name) | [^M] | Researched | [^X] | | +| Map editor: Select nation start location | (nation name) | [^M] | Theme | | [^S] | +| Options: Volume slider or Default track downloaded | | | | | [^D] | +| Music controls (Options or from Menu) Next track | | | Ambient | | | Legend: @@ -126,4 +127,3 @@ Legend: - [^3]: According to your relation to the picked player. - [^4]: Excluding City States. - [^5]: Both in the alert when another player declares War on you and declaring War yourself in Diplomacy screen. -- [^6]: Yes these flags are not optimal.