Map editor menu (#1739)
* Refactor: map size is enum * Feature: map editor menu * Cleanup * Added "Empty" map generation type for the map editor
This commit is contained in:
parent
617eea92cf
commit
9e0ed36bba
7 changed files with 171 additions and 44 deletions
|
@ -977,6 +977,9 @@ Version =
|
|||
Resolution =
|
||||
Tileset =
|
||||
Map editor =
|
||||
Create =
|
||||
New map =
|
||||
Empty =
|
||||
Language =
|
||||
Terrains & Resources =
|
||||
Improvements =
|
||||
|
|
|
@ -4,6 +4,7 @@ package com.unciv.logic.civilization
|
|||
import com.badlogic.gdx.graphics.Color
|
||||
import com.unciv.Constants
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.logic.map.MapSize
|
||||
import com.unciv.logic.map.RoadStatus
|
||||
import com.unciv.models.ruleset.tech.Technology
|
||||
import com.unciv.models.ruleset.unit.BaseUnit
|
||||
|
@ -60,11 +61,11 @@ class TechManager {
|
|||
// https://forums.civfanatics.com/threads/the-mechanics-of-overflow-inflation.517970/
|
||||
techCost /= 1 + techsResearchedKnownCivs / undefeatedCivs.toFloat() * 0.3f
|
||||
// http://www.civclub.net/bbs/forum.php?mod=viewthread&tid=123976
|
||||
val worldSizeModifier = when(civInfo.gameInfo.tileMap.mapParameters.radius) {
|
||||
20 -> floatArrayOf(1.1f, 0.05f) // Medium Size
|
||||
30 -> floatArrayOf(1.2f, 0.03f) // Large Size
|
||||
40 -> floatArrayOf(1.3f, 0.02f) // Huge Size
|
||||
else -> floatArrayOf(1f, 0.05f) // Tiny and Small Size
|
||||
val worldSizeModifier = when(civInfo.gameInfo.tileMap.mapParameters.size) {
|
||||
MapSize.Medium -> floatArrayOf(1.1f, 0.05f)
|
||||
MapSize.Large -> floatArrayOf(1.2f, 0.03f)
|
||||
MapSize.Huge -> floatArrayOf(1.3f, 0.02f)
|
||||
else -> floatArrayOf(1f, 0.05f)
|
||||
}
|
||||
techCost *= worldSizeModifier[0]
|
||||
techCost *= 1 + (civInfo.cities.size -1) * worldSizeModifier[1]
|
||||
|
|
|
@ -24,18 +24,22 @@ class MapType {
|
|||
val continents = "Continents"
|
||||
val pangaea = "Pangaea"
|
||||
val custom="Custom"
|
||||
val empty="Empty"
|
||||
}
|
||||
}
|
||||
|
||||
class MapGenerator {
|
||||
|
||||
fun generateMap(mapParameters: MapParameters, ruleset: Ruleset): TileMap {
|
||||
val mapRadius = mapParameters.radius
|
||||
val mapRadius = mapParameters.size.radius
|
||||
val mapType = mapParameters.type
|
||||
|
||||
val map = TileMap(mapRadius, ruleset)
|
||||
map.mapParameters = mapParameters
|
||||
|
||||
// Is the empty map is requested, there's no need for further generation
|
||||
if (mapType == MapType.empty) return map
|
||||
|
||||
// Step one - separate land and water, in form of Grasslands and Oceans
|
||||
if (mapType == MapType.perlin)
|
||||
MapLandmassGenerator().generateLandPerlin(map)
|
||||
|
|
|
@ -1,9 +1,17 @@
|
|||
package com.unciv.logic.map
|
||||
|
||||
enum class MapSize(val radius: Int) {
|
||||
Tiny(10),
|
||||
Small(15),
|
||||
Medium(20),
|
||||
Large(30),
|
||||
Huge(40)
|
||||
}
|
||||
|
||||
class MapParameters {
|
||||
var name = ""
|
||||
var type = MapType.pangaea
|
||||
var radius = 20
|
||||
var size: MapSize = MapSize.Medium
|
||||
var noRuins = false
|
||||
var noNaturalWonders = true
|
||||
}
|
79
core/src/com/unciv/ui/mapeditor/NewMapScreen.kt
Normal file
79
core/src/com/unciv/ui/mapeditor/NewMapScreen.kt
Normal file
|
@ -0,0 +1,79 @@
|
|||
package com.unciv.ui.mapeditor
|
||||
|
||||
import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.logic.map.MapGenerator
|
||||
import com.unciv.logic.map.MapParameters
|
||||
import com.unciv.logic.map.TileMap
|
||||
import com.unciv.models.ruleset.RulesetCache
|
||||
import com.unciv.models.translations.tr
|
||||
import com.unciv.ui.newgamescreen.MapParametersTable
|
||||
import com.unciv.ui.pickerscreens.PickerScreen
|
||||
import com.unciv.ui.utils.*
|
||||
import kotlin.concurrent.thread
|
||||
|
||||
/** New map generation screen */
|
||||
class NewMapScreen : PickerScreen() {
|
||||
|
||||
private val mapParameters = MapParameters()
|
||||
private var generatedMap: TileMap? = null
|
||||
|
||||
init {
|
||||
setDefaultCloseAction()
|
||||
|
||||
val newMapScreenOptionsTable = Table(skin).apply {
|
||||
pad(10f)
|
||||
add("Map options".toLabel(fontSize = 24)).row()
|
||||
add(MapParametersTable(mapParameters, isEmptyMapAllowed = true)).row()
|
||||
pack()
|
||||
}
|
||||
|
||||
|
||||
topTable.apply {
|
||||
add(ScrollPane(newMapScreenOptionsTable)).height(topTable.parent.height)
|
||||
pack()
|
||||
setFillParent(true)
|
||||
}
|
||||
|
||||
rightButtonSetEnabled(true)
|
||||
rightSideButton.onClick {
|
||||
Gdx.input.inputProcessor = null // remove input processing - nothing will be clicked!
|
||||
rightButtonSetEnabled(false)
|
||||
|
||||
thread(name = "MapGenerator") {
|
||||
try {
|
||||
// Map generation can take a while and we don't want ANRs
|
||||
val ruleset = RulesetCache.getBaseRuleset()
|
||||
generatedMap = MapGenerator().generateMap(mapParameters, ruleset)
|
||||
|
||||
Gdx.app.postRunnable {
|
||||
UncivGame.Current.setScreen(MapEditorScreen(generatedMap!!))
|
||||
}
|
||||
|
||||
} catch (exception: Exception) {
|
||||
rightButtonSetEnabled(true)
|
||||
val cantMakeThatMapPopup = Popup(this)
|
||||
cantMakeThatMapPopup.addGoodSizedLabel("It looks like we can't make a map with the parameters you requested!".tr())
|
||||
.row()
|
||||
cantMakeThatMapPopup.addCloseButton()
|
||||
cantMakeThatMapPopup.open()
|
||||
Gdx.input.inputProcessor = stage
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/** Changes the state and the text of the [rightSideButton] */
|
||||
private fun rightButtonSetEnabled(enabled: Boolean) {
|
||||
if (enabled) {
|
||||
rightSideButton.enable()
|
||||
rightSideButton.setText("Create".tr())
|
||||
} else {
|
||||
rightSideButton.disable()
|
||||
rightSideButton.setText("Working...".tr())
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,13 +5,23 @@ import com.badlogic.gdx.scenes.scene2d.ui.CheckBox
|
|||
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener
|
||||
import com.unciv.logic.map.MapParameters
|
||||
import com.unciv.logic.map.MapSize
|
||||
import com.unciv.logic.map.MapType
|
||||
import com.unciv.models.translations.tr
|
||||
import com.unciv.ui.utils.CameraStageBaseScreen
|
||||
import com.unciv.ui.utils.toLabel
|
||||
|
||||
// This is a separate class, because it should be in use both in the New Game screen and the Map Editor screen
|
||||
class MapParametersTable(val mapParameters: MapParameters): Table(){
|
||||
/** Table for editing [mapParameters]
|
||||
*
|
||||
* This is a separate class, because it should be in use both in the New Game screen and the Map Editor screen
|
||||
*
|
||||
* @param isEmptyMapAllowed whether the [MapType.empty] option should be present. Is used by the Map Editor, but should **never** be used with the New Game
|
||||
* */
|
||||
class MapParametersTable(val mapParameters: MapParameters, val isEmptyMapAllowed: Boolean = false) :
|
||||
Table() {
|
||||
|
||||
lateinit var noRuinsCheckbox: CheckBox
|
||||
lateinit var noNaturalWondersCheckbox: CheckBox
|
||||
|
||||
init {
|
||||
addMapTypeSelectBox()
|
||||
|
@ -23,35 +33,41 @@ class MapParametersTable(val mapParameters: MapParameters): Table(){
|
|||
private fun addMapTypeSelectBox() {
|
||||
add("{Map generation type}:".toLabel())
|
||||
|
||||
val mapTypes = listOf(MapType.default, MapType.pangaea, MapType.continents, MapType.perlin)
|
||||
val mapTypeSelectBox = TranslatedSelectBox(mapTypes, mapParameters.type, CameraStageBaseScreen.skin)
|
||||
val mapTypes = listOfNotNull(
|
||||
MapType.default,
|
||||
MapType.pangaea,
|
||||
MapType.continents,
|
||||
MapType.perlin,
|
||||
if (isEmptyMapAllowed) MapType.empty else null
|
||||
)
|
||||
val mapTypeSelectBox =
|
||||
TranslatedSelectBox(mapTypes, mapParameters.type, CameraStageBaseScreen.skin)
|
||||
|
||||
mapTypeSelectBox.addListener(object : ChangeListener() {
|
||||
override fun changed(event: ChangeEvent?, actor: Actor?) {
|
||||
mapParameters.type=mapTypeSelectBox.selected.value
|
||||
mapParameters.type = mapTypeSelectBox.selected.value
|
||||
|
||||
// If the map won't be generated, these options are irrelevant and are hidden
|
||||
noRuinsCheckbox.isVisible = mapParameters.type != MapType.empty
|
||||
noNaturalWondersCheckbox.isVisible = mapParameters.type != MapType.empty
|
||||
}
|
||||
})
|
||||
add(mapTypeSelectBox).row()
|
||||
}
|
||||
|
||||
|
||||
private fun addWorldSizeSelectBox(){
|
||||
private fun addWorldSizeSelectBox() {
|
||||
|
||||
val worldSizeLabel = "{World size}:".toLabel()
|
||||
val worldSizeToRadius = LinkedHashMap<String, Int>()
|
||||
worldSizeToRadius["Tiny"] = 10
|
||||
worldSizeToRadius["Small"] = 15
|
||||
worldSizeToRadius["Medium"] = 20
|
||||
worldSizeToRadius["Large"] = 30
|
||||
worldSizeToRadius["Huge"] = 40
|
||||
|
||||
val currentWorldSizeName = worldSizeToRadius.entries
|
||||
.first { it.value == mapParameters.radius }.key
|
||||
val worldSizeSelectBox = TranslatedSelectBox(worldSizeToRadius.keys, currentWorldSizeName, CameraStageBaseScreen.skin)
|
||||
val worldSizeSelectBox = TranslatedSelectBox(
|
||||
MapSize.values().map { it.name },
|
||||
mapParameters.size.name,
|
||||
CameraStageBaseScreen.skin
|
||||
)
|
||||
|
||||
worldSizeSelectBox.addListener(object : ChangeListener() {
|
||||
override fun changed(event: ChangeEvent?, actor: Actor?) {
|
||||
mapParameters.radius = worldSizeToRadius[worldSizeSelectBox.selected.value]!!
|
||||
mapParameters.size = MapSize.valueOf(worldSizeSelectBox.selected.value)
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -60,7 +76,7 @@ class MapParametersTable(val mapParameters: MapParameters): Table(){
|
|||
}
|
||||
|
||||
private fun addNoRuinsCheckbox() {
|
||||
val noRuinsCheckbox = CheckBox("No ancient ruins".tr(), CameraStageBaseScreen.skin)
|
||||
noRuinsCheckbox = CheckBox("No ancient ruins".tr(), CameraStageBaseScreen.skin)
|
||||
noRuinsCheckbox.isChecked = mapParameters.noRuins
|
||||
noRuinsCheckbox.addListener(object : ChangeListener() {
|
||||
override fun changed(event: ChangeEvent?, actor: Actor?) {
|
||||
|
@ -71,7 +87,7 @@ class MapParametersTable(val mapParameters: MapParameters): Table(){
|
|||
}
|
||||
|
||||
private fun addNoNaturalWondersCheckbox() {
|
||||
val noNaturalWondersCheckbox = CheckBox("No Natural Wonders".tr(), CameraStageBaseScreen.skin)
|
||||
noNaturalWondersCheckbox = CheckBox("No Natural Wonders".tr(), CameraStageBaseScreen.skin)
|
||||
noNaturalWondersCheckbox.isChecked = mapParameters.noNaturalWonders
|
||||
noNaturalWondersCheckbox.addListener(object : ChangeListener() {
|
||||
override fun changed(event: ChangeEvent?, actor: Actor?) {
|
||||
|
|
|
@ -3,21 +3,17 @@ package com.unciv.ui.worldscreen.mainmenu
|
|||
import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.logic.map.RoadStatus
|
||||
import com.unciv.models.translations.tr
|
||||
import com.unciv.ui.CivilopediaScreen
|
||||
import com.unciv.ui.VictoryScreen
|
||||
import com.unciv.ui.mapeditor.MapEditorScreen
|
||||
import com.unciv.ui.mapeditor.LoadMapScreen
|
||||
import com.unciv.ui.mapeditor.NewMapScreen
|
||||
import com.unciv.ui.newgamescreen.NewGameScreen
|
||||
import com.unciv.ui.saves.LoadGameScreen
|
||||
import com.unciv.ui.saves.SaveGameScreen
|
||||
import com.unciv.ui.utils.Popup
|
||||
import com.unciv.ui.utils.addSeparator
|
||||
import com.unciv.ui.utils.disable
|
||||
import com.unciv.ui.utils.toLabel
|
||||
import com.unciv.ui.utils.*
|
||||
import com.unciv.ui.worldscreen.WorldScreen
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
import kotlin.concurrent.thread
|
||||
|
||||
class WorldScreenMenuPopup(val worldScreen: WorldScreen) : Popup(worldScreen) {
|
||||
|
@ -26,17 +22,7 @@ class WorldScreenMenuPopup(val worldScreen: WorldScreen) : Popup(worldScreen) {
|
|||
val width = 200f
|
||||
val height = 30f
|
||||
addSquareButton("Map editor".tr()){
|
||||
val tileMapClone = worldScreen.gameInfo.tileMap.clone()
|
||||
for(tile in tileMapClone.values){
|
||||
tile.militaryUnit=null
|
||||
tile.civilianUnit=null
|
||||
tile.airUnits=ArrayList()
|
||||
tile.improvement=null
|
||||
tile.improvementInProgress=null
|
||||
tile.turnsToImprovement=0
|
||||
tile.roadStatus=RoadStatus.None
|
||||
}
|
||||
UncivGame.Current.setScreen(MapEditorScreen(tileMapClone))
|
||||
openMapEditorPopup()
|
||||
remove()
|
||||
}.size(width,height)
|
||||
addSeparator()
|
||||
|
@ -137,6 +123,36 @@ class WorldScreenMenuPopup(val worldScreen: WorldScreen) : Popup(worldScreen) {
|
|||
multiplayerPopup.addCloseButton()
|
||||
multiplayerPopup.open()
|
||||
}
|
||||
|
||||
/** Shows the [Popup] with the map editor initialization options */
|
||||
private fun openMapEditorPopup() {
|
||||
|
||||
close()
|
||||
val mapEditorPopup = Popup(screen)
|
||||
|
||||
mapEditorPopup.addGoodSizedLabel("Map editor".tr()).row()
|
||||
|
||||
// Create a new map
|
||||
mapEditorPopup.addButton("New map") {
|
||||
UncivGame.Current.setScreen(NewMapScreen())
|
||||
mapEditorPopup.close()
|
||||
}
|
||||
|
||||
// Load the map
|
||||
mapEditorPopup.addButton("Load map") {
|
||||
val loadMapScreen = LoadMapScreen(null)
|
||||
loadMapScreen.closeButton.isVisible = true
|
||||
loadMapScreen.closeButton.onClick {
|
||||
UncivGame.Current.setWorldScreen()
|
||||
loadMapScreen.dispose() }
|
||||
UncivGame.Current.setScreen(loadMapScreen)
|
||||
mapEditorPopup.close()
|
||||
}
|
||||
|
||||
mapEditorPopup.addCloseButton()
|
||||
mapEditorPopup.open()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class WorldScreenCommunityPopup(val worldScreen: WorldScreen) : Popup(worldScreen) {
|
||||
|
|
Loading…
Reference in a new issue