mirror of
https://github.com/yairm210/Unciv.git
synced 2025-01-10 07:16:54 +07:00
Victory screen reorg/cleanup (#9111)
* VictoryScreen reorg * VictoryScreen reorg - use TabbedPager * VictoryScreen reorg - make helpers reusable * VictoryScreen reorg - fixed headers * VictoryScreen reorg - debug access to Replay * Victories reorg - more cleanup * VictoryScreen reorg - icons and keys * VictoryScreen reorg - RankingType * VictoryScreen reorg - RecreateOnResize * VictoryScreen reorg - Avoid floating text overlapping buttons * VictoryScreen reorg - remove obsolete todo
This commit is contained in:
parent
8b01498227
commit
cd4e25a4f1
@ -27,7 +27,6 @@
|
||||
},
|
||||
{
|
||||
"name": "Diplomatic",
|
||||
"hiddenInVictoryScreen": false,
|
||||
"victoryScreenHeader": "Build the UN and be voted\nworld leader to win!",
|
||||
"milestones": ["Anyone should build [United Nations]", "Win diplomatic vote"],
|
||||
"victoryString": "You have triumphed over your foes through the art of diplomacy! Your cunning and wisdom have earned you great friends - and divided and sown confusion among your enemies! Forever will you be remembered as the leader who brought peace to this weary world!",
|
||||
@ -40,4 +39,4 @@
|
||||
"victoryString": "The world has been convulsed by war. Many great and powerful civilizations have fallen, but you have survived - and emerged victorious! The world will long remember your glorious triumph!",
|
||||
"defeatString": "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!"
|
||||
}
|
||||
]
|
||||
]
|
||||
|
@ -27,7 +27,6 @@
|
||||
},
|
||||
{
|
||||
"name": "Diplomatic",
|
||||
"hiddenInVictoryScreen": false,
|
||||
"victoryScreenHeader": "Build the UN and be voted\nworld leader to win!",
|
||||
"milestones": ["Anyone should build [United Nations]", "Win diplomatic vote"],
|
||||
"victoryString": "You have triumphed over your foes through the art of diplomacy! Your cunning and wisdom have earned you great friends - and divided and sown confusion among your enemies! Forever will you be remembered as the leader who brought peace to this weary world!",
|
||||
@ -40,4 +39,4 @@
|
||||
"victoryString": "The world has been convulsed by war. Many great and powerful civilizations have fallen, but you have survived - and emerged victorious! The world will long remember your glorious triumph!",
|
||||
"defeatString": "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!"
|
||||
}
|
||||
]
|
||||
]
|
||||
|
@ -45,7 +45,7 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){
|
||||
|
||||
private val isAtWar = civInfo.isAtWar()
|
||||
private val buildingsForVictory = civInfo.gameInfo.getEnabledVictories().values
|
||||
.mapNotNull { civInfo.victoryManager.getNextMilestone(it.name) }
|
||||
.mapNotNull { civInfo.victoryManager.getNextMilestone(it) }
|
||||
.filter { it.type == MilestoneType.BuiltBuilding || it.type == MilestoneType.BuildingBuiltGlobally }
|
||||
.map { it.params[0] }
|
||||
|
||||
|
@ -572,7 +572,7 @@ object NextTurnAutomation {
|
||||
* a unit and selling a building to make room. Can happen due to trades etc */
|
||||
private fun freeUpSpaceResources(civInfo: Civilization) {
|
||||
// No need to build spaceship parts just yet
|
||||
if (civInfo.gameInfo.ruleset.victories.none { civInfo.victoryManager.getNextMilestone(it.key)?.type == MilestoneType.AddedSSPartsInCapital } )
|
||||
if (civInfo.gameInfo.ruleset.victories.none { civInfo.victoryManager.getNextMilestone(it.value)?.type == MilestoneType.AddedSSPartsInCapital } )
|
||||
return
|
||||
|
||||
for (resource in civInfo.gameInfo.spaceResources) {
|
||||
|
@ -541,7 +541,7 @@ class Civilization : IsPartOfGameInfoSerialization {
|
||||
else when (category) {
|
||||
RankingType.Score -> calculateTotalScore().toInt()
|
||||
RankingType.Population -> cities.sumOf { it.population.population }
|
||||
RankingType.Crop_Yield -> stats.statsForNextTurn.food.roundToInt()
|
||||
RankingType.CropYield -> stats.statsForNextTurn.food.roundToInt()
|
||||
RankingType.Production -> stats.statsForNextTurn.production.roundToInt()
|
||||
RankingType.Gold -> gold
|
||||
RankingType.Territory -> cities.sumOf { it.tiles.size }
|
||||
|
@ -5,6 +5,7 @@ import com.unciv.logic.IsPartOfGameInfoSerialization
|
||||
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.UniqueType
|
||||
|
||||
class VictoryManager : IsPartOfGameInfoSerialization {
|
||||
@ -57,27 +58,28 @@ class VictoryManager : IsPartOfGameInfoSerialization {
|
||||
|
||||
fun getVictoryTypeAchieved(): String? {
|
||||
if (!civInfo.isMajorCiv()) return null
|
||||
for (victoryName in civInfo.gameInfo.gameParameters.victoryTypes
|
||||
.filter { it != Constants.neutralVictoryType && it in civInfo.gameInfo.ruleset.victories}) {
|
||||
if (getNextMilestone(victoryName) == null)
|
||||
return victoryName
|
||||
}
|
||||
val enabledVictories = civInfo.gameInfo.gameParameters.victoryTypes
|
||||
val victory = civInfo.gameInfo.ruleset.victories
|
||||
.filter { it.key != Constants.neutralVictoryType && it.key in enabledVictories }
|
||||
.map { it.value }
|
||||
.firstOrNull { getNextMilestone(it) == null }
|
||||
if (victory != null) return victory.name
|
||||
if (civInfo.hasUnique(UniqueType.TriggersVictory))
|
||||
return Constants.neutralVictoryType
|
||||
return null
|
||||
}
|
||||
|
||||
fun getNextMilestone(victory: String): Milestone? {
|
||||
for (milestone in civInfo.gameInfo.ruleset.victories[victory]!!.milestoneObjects) {
|
||||
fun getNextMilestone(victory: Victory): Milestone? {
|
||||
for (milestone in victory.milestoneObjects) {
|
||||
if (!milestone.hasBeenCompletedBy(civInfo))
|
||||
return milestone
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun amountMilestonesCompleted(victory: String): Int {
|
||||
fun amountMilestonesCompleted(victory: Victory): Int {
|
||||
var completed = 0
|
||||
for (milestone in civInfo.gameInfo.ruleset.victories[victory]!!.milestoneObjects) {
|
||||
for (milestone in victory.milestoneObjects) {
|
||||
if (milestone.hasBeenCompletedBy(civInfo))
|
||||
++completed
|
||||
else
|
||||
|
@ -9,6 +9,7 @@ import com.badlogic.gdx.scenes.scene2d.InputListener
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Button
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Cell
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Image
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Label
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.WidgetGroup
|
||||
@ -24,6 +25,7 @@ import com.unciv.ui.components.extensions.keyShortcuts
|
||||
import com.unciv.ui.components.extensions.onActivation
|
||||
import com.unciv.ui.components.extensions.packIfNeeded
|
||||
import com.unciv.ui.components.extensions.pad
|
||||
import com.unciv.ui.components.extensions.toLabel
|
||||
import com.unciv.ui.images.IconTextButton
|
||||
import com.unciv.ui.popups.Popup
|
||||
import com.unciv.ui.screens.basescreen.BaseScreen
|
||||
@ -64,7 +66,7 @@ open class TabbedPager(
|
||||
backgroundColor: Color = BaseScreen.skinStrings.skinConfig.baseColor.darken(0.5f),
|
||||
private val headerPadding: Float = 10f,
|
||||
separatorColor: Color = Color.CLEAR,
|
||||
private val shorcutScreen: BaseScreen? = null,
|
||||
private val shortcutScreen: BaseScreen? = null,
|
||||
capacity: Int = 4
|
||||
) : Table() {
|
||||
|
||||
@ -80,7 +82,7 @@ open class TabbedPager(
|
||||
private set
|
||||
|
||||
private val header = Table(BaseScreen.skin)
|
||||
protected val headerScroll = LinkedScrollPane(horizontalOnly = true, header)
|
||||
val headerScroll = LinkedScrollPane(horizontalOnly = true, header)
|
||||
protected var headerHeight = 0f
|
||||
|
||||
private val fixedContentScroll = LinkedScrollPane(horizontalOnly = true)
|
||||
@ -105,6 +107,40 @@ open class TabbedPager(
|
||||
|
||||
/** @return Optional second content [Actor], will be placed outside the tab's main [ScrollPane] between header and `content`. Scrolls horizontally only. */
|
||||
fun getFixedContent(): Actor? = null
|
||||
|
||||
/** Sets first row cell's minWidth to the max of the widths of that column over all given tables
|
||||
*
|
||||
* Notes:
|
||||
* - This aligns columns only if the tables are arranged vertically with equal X coordinates.
|
||||
* - first table determines columns processed, all others must have at least the same column count.
|
||||
* - Tables are left as needsLayout==true, so while equal width is ensured, you may have to pack if you want to see the value before this is rendered.
|
||||
*/
|
||||
fun equalizeColumns(vararg tables: Table) {
|
||||
for (table in tables)
|
||||
table.packIfNeeded()
|
||||
val columns = tables.first().columns
|
||||
if (tables.any { it.columns < columns })
|
||||
throw IllegalStateException("IPageExtensions.equalizeColumns needs all tables to have at least the same number of columns as the first one")
|
||||
val widths = (0 until columns)
|
||||
.mapTo(ArrayList(columns)) { column ->
|
||||
tables.maxOf { it.getColumnWidth(column) }
|
||||
}
|
||||
for (table in tables) {
|
||||
for (column in 0 until columns)
|
||||
table.cells[column].run {
|
||||
if (actor == null)
|
||||
// Empty cells ignore minWidth, so just doing Table.add() for an empty cell in the top row will break this. Fix!
|
||||
setActor<Label>("".toLabel())
|
||||
else if (Align.isCenterHorizontal(align)) (actor as? Label)?.run {
|
||||
// minWidth acts like fillX, so Labels will fill and then left-align by default. Fix!
|
||||
if (!Align.isCenterHorizontal(labelAlign))
|
||||
setAlignment(Align.center)
|
||||
}
|
||||
minWidth(widths[column] - padLeft - padRight)
|
||||
}
|
||||
table.invalidate()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//endregion
|
||||
@ -472,8 +508,8 @@ open class TabbedPager(
|
||||
if (index !in 0 until pages.size) return false
|
||||
if (index == activePage) selectPage(-1)
|
||||
val page = pages.removeAt(index)
|
||||
header.getCell(page.button).clearActor()
|
||||
header.cells.removeIndex(index)
|
||||
val cell = header.getCell(page.button).clearActor()
|
||||
header.cells.removeValue(cell, true)
|
||||
return true
|
||||
}
|
||||
|
||||
@ -620,15 +656,9 @@ open class TabbedPager(
|
||||
val buttonCell: Cell<Button>
|
||||
if (insertBefore >= 0 && insertBefore < pages.size) {
|
||||
newIndex = insertBefore
|
||||
val cellIndex = header.cells.indexOf(header.getCell(pages[insertBefore].button))
|
||||
pages.add(insertBefore, page)
|
||||
// Table.addActorAt breaks the Table, it's a Group method that updates children but not cells
|
||||
// So we add an empty cell and move cell actors around
|
||||
header.add()
|
||||
for (i in header.cells.size - 1 downTo insertBefore + 1) {
|
||||
val actor = header.removeActorAt(i - 1, true) as Button
|
||||
header.cells[i].setActor<Button>(actor)
|
||||
}
|
||||
header.cells[insertBefore].setActor<Button>(page.button)
|
||||
insertHeaderCellAt(cellIndex).setActor(page.button)
|
||||
buttonCell = header.getCell(page.button)
|
||||
} else {
|
||||
newIndex = pages.size
|
||||
@ -645,10 +675,40 @@ open class TabbedPager(
|
||||
return newIndex
|
||||
}
|
||||
|
||||
private fun insertHeaderCellAt(insertBefore: Int): Cell<Actor?> {
|
||||
if (insertBefore < 0 || insertBefore >= header.cells.size) return header.add()
|
||||
// Table.addActorAt breaks the Table, it's a Group method that updates children but not cells
|
||||
// So we add an empty cell and move cell actors around
|
||||
header.add()
|
||||
for (i in header.cells.size - 1 downTo insertBefore + 1) {
|
||||
val actor = header.removeActorAt(i - 1, true)
|
||||
header.cells[i].setActor<Actor>(actor)
|
||||
}
|
||||
return header.cells[insertBefore]
|
||||
}
|
||||
|
||||
private fun addDeferredSecrets() {
|
||||
while (true) {
|
||||
val page = deferredSecretPages.removeFirstOrNull() ?: return
|
||||
addAndShowPage(page, -1)
|
||||
}
|
||||
}
|
||||
|
||||
/** Gets total width of the header buttons including their padding.
|
||||
* Header will be scrollable if getHeaderPrefWidth > width. */
|
||||
fun getHeaderPrefWidth() = header.prefWidth
|
||||
|
||||
/** Adds any Actor to the header, e.g. informative labels.
|
||||
* Must be called _after_ all pages are final, otherwise effects not guaranteed.
|
||||
* @param leftSide If `true` then [actor] is inserted on the left, otherwise on the right of the page buttons.
|
||||
*/
|
||||
fun decorateHeader(actor: Actor, leftSide: Boolean) {
|
||||
val cell = insertHeaderCellAt(if (leftSide) 0 else -1)
|
||||
cell.setActor(actor)
|
||||
if (!leftSide) return
|
||||
val addWidth = actor.width
|
||||
for (page in pages) {
|
||||
page.buttonX += addWidth
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -597,3 +597,6 @@ object GdxKeyCodeFixes {
|
||||
else -> Input.Keys.valueOf(name)
|
||||
}
|
||||
}
|
||||
|
||||
fun Input.areSecretKeysPressed() = isKeyPressed(Input.Keys.SHIFT_RIGHT) &&
|
||||
(isKeyPressed(Input.Keys.CONTROL_RIGHT) || isKeyPressed(Input.Keys.ALT_RIGHT))
|
||||
|
@ -9,6 +9,7 @@ import com.unciv.UncivGame
|
||||
import com.unciv.models.metadata.BaseRuleset
|
||||
import com.unciv.models.ruleset.RulesetCache
|
||||
import com.unciv.ui.components.TabbedPager
|
||||
import com.unciv.ui.components.extensions.areSecretKeysPressed
|
||||
import com.unciv.ui.components.extensions.center
|
||||
import com.unciv.ui.components.extensions.toCheckBox
|
||||
import com.unciv.ui.images.ImageGetter
|
||||
@ -110,7 +111,7 @@ class OptionsPopup(
|
||||
val content = ModCheckTab(screen)
|
||||
tabs.addPage("Locate mod errors", content, ImageGetter.getImage("OtherIcons/Mods"), 24f)
|
||||
}
|
||||
if (Gdx.input.isKeyPressed(Input.Keys.SHIFT_RIGHT) && (Gdx.input.isKeyPressed(Input.Keys.CONTROL_RIGHT) || Gdx.input.isKeyPressed(Input.Keys.ALT_RIGHT))) {
|
||||
if (Gdx.input.areSecretKeysPressed()) {
|
||||
tabs.addPage("Debug", debugTab(this), ImageGetter.getImage("OtherIcons/SecretOptions"), 24f, secret = true)
|
||||
}
|
||||
|
||||
|
@ -160,7 +160,7 @@ class DetailedStatsPopup(
|
||||
}
|
||||
totalTable.row()
|
||||
|
||||
// Mini version of EmpireOverviewTab.equalizeColumns - the number columns work thanks to statColMinWidth
|
||||
// Mini version of IPageExtensions.equalizeColumns - the number columns work thanks to statColMinWidth
|
||||
headerTable.packIfNeeded()
|
||||
totalTable.packIfNeeded()
|
||||
val firstColumnWidth = max(totalTable.getColumnWidth(0), headerTable.getColumnWidth(0))
|
||||
|
@ -1,13 +1,9 @@
|
||||
package com.unciv.ui.screens.overviewscreen
|
||||
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Label
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||
import com.badlogic.gdx.utils.Align
|
||||
import com.unciv.logic.civilization.Civilization
|
||||
import com.unciv.ui.screens.basescreen.BaseScreen
|
||||
import com.unciv.ui.components.TabbedPager
|
||||
import com.unciv.ui.components.extensions.packIfNeeded
|
||||
import com.unciv.ui.components.extensions.toLabel
|
||||
import com.unciv.ui.screens.basescreen.BaseScreen
|
||||
|
||||
abstract class EmpireOverviewTab (
|
||||
val viewingPlayer: Civilization,
|
||||
@ -33,37 +29,4 @@ abstract class EmpireOverviewTab (
|
||||
|
||||
val gameInfo = viewingPlayer.gameInfo
|
||||
|
||||
/** Sets first row cell's minWidth to the max of the widths of that column over all given tables
|
||||
*
|
||||
* Notes:
|
||||
* - This aligns columns only if the tables are arranged vertically with equal X coordinates.
|
||||
* - first table determines columns processed, all others must have at least the same column count.
|
||||
* - Tables are left as needsLayout==true, so while equal width is ensured, you may have to pack if you want to see the value before this is rendered.
|
||||
*/
|
||||
protected fun equalizeColumns(vararg tables: Table) {
|
||||
for (table in tables)
|
||||
table.packIfNeeded()
|
||||
val columns = tables.first().columns
|
||||
if (tables.any { it.columns < columns })
|
||||
throw IllegalStateException("EmpireOverviewTab.equalizeColumns needs all tables to have at least the same number of columns as the first one")
|
||||
val widths = (0 until columns)
|
||||
.mapTo(ArrayList(columns)) { column ->
|
||||
tables.maxOf { it.getColumnWidth(column) }
|
||||
}
|
||||
for (table in tables) {
|
||||
for (column in 0 until columns)
|
||||
table.cells[column].run {
|
||||
if (actor == null)
|
||||
// Empty cells ignore minWidth, so just doing Table.add() for an empty cell in the top row will break this. Fix!
|
||||
setActor<Label>("".toLabel())
|
||||
else if (Align.isCenterHorizontal(align)) (actor as? Label)?.run {
|
||||
// minWidth acts like fillX, so Labels will fill and then left-align by default. Fix!
|
||||
if (!Align.isCenterHorizontal(labelAlign))
|
||||
setAlignment(Align.center)
|
||||
}
|
||||
minWidth(widths[column] - padLeft - padRight)
|
||||
}
|
||||
table.invalidate()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,21 +4,26 @@ import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Image
|
||||
import com.unciv.ui.images.ImageGetter
|
||||
|
||||
enum class RankingType(val getImage: () -> Image?, val idForSerialization: String) {
|
||||
enum class RankingType(
|
||||
label: String?,
|
||||
val getImage: () -> Image?,
|
||||
val idForSerialization: String
|
||||
) {
|
||||
// production, gold, happiness, and culture already have icons added when the line is `tr()`anslated
|
||||
Score(
|
||||
{ ImageGetter.getImage("CityStateIcons/Cultured").apply { color = Color.FIREBRICK } },
|
||||
"S"
|
||||
),
|
||||
Score({ ImageGetter.getImage("CityStateIcons/Cultured").apply { color = Color.FIREBRICK } }, "S"),
|
||||
Population({ ImageGetter.getStatIcon("Population") }, "N"),
|
||||
Crop_Yield({ ImageGetter.getStatIcon("Food") }, "C"),
|
||||
Production({ null }, "P"),
|
||||
Gold({ null }, "G"),
|
||||
CropYield("Crop Yield", { ImageGetter.getStatIcon("Food") }, "C"),
|
||||
Production("P"),
|
||||
Gold("G"),
|
||||
Territory({ ImageGetter.getImage("OtherIcons/Hexagon") }, "T"),
|
||||
Force({ ImageGetter.getImage("OtherIcons/Shield") }, "F"),
|
||||
Happiness({ null }, "H"),
|
||||
Happiness("H"),
|
||||
Technologies({ ImageGetter.getStatIcon("Science") }, "W"),
|
||||
Culture({ null }, "A");
|
||||
Culture("A")
|
||||
;
|
||||
val label = label ?: name
|
||||
constructor(getImage: () -> Image?, idForSerialization: String) : this(null, getImage, idForSerialization)
|
||||
constructor(idForSerialization: String) : this(null, { null }, idForSerialization)
|
||||
|
||||
companion object {
|
||||
fun fromIdForSerialization(s: String): RankingType? =
|
||||
|
@ -1,7 +1,9 @@
|
||||
package com.unciv.ui.screens.victoryscreen
|
||||
|
||||
import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.VerticalGroup
|
||||
import com.badlogic.gdx.utils.Align
|
||||
import com.unciv.Constants
|
||||
import com.unciv.UncivGame
|
||||
@ -9,58 +11,99 @@ 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.extensions.addSeparator
|
||||
import com.unciv.ui.components.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.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.basescreen.RecreateOnResize
|
||||
import com.unciv.ui.screens.newgamescreen.NewGameScreen
|
||||
import com.unciv.ui.screens.pickerscreens.PickerScreen
|
||||
import com.unciv.ui.screens.worldscreen.WorldScreen
|
||||
|
||||
class VictoryScreen(private val worldScreen: WorldScreen) : PickerScreen() {
|
||||
//TODO someoneHasWon should look at gameInfo.victoryData
|
||||
//TODO replay slider
|
||||
|
||||
class VictoryScreen(
|
||||
private val worldScreen: WorldScreen,
|
||||
pageNumber: Int = 0
|
||||
) : PickerScreen(), RecreateOnResize {
|
||||
|
||||
private val gameInfo = worldScreen.gameInfo
|
||||
private val playerCivInfo = worldScreen.viewingCiv
|
||||
private val playerCiv = worldScreen.viewingCiv
|
||||
private val tabs = TabbedPager(separatorColor = Color.WHITE, shortcutScreen = this)
|
||||
|
||||
private val headerTable = Table()
|
||||
private val contentsTable = Table()
|
||||
internal class CivWithStat(val civ: Civilization, val value: Int) {
|
||||
constructor(civ: Civilization, category: RankingType) : this(civ, civ.getStatForRanking(category))
|
||||
}
|
||||
|
||||
private var replayTab: VictoryScreenReplay? = null
|
||||
private enum class VictoryTabs(
|
||||
val key: Char,
|
||||
val iconName: String = "",
|
||||
val caption: String? = null,
|
||||
val align: Int = Align.topLeft,
|
||||
val syncScroll: Boolean = true,
|
||||
val allowAsSecret: Boolean = false
|
||||
) {
|
||||
OurStatus('O', "StatIcons/Specialist", caption = "Our status") {
|
||||
override fun getContent(worldScreen: WorldScreen) = VictoryScreenOurVictory(worldScreen)
|
||||
override fun isHidden(playerCiv: Civilization) = playerCiv.isSpectator()
|
||||
},
|
||||
Global('G', "OtherIcons/Nations", caption = "Global status") {
|
||||
override fun getContent(worldScreen: WorldScreen) = VictoryScreenGlobalVictory(worldScreen)
|
||||
},
|
||||
Demographics('D', "CityStateIcons/Cultured", allowAsSecret = true) {
|
||||
override fun getContent(worldScreen: WorldScreen) = VictoryScreenDemographics(worldScreen)
|
||||
override fun isHidden(playerCiv: Civilization) = !UncivGame.Current.settings.useDemographics
|
||||
},
|
||||
Rankings('R', "CityStateIcons/Cultured", allowAsSecret = true) {
|
||||
override fun getContent(worldScreen: WorldScreen) = VictoryScreenCivRankings(worldScreen)
|
||||
override fun isHidden(playerCiv: Civilization) = UncivGame.Current.settings.useDemographics
|
||||
},
|
||||
Replay('P', "OtherIcons/Load", align = Align.top, syncScroll = false, allowAsSecret = true) {
|
||||
override fun getContent(worldScreen: WorldScreen) = VictoryScreenReplay(worldScreen)
|
||||
override fun isHidden(playerCiv: Civilization) =
|
||||
!playerCiv.isSpectator() && playerCiv.gameInfo.victoryData == null && playerCiv.isAlive()
|
||||
};
|
||||
abstract fun getContent(worldScreen: WorldScreen): Table
|
||||
open fun isHidden(playerCiv: Civilization) = false
|
||||
}
|
||||
|
||||
init {
|
||||
val difficultyLabel = ("{Difficulty}: {${gameInfo.difficulty}}").toLabel()
|
||||
//**************** Set up the tabs ****************
|
||||
splitPane.setFirstWidget(tabs)
|
||||
val iconSize = Constants.defaultFontSize.toFloat()
|
||||
|
||||
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)
|
||||
|
||||
val rankingLabel = if (UncivGame.Current.settings.useDemographics) "Demographics" else "Rankings"
|
||||
val setCivRankingsButton = rankingLabel.toTextButton().onClick { setCivRankingsTable() }
|
||||
tabsTable.add(setCivRankingsButton)
|
||||
|
||||
if (playerCivInfo.isSpectator())
|
||||
setGlobalVictoryTable()
|
||||
else
|
||||
setOurVictoryTable()
|
||||
for (tab in VictoryTabs.values()) {
|
||||
val tabHidden = tab.isHidden(playerCiv)
|
||||
if (tabHidden && !(tab.allowAsSecret && Gdx.input.areSecretKeysPressed()))
|
||||
continue
|
||||
val icon = if (tab.iconName.isEmpty()) null else ImageGetter.getImage(tab.iconName)
|
||||
tabs.addPage(
|
||||
tab.caption ?: tab.name,
|
||||
tab.getContent(worldScreen),
|
||||
icon, iconSize,
|
||||
scrollAlign = tab.align, syncScroll = tab.syncScroll,
|
||||
shortcutKey = KeyCharAndCode(tab.key),
|
||||
secret = tabHidden && tab.allowAsSecret
|
||||
)
|
||||
}
|
||||
tabs.selectPage(pageNumber)
|
||||
|
||||
//**************** Set up bottom area - buttons and description label ****************
|
||||
rightSideButton.isVisible = false
|
||||
|
||||
//TODO the following should look at gameInfo.victoryData
|
||||
var someoneHasWon = false
|
||||
|
||||
val playerVictoryType = playerCivInfo.victoryManager.getVictoryTypeAchieved()
|
||||
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 != playerCivInfo }) {
|
||||
for (civ in gameInfo.civilizations.filter { it.isMajorCiv() && it != playerCiv }) {
|
||||
val civVictoryType = civ.victoryManager.getVictoryTypeAchieved()
|
||||
if (civVictoryType != null) {
|
||||
someoneHasWon = true
|
||||
@ -68,44 +111,41 @@ class VictoryScreen(private val worldScreen: WorldScreen) : PickerScreen() {
|
||||
}
|
||||
}
|
||||
|
||||
if (playerCivInfo.isDefeated()) {
|
||||
if (playerCiv.isDefeated()) {
|
||||
wonOrLost("", null, false)
|
||||
} else if (!someoneHasWon) {
|
||||
setDefaultCloseAction()
|
||||
}
|
||||
|
||||
if (playerCivInfo.isSpectator() || someoneHasWon || playerCivInfo.isDefeated()) {
|
||||
val replayLabel = "Replay"
|
||||
val replayButton = replayLabel.toTextButton().onClick { setReplayTable() }
|
||||
tabsTable.add(replayButton)
|
||||
//**************** Set up floating info panels ****************
|
||||
// When horizontal screen space is scarce so they would overlap, insert
|
||||
// them into the scrolling portion of the TabbedPager header instead
|
||||
tabs.pack()
|
||||
val topRightPanel = VerticalGroup().apply {
|
||||
space(5f)
|
||||
align(Align.right)
|
||||
addActor("{Game Speed}: {${gameInfo.gameParameters.speed}}".toLabel())
|
||||
if ("Time" in gameInfo.gameParameters.victoryTypes)
|
||||
addActor("{Max Turns}: ${gameInfo.gameParameters.maxTurns}".toLabel())
|
||||
pack()
|
||||
}
|
||||
|
||||
val headerTableRightCell = Table()
|
||||
val gameSpeedLabel = "{Game Speed}: {${gameInfo.gameParameters.speed}}".toLabel()
|
||||
headerTableRightCell.add(gameSpeedLabel).row()
|
||||
if (gameInfo.gameParameters.victoryTypes.contains("Time")) {
|
||||
val maxTurnsLabel = "{Max Turns}: ${gameInfo.gameParameters.maxTurns}".toLabel()
|
||||
headerTableRightCell.add(maxTurnsLabel).padTop(5f)
|
||||
val difficultyLabel = "{Difficulty}: {${gameInfo.difficulty}}".toLabel()
|
||||
val neededSpace = topRightPanel.width.coerceAtLeast(difficultyLabel.width) * 2 + tabs.getHeaderPrefWidth()
|
||||
if (neededSpace > stage.width) {
|
||||
tabs.decorateHeader(difficultyLabel, true)
|
||||
tabs.decorateHeader(topRightPanel, false)
|
||||
tabs.headerScroll.fadeScrollBars = false
|
||||
} else {
|
||||
val panelY = stage.height - tabs.getRowHeight(0) * 0.5f
|
||||
stage.addActor(topRightPanel)
|
||||
topRightPanel.setPosition(stage.width - 10f, panelY, Align.right)
|
||||
stage.addActor(difficultyLabel)
|
||||
difficultyLabel.setPosition(10f, panelY, Align.left)
|
||||
}
|
||||
|
||||
val leftCell = headerTable.add(difficultyLabel).padLeft(10f).left()
|
||||
headerTable.add(tabsTable).expandX().center()
|
||||
val rightCell = headerTable.add(headerTableRightCell).padRight(10f).right()
|
||||
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)
|
||||
else leftCell.width(rightCell.actorWidth)
|
||||
|
||||
pickerPane.clearChildren()
|
||||
pickerPane.add(headerTable).growX().row()
|
||||
pickerPane.add(splitPane).expand().fill()
|
||||
|
||||
topTable.add(contentsTable)
|
||||
}
|
||||
|
||||
private fun wonOrLost(description: String, victoryType: String?, hasWon: Boolean) {
|
||||
val victory = playerCivInfo.gameInfo.ruleset.victories[victoryType]
|
||||
val victory = playerCiv.gameInfo.ruleset.victories[victoryType]
|
||||
?: Victory() // This contains our default victory/defeat texts
|
||||
val endGameMessage = when {
|
||||
hasWon -> victory.victoryString
|
||||
@ -130,72 +170,15 @@ class VictoryScreen(private val worldScreen: WorldScreen) : PickerScreen() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun setOurVictoryTable() {
|
||||
resetContent(VictoryScreenOurVictory(worldScreen))
|
||||
}
|
||||
|
||||
private fun setGlobalVictoryTable() {
|
||||
resetContent(VictoryScreenGlobalVictory(worldScreen))
|
||||
}
|
||||
|
||||
private fun setCivRankingsTable() {
|
||||
resetContent(VictoryScreenCivRankings(worldScreen))
|
||||
}
|
||||
|
||||
private fun setReplayTable() {
|
||||
if (replayTab == null) replayTab = VictoryScreenReplay(worldScreen)
|
||||
resetContent(replayTab!!)
|
||||
replayTab!!.restartTimer()
|
||||
}
|
||||
|
||||
private fun resetContent(newContent: Table) {
|
||||
replayTab?.resetTimer()
|
||||
contentsTable.clear()
|
||||
contentsTable.add(newContent)
|
||||
override fun show() {
|
||||
super.show()
|
||||
tabs.askForPassword(secretHashCode = 2747985)
|
||||
}
|
||||
|
||||
override fun dispose() {
|
||||
tabs.selectPage(-1) // Tells Replay page to stop its timer
|
||||
super.dispose()
|
||||
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
|
||||
}
|
||||
}
|
||||
override fun recreate(): BaseScreen = VictoryScreen(worldScreen, tabs.activePage)
|
||||
}
|
||||
|
@ -0,0 +1,67 @@
|
||||
package com.unciv.ui.screens.victoryscreen
|
||||
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||
import com.badlogic.gdx.utils.Align
|
||||
import com.unciv.Constants
|
||||
import com.unciv.logic.civilization.Civilization
|
||||
import com.unciv.models.translations.tr
|
||||
import com.unciv.ui.components.extensions.toLabel
|
||||
import com.unciv.ui.images.ImageGetter
|
||||
import com.unciv.ui.screens.basescreen.BaseScreen
|
||||
|
||||
/** Element displaying one Civilization as seen by another Civilization on a rounded-edge background.
|
||||
* @param civ Civilization to show, with nation icon (depending on alive / known) and name, optionally followed by …
|
||||
* @param separator … a separator (untranslated, only if additionalInfo isn't empty) and …
|
||||
* @param additionalInfo … some additional info, auto-translated.
|
||||
* @param currentPlayer Viewing Civilization
|
||||
*/
|
||||
internal class VictoryScreenCivGroup(
|
||||
civ: Civilization,
|
||||
separator: String,
|
||||
additionalInfo: String,
|
||||
currentPlayer: Civilization
|
||||
) : Table() {
|
||||
// Note this Table has no skin - works as long as no element tries to get its skin from the parent
|
||||
|
||||
constructor(civEntry: VictoryScreen.CivWithStat, currentPlayer: Civilization)
|
||||
: this(civEntry.civ, ": ", civEntry.value.toString(), currentPlayer)
|
||||
constructor(civ: Civilization, additionalInfo: String, currentPlayer: Civilization)
|
||||
// That tr() is only needed to support additionalInfo containing {} because tr() doesn't support nested ones.
|
||||
: this(civ, "\n", additionalInfo.tr(), currentPlayer)
|
||||
|
||||
init {
|
||||
var labelText = if (additionalInfo.isEmpty()) civ.civName
|
||||
else "{${civ.civName}}$separator{$additionalInfo}"
|
||||
val labelColor: Color
|
||||
val backgroundColor: Color
|
||||
|
||||
when {
|
||||
civ.isDefeated() -> {
|
||||
add(ImageGetter.getImage("OtherIcons/DisbandUnit")).size(30f)
|
||||
backgroundColor = Color.LIGHT_GRAY
|
||||
labelColor = Color.BLACK
|
||||
}
|
||||
currentPlayer == civ // || game.viewEntireMapForDebug
|
||||
|| currentPlayer.knows(civ)
|
||||
|| currentPlayer.isDefeated()
|
||||
|| currentPlayer.victoryManager.hasWon() -> {
|
||||
add(ImageGetter.getNationPortrait(civ.nation, 30f))
|
||||
backgroundColor = civ.nation.getOuterColor()
|
||||
labelColor = civ.nation.getInnerColor()
|
||||
}
|
||||
else -> {
|
||||
add(ImageGetter.getRandomNationPortrait(30f))
|
||||
backgroundColor = Color.DARK_GRAY
|
||||
labelColor = Color.WHITE
|
||||
labelText = Constants.unknownNationName
|
||||
}
|
||||
}
|
||||
|
||||
background = BaseScreen.skinStrings.getUiBackground("VictoryScreen/CivGroup", BaseScreen.skinStrings.roundedEdgeRectangleShape, backgroundColor)
|
||||
val label = labelText.toLabel(labelColor)
|
||||
label.setAlignment(Align.center)
|
||||
|
||||
add(label).padLeft(10f)
|
||||
}
|
||||
}
|
@ -1,87 +1,48 @@
|
||||
package com.unciv.ui.screens.victoryscreen
|
||||
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
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.TabbedPager
|
||||
import com.unciv.ui.components.extensions.addSeparator
|
||||
import com.unciv.ui.components.extensions.toLabel
|
||||
import com.unciv.ui.screens.basescreen.BaseScreen
|
||||
import com.unciv.ui.screens.worldscreen.WorldScreen
|
||||
|
||||
class VictoryScreenCivRankings(
|
||||
private val worldScreen: WorldScreen
|
||||
) : VictoryScreen.VictoryScreenTab(worldScreen) {
|
||||
worldScreen: WorldScreen
|
||||
) : Table(BaseScreen.skin), TabbedPager.IPageExtensions {
|
||||
private val header = Table()
|
||||
|
||||
init {
|
||||
defaults().pad(5f)
|
||||
defaults().pad(10f)
|
||||
|
||||
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<Civilization>) {
|
||||
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)
|
||||
val majorCivs = worldScreen.gameInfo.civilizations.filter { it.isMajorCiv() }
|
||||
|
||||
for (category in RankingType.values()) {
|
||||
val headers = Table().apply { defaults().pad(5f) }
|
||||
val textAndIcon = Table().apply { defaults() }
|
||||
val textAndIcon = Table()
|
||||
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)
|
||||
}
|
||||
}
|
||||
if (columnImage != null)
|
||||
textAndIcon.add(columnImage).size(Constants.defaultFontSize.toFloat() * 0.75f)
|
||||
.padRight(2f).padTop(-2f)
|
||||
textAndIcon.add(category.label.toLabel()).row()
|
||||
header.add(textAndIcon).pad(10f)
|
||||
|
||||
private fun buildRankingsTable(majorCivs: List<Civilization>) {
|
||||
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()
|
||||
val column = Table().apply { defaults().space(10f) }
|
||||
val civData = majorCivs
|
||||
.map { VictoryScreen.CivWithStat(it, category) }
|
||||
.sortedByDescending { it.value }
|
||||
for (civEntry in civData) {
|
||||
column.add(VictoryScreenCivGroup(civEntry, worldScreen.viewingCiv)).fillX().row()
|
||||
}
|
||||
|
||||
add(column)
|
||||
}
|
||||
header.addSeparator(Color.GRAY)
|
||||
}
|
||||
|
||||
override fun activated(index: Int, caption: String, pager: TabbedPager) {
|
||||
equalizeColumns(header, this)
|
||||
}
|
||||
|
||||
override fun getFixedContent() = header
|
||||
}
|
||||
|
@ -0,0 +1,70 @@
|
||||
package com.unciv.ui.screens.victoryscreen
|
||||
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||
import com.unciv.Constants
|
||||
import com.unciv.ui.components.extensions.addSeparator
|
||||
import com.unciv.ui.components.extensions.toLabel
|
||||
import com.unciv.ui.screens.basescreen.BaseScreen
|
||||
import com.unciv.ui.screens.worldscreen.WorldScreen
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class VictoryScreenDemographics(
|
||||
worldScreen: WorldScreen
|
||||
) : Table(BaseScreen.skin) {
|
||||
private val playerCiv = worldScreen.viewingCiv
|
||||
|
||||
private enum class RankLabels { Rank, Value, Best, Average, Worst }
|
||||
|
||||
init {
|
||||
defaults().pad(5f)
|
||||
val majorCivs = worldScreen.gameInfo.civilizations.filter { it.isMajorCiv() }
|
||||
|
||||
buildDemographicsHeaders()
|
||||
|
||||
for (rankLabel in RankLabels.values()) {
|
||||
row()
|
||||
add(rankLabel.name.toLabel())
|
||||
|
||||
for (category in RankingType.values()) {
|
||||
val aliveMajorCivsSorted = majorCivs.filter { it.isAlive() || it == playerCiv }
|
||||
.map { VictoryScreen.CivWithStat(it, category) }
|
||||
.sortedByDescending { it.value }
|
||||
|
||||
fun addRankCivGroup(civEntry: VictoryScreen.CivWithStat) {
|
||||
add(VictoryScreenCivGroup(civEntry, playerCiv)).fillX()
|
||||
}
|
||||
|
||||
@Suppress("NON_EXHAUSTIVE_WHEN") // RankLabels.Demographic treated above
|
||||
when (rankLabel) {
|
||||
RankLabels.Rank -> add((aliveMajorCivsSorted.indexOfFirst { it.civ == playerCiv } + 1).toLabel())
|
||||
RankLabels.Value -> addRankCivGroup(aliveMajorCivsSorted.first { it.civ == playerCiv })
|
||||
RankLabels.Best -> addRankCivGroup(aliveMajorCivsSorted.first())
|
||||
RankLabels.Average -> add((aliveMajorCivsSorted.sumOf { it.value }.toFloat() / aliveMajorCivsSorted.size).roundToInt().toLabel())
|
||||
RankLabels.Worst -> addRankCivGroup(aliveMajorCivsSorted.last())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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.label.toLabel()).row()
|
||||
headers.add(textAndIcon)
|
||||
headers.addSeparator()
|
||||
add(headers)
|
||||
}
|
||||
}
|
||||
}
|
@ -1,47 +1,54 @@
|
||||
package com.unciv.ui.screens.victoryscreen
|
||||
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||
import com.unciv.logic.civilization.Civilization
|
||||
import com.unciv.models.translations.tr
|
||||
import com.unciv.models.ruleset.Victory
|
||||
import com.unciv.ui.components.TabbedPager
|
||||
import com.unciv.ui.components.extensions.addSeparator
|
||||
import com.unciv.ui.components.extensions.toLabel
|
||||
import com.unciv.ui.screens.basescreen.BaseScreen
|
||||
import com.unciv.ui.screens.worldscreen.WorldScreen
|
||||
|
||||
class VictoryScreenGlobalVictory(
|
||||
worldScreen: WorldScreen
|
||||
) : VictoryScreen.VictoryScreenTab(worldScreen) {
|
||||
) : Table(BaseScreen.skin), TabbedPager.IPageExtensions {
|
||||
private val header = Table()
|
||||
|
||||
init {
|
||||
val gameInfo = worldScreen.gameInfo
|
||||
val majorCivs = gameInfo.civilizations.asSequence().filter { it.isMajorCiv() }
|
||||
val victoriesToShow = gameInfo.getEnabledVictories()
|
||||
|
||||
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 ((victoryName, victory) in victoriesToShow) {
|
||||
header.add("[$victoryName] Victory".toLabel()).pad(10f)
|
||||
add(getColumn(majorCivs, victory, worldScreen.viewingCiv))
|
||||
}
|
||||
|
||||
for (victory in victoriesToShow) {
|
||||
add(getGlobalVictoryColumn(majorCivs, victory.key))
|
||||
}
|
||||
|
||||
header.addSeparator(Color.GRAY)
|
||||
}
|
||||
|
||||
private fun getGlobalVictoryColumn(majorCivs: List<Civilization>, 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()
|
||||
private fun getColumn(
|
||||
majorCivs: Sequence<Civilization>,
|
||||
victory: Victory,
|
||||
playerCiv: Civilization
|
||||
) = Table().apply {
|
||||
defaults().pad(10f)
|
||||
val sortedCivs = majorCivs.sortedWith(
|
||||
compareBy<Civilization> { it.isDefeated() }
|
||||
.thenBy { it.victoryManager.amountMilestonesCompleted(victory) }
|
||||
)
|
||||
for (civ in sortedCivs) {
|
||||
val buttonText = civ.victoryManager.getNextMilestone(victory)
|
||||
?.getVictoryScreenButtonHeaderText(false, civ)
|
||||
?: "Done!"
|
||||
add(VictoryScreenCivGroup(civ, buttonText, playerCiv)).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
|
||||
}
|
||||
|
||||
override fun activated(index: Int, caption: String, pager: TabbedPager) {
|
||||
equalizeColumns(header, this)
|
||||
}
|
||||
|
||||
override fun getFixedContent() = header
|
||||
}
|
||||
|
@ -1,54 +1,61 @@
|
||||
package com.unciv.ui.screens.victoryscreen
|
||||
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||
import com.unciv.logic.civilization.Civilization
|
||||
import com.unciv.models.ruleset.Victory
|
||||
import com.unciv.ui.components.TabbedPager
|
||||
import com.unciv.ui.components.extensions.addSeparator
|
||||
import com.unciv.ui.components.extensions.toLabel
|
||||
import com.unciv.ui.screens.basescreen.BaseScreen
|
||||
import com.unciv.ui.screens.worldscreen.WorldScreen
|
||||
|
||||
class VictoryScreenOurVictory(
|
||||
worldScreen: WorldScreen
|
||||
) : VictoryScreen.VictoryScreenTab(worldScreen) {
|
||||
) : Table(BaseScreen.skin), TabbedPager.IPageExtensions {
|
||||
private val header = Table()
|
||||
|
||||
init {
|
||||
defaults().pad(10f)
|
||||
val gameInfo = worldScreen.gameInfo
|
||||
val victoriesToShow = gameInfo.getEnabledVictories()
|
||||
|
||||
for (victory in victoriesToShow) {
|
||||
add("[${victory.key}] Victory".toLabel())
|
||||
defaults().pad(10f)
|
||||
for ((victoryName, victory) in victoriesToShow) {
|
||||
header.add("[$victoryName] Victory".toLabel()).pad(10f)
|
||||
add(getColumn(victory, worldScreen.viewingCiv))
|
||||
}
|
||||
|
||||
row()
|
||||
|
||||
for (victory in victoriesToShow) {
|
||||
add(getOurVictoryColumn(victory.key))
|
||||
}
|
||||
row()
|
||||
|
||||
for (victory in victoriesToShow) {
|
||||
add(victory.value.victoryScreenHeader.toLabel())
|
||||
for (victory in victoriesToShow.values) {
|
||||
add(victory.victoryScreenHeader.toLabel())
|
||||
}
|
||||
|
||||
header.addSeparator(Color.GRAY)
|
||||
}
|
||||
|
||||
private fun getOurVictoryColumn(victory: String): Table {
|
||||
val victoryObject = gameInfo.ruleset.victories[victory]!!
|
||||
private fun getColumn(victory: Victory, playerCiv: Civilization): Table {
|
||||
val table = Table()
|
||||
table.defaults().pad(5f)
|
||||
table.defaults().space(10f)
|
||||
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)) {
|
||||
for (milestone in victory.milestoneObjects) {
|
||||
val completionStatus = when {
|
||||
milestone.hasBeenCompletedBy(playerCiv) -> Victory.CompletionStatus.Completed
|
||||
firstIncomplete -> {
|
||||
firstIncomplete = false
|
||||
Victory.CompletionStatus.Partially
|
||||
}
|
||||
else -> Victory.CompletionStatus.Incomplete
|
||||
}
|
||||
for (button in milestone.getVictoryScreenButtons(completionStatus, playerCiv)) {
|
||||
table.add(button).row()
|
||||
}
|
||||
}
|
||||
return table
|
||||
}
|
||||
|
||||
override fun activated(index: Int, caption: String, pager: TabbedPager) {
|
||||
equalizeColumns(header, this)
|
||||
}
|
||||
|
||||
override fun getFixedContent() = header
|
||||
}
|
||||
|
@ -1,27 +1,29 @@
|
||||
package com.unciv.ui.screens.victoryscreen
|
||||
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||
import com.badlogic.gdx.utils.Timer
|
||||
import com.unciv.ui.components.TabbedPager
|
||||
import com.unciv.ui.components.YearTextUtil
|
||||
import com.unciv.ui.components.extensions.toLabel
|
||||
import com.unciv.ui.screens.basescreen.BaseScreen
|
||||
import com.unciv.ui.screens.worldscreen.WorldScreen
|
||||
|
||||
class VictoryScreenReplay(
|
||||
worldScreen: WorldScreen
|
||||
) : VictoryScreen.VictoryScreenTab(worldScreen) {
|
||||
) : Table(BaseScreen.skin), TabbedPager.IPageExtensions {
|
||||
private val gameInfo = worldScreen.gameInfo
|
||||
|
||||
private var replayTimer : Timer.Task? = null
|
||||
private val yearLabel = "".toLabel()
|
||||
private val replayMap = ReplayMap(gameInfo.tileMap)
|
||||
private val header = Table()
|
||||
|
||||
init {
|
||||
defaults().pad(10f)
|
||||
|
||||
add(yearLabel).row()
|
||||
add(replayMap).row()
|
||||
|
||||
// restartTimer() - done later!
|
||||
header.add(yearLabel).pad(10f)
|
||||
add(replayMap).pad(10f)
|
||||
}
|
||||
|
||||
internal fun restartTimer() {
|
||||
private fun restartTimer() {
|
||||
replayTimer?.cancel()
|
||||
val firstTurn = gameInfo.historyStartTurn
|
||||
val finalTurn = gameInfo.turns
|
||||
@ -39,7 +41,7 @@ class VictoryScreenReplay(
|
||||
)
|
||||
}
|
||||
|
||||
internal fun resetTimer() {
|
||||
private fun resetTimer() {
|
||||
replayTimer?.cancel()
|
||||
replayTimer = null
|
||||
}
|
||||
@ -54,4 +56,14 @@ class VictoryScreenReplay(
|
||||
)
|
||||
replayMap.update(turn)
|
||||
}
|
||||
|
||||
override fun activated(index: Int, caption: String, pager: TabbedPager) {
|
||||
restartTimer()
|
||||
}
|
||||
|
||||
override fun deactivated(index: Int, caption: String, pager: TabbedPager) {
|
||||
resetTimer()
|
||||
}
|
||||
|
||||
override fun getFixedContent() = header
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user