Adding units on map editor. (#2667)

* Adding units to map editor.

* loadScenario checkbox Prototype added to MapOptions table.

* adds switch for Scenario and Unit editor debug

* New Scenario class

* Background step1:
1. Create a new class Scenario, containing TileMap, GameParameters and string name (doesn't really matter where, we can move it around later)
2. Create SaveScenario and LoadScenario functions in MapSaver (save to/ load from scenario name)

* Prototype of Save/Load scenario implementation.

* Add update method to NewGameOptionsTable

* First working Save/Load scenario prototype

* First working prototype of Load/Save scenario

* Added test conditions for the new debug modes

* Resolve merge conflict

Co-authored-by: Yair Morgenstern <yairm210@hotmail.com>
This commit is contained in:
Alexander Korolyov 2020-06-13 15:53:04 -04:00 committed by GitHub
parent 1961aa7245
commit c3da044c43
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 297 additions and 81 deletions

1
.gitignore vendored
View file

@ -137,3 +137,4 @@ android/release/
android/assets/mods/
android/assets/SaveFiles/
android/assets/GameSettingsOld.json
android/assets/scenarios/

View file

@ -56,6 +56,9 @@ class UncivGame(
/** Console log battles
*/
val alertBattle = true
/** Debug new Scenario functionality
*/
val scenarioDebugSwitch = false
lateinit var worldScreen: WorldScreen

View file

@ -21,7 +21,9 @@ object GameStarter {
gameInfo.gameParameters = gameSetupInfo.gameParameters
val ruleset = RulesetCache.getComplexRuleset(gameInfo.gameParameters.mods)
if (gameSetupInfo.mapParameters.name != "")
if (gameSetupInfo.mapParameters.type == MapType.scenario)
gameInfo.tileMap = MapSaver.loadScenario(gameSetupInfo.mapParameters.name).tileMap
else if (gameSetupInfo.mapParameters.name != "")
gameInfo.tileMap = MapSaver.loadMap(gameSetupInfo.mapParameters.name)
else gameInfo.tileMap = MapGenerator(ruleset).generateMap(gameSetupInfo.mapParameters)
gameInfo.tileMap.mapParameters = gameSetupInfo.mapParameters

View file

@ -1,6 +1,7 @@
package com.unciv.logic
import com.badlogic.gdx.Gdx
import com.unciv.logic.map.Scenario
import com.unciv.logic.map.TileMap
import com.unciv.ui.saves.Gzip
@ -9,23 +10,36 @@ object MapSaver {
fun json() = GameSaver.json()
private const val mapsFolder = "maps"
private const val scenariosFolder = "scenarios"
private fun getMap(mapName:String) = Gdx.files.local("$mapsFolder/$mapName")
private fun getScenario(scenarioName:String) = Gdx.files.local("$scenariosFolder/$scenarioName")
fun saveMap(mapName: String,tileMap: TileMap) {
getMap(mapName).writeString(Gzip.zip(json().toJson(tileMap)), false)
}
fun saveScenario(scenarioName:String, scenario: Scenario) {
getScenario(scenarioName).writeString(json().toJson(scenario), false)
}
fun loadMap(mapName: String): TileMap {
val gzippedString = getMap(mapName).readString()
val unzippedJson = Gzip.unzip(gzippedString)
return json().fromJson(TileMap::class.java, unzippedJson)
}
fun loadScenario(scenarioName: String): Scenario {
val scenarioJson = getScenario(scenarioName).readString()
return json().fromJson(Scenario::class.java, scenarioJson)
}
fun deleteMap(mapName: String) = getMap(mapName).delete()
fun getMaps() = Gdx.files.local(mapsFolder).list().map { it.name() }
fun getScenarios() = Gdx.files.local(scenariosFolder).list().map { it.name() }
fun mapFromJson(json:String): TileMap = json().fromJson(TileMap::class.java, json)
}

View file

@ -25,6 +25,9 @@ object MapType {
// Non-generated maps
const val custom = "Custom"
// Loaded scenario
const val scenario = "Scenario"
// All ocean tiles
const val empty = "Empty"
}

View file

@ -0,0 +1,16 @@
package com.unciv.logic.map
import com.unciv.models.metadata.GameParameters
class Scenario {
lateinit var tileMap: TileMap
lateinit var gameParameters: GameParameters
/** for json parsing, we need to have a default constructor */
constructor()
constructor(tileMap:TileMap, gameParameters: GameParameters) {
this.tileMap = tileMap
this.gameParameters = gameParameters
}
}

View file

@ -9,6 +9,11 @@ import com.unciv.UncivGame
import com.unciv.logic.MapSaver
import com.unciv.logic.map.MapType
import com.unciv.logic.map.RoadStatus
import com.unciv.logic.map.Scenario
import com.unciv.logic.map.TileMap
import com.unciv.models.metadata.Player
import com.unciv.ui.newgamescreen.GameOptionsTable
import com.unciv.ui.newgamescreen.PlayerPickerTable
import com.unciv.ui.saves.Gzip
import com.unciv.ui.utils.*
import com.unciv.ui.worldscreen.mainmenu.DropBox
@ -118,6 +123,32 @@ class MapEditorMenuPopup(mapEditorScreen: MapEditorScreen): Popup(mapEditorScree
}
add(uploadMapButton).row()
if (UncivGame.Current.scenarioDebugSwitch) {
val createScenarioButton = "Create scenario".toTextButton()
add(createScenarioButton).row()
createScenarioButton.onClick {
remove()
mapEditorScreen.gameSetupInfo.gameParameters.players = getPlayersFromMap(mapEditorScreen.tileMap) // update players list from tileMap starting locations
val gameParametersPopup = Popup(screen)
val playerPickerTable = PlayerPickerTable(mapEditorScreen, mapEditorScreen.gameSetupInfo.gameParameters)
val gameOptionsTable = GameOptionsTable(mapEditorScreen) {desiredCiv: String -> playerPickerTable.update(desiredCiv)}
val scenarioNameEditor = TextField(mapEditorScreen.mapName, skin)
gameParametersPopup.add(playerPickerTable)
gameParametersPopup.addSeparatorVertical()
gameParametersPopup.add(gameOptionsTable).row()
gameParametersPopup.add(scenarioNameEditor)
gameParametersPopup.addButton("Save scenario"){
mapEditorScreen.tileMap.mapParameters.type=MapType.scenario
MapSaver.saveScenario(scenarioNameEditor.text, Scenario(mapEditorScreen.tileMap, mapEditorScreen.gameSetupInfo.gameParameters))
ResponsePopup("Scenario saved", mapEditorScreen)
gameParametersPopup.close()
}.row()
gameParametersPopup.addCloseButton().row()
gameParametersPopup.open()
}
}
val exitMapEditorButton = "Exit map editor".toTextButton()
add(exitMapEditorButton ).row()
@ -128,3 +159,15 @@ class MapEditorMenuPopup(mapEditorScreen: MapEditorScreen): Popup(mapEditorScree
add(closeOptionsButton).row()
}
}
private fun getPlayersFromMap(tileMap: TileMap): ArrayList<Player> {
val tilesWithStartingLocations = tileMap.values
.filter { it.improvement != null && it.improvement!!.startsWith("StartingLocation ") }
var players = ArrayList<Player>()
for (tile in tilesWithStartingLocations) {
players.add(Player().apply{
chosenCiv = tile.improvement!!.removePrefix("StartingLocation ")
})
}
return players
}

View file

@ -5,17 +5,24 @@ import com.badlogic.gdx.math.Vector2
import com.badlogic.gdx.scenes.scene2d.InputEvent
import com.badlogic.gdx.scenes.scene2d.InputListener
import com.badlogic.gdx.scenes.scene2d.actions.Actions
import com.badlogic.gdx.scenes.scene2d.ui.SelectBox
import com.badlogic.gdx.scenes.scene2d.ui.Skin
import com.badlogic.gdx.utils.Array
import com.unciv.logic.MapSaver
import com.unciv.logic.map.TileInfo
import com.unciv.logic.map.TileMap
import com.unciv.models.ruleset.RulesetCache
import com.unciv.models.translations.tr
import com.unciv.ui.newgamescreen.GameParametersPreviousScreen
import com.unciv.ui.newgamescreen.GameSetupInfo
import com.unciv.ui.utils.*
class MapEditorScreen(): CameraStageBaseScreen() {
val ruleset = RulesetCache.getBaseRuleset()
class MapEditorScreen(): GameParametersPreviousScreen() {
override val ruleset = RulesetCache.getBaseRuleset()
var mapName = ""
var tileMap = TileMap()
override var gameSetupInfo = GameSetupInfo()
lateinit var mapHolder: EditorMapHolder
val tileEditorOptions = TileEditorOptionsTable(this)
@ -149,4 +156,19 @@ class MapEditorScreen(): CameraStageBaseScreen() {
}
}
class TranslatedSelectBox(values : Collection<String>, default:String, skin: Skin) : SelectBox<TranslatedSelectBox.TranslatedString>(skin) {
class TranslatedString(val value: String) {
val translation = value.tr()
override fun toString() = translation
}
init {
val array = Array<TranslatedString>()
values.forEach { array.add(TranslatedString(it)) }
items = array
val defaultItem = array.firstOrNull { it.value == default }
selected = if (defaultItem != null) defaultItem else array.first()
}
}

View file

@ -12,6 +12,8 @@ import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.logic.map.MapUnit
import com.unciv.logic.map.RoadStatus
import com.unciv.logic.map.TileInfo
import com.unciv.logic.map.TileMap
import com.unciv.models.ruleset.Nation
import com.unciv.models.ruleset.tile.ResourceType
import com.unciv.models.ruleset.tile.TerrainType
import com.unciv.models.translations.tr
@ -48,8 +50,10 @@ class TileEditorOptionsTable(val mapEditorScreen: MapEditorScreen): Table(Camera
.onClick { setImprovements() }
tabPickerTable.add(improvementsButton)
// val unitsButton = "Units".toTextButton().onClick { setUnits() }
// tabPickerTable.add(unitsButton)
if (UncivGame.Current.scenarioDebugSwitch) {
val unitsButton = "Units".toTextButton().onClick { setUnits() }
tabPickerTable.add(unitsButton)
}
tabPickerTable.pack()
@ -154,11 +158,15 @@ class TileEditorOptionsTable(val mapEditorScreen: MapEditorScreen): Table(Camera
}
val nationsTable = Table()
for(nation in ruleset.nations.values){
val nations = nationsFromMap(mapEditorScreen.tileMap)
val barbarians = ruleset.nations.values.filter { it.isBarbarian()}
for(nation in nations + barbarians){
val nationImage = ImageGetter.getNationIndicator(nation, 40f)
nationsTable.add(nationImage).row()
nationImage.onClick { currentNation = nation; setUnitTileAction() }
}
editorPickTable.add(ScrollPane(nationsTable)).height(stage.height*0.8f)
val unitsTable = Table()
@ -170,6 +178,18 @@ class TileEditorOptionsTable(val mapEditorScreen: MapEditorScreen): Table(Camera
editorPickTable.add(ScrollPane(unitsTable)).height(stage.height*0.8f)
}
private fun nationsFromMap(tileMap: TileMap): ArrayList<Nation> {
val tilesWithStartingLocations = tileMap.values
.filter { it.improvement != null && it.improvement!!.startsWith("StartingLocation ") }
var nations = ArrayList<Nation>()
for (tile in tilesWithStartingLocations) {
var civName = tile.improvement!!.removePrefix("StartingLocation ")
nations.add(ruleset.nations[civName]!!)
}
return nations
}
private fun getRedCross(size: Float, alpha: Float): Actor {
val redCross = ImageGetter.getImage("OtherIcons/Close")
redCross.setSize( size, size)

View file

@ -8,17 +8,24 @@ import com.unciv.models.metadata.GameSpeed
import com.unciv.models.ruleset.RulesetCache
import com.unciv.models.ruleset.VictoryType
import com.unciv.models.translations.tr
import com.unciv.ui.utils.CameraStageBaseScreen
import com.unciv.ui.utils.ImageGetter
import com.unciv.ui.utils.onChange
import com.unciv.ui.utils.toLabel
import com.unciv.ui.utils.*
class NewGameOptionsTable(newGameScreen: NewGameScreen, val updatePlayerPickerTable:(desiredCiv:String)->Unit)
class GameOptionsTable(previousScreen: GameParametersPreviousScreen, val updatePlayerPickerTable:(desiredCiv:String)->Unit)
: Table(CameraStageBaseScreen.skin) {
val newGameParameters = newGameScreen.gameSetupInfo.gameParameters
val ruleset = newGameScreen.ruleset
var gameParameters = previousScreen.gameSetupInfo.gameParameters
val ruleset = previousScreen.ruleset
var locked = false
init {
getGameOptionsTable()
}
fun update() {
clear()
getGameOptionsTable()
}
private fun getGameOptionsTable() {
top()
defaults().pad(5f)
@ -46,26 +53,27 @@ class NewGameOptionsTable(newGameScreen: NewGameScreen, val updatePlayerPickerTa
private fun Table.addCheckbox(text: String, initialState: Boolean, onChange: (newValue: Boolean) -> Unit) {
val checkbox = CheckBox(text.tr(), CameraStageBaseScreen.skin)
checkbox.isChecked = initialState
checkbox.isDisabled = locked
checkbox.onChange { onChange(checkbox.isChecked) }
add(checkbox).colspan(2).left().row()
}
private fun Table.addBarbariansCheckbox() =
addCheckbox("No Barbarians", newGameParameters.noBarbarians)
{ newGameParameters.noBarbarians = it }
addCheckbox("No Barbarians", gameParameters.noBarbarians)
{ gameParameters.noBarbarians = it }
private fun Table.addOneCityChallengeCheckbox() =
addCheckbox("One City Challenge", newGameParameters.oneCityChallenge)
{ newGameParameters.oneCityChallenge = it }
addCheckbox("One City Challenge", gameParameters.oneCityChallenge)
{ gameParameters.oneCityChallenge = it }
private fun Table.addNuclearWeaponsCheckbox() =
addCheckbox("Enable nuclear weapons", newGameParameters.nuclearWeaponsEnabled)
{ newGameParameters.nuclearWeaponsEnabled = it }
addCheckbox("Enable nuclear weapons", gameParameters.nuclearWeaponsEnabled)
{ gameParameters.nuclearWeaponsEnabled = it }
private fun Table.addIsOnlineMultiplayerCheckbox() =
addCheckbox("Online Multiplayer", newGameParameters.isOnlineMultiplayer)
{ newGameParameters.isOnlineMultiplayer = it
addCheckbox("Online Multiplayer", gameParameters.isOnlineMultiplayer)
{ gameParameters.isOnlineMultiplayer = it
updatePlayerPickerTable("") }
private fun addCityStatesSelectBox() {
@ -78,34 +86,36 @@ class NewGameOptionsTable(newGameScreen: NewGameScreen, val updatePlayerPickerTa
(0..numberOfCityStates).forEach { cityStatesArray.add(it) }
cityStatesSelectBox.items = cityStatesArray
cityStatesSelectBox.selected = newGameParameters.numberOfCityStates
cityStatesSelectBox.selected = gameParameters.numberOfCityStates
add(cityStatesSelectBox).width(50f).row()
cityStatesSelectBox.isDisabled = locked
cityStatesSelectBox.onChange {
newGameParameters.numberOfCityStates = cityStatesSelectBox.selected
gameParameters.numberOfCityStates = cityStatesSelectBox.selected
}
}
fun Table.addSelectBox(text: String, values: Collection<String>, initialState: String, onChange: (newValue: String) -> Unit) {
add(text.toLabel()).left()
val selectBox = TranslatedSelectBox(values, initialState, CameraStageBaseScreen.skin)
selectBox.isDisabled = locked
selectBox.onChange { onChange(selectBox.selected.value) }
add(selectBox).fillX().row()
}
private fun Table.addDifficultySelectBox() {
addSelectBox("{Difficulty}:", ruleset.difficulties.keys, newGameParameters.difficulty)
{ newGameParameters.difficulty = it }
addSelectBox("{Difficulty}:", ruleset.difficulties.keys, gameParameters.difficulty)
{ gameParameters.difficulty = it }
}
private fun Table.addGameSpeedSelectBox() {
addSelectBox("{Game Speed}:", GameSpeed.values().map { it.name }, newGameParameters.gameSpeed.name)
{ newGameParameters.gameSpeed = GameSpeed.valueOf(it) }
addSelectBox("{Game Speed}:", GameSpeed.values().map { it.name }, gameParameters.gameSpeed.name)
{ gameParameters.gameSpeed = GameSpeed.valueOf(it) }
}
private fun Table.addEraSelectBox() {
val eras = ruleset.technologies.values.map { it.era() }.distinct()
addSelectBox("{Starting Era}:", eras, newGameParameters.startingEra)
{ newGameParameters.startingEra = it }
addSelectBox("{Starting Era}:", eras, gameParameters.startingEra)
{ gameParameters.startingEra = it }
}
@ -119,13 +129,14 @@ class NewGameOptionsTable(newGameScreen: NewGameScreen, val updatePlayerPickerTa
if (victoryType == VictoryType.Neutral) continue
val victoryCheckbox = CheckBox(victoryType.name.tr(), CameraStageBaseScreen.skin)
victoryCheckbox.name = victoryType.name
victoryCheckbox.isChecked = newGameParameters.victoryTypes.contains(victoryType)
victoryCheckbox.isChecked = gameParameters.victoryTypes.contains(victoryType)
victoryCheckbox.isDisabled = locked
victoryCheckbox.onChange {
// If the checkbox is checked, adds the victoryTypes else remove it
if (victoryCheckbox.isChecked) {
newGameParameters.victoryTypes.add(victoryType)
gameParameters.victoryTypes.add(victoryType)
} else {
newGameParameters.victoryTypes.remove(victoryType)
gameParameters.victoryTypes.remove(victoryType)
}
}
victoryConditionsTable.add(victoryCheckbox).left()
@ -141,9 +152,9 @@ class NewGameOptionsTable(newGameScreen: NewGameScreen, val updatePlayerPickerTa
fun reloadMods() {
ruleset.clear()
val newRuleset = RulesetCache.getComplexRuleset(newGameParameters.mods)
val newRuleset = RulesetCache.getComplexRuleset(gameParameters.mods)
ruleset.add(newRuleset)
ruleset.mods += newGameParameters.mods
ruleset.mods += gameParameters.mods
ruleset.modOptions = newRuleset.modOptions
ImageGetter.ruleset = ruleset
@ -154,10 +165,11 @@ class NewGameOptionsTable(newGameScreen: NewGameScreen, val updatePlayerPickerTa
val modCheckboxTable = Table().apply { defaults().pad(5f) }
for (mod in modRulesets) {
val checkBox = CheckBox(mod.name.tr(), CameraStageBaseScreen.skin)
if (mod.name in newGameParameters.mods) checkBox.isChecked = true
checkBox.isDisabled = locked
if (mod.name in gameParameters.mods) checkBox.isChecked = true
checkBox.onChange {
if (checkBox.isChecked) newGameParameters.mods.add(mod.name)
else newGameParameters.mods.remove(mod.name)
if (checkBox.isChecked) gameParameters.mods.add(mod.name)
else gameParameters.mods.remove(mod.name)
reloadMods()
var desiredCiv = ""
if (checkBox.isChecked) {

View file

@ -0,0 +1,11 @@
package com.unciv.ui.newgamescreen
import com.badlogic.gdx.scenes.scene2d.Stage
import com.unciv.models.ruleset.Ruleset
import com.unciv.ui.pickerscreens.PickerScreen
import com.unciv.ui.utils.CameraStageBaseScreen
abstract class GameParametersPreviousScreen: PickerScreen() {
abstract var gameSetupInfo: GameSetupInfo
abstract val ruleset: Ruleset
}

View file

@ -15,10 +15,10 @@ class MapOptionsTable(val newGameScreen: NewGameScreen): Table() {
private var mapTypeSpecificTable = Table()
private val generatedMapOptionsTable = MapParametersTable(mapParameters)
private val savedMapOptionsTable = Table()
private val savedScenarioOptionsTable = Table()
init {
defaults().pad(5f)
add("Map Options".toLabel(fontSize = 24)).top().padBottom(20f).colspan(2).row()
addMapTypeSelection()
}
@ -28,6 +28,7 @@ class MapOptionsTable(val newGameScreen: NewGameScreen): Table() {
add("{Map Type}:".toLabel())
val mapTypes = arrayListOf("Generated")
if (MapSaver.getMaps().isNotEmpty()) mapTypes.add(MapType.custom)
if (MapSaver.getScenarios().isNotEmpty()) mapTypes.add(MapType.scenario)
val mapTypeSelectBox = TranslatedSelectBox(mapTypes, "Generated", CameraStageBaseScreen.skin)
val mapFileSelectBox = getMapFileSelectBox()
@ -37,16 +38,39 @@ class MapOptionsTable(val newGameScreen: NewGameScreen): Table() {
savedMapOptionsTable.add(mapFileSelectBox).maxWidth(newGameScreen.stage.width / 2)
.right().row()
val scenarioFileSelectBox = getScenarioFileSelectBox()
savedScenarioOptionsTable.defaults().pad(5f)
savedScenarioOptionsTable.add("{Scenario file}:".toLabel()).left()
// because SOME people gotta give the hugest names to their maps
savedScenarioOptionsTable.add(scenarioFileSelectBox).maxWidth(newGameScreen.stage.width / 2)
.right().row()
fun updateOnMapTypeChange() {
mapTypeSpecificTable.clear()
if (mapTypeSelectBox.selected.value == MapType.custom) {
mapParameters.type = MapType.custom
mapParameters.name = mapFileSelectBox.selected
mapTypeSpecificTable.add(savedMapOptionsTable)
newGameScreen.gameSetupInfo = GameSetupInfo()
newGameScreen.unlockTables()
newGameScreen.updateTables()
} else if (mapTypeSelectBox.selected.value == MapType.scenario) {
mapParameters.type = MapType.scenario
mapParameters.name = scenarioFileSelectBox.selected
mapTypeSpecificTable.add(savedScenarioOptionsTable)
val scenario = MapSaver.loadScenario(mapParameters.name)
newGameScreen.gameSetupInfo.gameParameters = scenario.gameParameters
newGameScreen.gameSetupInfo.mapParameters = mapParameters
// update PlayerTable and GameOptionsTable
newGameScreen.lockTables()
newGameScreen.updateTables()
} else {
mapParameters.name = ""
mapParameters.type = generatedMapOptionsTable.mapTypeSelectBox.selected.value
mapTypeSpecificTable.add(generatedMapOptionsTable)
newGameScreen.gameSetupInfo = GameSetupInfo()
newGameScreen.unlockTables()
newGameScreen.updateTables()
}
}
@ -59,7 +83,6 @@ class MapOptionsTable(val newGameScreen: NewGameScreen): Table() {
add(mapTypeSpecificTable).colspan(2).row()
}
private fun getMapFileSelectBox(): SelectBox<String> {
val mapFileSelectBox = SelectBox<String>(CameraStageBaseScreen.skin)
val mapNames = Array<String>()
@ -71,4 +94,21 @@ class MapOptionsTable(val newGameScreen: NewGameScreen): Table() {
return mapFileSelectBox
}
private fun getScenarioFileSelectBox(): SelectBox<String> {
val scenarioFileSelectBox = SelectBox<String>(CameraStageBaseScreen.skin)
val scenarioNames = Array<String>()
for (scenarioName in MapSaver.getScenarios()) scenarioNames.add(scenarioName)
scenarioFileSelectBox.items = scenarioNames
if (mapParameters.name in scenarioNames) scenarioFileSelectBox.selected = mapParameters.name
scenarioFileSelectBox.onChange {
mapParameters.name = scenarioFileSelectBox.selected!!
val scenario = MapSaver.loadScenario(mapParameters.name)
newGameScreen.gameSetupInfo.gameParameters = scenario.gameParameters
newGameScreen.updateTables()
}
return scenarioFileSelectBox
}
}

View file

@ -2,20 +2,18 @@ package com.unciv.ui.newgamescreen
import com.unciv.ui.utils.AutoScrollPane as ScrollPane
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.scenes.scene2d.ui.CheckBox
import com.badlogic.gdx.scenes.scene2d.ui.SelectBox
import com.badlogic.gdx.scenes.scene2d.ui.Skin
import com.badlogic.gdx.utils.Array
import com.unciv.UncivGame
import com.unciv.logic.GameInfo
import com.unciv.logic.GameSaver
import com.unciv.logic.GameStarter
import com.unciv.logic.IdChecker
import com.unciv.logic.*
import com.unciv.logic.civilization.PlayerType
import com.unciv.logic.map.MapParameters
import com.unciv.logic.map.MapType
import com.unciv.models.metadata.GameParameters
import com.unciv.models.ruleset.RulesetCache
import com.unciv.models.translations.tr
import com.unciv.ui.pickerscreens.PickerScreen
import com.unciv.ui.utils.*
import com.unciv.ui.worldscreen.mainmenu.OnlineMultiplayer
import java.util.*
@ -27,18 +25,21 @@ class GameSetupInfo(var gameId:String, var gameParameters: GameParameters, var m
constructor(gameInfo: GameInfo) : this("", gameInfo.gameParameters.clone(), gameInfo.tileMap.mapParameters)
}
class NewGameScreen(previousScreen:CameraStageBaseScreen, _gameSetupInfo: GameSetupInfo?=null): PickerScreen() {
class NewGameScreen(previousScreen:CameraStageBaseScreen, _gameSetupInfo: GameSetupInfo?=null): GameParametersPreviousScreen() {
var gameSetupInfo: GameSetupInfo = _gameSetupInfo ?: GameSetupInfo()
val ruleset = RulesetCache.getComplexRuleset(gameSetupInfo.gameParameters.mods)
override var gameSetupInfo: GameSetupInfo = _gameSetupInfo ?: GameSetupInfo()
override val ruleset = RulesetCache.getComplexRuleset(gameSetupInfo.gameParameters.mods)
var playerPickerTable = PlayerPickerTable(this, gameSetupInfo.gameParameters)
var newGameOptionsTable = GameOptionsTable(this) { desiredCiv: String -> playerPickerTable.update(desiredCiv) }
var mapOptionsTable = MapOptionsTable(this)
init {
setDefaultCloseAction(previousScreen)
scrollPane.setScrollingDisabled(true, true)
val playerPickerTable = PlayerPickerTable(this, gameSetupInfo.gameParameters)
val newGameOptionsTable = NewGameOptionsTable(this) { desiredCiv: String -> playerPickerTable.update(desiredCiv) }
topTable.add(ScrollPane(MapOptionsTable(this)).apply { setOverscroll(false, false) })
// val playerPickerTable = PlayerPickerTable(this, gameSetupInfo.gameParameters)
// val newGameOptionsTable = GameOptionsTable(this) { desiredCiv: String -> playerPickerTable.update(desiredCiv) }
topTable.add(ScrollPane(mapOptionsTable).apply { setOverscroll(false, false) })
.maxHeight(topTable.parent.height).width(stage.width / 3).padTop(20f).top()
topTable.addSeparatorVertical()
topTable.add(playerPickerTable).maxHeight(topTable.parent.height).width(stage.width / 3).padTop(20f).top()
@ -124,11 +125,27 @@ class NewGameScreen(previousScreen:CameraStageBaseScreen, _gameSetupInfo: GameSe
Gdx.graphics.requestRendering()
}
fun setNewGameButtonEnabled(bool: Boolean) {
if (bool) rightSideButton.enable()
else rightSideButton.disable()
// fun setNewGameButtonEnabled(bool: Boolean) {
// if (bool) rightSideButton.enable()
// else rightSideButton.disable()
// }
fun lockTables() {
playerPickerTable.locked = true
newGameOptionsTable.locked = true
}
fun unlockTables() {
playerPickerTable.locked = false
newGameOptionsTable.locked = false
}
fun updateTables() {
playerPickerTable.gameParameters = gameSetupInfo.gameParameters
playerPickerTable.update()
newGameOptionsTable.gameParameters = gameSetupInfo.gameParameters
newGameOptionsTable.update()
}
var newGame: GameInfo? = null

View file

@ -6,7 +6,6 @@ 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.Table
import com.badlogic.gdx.scenes.scene2d.ui.TextButton
import com.badlogic.gdx.scenes.scene2d.ui.TextField
import com.badlogic.gdx.utils.Align
import com.unciv.Constants
@ -20,10 +19,12 @@ import com.unciv.models.translations.tr
import com.unciv.ui.utils.*
import java.util.*
class PlayerPickerTable(val newGameScreen: NewGameScreen, val newGameParameters: GameParameters): Table() {
class PlayerPickerTable(val previousScreen: GameParametersPreviousScreen, var gameParameters: GameParameters): Table() {
val playerListTable = Table()
val nationsPopupWidth = newGameScreen.stage.width / 2f
val civBlocksWidth = newGameScreen.stage.width / 3
val nationsPopupWidth = previousScreen.stage.width / 2f
val civBlocksWidth = previousScreen.stage.width / 3
var locked = false
init {
top()
@ -34,36 +35,37 @@ class PlayerPickerTable(val newGameScreen: NewGameScreen, val newGameParameters:
fun update(desiredCiv: String = "") {
playerListTable.clear()
val gameBasics = newGameScreen.ruleset // the mod picking changes this ruleset
val gameBasics = previousScreen.ruleset // the mod picking changes this ruleset
reassignRemovedModReferences()
val newRulesetPlayableCivs = newGameScreen.ruleset.nations.count { it.key != Constants.barbarians }
if (newGameParameters.players.size > newRulesetPlayableCivs)
newGameParameters.players = ArrayList(newGameParameters.players.subList(0, newRulesetPlayableCivs))
val newRulesetPlayableCivs = previousScreen.ruleset.nations.count { it.key != Constants.barbarians }
if (gameParameters.players.size > newRulesetPlayableCivs)
gameParameters.players = ArrayList(gameParameters.players.subList(0, newRulesetPlayableCivs))
if (desiredCiv.isNotEmpty()) assignDesiredCiv(desiredCiv)
for (player in newGameParameters.players) {
for (player in gameParameters.players) {
playerListTable.add(getPlayerTable(player, gameBasics)).width(civBlocksWidth).padBottom(20f).row()
}
if (newGameParameters.players.count() < gameBasics.nations.values.count { it.isMajorCiv() }) {
if (gameParameters.players.count() < gameBasics.nations.values.count { it.isMajorCiv() }
&& !locked) {
playerListTable.add("+".toLabel(Color.BLACK, 30).apply { this.setAlignment(Align.center) }
.surroundWithCircle(50f).onClick { newGameParameters.players.add(Player()); update() }).pad(10f)
.surroundWithCircle(50f).onClick { gameParameters.players.add(Player()); update() }).pad(10f)
}
newGameScreen.setNewGameButtonEnabled(newGameParameters.players.size > 1)
previousScreen.setRightSideButtonEnabled(gameParameters.players.size > 1)
}
private fun reassignRemovedModReferences() {
for (player in newGameParameters.players) {
if (!newGameScreen.ruleset.nations.containsKey(player.chosenCiv))
for (player in gameParameters.players) {
if (!previousScreen.ruleset.nations.containsKey(player.chosenCiv))
player.chosenCiv = "Random"
}
}
private fun assignDesiredCiv(desiredCiv: String) {
// No auto-select if desiredCiv already used
if (newGameParameters.players.any { it.chosenCiv == desiredCiv }) return
if (gameParameters.players.any { it.chosenCiv == desiredCiv }) return
// Do auto-select, silently no-op if no suitable slot (human with 'random' choice)
newGameParameters.players.firstOrNull { it.chosenCiv == "Random" && it.playerType == PlayerType.Human }?.chosenCiv = desiredCiv
gameParameters.players.firstOrNull { it.chosenCiv == "Random" && it.playerType == PlayerType.Human }?.chosenCiv = desiredCiv
}
fun getPlayerTable(player: Player, ruleset: Ruleset): Table {
@ -76,16 +78,19 @@ class PlayerPickerTable(val newGameScreen: NewGameScreen, val newGameParameters:
val playerTypeTextbutton = player.playerType.name.toTextButton()
playerTypeTextbutton.onClick {
if (locked) return@onClick
if (player.playerType == PlayerType.AI)
player.playerType = PlayerType.Human
else player.playerType = PlayerType.AI
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 { newGameParameters.players.remove(player); update() }).pad(5f).right().row()
if (newGameParameters.isOnlineMultiplayer && player.playerType == PlayerType.Human) {
.onClick { gameParameters.players.remove(player); update() }).pad(5f).right().row()
}
if (gameParameters.isOnlineMultiplayer && player.playerType == PlayerType.Human) {
val playerIdTextfield = TextField(player.playerId, CameraStageBaseScreen.skin)
playerIdTextfield.messageText = "Please input Player ID!".tr()
@ -129,7 +134,7 @@ class PlayerPickerTable(val newGameScreen: NewGameScreen, val newGameParameters:
.apply { this.setAlignment(Align.center) }
.surroundWithCircle(36f).apply { circle.color = Color.BLACK }
.surroundWithCircle(40f, false).apply { circle.color = Color.WHITE }
else ImageGetter.getNationIndicator(newGameScreen.ruleset.nations[player.chosenCiv]!!, 40f)
else ImageGetter.getNationIndicator(previousScreen.ruleset.nations[player.chosenCiv]!!, 40f)
nationTable.add(nationImage).pad(5f)
nationTable.add(player.chosenCiv.toLabel()).pad(5f)
nationTable.touchable = Touchable.enabled
@ -140,7 +145,7 @@ class PlayerPickerTable(val newGameScreen: NewGameScreen, val newGameParameters:
}
private fun popupNationPicker(player: Player) {
val nationsPopup = Popup(newGameScreen)
val nationsPopup = Popup(previousScreen)
val nationListTable = Table()
val randomPlayerTable = Table()
@ -160,18 +165,18 @@ class PlayerPickerTable(val newGameScreen: NewGameScreen, val newGameParameters:
nationListTable.add(randomPlayerTable).pad(10f).width(nationsPopupWidth).row()
for (nation in newGameScreen.ruleset.nations.values
for (nation in previousScreen.ruleset.nations.values
.filter { !it.isCityState() && it.name != Constants.barbarians }) {
if (player.chosenCiv != nation.name && newGameParameters.players.any { it.chosenCiv == nation.name })
if (player.chosenCiv != nation.name && gameParameters.players.any { it.chosenCiv == nation.name })
continue
nationListTable.add(NationTable(nation, nationsPopupWidth, newGameScreen.ruleset).onClick {
nationListTable.add(NationTable(nation, nationsPopupWidth, previousScreen.ruleset).onClick {
player.chosenCiv = nation.name
nationsPopup.close()
update()
}).pad(10f).width(nationsPopupWidth).row()
}
nationsPopup.add(ScrollPane(nationListTable)).height(newGameScreen.stage.height * 0.8f)
nationsPopup.add(ScrollPane(nationListTable)).height(previousScreen.stage.height * 0.8f)
nationsPopup.pack()
val closeImage = ImageGetter.getImage("OtherIcons/Close")

View file

@ -53,6 +53,11 @@ open class PickerScreen : CameraStageBaseScreen() {
}
}
fun setRightSideButtonEnabled(bool: Boolean) {
if (bool) rightSideButton.enable()
else rightSideButton.disable()
}
protected fun pick(rightButtonText: String) {
if(UncivGame.Current.worldScreen.isPlayersTurn) rightSideButton.enable()
rightSideButton.setText(rightButtonText)

View file

@ -39,7 +39,9 @@ class BasicTests {
Assert.assertTrue("This test will only pass if the game is not run with debug modes",
!game.superchargedForDebug
&& !game.viewEntireMapForDebug
&& game.simulateUntilTurnForDebug <= 0)
&& game.simulateUntilTurnForDebug <= 0
&& game.simulateUntilWinOrLose <= 0
&& !game.scenarioDebugSwitch)
}
// If there's a unit that obsoletes with no upgrade then when it obsoletes