mirror of
https://github.com/yairm210/Unciv.git
synced 2025-01-05 13:08:48 +07: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,14 +344,18 @@ object GameStarter {
|
||||
|
||||
for (player in chosenPlayers) {
|
||||
val civ = Civilization(player.chosenCiv)
|
||||
if (player.chosenCiv in usedMajorCivs) {
|
||||
for (tech in startingTechs)
|
||||
civ.tech.techsResearched.add(tech.name) // can't be .addTechnology because the civInfo isn't assigned yet
|
||||
civ.playerType = player.playerType
|
||||
civ.playerId = player.playerId
|
||||
} else {
|
||||
if (!civ.cityStateFunctions.initCityState(ruleset, newGameParameters.startingEra, unusedMajorCivs))
|
||||
continue
|
||||
when (player.chosenCiv) {
|
||||
Constants.spectator ->
|
||||
civ.playerType = player.playerType
|
||||
in usedMajorCivs -> {
|
||||
for (tech in startingTechs)
|
||||
civ.tech.techsResearched.add(tech.name) // can't be .addTechnology because the civInfo isn't assigned yet
|
||||
civ.playerType = player.playerType
|
||||
civ.playerId = player.playerId
|
||||
}
|
||||
else ->
|
||||
if (!civ.cityStateFunctions.initCityState(ruleset, newGameParameters.startingEra, unusedMajorCivs))
|
||||
continue
|
||||
}
|
||||
gameInfo.civilizations.add(civ)
|
||||
}
|
||||
|
@ -4,5 +4,6 @@ import com.unciv.logic.IsPartOfGameInfoSerialization
|
||||
|
||||
enum class PlayerType : IsPartOfGameInfoSerialization {
|
||||
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.unciv.Constants
|
||||
@ -15,10 +15,10 @@ import com.unciv.ui.screens.civilopediascreen.CivilopediaScreen.Companion.showRe
|
||||
import com.unciv.ui.screens.civilopediascreen.FormattedLine
|
||||
import kotlin.math.pow
|
||||
|
||||
class Nation : RulesetObject() {
|
||||
class Nation : RulesetObject() {
|
||||
var leaderName = ""
|
||||
fun getLeaderDisplayName() = if (isCityState) name
|
||||
else "[$leaderName] of [$name]"
|
||||
fun getLeaderDisplayName() = if (isCityState || isSpectator) name
|
||||
else "[$leaderName] of [$name]"
|
||||
|
||||
val style = ""
|
||||
fun getStyleOrCivName() = style.ifEmpty { name }
|
||||
@ -36,7 +36,6 @@ import kotlin.math.pow
|
||||
|
||||
lateinit var outerColor: List<Int>
|
||||
var uniqueName = ""
|
||||
override fun getUniqueTarget() = UniqueTarget.Nation
|
||||
var uniqueText = ""
|
||||
var innerColor: List<Int>? = null
|
||||
var startBias = ArrayList<String>()
|
||||
@ -52,6 +51,10 @@ import kotlin.math.pow
|
||||
|
||||
var favoredReligion: String? = null
|
||||
|
||||
var cities: ArrayList<String> = arrayListOf()
|
||||
|
||||
override fun getUniqueTarget() = UniqueTarget.Nation
|
||||
|
||||
@Transient
|
||||
private lateinit var outerColorObject: Color
|
||||
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")
|
||||
}
|
||||
|
||||
var cities: ArrayList<String> = arrayListOf()
|
||||
|
||||
|
||||
override fun makeLink() = "Nation/$name"
|
||||
override fun getSortGroup(ruleset: Ruleset) = when {
|
||||
@ -294,38 +295,39 @@ import kotlin.math.pow
|
||||
}
|
||||
}
|
||||
|
||||
fun getContrastRatio() = getContrastRatio(getInnerColor(), getOuterColor())
|
||||
fun getContrastRatio() = getContrastRatio(getInnerColor(), getOuterColor())
|
||||
|
||||
fun matchesFilter(filter: String): Boolean {
|
||||
return when (filter) {
|
||||
"All" -> true
|
||||
name -> true
|
||||
"Major" -> isMajorCiv
|
||||
"CityState" -> isCityState
|
||||
else -> uniques.contains(filter)
|
||||
}
|
||||
}
|
||||
}
|
||||
fun matchesFilter(filter: String): Boolean {
|
||||
return when (filter) {
|
||||
"All" -> true
|
||||
name -> true
|
||||
"Major" -> isMajorCiv
|
||||
"CityState" -> isCityState
|
||||
else -> uniques.contains(filter)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** All defined by https://www.w3.org/TR/WCAG20/#relativeluminancedef */
|
||||
fun getRelativeLuminance(color:Color):Double{
|
||||
fun getRelativeChannelLuminance(channel:Float):Double =
|
||||
if (channel < 0.03928) channel / 12.92
|
||||
else ((channel + 0.055) / 1.055).pow(2.4)
|
||||
/** All defined by https://www.w3.org/TR/WCAG20/#relativeluminancedef */
|
||||
fun getRelativeLuminance(color: Color): Double {
|
||||
fun getRelativeChannelLuminance(channel: Float): Double =
|
||||
if (channel < 0.03928) channel / 12.92
|
||||
else ((channel + 0.055) / 1.055).pow(2.4)
|
||||
|
||||
val R = getRelativeChannelLuminance(color.r)
|
||||
val G = getRelativeChannelLuminance(color.g)
|
||||
val B = getRelativeChannelLuminance(color.b)
|
||||
val R = getRelativeChannelLuminance(color.r)
|
||||
val G = getRelativeChannelLuminance(color.g)
|
||||
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 */
|
||||
fun getContrastRatio(color1:Color, color2:Color): Double { // ratio can range from 1 to 21
|
||||
val innerColorLuminance = getRelativeLuminance(color1)
|
||||
val outerColorLuminance = getRelativeLuminance(color2)
|
||||
/** https://www.w3.org/TR/WCAG20/#contrast-ratiodef */
|
||||
fun getContrastRatio(color1: Color, color2: Color): Double { // ratio can range from 1 to 21
|
||||
val innerColorLuminance = getRelativeLuminance(color1)
|
||||
val outerColorLuminance = getRelativeLuminance(color2)
|
||||
|
||||
return if (innerColorLuminance > outerColorLuminance) (innerColorLuminance + 0.05) / (outerColorLuminance + 0.05)
|
||||
else (outerColorLuminance + 0.05) / (innerColorLuminance + 0.05)
|
||||
}
|
||||
return if (innerColorLuminance > outerColorLuminance)
|
||||
(innerColorLuminance + 0.05) / (outerColorLuminance + 0.05)
|
||||
else (outerColorLuminance + 0.05) / (innerColorLuminance + 0.05)
|
||||
}
|
||||
|
@ -48,15 +48,15 @@ private class RestorableTextButtonStyle(
|
||||
val restoreStyle: ButtonStyle
|
||||
) : 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() {
|
||||
touchable = Touchable.disabled
|
||||
val oldStyle = style
|
||||
if (oldStyle is RestorableTextButtonStyle) return
|
||||
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() {
|
||||
val oldStyle = style
|
||||
if (oldStyle is RestorableTextButtonStyle) {
|
||||
@ -64,7 +64,7 @@ fun Button.enable() {
|
||||
}
|
||||
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.
|
||||
*
|
||||
* Do not confuse with Gdx' builtin [isDisabled][Button.isDisabled] property,
|
||||
|
@ -299,7 +299,7 @@ class MapEditorEditStartsTab(
|
||||
}
|
||||
|
||||
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()
|
||||
.sortedWith(compareBy<Nation>{ it.isCityState }.thenBy(collator) { it.name.tr() })
|
||||
.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.Table
|
||||
import com.badlogic.gdx.utils.Align
|
||||
import com.unciv.Constants
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.logic.civilization.PlayerType
|
||||
import com.unciv.models.metadata.GameParameters
|
||||
import com.unciv.models.metadata.Player
|
||||
import com.unciv.models.ruleset.RulesetCache
|
||||
import com.unciv.models.ruleset.nation.Nation
|
||||
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.screens.basescreen.BaseScreen
|
||||
import com.unciv.ui.screens.multiplayerscreens.MultiplayerHelpers
|
||||
import kotlin.reflect.KMutableProperty0
|
||||
|
||||
class GameOptionsTable(
|
||||
private val previousScreen: IPreviousScreen,
|
||||
private val isPortrait: Boolean = false,
|
||||
private val updatePlayerPickerTable: (desiredCiv:String)->Unit
|
||||
private val updatePlayerPickerTable: (desiredCiv: String) -> Unit,
|
||||
private val updatePlayerPickerRandomLabel: () -> Unit
|
||||
) : Table(BaseScreen.skin) {
|
||||
var gameParameters = previousScreen.gameSetupInfo.gameParameters
|
||||
val ruleset = previousScreen.ruleset
|
||||
@ -77,12 +82,10 @@ class GameOptionsTable(
|
||||
if (turnSlider != null)
|
||||
add(turnSlider).padTop(10f).row()
|
||||
if (gameParameters.randomNumberOfPlayers) {
|
||||
addMinPlayersSlider()
|
||||
addMaxPlayersSlider()
|
||||
addMinMaxPlayersSliders()
|
||||
}
|
||||
if (gameParameters.randomNumberOfCityStates) {
|
||||
addMinCityStatesSlider()
|
||||
addMaxCityStatesSlider()
|
||||
addMinMaxCityStatesSliders()
|
||||
} else {
|
||||
addCityStatesSlider()
|
||||
}
|
||||
@ -204,7 +207,7 @@ class GameOptionsTable(
|
||||
add(button)
|
||||
}
|
||||
|
||||
private fun numberOfPlayable() = ruleset.nations.values.count {
|
||||
private fun numberOfMajorCivs() = ruleset.nations.values.count {
|
||||
it.isMajorCiv
|
||||
}
|
||||
|
||||
@ -218,64 +221,101 @@ class GameOptionsTable(
|
||||
|
||||
private fun Table.addRandomPlayersCheckbox() =
|
||||
addCheckbox("Random number of Civilizations", gameParameters.randomNumberOfPlayers)
|
||||
{
|
||||
gameParameters.randomNumberOfPlayers = it
|
||||
{newRandomNumberOfPlayers ->
|
||||
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
|
||||
}
|
||||
|
||||
private fun Table.addRandomCityStatesCheckbox() =
|
||||
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
|
||||
}
|
||||
|
||||
private fun Table.addMinPlayersSlider() {
|
||||
val playableAvailable = numberOfPlayable()
|
||||
if (playableAvailable == 0) return
|
||||
private fun Table.addLinkedMinMaxSliders(
|
||||
minValue: Int, maxValue: Int,
|
||||
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()
|
||||
val slider = UncivSlider(2f, playableAvailable.toFloat(), 1f, initial = gameParameters.minNumberOfPlayers.toFloat()) {
|
||||
gameParameters.minNumberOfPlayers = it.toInt()
|
||||
@Suppress("JoinDeclarationAndAssignment") // it's a forward declaration!
|
||||
lateinit var maxSlider: UncivSlider // lateinit safe because the closure won't use it until the user operates a slider
|
||||
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)
|
||||
}
|
||||
onChangeCallback?.invoke()
|
||||
}
|
||||
slider.isDisabled = locked
|
||||
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() {
|
||||
val playableAvailable = numberOfPlayable()
|
||||
if (playableAvailable == 0) return
|
||||
|
||||
add("{Max number of Civilizations}:".toLabel()).left().expandX()
|
||||
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.addMinMaxPlayersSliders() {
|
||||
addLinkedMinMaxSliders(2, numberOfMajorCivs(),
|
||||
"{Min number of Civilizations}:", "{Max number of Civilizations}:",
|
||||
gameParameters::minNumberOfPlayers, gameParameters::maxNumberOfPlayers,
|
||||
updatePlayerPickerRandomLabel
|
||||
)
|
||||
}
|
||||
|
||||
private fun Table.addMinCityStatesSlider() {
|
||||
val cityStatesAvailable = numberOfCityStates()
|
||||
if (cityStatesAvailable == 0) return
|
||||
|
||||
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.addMinMaxCityStatesSliders() {
|
||||
addLinkedMinMaxSliders( 0, numberOfCityStates(),
|
||||
"{Min number of City-States}:", "{Max number of City-States}:",
|
||||
gameParameters::minNumberOfCityStates, gameParameters::maxNumberOfCityStates
|
||||
)
|
||||
}
|
||||
|
||||
private fun Table.addCityStatesSlider() {
|
||||
|
@ -11,22 +11,15 @@ import com.unciv.UncivGame
|
||||
import com.unciv.logic.GameInfo
|
||||
import com.unciv.logic.GameStarter
|
||||
import com.unciv.logic.IdChecker
|
||||
import com.unciv.logic.files.MapSaver
|
||||
import com.unciv.logic.civilization.PlayerType
|
||||
import com.unciv.logic.files.MapSaver
|
||||
import com.unciv.logic.map.MapGeneratedMainType
|
||||
import com.unciv.logic.multiplayer.OnlineMultiplayer
|
||||
import com.unciv.logic.multiplayer.storage.FileStorageRateLimitReached
|
||||
import com.unciv.models.metadata.GameSetupInfo
|
||||
import com.unciv.models.ruleset.RulesetCache
|
||||
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.screens.basescreen.RecreateOnResize
|
||||
import com.unciv.ui.components.extensions.addSeparator
|
||||
import com.unciv.ui.components.extensions.addSeparatorVertical
|
||||
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.toLabel
|
||||
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.concurrency.Concurrency
|
||||
import com.unciv.utils.concurrency.launchOnGLThread
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import java.net.URL
|
||||
import java.util.*
|
||||
import java.util.UUID
|
||||
import com.unciv.ui.components.AutoScrollPane as ScrollPane
|
||||
|
||||
class NewGameScreen(
|
||||
@ -54,6 +54,8 @@ class NewGameScreen(
|
||||
private val mapOptionsTable: MapOptionsTable
|
||||
|
||||
init {
|
||||
val isPortrait = isNarrowerThan4to3()
|
||||
|
||||
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
|
||||
|
||||
@ -65,13 +67,17 @@ class NewGameScreen(
|
||||
|
||||
playerPickerTable = PlayerPickerTable(
|
||||
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)
|
||||
setDefaultCloseAction()
|
||||
|
||||
if (isNarrowerThan4to3()) initPortrait()
|
||||
if (isPortrait) initPortrait()
|
||||
else initLandscape()
|
||||
|
||||
pickerPane.bottomTable.background = skinStrings.getUiBackground("NewGameScreen/BottomTable", tintColor = skinStrings.skinConfig.clearColor)
|
||||
@ -94,107 +100,109 @@ class NewGameScreen(
|
||||
|
||||
rightSideButton.enable()
|
||||
rightSideButton.setText("Start game!".tr())
|
||||
rightSideButton.onClick {
|
||||
if (gameSetupInfo.gameParameters.isOnlineMultiplayer) {
|
||||
if (!checkConnectionToMultiplayerServer()) {
|
||||
val noInternetConnectionPopup = Popup(this)
|
||||
val label = if (OnlineMultiplayer.usesCustomServer()) "Couldn't connect to Multiplayer Server!" else "Couldn't connect to Dropbox!"
|
||||
noInternetConnectionPopup.addGoodSizedLabel(label.tr()).row()
|
||||
noInternetConnectionPopup.addCloseButton()
|
||||
noInternetConnectionPopup.open()
|
||||
return@onClick
|
||||
}
|
||||
rightSideButton.onClick(this::onStartGameClicked)
|
||||
}
|
||||
|
||||
for (player in gameSetupInfo.gameParameters.players.filter { it.playerType == PlayerType.Human }) {
|
||||
try {
|
||||
UUID.fromString(IdChecker.checkAndReturnPlayerUuid(player.playerId))
|
||||
} catch (ex: Exception) {
|
||||
val invalidPlayerIdPopup = Popup(this)
|
||||
invalidPlayerIdPopup.addGoodSizedLabel("Invalid player ID!".tr()).row()
|
||||
invalidPlayerIdPopup.addCloseButton()
|
||||
invalidPlayerIdPopup.open()
|
||||
return@onClick
|
||||
}
|
||||
}
|
||||
private fun onStartGameClicked() {
|
||||
if (gameSetupInfo.gameParameters.isOnlineMultiplayer) {
|
||||
if (!checkConnectionToMultiplayerServer()) {
|
||||
val noInternetConnectionPopup = Popup(this)
|
||||
val label = if (OnlineMultiplayer.usesCustomServer()) "Couldn't connect to Multiplayer Server!" else "Couldn't connect to Dropbox!"
|
||||
noInternetConnectionPopup.addGoodSizedLabel(label.tr()).row()
|
||||
noInternetConnectionPopup.addCloseButton()
|
||||
noInternetConnectionPopup.open()
|
||||
return
|
||||
}
|
||||
|
||||
if (!gameSetupInfo.gameParameters.anyoneCanSpectate) {
|
||||
if (gameSetupInfo.gameParameters.players.none { it.playerId == UncivGame.Current.settings.multiplayer.userId }) {
|
||||
val notAllowedToSpectate = Popup(this)
|
||||
notAllowedToSpectate.addGoodSizedLabel("You are not allowed to spectate!".tr()).row()
|
||||
notAllowedToSpectate.addCloseButton()
|
||||
notAllowedToSpectate.open()
|
||||
return@onClick
|
||||
}
|
||||
for (player in gameSetupInfo.gameParameters.players.filter { it.playerType == PlayerType.Human }) {
|
||||
try {
|
||||
UUID.fromString(IdChecker.checkAndReturnPlayerUuid(player.playerId))
|
||||
} catch (ex: Exception) {
|
||||
val invalidPlayerIdPopup = Popup(this)
|
||||
invalidPlayerIdPopup.addGoodSizedLabel("Invalid player ID!".tr()).row()
|
||||
invalidPlayerIdPopup.addCloseButton()
|
||||
invalidPlayerIdPopup.open()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if (gameSetupInfo.gameParameters.players.none {
|
||||
it.playerType == PlayerType.Human &&
|
||||
// do not allow multiplayer with only remote spectator(s) and AI(s) - non-MP that works
|
||||
!(it.chosenCiv == Constants.spectator && gameSetupInfo.gameParameters.isOnlineMultiplayer &&
|
||||
it.playerId != UncivGame.Current.settings.multiplayer.userId)
|
||||
}) {
|
||||
val noHumanPlayersPopup = Popup(this)
|
||||
noHumanPlayersPopup.addGoodSizedLabel("No human players selected!".tr()).row()
|
||||
noHumanPlayersPopup.addCloseButton()
|
||||
noHumanPlayersPopup.open()
|
||||
return@onClick
|
||||
}
|
||||
|
||||
if (gameSetupInfo.gameParameters.victoryTypes.isEmpty()) {
|
||||
val noVictoryTypesPopup = Popup(this)
|
||||
noVictoryTypesPopup.addGoodSizedLabel("No victory conditions were selected!".tr()).row()
|
||||
noVictoryTypesPopup.addCloseButton()
|
||||
noVictoryTypesPopup.open()
|
||||
return@onClick
|
||||
}
|
||||
|
||||
Gdx.input.inputProcessor = null // remove input processing - nothing will be clicked!
|
||||
|
||||
if (mapOptionsTable.mapTypeSelectBox.selected.value == MapGeneratedMainType.custom) {
|
||||
val map = try {
|
||||
MapSaver.loadMap(gameSetupInfo.mapFile!!)
|
||||
} catch (ex: Throwable) {
|
||||
Gdx.input.inputProcessor = stage
|
||||
ToastPopup("Could not load map!", this)
|
||||
return@onClick
|
||||
}
|
||||
|
||||
val rulesetIncompatibilities = map.getRulesetIncompatibility(ruleset)
|
||||
if (rulesetIncompatibilities.isNotEmpty()) {
|
||||
val incompatibleMap = Popup(this)
|
||||
incompatibleMap.addGoodSizedLabel("Map is incompatible with the chosen ruleset!".tr()).row()
|
||||
for(incompatibility in rulesetIncompatibilities)
|
||||
incompatibleMap.addGoodSizedLabel(incompatibility).row()
|
||||
incompatibleMap.addCloseButton()
|
||||
incompatibleMap.open()
|
||||
Gdx.input.inputProcessor = stage
|
||||
return@onClick
|
||||
}
|
||||
} else {
|
||||
// Generated map - check for sensible dimensions and if exceeded correct them and notify user
|
||||
val mapSize = gameSetupInfo.mapParameters.mapSize
|
||||
val message = mapSize.fixUndesiredSizes(gameSetupInfo.mapParameters.worldWrap)
|
||||
if (message != null) {
|
||||
ToastPopup( message, UncivGame.Current.screen!!, 4000 )
|
||||
with (mapOptionsTable.generatedMapOptionsTable) {
|
||||
customMapSizeRadius.text = mapSize.radius.toString()
|
||||
customMapWidth.text = mapSize.width.toString()
|
||||
customMapHeight.text = mapSize.height.toString()
|
||||
}
|
||||
Gdx.input.inputProcessor = stage
|
||||
return@onClick
|
||||
if (!gameSetupInfo.gameParameters.anyoneCanSpectate) {
|
||||
if (gameSetupInfo.gameParameters.players.none { it.playerId == UncivGame.Current.settings.multiplayer.userId }) {
|
||||
val notAllowedToSpectate = Popup(this)
|
||||
notAllowedToSpectate.addGoodSizedLabel("You are not allowed to spectate!".tr()).row()
|
||||
notAllowedToSpectate.addCloseButton()
|
||||
notAllowedToSpectate.open()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rightSideButton.disable()
|
||||
rightSideButton.setText("Working...".tr())
|
||||
if (gameSetupInfo.gameParameters.players.none {
|
||||
it.playerType == PlayerType.Human &&
|
||||
// do not allow multiplayer with only remote spectator(s) and AI(s) - non-MP that works
|
||||
!(it.chosenCiv == Constants.spectator && gameSetupInfo.gameParameters.isOnlineMultiplayer &&
|
||||
it.playerId != UncivGame.Current.settings.multiplayer.userId)
|
||||
}) {
|
||||
val noHumanPlayersPopup = Popup(this)
|
||||
noHumanPlayersPopup.addGoodSizedLabel("No human players selected!".tr()).row()
|
||||
noHumanPlayersPopup.addCloseButton()
|
||||
noHumanPlayersPopup.open()
|
||||
return
|
||||
}
|
||||
|
||||
setSkin()
|
||||
// Creating a new game can take a while and we don't want ANRs
|
||||
Concurrency.runOnNonDaemonThreadPool("NewGame") {
|
||||
startNewGame()
|
||||
if (gameSetupInfo.gameParameters.victoryTypes.isEmpty()) {
|
||||
val noVictoryTypesPopup = Popup(this)
|
||||
noVictoryTypesPopup.addGoodSizedLabel("No victory conditions were selected!".tr()).row()
|
||||
noVictoryTypesPopup.addCloseButton()
|
||||
noVictoryTypesPopup.open()
|
||||
return
|
||||
}
|
||||
|
||||
Gdx.input.inputProcessor = null // remove input processing - nothing will be clicked!
|
||||
|
||||
if (mapOptionsTable.mapTypeSelectBox.selected.value == MapGeneratedMainType.custom) {
|
||||
val map = try {
|
||||
MapSaver.loadMap(gameSetupInfo.mapFile!!)
|
||||
} catch (ex: Throwable) {
|
||||
Gdx.input.inputProcessor = stage
|
||||
ToastPopup("Could not load map!", this)
|
||||
return
|
||||
}
|
||||
|
||||
val rulesetIncompatibilities = map.getRulesetIncompatibility(ruleset)
|
||||
if (rulesetIncompatibilities.isNotEmpty()) {
|
||||
val incompatibleMap = Popup(this)
|
||||
incompatibleMap.addGoodSizedLabel("Map is incompatible with the chosen ruleset!".tr()).row()
|
||||
for(incompatibility in rulesetIncompatibilities)
|
||||
incompatibleMap.addGoodSizedLabel(incompatibility).row()
|
||||
incompatibleMap.addCloseButton()
|
||||
incompatibleMap.open()
|
||||
Gdx.input.inputProcessor = stage
|
||||
return
|
||||
}
|
||||
} else {
|
||||
// Generated map - check for sensible dimensions and if exceeded correct them and notify user
|
||||
val mapSize = gameSetupInfo.mapParameters.mapSize
|
||||
val message = mapSize.fixUndesiredSizes(gameSetupInfo.mapParameters.worldWrap)
|
||||
if (message != null) {
|
||||
ToastPopup( message, UncivGame.Current.screen!!, 4000 )
|
||||
with (mapOptionsTable.generatedMapOptionsTable) {
|
||||
customMapSizeRadius.text = mapSize.radius.toString()
|
||||
customMapWidth.text = mapSize.width.toString()
|
||||
customMapHeight.text = mapSize.height.toString()
|
||||
}
|
||||
Gdx.input.inputProcessor = stage
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
rightSideButton.disable()
|
||||
rightSideButton.setText("Working...".tr())
|
||||
|
||||
setSkin()
|
||||
// Creating a new game can take a while and we don't want ANRs
|
||||
Concurrency.runOnNonDaemonThreadPool("NewGame") {
|
||||
startNewGame()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@ import com.unciv.logic.IdChecker
|
||||
import com.unciv.logic.civilization.PlayerType
|
||||
import com.unciv.logic.multiplayer.FriendList
|
||||
import com.unciv.models.metadata.GameParameters
|
||||
import com.unciv.models.metadata.GameSetupInfo
|
||||
import com.unciv.models.metadata.Player
|
||||
import com.unciv.models.ruleset.Ruleset
|
||||
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.components.KeyCharAndCode
|
||||
import com.unciv.ui.components.UncivTextField
|
||||
import com.unciv.ui.components.WrappableLabel
|
||||
import com.unciv.ui.components.extensions.*
|
||||
import com.unciv.ui.images.ImageGetter
|
||||
import com.unciv.ui.popups.Popup
|
||||
@ -44,12 +46,13 @@ class PlayerPickerTable(
|
||||
blockWidth: Float = 0f
|
||||
): 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
|
||||
|
||||
/** 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
|
||||
|
||||
private val friendList = FriendList()
|
||||
@ -82,27 +85,47 @@ class PlayerPickerTable(
|
||||
for (player in gameParameters.players) {
|
||||
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 }) {
|
||||
val addPlayerButton = "+".toLabel(Color.BLACK, 30)
|
||||
.apply { this.setAlignment(Align.center) }
|
||||
.surroundWithCircle(50f)
|
||||
.onClick {
|
||||
var player = Player()
|
||||
// no random mode - add first not spectator civ if still available
|
||||
if (noRandom) {
|
||||
val player = if (noRandom || isRandomNumberOfPlayers) {
|
||||
val availableCiv = getAvailablePlayerCivs().firstOrNull()
|
||||
if (availableCiv != null) player = Player(availableCiv.name)
|
||||
// Spectators only Humans
|
||||
else player = Player(Constants.spectator, PlayerType.Human)
|
||||
}
|
||||
if (availableCiv != null) Player(availableCiv.name)
|
||||
// Spectators can only be Humans
|
||||
else Player(Constants.spectator, PlayerType.Human)
|
||||
} else Player() // normal: add random AI
|
||||
gameParameters.players.add(player)
|
||||
update()
|
||||
}
|
||||
playerListTable.add(addPlayerButton).pad(10f)
|
||||
}
|
||||
// enable start game when more than 1 active player
|
||||
val moreThanOnePlayer = 1 < gameParameters.players.count { it.chosenCiv != Constants.spectator }
|
||||
(previousScreen as? PickerScreen)?.setRightSideButtonEnabled(moreThanOnePlayer)
|
||||
|
||||
// enable start game when at least one human player and they're not alone
|
||||
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,88 +168,109 @@ class PlayerPickerTable(
|
||||
playerTable.add(nationTable).left()
|
||||
|
||||
val playerTypeTextButton = player.playerType.name.toTextButton()
|
||||
playerTable.add(playerTypeTextButton).width(100f).pad(5f).right()
|
||||
fun updatePlayerTypeButtonEnabled() {
|
||||
// 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 :(
|
||||
player.chosenCiv == Constants.spectator -> false
|
||||
// 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 {
|
||||
if (player.playerType == PlayerType.AI)
|
||||
player.playerType = PlayerType.Human
|
||||
// we cannot change Spectator player to AI type, robots not allowed to spectate :(
|
||||
else if (player.chosenCiv != Constants.spectator)
|
||||
player.playerType = PlayerType.AI
|
||||
player.playerType = player.playerType.toggle()
|
||||
update()
|
||||
}
|
||||
playerTable.add(playerTypeTextButton).width(100f).pad(5f).right()
|
||||
|
||||
if (!locked) {
|
||||
playerTable.add("-".toLabel(Color.BLACK, 30).apply { this.setAlignment(Align.center) }
|
||||
.surroundWithCircle(40f)
|
||||
.onClick {
|
||||
gameParameters.players.remove(player)
|
||||
update()
|
||||
}).pad(5f).right().row()
|
||||
}
|
||||
if (gameParameters.isOnlineMultiplayer && player.playerType == PlayerType.Human) {
|
||||
|
||||
val playerIdTextField = UncivTextField.create("Please input Player ID!", player.playerId)
|
||||
playerTable.add(playerIdTextField).colspan(2).fillX().pad(5f)
|
||||
val errorLabel = "✘".toLabel(Color.RED)
|
||||
playerTable.add(errorLabel).pad(5f).row()
|
||||
|
||||
fun onPlayerIdTextUpdated() {
|
||||
try {
|
||||
UUID.fromString(IdChecker.checkAndReturnPlayerUuid(playerIdTextField.text))
|
||||
player.playerId = playerIdTextField.text.trim()
|
||||
errorLabel.apply { setText("✔");setFontColor(Color.GREEN) }
|
||||
} catch (ex: Exception) {
|
||||
errorLabel.apply { setText("✘");setFontColor(Color.RED) }
|
||||
playerTable.add("-".toLabel(Color.BLACK, 30, Align.center)
|
||||
.surroundWithCircle(40f)
|
||||
.onClick {
|
||||
gameParameters.players.remove(player)
|
||||
update()
|
||||
}
|
||||
}
|
||||
onPlayerIdTextUpdated()
|
||||
|
||||
playerIdTextField.addListener { onPlayerIdTextUpdated(); true }
|
||||
val currentUserId = UncivGame.Current.settings.multiplayer.userId
|
||||
val setCurrentUserButton = "Set current user".toTextButton()
|
||||
setCurrentUserButton.onClick {
|
||||
playerIdTextField.text = currentUserId
|
||||
onPlayerIdTextUpdated()
|
||||
}
|
||||
playerTable.add(setCurrentUserButton).colspan(3).fillX().pad(5f).row()
|
||||
|
||||
val copyFromClipboardButton = "Player ID from clipboard".toTextButton()
|
||||
copyFromClipboardButton.onClick {
|
||||
playerIdTextField.text = Gdx.app.clipboard.contents
|
||||
onPlayerIdTextUpdated()
|
||||
}
|
||||
playerTable.add(copyFromClipboardButton).right().colspan(3).fillX().pad(5f).row()
|
||||
|
||||
//check if friends list is empty before adding the select friend button
|
||||
if (friendList.friendList.isNotEmpty()) {
|
||||
val selectPlayerFromFriendsList = "Player ID from friends list".toTextButton()
|
||||
selectPlayerFromFriendsList.onClick {
|
||||
popupFriendPicker(player)
|
||||
}
|
||||
playerTable.add(selectPlayerFromFriendsList).left().colspan(3).fillX().pad(5f)
|
||||
}
|
||||
).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)
|
||||
add(playerIdTextField).colspan(2).fillX().pad(5f)
|
||||
val errorLabel = "✘".toLabel(Color.RED)
|
||||
add(errorLabel).pad(5f).row()
|
||||
|
||||
fun onPlayerIdTextUpdated() {
|
||||
try {
|
||||
UUID.fromString(IdChecker.checkAndReturnPlayerUuid(playerIdTextField.text))
|
||||
player.playerId = playerIdTextField.text.trim()
|
||||
errorLabel.apply { setText("✔");setFontColor(Color.GREEN) }
|
||||
} catch (ex: Exception) {
|
||||
errorLabel.apply { setText("✘");setFontColor(Color.RED) }
|
||||
}
|
||||
}
|
||||
onPlayerIdTextUpdated()
|
||||
playerIdTextField.addListener { onPlayerIdTextUpdated(); true }
|
||||
|
||||
val currentUserId = UncivGame.Current.settings.multiplayer.userId
|
||||
val setCurrentUserButton = "Set current user".toTextButton()
|
||||
setCurrentUserButton.onClick {
|
||||
playerIdTextField.text = currentUserId
|
||||
onPlayerIdTextUpdated()
|
||||
}
|
||||
add(setCurrentUserButton).colspan(3).fillX().pad(5f).row()
|
||||
|
||||
val copyFromClipboardButton = "Player ID from clipboard".toTextButton()
|
||||
copyFromClipboardButton.onClick {
|
||||
playerIdTextField.text = Gdx.app.clipboard.contents
|
||||
onPlayerIdTextUpdated()
|
||||
}
|
||||
add(copyFromClipboardButton).right().colspan(3).fillX().pad(5f).row()
|
||||
|
||||
//check if friends list is empty before adding the select friend button
|
||||
if (friendList.friendList.isNotEmpty()) {
|
||||
val selectPlayerFromFriendsList = "Player ID from friends list".toTextButton()
|
||||
selectPlayerFromFriendsList.onClick {
|
||||
popupFriendPicker(player)
|
||||
}
|
||||
add(selectPlayerFromFriendsList).left().colspan(3).fillX().pad(5f)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates clickable icon and nation name for some [Player]
|
||||
* as a [Table]. Clicking creates [popupNationPicker] to choose new nation.
|
||||
* Creates clickable icon and nation name for some [Player].
|
||||
* @param player [Player] for which generated
|
||||
* @return [Table] containing nation icon and name
|
||||
*/
|
||||
private fun getNationTable(player: Player): Table {
|
||||
val nationTable = Table()
|
||||
val nationImageName = previousScreen.ruleset.nations[player.chosenCiv]
|
||||
val nationImage =
|
||||
if (player.chosenCiv == Constants.random)
|
||||
if (nationImageName == null)
|
||||
ImageGetter.getRandomNationPortrait(40f)
|
||||
else ImageGetter.getNationPortrait(previousScreen.ruleset.nations[player.chosenCiv]!!, 40f)
|
||||
else ImageGetter.getNationPortrait(nationImageName, 40f)
|
||||
nationTable.add(nationImage).pad(5f)
|
||||
nationTable.add(player.chosenCiv.toLabel()).pad(5f)
|
||||
nationTable.touchable = Touchable.enabled
|
||||
nationTable.onClick {
|
||||
if (!locked) popupNationPicker(player)
|
||||
}
|
||||
return nationTable
|
||||
}
|
||||
|
||||
@ -247,8 +291,8 @@ class PlayerPickerTable(
|
||||
* ruleset and other players nation choice.
|
||||
* @param player current player
|
||||
*/
|
||||
private fun popupNationPicker(player: Player) {
|
||||
NationPickerPopup(this, player).open()
|
||||
private fun popupNationPicker(player: Player, noRandom: Boolean) {
|
||||
NationPickerPopup(this, player, noRandom).open()
|
||||
update()
|
||||
}
|
||||
|
||||
@ -288,7 +332,7 @@ class FriendSelectionPopup(
|
||||
screen: BaseScreen,
|
||||
) : Popup(screen) {
|
||||
|
||||
val pickerPane = PickerPane()
|
||||
private val pickerPane = PickerPane()
|
||||
private var selectedFriendId: String? = null
|
||||
|
||||
init {
|
||||
@ -327,7 +371,8 @@ class FriendSelectionPopup(
|
||||
|
||||
private class NationPickerPopup(
|
||||
private val playerPicker: PlayerPickerTable,
|
||||
private val player: Player
|
||||
private val player: Player,
|
||||
noRandom: Boolean
|
||||
) : Popup(playerPicker.previousScreen as BaseScreen) {
|
||||
companion object {
|
||||
// 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)
|
||||
add(nationDetailsScroll).size(civBlocksWidth + 10f, partHeight) // Same here, see above
|
||||
|
||||
val randomNation = Nation().apply {
|
||||
name = Constants.random
|
||||
innerColor = listOf(255, 255, 255)
|
||||
outerColor = listOf(0, 0, 0)
|
||||
setTransients()
|
||||
}
|
||||
val nations = ArrayList<Nation>()
|
||||
if (!playerPicker.noRandom) nations += randomNation
|
||||
val spectator = previousScreen.ruleset.nations[Constants.spectator]
|
||||
if (spectator != null) nations += spectator
|
||||
|
||||
nations += playerPicker.getAvailablePlayerCivs(player.chosenCiv)
|
||||
val nationSequence = sequence {
|
||||
if (!noRandom) yield(Nation().apply {
|
||||
name = Constants.random
|
||||
innerColor = listOf(255, 255, 255)
|
||||
outerColor = listOf(0, 0, 0)
|
||||
setTransients()
|
||||
})
|
||||
val spectator = previousScreen.ruleset.nations[Constants.spectator]
|
||||
if (spectator != null && player.playerType != PlayerType.AI) // only humans can spectate, sorry robots
|
||||
yield(spectator)
|
||||
} + playerPicker.getAvailablePlayerCivs(player.chosenCiv)
|
||||
.sortedWith(compareBy(UncivGame.Current.settings.getCollatorFromLocale()) { it.name.tr() })
|
||||
val nations = nationSequence.toCollection(ArrayList<Nation>(previousScreen.ruleset.nations.size))
|
||||
|
||||
var nationListScrollY = 0f
|
||||
var currentY = 0f
|
||||
for (nation in nations) {
|
||||
// only humans can spectate, sorry robots
|
||||
if (player.playerType == PlayerType.AI && nation.isSpectator)
|
||||
continue
|
||||
if (player.chosenCiv == nation.name)
|
||||
nationListScrollY = currentY
|
||||
val nationTable = NationTable(nation, civBlocksWidth, 0f) // no need for min height
|
||||
@ -386,6 +428,10 @@ private class NationPickerPopup(
|
||||
nationTable.onClick {
|
||||
setNationDetails(nation)
|
||||
}
|
||||
nationTable.onDoubleClick {
|
||||
selectedNation = nation
|
||||
returnSelected()
|
||||
}
|
||||
if (player.chosenCiv == nation.name)
|
||||
setNationDetails(nation)
|
||||
}
|
||||
|
@ -169,7 +169,7 @@ Each specialist can have the following attributes:
|
||||
| science | Integer | defaults to 0 |
|
||||
| faith | Integer | defaults to 0 |
|
||||
| color | List of 3 Integers | required | Color of the image for this specialist |
|
||||
| greatPersonPoints | Object | defaults to none | Great person points generated by this specialist. Valid keys are the names of the great person(Great Scientist, Great Merachant, etc.), valid values are Integers (≥0) |
|
||||
| greatPersonPoints | Object | defaults to none | Great person points generated by this specialist. Valid keys are the names of the great person(Great Scientist, Great Merachant, etc.), valid values are Integers (≥0) |
|
||||
|
||||
## Techs.json
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user