mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-29 06:51:30 -04:00
Random Nations game starter - reactive UI (#9127)
* Random Nations game starter - reactive UI * Random Nations game starter - reactive UI continued * Random Nations game starter - reactive UI - patch
This commit is contained in:
parent
21510a8455
commit
36667d9d18
@ -344,12 +344,16 @@ object GameStarter {
|
|||||||
|
|
||||||
for (player in chosenPlayers) {
|
for (player in chosenPlayers) {
|
||||||
val civ = Civilization(player.chosenCiv)
|
val civ = Civilization(player.chosenCiv)
|
||||||
if (player.chosenCiv in usedMajorCivs) {
|
when (player.chosenCiv) {
|
||||||
|
Constants.spectator ->
|
||||||
|
civ.playerType = player.playerType
|
||||||
|
in usedMajorCivs -> {
|
||||||
for (tech in startingTechs)
|
for (tech in startingTechs)
|
||||||
civ.tech.techsResearched.add(tech.name) // can't be .addTechnology because the civInfo isn't assigned yet
|
civ.tech.techsResearched.add(tech.name) // can't be .addTechnology because the civInfo isn't assigned yet
|
||||||
civ.playerType = player.playerType
|
civ.playerType = player.playerType
|
||||||
civ.playerId = player.playerId
|
civ.playerId = player.playerId
|
||||||
} else {
|
}
|
||||||
|
else ->
|
||||||
if (!civ.cityStateFunctions.initCityState(ruleset, newGameParameters.startingEra, unusedMajorCivs))
|
if (!civ.cityStateFunctions.initCityState(ruleset, newGameParameters.startingEra, unusedMajorCivs))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -4,5 +4,6 @@ import com.unciv.logic.IsPartOfGameInfoSerialization
|
|||||||
|
|
||||||
enum class PlayerType : IsPartOfGameInfoSerialization {
|
enum class PlayerType : IsPartOfGameInfoSerialization {
|
||||||
AI,
|
AI,
|
||||||
Human
|
Human;
|
||||||
|
fun toggle() = if (this == AI) Human else AI
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package com.unciv.models.ruleset.nation
|
package com.unciv.models.ruleset.nation
|
||||||
|
|
||||||
import com.badlogic.gdx.graphics.Color
|
import com.badlogic.gdx.graphics.Color
|
||||||
import com.unciv.Constants
|
import com.unciv.Constants
|
||||||
@ -15,9 +15,9 @@ import com.unciv.ui.screens.civilopediascreen.CivilopediaScreen.Companion.showRe
|
|||||||
import com.unciv.ui.screens.civilopediascreen.FormattedLine
|
import com.unciv.ui.screens.civilopediascreen.FormattedLine
|
||||||
import kotlin.math.pow
|
import kotlin.math.pow
|
||||||
|
|
||||||
class Nation : RulesetObject() {
|
class Nation : RulesetObject() {
|
||||||
var leaderName = ""
|
var leaderName = ""
|
||||||
fun getLeaderDisplayName() = if (isCityState) name
|
fun getLeaderDisplayName() = if (isCityState || isSpectator) name
|
||||||
else "[$leaderName] of [$name]"
|
else "[$leaderName] of [$name]"
|
||||||
|
|
||||||
val style = ""
|
val style = ""
|
||||||
@ -36,7 +36,6 @@ import kotlin.math.pow
|
|||||||
|
|
||||||
lateinit var outerColor: List<Int>
|
lateinit var outerColor: List<Int>
|
||||||
var uniqueName = ""
|
var uniqueName = ""
|
||||||
override fun getUniqueTarget() = UniqueTarget.Nation
|
|
||||||
var uniqueText = ""
|
var uniqueText = ""
|
||||||
var innerColor: List<Int>? = null
|
var innerColor: List<Int>? = null
|
||||||
var startBias = ArrayList<String>()
|
var startBias = ArrayList<String>()
|
||||||
@ -52,6 +51,10 @@ import kotlin.math.pow
|
|||||||
|
|
||||||
var favoredReligion: String? = null
|
var favoredReligion: String? = null
|
||||||
|
|
||||||
|
var cities: ArrayList<String> = arrayListOf()
|
||||||
|
|
||||||
|
override fun getUniqueTarget() = UniqueTarget.Nation
|
||||||
|
|
||||||
@Transient
|
@Transient
|
||||||
private lateinit var outerColorObject: Color
|
private lateinit var outerColorObject: Color
|
||||||
fun getOuterColor(): Color = outerColorObject
|
fun getOuterColor(): Color = outerColorObject
|
||||||
@ -84,8 +87,6 @@ import kotlin.math.pow
|
|||||||
ignoreHillMovementCost = uniques.contains("Units ignore terrain costs when moving into any tile with Hills")
|
ignoreHillMovementCost = uniques.contains("Units ignore terrain costs when moving into any tile with Hills")
|
||||||
}
|
}
|
||||||
|
|
||||||
var cities: ArrayList<String> = arrayListOf()
|
|
||||||
|
|
||||||
|
|
||||||
override fun makeLink() = "Nation/$name"
|
override fun makeLink() = "Nation/$name"
|
||||||
override fun getSortGroup(ruleset: Ruleset) = when {
|
override fun getSortGroup(ruleset: Ruleset) = when {
|
||||||
@ -305,12 +306,12 @@ import kotlin.math.pow
|
|||||||
else -> uniques.contains(filter)
|
else -> uniques.contains(filter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** All defined by https://www.w3.org/TR/WCAG20/#relativeluminancedef */
|
/** All defined by https://www.w3.org/TR/WCAG20/#relativeluminancedef */
|
||||||
fun getRelativeLuminance(color:Color):Double{
|
fun getRelativeLuminance(color: Color): Double {
|
||||||
fun getRelativeChannelLuminance(channel:Float):Double =
|
fun getRelativeChannelLuminance(channel: Float): Double =
|
||||||
if (channel < 0.03928) channel / 12.92
|
if (channel < 0.03928) channel / 12.92
|
||||||
else ((channel + 0.055) / 1.055).pow(2.4)
|
else ((channel + 0.055) / 1.055).pow(2.4)
|
||||||
|
|
||||||
@ -319,13 +320,14 @@ import kotlin.math.pow
|
|||||||
val B = getRelativeChannelLuminance(color.b)
|
val B = getRelativeChannelLuminance(color.b)
|
||||||
|
|
||||||
return 0.2126 * R + 0.7152 * G + 0.0722 * B
|
return 0.2126 * R + 0.7152 * G + 0.0722 * B
|
||||||
}
|
}
|
||||||
|
|
||||||
/** https://www.w3.org/TR/WCAG20/#contrast-ratiodef */
|
/** https://www.w3.org/TR/WCAG20/#contrast-ratiodef */
|
||||||
fun getContrastRatio(color1:Color, color2:Color): Double { // ratio can range from 1 to 21
|
fun getContrastRatio(color1: Color, color2: Color): Double { // ratio can range from 1 to 21
|
||||||
val innerColorLuminance = getRelativeLuminance(color1)
|
val innerColorLuminance = getRelativeLuminance(color1)
|
||||||
val outerColorLuminance = getRelativeLuminance(color2)
|
val outerColorLuminance = getRelativeLuminance(color2)
|
||||||
|
|
||||||
return if (innerColorLuminance > outerColorLuminance) (innerColorLuminance + 0.05) / (outerColorLuminance + 0.05)
|
return if (innerColorLuminance > outerColorLuminance)
|
||||||
|
(innerColorLuminance + 0.05) / (outerColorLuminance + 0.05)
|
||||||
else (outerColorLuminance + 0.05) / (innerColorLuminance + 0.05)
|
else (outerColorLuminance + 0.05) / (innerColorLuminance + 0.05)
|
||||||
}
|
}
|
||||||
|
@ -48,15 +48,15 @@ private class RestorableTextButtonStyle(
|
|||||||
val restoreStyle: ButtonStyle
|
val restoreStyle: ButtonStyle
|
||||||
) : TextButtonStyle(baseStyle)
|
) : TextButtonStyle(baseStyle)
|
||||||
|
|
||||||
/** Disable a [Button] by setting its [touchable][Button.touchable] and [color][Button.color] properties. */
|
/** Disable a [Button] by setting its [touchable][Button.touchable] and [style][Button.style] properties. */
|
||||||
fun Button.disable() {
|
fun Button.disable() {
|
||||||
touchable = Touchable.disabled
|
touchable = Touchable.disabled
|
||||||
val oldStyle = style
|
val oldStyle = style
|
||||||
|
if (oldStyle is RestorableTextButtonStyle) return
|
||||||
val disabledStyle = BaseScreen.skin.get("disabled", TextButtonStyle::class.java)
|
val disabledStyle = BaseScreen.skin.get("disabled", TextButtonStyle::class.java)
|
||||||
if (oldStyle !is RestorableTextButtonStyle)
|
|
||||||
style = RestorableTextButtonStyle(disabledStyle, oldStyle)
|
style = RestorableTextButtonStyle(disabledStyle, oldStyle)
|
||||||
}
|
}
|
||||||
/** Enable a [Button] by setting its [touchable][Button.touchable] and [color][Button.color] properties. */
|
/** Enable a [Button] by setting its [touchable][Button.touchable] and [style][Button.style] properties. */
|
||||||
fun Button.enable() {
|
fun Button.enable() {
|
||||||
val oldStyle = style
|
val oldStyle = style
|
||||||
if (oldStyle is RestorableTextButtonStyle) {
|
if (oldStyle is RestorableTextButtonStyle) {
|
||||||
@ -64,7 +64,7 @@ fun Button.enable() {
|
|||||||
}
|
}
|
||||||
touchable = Touchable.enabled
|
touchable = Touchable.enabled
|
||||||
}
|
}
|
||||||
/** Enable or disable a [Button] by setting its [touchable][Button.touchable] and [color][Button.color] properties,
|
/** Enable or disable a [Button] by setting its [touchable][Button.touchable] and [style][Button.style] properties,
|
||||||
* or returns the corresponding state.
|
* or returns the corresponding state.
|
||||||
*
|
*
|
||||||
* Do not confuse with Gdx' builtin [isDisabled][Button.isDisabled] property,
|
* Do not confuse with Gdx' builtin [isDisabled][Button.isDisabled] property,
|
||||||
|
@ -299,7 +299,7 @@ class MapEditorEditStartsTab(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun allowedNations() = ruleset.nations.values.asSequence()
|
private fun allowedNations() = ruleset.nations.values.asSequence()
|
||||||
.filter { it.name !in disallowNations }
|
.filter { it.name !in disallowNations && !it.hasUnique(UniqueType.CityStateDeprecated) }
|
||||||
private fun getNations() = allowedNations()
|
private fun getNations() = allowedNations()
|
||||||
.sortedWith(compareBy<Nation>{ it.isCityState }.thenBy(collator) { it.name.tr() })
|
.sortedWith(compareBy<Nation>{ it.isCityState }.thenBy(collator) { it.name.tr() })
|
||||||
.map { FormattedLine("[${it.name}] starting location", it.name, "Nation/${it.name}", size = 24) }
|
.map { FormattedLine("[${it.name}] starting location", it.name, "Nation/${it.name}", size = 24) }
|
||||||
|
@ -5,8 +5,11 @@ import com.badlogic.gdx.scenes.scene2d.Touchable
|
|||||||
import com.badlogic.gdx.scenes.scene2d.ui.CheckBox
|
import com.badlogic.gdx.scenes.scene2d.ui.CheckBox
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||||
import com.badlogic.gdx.utils.Align
|
import com.badlogic.gdx.utils.Align
|
||||||
|
import com.unciv.Constants
|
||||||
import com.unciv.UncivGame
|
import com.unciv.UncivGame
|
||||||
|
import com.unciv.logic.civilization.PlayerType
|
||||||
import com.unciv.models.metadata.GameParameters
|
import com.unciv.models.metadata.GameParameters
|
||||||
|
import com.unciv.models.metadata.Player
|
||||||
import com.unciv.models.ruleset.RulesetCache
|
import com.unciv.models.ruleset.RulesetCache
|
||||||
import com.unciv.models.ruleset.nation.Nation
|
import com.unciv.models.ruleset.nation.Nation
|
||||||
import com.unciv.models.ruleset.unique.UniqueType
|
import com.unciv.models.ruleset.unique.UniqueType
|
||||||
@ -31,11 +34,13 @@ import com.unciv.ui.popups.Popup
|
|||||||
import com.unciv.ui.popups.ToastPopup
|
import com.unciv.ui.popups.ToastPopup
|
||||||
import com.unciv.ui.screens.basescreen.BaseScreen
|
import com.unciv.ui.screens.basescreen.BaseScreen
|
||||||
import com.unciv.ui.screens.multiplayerscreens.MultiplayerHelpers
|
import com.unciv.ui.screens.multiplayerscreens.MultiplayerHelpers
|
||||||
|
import kotlin.reflect.KMutableProperty0
|
||||||
|
|
||||||
class GameOptionsTable(
|
class GameOptionsTable(
|
||||||
private val previousScreen: IPreviousScreen,
|
private val previousScreen: IPreviousScreen,
|
||||||
private val isPortrait: Boolean = false,
|
private val isPortrait: Boolean = false,
|
||||||
private val updatePlayerPickerTable: (desiredCiv:String)->Unit
|
private val updatePlayerPickerTable: (desiredCiv: String) -> Unit,
|
||||||
|
private val updatePlayerPickerRandomLabel: () -> Unit
|
||||||
) : Table(BaseScreen.skin) {
|
) : Table(BaseScreen.skin) {
|
||||||
var gameParameters = previousScreen.gameSetupInfo.gameParameters
|
var gameParameters = previousScreen.gameSetupInfo.gameParameters
|
||||||
val ruleset = previousScreen.ruleset
|
val ruleset = previousScreen.ruleset
|
||||||
@ -77,12 +82,10 @@ class GameOptionsTable(
|
|||||||
if (turnSlider != null)
|
if (turnSlider != null)
|
||||||
add(turnSlider).padTop(10f).row()
|
add(turnSlider).padTop(10f).row()
|
||||||
if (gameParameters.randomNumberOfPlayers) {
|
if (gameParameters.randomNumberOfPlayers) {
|
||||||
addMinPlayersSlider()
|
addMinMaxPlayersSliders()
|
||||||
addMaxPlayersSlider()
|
|
||||||
}
|
}
|
||||||
if (gameParameters.randomNumberOfCityStates) {
|
if (gameParameters.randomNumberOfCityStates) {
|
||||||
addMinCityStatesSlider()
|
addMinMaxCityStatesSliders()
|
||||||
addMaxCityStatesSlider()
|
|
||||||
} else {
|
} else {
|
||||||
addCityStatesSlider()
|
addCityStatesSlider()
|
||||||
}
|
}
|
||||||
@ -204,7 +207,7 @@ class GameOptionsTable(
|
|||||||
add(button)
|
add(button)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun numberOfPlayable() = ruleset.nations.values.count {
|
private fun numberOfMajorCivs() = ruleset.nations.values.count {
|
||||||
it.isMajorCiv
|
it.isMajorCiv
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -218,64 +221,101 @@ class GameOptionsTable(
|
|||||||
|
|
||||||
private fun Table.addRandomPlayersCheckbox() =
|
private fun Table.addRandomPlayersCheckbox() =
|
||||||
addCheckbox("Random number of Civilizations", gameParameters.randomNumberOfPlayers)
|
addCheckbox("Random number of Civilizations", gameParameters.randomNumberOfPlayers)
|
||||||
{
|
{newRandomNumberOfPlayers ->
|
||||||
gameParameters.randomNumberOfPlayers = it
|
gameParameters.randomNumberOfPlayers = newRandomNumberOfPlayers
|
||||||
|
if (newRandomNumberOfPlayers) {
|
||||||
|
// remove all random AI from player picker
|
||||||
|
val newPlayers = gameParameters.players.asSequence()
|
||||||
|
.filterNot { it.playerType == PlayerType.AI && it.chosenCiv == Constants.random }
|
||||||
|
.toCollection(ArrayList(gameParameters.players.size))
|
||||||
|
if (newPlayers.size != gameParameters.players.size) {
|
||||||
|
gameParameters.players = newPlayers
|
||||||
|
updatePlayerPickerTable("")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Fill up player picker with random AI until previously active min reached
|
||||||
|
val additionalRandom = gameParameters.minNumberOfPlayers - gameParameters.players.size
|
||||||
|
if (additionalRandom > 0) {
|
||||||
|
repeat(additionalRandom) {
|
||||||
|
gameParameters.players.add(Player(Constants.random))
|
||||||
|
}
|
||||||
|
updatePlayerPickerTable("")
|
||||||
|
}
|
||||||
|
}
|
||||||
update() // To see the new sliders
|
update() // To see the new sliders
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Table.addRandomCityStatesCheckbox() =
|
private fun Table.addRandomCityStatesCheckbox() =
|
||||||
addCheckbox("Random number of City-States", gameParameters.randomNumberOfCityStates)
|
addCheckbox("Random number of City-States", gameParameters.randomNumberOfCityStates)
|
||||||
{
|
{
|
||||||
gameParameters.randomNumberOfCityStates = it
|
gameParameters.run {
|
||||||
|
randomNumberOfCityStates = it
|
||||||
|
if (it) {
|
||||||
|
if (numberOfCityStates > maxNumberOfCityStates)
|
||||||
|
maxNumberOfCityStates = numberOfCityStates
|
||||||
|
if (numberOfCityStates < minNumberOfCityStates)
|
||||||
|
minNumberOfCityStates = numberOfCityStates
|
||||||
|
} else {
|
||||||
|
if (numberOfCityStates > maxNumberOfCityStates)
|
||||||
|
numberOfCityStates = maxNumberOfCityStates
|
||||||
|
if (numberOfCityStates < minNumberOfCityStates)
|
||||||
|
numberOfCityStates = minNumberOfCityStates
|
||||||
|
}
|
||||||
|
}
|
||||||
update() // To see the changed sliders
|
update() // To see the changed sliders
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Table.addMinPlayersSlider() {
|
private fun Table.addLinkedMinMaxSliders(
|
||||||
val playableAvailable = numberOfPlayable()
|
minValue: Int, maxValue: Int,
|
||||||
if (playableAvailable == 0) return
|
minText: String, maxText: String,
|
||||||
|
minField: KMutableProperty0<Int>,
|
||||||
|
maxField: KMutableProperty0<Int>,
|
||||||
|
onChangeCallback: (() -> Unit)? = null
|
||||||
|
) {
|
||||||
|
if (maxValue < minValue) return
|
||||||
|
|
||||||
add("{Min number of Civilizations}:".toLabel()).left().expandX()
|
@Suppress("JoinDeclarationAndAssignment") // it's a forward declaration!
|
||||||
val slider = UncivSlider(2f, playableAvailable.toFloat(), 1f, initial = gameParameters.minNumberOfPlayers.toFloat()) {
|
lateinit var maxSlider: UncivSlider // lateinit safe because the closure won't use it until the user operates a slider
|
||||||
gameParameters.minNumberOfPlayers = it.toInt()
|
val minSlider = UncivSlider(minValue.toFloat(), maxValue.toFloat(), 1f, initial = minField.get().toFloat()) {
|
||||||
|
val newMin = it.toInt()
|
||||||
|
minField.set(newMin)
|
||||||
|
if (newMin > maxSlider.value.toInt()) {
|
||||||
|
maxSlider.value = it
|
||||||
|
maxField.set(newMin)
|
||||||
}
|
}
|
||||||
slider.isDisabled = locked
|
onChangeCallback?.invoke()
|
||||||
add(slider).padTop(10f).row()
|
}
|
||||||
|
minSlider.isDisabled = locked
|
||||||
|
maxSlider = UncivSlider(minValue.toFloat(), maxValue.toFloat(), 1f, initial = maxField.get().toFloat()) {
|
||||||
|
val newMax = it.toInt()
|
||||||
|
maxField.set(newMax)
|
||||||
|
if (newMax < minSlider.value.toInt()) {
|
||||||
|
minSlider.value = it
|
||||||
|
minField.set(newMax)
|
||||||
|
}
|
||||||
|
onChangeCallback?.invoke()
|
||||||
|
}
|
||||||
|
maxSlider.isDisabled = locked
|
||||||
|
|
||||||
|
add(minText.toLabel()).left().expandX()
|
||||||
|
add(minSlider).padTop(10f).row()
|
||||||
|
add(maxText.toLabel()).left().expandX()
|
||||||
|
add(maxSlider).padTop(10f).row()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Table.addMaxPlayersSlider() {
|
private fun Table.addMinMaxPlayersSliders() {
|
||||||
val playableAvailable = numberOfPlayable()
|
addLinkedMinMaxSliders(2, numberOfMajorCivs(),
|
||||||
if (playableAvailable == 0) return
|
"{Min number of Civilizations}:", "{Max number of Civilizations}:",
|
||||||
|
gameParameters::minNumberOfPlayers, gameParameters::maxNumberOfPlayers,
|
||||||
add("{Max number of Civilizations}:".toLabel()).left().expandX()
|
updatePlayerPickerRandomLabel
|
||||||
val slider = UncivSlider(2f, playableAvailable.toFloat(), 1f, initial = gameParameters.maxNumberOfPlayers.toFloat()) {
|
)
|
||||||
gameParameters.maxNumberOfPlayers = it.toInt()
|
|
||||||
}
|
|
||||||
slider.isDisabled = locked
|
|
||||||
add(slider).padTop(10f).row()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Table.addMinCityStatesSlider() {
|
private fun Table.addMinMaxCityStatesSliders() {
|
||||||
val cityStatesAvailable = numberOfCityStates()
|
addLinkedMinMaxSliders( 0, numberOfCityStates(),
|
||||||
if (cityStatesAvailable == 0) return
|
"{Min number of City-States}:", "{Max number of City-States}:",
|
||||||
|
gameParameters::minNumberOfCityStates, gameParameters::maxNumberOfCityStates
|
||||||
add("{Min number of City-States}:".toLabel()).left().expandX()
|
)
|
||||||
val slider = UncivSlider(0f, cityStatesAvailable.toFloat(), 1f, initial = gameParameters.minNumberOfCityStates.toFloat()) {
|
|
||||||
gameParameters.minNumberOfCityStates = it.toInt()
|
|
||||||
}
|
|
||||||
slider.isDisabled = locked
|
|
||||||
add(slider).padTop(10f).row()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun Table.addMaxCityStatesSlider() {
|
|
||||||
val cityStatesAvailable = numberOfCityStates()
|
|
||||||
if (cityStatesAvailable == 0) return
|
|
||||||
|
|
||||||
add("{Max number of City-States}:".toLabel()).left().expandX()
|
|
||||||
val slider = UncivSlider(0f, cityStatesAvailable.toFloat(), 1f, initial = gameParameters.maxNumberOfCityStates.toFloat()) {
|
|
||||||
gameParameters.maxNumberOfCityStates = it.toInt()
|
|
||||||
}
|
|
||||||
slider.isDisabled = locked
|
|
||||||
add(slider).padTop(10f).row()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Table.addCityStatesSlider() {
|
private fun Table.addCityStatesSlider() {
|
||||||
|
@ -11,22 +11,15 @@ import com.unciv.UncivGame
|
|||||||
import com.unciv.logic.GameInfo
|
import com.unciv.logic.GameInfo
|
||||||
import com.unciv.logic.GameStarter
|
import com.unciv.logic.GameStarter
|
||||||
import com.unciv.logic.IdChecker
|
import com.unciv.logic.IdChecker
|
||||||
import com.unciv.logic.files.MapSaver
|
|
||||||
import com.unciv.logic.civilization.PlayerType
|
import com.unciv.logic.civilization.PlayerType
|
||||||
|
import com.unciv.logic.files.MapSaver
|
||||||
import com.unciv.logic.map.MapGeneratedMainType
|
import com.unciv.logic.map.MapGeneratedMainType
|
||||||
import com.unciv.logic.multiplayer.OnlineMultiplayer
|
import com.unciv.logic.multiplayer.OnlineMultiplayer
|
||||||
import com.unciv.logic.multiplayer.storage.FileStorageRateLimitReached
|
import com.unciv.logic.multiplayer.storage.FileStorageRateLimitReached
|
||||||
import com.unciv.models.metadata.GameSetupInfo
|
import com.unciv.models.metadata.GameSetupInfo
|
||||||
import com.unciv.models.ruleset.RulesetCache
|
import com.unciv.models.ruleset.RulesetCache
|
||||||
import com.unciv.models.translations.tr
|
import com.unciv.models.translations.tr
|
||||||
import com.unciv.ui.images.ImageGetter
|
|
||||||
import com.unciv.ui.screens.pickerscreens.PickerScreen
|
|
||||||
import com.unciv.ui.popups.ConfirmPopup
|
|
||||||
import com.unciv.ui.popups.Popup
|
|
||||||
import com.unciv.ui.popups.ToastPopup
|
|
||||||
import com.unciv.ui.screens.basescreen.BaseScreen
|
|
||||||
import com.unciv.ui.components.ExpanderTab
|
import com.unciv.ui.components.ExpanderTab
|
||||||
import com.unciv.ui.screens.basescreen.RecreateOnResize
|
|
||||||
import com.unciv.ui.components.extensions.addSeparator
|
import com.unciv.ui.components.extensions.addSeparator
|
||||||
import com.unciv.ui.components.extensions.addSeparatorVertical
|
import com.unciv.ui.components.extensions.addSeparatorVertical
|
||||||
import com.unciv.ui.components.extensions.disable
|
import com.unciv.ui.components.extensions.disable
|
||||||
@ -35,12 +28,19 @@ import com.unciv.ui.components.extensions.onClick
|
|||||||
import com.unciv.ui.components.extensions.pad
|
import com.unciv.ui.components.extensions.pad
|
||||||
import com.unciv.ui.components.extensions.toLabel
|
import com.unciv.ui.components.extensions.toLabel
|
||||||
import com.unciv.ui.components.extensions.toTextButton
|
import com.unciv.ui.components.extensions.toTextButton
|
||||||
|
import com.unciv.ui.images.ImageGetter
|
||||||
|
import com.unciv.ui.popups.ConfirmPopup
|
||||||
|
import com.unciv.ui.popups.Popup
|
||||||
|
import com.unciv.ui.popups.ToastPopup
|
||||||
|
import com.unciv.ui.screens.basescreen.BaseScreen
|
||||||
|
import com.unciv.ui.screens.basescreen.RecreateOnResize
|
||||||
|
import com.unciv.ui.screens.pickerscreens.PickerScreen
|
||||||
import com.unciv.utils.Log
|
import com.unciv.utils.Log
|
||||||
import com.unciv.utils.concurrency.Concurrency
|
import com.unciv.utils.concurrency.Concurrency
|
||||||
import com.unciv.utils.concurrency.launchOnGLThread
|
import com.unciv.utils.concurrency.launchOnGLThread
|
||||||
import kotlinx.coroutines.coroutineScope
|
import kotlinx.coroutines.coroutineScope
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
import java.util.*
|
import java.util.UUID
|
||||||
import com.unciv.ui.components.AutoScrollPane as ScrollPane
|
import com.unciv.ui.components.AutoScrollPane as ScrollPane
|
||||||
|
|
||||||
class NewGameScreen(
|
class NewGameScreen(
|
||||||
@ -54,6 +54,8 @@ class NewGameScreen(
|
|||||||
private val mapOptionsTable: MapOptionsTable
|
private val mapOptionsTable: MapOptionsTable
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
val isPortrait = isNarrowerThan4to3()
|
||||||
|
|
||||||
updateRuleset() // must come before playerPickerTable so mod nations from fromSettings
|
updateRuleset() // must come before playerPickerTable so mod nations from fromSettings
|
||||||
// Has to be initialized before the mapOptionsTable, since the mapOptionsTable refers to it on init
|
// Has to be initialized before the mapOptionsTable, since the mapOptionsTable refers to it on init
|
||||||
|
|
||||||
@ -65,13 +67,17 @@ class NewGameScreen(
|
|||||||
|
|
||||||
playerPickerTable = PlayerPickerTable(
|
playerPickerTable = PlayerPickerTable(
|
||||||
this, gameSetupInfo.gameParameters,
|
this, gameSetupInfo.gameParameters,
|
||||||
if (isNarrowerThan4to3()) stage.width - 20f else 0f
|
if (isPortrait) stage.width - 20f else 0f
|
||||||
|
)
|
||||||
|
newGameOptionsTable = GameOptionsTable(
|
||||||
|
this, isPortrait,
|
||||||
|
updatePlayerPickerTable = { desiredCiv -> playerPickerTable.update(desiredCiv) },
|
||||||
|
updatePlayerPickerRandomLabel = { playerPickerTable.updateRandomNumberLabel() }
|
||||||
)
|
)
|
||||||
newGameOptionsTable = GameOptionsTable(this, isNarrowerThan4to3()) { desiredCiv: String -> playerPickerTable.update(desiredCiv) }
|
|
||||||
mapOptionsTable = MapOptionsTable(this)
|
mapOptionsTable = MapOptionsTable(this)
|
||||||
setDefaultCloseAction()
|
setDefaultCloseAction()
|
||||||
|
|
||||||
if (isNarrowerThan4to3()) initPortrait()
|
if (isPortrait) initPortrait()
|
||||||
else initLandscape()
|
else initLandscape()
|
||||||
|
|
||||||
pickerPane.bottomTable.background = skinStrings.getUiBackground("NewGameScreen/BottomTable", tintColor = skinStrings.skinConfig.clearColor)
|
pickerPane.bottomTable.background = skinStrings.getUiBackground("NewGameScreen/BottomTable", tintColor = skinStrings.skinConfig.clearColor)
|
||||||
@ -94,7 +100,10 @@ class NewGameScreen(
|
|||||||
|
|
||||||
rightSideButton.enable()
|
rightSideButton.enable()
|
||||||
rightSideButton.setText("Start game!".tr())
|
rightSideButton.setText("Start game!".tr())
|
||||||
rightSideButton.onClick {
|
rightSideButton.onClick(this::onStartGameClicked)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onStartGameClicked() {
|
||||||
if (gameSetupInfo.gameParameters.isOnlineMultiplayer) {
|
if (gameSetupInfo.gameParameters.isOnlineMultiplayer) {
|
||||||
if (!checkConnectionToMultiplayerServer()) {
|
if (!checkConnectionToMultiplayerServer()) {
|
||||||
val noInternetConnectionPopup = Popup(this)
|
val noInternetConnectionPopup = Popup(this)
|
||||||
@ -102,7 +111,7 @@ class NewGameScreen(
|
|||||||
noInternetConnectionPopup.addGoodSizedLabel(label.tr()).row()
|
noInternetConnectionPopup.addGoodSizedLabel(label.tr()).row()
|
||||||
noInternetConnectionPopup.addCloseButton()
|
noInternetConnectionPopup.addCloseButton()
|
||||||
noInternetConnectionPopup.open()
|
noInternetConnectionPopup.open()
|
||||||
return@onClick
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for (player in gameSetupInfo.gameParameters.players.filter { it.playerType == PlayerType.Human }) {
|
for (player in gameSetupInfo.gameParameters.players.filter { it.playerType == PlayerType.Human }) {
|
||||||
@ -113,7 +122,7 @@ class NewGameScreen(
|
|||||||
invalidPlayerIdPopup.addGoodSizedLabel("Invalid player ID!".tr()).row()
|
invalidPlayerIdPopup.addGoodSizedLabel("Invalid player ID!".tr()).row()
|
||||||
invalidPlayerIdPopup.addCloseButton()
|
invalidPlayerIdPopup.addCloseButton()
|
||||||
invalidPlayerIdPopup.open()
|
invalidPlayerIdPopup.open()
|
||||||
return@onClick
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,7 +132,7 @@ class NewGameScreen(
|
|||||||
notAllowedToSpectate.addGoodSizedLabel("You are not allowed to spectate!".tr()).row()
|
notAllowedToSpectate.addGoodSizedLabel("You are not allowed to spectate!".tr()).row()
|
||||||
notAllowedToSpectate.addCloseButton()
|
notAllowedToSpectate.addCloseButton()
|
||||||
notAllowedToSpectate.open()
|
notAllowedToSpectate.open()
|
||||||
return@onClick
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -138,7 +147,7 @@ class NewGameScreen(
|
|||||||
noHumanPlayersPopup.addGoodSizedLabel("No human players selected!".tr()).row()
|
noHumanPlayersPopup.addGoodSizedLabel("No human players selected!".tr()).row()
|
||||||
noHumanPlayersPopup.addCloseButton()
|
noHumanPlayersPopup.addCloseButton()
|
||||||
noHumanPlayersPopup.open()
|
noHumanPlayersPopup.open()
|
||||||
return@onClick
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gameSetupInfo.gameParameters.victoryTypes.isEmpty()) {
|
if (gameSetupInfo.gameParameters.victoryTypes.isEmpty()) {
|
||||||
@ -146,7 +155,7 @@ class NewGameScreen(
|
|||||||
noVictoryTypesPopup.addGoodSizedLabel("No victory conditions were selected!".tr()).row()
|
noVictoryTypesPopup.addGoodSizedLabel("No victory conditions were selected!".tr()).row()
|
||||||
noVictoryTypesPopup.addCloseButton()
|
noVictoryTypesPopup.addCloseButton()
|
||||||
noVictoryTypesPopup.open()
|
noVictoryTypesPopup.open()
|
||||||
return@onClick
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
Gdx.input.inputProcessor = null // remove input processing - nothing will be clicked!
|
Gdx.input.inputProcessor = null // remove input processing - nothing will be clicked!
|
||||||
@ -157,7 +166,7 @@ class NewGameScreen(
|
|||||||
} catch (ex: Throwable) {
|
} catch (ex: Throwable) {
|
||||||
Gdx.input.inputProcessor = stage
|
Gdx.input.inputProcessor = stage
|
||||||
ToastPopup("Could not load map!", this)
|
ToastPopup("Could not load map!", this)
|
||||||
return@onClick
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val rulesetIncompatibilities = map.getRulesetIncompatibility(ruleset)
|
val rulesetIncompatibilities = map.getRulesetIncompatibility(ruleset)
|
||||||
@ -169,7 +178,7 @@ class NewGameScreen(
|
|||||||
incompatibleMap.addCloseButton()
|
incompatibleMap.addCloseButton()
|
||||||
incompatibleMap.open()
|
incompatibleMap.open()
|
||||||
Gdx.input.inputProcessor = stage
|
Gdx.input.inputProcessor = stage
|
||||||
return@onClick
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Generated map - check for sensible dimensions and if exceeded correct them and notify user
|
// Generated map - check for sensible dimensions and if exceeded correct them and notify user
|
||||||
@ -183,7 +192,7 @@ class NewGameScreen(
|
|||||||
customMapHeight.text = mapSize.height.toString()
|
customMapHeight.text = mapSize.height.toString()
|
||||||
}
|
}
|
||||||
Gdx.input.inputProcessor = stage
|
Gdx.input.inputProcessor = stage
|
||||||
return@onClick
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,7 +205,6 @@ class NewGameScreen(
|
|||||||
startNewGame()
|
startNewGame()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private fun initLandscape() {
|
private fun initLandscape() {
|
||||||
scrollPane.setScrollingDisabled(true,true)
|
scrollPane.setScrollingDisabled(true,true)
|
||||||
|
@ -11,6 +11,7 @@ import com.unciv.logic.IdChecker
|
|||||||
import com.unciv.logic.civilization.PlayerType
|
import com.unciv.logic.civilization.PlayerType
|
||||||
import com.unciv.logic.multiplayer.FriendList
|
import com.unciv.logic.multiplayer.FriendList
|
||||||
import com.unciv.models.metadata.GameParameters
|
import com.unciv.models.metadata.GameParameters
|
||||||
|
import com.unciv.models.metadata.GameSetupInfo
|
||||||
import com.unciv.models.metadata.Player
|
import com.unciv.models.metadata.Player
|
||||||
import com.unciv.models.ruleset.Ruleset
|
import com.unciv.models.ruleset.Ruleset
|
||||||
import com.unciv.models.ruleset.nation.Nation
|
import com.unciv.models.ruleset.nation.Nation
|
||||||
@ -19,6 +20,7 @@ import com.unciv.ui.audio.MusicMood
|
|||||||
import com.unciv.ui.audio.MusicTrackChooserFlags
|
import com.unciv.ui.audio.MusicTrackChooserFlags
|
||||||
import com.unciv.ui.components.KeyCharAndCode
|
import com.unciv.ui.components.KeyCharAndCode
|
||||||
import com.unciv.ui.components.UncivTextField
|
import com.unciv.ui.components.UncivTextField
|
||||||
|
import com.unciv.ui.components.WrappableLabel
|
||||||
import com.unciv.ui.components.extensions.*
|
import com.unciv.ui.components.extensions.*
|
||||||
import com.unciv.ui.images.ImageGetter
|
import com.unciv.ui.images.ImageGetter
|
||||||
import com.unciv.ui.popups.Popup
|
import com.unciv.ui.popups.Popup
|
||||||
@ -44,12 +46,13 @@ class PlayerPickerTable(
|
|||||||
blockWidth: Float = 0f
|
blockWidth: Float = 0f
|
||||||
): Table() {
|
): Table() {
|
||||||
val playerListTable = Table()
|
val playerListTable = Table()
|
||||||
val civBlocksWidth = if(blockWidth <= 10f) previousScreen.stage.width / 3 - 5f else blockWidth
|
val civBlocksWidth = if (blockWidth <= 10f) previousScreen.stage.width / 3 - 5f else blockWidth
|
||||||
|
private var randomNumberLabel: WrappableLabel? = null
|
||||||
|
|
||||||
/** Locks player table for editing, currently unused, was previously used for scenarios and could be useful in the future.*/
|
/** Locks player table for editing, currently unused, was previously used for scenarios and could be useful in the future. */
|
||||||
var locked = false
|
var locked = false
|
||||||
|
|
||||||
/** No random civilization is available, used during map editing.*/
|
/** No random civilization is available, potentially used in the future during map editing. */
|
||||||
var noRandom = false
|
var noRandom = false
|
||||||
|
|
||||||
private val friendList = FriendList()
|
private val friendList = FriendList()
|
||||||
@ -82,27 +85,47 @@ class PlayerPickerTable(
|
|||||||
for (player in gameParameters.players) {
|
for (player in gameParameters.players) {
|
||||||
playerListTable.add(getPlayerTable(player)).width(civBlocksWidth).padBottom(20f).row()
|
playerListTable.add(getPlayerTable(player)).width(civBlocksWidth).padBottom(20f).row()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val isRandomNumberOfPlayers = gameParameters.randomNumberOfPlayers
|
||||||
|
if (isRandomNumberOfPlayers) {
|
||||||
|
randomNumberLabel = WrappableLabel("", civBlocksWidth - 20f, Color.GOLD)
|
||||||
|
playerListTable.add(randomNumberLabel).fillX().pad(0f, 10f, 20f, 10f).row()
|
||||||
|
updateRandomNumberLabel()
|
||||||
|
}
|
||||||
|
|
||||||
if (!locked && gameParameters.players.size < gameBasics.nations.values.count { it.isMajorCiv }) {
|
if (!locked && gameParameters.players.size < gameBasics.nations.values.count { it.isMajorCiv }) {
|
||||||
val addPlayerButton = "+".toLabel(Color.BLACK, 30)
|
val addPlayerButton = "+".toLabel(Color.BLACK, 30)
|
||||||
.apply { this.setAlignment(Align.center) }
|
.apply { this.setAlignment(Align.center) }
|
||||||
.surroundWithCircle(50f)
|
.surroundWithCircle(50f)
|
||||||
.onClick {
|
.onClick {
|
||||||
var player = Player()
|
|
||||||
// no random mode - add first not spectator civ if still available
|
// no random mode - add first not spectator civ if still available
|
||||||
if (noRandom) {
|
val player = if (noRandom || isRandomNumberOfPlayers) {
|
||||||
val availableCiv = getAvailablePlayerCivs().firstOrNull()
|
val availableCiv = getAvailablePlayerCivs().firstOrNull()
|
||||||
if (availableCiv != null) player = Player(availableCiv.name)
|
if (availableCiv != null) Player(availableCiv.name)
|
||||||
// Spectators only Humans
|
// Spectators can only be Humans
|
||||||
else player = Player(Constants.spectator, PlayerType.Human)
|
else Player(Constants.spectator, PlayerType.Human)
|
||||||
}
|
} else Player() // normal: add random AI
|
||||||
gameParameters.players.add(player)
|
gameParameters.players.add(player)
|
||||||
update()
|
update()
|
||||||
}
|
}
|
||||||
playerListTable.add(addPlayerButton).pad(10f)
|
playerListTable.add(addPlayerButton).pad(10f)
|
||||||
}
|
}
|
||||||
// enable start game when more than 1 active player
|
|
||||||
val moreThanOnePlayer = 1 < gameParameters.players.count { it.chosenCiv != Constants.spectator }
|
// enable start game when at least one human player and they're not alone
|
||||||
(previousScreen as? PickerScreen)?.setRightSideButtonEnabled(moreThanOnePlayer)
|
val humanPlayerCount = gameParameters.players.count { it.playerType == PlayerType.Human }
|
||||||
|
val isValid = humanPlayerCount >= 2 || humanPlayerCount >= 1 && isRandomNumberOfPlayers
|
||||||
|
(previousScreen as? PickerScreen)?.setRightSideButtonEnabled(isValid)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateRandomNumberLabel() {
|
||||||
|
randomNumberLabel?.run {
|
||||||
|
val text = "These [${gameParameters.players.size}] players will be adjusted to [${gameParameters.minNumberOfPlayers}" +
|
||||||
|
"]-[${gameParameters.maxNumberOfPlayers}] actual players by adding random AI's or by randomly omitting AI's."
|
||||||
|
wrap = false
|
||||||
|
align(Align.center)
|
||||||
|
setText(text.tr())
|
||||||
|
wrap = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -145,29 +168,56 @@ class PlayerPickerTable(
|
|||||||
playerTable.add(nationTable).left()
|
playerTable.add(nationTable).left()
|
||||||
|
|
||||||
val playerTypeTextButton = player.playerType.name.toTextButton()
|
val playerTypeTextButton = player.playerType.name.toTextButton()
|
||||||
playerTypeTextButton.onClick {
|
playerTable.add(playerTypeTextButton).width(100f).pad(5f).right()
|
||||||
if (player.playerType == PlayerType.AI)
|
fun updatePlayerTypeButtonEnabled() {
|
||||||
player.playerType = PlayerType.Human
|
// This could be written much shorter with logical operators - I think this is readable
|
||||||
|
playerTypeTextButton.isEnabled = when {
|
||||||
|
// Can always change AI to Human
|
||||||
|
player.playerType == PlayerType.AI -> true
|
||||||
// we cannot change Spectator player to AI type, robots not allowed to spectate :(
|
// we cannot change Spectator player to AI type, robots not allowed to spectate :(
|
||||||
else if (player.chosenCiv != Constants.spectator)
|
player.chosenCiv == Constants.spectator -> false
|
||||||
player.playerType = PlayerType.AI
|
// In randomNumberOfPlayers mode, don't let the user choose random AI's
|
||||||
|
gameParameters.randomNumberOfPlayers && player.chosenCiv == Constants.random -> false
|
||||||
|
else -> true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updatePlayerTypeButtonEnabled()
|
||||||
|
|
||||||
|
nationTable.onClick {
|
||||||
|
if (locked) return@onClick
|
||||||
|
val noRandom = noRandom ||
|
||||||
|
gameParameters.randomNumberOfPlayers && player.playerType == PlayerType.AI
|
||||||
|
popupNationPicker(player, noRandom)
|
||||||
|
updatePlayerTypeButtonEnabled()
|
||||||
|
}
|
||||||
|
playerTypeTextButton.onClick {
|
||||||
|
player.playerType = player.playerType.toggle()
|
||||||
update()
|
update()
|
||||||
}
|
}
|
||||||
playerTable.add(playerTypeTextButton).width(100f).pad(5f).right()
|
|
||||||
if (!locked) {
|
if (!locked) {
|
||||||
playerTable.add("-".toLabel(Color.BLACK, 30).apply { this.setAlignment(Align.center) }
|
playerTable.add("-".toLabel(Color.BLACK, 30, Align.center)
|
||||||
.surroundWithCircle(40f)
|
.surroundWithCircle(40f)
|
||||||
.onClick {
|
.onClick {
|
||||||
gameParameters.players.remove(player)
|
gameParameters.players.remove(player)
|
||||||
update()
|
update()
|
||||||
}).pad(5f).right().row()
|
|
||||||
}
|
}
|
||||||
if (gameParameters.isOnlineMultiplayer && player.playerType == PlayerType.Human) {
|
).pad(5f).right()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gameParameters.isOnlineMultiplayer && player.playerType == PlayerType.Human)
|
||||||
|
playerTable.addPlayerTableMultiplayerControls(player)
|
||||||
|
|
||||||
|
return playerTable
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Table.addPlayerTableMultiplayerControls(player: Player) {
|
||||||
|
row()
|
||||||
|
|
||||||
val playerIdTextField = UncivTextField.create("Please input Player ID!", player.playerId)
|
val playerIdTextField = UncivTextField.create("Please input Player ID!", player.playerId)
|
||||||
playerTable.add(playerIdTextField).colspan(2).fillX().pad(5f)
|
add(playerIdTextField).colspan(2).fillX().pad(5f)
|
||||||
val errorLabel = "✘".toLabel(Color.RED)
|
val errorLabel = "✘".toLabel(Color.RED)
|
||||||
playerTable.add(errorLabel).pad(5f).row()
|
add(errorLabel).pad(5f).row()
|
||||||
|
|
||||||
fun onPlayerIdTextUpdated() {
|
fun onPlayerIdTextUpdated() {
|
||||||
try {
|
try {
|
||||||
@ -179,22 +229,22 @@ class PlayerPickerTable(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
onPlayerIdTextUpdated()
|
onPlayerIdTextUpdated()
|
||||||
|
|
||||||
playerIdTextField.addListener { onPlayerIdTextUpdated(); true }
|
playerIdTextField.addListener { onPlayerIdTextUpdated(); true }
|
||||||
|
|
||||||
val currentUserId = UncivGame.Current.settings.multiplayer.userId
|
val currentUserId = UncivGame.Current.settings.multiplayer.userId
|
||||||
val setCurrentUserButton = "Set current user".toTextButton()
|
val setCurrentUserButton = "Set current user".toTextButton()
|
||||||
setCurrentUserButton.onClick {
|
setCurrentUserButton.onClick {
|
||||||
playerIdTextField.text = currentUserId
|
playerIdTextField.text = currentUserId
|
||||||
onPlayerIdTextUpdated()
|
onPlayerIdTextUpdated()
|
||||||
}
|
}
|
||||||
playerTable.add(setCurrentUserButton).colspan(3).fillX().pad(5f).row()
|
add(setCurrentUserButton).colspan(3).fillX().pad(5f).row()
|
||||||
|
|
||||||
val copyFromClipboardButton = "Player ID from clipboard".toTextButton()
|
val copyFromClipboardButton = "Player ID from clipboard".toTextButton()
|
||||||
copyFromClipboardButton.onClick {
|
copyFromClipboardButton.onClick {
|
||||||
playerIdTextField.text = Gdx.app.clipboard.contents
|
playerIdTextField.text = Gdx.app.clipboard.contents
|
||||||
onPlayerIdTextUpdated()
|
onPlayerIdTextUpdated()
|
||||||
}
|
}
|
||||||
playerTable.add(copyFromClipboardButton).right().colspan(3).fillX().pad(5f).row()
|
add(copyFromClipboardButton).right().colspan(3).fillX().pad(5f).row()
|
||||||
|
|
||||||
//check if friends list is empty before adding the select friend button
|
//check if friends list is empty before adding the select friend button
|
||||||
if (friendList.friendList.isNotEmpty()) {
|
if (friendList.friendList.isNotEmpty()) {
|
||||||
@ -202,31 +252,25 @@ class PlayerPickerTable(
|
|||||||
selectPlayerFromFriendsList.onClick {
|
selectPlayerFromFriendsList.onClick {
|
||||||
popupFriendPicker(player)
|
popupFriendPicker(player)
|
||||||
}
|
}
|
||||||
playerTable.add(selectPlayerFromFriendsList).left().colspan(3).fillX().pad(5f)
|
add(selectPlayerFromFriendsList).left().colspan(3).fillX().pad(5f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return playerTable
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates clickable icon and nation name for some [Player]
|
* Creates clickable icon and nation name for some [Player].
|
||||||
* as a [Table]. Clicking creates [popupNationPicker] to choose new nation.
|
|
||||||
* @param player [Player] for which generated
|
* @param player [Player] for which generated
|
||||||
* @return [Table] containing nation icon and name
|
* @return [Table] containing nation icon and name
|
||||||
*/
|
*/
|
||||||
private fun getNationTable(player: Player): Table {
|
private fun getNationTable(player: Player): Table {
|
||||||
val nationTable = Table()
|
val nationTable = Table()
|
||||||
|
val nationImageName = previousScreen.ruleset.nations[player.chosenCiv]
|
||||||
val nationImage =
|
val nationImage =
|
||||||
if (player.chosenCiv == Constants.random)
|
if (nationImageName == null)
|
||||||
ImageGetter.getRandomNationPortrait(40f)
|
ImageGetter.getRandomNationPortrait(40f)
|
||||||
else ImageGetter.getNationPortrait(previousScreen.ruleset.nations[player.chosenCiv]!!, 40f)
|
else ImageGetter.getNationPortrait(nationImageName, 40f)
|
||||||
nationTable.add(nationImage).pad(5f)
|
nationTable.add(nationImage).pad(5f)
|
||||||
nationTable.add(player.chosenCiv.toLabel()).pad(5f)
|
nationTable.add(player.chosenCiv.toLabel()).pad(5f)
|
||||||
nationTable.touchable = Touchable.enabled
|
nationTable.touchable = Touchable.enabled
|
||||||
nationTable.onClick {
|
|
||||||
if (!locked) popupNationPicker(player)
|
|
||||||
}
|
|
||||||
return nationTable
|
return nationTable
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -247,8 +291,8 @@ class PlayerPickerTable(
|
|||||||
* ruleset and other players nation choice.
|
* ruleset and other players nation choice.
|
||||||
* @param player current player
|
* @param player current player
|
||||||
*/
|
*/
|
||||||
private fun popupNationPicker(player: Player) {
|
private fun popupNationPicker(player: Player, noRandom: Boolean) {
|
||||||
NationPickerPopup(this, player).open()
|
NationPickerPopup(this, player, noRandom).open()
|
||||||
update()
|
update()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -288,7 +332,7 @@ class FriendSelectionPopup(
|
|||||||
screen: BaseScreen,
|
screen: BaseScreen,
|
||||||
) : Popup(screen) {
|
) : Popup(screen) {
|
||||||
|
|
||||||
val pickerPane = PickerPane()
|
private val pickerPane = PickerPane()
|
||||||
private var selectedFriendId: String? = null
|
private var selectedFriendId: String? = null
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@ -327,7 +371,8 @@ class FriendSelectionPopup(
|
|||||||
|
|
||||||
private class NationPickerPopup(
|
private class NationPickerPopup(
|
||||||
private val playerPicker: PlayerPickerTable,
|
private val playerPicker: PlayerPickerTable,
|
||||||
private val player: Player
|
private val player: Player,
|
||||||
|
noRandom: Boolean
|
||||||
) : Popup(playerPicker.previousScreen as BaseScreen) {
|
) : Popup(playerPicker.previousScreen as BaseScreen) {
|
||||||
companion object {
|
companion object {
|
||||||
// These are used for the Close/OK buttons in the lower left/right corners:
|
// These are used for the Close/OK buttons in the lower left/right corners:
|
||||||
@ -357,26 +402,23 @@ private class NationPickerPopup(
|
|||||||
nationDetailsScroll.setOverscroll(false, false)
|
nationDetailsScroll.setOverscroll(false, false)
|
||||||
add(nationDetailsScroll).size(civBlocksWidth + 10f, partHeight) // Same here, see above
|
add(nationDetailsScroll).size(civBlocksWidth + 10f, partHeight) // Same here, see above
|
||||||
|
|
||||||
val randomNation = Nation().apply {
|
val nationSequence = sequence {
|
||||||
|
if (!noRandom) yield(Nation().apply {
|
||||||
name = Constants.random
|
name = Constants.random
|
||||||
innerColor = listOf(255, 255, 255)
|
innerColor = listOf(255, 255, 255)
|
||||||
outerColor = listOf(0, 0, 0)
|
outerColor = listOf(0, 0, 0)
|
||||||
setTransients()
|
setTransients()
|
||||||
}
|
})
|
||||||
val nations = ArrayList<Nation>()
|
|
||||||
if (!playerPicker.noRandom) nations += randomNation
|
|
||||||
val spectator = previousScreen.ruleset.nations[Constants.spectator]
|
val spectator = previousScreen.ruleset.nations[Constants.spectator]
|
||||||
if (spectator != null) nations += spectator
|
if (spectator != null && player.playerType != PlayerType.AI) // only humans can spectate, sorry robots
|
||||||
|
yield(spectator)
|
||||||
nations += playerPicker.getAvailablePlayerCivs(player.chosenCiv)
|
} + playerPicker.getAvailablePlayerCivs(player.chosenCiv)
|
||||||
.sortedWith(compareBy(UncivGame.Current.settings.getCollatorFromLocale()) { it.name.tr() })
|
.sortedWith(compareBy(UncivGame.Current.settings.getCollatorFromLocale()) { it.name.tr() })
|
||||||
|
val nations = nationSequence.toCollection(ArrayList<Nation>(previousScreen.ruleset.nations.size))
|
||||||
|
|
||||||
var nationListScrollY = 0f
|
var nationListScrollY = 0f
|
||||||
var currentY = 0f
|
var currentY = 0f
|
||||||
for (nation in nations) {
|
for (nation in nations) {
|
||||||
// only humans can spectate, sorry robots
|
|
||||||
if (player.playerType == PlayerType.AI && nation.isSpectator)
|
|
||||||
continue
|
|
||||||
if (player.chosenCiv == nation.name)
|
if (player.chosenCiv == nation.name)
|
||||||
nationListScrollY = currentY
|
nationListScrollY = currentY
|
||||||
val nationTable = NationTable(nation, civBlocksWidth, 0f) // no need for min height
|
val nationTable = NationTable(nation, civBlocksWidth, 0f) // no need for min height
|
||||||
@ -386,6 +428,10 @@ private class NationPickerPopup(
|
|||||||
nationTable.onClick {
|
nationTable.onClick {
|
||||||
setNationDetails(nation)
|
setNationDetails(nation)
|
||||||
}
|
}
|
||||||
|
nationTable.onDoubleClick {
|
||||||
|
selectedNation = nation
|
||||||
|
returnSelected()
|
||||||
|
}
|
||||||
if (player.chosenCiv == nation.name)
|
if (player.chosenCiv == nation.name)
|
||||||
setNationDetails(nation)
|
setNationDetails(nation)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user