diff --git a/core/src/com/unciv/UnCivGame.kt b/core/src/com/unciv/UnCivGame.kt index 83c10a55cb..aeced6fbd4 100644 --- a/core/src/com/unciv/UnCivGame.kt +++ b/core/src/com/unciv/UnCivGame.kt @@ -20,24 +20,23 @@ class UnCivGame : Game() { var settings = GameSettings() var worldScreen: WorldScreen? = null + override fun create() { setupGameBasics() Current = this if (GameSaver.getSave("Autosave").exists()) { try { - GameSaver.loadGame(this, "Autosave") - gameInfo.getPlayerCivilization().civName="Babylon" - gameInfo.tileMap.values.forEach { - //if (it.getOwner() == "Player") it.getOwner() = "Babylon" - if (it.unit != null && it.unit!!.owner == "Player") it.unit!!.owner = "Babylon" - } + loadGame("Autosave") } catch (ex: Exception) { // silent fail if we can't read the autosave startNewGame() } } else startNewGame() + } + fun loadGame(gameName:String){ + gameInfo = GameSaver.loadGame( gameName) worldScreen = WorldScreen() setWorldScreen() } diff --git a/core/src/com/unciv/ui/LoadScreen.kt b/core/src/com/unciv/ui/LoadScreen.kt new file mode 100644 index 0000000000..b222b3a254 --- /dev/null +++ b/core/src/com/unciv/ui/LoadScreen.kt @@ -0,0 +1,57 @@ +package com.unciv.ui + +import com.badlogic.gdx.graphics.Color +import com.badlogic.gdx.scenes.scene2d.ui.Table +import com.badlogic.gdx.scenes.scene2d.ui.TextButton +import com.unciv.UnCivGame +import com.unciv.ui.cityscreen.addClickListener +import com.unciv.ui.pickerscreens.PickerScreen +import com.unciv.ui.utils.CameraStageBaseScreen +import com.unciv.ui.utils.GameSaver +import com.unciv.ui.utils.disable +import com.unciv.ui.utils.enable + +class LoadScreen : PickerScreen() { + lateinit var selectedSave:String + + init { + val saveTable = Table() + + + val deleteSaveButton = TextButton("Delete save", CameraStageBaseScreen.skin) + deleteSaveButton .addClickListener { + GameSaver.deleteSave(selectedSave) + UnCivGame.Current.screen = LoadScreen() + } + deleteSaveButton.disable() + rightSideGroup.addActor(deleteSaveButton) + + topTable.add(saveTable) + val saves = GameSaver.getSaves() + rightSideButton.setText("Load game") + saves.forEach { + val textButton = TextButton(it,skin) + textButton.addClickListener { + selectedSave=it + + descriptionLabel.setText(it) + rightSideButton.setText("Load\r\n$it") + rightSideButton.enable() + deleteSaveButton.enable() + deleteSaveButton.color= Color.RED + } + saveTable.add(textButton).pad(5f).row() + } + + rightSideButton.addClickListener { + UnCivGame.Current.loadGame(selectedSave) + } + + + + } + + +} + + diff --git a/core/src/com/unciv/ui/SaveScreen.kt b/core/src/com/unciv/ui/SaveScreen.kt new file mode 100644 index 0000000000..8797ad256f --- /dev/null +++ b/core/src/com/unciv/ui/SaveScreen.kt @@ -0,0 +1,53 @@ +package com.unciv.ui + +import com.badlogic.gdx.scenes.scene2d.ui.Label +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.unciv.UnCivGame +import com.unciv.ui.cityscreen.addClickListener +import com.unciv.ui.pickerscreens.PickerScreen +import com.unciv.ui.utils.GameSaver +import com.unciv.ui.utils.enable +import java.text.SimpleDateFormat +import java.util.* + +class SaveScreen : PickerScreen() { + val textField = TextField("", skin) + + init { + val currentSaves = Table() + + currentSaves.add(Label("Current saves:",skin)).row() + val saves = GameSaver.getSaves() + saves.forEach { + val textButton = TextButton(it, skin) + textButton.addClickListener { + textField.text = it + } + currentSaves.add(textButton).pad(5f).row() + + } + topTable.add(currentSaves) + + + val newSave = Table() + val defaultSaveName = SimpleDateFormat("dd-MM-yy HH.mm").format(Date())+ + " Turn "+ UnCivGame.Current.gameInfo.turns + textField.text = defaultSaveName + + newSave.add(Label("Saved game name:",skin)).row() + newSave.add(textField).width(300f) + + topTable.add(newSave) + topTable.pack() + + rightSideButton.setText("Save game") + rightSideButton.addClickListener { + GameSaver.saveGame(UnCivGame.Current.gameInfo, textField.text) + UnCivGame.Current.setWorldScreen() + } + rightSideButton.enable() + } + +} \ No newline at end of file diff --git a/core/src/com/unciv/ui/pickerscreens/PickerScreen.kt b/core/src/com/unciv/ui/pickerscreens/PickerScreen.kt index 36ed455399..ff8a6e1c10 100644 --- a/core/src/com/unciv/ui/pickerscreens/PickerScreen.kt +++ b/core/src/com/unciv/ui/pickerscreens/PickerScreen.kt @@ -10,33 +10,34 @@ import com.unciv.ui.utils.disable open class PickerScreen : CameraStageBaseScreen() { - internal var closeButton: TextButton + internal var closeButton: TextButton = TextButton("Close", CameraStageBaseScreen.skin) protected var descriptionLabel: Label + protected var rightSideGroup = VerticalGroup() protected var rightSideButton: TextButton - internal var screenSplit = 0.85f + private var screenSplit = 0.85f protected var topTable: Table + var bottomTable:Table = Table() internal var splitPane: SplitPane init { - val buttonTable = Table() - closeButton = TextButton("Close", CameraStageBaseScreen.skin) closeButton.addClickListener { game.setWorldScreen() dispose() } - buttonTable.add(closeButton).width(stage.width / 4) + bottomTable.add(closeButton).width(stage.width / 4) descriptionLabel = Label("", CameraStageBaseScreen.skin) descriptionLabel.setWrap(true) descriptionLabel.setFontScale(game.settings.labelScale) descriptionLabel.width = stage.width / 2 - buttonTable.add(descriptionLabel).pad(5f).width(stage.width / 2) + bottomTable.add(descriptionLabel).pad(5f).width(stage.width / 2) rightSideButton = TextButton("", CameraStageBaseScreen.skin) - buttonTable.add(rightSideButton).width(stage.width / 4) - buttonTable.height = stage.height * (1 - screenSplit) - buttonTable.align(Align.center) + rightSideGroup.addActor(rightSideButton) + bottomTable.add(rightSideGroup).width(stage.width / 4) + bottomTable.height = stage.height * (1 - screenSplit) + bottomTable.align(Align.center) rightSideButton.disable() topTable = Table() @@ -44,7 +45,7 @@ open class PickerScreen : CameraStageBaseScreen() { scrollPane.setSize(stage.width, stage.height * screenSplit) - splitPane = SplitPane(scrollPane, buttonTable, true, CameraStageBaseScreen.skin) + splitPane = SplitPane(scrollPane, bottomTable, true, CameraStageBaseScreen.skin) splitPane.setSplitAmount(screenSplit) splitPane.setFillParent(true) stage.addActor(splitPane) diff --git a/core/src/com/unciv/ui/utils/GameSaver.kt b/core/src/com/unciv/ui/utils/GameSaver.kt index a9f417ec84..ac6045d2f6 100644 --- a/core/src/com/unciv/ui/utils/GameSaver.kt +++ b/core/src/com/unciv/ui/utils/GameSaver.kt @@ -4,7 +4,6 @@ import com.badlogic.gdx.Gdx import com.badlogic.gdx.files.FileHandle import com.badlogic.gdx.utils.Json import com.unciv.logic.GameInfo -import com.unciv.UnCivGame object GameSaver { private const val saveFilesFolder = "SaveFiles" @@ -13,12 +12,21 @@ object GameSaver { return Gdx.files.local("$saveFilesFolder/$GameName") } - fun saveGame(game: UnCivGame, GameName: String) { - getSave(GameName).writeString(Json().toJson(game.gameInfo), false) + fun getSaves(): List { + return Gdx.files.local(saveFilesFolder).list().map { it.name() } } - fun loadGame(game: UnCivGame, GameName: String) { - game.gameInfo = Json().fromJson(GameInfo::class.java, getSave(GameName).readString()) - game.gameInfo.setTransients() + fun saveGame(game: GameInfo, GameName: String) { + getSave(GameName).writeString(Json().toJson(game), false) + } + + fun loadGame(GameName: String) : GameInfo { + val game = Json().fromJson(GameInfo::class.java, getSave(GameName).readString()) + game.setTransients() + return game + } + + fun deleteSave(GameName: String){ + getSave(GameName).delete() } } diff --git a/core/src/com/unciv/ui/worldscreen/BattleTable.kt b/core/src/com/unciv/ui/worldscreen/BattleTable.kt index 5acb12d024..20673d9ca2 100644 --- a/core/src/com/unciv/ui/worldscreen/BattleTable.kt +++ b/core/src/com/unciv/ui/worldscreen/BattleTable.kt @@ -1,5 +1,6 @@ package com.unciv.ui.worldscreen +import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.scenes.scene2d.ui.Label import com.badlogic.gdx.scenes.scene2d.ui.Table import com.badlogic.gdx.scenes.scene2d.ui.TextButton @@ -8,6 +9,7 @@ import com.unciv.logic.map.TileInfo import com.unciv.logic.map.UnitType import com.unciv.ui.cityscreen.addClickListener import com.unciv.ui.utils.CameraStageBaseScreen +import com.unciv.ui.utils.ImageGetter import com.unciv.ui.utils.disable import kotlin.math.max @@ -18,10 +20,15 @@ class BattleTable(val worldScreen: WorldScreen): Table() { skin = CameraStageBaseScreen.skin } + fun hide(){ + clear() + background=null + } + fun update() { if (worldScreen.unitTable.selectedUnit == null || worldScreen.unitTable.selectedUnit!!.getBaseUnit().unitType == UnitType.Civilian){ - clear() + hide() return } // no attacker @@ -38,16 +45,14 @@ class BattleTable(val worldScreen: WorldScreen): Table() { && worldScreen.civInfo.getViewableTiles().contains(selectedTile)) defender = MapUnitCombatant(selectedTile.unit!!) else { - clear() + hide() return } simulateBattle(attacker, defender) - } fun simulateBattle(attacker: MapUnitCombatant, defender: ICombatant){ clear() - row().pad(5f) val attackerLabel = Label(attacker.getName(), skin) attackerLabel.style= Label.LabelStyle(attackerLabel.style) @@ -81,10 +86,10 @@ class BattleTable(val worldScreen: WorldScreen): Table() { var damageToAttacker = battle.calculateDamageToAttacker(attacker,defender) - if (damageToAttacker>attacker.getHealth() && damageToDefender>defender.getHealth() // when damage exceeds health, we don't want to show negative health numbers + if (damageToAttacker>attacker.getHealth() && damageToDefender>defender.getHealth()) // when damage exceeds health, we don't want to show negative health numbers // Also if both parties are supposed to die it's not indicative of who is more likely to win // So we "normalize" the damages until one dies - ) { + { if(damageToDefender/defender.getHealth().toFloat() > damageToAttacker/attacker.getHealth().toFloat()) // defender dies quicker ie first { // Both damages *= (defender.health/damageToDefender) @@ -150,6 +155,13 @@ class BattleTable(val worldScreen: WorldScreen): Table() { add(attackButton).colspan(2) pack() + + val tileTableBackground = ImageGetter.getDrawable("skin/tileTableBackground.png") + .tint(Color(0x004085bf)) + tileTableBackground.minHeight = 0f + tileTableBackground.minWidth = 0f + background = tileTableBackground + setPosition(worldScreen.stage.width/2-width/2, 5f) } diff --git a/core/src/com/unciv/ui/worldscreen/WorldScreen.kt b/core/src/com/unciv/ui/worldscreen/WorldScreen.kt index 13b4b9d698..0e41c06907 100644 --- a/core/src/com/unciv/ui/worldscreen/WorldScreen.kt +++ b/core/src/com/unciv/ui/worldscreen/WorldScreen.kt @@ -120,7 +120,7 @@ class WorldScreen : CameraStageBaseScreen() { game.gameInfo.nextTurn() unitTable.currentlyExecutingAction = null - GameSaver.saveGame(game, "Autosave") + GameSaver.saveGame(game.gameInfo, "Autosave") update() displayTutorials("NextTurn") } diff --git a/core/src/com/unciv/ui/worldscreen/WorldScreenOptionsTable.kt b/core/src/com/unciv/ui/worldscreen/WorldScreenOptionsTable.kt index d8ed87c0db..f6bdee7951 100644 --- a/core/src/com/unciv/ui/worldscreen/WorldScreenOptionsTable.kt +++ b/core/src/com/unciv/ui/worldscreen/WorldScreenOptionsTable.kt @@ -5,6 +5,8 @@ import com.badlogic.gdx.scenes.scene2d.ui.Table import com.badlogic.gdx.scenes.scene2d.ui.TextButton import com.unciv.logic.civilization.CivilizationInfo import com.unciv.ui.CivilopediaScreen +import com.unciv.ui.LoadScreen +import com.unciv.ui.SaveScreen import com.unciv.ui.ScienceVictoryScreen import com.unciv.ui.cityscreen.addClickListener import com.unciv.ui.pickerscreens.PolicyPickerScreen @@ -17,7 +19,6 @@ class WorldScreenOptionsTable internal constructor(worldScreen: WorldScreen, pri val tileTableBackground = ImageGetter.getDrawable("skin/tileTableBackground.png") .tint(Color(0x004085bf)) background = tileTableBackground - isVisible = false val openCivilopediaButton = TextButton("Civilopedia", CameraStageBaseScreen.skin) @@ -25,32 +26,42 @@ class WorldScreenOptionsTable internal constructor(worldScreen: WorldScreen, pri worldScreen.game.screen = CivilopediaScreen() isVisible = false } - add(openCivilopediaButton).pad(10f) - row() + add(openCivilopediaButton).pad(10f).row() + val LoadGameButton = TextButton("Load game", CameraStageBaseScreen.skin) + LoadGameButton .addClickListener { + worldScreen.game.screen = LoadScreen() + isVisible=false + } + add(LoadGameButton ).pad(10f).row() + + + val SaveGameButton = TextButton("Save game", CameraStageBaseScreen.skin) + SaveGameButton .addClickListener { + worldScreen.game.screen = SaveScreen() + isVisible=false + } + add(SaveGameButton ).pad(10f).row() val StartNewGameButton = TextButton("Start new game", CameraStageBaseScreen.skin) StartNewGameButton.addClickListener { worldScreen.game.startNewGame(true) } - - add(StartNewGameButton).pad(10f) - row() + add(StartNewGameButton).pad(10f).row() val OpenScienceVictoryScreen = TextButton("Science victory status", CameraStageBaseScreen.skin) OpenScienceVictoryScreen.addClickListener { worldScreen.game.screen = ScienceVictoryScreen(this@WorldScreenOptionsTable.civInfo) } - add(OpenScienceVictoryScreen).pad(10f) - row() + add(OpenScienceVictoryScreen).pad(10f).row() val OpenPolicyPickerScreen = TextButton("Social Policies", CameraStageBaseScreen.skin) OpenPolicyPickerScreen.addClickListener { worldScreen.game.screen = PolicyPickerScreen(this@WorldScreenOptionsTable.civInfo) } - add(OpenPolicyPickerScreen).pad(10f) - row() + add(OpenPolicyPickerScreen).pad(10f).row() val closeButton = TextButton("Close", CameraStageBaseScreen.skin) closeButton.addClickListener { isVisible = false } add(closeButton).pad(10f) + pack() // Needed to show the background. setPosition(worldScreen.stage.width / 2 - width / 2, worldScreen.stage.height / 2 - height / 2)