mirror of
https://github.com/yairm210/Unciv.git
synced 2025-02-11 11:28:03 +07:00
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
@ -977,6 +977,9 @@ Version =
|
|||||||
Resolution =
|
Resolution =
|
||||||
Tileset =
|
Tileset =
|
||||||
Map editor =
|
Map editor =
|
||||||
|
Create =
|
||||||
|
New map =
|
||||||
|
Empty =
|
||||||
Language =
|
Language =
|
||||||
Terrains & Resources =
|
Terrains & Resources =
|
||||||
Improvements =
|
Improvements =
|
||||||
|
@ -4,6 +4,7 @@ package com.unciv.logic.civilization
|
|||||||
import com.badlogic.gdx.graphics.Color
|
import com.badlogic.gdx.graphics.Color
|
||||||
import com.unciv.Constants
|
import com.unciv.Constants
|
||||||
import com.unciv.UncivGame
|
import com.unciv.UncivGame
|
||||||
|
import com.unciv.logic.map.MapSize
|
||||||
import com.unciv.logic.map.RoadStatus
|
import com.unciv.logic.map.RoadStatus
|
||||||
import com.unciv.models.ruleset.tech.Technology
|
import com.unciv.models.ruleset.tech.Technology
|
||||||
import com.unciv.models.ruleset.unit.BaseUnit
|
import com.unciv.models.ruleset.unit.BaseUnit
|
||||||
@ -60,11 +61,11 @@ class TechManager {
|
|||||||
// https://forums.civfanatics.com/threads/the-mechanics-of-overflow-inflation.517970/
|
// https://forums.civfanatics.com/threads/the-mechanics-of-overflow-inflation.517970/
|
||||||
techCost /= 1 + techsResearchedKnownCivs / undefeatedCivs.toFloat() * 0.3f
|
techCost /= 1 + techsResearchedKnownCivs / undefeatedCivs.toFloat() * 0.3f
|
||||||
// http://www.civclub.net/bbs/forum.php?mod=viewthread&tid=123976
|
// http://www.civclub.net/bbs/forum.php?mod=viewthread&tid=123976
|
||||||
val worldSizeModifier = when(civInfo.gameInfo.tileMap.mapParameters.radius) {
|
val worldSizeModifier = when(civInfo.gameInfo.tileMap.mapParameters.size) {
|
||||||
20 -> floatArrayOf(1.1f, 0.05f) // Medium Size
|
MapSize.Medium -> floatArrayOf(1.1f, 0.05f)
|
||||||
30 -> floatArrayOf(1.2f, 0.03f) // Large Size
|
MapSize.Large -> floatArrayOf(1.2f, 0.03f)
|
||||||
40 -> floatArrayOf(1.3f, 0.02f) // Huge Size
|
MapSize.Huge -> floatArrayOf(1.3f, 0.02f)
|
||||||
else -> floatArrayOf(1f, 0.05f) // Tiny and Small Size
|
else -> floatArrayOf(1f, 0.05f)
|
||||||
}
|
}
|
||||||
techCost *= worldSizeModifier[0]
|
techCost *= worldSizeModifier[0]
|
||||||
techCost *= 1 + (civInfo.cities.size -1) * worldSizeModifier[1]
|
techCost *= 1 + (civInfo.cities.size -1) * worldSizeModifier[1]
|
||||||
|
@ -24,18 +24,22 @@ class MapType {
|
|||||||
val continents = "Continents"
|
val continents = "Continents"
|
||||||
val pangaea = "Pangaea"
|
val pangaea = "Pangaea"
|
||||||
val custom="Custom"
|
val custom="Custom"
|
||||||
|
val empty="Empty"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MapGenerator {
|
class MapGenerator {
|
||||||
|
|
||||||
fun generateMap(mapParameters: MapParameters, ruleset: Ruleset): TileMap {
|
fun generateMap(mapParameters: MapParameters, ruleset: Ruleset): TileMap {
|
||||||
val mapRadius = mapParameters.radius
|
val mapRadius = mapParameters.size.radius
|
||||||
val mapType = mapParameters.type
|
val mapType = mapParameters.type
|
||||||
|
|
||||||
val map = TileMap(mapRadius, ruleset)
|
val map = TileMap(mapRadius, ruleset)
|
||||||
map.mapParameters = mapParameters
|
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
|
// Step one - separate land and water, in form of Grasslands and Oceans
|
||||||
if (mapType == MapType.perlin)
|
if (mapType == MapType.perlin)
|
||||||
MapLandmassGenerator().generateLandPerlin(map)
|
MapLandmassGenerator().generateLandPerlin(map)
|
||||||
|
@ -1,9 +1,17 @@
|
|||||||
package com.unciv.logic.map
|
package com.unciv.logic.map
|
||||||
|
|
||||||
|
enum class MapSize(val radius: Int) {
|
||||||
|
Tiny(10),
|
||||||
|
Small(15),
|
||||||
|
Medium(20),
|
||||||
|
Large(30),
|
||||||
|
Huge(40)
|
||||||
|
}
|
||||||
|
|
||||||
class MapParameters {
|
class MapParameters {
|
||||||
var name = ""
|
var name = ""
|
||||||
var type = MapType.pangaea
|
var type = MapType.pangaea
|
||||||
var radius = 20
|
var size: MapSize = MapSize.Medium
|
||||||
var noRuins = false
|
var noRuins = false
|
||||||
var noNaturalWonders = true
|
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.ui.Table
|
||||||
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener
|
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener
|
||||||
import com.unciv.logic.map.MapParameters
|
import com.unciv.logic.map.MapParameters
|
||||||
|
import com.unciv.logic.map.MapSize
|
||||||
import com.unciv.logic.map.MapType
|
import com.unciv.logic.map.MapType
|
||||||
import com.unciv.models.translations.tr
|
import com.unciv.models.translations.tr
|
||||||
import com.unciv.ui.utils.CameraStageBaseScreen
|
import com.unciv.ui.utils.CameraStageBaseScreen
|
||||||
import com.unciv.ui.utils.toLabel
|
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
|
/** Table for editing [mapParameters]
|
||||||
class MapParametersTable(val mapParameters: MapParameters): Table(){
|
*
|
||||||
|
* 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 {
|
init {
|
||||||
addMapTypeSelectBox()
|
addMapTypeSelectBox()
|
||||||
@ -23,35 +33,41 @@ class MapParametersTable(val mapParameters: MapParameters): Table(){
|
|||||||
private fun addMapTypeSelectBox() {
|
private fun addMapTypeSelectBox() {
|
||||||
add("{Map generation type}:".toLabel())
|
add("{Map generation type}:".toLabel())
|
||||||
|
|
||||||
val mapTypes = listOf(MapType.default, MapType.pangaea, MapType.continents, MapType.perlin)
|
val mapTypes = listOfNotNull(
|
||||||
val mapTypeSelectBox = TranslatedSelectBox(mapTypes, mapParameters.type, CameraStageBaseScreen.skin)
|
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() {
|
mapTypeSelectBox.addListener(object : ChangeListener() {
|
||||||
override fun changed(event: ChangeEvent?, actor: Actor?) {
|
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()
|
add(mapTypeSelectBox).row()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun addWorldSizeSelectBox(){
|
private fun addWorldSizeSelectBox() {
|
||||||
|
|
||||||
val worldSizeLabel = "{World size}:".toLabel()
|
val worldSizeLabel = "{World size}:".toLabel()
|
||||||
val worldSizeToRadius = LinkedHashMap<String, Int>()
|
val worldSizeSelectBox = TranslatedSelectBox(
|
||||||
worldSizeToRadius["Tiny"] = 10
|
MapSize.values().map { it.name },
|
||||||
worldSizeToRadius["Small"] = 15
|
mapParameters.size.name,
|
||||||
worldSizeToRadius["Medium"] = 20
|
CameraStageBaseScreen.skin
|
||||||
worldSizeToRadius["Large"] = 30
|
)
|
||||||
worldSizeToRadius["Huge"] = 40
|
|
||||||
|
|
||||||
val currentWorldSizeName = worldSizeToRadius.entries
|
|
||||||
.first { it.value == mapParameters.radius }.key
|
|
||||||
val worldSizeSelectBox = TranslatedSelectBox(worldSizeToRadius.keys, currentWorldSizeName, CameraStageBaseScreen.skin)
|
|
||||||
|
|
||||||
worldSizeSelectBox.addListener(object : ChangeListener() {
|
worldSizeSelectBox.addListener(object : ChangeListener() {
|
||||||
override fun changed(event: ChangeEvent?, actor: Actor?) {
|
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() {
|
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.isChecked = mapParameters.noRuins
|
||||||
noRuinsCheckbox.addListener(object : ChangeListener() {
|
noRuinsCheckbox.addListener(object : ChangeListener() {
|
||||||
override fun changed(event: ChangeEvent?, actor: Actor?) {
|
override fun changed(event: ChangeEvent?, actor: Actor?) {
|
||||||
@ -71,7 +87,7 @@ class MapParametersTable(val mapParameters: MapParameters): Table(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun addNoNaturalWondersCheckbox() {
|
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.isChecked = mapParameters.noNaturalWonders
|
||||||
noNaturalWondersCheckbox.addListener(object : ChangeListener() {
|
noNaturalWondersCheckbox.addListener(object : ChangeListener() {
|
||||||
override fun changed(event: ChangeEvent?, actor: Actor?) {
|
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.Gdx
|
||||||
import com.badlogic.gdx.graphics.Color
|
import com.badlogic.gdx.graphics.Color
|
||||||
import com.unciv.UncivGame
|
import com.unciv.UncivGame
|
||||||
import com.unciv.logic.map.RoadStatus
|
|
||||||
import com.unciv.models.translations.tr
|
import com.unciv.models.translations.tr
|
||||||
import com.unciv.ui.CivilopediaScreen
|
import com.unciv.ui.CivilopediaScreen
|
||||||
import com.unciv.ui.VictoryScreen
|
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.newgamescreen.NewGameScreen
|
||||||
import com.unciv.ui.saves.LoadGameScreen
|
import com.unciv.ui.saves.LoadGameScreen
|
||||||
import com.unciv.ui.saves.SaveGameScreen
|
import com.unciv.ui.saves.SaveGameScreen
|
||||||
import com.unciv.ui.utils.Popup
|
import com.unciv.ui.utils.*
|
||||||
import com.unciv.ui.utils.addSeparator
|
|
||||||
import com.unciv.ui.utils.disable
|
|
||||||
import com.unciv.ui.utils.toLabel
|
|
||||||
import com.unciv.ui.worldscreen.WorldScreen
|
import com.unciv.ui.worldscreen.WorldScreen
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.collections.ArrayList
|
|
||||||
import kotlin.concurrent.thread
|
import kotlin.concurrent.thread
|
||||||
|
|
||||||
class WorldScreenMenuPopup(val worldScreen: WorldScreen) : Popup(worldScreen) {
|
class WorldScreenMenuPopup(val worldScreen: WorldScreen) : Popup(worldScreen) {
|
||||||
@ -26,17 +22,7 @@ class WorldScreenMenuPopup(val worldScreen: WorldScreen) : Popup(worldScreen) {
|
|||||||
val width = 200f
|
val width = 200f
|
||||||
val height = 30f
|
val height = 30f
|
||||||
addSquareButton("Map editor".tr()){
|
addSquareButton("Map editor".tr()){
|
||||||
val tileMapClone = worldScreen.gameInfo.tileMap.clone()
|
openMapEditorPopup()
|
||||||
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))
|
|
||||||
remove()
|
remove()
|
||||||
}.size(width,height)
|
}.size(width,height)
|
||||||
addSeparator()
|
addSeparator()
|
||||||
@ -137,6 +123,36 @@ class WorldScreenMenuPopup(val worldScreen: WorldScreen) : Popup(worldScreen) {
|
|||||||
multiplayerPopup.addCloseButton()
|
multiplayerPopup.addCloseButton()
|
||||||
multiplayerPopup.open()
|
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) {
|
class WorldScreenCommunityPopup(val worldScreen: WorldScreen) : Popup(worldScreen) {
|
||||||
|
Loading…
Reference in New Issue
Block a user