mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-08 23:08:35 +07:00
added feature to select specific city states
created MultiNationSelectPopup to reuse for the city states
This commit is contained in:
@ -336,8 +336,11 @@ Promotions =
|
||||
Load copied data =
|
||||
Reset to defaults =
|
||||
Select nations =
|
||||
Select city states =
|
||||
Random nations pool =
|
||||
Random city states pool =
|
||||
Blacklist random nations pool =
|
||||
Blacklist random city states pool =
|
||||
Are you sure you want to reset all game options to defaults? =
|
||||
Start game! =
|
||||
Map Options =
|
||||
|
@ -291,16 +291,25 @@ object GameStarter {
|
||||
gameInfo.civilizations.add(playerCiv)
|
||||
}
|
||||
|
||||
val availableCityStatesNames = Stack<String>()
|
||||
var availableCityStatesNames = Stack<String>()
|
||||
// since we shuffle and then order by, we end up with all the City-States with starting tiles first in a random order,
|
||||
// and then all the other City-States in a random order! Because the sortedBy function is stable!
|
||||
availableCityStatesNames.addAll( ruleset.nations
|
||||
.filter {
|
||||
it.value.isCityState() &&
|
||||
!it.value.hasUnique(UniqueType.CityStateDeprecated)
|
||||
}.keys
|
||||
.shuffled()
|
||||
.sortedBy { it in civNamesWithStartingLocations } ) // pop() gets the last item, so sort ascending
|
||||
|
||||
val selectedCityStatesPoolNames = Stack<String>()
|
||||
for (selectedCityState in gameSetupInfo.gameParameters.randomCityStates)
|
||||
selectedCityStatesPoolNames.add(selectedCityState.name)
|
||||
if (gameSetupInfo.gameParameters.blacklistRandomCityStatesPool) {
|
||||
availableCityStatesNames.addAll( ruleset.nations
|
||||
.filter {
|
||||
it.value.isCityState() &&
|
||||
!it.value.hasUnique(UniqueType.CityStateDeprecated)
|
||||
}.keys
|
||||
.shuffled()
|
||||
.sortedBy { it in civNamesWithStartingLocations } ) // pop() gets the last item, so sort ascending
|
||||
availableCityStatesNames.removeAll(selectedCityStatesPoolNames)
|
||||
} else {
|
||||
availableCityStatesNames = selectedCityStatesPoolNames
|
||||
}
|
||||
|
||||
val numberOfCityStates = if (newGameParameters.randomNumberOfCityStates) {
|
||||
// This swaps min and max if the user accidentally swapped min and max
|
||||
|
@ -29,8 +29,11 @@ class GameParameters : IsPartOfGameInfoSerialization { // Default values are the
|
||||
var numberOfCityStates = 6
|
||||
|
||||
var enableRandomNationsPool = false
|
||||
var enableRandomCityStatesPool = false
|
||||
var blacklistRandomNationsPool = false
|
||||
var blacklistRandomCityStatesPool = false
|
||||
var randomNations = arrayListOf<Nation>()
|
||||
var randomCityStates = arrayListOf<Nation>()
|
||||
|
||||
var noCityRazing = false
|
||||
var noBarbarians = false
|
||||
|
@ -1,34 +1,21 @@
|
||||
package com.unciv.ui.newgamescreen
|
||||
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.scenes.scene2d.Group
|
||||
import com.badlogic.gdx.scenes.scene2d.Touchable
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.ImageButton
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||
import com.badlogic.gdx.utils.Align
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.models.metadata.GameParameters
|
||||
import com.unciv.models.ruleset.RulesetCache
|
||||
import com.unciv.models.ruleset.nation.Nation
|
||||
import com.unciv.models.ruleset.unique.UniqueType
|
||||
import com.unciv.models.translations.tr
|
||||
import com.unciv.ui.audio.MusicMood
|
||||
import com.unciv.ui.audio.MusicTrackChooserFlags
|
||||
import com.unciv.ui.images.ImageGetter
|
||||
import com.unciv.ui.multiplayer.MultiplayerHelpers
|
||||
import com.unciv.ui.popup.Popup
|
||||
import com.unciv.ui.popup.ToastPopup
|
||||
import com.unciv.ui.utils.AutoScrollPane
|
||||
import com.unciv.ui.utils.BaseScreen
|
||||
import com.unciv.ui.utils.ExpanderTab
|
||||
import com.unciv.ui.utils.KeyCharAndCode
|
||||
import com.unciv.ui.utils.UncivSlider
|
||||
import com.unciv.ui.utils.extensions.isNarrowerThan4to3
|
||||
import com.unciv.ui.utils.extensions.keyShortcuts
|
||||
import com.unciv.ui.utils.extensions.onActivation
|
||||
import com.unciv.ui.utils.extensions.onChange
|
||||
import com.unciv.ui.utils.extensions.onClick
|
||||
import com.unciv.ui.utils.extensions.surroundWithCircle
|
||||
import com.unciv.ui.utils.extensions.toCheckBox
|
||||
import com.unciv.ui.utils.extensions.toLabel
|
||||
import com.unciv.ui.utils.extensions.toTextButton
|
||||
@ -107,12 +94,17 @@ class GameOptionsTable(
|
||||
it.addEnableEspionageCheckbox()
|
||||
it.addNoStartBiasCheckbox()
|
||||
it.addRandomPlayersCheckbox()
|
||||
it.addRandomCityStatesCheckbox()
|
||||
it.addRandomNrCityStatesCheckbox()
|
||||
it.addRandomNationsPoolCheckbox()
|
||||
if (gameParameters.enableRandomNationsPool) {
|
||||
it.addBlacklistRandomPool()
|
||||
it.addBlacklistRandomNationsPool()
|
||||
it.addNationsSelectTextButton()
|
||||
}
|
||||
it.addRandomCityStatesPoolCheckbox()
|
||||
if (gameParameters.enableRandomCityStatesPool){
|
||||
it.addBlacklistRandomCityStatesPool()
|
||||
it.addCityStatesSelectTextButton()
|
||||
}
|
||||
}
|
||||
add(expander).pad(10f).padTop(10f).growX().row()
|
||||
|
||||
@ -177,19 +169,40 @@ class GameOptionsTable(
|
||||
update()
|
||||
}
|
||||
|
||||
private fun Table.addBlacklistRandomPool() =
|
||||
private fun Table.addRandomCityStatesPoolCheckbox() =
|
||||
addCheckbox("Random city states pool", gameParameters.enableRandomCityStatesPool) {
|
||||
gameParameters.enableRandomCityStatesPool = it
|
||||
update()
|
||||
}
|
||||
|
||||
private fun Table.addBlacklistRandomNationsPool() =
|
||||
addCheckbox("Blacklist random nations pool", gameParameters.blacklistRandomNationsPool) {
|
||||
gameParameters.blacklistRandomNationsPool = it
|
||||
}
|
||||
|
||||
private fun Table.addBlacklistRandomCityStatesPool() =
|
||||
addCheckbox("Blacklist random city states pool", gameParameters.blacklistRandomCityStatesPool) {
|
||||
gameParameters.blacklistRandomCityStatesPool = it
|
||||
}
|
||||
|
||||
private fun Table.addNationsSelectTextButton() {
|
||||
val button = "Select nations".toTextButton()
|
||||
button.onClick {
|
||||
val popup = RandomNationPickerPopup(previousScreen, gameParameters)
|
||||
val popup = MultiNationSelectPopup(previousScreen, gameParameters, true)
|
||||
popup.open()
|
||||
popup.update()
|
||||
}
|
||||
add(button)
|
||||
add(button).row()
|
||||
}
|
||||
|
||||
private fun Table.addCityStatesSelectTextButton() {
|
||||
val button = "Select city states".toTextButton()
|
||||
button.onClick {
|
||||
val popup = MultiNationSelectPopup(previousScreen, gameParameters, false)
|
||||
popup.open()
|
||||
popup.update()
|
||||
}
|
||||
add(button).row()
|
||||
}
|
||||
|
||||
private fun numberOfPlayable() = ruleset.nations.values.count {
|
||||
@ -212,7 +225,7 @@ class GameOptionsTable(
|
||||
update()
|
||||
}
|
||||
|
||||
private fun Table.addRandomCityStatesCheckbox() =
|
||||
private fun Table.addRandomNrCityStatesCheckbox() =
|
||||
addCheckbox("Random number of City-States", gameParameters.randomNumberOfCityStates)
|
||||
{
|
||||
gameParameters.randomNumberOfCityStates = it
|
||||
@ -439,136 +452,3 @@ class GameOptionsTable(
|
||||
updatePlayerPickerTable(desiredCiv)
|
||||
}
|
||||
}
|
||||
|
||||
private class RandomNationPickerPopup(
|
||||
previousScreen: IPreviousScreen,
|
||||
val gameParameters: GameParameters
|
||||
) : Popup(previousScreen as BaseScreen) {
|
||||
companion object {
|
||||
// These are used for the Close/OK buttons in the lower left/right corners:
|
||||
const val buttonsCircleSize = 70f
|
||||
const val buttonsIconSize = 50f
|
||||
const val buttonsOffsetFromEdge = 5f
|
||||
val buttonsBackColor: Color = Color.BLACK.cpy().apply { a = 0.67f }
|
||||
}
|
||||
|
||||
val blockWidth: Float = 0f
|
||||
val civBlocksWidth = if(blockWidth <= 10f) previousScreen.stage.width / 3 - 5f else blockWidth
|
||||
|
||||
// This Popup's body has two halves of same size, either side by side or arranged vertically
|
||||
// depending on screen proportions - determine height for one of those
|
||||
private val partHeight = stageToShowOn.height * (if (stageToShowOn.isNarrowerThan4to3()) 0.45f else 0.8f)
|
||||
private val nationListTable = Table()
|
||||
private val nationListScroll = AutoScrollPane(nationListTable)
|
||||
private val selectedNationsListTable = Table()
|
||||
private val selectedNationsListScroll = AutoScrollPane(selectedNationsListTable)
|
||||
private var selectedNations = gameParameters.randomNations
|
||||
var nations = arrayListOf<Nation>()
|
||||
|
||||
|
||||
init {
|
||||
var nationListScrollY = 0f
|
||||
nations += previousScreen.ruleset.nations.values.asSequence()
|
||||
.filter { it.isMajorCiv() }
|
||||
nationListScroll.setOverscroll(false, false)
|
||||
add(nationListScroll).size( civBlocksWidth + 10f, partHeight )
|
||||
// +10, because the nation table has a 5f pad, for a total of +10f
|
||||
if (stageToShowOn.isNarrowerThan4to3()) row()
|
||||
selectedNationsListScroll.setOverscroll(false, false)
|
||||
add(selectedNationsListScroll).size(civBlocksWidth + 10f, partHeight) // Same here, see above
|
||||
|
||||
update()
|
||||
|
||||
nationListScroll.layout()
|
||||
pack()
|
||||
if (nationListScrollY > 0f) {
|
||||
// center the selected nation vertically, getRowHeight safe because nationListScrollY > 0f ensures at least 1 row
|
||||
nationListScrollY -= (nationListScroll.height - nationListTable.getRowHeight(0)) / 2
|
||||
nationListScroll.scrollY = nationListScrollY.coerceIn(0f, nationListScroll.maxY)
|
||||
}
|
||||
|
||||
val closeButton = "OtherIcons/Close".toImageButton(Color.FIREBRICK)
|
||||
closeButton.onActivation { close() }
|
||||
closeButton.keyShortcuts.add(KeyCharAndCode.BACK)
|
||||
closeButton.setPosition(buttonsOffsetFromEdge, buttonsOffsetFromEdge, Align.bottomLeft)
|
||||
innerTable.addActor(closeButton)
|
||||
|
||||
val okButton = "OtherIcons/Checkmark".toImageButton(Color.LIME)
|
||||
okButton.onClick { returnSelected() }
|
||||
okButton.setPosition(innerTable.width - buttonsOffsetFromEdge, buttonsOffsetFromEdge, Align.bottomRight)
|
||||
innerTable.addActor(okButton)
|
||||
|
||||
selectedNationsListTable.touchable = Touchable.enabled
|
||||
}
|
||||
|
||||
fun update() {
|
||||
nationListTable.clear()
|
||||
selectedNations = gameParameters.randomNations
|
||||
nations -= selectedNations.toSet()
|
||||
nations = nations.sortedWith(compareBy(UncivGame.Current.settings.getCollatorFromLocale()) { it.name.tr() }).toMutableList() as ArrayList<Nation>
|
||||
|
||||
var currentY = 0f
|
||||
for (nation in nations) {
|
||||
val nationTable = NationTable(nation, civBlocksWidth, 0f) // no need for min height
|
||||
val cell = nationListTable.add(nationTable)
|
||||
currentY += cell.padBottom + cell.prefHeight + cell.padTop
|
||||
cell.row()
|
||||
nationTable.onClick {
|
||||
addNationToPool(nation)
|
||||
}
|
||||
}
|
||||
|
||||
if (selectedNations.isNotEmpty()) {
|
||||
selectedNationsListTable.clear()
|
||||
|
||||
for (currentNation in selectedNations) {
|
||||
val nationTable = NationTable(currentNation, civBlocksWidth, 0f)
|
||||
nationTable.onClick { removeNationFromPool(currentNation) }
|
||||
selectedNationsListTable.add(nationTable).row()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun String.toImageButton(overColor: Color): Group {
|
||||
val style = ImageButton.ImageButtonStyle()
|
||||
val image = ImageGetter.getDrawable(this)
|
||||
style.imageUp = image
|
||||
style.imageOver = image.tint(overColor)
|
||||
val button = ImageButton(style)
|
||||
button.setSize(buttonsIconSize, buttonsIconSize)
|
||||
|
||||
return button.surroundWithCircle(buttonsCircleSize, false, buttonsBackColor)
|
||||
}
|
||||
|
||||
private fun updateNationListTable() {
|
||||
selectedNationsListTable.clear()
|
||||
|
||||
for (currentNation in selectedNations) {
|
||||
val nationTable = NationTable(currentNation, civBlocksWidth, 0f)
|
||||
nationTable.onClick { removeNationFromPool(currentNation) }
|
||||
selectedNationsListTable.add(nationTable).row()
|
||||
}
|
||||
}
|
||||
|
||||
private fun addNationToPool(nation: Nation) {
|
||||
selectedNations.add(nation)
|
||||
|
||||
update()
|
||||
updateNationListTable()
|
||||
}
|
||||
|
||||
private fun removeNationFromPool(nation: Nation) {
|
||||
nations.add(nation)
|
||||
selectedNations.remove(nation)
|
||||
|
||||
update()
|
||||
updateNationListTable()
|
||||
}
|
||||
|
||||
private fun returnSelected() {
|
||||
close()
|
||||
gameParameters.randomNations = selectedNations
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
170
core/src/com/unciv/ui/newgamescreen/MultiNationSelectPopup.kt
Normal file
170
core/src/com/unciv/ui/newgamescreen/MultiNationSelectPopup.kt
Normal file
@ -0,0 +1,170 @@
|
||||
package com.unciv.ui.newgamescreen
|
||||
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.scenes.scene2d.Group
|
||||
import com.badlogic.gdx.scenes.scene2d.Touchable
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.ImageButton
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||
import com.badlogic.gdx.utils.Align
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.models.metadata.GameParameters
|
||||
import com.unciv.models.ruleset.nation.Nation
|
||||
import com.unciv.models.translations.tr
|
||||
import com.unciv.ui.images.ImageGetter
|
||||
import com.unciv.ui.popup.Popup
|
||||
import com.unciv.ui.utils.AutoScrollPane
|
||||
import com.unciv.ui.utils.BaseScreen
|
||||
import com.unciv.ui.utils.KeyCharAndCode
|
||||
import com.unciv.ui.utils.extensions.isNarrowerThan4to3
|
||||
import com.unciv.ui.utils.extensions.keyShortcuts
|
||||
import com.unciv.ui.utils.extensions.onActivation
|
||||
import com.unciv.ui.utils.extensions.onClick
|
||||
import com.unciv.ui.utils.extensions.surroundWithCircle
|
||||
|
||||
|
||||
class MultiNationSelectPopup(
|
||||
previousScreen: IPreviousScreen,
|
||||
val gameParameters: GameParameters,
|
||||
val majorCivs: Boolean
|
||||
) : Popup(previousScreen as BaseScreen) {
|
||||
companion object {
|
||||
// These are used for the Close/OK buttons in the lower left/right corners:
|
||||
const val buttonsCircleSize = 70f
|
||||
const val buttonsIconSize = 50f
|
||||
const val buttonsOffsetFromEdge = 5f
|
||||
val buttonsBackColor: Color = Color.BLACK.cpy().apply { a = 0.67f }
|
||||
}
|
||||
|
||||
private val blockWidth: Float = 0f
|
||||
private val civBlocksWidth = if(blockWidth <= 10f) previousScreen.stage.width / 3 - 5f else blockWidth
|
||||
|
||||
// This Popup's body has two halves of same size, either side by side or arranged vertically
|
||||
// depending on screen proportions - determine height for one of those
|
||||
private val partHeight = stageToShowOn.height * (if (stageToShowOn.isNarrowerThan4to3()) 0.45f else 0.8f)
|
||||
private val nationListTable = Table()
|
||||
private val nationListScroll = AutoScrollPane(nationListTable)
|
||||
private val selectedNationsListTable = Table()
|
||||
private val selectedNationsListScroll = AutoScrollPane(selectedNationsListTable)
|
||||
private var selectedNations = gameParameters.randomNations
|
||||
var nations = arrayListOf<Nation>()
|
||||
|
||||
|
||||
init {
|
||||
var nationListScrollY = 0f
|
||||
nations += if(majorCivs) {
|
||||
previousScreen.ruleset.nations.values.asSequence()
|
||||
.filter { it.isMajorCiv() }
|
||||
} else {
|
||||
previousScreen.ruleset.nations.values.asSequence()
|
||||
.filter { it.isCityState() }
|
||||
}
|
||||
|
||||
nationListScroll.setOverscroll(false, false)
|
||||
add(nationListScroll).size( civBlocksWidth + 10f, partHeight )
|
||||
// +10, because the nation table has a 5f pad, for a total of +10f
|
||||
if (stageToShowOn.isNarrowerThan4to3()) row()
|
||||
selectedNationsListScroll.setOverscroll(false, false)
|
||||
add(selectedNationsListScroll).size(civBlocksWidth + 10f, partHeight) // Same here, see above
|
||||
|
||||
update()
|
||||
|
||||
nationListScroll.layout()
|
||||
pack()
|
||||
if (nationListScrollY > 0f) {
|
||||
// center the selected nation vertically, getRowHeight safe because nationListScrollY > 0f ensures at least 1 row
|
||||
nationListScrollY -= (nationListScroll.height - nationListTable.getRowHeight(0)) / 2
|
||||
nationListScroll.scrollY = nationListScrollY.coerceIn(0f, nationListScroll.maxY)
|
||||
}
|
||||
|
||||
val closeButton = "OtherIcons/Close".toImageButton(Color.FIREBRICK)
|
||||
closeButton.onActivation { close() }
|
||||
closeButton.keyShortcuts.add(KeyCharAndCode.BACK)
|
||||
closeButton.setPosition(buttonsOffsetFromEdge, buttonsOffsetFromEdge, Align.bottomLeft)
|
||||
innerTable.addActor(closeButton)
|
||||
|
||||
val okButton = "OtherIcons/Checkmark".toImageButton(Color.LIME)
|
||||
okButton.onClick { returnSelected() }
|
||||
okButton.setPosition(innerTable.width - buttonsOffsetFromEdge, buttonsOffsetFromEdge, Align.bottomRight)
|
||||
innerTable.addActor(okButton)
|
||||
|
||||
selectedNationsListTable.touchable = Touchable.enabled
|
||||
}
|
||||
|
||||
fun update() {
|
||||
nationListTable.clear()
|
||||
selectedNations = if (majorCivs) {
|
||||
gameParameters.randomNations
|
||||
} else {
|
||||
gameParameters.randomCityStates
|
||||
}
|
||||
nations -= selectedNations.toSet()
|
||||
nations = nations.sortedWith(compareBy(UncivGame.Current.settings.getCollatorFromLocale()) { it.name.tr() }).toMutableList() as ArrayList<Nation>
|
||||
|
||||
var currentY = 0f
|
||||
for (nation in nations) {
|
||||
val nationTable = NationTable(nation, civBlocksWidth, 0f) // no need for min height
|
||||
val cell = nationListTable.add(nationTable)
|
||||
currentY += cell.padBottom + cell.prefHeight + cell.padTop
|
||||
cell.row()
|
||||
nationTable.onClick {
|
||||
addNationToPool(nation)
|
||||
}
|
||||
}
|
||||
|
||||
if (selectedNations.isNotEmpty()) {
|
||||
selectedNationsListTable.clear()
|
||||
|
||||
for (currentNation in selectedNations) {
|
||||
val nationTable = NationTable(currentNation, civBlocksWidth, 0f)
|
||||
nationTable.onClick { removeNationFromPool(currentNation) }
|
||||
selectedNationsListTable.add(nationTable).row()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun String.toImageButton(overColor: Color): Group {
|
||||
val style = ImageButton.ImageButtonStyle()
|
||||
val image = ImageGetter.getDrawable(this)
|
||||
style.imageUp = image
|
||||
style.imageOver = image.tint(overColor)
|
||||
val button = ImageButton(style)
|
||||
button.setSize(buttonsIconSize, buttonsIconSize)
|
||||
|
||||
return button.surroundWithCircle(buttonsCircleSize, false, buttonsBackColor)
|
||||
}
|
||||
|
||||
private fun updateNationListTable() {
|
||||
selectedNationsListTable.clear()
|
||||
|
||||
for (currentNation in selectedNations) {
|
||||
val nationTable = NationTable(currentNation, civBlocksWidth, 0f)
|
||||
nationTable.onClick { removeNationFromPool(currentNation) }
|
||||
selectedNationsListTable.add(nationTable).row()
|
||||
}
|
||||
}
|
||||
|
||||
private fun addNationToPool(nation: Nation) {
|
||||
selectedNations.add(nation)
|
||||
|
||||
update()
|
||||
updateNationListTable()
|
||||
}
|
||||
|
||||
private fun removeNationFromPool(nation: Nation) {
|
||||
nations.add(nation)
|
||||
selectedNations.remove(nation)
|
||||
|
||||
update()
|
||||
updateNationListTable()
|
||||
}
|
||||
|
||||
private fun returnSelected() {
|
||||
close()
|
||||
if (majorCivs)
|
||||
gameParameters.randomNations = selectedNations
|
||||
else
|
||||
gameParameters.randomCityStates = selectedNations
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user