Victory screen and victory detection use VictoryData (#9175)

* VictoryScreen uses VictoryData

* Victory detection no longer circumvents VictoryData
This commit is contained in:
SomeTroglodyte
2023-04-13 10:54:11 +02:00
committed by GitHub
parent 2e61023248
commit 0500f73770
6 changed files with 61 additions and 51 deletions

View File

@ -18,6 +18,7 @@ import com.unciv.logic.civilization.NotificationIcon
import com.unciv.logic.civilization.PlayerType import com.unciv.logic.civilization.PlayerType
import com.unciv.logic.civilization.managers.TechManager import com.unciv.logic.civilization.managers.TechManager
import com.unciv.logic.civilization.managers.TurnManager 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.CityDistanceData
import com.unciv.logic.map.TileMap import com.unciv.logic.map.TileMap
import com.unciv.logic.map.tile.Tile import com.unciv.logic.map.tile.Tile
@ -397,6 +398,16 @@ class GameInfo : IsPartOfGameInfoSerialization, HasGameInfoSerializationVersion
diplomaticVictoryVotesProcessed = true 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<Tile>, inOrNear: String) { private fun addEnemyUnitNotification(thisPlayer: Civilization, tiles: List<Tile>, inOrNear: String) {
// don't flood the player with similar messages. instead cycle through units by clicking the message multiple times. // don't flood the player with similar messages. instead cycle through units by clicking the message multiple times.
if (tiles.size < 3) { if (tiles.size < 3) {

View File

@ -291,7 +291,7 @@ class TurnManager(val civInfo: Civilization) {
updateWinningCiv() // Maybe we did something this turn to win updateWinningCiv() // Maybe we did something this turn to win
} }
private fun updateWinningCiv(){ fun updateWinningCiv(){
if (civInfo.gameInfo.victoryData != null) return // Game already won if (civInfo.gameInfo.victoryData != null) return // Game already won
val victoryType = civInfo.victoryManager.getVictoryTypeAchieved() val victoryType = civInfo.victoryManager.getVictoryTypeAchieved()

View File

@ -10,6 +10,7 @@ object MusicMood {
const val Golden = "Golden" const val Golden = "Golden"
const val Wonder = "Wonder" const val Wonder = "Wonder"
const val Researched = "Researched" const val Researched = "Researched"
const val Victory = "Victory"
val themeOrPeace = listOf(Theme, Peace) val themeOrPeace = listOf(Theme, Peace)
fun peaceOrWar(isAtWar: Boolean) = if (isAtWar) War else Peace fun peaceOrWar(isAtWar: Boolean) = if (isAtWar) War else Peace

View File

@ -7,10 +7,13 @@ import com.badlogic.gdx.scenes.scene2d.ui.VerticalGroup
import com.badlogic.gdx.utils.Align import com.badlogic.gdx.utils.Align
import com.unciv.Constants import com.unciv.Constants
import com.unciv.UncivGame import com.unciv.UncivGame
import com.unciv.logic.VictoryData
import com.unciv.logic.civilization.Civilization import com.unciv.logic.civilization.Civilization
import com.unciv.models.metadata.GameSetupInfo import com.unciv.models.metadata.GameSetupInfo
import com.unciv.models.ruleset.Victory 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.MusicTrackChooserFlags
import com.unciv.ui.components.KeyCharAndCode import com.unciv.ui.components.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
@ -23,14 +26,13 @@ import com.unciv.ui.screens.basescreen.RecreateOnResize
import com.unciv.ui.screens.newgamescreen.NewGameScreen import com.unciv.ui.screens.newgamescreen.NewGameScreen
import com.unciv.ui.screens.pickerscreens.PickerScreen import com.unciv.ui.screens.pickerscreens.PickerScreen
import com.unciv.ui.screens.worldscreen.WorldScreen import com.unciv.ui.screens.worldscreen.WorldScreen
import java.util.EnumSet
//TODO someoneHasWon should look at gameInfo.victoryData
class VictoryScreen( class VictoryScreen(
private val worldScreen: WorldScreen, private val worldScreen: WorldScreen,
pageNumber: Int = 0 pageNumber: Int = 0
) : PickerScreen(), RecreateOnResize { ) : PickerScreen(), RecreateOnResize {
private val music get() = UncivGame.Current.musicController
private val gameInfo = worldScreen.gameInfo private val gameInfo = worldScreen.gameInfo
private val playerCiv = worldScreen.viewingCiv private val playerCiv = worldScreen.viewingCiv
private val tabs = TabbedPager(separatorColor = Color.WHITE, shortcutScreen = this) private val tabs = TabbedPager(separatorColor = Color.WHITE, shortcutScreen = this)
@ -96,27 +98,17 @@ class VictoryScreen(
tabs.selectPage(pageNumber) tabs.selectPage(pageNumber)
//**************** Set up bottom area - buttons and description label **************** //**************** Set up bottom area - buttons and description label ****************
rightSideButton.isVisible = false when {
gameInfo.victoryData != null ->
var someoneHasWon = false displayWinner(gameInfo.victoryData!!)
playerCiv.isDefeated() -> {
val playerVictoryType = playerCiv.victoryManager.getVictoryTypeAchieved() displayWonOrLost(Victory().defeatString)
if (playerVictoryType != null) { music.chooseTrack(playerCiv.civName, MusicMood.Defeat, EnumSet.of(MusicTrackChooserFlags.SuffixMustMatch))
someoneHasWon = true }
wonOrLost("You have won a [$playerVictoryType] Victory!", playerVictoryType, true) else -> {
} rightSideButton.isVisible = false
for (civ in gameInfo.civilizations.filter { it.isMajorCiv() && it != playerCiv }) { setDefaultCloseAction()
val civVictoryType = civ.victoryManager.getVictoryTypeAchieved()
if (civVictoryType != null) {
someoneHasWon = true
wonOrLost("[${civ.civName}] has won a [$civVictoryType] Victory!", civVictoryType, false)
} }
}
if (playerCiv.isDefeated()) {
wonOrLost("", null, false)
} else if (!someoneHasWon) {
setDefaultCloseAction()
} }
//**************** Set up floating info panels **************** //**************** Set up floating info panels ****************
@ -146,18 +138,24 @@ class VictoryScreen(
} }
} }
private fun wonOrLost(description: String, victoryType: String?, hasWon: Boolean) { private fun displayWinner(victoryData: VictoryData) {
val victory = playerCiv.gameInfo.ruleset.victories[victoryType] // 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 ?: Victory() // This contains our default victory/defeat texts
val endGameMessage = when { if (winningCiv == playerCiv.civName) {
hasWon -> victory.victoryString displayWonOrLost("You have won a [$victoryType] Victory!", victory.victoryString)
else -> victory.defeatString 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.setText("Start new game".tr())
rightSideButton.isVisible = true
rightSideButton.enable() rightSideButton.enable()
rightSideButton.onClick { rightSideButton.onClick {
val newGameSetupInfo = GameSetupInfo(gameInfo) val newGameSetupInfo = GameSetupInfo(gameInfo)

View File

@ -377,7 +377,7 @@ class WorldScreen(
when { when {
viewingCiv.shouldShowDiplomaticVotingResults() -> viewingCiv.shouldShowDiplomaticVotingResults() ->
UncivGame.Current.pushScreen(DiplomaticVoteResultScreen(gameInfo.diplomaticVictoryVotesCast, viewingCiv)) 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)) game.pushScreen(VictoryScreen(this))
viewingCiv.greatPeople.freeGreatPeople > 0 -> viewingCiv.greatPeople.freeGreatPeople > 0 ->
game.pushScreen(GreatPersonPickerScreen(viewingCiv)) game.pushScreen(GreatPersonPickerScreen(viewingCiv))

View File

@ -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: The current list of triggers is as follows:
| Description | Prefix | [^M] | Suffix | [^X] | Flags | | Description | Prefix | [^M] | Suffix | [^X] | Flags |
| ----------- |:------ |:----:| ------:|:----:|:-----:| |----------------------------------------------------|:------------------|:----:|-----------------:|:-----:|:-----:|
| Automatic next-track[^0] | | | Ambient | | | | Automatic next-track[^0] | | | Ambient | | |
| Launch game[^1] | | | Menu | | | | Launch game[^1] | | | Menu | | |
| Every 10th turn | (player civ name) | [^M] | Peace or War[^2] | | [^F] | | Every 10th turn | (player civ name) | [^M] | Peace or War[^2] | | [^F] |
| New game: Select a mod | (mod name) | [^M] | Theme | | [^S] | | 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] | | 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] | | Diplomacy: Select player | (nation name) | [^M] | Peace or War[^3] | | [^S] |
| First contact[^4] | (civ name) | [^M] | Theme or Peace | [^X] | | | First contact[^4] | (civ name) | [^M] | Theme or Peace | [^X] | |
| War declaration[^5] | (civ name) | [^M] | War | [^X] | | | War declaration[^5] | (civ name) | [^M] | War | [^X] | |
| Civ defeated | (civ name) | | Defeat | [^X] | | | Civ defeated | (civ name) | | Defeat | [^X] | |
| Golden Age | (civ name) | [^M] | Golden | [^X] | | | Player wins | (civ name) | | Victory | [^X] | |
| Wonder built | (wonder name) | [^M] | Wonder | [^X] | | | Golden Age | (civ name) | [^M] | Golden | [^X] | |
| Tech researched | (tech name) | [^M] | Researched | [^X] | | | Wonder built | (wonder name) | [^M] | Wonder | [^X] | |
| Map editor: Select nation start location | (nation name) | [^M] | Theme | | [^S] | | Tech researched | (tech name) | [^M] | Researched | [^X] | |
| Options: Volume slider or Default track downloaded | | | | | [^D] | | Map editor: Select nation start location | (nation name) | [^M] | Theme | | [^S] |
| Options: Click currently playing label[^6] | | [^M] | Ambient | | [^S] | | Options: Volume slider or Default track downloaded | | | | | [^D] |
| Music controls (Options or from Menu) Next track | | | Ambient | | |
Legend: Legend:
@ -126,4 +127,3 @@ Legend:
- [^3]: According to your relation to the picked player. - [^3]: According to your relation to the picked player.
- [^4]: Excluding City States. - [^4]: Excluding City States.
- [^5]: Both in the alert when another player declares War on you and declaring War yourself in Diplomacy screen. - [^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.