Fix custom map sizes - saves match, size obeyed, limit UI (#3965)

* Fix custom map sizes - Revive Enum MapSize and fix tech modifier for custom maps

* Fix custom map sizes - Fix saved size not matching tileset, obey custom size

* Fix custom map sizes - limiting custom size and UI

* Fix custom map sizes - linting and reduce warnings

* Fix custom map sizes - less verbose

* Popup gets a KeyPressDispatcher - templates
This commit is contained in:
SomeTroglodyte
2021-05-20 21:17:07 +02:00
committed by GitHub
parent f07c63c07f
commit 7c7d4181cc
13 changed files with 163 additions and 82 deletions

View File

@ -243,6 +243,10 @@ Small =
Medium = Medium =
Large = Large =
Huge = Huge =
World wrap requires a minimum width of 32 tiles =
The provided map dimensions were too small =
The provided map dimensions were too big =
The provided map dimensions had an unacceptable aspect ratio =
Difficulty = Difficulty =

View File

@ -76,11 +76,5 @@ object Constants {
const val futureEra = "Future era" const val futureEra = "Future era"
const val barbarians = "Barbarians" const val barbarians = "Barbarians"
const val spectator = "Spectator" const val spectator = "Spectator"
const val tiny = "Tiny"
const val small = "Small"
const val medium = "Medium"
const val large = "Large"
const val huge = "Huge"
const val custom = "Custom" const val custom = "Custom"
} }

View File

@ -10,6 +10,7 @@ import com.unciv.logic.GameSaver
import com.unciv.logic.GameStarter import com.unciv.logic.GameStarter
import com.unciv.logic.map.mapgenerator.MapGenerator import com.unciv.logic.map.mapgenerator.MapGenerator
import com.unciv.logic.map.MapParameters import com.unciv.logic.map.MapParameters
import com.unciv.logic.map.MapSize
import com.unciv.logic.map.MapSizeNew import com.unciv.logic.map.MapSizeNew
import com.unciv.logic.map.MapType import com.unciv.logic.map.MapType
import com.unciv.models.ruleset.RulesetCache import com.unciv.models.ruleset.RulesetCache
@ -51,7 +52,7 @@ class MainMenuScreen: CameraStageBaseScreen() {
thread(name = "ShowMapBackground") { thread(name = "ShowMapBackground") {
val newMap = MapGenerator(RulesetCache.getBaseRuleset()) val newMap = MapGenerator(RulesetCache.getBaseRuleset())
.generateMap(MapParameters().apply { mapSize = MapSizeNew(Constants.small); type = MapType.default }) .generateMap(MapParameters().apply { mapSize = MapSizeNew(MapSize.Small); type = MapType.default })
Gdx.app.postRunnable { // for GL context Gdx.app.postRunnable { // for GL context
ImageGetter.setNewRuleset(RulesetCache.getBaseRuleset()) ImageGetter.setNewRuleset(RulesetCache.getBaseRuleset())
val mapHolder = EditorMapHolder(MapEditorScreen(), newMap) val mapHolder = EditorMapHolder(MapEditorScreen(), newMap)

View File

@ -1,7 +1,7 @@
package com.unciv.logic.civilization package com.unciv.logic.civilization
import com.unciv.Constants
import com.unciv.logic.city.CityInfo import com.unciv.logic.city.CityInfo
import com.unciv.logic.map.MapSize
import com.unciv.logic.map.RoadStatus import com.unciv.logic.map.RoadStatus
import com.unciv.logic.map.TileInfo import com.unciv.logic.map.TileInfo
import com.unciv.models.ruleset.Unique import com.unciv.models.ruleset.Unique
@ -24,7 +24,7 @@ class TechManager {
@Transient @Transient
private var researchedTechUniques = ArrayList<Unique>() private var researchedTechUniques = ArrayList<Unique>()
// MapUnit.canPassThrough is the most called function in the game, and having these extremey specific booleans is or way of improving the time cost // MapUnit.canPassThrough is the most called function in the game, and having these extremely specific booleans is or way of improving the time cost
@Transient @Transient
var wayfinding = false var wayfinding = false
@Transient @Transient
@ -83,12 +83,14 @@ class TechManager {
.count { it.isMajorCiv() && !it.isDefeated() } .count { it.isMajorCiv() && !it.isDefeated() }
// 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://web.archive.org/web/20201204043641/http://www.civclub.net/bbs/forum.php?mod=viewthread&tid=123976
val worldSizeModifier = when (civInfo.gameInfo.tileMap.mapParameters.mapSize.name) { val worldSizeModifier = with (civInfo.gameInfo.tileMap.mapParameters.mapSize) {
Constants.medium -> floatArrayOf(1.1f, 0.05f) when {
Constants.large -> floatArrayOf(1.2f, 0.03f) radius >= MapSize.Medium.radius -> floatArrayOf(1.1f, 0.05f)
Constants.huge -> floatArrayOf(1.3f, 0.02f) radius >= MapSize.Large.radius -> floatArrayOf(1.2f, 0.03f)
else -> floatArrayOf(1f, 0.05f) radius >= MapSize.Huge.radius -> floatArrayOf(1.3f, 0.02f)
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]

View File

@ -5,12 +5,12 @@ import com.unciv.logic.HexMath.getEquivalentHexagonalRadius
import com.unciv.logic.HexMath.getEquivalentRectangularSize import com.unciv.logic.HexMath.getEquivalentRectangularSize
enum class MapSize(val radius: Int) { enum class MapSize(val radius: Int, val width: Int, val height: Int) {
Tiny(10), Tiny(10, 23, 15),
Small(15), Small(15, 33, 21),
Medium(20), Medium(20, 44, 29),
Large(30), Large(30, 66, 43),
Huge(40) Huge(40, 87, 57)
} }
class MapSizeNew { class MapSizeNew {
@ -20,17 +20,25 @@ class MapSizeNew {
var name = "" var name = ""
/** Needed for Json parsing */ /** Needed for Json parsing */
@Suppress("unused")
constructor() constructor()
private fun fromPredefined(predefined: MapSize) {
name = predefined.name
radius = predefined.radius
width = predefined.width
height = predefined.height
}
constructor(size: MapSize) {
fromPredefined(size)
}
constructor(name: String) { constructor(name: String) {
this.name = name try {
/** Hard coded values from getEquivalentRectangularSize() */ fromPredefined(MapSize.valueOf(name))
when (name) { } catch (_: Exception) {
Constants.tiny -> { radius = 10; width = 23; height = 15 } fromPredefined(MapSize.Tiny)
Constants.small -> { radius = 15; width = 33; height = 21 }
Constants.medium -> { radius = 20; width = 44; height = 29 }
Constants.large -> { radius = 30; width = 66; height = 43 }
Constants.huge -> { radius = 40; width = 87; height = 57 }
} }
} }
@ -47,7 +55,42 @@ class MapSizeNew {
this.width = width this.width = width
this.height = height this.height = height
this.radius = getEquivalentHexagonalRadius(width, height) this.radius = getEquivalentHexagonalRadius(width, height)
}
/** Check custom dimensions, fix if too extreme
* @param worldWrap whether world wrap is on
* @return null if size was acceptable, otherwise untranslated reason message
*/
fun fixUndesiredSizes(worldWrap: Boolean): String? {
if (name != Constants.custom) return null // predefined sizes are OK
// world-wrap mas must always have an even width, so round down silently
if (worldWrap && width % 2 != 0 ) width--
// check for any bad condition and bail if none of them
val message = when {
worldWrap && width < 32 -> // otherwise horizontal scrolling will show edges, empirical
"World wrap requires a minimum width of 32 tiles"
width < 3 || height < 3 || radius < 2 ->
"The provided map dimensions were too small"
radius > 500 ->
"The provided map dimensions were too big"
height * 16 < width || width * 16 < height -> // aspect ratio > 16:1
"The provided map dimensions had an unacceptable aspect ratio"
else -> null
} ?: return null
// fix the size - not knowing whether hexagonal or rectangular is used
radius = when {
radius < 2 -> 2
radius > 500 -> 500
worldWrap && radius < 15 -> 15 // minimum for hexagonal but more than required for rectangular
else -> radius
}
val size = getEquivalentRectangularSize(radius)
width = size.x.toInt()
height = size.y.toInt()
// tell the caller that map dimensions have changed and why
return message
} }
} }
@ -78,7 +121,7 @@ class MapParameters {
var shape = MapShape.hexagonal var shape = MapShape.hexagonal
@Deprecated("replaced by mapSize since 3.14.7") @Deprecated("replaced by mapSize since 3.14.7")
var size = MapSize.Medium var size = MapSize.Medium
var mapSize = MapSizeNew(Constants.medium) var mapSize = MapSizeNew(MapSize.Medium)
var noRuins = false var noRuins = false
var noNaturalWonders = false var noNaturalWonders = false
var worldWrap = false var worldWrap = false

View File

@ -25,10 +25,10 @@ class TileMap {
var bottomY = 0 var bottomY = 0
@delegate:Transient @delegate:Transient
val maxLatitude: Float by lazy { if (values.isEmpty()) 0f else values.map { abs(it.latitude) }.max()!! } val maxLatitude: Float by lazy { if (values.isEmpty()) 0f else values.map { abs(it.latitude) }.maxOrNull()!! }
@delegate:Transient @delegate:Transient
val maxLongitude: Float by lazy { if (values.isEmpty()) 0f else values.map { abs(it.longitude) }.max()!! } val maxLongitude: Float by lazy { if (values.isEmpty()) 0f else values.map { abs(it.longitude) }.maxOrNull()!! }
@delegate:Transient @delegate:Transient
val naturalWonders: List<String> by lazy { tileList.asSequence().filter { it.isNaturalWonder() }.map { it.naturalWonder!! }.distinct().toList() } val naturalWonders: List<String> by lazy { tileList.asSequence().filter { it.isNaturalWonder() }.map { it.naturalWonder!! }.distinct().toList() }
@ -52,13 +52,18 @@ class TileMap {
/** generates a rectangular map of given width and height*/ /** generates a rectangular map of given width and height*/
constructor(width: Int, height: Int, ruleset: Ruleset, worldWrap: Boolean = false) { constructor(width: Int, height: Int, ruleset: Ruleset, worldWrap: Boolean = false) {
val halfway = if (worldWrap) width / 2 - 1 else width / 2 // world-wrap maps must always have an even width, so round down
for (x in -width / 2..halfway) val wrapAdjustedWidth = if (worldWrap && width % 2 != 0 ) width -1 else width
for (y in -height / 2..height / 2)
// Even widths will have coordinates ranging -x..(x-1), not -x..x, which is always an odd-sized range
// e.g. w=4 -> -2..1, w=5 -> -2..2, w=6 -> -3..2, w=7 -> -3..3
for (x in -wrapAdjustedWidth / 2 .. (wrapAdjustedWidth-1) / 2)
for (y in -height / 2 .. (height-1) / 2)
tileList.add(TileInfo().apply { tileList.add(TileInfo().apply {
position = HexMath.evenQ2HexCoords(Vector2(x.toFloat(), y.toFloat())) position = HexMath.evenQ2HexCoords(Vector2(x.toFloat(), y.toFloat()))
baseTerrain = Constants.grassland baseTerrain = Constants.grassland
}) })
setTransients(ruleset) setTransients(ruleset)
} }

View File

@ -21,13 +21,11 @@ class MapGenerator(val ruleset: Ruleset) {
fun generateMap(mapParameters: MapParameters, seed: Long = System.currentTimeMillis()): TileMap { fun generateMap(mapParameters: MapParameters, seed: Long = System.currentTimeMillis()): TileMap {
val mapSize = mapParameters.mapSize val mapSize = mapParameters.mapSize
val mapType = mapParameters.type val mapType = mapParameters.type
val map: TileMap
if (mapParameters.shape == MapShape.rectangular) { val map: TileMap = if (mapParameters.shape == MapShape.rectangular)
val size = HexMath.getEquivalentRectangularSize(mapSize.radius) TileMap(mapSize.width, mapSize.height, ruleset, mapParameters.worldWrap)
map = TileMap(size.x.toInt(), size.y.toInt(), ruleset, mapParameters.worldWrap) else
} TileMap(mapSize.radius, ruleset, mapParameters.worldWrap)
else map = TileMap(mapSize.radius, ruleset, mapParameters.worldWrap)
map.mapParameters = mapParameters map.mapParameters = mapParameters
map.mapParameters.seed = seed map.mapParameters.seed = seed
@ -232,8 +230,8 @@ class MapGenerator(val ruleset: Ruleset) {
continue continue
} }
val matchingTerrain = ruleset.terrains.values.firstOrNull { val matchingTerrain = ruleset.terrains.values.firstOrNull { terrain ->
it.uniqueObjects.any { terrain.uniqueObjects.any {
it.placeholderText == "Occurs at temperature between [] and [] and humidity between [] and []" it.placeholderText == "Occurs at temperature between [] and [] and humidity between [] and []"
&& it.params[0].toFloat() < temperature && temperature <= it.params[1].toFloat() && it.params[0].toFloat() < temperature && temperature <= it.params[1].toFloat()
&& it.params[2].toFloat() < humidity && humidity <= it.params[3].toFloat() && it.params[2].toFloat() < humidity && humidity <= it.params[3].toFloat()

View File

@ -3,6 +3,7 @@ package com.unciv.ui.mapeditor
import com.badlogic.gdx.Gdx import com.badlogic.gdx.Gdx
import com.badlogic.gdx.scenes.scene2d.ui.Table import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.unciv.MainMenuScreen import com.unciv.MainMenuScreen
import com.unciv.UncivGame
import com.unciv.logic.map.MapParameters import com.unciv.logic.map.MapParameters
import com.unciv.logic.map.TileMap import com.unciv.logic.map.TileMap
import com.unciv.logic.map.mapgenerator.MapGenerator import com.unciv.logic.map.mapgenerator.MapGenerator
@ -20,14 +21,16 @@ class NewMapScreen(val mapParameters: MapParameters = MapParameters()) : PickerS
private val ruleset = RulesetCache.getBaseRuleset() private val ruleset = RulesetCache.getBaseRuleset()
private var generatedMap: TileMap? = null private var generatedMap: TileMap? = null
private val mapParametersTable: MapParametersTable
init { init {
setDefaultCloseAction(MainMenuScreen()) setDefaultCloseAction(MainMenuScreen())
mapParametersTable = MapParametersTable(mapParameters, isEmptyMapAllowed = true)
val newMapScreenOptionsTable = Table(skin).apply { val newMapScreenOptionsTable = Table(skin).apply {
pad(10f) pad(10f)
add("Map Options".toLabel(fontSize = 24)).row() add("Map Options".toLabel(fontSize = 24)).row()
add(MapParametersTable(mapParameters, isEmptyMapAllowed = true)).row() add(mapParametersTable).row()
add(ModCheckboxTable(mapParameters.mods, this@NewMapScreen) { add(ModCheckboxTable(mapParameters.mods, this@NewMapScreen) {
ruleset.clear() ruleset.clear()
val newRuleset = RulesetCache.getComplexRuleset(mapParameters.mods) val newRuleset = RulesetCache.getComplexRuleset(mapParameters.mods)
@ -49,6 +52,18 @@ class NewMapScreen(val mapParameters: MapParameters = MapParameters()) : PickerS
rightButtonSetEnabled(true) rightButtonSetEnabled(true)
rightSideButton.onClick { rightSideButton.onClick {
val message = mapParameters.mapSize.fixUndesiredSizes(mapParameters.worldWrap)
if (message != null) {
Gdx.app.postRunnable {
ToastPopup( message, UncivGame.Current.screen as CameraStageBaseScreen, 4000 )
with (mapParameters.mapSize) {
mapParametersTable.customMapSizeRadius.text = radius.toString()
mapParametersTable.customMapWidth.text = width.toString()
mapParametersTable.customMapHeight.text = height.toString()
}
}
return@onClick
}
Gdx.input.inputProcessor = null // remove input processing - nothing will be clicked! Gdx.input.inputProcessor = null // remove input processing - nothing will be clicked!
rightButtonSetEnabled(false) rightButtonSetEnabled(false)

View File

@ -17,7 +17,7 @@ class MapOptionsTable(val newGameScreen: NewGameScreen): Table() {
val mapParameters = newGameScreen.gameSetupInfo.mapParameters val mapParameters = newGameScreen.gameSetupInfo.mapParameters
private var mapTypeSpecificTable = Table() private var mapTypeSpecificTable = Table()
private val generatedMapOptionsTable = MapParametersTable(mapParameters) val generatedMapOptionsTable = MapParametersTable(mapParameters)
private val savedMapOptionsTable = Table() private val savedMapOptionsTable = Table()
lateinit var mapTypeSelectBox: TranslatedSelectBox lateinit var mapTypeSelectBox: TranslatedSelectBox
@ -115,6 +115,6 @@ class MapOptionsTable(val newGameScreen: NewGameScreen): Table() {
// The SelectBox auto displays the text a object.toString(), which on the FileHandle itself includes the folder path. // The SelectBox auto displays the text a object.toString(), which on the FileHandle itself includes the folder path.
// So we wrap it in another object with a custom toString() // So we wrap it in another object with a custom toString()
class FileHandleWrapper(val fileHandle: FileHandle) { class FileHandleWrapper(val fileHandle: FileHandle) {
override fun toString() = fileHandle.name() override fun toString(): String = fileHandle.name()
} }
} }

View File

@ -7,10 +7,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.badlogic.gdx.scenes.scene2d.ui.TextField import com.badlogic.gdx.scenes.scene2d.ui.TextField
import com.unciv.Constants import com.unciv.Constants
import com.unciv.UncivGame import com.unciv.UncivGame
import com.unciv.logic.map.MapParameters import com.unciv.logic.map.*
import com.unciv.logic.map.MapShape
import com.unciv.logic.map.MapSizeNew
import com.unciv.logic.map.MapType
import com.unciv.models.translations.tr import com.unciv.models.translations.tr
import com.unciv.ui.utils.* import com.unciv.ui.utils.*
@ -30,6 +27,9 @@ class MapParametersTable(val mapParameters: MapParameters, val isEmptyMapAllowed
lateinit var noRuinsCheckbox: CheckBox lateinit var noRuinsCheckbox: CheckBox
lateinit var noNaturalWondersCheckbox: CheckBox lateinit var noNaturalWondersCheckbox: CheckBox
lateinit var worldWrapCheckbox: CheckBox lateinit var worldWrapCheckbox: CheckBox
lateinit var customMapSizeRadius: TextField
lateinit var customMapWidth: TextField
lateinit var customMapHeight: TextField
init { init {
@ -88,15 +88,7 @@ class MapParametersTable(val mapParameters: MapParameters, val isEmptyMapAllowed
} }
private fun addWorldSizeTable() { private fun addWorldSizeTable() {
val mapSizes = listOfNotNull( val mapSizes = MapSize.values().map { it.name } + listOf(Constants.custom)
Constants.tiny,
Constants.small,
Constants.medium,
Constants.large,
Constants.huge,
Constants.custom
)
worldSizeSelectBox = TranslatedSelectBox(mapSizes, mapParameters.mapSize.name, skin) worldSizeSelectBox = TranslatedSelectBox(mapSizes, mapParameters.mapSize.name, skin)
worldSizeSelectBox.onChange { updateWorldSizeTable() } worldSizeSelectBox.onChange { updateWorldSizeTable() }
@ -112,7 +104,7 @@ class MapParametersTable(val mapParameters: MapParameters, val isEmptyMapAllowed
private fun addHexagonalSizeTable() { private fun addHexagonalSizeTable() {
val defaultRadius = mapParameters.mapSize.radius.toString() val defaultRadius = mapParameters.mapSize.radius.toString()
val customMapSizeRadius = TextField(defaultRadius, skin).apply { customMapSizeRadius = TextField(defaultRadius, skin).apply {
textFieldFilter = TextField.TextFieldFilter.DigitsOnlyFilter() textFieldFilter = TextField.TextFieldFilter.DigitsOnlyFilter()
} }
customMapSizeRadius.onChange { customMapSizeRadius.onChange {
@ -126,12 +118,12 @@ class MapParametersTable(val mapParameters: MapParameters, val isEmptyMapAllowed
private fun addRectangularSizeTable() { private fun addRectangularSizeTable() {
val defaultWidth = mapParameters.mapSize.width.toString() val defaultWidth = mapParameters.mapSize.width.toString()
val customMapWidth = TextField(defaultWidth, skin).apply { customMapWidth = TextField(defaultWidth, skin).apply {
textFieldFilter = TextField.TextFieldFilter.DigitsOnlyFilter() textFieldFilter = TextField.TextFieldFilter.DigitsOnlyFilter()
} }
val defaultHeight = mapParameters.mapSize.height.toString() val defaultHeight = mapParameters.mapSize.height.toString()
val customMapHeight = TextField(defaultHeight, skin).apply { customMapHeight = TextField(defaultHeight, skin).apply {
textFieldFilter = TextField.TextFieldFilter.DigitsOnlyFilter() textFieldFilter = TextField.TextFieldFilter.DigitsOnlyFilter()
} }

View File

@ -5,6 +5,7 @@ import com.badlogic.gdx.files.FileHandle
import com.badlogic.gdx.scenes.scene2d.ui.SelectBox import com.badlogic.gdx.scenes.scene2d.ui.SelectBox
import com.badlogic.gdx.scenes.scene2d.ui.Skin import com.badlogic.gdx.scenes.scene2d.ui.Skin
import com.badlogic.gdx.utils.Array import com.badlogic.gdx.utils.Array
import com.unciv.UncivGame
import com.unciv.logic.* import com.unciv.logic.*
import com.unciv.logic.civilization.PlayerType import com.unciv.logic.civilization.PlayerType
import com.unciv.logic.map.MapParameters import com.unciv.logic.map.MapParameters
@ -38,12 +39,12 @@ class GameSetupInfo(var gameId:String, var gameParameters: GameParameters, var m
class NewGameScreen(private val previousScreen: CameraStageBaseScreen, _gameSetupInfo: GameSetupInfo?=null): IPreviousScreen, PickerScreen(disableScroll = true) { class NewGameScreen(private val previousScreen: CameraStageBaseScreen, _gameSetupInfo: GameSetupInfo?=null): IPreviousScreen, PickerScreen(disableScroll = true) {
override val gameSetupInfo = _gameSetupInfo ?: GameSetupInfo() override val gameSetupInfo = _gameSetupInfo ?: GameSetupInfo()
override var ruleset = RulesetCache.getComplexRuleset(gameSetupInfo.gameParameters.mods) // needs to be set because the gameoptionstable etc. depend on this override var ruleset = RulesetCache.getComplexRuleset(gameSetupInfo.gameParameters.mods) // needs to be set because the GameOptionsTable etc. depend on this
var newGameOptionsTable = GameOptionsTable(this) { desiredCiv: String -> playerPickerTable.update(desiredCiv) } var newGameOptionsTable = GameOptionsTable(this) { desiredCiv: String -> playerPickerTable.update(desiredCiv) }
// Has to be defined before the mapOptionsTable, since the mapOptionsTable refers to it on init // Has to be defined before the mapOptionsTable, since the mapOptionsTable refers to it on init
private var playerPickerTable = PlayerPickerTable(this, gameSetupInfo.gameParameters) private var playerPickerTable = PlayerPickerTable(this, gameSetupInfo.gameParameters)
var mapOptionsTable = MapOptionsTable(this) private var mapOptionsTable = MapOptionsTable(this)
init { init {
@ -100,13 +101,29 @@ class NewGameScreen(private val previousScreen: CameraStageBaseScreen, _gameSetu
if (rulesetIncompatibilities.isNotEmpty()) { if (rulesetIncompatibilities.isNotEmpty()) {
val incompatibleMap = Popup(this) val incompatibleMap = Popup(this)
incompatibleMap.addGoodSizedLabel("Map is incompatible with the chosen ruleset!".tr()).row() incompatibleMap.addGoodSizedLabel("Map is incompatible with the chosen ruleset!".tr()).row()
for(incompat in rulesetIncompatibilities) for(incompatibility in rulesetIncompatibilities)
incompatibleMap.addGoodSizedLabel(incompat).row() incompatibleMap.addGoodSizedLabel(incompatibility).row()
incompatibleMap.addCloseButton() incompatibleMap.addCloseButton()
incompatibleMap.open() incompatibleMap.open()
game.setScreen(this) // to get the input back game.setScreen(this) // to get the input back
return@onClick return@onClick
} }
} else {
// Generated map - check for sensible dimensions and if exceeded correct them and notify user
val mapSize = gameSetupInfo.mapParameters.mapSize
val message = mapSize.fixUndesiredSizes(gameSetupInfo.mapParameters.worldWrap)
if (message != null) {
Gdx.app.postRunnable {
ToastPopup( message, UncivGame.Current.screen as CameraStageBaseScreen, 4000 )
with (mapOptionsTable.generatedMapOptionsTable) {
customMapSizeRadius.text = mapSize.radius.toString()
customMapWidth.text = mapSize.width.toString()
customMapHeight.text = mapSize.height.toString()
}
}
game.setScreen(this) // to get the input back
return@onClick
}
} }
rightSideButton.disable() rightSideButton.disable()

View File

@ -14,6 +14,8 @@ import com.badlogic.gdx.utils.Align
import com.unciv.UncivGame import com.unciv.UncivGame
import com.unciv.logic.HexMath import com.unciv.logic.HexMath
import com.unciv.logic.civilization.CivilizationInfo import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.logic.map.MapShape
import com.unciv.logic.map.MapSize
import com.unciv.logic.map.TileInfo import com.unciv.logic.map.TileInfo
import com.unciv.ui.utils.IconCircleGroup import com.unciv.ui.utils.IconCircleGroup
import com.unciv.ui.utils.ImageGetter import com.unciv.ui.utils.ImageGetter
@ -35,11 +37,19 @@ class Minimap(val mapHolder: WorldMapHolder, minimapSize: Int) : Table(){
var bottomX = 0f var bottomX = 0f
var bottomY = 0f var bottomY = 0f
fun hexRow(vector2: Vector2) = vector2.x + vector2.y // fun hexRow(vector2: Vector2) = vector2.x + vector2.y
val maxHexRow = mapHolder.tileMap.values.asSequence().map { hexRow(it.position) }.maxOrNull()!! // val maxHexRow = mapHolder.tileMap.values.asSequence().map { hexRow(it.position) }.maxOrNull()!!
val minHexRow = mapHolder.tileMap.values.asSequence().map { hexRow(it.position) }.minOrNull()!! // val minHexRow = mapHolder.tileMap.values.asSequence().map { hexRow(it.position) }.minOrNull()!!
val totalHexRows = maxHexRow - minHexRow // val totalHexRows = maxHexRow - minHexRow
val groupSize = (minimapSize + 1) * 200f / totalHexRows // val groupSize = (minimapSize + 1) * 200f / totalHexRows
// On hexagonal maps totalHexRows as calculated above is always 2 * radius.
// Support rectangular maps with extreme aspect ratios by scaling to the larger coordinate with a slight weighting to make the bounding box 4:3
val effectiveRadius = with(mapHolder.tileMap.mapParameters) {
if (shape != MapShape.rectangular) mapSize.radius
else max (mapSize.height, mapSize.width * 3 / 4) * MapSize.Huge.radius / MapSize.Huge.height
}
val groupSize = (minimapSize + 1) * 100f / effectiveRadius
for (tileInfo in mapHolder.tileMap.values) { for (tileInfo in mapHolder.tileMap.values) {
val hex = ImageGetter.getImage("OtherIcons/Hexagon") val hex = ImageGetter.getImage("OtherIcons/Hexagon")
@ -78,7 +88,7 @@ class Minimap(val mapHolder: WorldMapHolder, minimapSize: Int) : Table(){
/**### Transform and set coordinates for the scrollPositionIndicator. /**### Transform and set coordinates for the scrollPositionIndicator.
* *
* Relies on the [MiniMap]'s copy of the main [WorldMapHolder] as input. * Relies on the [MiniMap][MinimapHolder.minimap]'s copy of the main [WorldMapHolder] as input.
* *
* Requires [scrollPositionIndicator] to be a [ClippingImage] to keep the displayed portion of the indicator within the bounds of the minimap. * Requires [scrollPositionIndicator] to be a [ClippingImage] to keep the displayed portion of the indicator within the bounds of the minimap.
*/ */

View File

@ -1,11 +1,11 @@
package com.unciv.app.desktop package com.unciv.app.desktop
import com.unciv.Constants
import com.unciv.UncivGame import com.unciv.UncivGame
import com.unciv.UncivGameParameters import com.unciv.UncivGameParameters
import com.unciv.logic.GameStarter import com.unciv.logic.GameStarter
import com.unciv.logic.civilization.PlayerType import com.unciv.logic.civilization.PlayerType
import com.unciv.logic.map.MapParameters import com.unciv.logic.map.MapParameters
import com.unciv.logic.map.MapSize
import com.unciv.logic.map.MapSizeNew import com.unciv.logic.map.MapSizeNew
import com.unciv.models.metadata.GameParameters import com.unciv.models.metadata.GameParameters
import com.unciv.models.metadata.GameSettings import com.unciv.models.metadata.GameSettings
@ -45,7 +45,7 @@ internal object ConsoleLauncher {
val newGame = GameStarter.startNewGame(gameSetupInfo) val newGame = GameStarter.startNewGame(gameSetupInfo)
UncivGame.Current.gameInfo = newGame UncivGame.Current.gameInfo = newGame
var simulation = Simulation(newGame,10,4) val simulation = Simulation(newGame,10,4)
simulation.start() simulation.start()
@ -55,7 +55,7 @@ internal object ConsoleLauncher {
private fun getMapParameters(): MapParameters { private fun getMapParameters(): MapParameters {
return MapParameters().apply { return MapParameters().apply {
mapSize = MapSizeNew(Constants.tiny) mapSize = MapSizeNew(MapSize.Tiny)
noRuins = true noRuins = true
noNaturalWonders = true noNaturalWonders = true
} }