From 708daf98165ff9d8f4a70a30ed921977e03ed50c Mon Sep 17 00:00:00 2001 From: SomeTroglodyte <63000004+SomeTroglodyte@users.noreply.github.com> Date: Sat, 25 Mar 2023 19:33:24 +0100 Subject: [PATCH] VictoryScreen code reorg (#9018) --- .../unciv/ui/screens/basescreen/BaseScreen.kt | 7 + .../ui/screens/victoryscreen/VictoryScreen.kt | 293 ++++-------------- .../victoryscreen/VictoryScreenCivRankings.kt | 87 ++++++ .../VictoryScreenGlobalVictory.kt | 47 +++ .../victoryscreen/VictoryScreenOurVictory.kt | 54 ++++ .../victoryscreen/VictoryScreenReplay.kt | 57 ++++ 6 files changed, 315 insertions(+), 230 deletions(-) create mode 100644 core/src/com/unciv/ui/screens/victoryscreen/VictoryScreenCivRankings.kt create mode 100644 core/src/com/unciv/ui/screens/victoryscreen/VictoryScreenGlobalVictory.kt create mode 100644 core/src/com/unciv/ui/screens/victoryscreen/VictoryScreenOurVictory.kt create mode 100644 core/src/com/unciv/ui/screens/victoryscreen/VictoryScreenReplay.kt diff --git a/core/src/com/unciv/ui/screens/basescreen/BaseScreen.kt b/core/src/com/unciv/ui/screens/basescreen/BaseScreen.kt index 370d60e392..0fbac3efa3 100644 --- a/core/src/com/unciv/ui/screens/basescreen/BaseScreen.kt +++ b/core/src/com/unciv/ui/screens/basescreen/BaseScreen.kt @@ -97,7 +97,14 @@ abstract class BaseScreen : Screen { override fun hide() {} + /** + * Called when this screen should release all resources. + * + * This is _not_ called automatically by Gdx, but by the [screenStack][UncivGame.screenStack] + * functions in [UncivGame], e.g. [replaceCurrentScreen][UncivGame.replaceCurrentScreen]. + */ override fun dispose() { + // FYI - This is a method of Gdx [Screen], not of Gdx [Disposable], but the one below _is_. stage.dispose() } diff --git a/core/src/com/unciv/ui/screens/victoryscreen/VictoryScreen.kt b/core/src/com/unciv/ui/screens/victoryscreen/VictoryScreen.kt index aaec9a61cd..1b86397551 100644 --- a/core/src/com/unciv/ui/screens/victoryscreen/VictoryScreen.kt +++ b/core/src/com/unciv/ui/screens/victoryscreen/VictoryScreen.kt @@ -1,44 +1,43 @@ package com.unciv.ui.screens.victoryscreen import com.badlogic.gdx.graphics.Color -import com.badlogic.gdx.scenes.scene2d.ui.Label import com.badlogic.gdx.scenes.scene2d.ui.Table import com.badlogic.gdx.utils.Align -import com.badlogic.gdx.utils.Timer import com.unciv.Constants import com.unciv.UncivGame 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.components.YearTextUtil import com.unciv.ui.components.extensions.addSeparator import com.unciv.ui.components.extensions.enable import com.unciv.ui.components.extensions.onClick import com.unciv.ui.components.extensions.toLabel import com.unciv.ui.components.extensions.toTextButton import com.unciv.ui.images.ImageGetter +import com.unciv.ui.screens.basescreen.BaseScreen import com.unciv.ui.screens.newgamescreen.NewGameScreen import com.unciv.ui.screens.pickerscreens.PickerScreen import com.unciv.ui.screens.worldscreen.WorldScreen -class VictoryScreen(val worldScreen: WorldScreen) : PickerScreen() { +class VictoryScreen(private val worldScreen: WorldScreen) : PickerScreen() { private val gameInfo = worldScreen.gameInfo private val playerCivInfo = worldScreen.viewingCiv - private val enabledVictoryTypes = gameInfo.gameParameters.victoryTypes private val headerTable = Table() private val contentsTable = Table() - private var replayTimer : Timer.Task? = null + private var replayTab: VictoryScreenReplay? = null init { val difficultyLabel = ("{Difficulty}: {${gameInfo.difficulty}}").toLabel() val tabsTable = Table().apply { defaults().pad(10f) } + val setMyVictoryButton = "Our status".toTextButton().onClick { setOurVictoryTable() } if (!playerCivInfo.isSpectator()) tabsTable.add(setMyVictoryButton) + val setGlobalVictoryButton = "Global status".toTextButton().onClick { setGlobalVictoryTable() } tabsTable.add(setGlobalVictoryButton) @@ -53,6 +52,7 @@ class VictoryScreen(val worldScreen: WorldScreen) : PickerScreen() { rightSideButton.isVisible = false + //TODO the following should look at gameInfo.victoryData var someoneHasWon = false val playerVictoryType = playerCivInfo.victoryManager.getVictoryTypeAchieved() @@ -83,7 +83,7 @@ class VictoryScreen(val worldScreen: WorldScreen) : PickerScreen() { val headerTableRightCell = Table() val gameSpeedLabel = "{Game Speed}: {${gameInfo.gameParameters.speed}}".toLabel() headerTableRightCell.add(gameSpeedLabel).row() - if(enabledVictoryTypes.contains("Time")) { + if (gameInfo.gameParameters.victoryTypes.contains("Time")) { val maxTurnsLabel = "{Max Turns}: ${gameInfo.gameParameters.maxTurns}".toLabel() headerTableRightCell.add(maxTurnsLabel).padTop(5f) } @@ -94,7 +94,7 @@ class VictoryScreen(val worldScreen: WorldScreen) : PickerScreen() { headerTable.addSeparator() headerTable.pack() // Make the outer cells the same so that the middle one is properly centered - if(leftCell.actorWidth > rightCell.actorWidth) rightCell.width(leftCell.actorWidth) + if (leftCell.actorWidth > rightCell.actorWidth) rightCell.width(leftCell.actorWidth) else leftCell.width(rightCell.actorWidth) pickerPane.clearChildren() @@ -105,12 +105,11 @@ class VictoryScreen(val worldScreen: WorldScreen) : PickerScreen() { } private fun wonOrLost(description: String, victoryType: String?, hasWon: Boolean) { - val endGameMessage = - when { - hasWon && (victoryType == null || victoryType !in gameInfo.ruleset.victories) -> "Your civilization stands above all others! The exploits of your people shall be remembered until the end of civilization itself!" - victoryType == null || victoryType !in gameInfo.ruleset.victories -> "You have been defeated. Your civilization has been overwhelmed by its many foes. But your people do not despair, for they know that one day you shall return - and lead them forward to victory!" - hasWon -> playerCivInfo.gameInfo.ruleset.victories[victoryType]!!.victoryString - else -> playerCivInfo.gameInfo.ruleset.victories[victoryType]!!.defeatString + val victory = playerCivInfo.gameInfo.ruleset.victories[victoryType] + ?: Victory() // This contains our default victory/defeat texts + val endGameMessage = when { + hasWon -> victory.victoryString + else -> victory.defeatString } descriptionLabel.setText(description.tr() + "\n" + endGameMessage.tr()) @@ -132,237 +131,71 @@ class VictoryScreen(val worldScreen: WorldScreen) : PickerScreen() { } private fun setOurVictoryTable() { - val ourVictoryStatusTable = Table() - ourVictoryStatusTable.defaults().pad(10f) - val victoriesToShow = gameInfo.getEnabledVictories() - - for (victory in victoriesToShow) { - ourVictoryStatusTable.add("[${victory.key}] Victory".toLabel()) - } - ourVictoryStatusTable.row() - - for (victory in victoriesToShow) { - ourVictoryStatusTable.add(getOurVictoryColumn(victory.key)) - } - ourVictoryStatusTable.row() - - for (victory in victoriesToShow) { - ourVictoryStatusTable.add(victory.value.victoryScreenHeader.toLabel()) - } - - resetContent() - contentsTable.add(ourVictoryStatusTable) - } - - private fun getOurVictoryColumn(victory: String): Table { - val victoryObject = gameInfo.ruleset.victories[victory]!! - val table = Table() - table.defaults().pad(5f) - var firstIncomplete = true - for (milestone in victoryObject.milestoneObjects) { - val completionStatus = - when { - milestone.hasBeenCompletedBy(playerCivInfo) -> Victory.CompletionStatus.Completed - firstIncomplete -> { - firstIncomplete = false - Victory.CompletionStatus.Partially - } - else -> Victory.CompletionStatus.Incomplete - } - for (button in milestone.getVictoryScreenButtons(completionStatus, playerCivInfo)) { - table.add(button).row() - } - } - return table + resetContent(VictoryScreenOurVictory(worldScreen)) } private fun setGlobalVictoryTable() { - val majorCivs = gameInfo.civilizations.filter { it.isMajorCiv() } - val globalVictoryTable = Table().apply { defaults().pad(10f) } - val victoriesToShow = gameInfo.ruleset.victories.filter { !it.value.hiddenInVictoryScreen && enabledVictoryTypes.contains(it.key) } - - for (victory in victoriesToShow) { - globalVictoryTable.add(getGlobalVictoryColumn(majorCivs, victory.key)) - } - - resetContent() - contentsTable.add(globalVictoryTable) - } - - private fun getGlobalVictoryColumn(majorCivs: List, victory: String): Table { - val victoryColumn = Table().apply { defaults().pad(10f) } - - victoryColumn.add("[$victory] Victory".toLabel()).row() - victoryColumn.addSeparator() - - for (civ in majorCivs.filter { !it.isDefeated() }.sortedByDescending { it.victoryManager.amountMilestonesCompleted(victory) }) { - val buttonText = civ.victoryManager.getNextMilestone(victory)?.getVictoryScreenButtonHeaderText(false, civ) ?: "Done!" - victoryColumn.add(getCivGroup(civ, "\n" + buttonText.tr(), playerCivInfo)).fillX().row() - } - - for (civ in majorCivs.filter { it.isDefeated() }.sortedByDescending { it.victoryManager.amountMilestonesCompleted(victory) }) { - val buttonText = civ.victoryManager.getNextMilestone(victory)?.getVictoryScreenButtonHeaderText(false, civ) ?: "Done!" - victoryColumn.add(getCivGroup(civ, "\n" + buttonText.tr(), playerCivInfo)).fillX().row() - } - - return victoryColumn + resetContent(VictoryScreenGlobalVictory(worldScreen)) } private fun setCivRankingsTable() { - val majorCivs = gameInfo.civilizations.filter { it.isMajorCiv() } - resetContent() - - if (UncivGame.Current.settings.useDemographics) contentsTable.add(buildDemographicsTable(majorCivs)) - else contentsTable.add(buildRankingsTable(majorCivs)) + resetContent(VictoryScreenCivRankings(worldScreen)) } private fun setReplayTable() { - val replayTable = Table().apply { defaults().pad(10f) } - val yearLabel = "".toLabel() - replayTable.add(yearLabel).row() - val replayMap = ReplayMap(gameInfo.tileMap) - replayTable.add(replayMap).row() - - var nextTurn = gameInfo.historyStartTurn - val finalTurn = gameInfo.turns - resetContent() - replayTimer = Timer.schedule( - object : Timer.Task() { - override fun run() { - updateReplayTable(yearLabel, replayMap, nextTurn++) - } - }, 0.0f, - // A game of 600 rounds will take one minute. - 0.1f, - // End at the last turn. - finalTurn - nextTurn - ) - contentsTable.add(replayTable) + if (replayTab == null) replayTab = VictoryScreenReplay(worldScreen) + resetContent(replayTab!!) + replayTab!!.restartTimer() } - private fun updateReplayTable(yearLabel: Label, replayMap: ReplayMap, turn: Int) { - val finalTurn = gameInfo.turns - val year = gameInfo.getYear(turn - finalTurn) - yearLabel.setText( - YearTextUtil.toYearText( - year, gameInfo.currentPlayerCiv.isLongCountDisplay() - ) - ) - replayMap.update(turn) - } - - enum class RankLabels { Rank, Value, Best, Average, Worst} - private fun buildDemographicsTable(majorCivs: List): Table { - val demographicsTable = Table().apply { defaults().pad(5f) } - buildDemographicsHeaders(demographicsTable) - - for (rankLabel in RankLabels.values()) { - demographicsTable.row() - demographicsTable.add(rankLabel.name.toLabel()) - - for (category in RankingType.values()) { - val aliveMajorCivsSorted = majorCivs.filter{ it.isAlive() }.sortedByDescending { it.getStatForRanking(category) } - - fun addRankCivGroup(civ: Civilization) { // local function for reuse of getting and formatting civ stats - demographicsTable.add(getCivGroup(civ, ": " + civ.getStatForRanking(category).toString(), playerCivInfo)).fillX() - } - - @Suppress("NON_EXHAUSTIVE_WHEN") // RankLabels.Demographic treated above - when (rankLabel) { - RankLabels.Rank -> demographicsTable.add((aliveMajorCivsSorted.indexOfFirst { it == worldScreen.viewingCiv } + 1).toLabel()) - RankLabels.Value -> addRankCivGroup(worldScreen.viewingCiv) - RankLabels.Best -> addRankCivGroup(aliveMajorCivsSorted.firstOrNull()!!) - RankLabels.Average -> demographicsTable.add((aliveMajorCivsSorted.sumOf { it.getStatForRanking(category) } / aliveMajorCivsSorted.size).toLabel()) - RankLabels.Worst -> addRankCivGroup(aliveMajorCivsSorted.lastOrNull()!!) - } - } - } - - return demographicsTable - } - - private fun buildDemographicsHeaders(demographicsTable: Table) { - val demoLabel = Table().apply { defaults().pad(5f) } - - demoLabel.add("Demographic".toLabel()).row() - demoLabel.addSeparator().fillX() - demographicsTable.add(demoLabel) - - for (category in RankingType.values()) { - val headers = Table().apply { defaults().pad(5f) } - val textAndIcon = Table().apply { defaults() } - val columnImage = category.getImage() - if (columnImage != null) textAndIcon.add(columnImage).center().size(Constants.defaultFontSize.toFloat() * 0.75f).padRight(2f).padTop(-2f) - textAndIcon.add(category.name.replace('_', ' ').toLabel()).row() - headers.add(textAndIcon) - headers.addSeparator() - demographicsTable.add(headers) - } - } - - private fun buildRankingsTable(majorCivs: List): Table { - val rankingsTable = Table().apply { defaults().pad(5f) } - - for (category in RankingType.values()) { - val column = Table().apply { defaults().pad(5f) } - val textAndIcon = Table().apply { defaults() } - val columnImage = category.getImage() - if (columnImage != null) textAndIcon.add(columnImage).size(Constants.defaultFontSize.toFloat() * 0.75f).padRight(2f).padTop(-2f) - textAndIcon.add(category.name.replace('_' , ' ').toLabel()).row() - column.add(textAndIcon) - column.addSeparator() - - for (civ in majorCivs.sortedByDescending { it.getStatForRanking(category) }) { - column.add(getCivGroup(civ, ": " + civ.getStatForRanking(category).toString(), playerCivInfo)).fillX().row() - } - - rankingsTable.add(column) - } - - return rankingsTable - } - - private fun getCivGroup(civ: Civilization, afterCivNameText: String, currentPlayer: Civilization): Table { - val civGroup = Table() - - var labelText = "{${civ.civName.tr()}}{${afterCivNameText.tr()}}" - var labelColor = Color.WHITE - val backgroundColor: Color - - if (civ.isDefeated()) { - civGroup.add(ImageGetter.getImage("OtherIcons/DisbandUnit")).size(30f) - backgroundColor = Color.LIGHT_GRAY - labelColor = Color.BLACK - } else if (currentPlayer == civ // || game.viewEntireMapForDebug - || currentPlayer.knows(civ) - || currentPlayer.isDefeated() - || currentPlayer.victoryManager.hasWon() - ) { - civGroup.add(ImageGetter.getNationPortrait(civ.nation, 30f)) - backgroundColor = civ.nation.getOuterColor() - labelColor = civ.nation.getInnerColor() - } else { - civGroup.add(ImageGetter.getRandomNationPortrait(30f)) - backgroundColor = Color.DARK_GRAY - labelText = Constants.unknownNationName - } - - civGroup.background = skinStrings.getUiBackground("VictoryScreen/CivGroup", skinStrings.roundedEdgeRectangleShape, backgroundColor) - val label = labelText.toLabel(labelColor) - label.setAlignment(Align.center) - - civGroup.add(label).padLeft(10f) - civGroup.pack() - return civGroup - } - - private fun resetContent() { - replayTimer?.cancel() + private fun resetContent(newContent: Table) { + replayTab?.resetTimer() contentsTable.clear() + contentsTable.add(newContent) } override fun dispose() { super.dispose() - replayTimer?.cancel() + replayTab?.resetTimer() + } + + open class VictoryScreenTab(worldScreen: WorldScreen) : Table(skin) { + protected val gameInfo = worldScreen.gameInfo + protected val playerCivInfo = worldScreen.viewingCiv + + // Common "service" for VictoryScreenGlobalVictory and VictoryScreenCivRankings + protected fun getCivGroup(civ: Civilization, afterCivNameText: String, currentPlayer: Civilization): Table { + val civGroup = Table() + + var labelText = "{${civ.civName.tr()}}{${afterCivNameText.tr()}}" + var labelColor = Color.WHITE + val backgroundColor: Color + + if (civ.isDefeated()) { + civGroup.add(ImageGetter.getImage("OtherIcons/DisbandUnit")).size(30f) + backgroundColor = Color.LIGHT_GRAY + labelColor = Color.BLACK + } else if (currentPlayer == civ // || game.viewEntireMapForDebug + || currentPlayer.knows(civ) + || currentPlayer.isDefeated() + || currentPlayer.victoryManager.hasWon() + ) { + civGroup.add(ImageGetter.getNationPortrait(civ.nation, 30f)) + backgroundColor = civ.nation.getOuterColor() + labelColor = civ.nation.getInnerColor() + } else { + civGroup.add(ImageGetter.getRandomNationPortrait(30f)) + backgroundColor = Color.DARK_GRAY + labelText = Constants.unknownNationName + } + + civGroup.background = skinStrings.getUiBackground("VictoryScreen/CivGroup", skinStrings.roundedEdgeRectangleShape, backgroundColor) + val label = labelText.toLabel(labelColor) + label.setAlignment(Align.center) + + civGroup.add(label).padLeft(10f) + civGroup.pack() + return civGroup + } } } diff --git a/core/src/com/unciv/ui/screens/victoryscreen/VictoryScreenCivRankings.kt b/core/src/com/unciv/ui/screens/victoryscreen/VictoryScreenCivRankings.kt new file mode 100644 index 0000000000..97d4ed3086 --- /dev/null +++ b/core/src/com/unciv/ui/screens/victoryscreen/VictoryScreenCivRankings.kt @@ -0,0 +1,87 @@ +package com.unciv.ui.screens.victoryscreen + +import com.badlogic.gdx.scenes.scene2d.ui.Table +import com.unciv.Constants +import com.unciv.UncivGame +import com.unciv.logic.civilization.Civilization +import com.unciv.ui.components.extensions.addSeparator +import com.unciv.ui.components.extensions.toLabel +import com.unciv.ui.screens.worldscreen.WorldScreen + +class VictoryScreenCivRankings( + private val worldScreen: WorldScreen +) : VictoryScreen.VictoryScreenTab(worldScreen) { + + init { + defaults().pad(5f) + + val majorCivs = gameInfo.civilizations.filter { it.isMajorCiv() } + if (UncivGame.Current.settings.useDemographics) buildDemographicsTable(majorCivs) + else buildRankingsTable(majorCivs) + } + + enum class RankLabels { Rank, Value, Best, Average, Worst} + private fun buildDemographicsTable(majorCivs: List) { + buildDemographicsHeaders() + + for (rankLabel in RankLabels.values()) { + row() + add(rankLabel.name.toLabel()) + + for (category in RankingType.values()) { + val aliveMajorCivsSorted = majorCivs.filter{ it.isAlive() }.sortedByDescending { it.getStatForRanking(category) } + + fun addRankCivGroup(civ: Civilization) { // local function for reuse of getting and formatting civ stats + add(getCivGroup(civ, ": " + civ.getStatForRanking(category).toString(), playerCivInfo)).fillX() + } + + @Suppress("NON_EXHAUSTIVE_WHEN") // RankLabels.Demographic treated above + when (rankLabel) { + RankLabels.Rank -> add((aliveMajorCivsSorted.indexOfFirst { it == worldScreen.viewingCiv } + 1).toLabel()) + RankLabels.Value -> addRankCivGroup(worldScreen.viewingCiv) + RankLabels.Best -> addRankCivGroup(aliveMajorCivsSorted.firstOrNull()!!) + RankLabels.Average -> add((aliveMajorCivsSorted.sumOf { it.getStatForRanking(category) } / aliveMajorCivsSorted.size).toLabel()) + RankLabels.Worst -> addRankCivGroup(aliveMajorCivsSorted.lastOrNull()!!) + } + } + } + } + + private fun buildDemographicsHeaders() { + val demoLabel = Table().apply { defaults().pad(5f) } + + demoLabel.add("Demographic".toLabel()).row() + demoLabel.addSeparator().fillX() + add(demoLabel) + + for (category in RankingType.values()) { + val headers = Table().apply { defaults().pad(5f) } + val textAndIcon = Table().apply { defaults() } + val columnImage = category.getImage() + if (columnImage != null) textAndIcon.add(columnImage).center().size(Constants.defaultFontSize.toFloat() * 0.75f).padRight(2f).padTop(-2f) + textAndIcon.add(category.name.replace('_', ' ').toLabel()).row() + headers.add(textAndIcon) + headers.addSeparator() + add(headers) + } + } + + private fun buildRankingsTable(majorCivs: List) { + for (category in RankingType.values()) { + val column = Table().apply { defaults().pad(5f) } + val textAndIcon = Table().apply { defaults() } + val columnImage = category.getImage() + if (columnImage != null) textAndIcon.add(columnImage).size(Constants.defaultFontSize.toFloat() * 0.75f).padRight(2f).padTop(-2f) + textAndIcon.add(category.name.replace('_' , ' ').toLabel()).row() + column.add(textAndIcon) + column.addSeparator() + + for (civ in majorCivs.sortedByDescending { it.getStatForRanking(category) }) { + column.add(getCivGroup(civ, ": " + civ.getStatForRanking(category).toString(), playerCivInfo)).fillX().row() + } + + add(column) + } + } + +} diff --git a/core/src/com/unciv/ui/screens/victoryscreen/VictoryScreenGlobalVictory.kt b/core/src/com/unciv/ui/screens/victoryscreen/VictoryScreenGlobalVictory.kt new file mode 100644 index 0000000000..8d995efa71 --- /dev/null +++ b/core/src/com/unciv/ui/screens/victoryscreen/VictoryScreenGlobalVictory.kt @@ -0,0 +1,47 @@ +package com.unciv.ui.screens.victoryscreen + +import com.badlogic.gdx.scenes.scene2d.ui.Table +import com.unciv.logic.civilization.Civilization +import com.unciv.models.translations.tr +import com.unciv.ui.components.extensions.addSeparator +import com.unciv.ui.components.extensions.toLabel +import com.unciv.ui.screens.worldscreen.WorldScreen + +class VictoryScreenGlobalVictory( + worldScreen: WorldScreen +) : VictoryScreen.VictoryScreenTab(worldScreen) { + + init { + defaults().pad(10f) + val majorCivs = gameInfo.civilizations.filter { it.isMajorCiv() } + val enabledVictoryTypes = gameInfo.gameParameters.victoryTypes + val victoriesToShow = gameInfo.ruleset.victories.filter { + !it.value.hiddenInVictoryScreen && enabledVictoryTypes.contains(it.key) + } + + for (victory in victoriesToShow) { + add(getGlobalVictoryColumn(majorCivs, victory.key)) + } + + } + + private fun getGlobalVictoryColumn(majorCivs: List, victory: String): Table { + val victoryColumn = Table().apply { defaults().pad(10f) } + + victoryColumn.add("[$victory] Victory".toLabel()).row() + victoryColumn.addSeparator() + + for (civ in majorCivs.filter { !it.isDefeated() }.sortedByDescending { it.victoryManager.amountMilestonesCompleted(victory) }) { + val buttonText = civ.victoryManager.getNextMilestone(victory)?.getVictoryScreenButtonHeaderText(false, civ) ?: "Done!" + victoryColumn.add(getCivGroup(civ, "\n" + buttonText.tr(), playerCivInfo)).fillX().row() + } + + for (civ in majorCivs.filter { it.isDefeated() }.sortedByDescending { it.victoryManager.amountMilestonesCompleted(victory) }) { + val buttonText = civ.victoryManager.getNextMilestone(victory)?.getVictoryScreenButtonHeaderText(false, civ) ?: "Done!" + victoryColumn.add(getCivGroup(civ, "\n" + buttonText.tr(), playerCivInfo)).fillX().row() + } + + return victoryColumn + } + +} diff --git a/core/src/com/unciv/ui/screens/victoryscreen/VictoryScreenOurVictory.kt b/core/src/com/unciv/ui/screens/victoryscreen/VictoryScreenOurVictory.kt new file mode 100644 index 0000000000..795d6c2566 --- /dev/null +++ b/core/src/com/unciv/ui/screens/victoryscreen/VictoryScreenOurVictory.kt @@ -0,0 +1,54 @@ +package com.unciv.ui.screens.victoryscreen + +import com.badlogic.gdx.scenes.scene2d.ui.Table +import com.unciv.models.ruleset.Victory +import com.unciv.ui.components.extensions.toLabel +import com.unciv.ui.screens.worldscreen.WorldScreen + +class VictoryScreenOurVictory( + worldScreen: WorldScreen +) : VictoryScreen.VictoryScreenTab(worldScreen) { + + init { + defaults().pad(10f) + val victoriesToShow = gameInfo.getEnabledVictories() + + for (victory in victoriesToShow) { + add("[${victory.key}] Victory".toLabel()) + } + row() + + for (victory in victoriesToShow) { + add(getOurVictoryColumn(victory.key)) + } + row() + + for (victory in victoriesToShow) { + add(victory.value.victoryScreenHeader.toLabel()) + } + + } + + private fun getOurVictoryColumn(victory: String): Table { + val victoryObject = gameInfo.ruleset.victories[victory]!! + val table = Table() + table.defaults().pad(5f) + var firstIncomplete = true + for (milestone in victoryObject.milestoneObjects) { + val completionStatus = + when { + milestone.hasBeenCompletedBy(playerCivInfo) -> Victory.CompletionStatus.Completed + firstIncomplete -> { + firstIncomplete = false + Victory.CompletionStatus.Partially + } + else -> Victory.CompletionStatus.Incomplete + } + for (button in milestone.getVictoryScreenButtons(completionStatus, playerCivInfo)) { + table.add(button).row() + } + } + return table + } + +} diff --git a/core/src/com/unciv/ui/screens/victoryscreen/VictoryScreenReplay.kt b/core/src/com/unciv/ui/screens/victoryscreen/VictoryScreenReplay.kt new file mode 100644 index 0000000000..c79d7e9766 --- /dev/null +++ b/core/src/com/unciv/ui/screens/victoryscreen/VictoryScreenReplay.kt @@ -0,0 +1,57 @@ +package com.unciv.ui.screens.victoryscreen + +import com.badlogic.gdx.utils.Timer +import com.unciv.ui.components.YearTextUtil +import com.unciv.ui.components.extensions.toLabel +import com.unciv.ui.screens.worldscreen.WorldScreen + +class VictoryScreenReplay( + worldScreen: WorldScreen +) : VictoryScreen.VictoryScreenTab(worldScreen) { + private var replayTimer : Timer.Task? = null + private val yearLabel = "".toLabel() + private val replayMap = ReplayMap(gameInfo.tileMap) + + init { + defaults().pad(10f) + + add(yearLabel).row() + add(replayMap).row() + + // restartTimer() - done later! + } + + internal fun restartTimer() { + replayTimer?.cancel() + val firstTurn = gameInfo.historyStartTurn + val finalTurn = gameInfo.turns + replayTimer = Timer.schedule( + object : Timer.Task() { + private var nextTurn = firstTurn + override fun run() { + updateReplayTable(nextTurn++) + } + }, 0.0f, + // A game of 600 rounds will take one minute. + 0.1f, + // End at the last turn. + finalTurn - firstTurn + ) + } + + internal fun resetTimer() { + replayTimer?.cancel() + replayTimer = null + } + + private fun updateReplayTable(turn: Int) { + val finalTurn = gameInfo.turns + val year = gameInfo.getYear(turn - finalTurn) + yearLabel.setText( + YearTextUtil.toYearText( + year, gameInfo.currentPlayerCiv.isLongCountDisplay() + ) + ) + replayMap.update(turn) + } +}