diff --git a/android/assets/jsons/Tutorials.json b/android/assets/jsons/Tutorials.json new file mode 100644 index 0000000000..e69de29bb2 diff --git a/core/src/com/unciv/logic/map/MapUnit.kt b/core/src/com/unciv/logic/map/MapUnit.kt index 1ce8418b2b..f5af8069ec 100644 --- a/core/src/com/unciv/logic/map/MapUnit.kt +++ b/core/src/com/unciv/logic/map/MapUnit.kt @@ -9,7 +9,7 @@ import java.text.DecimalFormat class MapUnit { @Transient - @JvmField var civInfo: CivilizationInfo? = null + lateinit var civInfo: CivilizationInfo @JvmField var owner: String? = null @JvmField var name: String? = null @@ -55,7 +55,7 @@ class MapUnit { private fun getPriority(tileInfo: TileInfo): Int { var priority = 0 if (tileInfo.workingCity != null) priority += 2 - if (tileInfo.hasViewableResource(civInfo!!)) priority += 1 + if (tileInfo.hasViewableResource(civInfo)) priority += 1 if (tileInfo.owner == owner) priority += 2 else if (tileInfo.neighbors.any { it.owner != null }) priority += 1 return priority @@ -64,15 +64,15 @@ class MapUnit { private fun findTileToWork(currentTile: TileInfo): TileInfo { var selectedTile = currentTile var selectedTilePriority = - if (currentTile.improvement == null && currentTile.canBuildImprovement(chooseImprovement(currentTile), civInfo!!)) + if (currentTile.improvement == null && currentTile.canBuildImprovement(chooseImprovement(currentTile), civInfo)) getPriority(currentTile) else 1 // min rank to get selected is 2 for (i in 1..4) - for (tile in civInfo!!.gameInfo.tileMap.getTilesAtDistance(currentTile.position, i)) + for (tile in civInfo.gameInfo.tileMap.getTilesAtDistance(currentTile.position, i)) if (tile.unit == null && tile.improvement == null && getPriority(tile) > selectedTilePriority - && tile.canBuildImprovement(chooseImprovement(tile), civInfo!!)) { + && tile.canBuildImprovement(chooseImprovement(tile), civInfo)) { selectedTile = tile selectedTilePriority = getPriority(tile) } @@ -90,9 +90,9 @@ class MapUnit { } if (tile.improvementInProgress == null) { val improvement = chooseImprovement(tile) - if (tile.canBuildImprovement(improvement, civInfo!!)) + if (tile.canBuildImprovement(improvement, civInfo)) // What if we're stuck on this tile but can't build there? - tile.startWorkingOnImprovement(improvement, civInfo!!) + tile.startWorkingOnImprovement(improvement, civInfo) } } @@ -121,16 +121,23 @@ class MapUnit { * @param destination * @return The tile that we reached this turn */ - private fun headTowards(origin: Vector2, destination: Vector2): TileInfo { - val tileMap = civInfo!!.gameInfo.tileMap - val isMachineryResearched = civInfo!!.tech.isResearched("Machinery") - val path = tileMap.getShortestPath(origin, destination, currentMovement, maxMovement, isMachineryResearched) + fun headTowards(origin: Vector2, destination: Vector2): TileInfo { + val tileMap = civInfo.gameInfo.tileMap + val isMachineryResearched = civInfo.tech.isResearched("Machinery") + val distanceToTiles = tileMap.getDistanceToTilesWithinTurn(origin, currentMovement, isMachineryResearched) - val destinationThisTurn = path.first() - if (destinationThisTurn.unit != null) return tileMap[origin] // Someone is blocking tohe path to the final tile... - val distanceToTile = tileMap.getDistanceToTilesWithinTurn(origin, currentMovement, isMachineryResearched)[destinationThisTurn]!! - tileMap[origin].moveUnitToTile(destinationThisTurn, distanceToTile) - return destinationThisTurn + val destinationTileThisTurn:TileInfo + if (distanceToTiles.containsKey(tileMap.get(destination))) + destinationTileThisTurn = tileMap.get(destination) + + else { // If the tile is far away, we need to build a path how to get there, and then take the first step + val path = tileMap.getShortestPath(origin, destination, currentMovement, maxMovement, isMachineryResearched) + destinationTileThisTurn = path.first() + } + if (destinationTileThisTurn.unit != null) return tileMap[origin] // Someone is blocking tohe path to the final tile... + val distanceToTile: Float = distanceToTiles[destinationTileThisTurn]!! + tileMap[origin].moveUnitToTile(destinationTileThisTurn, distanceToTile) + return destinationTileThisTurn } fun nextTurn(tileInfo: TileInfo) { diff --git a/core/src/com/unciv/logic/map/TileInfo.kt b/core/src/com/unciv/logic/map/TileInfo.kt index 9892abbcd2..d4af2c2b34 100644 --- a/core/src/com/unciv/logic/map/TileInfo.kt +++ b/core/src/com/unciv/logic/map/TileInfo.kt @@ -3,11 +3,11 @@ package com.unciv.logic.map import com.badlogic.gdx.math.Vector2 import com.unciv.logic.city.CityInfo import com.unciv.logic.civilization.CivilizationInfo -import com.unciv.models.linq.Linq import com.unciv.models.gamebasics.GameBasics import com.unciv.models.gamebasics.Terrain import com.unciv.models.gamebasics.TileImprovement import com.unciv.models.gamebasics.TileResource +import com.unciv.models.linq.Linq import com.unciv.models.stats.Stats class TileInfo { diff --git a/core/src/com/unciv/logic/map/TileMap.kt b/core/src/com/unciv/logic/map/TileMap.kt index da550db79b..804ead8dfb 100644 --- a/core/src/com/unciv/logic/map/TileMap.kt +++ b/core/src/com/unciv/logic/map/TileMap.kt @@ -1,11 +1,11 @@ package com.unciv.logic.map import com.badlogic.gdx.math.Vector2 +import com.unciv.logic.GameInfo import com.unciv.logic.civilization.CivilizationInfo import com.unciv.models.gamebasics.GameBasics import com.unciv.models.linq.Linq import com.unciv.models.linq.LinqHashMap -import com.unciv.logic.GameInfo import com.unciv.ui.utils.HexMath class TileMap { @@ -74,7 +74,7 @@ class TileMap { return distanceToTiles } - fun getShortestPath(origin: Vector2, destination: Vector2, currentMovement: Float, maxMovement: Int, isMachineryResearched: Boolean): Linq { + fun getShortestPath(origin: Vector2, destination: Vector2, currentMovement: Float, maxMovement: Int, isMachineryResearched: Boolean): List { var tilesToCheck: Linq = Linq(get(origin)) val movementTreeParents = LinqHashMap() // contains a map of "you can get from X to Y in that turn" movementTreeParents[get(origin)] = null @@ -82,24 +82,32 @@ class TileMap { var distance = 1 while (true) { val newTilesToCheck = Linq() + val distanceToDestination = HashMap() + val movementThisTurn = if (distance == 1) currentMovement else maxMovement.toFloat() for (tileToCheck in tilesToCheck) { - val movementThisTurn = if (distance == 1) currentMovement else maxMovement.toFloat() - for (reachableTile in getDistanceToTilesWithinTurn(tileToCheck.position, movementThisTurn, isMachineryResearched).keys) { - if (movementTreeParents.containsKey(reachableTile)) continue // We cannot be faster than anything existing... - if (reachableTile.position != destination && reachableTile.unit != null) continue // This is an intermediary tile that contains a unit - we can't go there! - movementTreeParents[reachableTile] = tileToCheck - if (reachableTile.position == destination) { - val path = Linq() // Traverse the tree upwards to get the list of tiles leading to the destination, - var current = reachableTile - while (movementTreeParents[current] != null) { - path.add(current) - current = movementTreeParents[current] - } - return path.reverse() // and reverse in order to get the list in chronological order + val distanceToTilesThisTurn = getDistanceToTilesWithinTurn(tileToCheck.position, movementThisTurn, isMachineryResearched) + for (reachableTile in distanceToTilesThisTurn.keys) { + if(reachableTile.position == destination) + distanceToDestination.put(tileToCheck, distanceToTilesThisTurn[reachableTile]!!) + else { + if (movementTreeParents.containsKey(reachableTile)) continue // We cannot be faster than anything existing... + if (reachableTile.position != destination && reachableTile.unit != null) continue // This is an intermediary tile that contains a unit - we can't go there! + movementTreeParents[reachableTile] = tileToCheck + newTilesToCheck.add(reachableTile) } - newTilesToCheck.add(reachableTile) } } + + if (distanceToDestination.isNotEmpty()) { + val path = Linq() // Traverse the tree upwards to get the list of tiles leading to the destination, + var currentTile = distanceToDestination.minBy { it.value }!!.key + while (currentTile.position != origin) { + path.add(currentTile) + currentTile = movementTreeParents[currentTile]!! + } + return path.reversed() // and reverse in order to get the list in chronological order + } + tilesToCheck = newTilesToCheck distance++ } diff --git a/core/src/com/unciv/models/gamebasics/Building.kt b/core/src/com/unciv/models/gamebasics/Building.kt index 288531258e..02be96b6b8 100644 --- a/core/src/com/unciv/models/gamebasics/Building.kt +++ b/core/src/com/unciv/models/gamebasics/Building.kt @@ -2,13 +2,13 @@ package com.unciv.models.gamebasics import com.unciv.logic.city.CityConstructions import com.unciv.logic.city.IConstruction +import com.unciv.models.linq.Linq +import com.unciv.models.stats.NamedStats +import com.unciv.models.stats.Stats import com.unciv.ui.ScienceVictoryScreen import com.unciv.ui.UnCivGame import com.unciv.ui.VictoryScreen import com.unciv.ui.pickerscreens.PolicyPickerScreen -import com.unciv.models.linq.Linq -import com.unciv.models.stats.Stats -import com.unciv.models.stats.NamedStats class Building : NamedStats(), IConstruction, ICivilopedia { private lateinit var baseDescription: String @@ -146,7 +146,7 @@ class Building : NamedStats(), IConstruction, ICivilopedia { if ("MustBeNextToDesert" == unique && !civInfo.gameInfo.tileMap.getTilesInDistance(construction.cityInfo.cityLocation, 1).any { it.baseTerrain == "Desert" }) return false if (requiredResource != null && !civInfo.getCivResources().containsKey(GameBasics.TileResources[requiredResource])) - return false // Only checks if exists, doesn't check amount - todo + return false if (requiredNearbyImprovedResources != null) { diff --git a/core/src/com/unciv/models/linq/Linq.java b/core/src/com/unciv/models/linq/Linq.java index b937b4c0fc..854e823de2 100644 --- a/core/src/com/unciv/models/linq/Linq.java +++ b/core/src/com/unciv/models/linq/Linq.java @@ -5,7 +5,6 @@ import com.badlogic.gdx.utils.Predicate; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; -import java.util.Collections; import java.util.HashSet; /** @@ -71,12 +70,6 @@ public class Linq extends ArrayList { return newCollection; } - public Linq reverse(){ - Linq newCol = clone(); - Collections.reverse(newCol); - return newCol; - } - public Linq clone(){ return new Linq(this); } diff --git a/core/src/com/unciv/ui/pickerscreens/PolicyPickerScreen.kt b/core/src/com/unciv/ui/pickerscreens/PolicyPickerScreen.kt index 246445d438..b4b5a4cdfa 100644 --- a/core/src/com/unciv/ui/pickerscreens/PolicyPickerScreen.kt +++ b/core/src/com/unciv/ui/pickerscreens/PolicyPickerScreen.kt @@ -88,7 +88,6 @@ class PolicyPickerScreen(internal val civInfo: CivilizationInfo) : PickerScreen( private fun pickPolicy(policy: Policy) { if (civInfo.policies.isAdopted(policy.name) - || policy.name.endsWith("Complete") || !civInfo.policies.getAdoptedPolicies().containsAll(policy.requires!!) || !civInfo.policies.canAdoptPolicy()) { rightSideButton.touchable = Touchable.disabled @@ -112,12 +111,13 @@ class PolicyPickerScreen(internal val civInfo: CivilizationInfo) : PickerScreen( } else toReturn = TextButton(policy.name, CameraStageBaseScreen.skin) - when { - civInfo.policies.isAdopted(policy.name) -> toReturn.color = Color.GREEN - policy.name.endsWith("Complete") || !civInfo.policies.getAdoptedPolicies().containsAll(policy.requires!!) - -> toReturn.color = Color.GRAY + if (civInfo.policies.isAdopted(policy.name)) { // existing + toReturn.color = Color.GREEN + } else if (!civInfo.policies.getAdoptedPolicies().containsAll(policy.requires!!)) + // non-available + { + toReturn.color = Color.GRAY } - toReturn.addClickListener { pickPolicy(policy) } toReturn.pack() return toReturn diff --git a/core/src/com/unciv/ui/worldscreen/TileInfoTable.kt b/core/src/com/unciv/ui/worldscreen/TileInfoTable.kt index 4583945d16..c9a0d9e0cf 100644 --- a/core/src/com/unciv/ui/worldscreen/TileInfoTable.kt +++ b/core/src/com/unciv/ui/worldscreen/TileInfoTable.kt @@ -1,14 +1,11 @@ package com.unciv.ui.worldscreen import com.badlogic.gdx.graphics.Color -import com.badlogic.gdx.scenes.scene2d.Touchable import com.badlogic.gdx.scenes.scene2d.ui.Label import com.badlogic.gdx.scenes.scene2d.ui.Table -import com.badlogic.gdx.scenes.scene2d.ui.TextButton import com.badlogic.gdx.utils.Align import com.unciv.logic.civilization.CivilizationInfo import com.unciv.logic.map.TileInfo -import com.unciv.ui.cityscreen.addClickListener import com.unciv.ui.utils.CameraStageBaseScreen import com.unciv.ui.utils.ImageGetter @@ -43,49 +40,15 @@ class TileInfoTable(private val worldScreen: WorldScreen, internal val civInfo: } - if (tile.unit != null) { - val tileMapHolder = worldScreen.tileMapHolder - val buttonText = if (tileMapHolder.unitTile == tile)"Stop movement" else "Move to" - var moveUnitButton = TextButton(buttonText, skin) - moveUnitButton.label.setFontScale(worldScreen.buttonScale) - if (tile.unit!!.currentMovement == 0f) { - moveUnitButton.color = Color.GRAY - moveUnitButton.touchable = Touchable.disabled - } - moveUnitButton.addClickListener { - if (tileMapHolder.unitTile != null) { - tileMapHolder.unitTile = null - tileMapHolder.updateTiles() - return@addClickListener - } - tileMapHolder.unitTile = tile +// if (tile.unit != null) { +// for (button in UnitActions().getUnitActions(tile)) +// add(button).colspan(2) +// .size(button.width * worldScreen.buttonScale, button.height * worldScreen.buttonScale).row() +// } - // Set all tiles transparent except those in unit range - for (TG in tileMapHolder.tileGroups.linqValues()) TG.setColor(0f, 0f, 0f, 0.3f) + pack() - val distanceToTiles = civInfo.gameInfo.tileMap.getDistanceToTilesWithinTurn( - tileMapHolder.unitTile!!.position, - tileMapHolder.unitTile!!.unit!!.currentMovement, - civInfo.tech.isResearched("Machinery")) - - for (tile in distanceToTiles.keys) { - tileMapHolder.tileGroups[tile.position.toString()]!!.color = Color.WHITE - } - - worldScreen.update() - } - - add(moveUnitButton).colspan(2) - .size(moveUnitButton.width * worldScreen.buttonScale, moveUnitButton.height * worldScreen.buttonScale).row() - - for (button in UnitActions().getUnitActions(tile.unit!!,tile,civInfo)) - add(button).colspan(2) - .size(button.width * worldScreen.buttonScale, button.height * worldScreen.buttonScale).row() - - pack() - - setPosition(worldScreen.stage.width - 10f - width, 10f) - } + setPosition(worldScreen.stage.width - 10f - width, 10f) } } diff --git a/core/src/com/unciv/ui/worldscreen/TileMapHolder.kt b/core/src/com/unciv/ui/worldscreen/TileMapHolder.kt index 6883368635..aecf26964b 100644 --- a/core/src/com/unciv/ui/worldscreen/TileMapHolder.kt +++ b/core/src/com/unciv/ui/worldscreen/TileMapHolder.kt @@ -13,11 +13,10 @@ import com.unciv.models.linq.LinqHashMap import com.unciv.ui.cityscreen.addClickListener import com.unciv.ui.tilegroups.WorldTileGroup import com.unciv.ui.utils.HexMath -import java.util.* class TileMapHolder(internal val worldScreen: WorldScreen, internal val tileMap: TileMap, internal val civInfo: CivilizationInfo) : ScrollPane(null) { internal var selectedTile: TileInfo? = null - internal var unitTile: TileInfo? = null + //internal var unitTile: TileInfo? = null val tileGroups = LinqHashMap() internal fun addTiles() { @@ -39,19 +38,7 @@ class TileMapHolder(internal val worldScreen: WorldScreen, internal val tileMap: worldScreen.displayTutorials("TileClicked", tutorial) selectedTile = tileInfo - if (unitTile != null && group.tileInfo.unit == null) { - val distanceToTiles = tileMap.getDistanceToTilesWithinTurn(unitTile!!.position, unitTile!!.unit!!.currentMovement, civInfo.tech.isResearched("Machinery")) - if (distanceToTiles.containsKey(selectedTile)) { - unitTile!!.moveUnitToTile(group.tileInfo, distanceToTiles[selectedTile]!!) - } else { - unitTile!!.unit!!.action = "moveTo " + selectedTile!!.position.x.toInt() + "," + selectedTile!!.position.y.toInt() - unitTile!!.unit!!.doPreTurnAction(unitTile!!) - } - - unitTile = null - selectedTile = group.tileInfo - } - + worldScreen.unitTable.tileSelected(tileInfo) worldScreen.update() } @@ -102,35 +89,28 @@ class TileMapHolder(internal val worldScreen: WorldScreen, internal val tileMap: internal fun updateTiles() { for (WG in tileGroups.linqValues()) WG.update(worldScreen) - if (unitTile != null) - return // While we're in "unit move" mode, no tiles but the tiles the unit can move to will be "visible" - // YES A TRIPLE FOR, GOT PROBLEMS WITH THAT? - // Seriously though, there is probably a more efficient way of doing this, probably? - // The original implementation caused serious lag on android, so efficiency is key, here for (WG in tileGroups.linqValues()) WG.setIsViewable(false) - val veiwableVectorStrings = HashSet() + var viewablePositions = emptyList() + if(worldScreen.unitTable.currentlyExecutingAction == null) { + viewablePositions += tileMap.values.where { it.owner == civInfo.civName } + .flatMap { HexMath.GetAdjacentVectors(it.position) } // tiles adjacent to city tiles + viewablePositions += tileMap.values.where { it.unit != null } + .flatMap { tileMap.getViewableTiles(it.position, 2).select { it.position } } // Tiles within 2 tiles of units + } - // tiles adjacent to city tiles - for (tileInfo in tileMap.values) - if (civInfo.civName == tileInfo.owner) - for (adjacentLocation in HexMath.GetAdjacentVectors(tileInfo.position)) - veiwableVectorStrings.add(adjacentLocation.toString()) + else + viewablePositions += worldScreen.unitTable.getViewablePositionsForExecutingAction() - // Tiles within 2 tiles of units - for (tile in tileMap.values - .where { arg0 -> arg0.unit != null }) - for (tileInfo in tileMap.getViewableTiles(tile.position, 2)) - veiwableVectorStrings.add(tileInfo.position.toString()) + for (string in viewablePositions.map { it.toString() }.filter { tileGroups.containsKey(it) }) + tileGroups[string]!!.setIsViewable(true) - for (string in veiwableVectorStrings) - if (tileGroups.containsKey(string)) - tileGroups[string]!!.setIsViewable(true) } - fun setCenterPosition(vector: Vector2) { val tileGroup = tileGroups.linqValues().first { it.tileInfo.position == vector } + selectedTile = tileGroup.tileInfo + if(selectedTile!!.unit!=null) worldScreen.unitTable.selectedUnitTile = selectedTile layout() // Fit the scroll pane to the contents - otherwise, setScroll won't work! // We want to center on the middle of TG (TG.getX()+TG.getWidth()/2) // and so the scroll position (== where the screen starts) needs to be half a screen away @@ -138,6 +118,7 @@ class TileMapHolder(internal val worldScreen: WorldScreen, internal val tileMap: // Here it's the same, only the Y axis is inverted - when at 0 we're at the top, not bottom - so we invert it back. scrollY = maxY - (tileGroup.y + tileGroup.width / 2 - worldScreen.stage.height / 2) updateVisualScroll() + worldScreen.update() } diff --git a/core/src/com/unciv/ui/worldscreen/WorldScreen.kt b/core/src/com/unciv/ui/worldscreen/WorldScreen.kt index 0293925e1a..afcfd97c5e 100644 --- a/core/src/com/unciv/ui/worldscreen/WorldScreen.kt +++ b/core/src/com/unciv/ui/worldscreen/WorldScreen.kt @@ -10,6 +10,7 @@ import com.unciv.ui.pickerscreens.PolicyPickerScreen import com.unciv.ui.pickerscreens.TechPickerScreen import com.unciv.ui.utils.CameraStageBaseScreen import com.unciv.ui.utils.GameSaver +import com.unciv.ui.worldscreen.unit.UnitTable class WorldScreen : CameraStageBaseScreen() { internal val civInfo: CivilizationInfo @@ -24,7 +25,7 @@ class WorldScreen : CameraStageBaseScreen() { internal val optionsTable: WorldScreenOptionsTable private val notificationsScroll: NotificationsScroll - internal val idleUnitButton = IdleUnitButton(this) + internal val unitTable = UnitTable(this) init { val gameInfo = game.gameInfo @@ -41,7 +42,7 @@ class WorldScreen : CameraStageBaseScreen() { stage.addActor(civTable) stage.addActor(techButton) stage.addActor(notificationsScroll) - stage.addActor(idleUnitButton) + stage.addActor(unitTable) update() tileMapHolder.setCenterPosition(Vector2.Zero) @@ -80,7 +81,7 @@ class WorldScreen : CameraStageBaseScreen() { tileMapHolder.updateTiles() civTable.update(this) notificationsScroll.update() - idleUnitButton.update() + unitTable.update() if (civInfo.tech.freeTechs != 0) { game.screen = TechPickerScreen(true, civInfo) } else if (civInfo.policies.shouldOpenPolicyPicker) { @@ -93,8 +94,8 @@ class WorldScreen : CameraStageBaseScreen() { techButton.isVisible = civInfo.cities.size != 0 techButton.clearListeners() techButton.addClickListener { - game.screen = TechPickerScreen(civInfo) - } + game.screen = TechPickerScreen(civInfo) + } if (civInfo.tech.currentTechnology() == null) techButton.setText("Choose a tech!") @@ -109,22 +110,23 @@ class WorldScreen : CameraStageBaseScreen() { private fun createNextTurnButton() { val nextTurnButton = TextButton("Next turn", CameraStageBaseScreen.skin) nextTurnButton.addClickListener { - if (civInfo.tech.currentTechnology() == null && civInfo.cities.size != 0) { - game.screen = TechPickerScreen(civInfo) - return@addClickListener - } - game.gameInfo.nextTurn() - tileMapHolder.unitTile = null - GameSaver.SaveGame(game, "Autosave") - update() - - val tutorial = Linq() - tutorial.add("In your first couple of turns," + - "\r\n you will have very little options," + - "\r\n but as your civilization grows, so do the " + - "\r\n number of things requiring your attention") - displayTutorials("NextTurn", tutorial) + if (civInfo.tech.currentTechnology() == null && civInfo.cities.size != 0) { + game.screen = TechPickerScreen(civInfo) + return@addClickListener } + game.gameInfo.nextTurn() + unitTable.selectedUnitTile = null + unitTable.currentlyExecutingAction = null + GameSaver.SaveGame(game, "Autosave") + update() + + val tutorial = Linq() + tutorial.add("In your first couple of turns," + + "\r\n you will have very little options," + + "\r\n but as your civilization grows, so do the " + + "\r\n number of things requiring your attention") + displayTutorials("NextTurn", tutorial) + } nextTurnButton.setPosition(stage.width - nextTurnButton.width - 10f, civTable.y - nextTurnButton.height - 10f) diff --git a/core/src/com/unciv/ui/worldscreen/IdleUnitButton.kt b/core/src/com/unciv/ui/worldscreen/unit/IdleUnitButton.kt similarity index 66% rename from core/src/com/unciv/ui/worldscreen/IdleUnitButton.kt rename to core/src/com/unciv/ui/worldscreen/unit/IdleUnitButton.kt index c4bb18e0be..e5381bf3e7 100644 --- a/core/src/com/unciv/ui/worldscreen/IdleUnitButton.kt +++ b/core/src/com/unciv/ui/worldscreen/unit/IdleUnitButton.kt @@ -1,4 +1,4 @@ -package com.unciv.ui.worldscreen +package com.unciv.ui.worldscreen.unit import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.scenes.scene2d.Touchable @@ -6,12 +6,12 @@ import com.badlogic.gdx.scenes.scene2d.ui.TextButton import com.unciv.logic.map.TileInfo import com.unciv.ui.cityscreen.addClickListener import com.unciv.ui.utils.CameraStageBaseScreen +import com.unciv.ui.worldscreen.WorldScreen class IdleUnitButton internal constructor(internal val worldScreen: WorldScreen) : TextButton("Select next idle unit", CameraStageBaseScreen.skin) { init { - setPosition(worldScreen.stage.width / 2 - width / 2, 5f) addClickListener { - val tilesWithIdleUnits = worldScreen.civInfo.gameInfo.tileMap.values.where { arg0 -> arg0.hasIdleUnit() } + val tilesWithIdleUnits = worldScreen.civInfo.gameInfo.tileMap.values.where { it.hasIdleUnit() } val tileToSelect: TileInfo if (!tilesWithIdleUnits.contains(worldScreen.tileMapHolder.selectedTile)) @@ -22,18 +22,18 @@ class IdleUnitButton internal constructor(internal val worldScreen: WorldScreen) tileToSelect = tilesWithIdleUnits[index] } worldScreen.tileMapHolder.setCenterPosition(tileToSelect.position) - worldScreen.tileMapHolder.selectedTile = tileToSelect worldScreen.update() } } internal fun update() { - if (worldScreen.civInfo.gameInfo.tileMap.values.any { arg0 -> arg0.hasIdleUnit() }) { - worldScreen.idleUnitButton.color = Color.WHITE - worldScreen.idleUnitButton.touchable = Touchable.enabled + if (worldScreen.civInfo.gameInfo.tileMap.values.any { it.hasIdleUnit() }) { + color = Color.WHITE + touchable = Touchable.enabled } else { - worldScreen.idleUnitButton.color = Color.GRAY - worldScreen.idleUnitButton.touchable = Touchable.disabled + color = Color.GRAY + touchable = Touchable.disabled } } } + diff --git a/core/src/com/unciv/ui/worldscreen/UnitActions.kt b/core/src/com/unciv/ui/worldscreen/unit/UnitActions.kt similarity index 65% rename from core/src/com/unciv/ui/worldscreen/UnitActions.kt rename to core/src/com/unciv/ui/worldscreen/unit/UnitActions.kt index 3ef7a9b839..6adcc31c67 100644 --- a/core/src/com/unciv/ui/worldscreen/UnitActions.kt +++ b/core/src/com/unciv/ui/worldscreen/unit/UnitActions.kt @@ -1,9 +1,8 @@ -package com.unciv.ui.worldscreen +package com.unciv.ui.worldscreen.unit import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.scenes.scene2d.Touchable import com.badlogic.gdx.scenes.scene2d.ui.TextButton -import com.unciv.logic.civilization.CivilizationInfo import com.unciv.logic.map.MapUnit import com.unciv.logic.map.TileInfo import com.unciv.models.gamebasics.Building @@ -11,11 +10,12 @@ import com.unciv.models.gamebasics.GameBasics import com.unciv.models.linq.Linq import com.unciv.ui.UnCivGame import com.unciv.ui.cityscreen.addClickListener +import com.unciv.ui.pickerscreens.ImprovementPickerScreen import com.unciv.ui.pickerscreens.TechPickerScreen import com.unciv.ui.utils.CameraStageBaseScreen -import java.util.ArrayList +import java.util.* -public class UnitActions { +class UnitActions { private fun constructImprovementAndDestroyUnit(tileInfo: TileInfo, improvementName: String): () -> Unit { return { @@ -24,15 +24,42 @@ public class UnitActions { } } - fun getUnitActions(unit: MapUnit, tile: TileInfo, civInfo: CivilizationInfo): List { + fun getUnitActions(tile: TileInfo): List { + val unit = tile.unit!! val worldScreen = UnCivGame.Current.worldScreen!! + val tileMapHolder = worldScreen.tileMapHolder + val unitTable = worldScreen.unitTable val actionList = ArrayList() + if (unitTable.currentlyExecutingAction != "moveTo"){ + actionList += getUnitActionButton(unit, "Move unit", true, { + unitTable.currentlyExecutingAction = "moveTo" + // Set all tiles transparent except those in unit range + for (TG in tileMapHolder.tileGroups.linqValues()) TG.setColor(0f, 0f, 0f, 0.3f) + + val distanceToTiles = tileMapHolder.tileMap.getDistanceToTilesWithinTurn( + unitTable.selectedUnitTile!!.position, + unitTable.getSelectedUnit().currentMovement, + unit.civInfo.tech.isResearched("Machinery")) + + for (tileInRange in distanceToTiles.keys) { + tileMapHolder.tileGroups[tileInRange.position.toString()]!!.color = Color.WHITE + } + }) + } + + else { + actionList += getUnitActionButton(unit, "Stop movement", true, { + unitTable.currentlyExecutingAction = null + tileMapHolder.updateTiles() + }) + } + if (unit.name == "Settler") { actionList += getUnitActionButton(unit, "Found City", - !civInfo.gameInfo.tileMap.getTilesInDistance(tile.position, 2).any { it.isCityCenter }, + !tileMapHolder.tileMap.getTilesInDistance(tile.position, 2).any { it.isCityCenter }, { val tutorial = Linq() tutorial.add("You have founded a city!" + @@ -48,9 +75,8 @@ public class UnitActions { worldScreen.displayTutorials("CityFounded", tutorial) - civInfo.addCity(tile.position) - if (worldScreen.tileMapHolder.unitTile == tile) - worldScreen.tileMapHolder.unitTile = null // The settler was in the middle of moving and we then founded a city with it + unit.civInfo.addCity(tile.position) + unitTable.currentlyExecutingAction = null // In case the settler was in the middle of doing something and we then founded a city with it tile.unit = null // Remove settler! worldScreen.update() }) @@ -60,25 +86,30 @@ public class UnitActions { val improvementButtonText = if (tile.improvementInProgress == null) "Construct\r\nimprovement" else tile.improvementInProgress!! + "\r\nin progress" - actionList += getUnitActionButton(unit, improvementButtonText, !tile.isCityCenter || GameBasics.TileImprovements.linqValues().any { arg0 -> tile.canBuildImprovement(arg0, civInfo) }, - { worldScreen.game.screen = com.unciv.ui.pickerscreens.ImprovementPickerScreen(tile) }) - actionList += getUnitActionButton(unit, if ("automation" == tile.unit!!.action) "Stop automation" else "Automate", true, { - if ("automation" == tile.unit!!.action) - tile.unit!!.action = null - else { - tile.unit!!.action = "automation" - tile.unit!!.doAutomatedAction(tile) - } - worldScreen.update() - }) + actionList += getUnitActionButton(unit, improvementButtonText, + !tile.isCityCenter || GameBasics.TileImprovements.linqValues().any { tile.canBuildImprovement(it, unit.civInfo) }, + { worldScreen.game.screen = ImprovementPickerScreen(tile) }) + + if("automation" == tile.unit!!.action){ + actionList += getUnitActionButton(unit,"Stop automation",true, + {tile.unit!!.action = null}) + } + else { + actionList += getUnitActionButton(unit, "Automate", true, + { + tile.unit!!.action = "automation" + tile.unit!!.doAutomatedAction(tile) + } + ) + } } if (unit.name == "Great Scientist") { actionList += getUnitActionButton(unit, "Discover Technology", true, { - civInfo.tech.freeTechs += 1 + unit.civInfo.tech.freeTechs += 1 tile.unit = null// destroy! - worldScreen.game.screen = TechPickerScreen(true, civInfo) + worldScreen.game.screen = TechPickerScreen(true, unit.civInfo) }) actionList += getUnitActionButton(unit, "Construct Academy", true, @@ -88,7 +119,7 @@ public class UnitActions { if (unit.name == "Great Artist") { actionList += getUnitActionButton(unit, "Start Golden Age", true, { - civInfo.goldenAges.enterGoldenAge() + unit.civInfo.goldenAges.enterGoldenAge() tile.unit = null// destroy! worldScreen.update() } @@ -112,7 +143,7 @@ public class UnitActions { if (unit.name == "Great Merchant") { actionList += getUnitActionButton(unit, "Conduct Trade Mission", true, { - civInfo.gold += 350 // + 50 * era_number - todo! + unit.civInfo.gold += 350 // + 50 * era_number - todo! tile.unit = null // destroy! }) actionList += getUnitActionButton(unit, "Construct Customs House", true, diff --git a/core/src/com/unciv/ui/worldscreen/unit/UnitTable.kt b/core/src/com/unciv/ui/worldscreen/unit/UnitTable.kt new file mode 100644 index 0000000000..dd172eeeca --- /dev/null +++ b/core/src/com/unciv/ui/worldscreen/unit/UnitTable.kt @@ -0,0 +1,80 @@ +package com.unciv.ui.worldscreen.unit + +import com.badlogic.gdx.graphics.Color +import com.badlogic.gdx.math.Vector2 +import com.badlogic.gdx.scenes.scene2d.ui.Label +import com.badlogic.gdx.scenes.scene2d.ui.Table +import com.unciv.logic.map.MapUnit +import com.unciv.logic.map.TileInfo +import com.unciv.models.linq.LinqHashMap +import com.unciv.ui.utils.CameraStageBaseScreen +import com.unciv.ui.utils.ImageGetter +import com.unciv.ui.worldscreen.WorldScreen + +class UnitTable(val worldScreen: WorldScreen) : Table(){ + private val idleUnitButton = IdleUnitButton(worldScreen) + private val unitLabel = Label("",CameraStageBaseScreen.skin) + var selectedUnitTile : TileInfo? = null + var currentlyExecutingAction : String? = null + + private val unitActionsTable = Table() + + fun getSelectedUnit(): MapUnit { + if(selectedUnitTile==null) throw Exception("getSelectedUnit was called when no unit was selected!") + else return selectedUnitTile!!.unit!! + } + + init { + val tileTableBackground = ImageGetter.getDrawable("skin/tileTableBackground.png") + .tint(Color(0x004085bf)) + pad(20f) + setBackground(tileTableBackground) + add(unitLabel) + add(unitActionsTable) + row() + add(idleUnitButton).colspan(2) + } + + fun update() { + idleUnitButton.update() + + unitActionsTable.clear() + if(selectedUnitTile!=null && selectedUnitTile!!.unit==null) selectedUnitTile=null // The unit that was there no longer exists + + if(selectedUnitTile!=null) { + unitLabel.setText(getSelectedUnit().name+" "+getSelectedUnit().movementString) + for (button in UnitActions().getUnitActions(selectedUnitTile!!)) + unitActionsTable.add(button).colspan(2).pad(5f) + .size(button.width * worldScreen.buttonScale, button.height * worldScreen.buttonScale).row() + } + unitActionsTable.pack() + pack() + + setPosition(worldScreen.stage.width / 2 - width / 2, 5f) + } + + fun tileSelected(selectedTile: TileInfo) { + if(currentlyExecutingAction=="moveTo"){ + val reachedTile = getSelectedUnit().headTowards(selectedUnitTile!!.position, selectedTile.position) + selectedUnitTile = reachedTile + if(reachedTile!=selectedTile) // Didn't get all the way there + getSelectedUnit().action = "moveTo " + selectedTile.position.x.toInt() + "," + selectedTile.position.y.toInt() + currentlyExecutingAction = null + } + + if(selectedTile.unit!=null) selectedUnitTile = selectedTile + } + + private fun getDistanceToTiles(): LinqHashMap { + return worldScreen.tileMapHolder.tileMap.getDistanceToTilesWithinTurn(selectedUnitTile!!.position, + getSelectedUnit().currentMovement, + getSelectedUnit().civInfo.tech.isResearched("Machinery")) + } + + fun getViewablePositionsForExecutingAction(): List + { + if(currentlyExecutingAction == "moveTo") + return getDistanceToTiles().keys.map { it.position } + return emptyList() + } +}