NextTurnAction as enum (#9889)

This commit is contained in:
SomeTroglodyte 2023-08-08 23:47:07 +02:00 committed by GitHub
parent 6c841e52c6
commit 903fb2c097
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 203 additions and 172 deletions

View File

@ -12,19 +12,19 @@ import com.badlogic.gdx.utils.Align
import com.unciv.GUI
import com.unciv.logic.battle.CityCombatant
import com.unciv.logic.city.City
import com.unciv.models.ruleset.INonPerpetualConstruction
import com.unciv.models.ruleset.PerpetualConstruction
import com.unciv.logic.civilization.diplomacy.RelationshipLevel
import com.unciv.models.TutorialTrigger
import com.unciv.models.ruleset.INonPerpetualConstruction
import com.unciv.models.ruleset.PerpetualConstruction
import com.unciv.ui.components.BorderedTable
import com.unciv.ui.components.Fonts
import com.unciv.ui.components.extensions.center
import com.unciv.ui.components.extensions.centerX
import com.unciv.ui.components.extensions.colorFromRGB
import com.unciv.ui.components.extensions.darken
import com.unciv.ui.components.input.onClick
import com.unciv.ui.components.extensions.toGroup
import com.unciv.ui.components.extensions.toLabel
import com.unciv.ui.components.input.onClick
import com.unciv.ui.images.ImageGetter
import com.unciv.ui.popups.Popup
import com.unciv.ui.screens.basescreen.BaseScreen
@ -594,7 +594,7 @@ class CityButton(val city: City, private val tileGroup: TileGroup): Table(BaseSc
addOKButton("Diplomacy") { openDiplomacy() }
add().expandX()
addCloseButton() {
GUI.getWorldScreen().run { nextTurnButton.update(this@run) }
GUI.getWorldScreen().run { nextTurnButton.update() }
}
}
popup.open()

View File

@ -118,7 +118,7 @@ class WorldScreen(
internal val minimapWrapper = MinimapHolder(mapHolder)
private val bottomTileInfoTable = TileInfoTable(viewingCiv)
internal val notificationsScroll = NotificationsScroll(this)
internal val nextTurnButton = NextTurnButton()
internal val nextTurnButton = NextTurnButton(this)
private val statusButtons = StatusButtons(nextTurnButton)
private val tutorialTaskTable = Table().apply {
background = skinStrings.getUiBackground("WorldScreen/TutorialTaskTable", tintColor = skinStrings.skinConfig.baseColor.darken(0.5f))
@ -251,9 +251,7 @@ class WorldScreen(
game.pushScreen(CityScreen(capital))
}
globalShortcuts.add(KeyboardBinding.Options) { // Game Options
this.openOptionsPopup(onClose = {
nextTurnButton.update(this)
})
openOptionsPopup { nextTurnButton.update() }
}
globalShortcuts.add(KeyboardBinding.SaveGame) { game.pushScreen(SaveGameScreen(gameInfo)) } // Save
globalShortcuts.add(KeyboardBinding.LoadGame) { game.pushScreen(LoadGameScreen()) } // Load
@ -679,7 +677,7 @@ class WorldScreen(
}
private fun updateGameplayButtons() {
nextTurnButton.update(this)
nextTurnButton.update()
updateMultiplayerStatusButton()

View File

@ -0,0 +1,185 @@
package com.unciv.ui.screens.worldscreen.status
import com.badlogic.gdx.graphics.Color
import com.unciv.Constants
import com.unciv.logic.civilization.managers.ReligionManager
import com.unciv.logic.civilization.managers.ReligionState
import com.unciv.models.Counter
import com.unciv.models.ruleset.BeliefType
import com.unciv.ui.components.extensions.disable
import com.unciv.ui.components.extensions.enable
import com.unciv.ui.popups.ConfirmPopup
import com.unciv.ui.screens.cityscreen.CityScreen
import com.unciv.ui.screens.pickerscreens.PantheonPickerScreen
import com.unciv.ui.screens.pickerscreens.PolicyPickerScreen
import com.unciv.ui.screens.pickerscreens.ReligiousBeliefsPickerScreen
import com.unciv.ui.screens.pickerscreens.TechPickerScreen
import com.unciv.ui.screens.worldscreen.WorldScreen
import com.unciv.utils.Concurrency
import com.unciv.utils.launchOnGLThread
enum class NextTurnAction(protected val text: String, val color: Color) {
Default("", Color.BLACK) {
override val icon get() = null
override fun isChoice(worldScreen: WorldScreen) = false
},
Working(Constants.working, Color.GRAY) {
override fun isChoice(worldScreen: WorldScreen) =
worldScreen.isNextTurnUpdateRunning()
},
Waiting("Waiting for other players...",Color.GRAY) {
override fun getText(worldScreen: WorldScreen) =
if (worldScreen.gameInfo.gameParameters.isOnlineMultiplayer)
"Waiting for [${worldScreen.gameInfo.currentPlayerCiv}]..."
else text
override fun isChoice(worldScreen: WorldScreen) =
!worldScreen.isPlayersTurn
},
PickConstruction("Pick construction", Color.CORAL) {
override fun isChoice(worldScreen: WorldScreen) =
getCityWithNoProductionSet(worldScreen) != null
override fun action(worldScreen: WorldScreen) {
val city = getCityWithNoProductionSet(worldScreen) ?: return
worldScreen.game.pushScreen(CityScreen(city))
}
},
PickTech("Pick a tech", Color.SKY) {
override fun isChoice(worldScreen: WorldScreen) =
worldScreen.viewingCiv.shouldOpenTechPicker()
override fun action(worldScreen: WorldScreen) =
worldScreen.game.pushScreen(
TechPickerScreen(worldScreen.viewingCiv, null, worldScreen.viewingCiv.tech.freeTechs != 0)
)
},
PickPolicy("Pick a policy", Color.VIOLET) {
override fun isChoice(worldScreen: WorldScreen) =
worldScreen.viewingCiv.policies.shouldOpenPolicyPicker
override fun action(worldScreen: WorldScreen) {
worldScreen.game.pushScreen(PolicyPickerScreen(worldScreen.selectedCiv, worldScreen.canChangeState))
worldScreen.viewingCiv.policies.shouldOpenPolicyPicker = false
}
},
FoundPantheon("Found Pantheon", Color.valueOf(BeliefType.Pantheon.color)) {
override fun isChoice(worldScreen: WorldScreen) =
worldScreen.viewingCiv.religionManager.run {
religionState != ReligionState.Pantheon && canFoundOrExpandPantheon()
}
override fun action(worldScreen: WorldScreen) =
worldScreen.game.pushScreen(PantheonPickerScreen(worldScreen.viewingCiv))
},
ExpandPantheon("Expand Pantheon", Color.valueOf(BeliefType.Pantheon.color)) {
override fun isChoice(worldScreen: WorldScreen) =
worldScreen.viewingCiv.religionManager.run {
religionState == ReligionState.Pantheon && canFoundOrExpandPantheon()
}
override fun action(worldScreen: WorldScreen) =
worldScreen.game.pushScreen(PantheonPickerScreen(worldScreen.viewingCiv))
},
FoundReligion("Found Religion", Color.valueOf(BeliefType.Founder.color)) {
override fun isChoice(worldScreen: WorldScreen) =
worldScreen.viewingCiv.religionManager.religionState == ReligionState.FoundingReligion
override fun action(worldScreen: WorldScreen) =
openReligionPicker(worldScreen, true) { getBeliefsToChooseAtFounding() }
},
EnhanceReligion("Enhance a Religion", Color.valueOf(BeliefType.Enhancer.color)) {
override fun isChoice(worldScreen: WorldScreen) =
worldScreen.viewingCiv.religionManager.religionState == ReligionState.EnhancingReligion
override fun action(worldScreen: WorldScreen) =
openReligionPicker(worldScreen, false) { getBeliefsToChooseAtEnhancing() }
},
ReformReligion("Reform Religion", Color.valueOf(BeliefType.Enhancer.color)) {
override fun isChoice(worldScreen: WorldScreen) =
worldScreen.viewingCiv.religionManager.hasFreeBeliefs()
override fun action(worldScreen: WorldScreen) =
openReligionPicker(worldScreen, false) { freeBeliefsAsEnums() }
},
WorldCongressVote("Vote for World Leader", Color.MAROON) {
override fun isChoice(worldScreen: WorldScreen) =
worldScreen.viewingCiv.mayVoteForDiplomaticVictory()
},
NextUnit("Next unit", Color.LIGHT_GRAY) {
override fun isChoice(worldScreen: WorldScreen) =
worldScreen.viewingCiv.units.shouldGoToDueUnit()
override fun action(worldScreen: WorldScreen) =
worldScreen.switchToNextUnit()
},
MoveAutomatedUnits("Move automated units", Color.LIGHT_GRAY) {
override fun isChoice(worldScreen: WorldScreen) =
worldScreen.isMoveAutomatedUnits()
override fun action(worldScreen: WorldScreen) =
moveAutomatedUnits(worldScreen)
},
NextTurn("Next turn", Color.WHITE) {
override fun isChoice(worldScreen: WorldScreen) =
true // When none of the others is active..
override fun action(worldScreen: WorldScreen) =
worldScreen.confirmedNextTurn()
},
;
open val icon: String? get() = "NotificationIcons/$name"
open fun getText(worldScreen: WorldScreen) = text
abstract fun isChoice(worldScreen: WorldScreen): Boolean
open fun action(worldScreen: WorldScreen) {}
companion object {
// Readability helpers to allow concise enum instances
private fun getCityWithNoProductionSet(worldScreen: WorldScreen) =
worldScreen.viewingCiv.cities
.firstOrNull {
!it.isPuppet && it.cityConstructions.currentConstructionFromQueue.isEmpty()
}
private fun openReligionPicker(
worldScreen: WorldScreen,
pickIconAndName: Boolean,
getBeliefs: ReligionManager.() -> Counter<BeliefType>
) =
worldScreen.game.pushScreen(
ReligiousBeliefsPickerScreen(
worldScreen.viewingCiv,
worldScreen.viewingCiv.religionManager.getBeliefs(),
pickIconAndName = pickIconAndName
)
)
private fun WorldScreen.isMoveAutomatedUnits(): Boolean {
if (game.settings.automatedUnitsMoveOnTurnStart || viewingCiv.hasMovedAutomatedUnits)
return false
return viewingCiv.units.getCivUnits()
.any {
it.currentMovement > Constants.minimumMovementEpsilon
&& (it.isMoving() || it.isAutomated() || it.isExploring())
}
}
private fun moveAutomatedUnits(worldScreen: WorldScreen) {
// Don't allow double-click of 'n' to spawn 2 processes trying to automate units
if (!worldScreen.isPlayersTurn) return
worldScreen.isPlayersTurn = false // Disable state changes
worldScreen.viewingCiv.hasMovedAutomatedUnits = true
worldScreen.nextTurnButton.disable()
Concurrency.run("Move automated units") {
for (unit in worldScreen.viewingCiv.units.getCivUnits())
unit.doAction()
launchOnGLThread {
worldScreen.shouldUpdate = true
worldScreen.isPlayersTurn = true //Re-enable state changes
worldScreen.nextTurnButton.enable()
}
}
}
private fun WorldScreen.confirmedNextTurn() {
fun action() {
game.settings.addCompletedTutorialTask("Pass a turn")
nextTurn()
}
if (game.settings.confirmNextTurn) {
ConfirmPopup(this, "Confirm next turn", "Next turn",
true, action = ::action).open()
} else action()
}
}
}

View File

@ -1,13 +1,7 @@
package com.unciv.ui.screens.worldscreen.status
import com.badlogic.gdx.graphics.Color
import com.unciv.Constants
import com.unciv.logic.civilization.managers.ReligionState
import com.unciv.models.ruleset.BeliefType
import com.unciv.models.translations.tr
import com.unciv.ui.components.UncivTooltip.Companion.addTooltip
import com.unciv.ui.components.extensions.disable
import com.unciv.ui.components.extensions.enable
import com.unciv.ui.components.extensions.isEnabled
import com.unciv.ui.components.extensions.setSize
import com.unciv.ui.components.input.KeyboardBinding
@ -15,32 +9,25 @@ import com.unciv.ui.components.input.keyShortcuts
import com.unciv.ui.components.input.onActivation
import com.unciv.ui.images.IconTextButton
import com.unciv.ui.images.ImageGetter
import com.unciv.ui.popups.ConfirmPopup
import com.unciv.ui.popups.hasOpenPopups
import com.unciv.ui.screens.cityscreen.CityScreen
import com.unciv.ui.screens.pickerscreens.DiplomaticVotePickerScreen
import com.unciv.ui.screens.pickerscreens.PantheonPickerScreen
import com.unciv.ui.screens.pickerscreens.PolicyPickerScreen
import com.unciv.ui.screens.pickerscreens.ReligiousBeliefsPickerScreen
import com.unciv.ui.screens.pickerscreens.TechPickerScreen
import com.unciv.ui.screens.worldscreen.WorldScreen
import com.unciv.utils.Concurrency
import com.unciv.utils.launchOnGLThread
class NextTurnButton : IconTextButton("", null, 30) {
class NextTurnButton(
private val worldScreen: WorldScreen
) : IconTextButton("", null, 30) {
private var nextTurnAction = NextTurnAction.Default
init {
// label.setFontSize(30)
labelCell.pad(10f)
onActivation { nextTurnAction.action() }
onActivation { nextTurnAction.action(worldScreen) }
keyShortcuts.add(KeyboardBinding.NextTurn)
keyShortcuts.add(KeyboardBinding.NextTurnAlternate)
// Let unit actions override this for command "Wait".
keyShortcuts.add(KeyboardBinding.Wait, -99)
}
fun update(worldScreen: WorldScreen) {
fun update() {
nextTurnAction = getNextTurnAction(worldScreen)
updateButton(nextTurnAction)
@ -49,156 +36,18 @@ class NextTurnButton : IconTextButton("", null, 30) {
if (isEnabled) addTooltip(KeyboardBinding.NextTurn) else addTooltip("")
}
internal fun updateButton(nextTurnAction: NextTurnAction) {
label.setText(nextTurnAction.text.tr())
label.setText(nextTurnAction.getText(worldScreen).tr())
label.color = nextTurnAction.color
if (nextTurnAction.icon != null && ImageGetter.imageExists(nextTurnAction.icon))
if (nextTurnAction.icon != null && ImageGetter.imageExists(nextTurnAction.icon!!))
iconCell.setActor(ImageGetter.getImage(nextTurnAction.icon).apply { setSize(30f) })
else
iconCell.clearActor()
pack()
}
private fun getNextTurnAction(worldScreen: WorldScreen): NextTurnAction {
return when {
worldScreen.isNextTurnUpdateRunning() ->
NextTurnAction.Working
!worldScreen.isPlayersTurn && worldScreen.gameInfo.gameParameters.isOnlineMultiplayer ->
NextTurnAction("Waiting for [${worldScreen.gameInfo.currentPlayerCiv}]...", Color.GRAY,
"NotificationIcons/Waiting") {}
!worldScreen.isPlayersTurn && !worldScreen.gameInfo.gameParameters.isOnlineMultiplayer ->
NextTurnAction.Waiting
worldScreen.viewingCiv.cities.any {
!it.isPuppet &&
it.cityConstructions.currentConstructionFromQueue == ""
} ->
NextTurnAction("Pick construction", Color.CORAL,
"NotificationIcons/PickConstruction") {
val cityWithNoProductionSet = worldScreen.viewingCiv.cities
.firstOrNull {
!it.isPuppet &&
it.cityConstructions.currentConstructionFromQueue == ""
}
if (cityWithNoProductionSet != null) worldScreen.game.pushScreen(
CityScreen(cityWithNoProductionSet)
)
}
worldScreen.viewingCiv.shouldOpenTechPicker() ->
NextTurnAction("Pick a tech", Color.SKY, "NotificationIcons/PickTech") {
worldScreen.game.pushScreen(
TechPickerScreen(worldScreen.viewingCiv, null, worldScreen.viewingCiv.tech.freeTechs != 0)
)
}
worldScreen.viewingCiv.policies.shouldOpenPolicyPicker
|| worldScreen.viewingCiv.policies.freePolicies > 0 && worldScreen.viewingCiv.policies.canAdoptPolicy() ->
NextTurnAction("Pick a policy", Color.VIOLET, "NotificationIcons/PickPolicy") {
worldScreen.game.pushScreen(PolicyPickerScreen(worldScreen.selectedCiv, worldScreen.canChangeState))
worldScreen.viewingCiv.policies.shouldOpenPolicyPicker = false
}
worldScreen.viewingCiv.religionManager.canFoundOrExpandPantheon() -> {
val displayString = if (worldScreen.viewingCiv.religionManager.religionState == ReligionState.Pantheon)
"Expand Pantheon"
else "Found Pantheon"
NextTurnAction(displayString, Color.valueOf(BeliefType.Pantheon.color),
"NotificationIcons/FoundPantheon") {
worldScreen.game.pushScreen(PantheonPickerScreen(worldScreen.viewingCiv))
}
}
worldScreen.viewingCiv.religionManager.religionState == ReligionState.FoundingReligion ->
NextTurnAction("Found Religion", Color.valueOf(BeliefType.Founder.color),
"NotificationIcons/FoundReligion") {
worldScreen.game.pushScreen(
ReligiousBeliefsPickerScreen(
worldScreen.viewingCiv,
worldScreen.viewingCiv.religionManager.getBeliefsToChooseAtFounding(),
pickIconAndName = true
)
)
}
worldScreen.viewingCiv.religionManager.religionState == ReligionState.EnhancingReligion ->
NextTurnAction("Enhance a Religion", Color.valueOf(BeliefType.Enhancer.color),
"NotificationIcons/EnhanceReligion") {
worldScreen.game.pushScreen(
ReligiousBeliefsPickerScreen(
worldScreen.viewingCiv,
worldScreen.viewingCiv.religionManager.getBeliefsToChooseAtEnhancing(),
pickIconAndName = false
)
)
}
worldScreen.viewingCiv.religionManager.hasFreeBeliefs() ->
NextTurnAction("Reform Religion", Color.valueOf(BeliefType.Enhancer.color),
"NotificationIcons/ReformReligion") {
worldScreen.game.pushScreen(
ReligiousBeliefsPickerScreen(
worldScreen.viewingCiv,
worldScreen.viewingCiv.religionManager.freeBeliefsAsEnums(),
pickIconAndName = false
)
)
}
worldScreen.viewingCiv.mayVoteForDiplomaticVictory() ->
NextTurnAction("Vote for World Leader", Color.MAROON,
"NotificationIcons/WorldCongressVote") {
worldScreen.game.pushScreen(DiplomaticVotePickerScreen(worldScreen.viewingCiv))
}
worldScreen.viewingCiv.units.shouldGoToDueUnit() ->
NextTurnAction("Next unit", Color.LIGHT_GRAY,
"NotificationIcons/NextUnit") { worldScreen.switchToNextUnit() }
!worldScreen.game.settings.automatedUnitsMoveOnTurnStart
&& !worldScreen.viewingCiv.hasMovedAutomatedUnits
&& worldScreen.viewingCiv.units.getCivUnits()
.any { it.currentMovement > Constants.minimumMovementEpsilon && (it.isMoving() || it.isAutomated() || it.isExploring()) } ->
NextTurnAction("Move automated units", Color.LIGHT_GRAY,
"NotificationIcons/MoveAutomatedUnits") {
// Don't allow double-click of 'n' to spawn 2 processes trying to automate units
if (!worldScreen.isPlayersTurn) return@NextTurnAction
worldScreen.isPlayersTurn = false // Disable state changes
worldScreen.viewingCiv.hasMovedAutomatedUnits = true
worldScreen.nextTurnButton.disable()
Concurrency.run("Move automated units") {
for (unit in worldScreen.viewingCiv.units.getCivUnits())
unit.doAction()
launchOnGLThread {
worldScreen.shouldUpdate = true
worldScreen.isPlayersTurn = true //Re-enable state changes
worldScreen.nextTurnButton.enable()
}
}
}
else ->
NextTurnAction("Next turn", Color.WHITE,
"NotificationIcons/NextTurn") {
val action = {
worldScreen.game.settings.addCompletedTutorialTask("Pass a turn")
worldScreen.nextTurn()
}
if (worldScreen.game.settings.confirmNextTurn) {
ConfirmPopup(worldScreen, "Confirm next turn", "Next turn",
true, action = action).open()
} else action()
}
}
}
}
class NextTurnAction(val text: String, val color: Color, val icon: String? = null, val action: () -> Unit) {
companion object Prefabs {
val Default = NextTurnAction("", Color.BLACK) {}
val Working = NextTurnAction(Constants.working, Color.GRAY, "NotificationIcons/Working") {}
val Waiting = NextTurnAction("Waiting for other players...",Color.GRAY, "NotificationIcons/Waiting") {}
}
private fun getNextTurnAction(worldScreen: WorldScreen) =
// Guaranteed to return a non-null NextTurnAction because the last isChoice always returns true
NextTurnAction.values().first { it.isChoice(worldScreen) }
}

View File

@ -10,7 +10,6 @@ import com.unciv.ui.images.ImageGetter
import com.unciv.ui.screens.basescreen.BaseScreen
import com.unciv.ui.screens.worldscreen.WorldScreen
import com.unciv.utils.Concurrency
import com.unciv.utils.Log
class NextTurnProgress(
// nullable so we can free the reference once the ProgressBar is shown