General Starting locations in map editor (#9920)

* Added an Any Civ starting location brush.

* Fixed the Remove starting locations brush from being too long.

* Civs without a specific starting location given to them now use the spectator starting locations before finding a free tile.

* Removed spectator from civilizations to give a starting location.

* Added comments

* Removed accidentally added import statements.

* Added new display text to template.properties

* Replaced an inline when statement with an if statement.

* Fixed not having a space after a translation.

* Moved finding a starting location to a new function.

* Fixed GameStarter.getCivStartingLocation to return a null if it couldn't find a tile to start on.
This commit is contained in:
Oskar Niesen 2023-08-21 14:42:14 -05:00 committed by GitHub
parent 70b04765cc
commit d668c5dceb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 39 additions and 13 deletions

View File

@ -546,6 +546,8 @@ Spread Resources =
Create ancient ruins =
Floodfill =
[nation] starting location =
Any Civ starting locations =
Any Civ =
Remove features =
Remove improvement =
Remove resource =

View File

@ -384,7 +384,8 @@ object GameStarter {
// First we get start locations for the major civs, on the second pass the city states (without predetermined starts) can squeeze in wherever
val civNamesWithStartingLocations = tileMap.startingLocationsByNation.keys
val bestCivs = allCivs.filter { !it.isCityState() || it.civName in civNamesWithStartingLocations }
val bestCivs = allCivs.filter { (!it.isCityState() || it.civName in civNamesWithStartingLocations)
&& !it.isSpectator()}
val bestLocations = getStartingLocations(bestCivs, tileMap, landTilesInBigEnoughGroup, startScores)
for ((civ, tile) in bestLocations) {
// A nation can have multiple marked starting locations, of which the first pass may have chosen one
@ -538,7 +539,7 @@ object GameStarter {
): HashMap<Civilization, Tile> {
val civsOrderedByAvailableLocations = getCivsOrderedByAvailableLocations(civs, tileMap)
for (minimumDistanceBetweenStartingLocations in tileMap.tileMatrix.size / 6 downTo 0) {
val freeTiles = getFreeTiles(tileMap, landTilesInBigEnoughGroup, minimumDistanceBetweenStartingLocations)
@ -580,21 +581,38 @@ object GameStarter {
): HashMap<Civilization, Tile>? {
val startingLocations = HashMap<Civilization, Tile>()
for (civ in civsOrderedByAvailableLocations) {
val startingLocation = getCivStartingLocation(civ, tileMap, freeTiles, startScores)
startingLocation ?: break
startingLocations[civ] = startingLocation
val distanceToNext = minimumDistanceBetweenStartingLocations /
(if (civ.isCityState()) 2 else 1) // We allow city states to squeeze in tighter
val presetStartingLocation = tileMap.startingLocationsByNation[civ.civName]?.randomOrNull()
val startingLocation = if (presetStartingLocation != null) presetStartingLocation
else {
if (freeTiles.isEmpty()) break // we failed to get all the starting tiles with this minimum distance
getOneStartingLocation(civ, tileMap, freeTiles, startScores)
}
startingLocations[civ] = startingLocation
freeTiles.removeAll(tileMap.getTilesInDistance(startingLocation.position, distanceToNext)
.toSet())
}
return if (startingLocations.size < civsOrderedByAvailableLocations.size) null else startingLocations
}
private fun getCivStartingLocation(
civ: Civilization,
tileMap: TileMap,
freeTiles: MutableList<Tile>,
startScores: HashMap<Tile, Float>,
): Tile? {
var startingLocation = tileMap.startingLocationsByNation[civ.civName]?.randomOrNull()
if (startingLocation == null) {
startingLocation = tileMap.startingLocationsByNation[Constants.spectator]?.randomOrNull()
if (startingLocation != null) {
tileMap.startingLocationsByNation[Constants.spectator]?.remove(startingLocation)
}
}
if (startingLocation == null && freeTiles.isNotEmpty())
startingLocation = getOneStartingLocation(civ, tileMap, freeTiles, startScores)
// If startingLocation is null we failed to get all the starting tiles with this minimum distance
return startingLocation
}
private fun getOneStartingLocation(
civ: Civilization,

View File

@ -281,18 +281,24 @@ class MapEditorEditStartsTab(
val eraserIcon = "Nation/${firstNation.name}"
val eraser = FormattedLine("Remove starting locations", icon = eraserIcon, size = 24, iconCrossed = true)
add(eraser.render(0f).apply { onClick {
editTab.setBrush(BrushHandlerType.Direct, "Remove starting locations", eraserIcon, true) { tile ->
editTab.setBrush(BrushHandlerType.Direct, "Remove", eraserIcon, true) { tile ->
tile.tileMap.removeStartingLocations(tile.position)
}
} }).padBottom(0f).row()
// Create the nation list with the spectator nation included
// We use Nation/Spectator because it hasn't been used yet and we need an icon within the Nation.
val anyCiv = FormattedLine("Any Civ starting location", Constants.spectator, "Nation/Spectator", size = 24)
val nations = getNations().toList()
val nationsToAdd = ArrayList<FormattedLine>(1 + nations.count())
nationsToAdd.add((anyCiv)) // An Civ starting location should be first
nationsToAdd.addAll(nations)
add(
MarkupRenderer.render(
getNations(),
nationsToAdd,
iconDisplay = FormattedLine.IconDisplay.NoLink
) {
UncivGame.Current.musicController.chooseTrack(it, MusicMood.Theme, MusicTrackChooserFlags.setSpecific)
editTab.setBrush(BrushHandlerType.Direct, it, "Nation/$it") { tile ->
editTab.setBrush(BrushHandlerType.Direct, if (it ==Constants.spectator) "Any Civ" else it, "Nation/$it") { tile ->
// toggle the starting location here, note this allows
// both multiple locations per nation and multiple nations per tile
if (!tile.tileMap.addStartingLocation(it, tile))