Can convert maps between different rulesets!

This commit is contained in:
Yair Morgenstern 2021-03-07 10:02:19 +02:00
parent a654937ad3
commit 7ddcc58955
3 changed files with 108 additions and 101 deletions

View File

@ -571,5 +571,52 @@ open class TileInfo {
turnsToImprovement = 0
}
fun normalizeToRuleset(ruleset: Ruleset){
if (!ruleset.terrains.containsKey(naturalWonder)) naturalWonder = null
if (naturalWonder != null) {
val naturalWonder = ruleset.terrains[naturalWonder]!!
baseTerrain = naturalWonder.turnsInto!!
terrainFeature = null
resource = null
improvement = null
}
if (!ruleset.terrains.containsKey(terrainFeature)) terrainFeature = null
if (terrainFeature != null) {
val terrainFeatureObject = ruleset.terrains[terrainFeature]!!
if (terrainFeatureObject.occursOn.isNotEmpty() && !terrainFeatureObject.occursOn.contains(baseTerrain))
terrainFeature = null
}
if (resource != null && !ruleset.tileResources.containsKey(resource)) resource = null
if (resource != null) {
val resourceObject = ruleset.tileResources[resource]!!
if (resourceObject.terrainsCanBeFoundOn.none { it == baseTerrain || it == terrainFeature })
resource = null
}
if (improvement != null) normalizeTileImprovement(ruleset)
if (isWater || isImpassible())
roadStatus = RoadStatus.None
}
private fun normalizeTileImprovement(ruleset: Ruleset) {
val topTerrain = getLastTerrain()
if (improvement!!.startsWith("StartingLocation")) {
if (!isLand || topTerrain.impassable) improvement = null
return
}
val improvementObject = ruleset.tileImprovements[improvement]!!
improvement = null // Unset, and check if it can be reset. If so, do it, if not, invalid.
if (canImprovementBeBuiltHere(improvementObject)
// Allow building 'other' improvements like city ruins, barb encampments, Great Improvements etc
|| (improvementObject.terrainsCanBeBuiltOn.isEmpty()
&& ruleset.tileResources.values.none { it.improvement == improvementObject.name }
&& !isImpassible() && isLand))
improvement = improvementObject.name
}
//endregion
}

View File

@ -1,71 +1,75 @@
package com.unciv.ui.mapeditor
import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane
import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.unciv.Constants
import com.unciv.MainMenuScreen
import com.unciv.UncivGame
import com.unciv.logic.map.TileMap
import com.unciv.models.metadata.Player
import com.unciv.ui.utils.Popup
import com.unciv.ui.utils.onClick
import com.unciv.ui.utils.toTextButton
import com.unciv.models.ruleset.RulesetCache
import com.unciv.ui.newgamescreen.ModCheckboxTable
import com.unciv.ui.utils.*
class MapEditorMenuPopup(var mapEditorScreen: MapEditorScreen): Popup(mapEditorScreen){
class MapEditorMenuPopup(var mapEditorScreen: MapEditorScreen): Popup(mapEditorScreen) {
init {
addNewMapButton()
addSaveMapButton()
addLoadMapButton()
addExitMapEditorButton()
addCloseOptionsButton()
addButton("New map") { UncivGame.Current.setScreen(NewMapScreen()) }
addButton("Save map") { mapEditorScreen.game.setScreen(SaveAndLoadMapScreen(mapEditorScreen.tileMap, true)) }
addButton("Load map") { mapEditorScreen.game.setScreen(SaveAndLoadMapScreen(mapEditorScreen.tileMap)) }
addButton("Exit map editor") { mapEditorScreen.game.setScreen(MainMenuScreen()); mapEditorScreen.dispose() }
addButton("Change ruleset") { MapEditorRulesetPopup(mapEditorScreen).open(); close() }
addButton(Constants.close) { close() }
}
private fun Popup.addNewMapButton() {
val newMapButton = "New map".toTextButton()
newMapButton.onClick {
UncivGame.Current.setScreen(NewMapScreen())
class MapEditorRulesetPopup(mapEditorScreen: MapEditorScreen) : Popup(mapEditorScreen) {
var ruleset = mapEditorScreen.ruleset.clone() // don't take the actual one, so w can decide to not make changes
init {
val mods = mapEditorScreen.tileMap.mapParameters.mods
val checkboxTable = ModCheckboxTable(mods, mapEditorScreen) {
ruleset.clear()
val newRuleset = RulesetCache.getComplexRuleset(mods)
ruleset.add(newRuleset)
ruleset.mods += mods
ruleset.modOptions = newRuleset.modOptions
ImageGetter.setNewRuleset(ruleset)
}
add(ScrollPane(checkboxTable)).maxHeight(mapEditorScreen.stage.height * 0.8f).row()
addButton("Save") {
val incompatibilities = mapEditorScreen.tileMap.values.map { it.getRulesetIncompatability(ruleset) }.toHashSet()
incompatibilities.remove("")
if (incompatibilities.isEmpty()) {
mapEditorScreen.tileMap.mapParameters.mods = mods;
mapEditorScreen.game.setScreen(MapEditorScreen(mapEditorScreen.tileMap)) // reset all images etc.
return@addButton
}
val incompatTable = Table()
for (inc in incompatibilities)
incompatTable.add(inc.toLabel()).row()
val incompatPopup = Popup(screen)
incompatPopup.add(ScrollPane(incompatTable)).maxHeight(stage.height * 0.8f).row()
incompatPopup.add("Change map to fit selected ruleset?").row()
incompatPopup.addButton("Yes") {
for (tile in mapEditorScreen.tileMap.values)
tile.normalizeToRuleset(ruleset)
mapEditorScreen.tileMap.mapParameters.mods = mods
mapEditorScreen.game.setScreen(MapEditorScreen(mapEditorScreen.tileMap)) // reset all images etc.
}
incompatPopup.addButton("No") { incompatPopup.close() }
incompatPopup.open(true)
}
// Reset - no changes
addCloseButton { ImageGetter.setNewRuleset(mapEditorScreen.ruleset) }
}
add(newMapButton).row()
}
private fun Popup.addSaveMapButton() {
val saveMapButton = "Save map".toTextButton()
saveMapButton.onClick {
mapEditorScreen.game.setScreen(SaveAndLoadMapScreen(mapEditorScreen.tileMap, true))
}
add(saveMapButton).row()
}
private fun Popup.addLoadMapButton() {
val loadMapButton = "Load map".toTextButton()
loadMapButton.onClick {
UncivGame.Current.setScreen(SaveAndLoadMapScreen(mapEditorScreen.tileMap))
}
add(loadMapButton).row()
}
private fun Popup.addExitMapEditorButton() {
val exitMapEditorButton = "Exit map editor".toTextButton()
add(exitMapEditorButton).row()
exitMapEditorButton.onClick { mapEditorScreen.game.setScreen(MainMenuScreen()); mapEditorScreen.dispose() }
}
private fun Popup.addCloseOptionsButton() {
val closeOptionsButton = Constants.close.toTextButton()
closeOptionsButton.onClick { close() }
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

@ -443,53 +443,9 @@ class TileEditorOptionsTable(val mapEditorScreen: MapEditorScreen): Table(Camera
fun updateTileWhenClicked(tileInfo: TileInfo) {
tileAction(tileInfo)
normalizeTile(tileInfo)
tileInfo.normalizeToRuleset(ruleset)
}
fun normalizeTile(tileInfo: TileInfo) {
/*Natural Wonder superpowers! */
if (tileInfo.naturalWonder != null) {
val naturalWonder = tileInfo.getNaturalWonder()
tileInfo.baseTerrain = naturalWonder.turnsInto!!
tileInfo.terrainFeature = null
tileInfo.resource = null
tileInfo.improvement = null
}
if (tileInfo.terrainFeature != null) {
val terrainFeature = tileInfo.getTerrainFeature()
if (terrainFeature == null || terrainFeature.occursOn.isNotEmpty() && !terrainFeature.occursOn.contains(tileInfo.baseTerrain))
tileInfo.terrainFeature = null
}
if (tileInfo.resource != null && !ruleset.tileResources.containsKey(tileInfo.resource))
tileInfo.resource = null
if (tileInfo.resource != null) {
val resource = tileInfo.getTileResource()
if (resource.terrainsCanBeFoundOn.none { it == tileInfo.baseTerrain || it == tileInfo.terrainFeature })
tileInfo.resource = null
}
if (tileInfo.improvement != null) {
normalizeTileImprovement(tileInfo)
}
if (tileInfo.isWater || tileInfo.isImpassible())
tileInfo.roadStatus = RoadStatus.None
}
private fun normalizeTileImprovement(tileInfo: TileInfo) {
val topTerrain = tileInfo.getLastTerrain()
if (tileInfo.improvement!!.startsWith("StartingLocation")) {
if (!tileInfo.isLand || topTerrain.impassable)
tileInfo.improvement = null
return
}
val improvement = tileInfo.getTileImprovement()!!
tileInfo.improvement = null // Unset, and check if it can be reset. If so, do it, if not, invalid.
if (tileInfo.canImprovementBeBuiltHere(improvement)
// Allow building 'other' improvements like city ruins, barb encampments, Great Improvements etc
|| (improvement.terrainsCanBeBuiltOn.isEmpty() && ruleset.tileResources.values.none { it.improvement == improvement.name }
&& !tileInfo.isImpassible() && tileInfo.isLand))
tileInfo.improvement = improvement.name
}
private fun setCurrentHex(tileInfo: TileInfo, text: String) {
val tileGroup = TileGroup(tileInfo, TileSetStrings())