Unit control transferred to UnitTable

This commit is contained in:
Yair Morgenstern 2018-03-07 18:37:16 +02:00
parent 07c011143d
commit 1a4a9d416c
13 changed files with 247 additions and 182 deletions

View File

View File

@ -9,7 +9,7 @@ import java.text.DecimalFormat
class MapUnit { class MapUnit {
@Transient @Transient
@JvmField var civInfo: CivilizationInfo? = null lateinit var civInfo: CivilizationInfo
@JvmField var owner: String? = null @JvmField var owner: String? = null
@JvmField var name: String? = null @JvmField var name: String? = null
@ -55,7 +55,7 @@ class MapUnit {
private fun getPriority(tileInfo: TileInfo): Int { private fun getPriority(tileInfo: TileInfo): Int {
var priority = 0 var priority = 0
if (tileInfo.workingCity != null) priority += 2 if (tileInfo.workingCity != null) priority += 2
if (tileInfo.hasViewableResource(civInfo!!)) priority += 1 if (tileInfo.hasViewableResource(civInfo)) priority += 1
if (tileInfo.owner == owner) priority += 2 if (tileInfo.owner == owner) priority += 2
else if (tileInfo.neighbors.any { it.owner != null }) priority += 1 else if (tileInfo.neighbors.any { it.owner != null }) priority += 1
return priority return priority
@ -64,15 +64,15 @@ class MapUnit {
private fun findTileToWork(currentTile: TileInfo): TileInfo { private fun findTileToWork(currentTile: TileInfo): TileInfo {
var selectedTile = currentTile var selectedTile = currentTile
var selectedTilePriority = var selectedTilePriority =
if (currentTile.improvement == null && currentTile.canBuildImprovement(chooseImprovement(currentTile), civInfo!!)) if (currentTile.improvement == null && currentTile.canBuildImprovement(chooseImprovement(currentTile), civInfo))
getPriority(currentTile) getPriority(currentTile)
else else
1 // min rank to get selected is 2 1 // min rank to get selected is 2
for (i in 1..4) 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 if (tile.unit == null && tile.improvement == null && getPriority(tile) > selectedTilePriority
&& tile.canBuildImprovement(chooseImprovement(tile), civInfo!!)) { && tile.canBuildImprovement(chooseImprovement(tile), civInfo)) {
selectedTile = tile selectedTile = tile
selectedTilePriority = getPriority(tile) selectedTilePriority = getPriority(tile)
} }
@ -90,9 +90,9 @@ class MapUnit {
} }
if (tile.improvementInProgress == null) { if (tile.improvementInProgress == null) {
val improvement = chooseImprovement(tile) 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? // 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 * @param destination
* @return The tile that we reached this turn * @return The tile that we reached this turn
*/ */
private fun headTowards(origin: Vector2, destination: Vector2): TileInfo { fun headTowards(origin: Vector2, destination: Vector2): TileInfo {
val tileMap = civInfo!!.gameInfo.tileMap val tileMap = civInfo.gameInfo.tileMap
val isMachineryResearched = civInfo!!.tech.isResearched("Machinery") val isMachineryResearched = civInfo.tech.isResearched("Machinery")
val path = tileMap.getShortestPath(origin, destination, currentMovement, maxMovement, isMachineryResearched) val distanceToTiles = tileMap.getDistanceToTilesWithinTurn(origin, currentMovement, isMachineryResearched)
val destinationThisTurn = path.first() val destinationTileThisTurn:TileInfo
if (destinationThisTurn.unit != null) return tileMap[origin] // Someone is blocking tohe path to the final tile... if (distanceToTiles.containsKey(tileMap.get(destination)))
val distanceToTile = tileMap.getDistanceToTilesWithinTurn(origin, currentMovement, isMachineryResearched)[destinationThisTurn]!! destinationTileThisTurn = tileMap.get(destination)
tileMap[origin].moveUnitToTile(destinationThisTurn, distanceToTile)
return destinationThisTurn 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) { fun nextTurn(tileInfo: TileInfo) {

View File

@ -3,11 +3,11 @@ package com.unciv.logic.map
import com.badlogic.gdx.math.Vector2 import com.badlogic.gdx.math.Vector2
import com.unciv.logic.city.CityInfo import com.unciv.logic.city.CityInfo
import com.unciv.logic.civilization.CivilizationInfo import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.models.linq.Linq
import com.unciv.models.gamebasics.GameBasics import com.unciv.models.gamebasics.GameBasics
import com.unciv.models.gamebasics.Terrain import com.unciv.models.gamebasics.Terrain
import com.unciv.models.gamebasics.TileImprovement import com.unciv.models.gamebasics.TileImprovement
import com.unciv.models.gamebasics.TileResource import com.unciv.models.gamebasics.TileResource
import com.unciv.models.linq.Linq
import com.unciv.models.stats.Stats import com.unciv.models.stats.Stats
class TileInfo { class TileInfo {

View File

@ -1,11 +1,11 @@
package com.unciv.logic.map package com.unciv.logic.map
import com.badlogic.gdx.math.Vector2 import com.badlogic.gdx.math.Vector2
import com.unciv.logic.GameInfo
import com.unciv.logic.civilization.CivilizationInfo import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.models.gamebasics.GameBasics import com.unciv.models.gamebasics.GameBasics
import com.unciv.models.linq.Linq import com.unciv.models.linq.Linq
import com.unciv.models.linq.LinqHashMap import com.unciv.models.linq.LinqHashMap
import com.unciv.logic.GameInfo
import com.unciv.ui.utils.HexMath import com.unciv.ui.utils.HexMath
class TileMap { class TileMap {
@ -74,7 +74,7 @@ class TileMap {
return distanceToTiles return distanceToTiles
} }
fun getShortestPath(origin: Vector2, destination: Vector2, currentMovement: Float, maxMovement: Int, isMachineryResearched: Boolean): Linq<TileInfo> { fun getShortestPath(origin: Vector2, destination: Vector2, currentMovement: Float, maxMovement: Int, isMachineryResearched: Boolean): List<TileInfo> {
var tilesToCheck: Linq<TileInfo> = Linq(get(origin)) var tilesToCheck: Linq<TileInfo> = Linq(get(origin))
val movementTreeParents = LinqHashMap<TileInfo, TileInfo>() // contains a map of "you can get from X to Y in that turn" val movementTreeParents = LinqHashMap<TileInfo, TileInfo>() // contains a map of "you can get from X to Y in that turn"
movementTreeParents[get(origin)] = null movementTreeParents[get(origin)] = null
@ -82,24 +82,32 @@ class TileMap {
var distance = 1 var distance = 1
while (true) { while (true) {
val newTilesToCheck = Linq<TileInfo>() val newTilesToCheck = Linq<TileInfo>()
val distanceToDestination = HashMap<TileInfo, Float>()
val movementThisTurn = if (distance == 1) currentMovement else maxMovement.toFloat()
for (tileToCheck in tilesToCheck) { for (tileToCheck in tilesToCheck) {
val movementThisTurn = if (distance == 1) currentMovement else maxMovement.toFloat() val distanceToTilesThisTurn = getDistanceToTilesWithinTurn(tileToCheck.position, movementThisTurn, isMachineryResearched)
for (reachableTile in getDistanceToTilesWithinTurn(tileToCheck.position, movementThisTurn, isMachineryResearched).keys) { for (reachableTile in distanceToTilesThisTurn.keys) {
if (movementTreeParents.containsKey(reachableTile)) continue // We cannot be faster than anything existing... if(reachableTile.position == destination)
if (reachableTile.position != destination && reachableTile.unit != null) continue // This is an intermediary tile that contains a unit - we can't go there! distanceToDestination.put(tileToCheck, distanceToTilesThisTurn[reachableTile]!!)
movementTreeParents[reachableTile] = tileToCheck else {
if (reachableTile.position == destination) { if (movementTreeParents.containsKey(reachableTile)) continue // We cannot be faster than anything existing...
val path = Linq<TileInfo>() // Traverse the tree upwards to get the list of tiles leading to the destination, if (reachableTile.position != destination && reachableTile.unit != null) continue // This is an intermediary tile that contains a unit - we can't go there!
var current = reachableTile movementTreeParents[reachableTile] = tileToCheck
while (movementTreeParents[current] != null) { newTilesToCheck.add(reachableTile)
path.add(current)
current = movementTreeParents[current]
}
return path.reverse() // and reverse in order to get the list in chronological order
} }
newTilesToCheck.add(reachableTile)
} }
} }
if (distanceToDestination.isNotEmpty()) {
val path = Linq<TileInfo>() // 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 tilesToCheck = newTilesToCheck
distance++ distance++
} }

View File

@ -2,13 +2,13 @@ package com.unciv.models.gamebasics
import com.unciv.logic.city.CityConstructions import com.unciv.logic.city.CityConstructions
import com.unciv.logic.city.IConstruction 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.ScienceVictoryScreen
import com.unciv.ui.UnCivGame import com.unciv.ui.UnCivGame
import com.unciv.ui.VictoryScreen import com.unciv.ui.VictoryScreen
import com.unciv.ui.pickerscreens.PolicyPickerScreen 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 { class Building : NamedStats(), IConstruction, ICivilopedia {
private lateinit var baseDescription: String 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" }) if ("MustBeNextToDesert" == unique && !civInfo.gameInfo.tileMap.getTilesInDistance(construction.cityInfo.cityLocation, 1).any { it.baseTerrain == "Desert" })
return false return false
if (requiredResource != null && !civInfo.getCivResources().containsKey(GameBasics.TileResources[requiredResource])) 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) { if (requiredNearbyImprovedResources != null) {

View File

@ -5,7 +5,6 @@ import com.badlogic.gdx.utils.Predicate;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
/** /**
@ -71,12 +70,6 @@ public class Linq<T> extends ArrayList<T> {
return newCollection; return newCollection;
} }
public Linq<T> reverse(){
Linq<T> newCol = clone();
Collections.reverse(newCol);
return newCol;
}
public Linq<T> clone(){ public Linq<T> clone(){
return new Linq<T>(this); return new Linq<T>(this);
} }

View File

@ -88,7 +88,6 @@ class PolicyPickerScreen(internal val civInfo: CivilizationInfo) : PickerScreen(
private fun pickPolicy(policy: Policy) { private fun pickPolicy(policy: Policy) {
if (civInfo.policies.isAdopted(policy.name) if (civInfo.policies.isAdopted(policy.name)
|| policy.name.endsWith("Complete")
|| !civInfo.policies.getAdoptedPolicies().containsAll(policy.requires!!) || !civInfo.policies.getAdoptedPolicies().containsAll(policy.requires!!)
|| !civInfo.policies.canAdoptPolicy()) { || !civInfo.policies.canAdoptPolicy()) {
rightSideButton.touchable = Touchable.disabled rightSideButton.touchable = Touchable.disabled
@ -112,12 +111,13 @@ class PolicyPickerScreen(internal val civInfo: CivilizationInfo) : PickerScreen(
} else } else
toReturn = TextButton(policy.name, CameraStageBaseScreen.skin) toReturn = TextButton(policy.name, CameraStageBaseScreen.skin)
when { if (civInfo.policies.isAdopted(policy.name)) { // existing
civInfo.policies.isAdopted(policy.name) -> toReturn.color = Color.GREEN toReturn.color = Color.GREEN
policy.name.endsWith("Complete") || !civInfo.policies.getAdoptedPolicies().containsAll(policy.requires!!) } else if (!civInfo.policies.getAdoptedPolicies().containsAll(policy.requires!!))
-> toReturn.color = Color.GRAY // non-available
{
toReturn.color = Color.GRAY
} }
toReturn.addClickListener { pickPolicy(policy) } toReturn.addClickListener { pickPolicy(policy) }
toReturn.pack() toReturn.pack()
return toReturn return toReturn

View File

@ -1,14 +1,11 @@
package com.unciv.ui.worldscreen package com.unciv.ui.worldscreen
import com.badlogic.gdx.graphics.Color 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.Label
import com.badlogic.gdx.scenes.scene2d.ui.Table import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.badlogic.gdx.scenes.scene2d.ui.TextButton
import com.badlogic.gdx.utils.Align import com.badlogic.gdx.utils.Align
import com.unciv.logic.civilization.CivilizationInfo import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.logic.map.TileInfo import com.unciv.logic.map.TileInfo
import com.unciv.ui.cityscreen.addClickListener
import com.unciv.ui.utils.CameraStageBaseScreen import com.unciv.ui.utils.CameraStageBaseScreen
import com.unciv.ui.utils.ImageGetter import com.unciv.ui.utils.ImageGetter
@ -43,49 +40,15 @@ class TileInfoTable(private val worldScreen: WorldScreen, internal val civInfo:
} }
if (tile.unit != null) { // if (tile.unit != null) {
val tileMapHolder = worldScreen.tileMapHolder // for (button in UnitActions().getUnitActions(tile))
val buttonText = if (tileMapHolder.unitTile == tile)"Stop movement" else "Move to" // add(button).colspan(2)
var moveUnitButton = TextButton(buttonText, skin) // .size(button.width * worldScreen.buttonScale, button.height * worldScreen.buttonScale).row()
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
// Set all tiles transparent except those in unit range pack()
for (TG in tileMapHolder.tileGroups.linqValues()) TG.setColor(0f, 0f, 0f, 0.3f)
val distanceToTiles = civInfo.gameInfo.tileMap.getDistanceToTilesWithinTurn( setPosition(worldScreen.stage.width - 10f - width, 10f)
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)
}
} }
} }

View File

@ -13,11 +13,10 @@ import com.unciv.models.linq.LinqHashMap
import com.unciv.ui.cityscreen.addClickListener import com.unciv.ui.cityscreen.addClickListener
import com.unciv.ui.tilegroups.WorldTileGroup import com.unciv.ui.tilegroups.WorldTileGroup
import com.unciv.ui.utils.HexMath 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) { class TileMapHolder(internal val worldScreen: WorldScreen, internal val tileMap: TileMap, internal val civInfo: CivilizationInfo) : ScrollPane(null) {
internal var selectedTile: TileInfo? = null internal var selectedTile: TileInfo? = null
internal var unitTile: TileInfo? = null //internal var unitTile: TileInfo? = null
val tileGroups = LinqHashMap<String, WorldTileGroup>() val tileGroups = LinqHashMap<String, WorldTileGroup>()
internal fun addTiles() { internal fun addTiles() {
@ -39,19 +38,7 @@ class TileMapHolder(internal val worldScreen: WorldScreen, internal val tileMap:
worldScreen.displayTutorials("TileClicked", tutorial) worldScreen.displayTutorials("TileClicked", tutorial)
selectedTile = tileInfo selectedTile = tileInfo
if (unitTile != null && group.tileInfo.unit == null) { worldScreen.unitTable.tileSelected(tileInfo)
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.update() worldScreen.update()
} }
@ -102,35 +89,28 @@ class TileMapHolder(internal val worldScreen: WorldScreen, internal val tileMap:
internal fun updateTiles() { internal fun updateTiles() {
for (WG in tileGroups.linqValues()) WG.update(worldScreen) 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) for (WG in tileGroups.linqValues()) WG.setIsViewable(false)
val veiwableVectorStrings = HashSet<String>() var viewablePositions = emptyList<Vector2>()
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 else
for (tileInfo in tileMap.values) viewablePositions += worldScreen.unitTable.getViewablePositionsForExecutingAction()
if (civInfo.civName == tileInfo.owner)
for (adjacentLocation in HexMath.GetAdjacentVectors(tileInfo.position))
veiwableVectorStrings.add(adjacentLocation.toString())
// Tiles within 2 tiles of units for (string in viewablePositions.map { it.toString() }.filter { tileGroups.containsKey(it) })
for (tile in tileMap.values tileGroups[string]!!.setIsViewable(true)
.where { arg0 -> arg0.unit != null })
for (tileInfo in tileMap.getViewableTiles(tile.position, 2))
veiwableVectorStrings.add(tileInfo.position.toString())
for (string in veiwableVectorStrings)
if (tileGroups.containsKey(string))
tileGroups[string]!!.setIsViewable(true)
} }
fun setCenterPosition(vector: Vector2) { fun setCenterPosition(vector: Vector2) {
val tileGroup = tileGroups.linqValues().first { it.tileInfo.position == vector } 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! 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) // 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 // 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. // 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) scrollY = maxY - (tileGroup.y + tileGroup.width / 2 - worldScreen.stage.height / 2)
updateVisualScroll() updateVisualScroll()
worldScreen.update()
} }

View File

@ -10,6 +10,7 @@ import com.unciv.ui.pickerscreens.PolicyPickerScreen
import com.unciv.ui.pickerscreens.TechPickerScreen import com.unciv.ui.pickerscreens.TechPickerScreen
import com.unciv.ui.utils.CameraStageBaseScreen import com.unciv.ui.utils.CameraStageBaseScreen
import com.unciv.ui.utils.GameSaver import com.unciv.ui.utils.GameSaver
import com.unciv.ui.worldscreen.unit.UnitTable
class WorldScreen : CameraStageBaseScreen() { class WorldScreen : CameraStageBaseScreen() {
internal val civInfo: CivilizationInfo internal val civInfo: CivilizationInfo
@ -24,7 +25,7 @@ class WorldScreen : CameraStageBaseScreen() {
internal val optionsTable: WorldScreenOptionsTable internal val optionsTable: WorldScreenOptionsTable
private val notificationsScroll: NotificationsScroll private val notificationsScroll: NotificationsScroll
internal val idleUnitButton = IdleUnitButton(this) internal val unitTable = UnitTable(this)
init { init {
val gameInfo = game.gameInfo val gameInfo = game.gameInfo
@ -41,7 +42,7 @@ class WorldScreen : CameraStageBaseScreen() {
stage.addActor(civTable) stage.addActor(civTable)
stage.addActor(techButton) stage.addActor(techButton)
stage.addActor(notificationsScroll) stage.addActor(notificationsScroll)
stage.addActor(idleUnitButton) stage.addActor(unitTable)
update() update()
tileMapHolder.setCenterPosition(Vector2.Zero) tileMapHolder.setCenterPosition(Vector2.Zero)
@ -80,7 +81,7 @@ class WorldScreen : CameraStageBaseScreen() {
tileMapHolder.updateTiles() tileMapHolder.updateTiles()
civTable.update(this) civTable.update(this)
notificationsScroll.update() notificationsScroll.update()
idleUnitButton.update() unitTable.update()
if (civInfo.tech.freeTechs != 0) { if (civInfo.tech.freeTechs != 0) {
game.screen = TechPickerScreen(true, civInfo) game.screen = TechPickerScreen(true, civInfo)
} else if (civInfo.policies.shouldOpenPolicyPicker) { } else if (civInfo.policies.shouldOpenPolicyPicker) {
@ -93,8 +94,8 @@ class WorldScreen : CameraStageBaseScreen() {
techButton.isVisible = civInfo.cities.size != 0 techButton.isVisible = civInfo.cities.size != 0
techButton.clearListeners() techButton.clearListeners()
techButton.addClickListener { techButton.addClickListener {
game.screen = TechPickerScreen(civInfo) game.screen = TechPickerScreen(civInfo)
} }
if (civInfo.tech.currentTechnology() == null) if (civInfo.tech.currentTechnology() == null)
techButton.setText("Choose a tech!") techButton.setText("Choose a tech!")
@ -109,22 +110,23 @@ class WorldScreen : CameraStageBaseScreen() {
private fun createNextTurnButton() { private fun createNextTurnButton() {
val nextTurnButton = TextButton("Next turn", CameraStageBaseScreen.skin) val nextTurnButton = TextButton("Next turn", CameraStageBaseScreen.skin)
nextTurnButton.addClickListener { nextTurnButton.addClickListener {
if (civInfo.tech.currentTechnology() == null && civInfo.cities.size != 0) { if (civInfo.tech.currentTechnology() == null && civInfo.cities.size != 0) {
game.screen = TechPickerScreen(civInfo) game.screen = TechPickerScreen(civInfo)
return@addClickListener return@addClickListener
}
game.gameInfo.nextTurn()
tileMapHolder.unitTile = null
GameSaver.SaveGame(game, "Autosave")
update()
val tutorial = Linq<String>()
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)
} }
game.gameInfo.nextTurn()
unitTable.selectedUnitTile = null
unitTable.currentlyExecutingAction = null
GameSaver.SaveGame(game, "Autosave")
update()
val tutorial = Linq<String>()
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, nextTurnButton.setPosition(stage.width - nextTurnButton.width - 10f,
civTable.y - nextTurnButton.height - 10f) civTable.y - nextTurnButton.height - 10f)

View File

@ -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.graphics.Color
import com.badlogic.gdx.scenes.scene2d.Touchable 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.logic.map.TileInfo
import com.unciv.ui.cityscreen.addClickListener import com.unciv.ui.cityscreen.addClickListener
import com.unciv.ui.utils.CameraStageBaseScreen 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) { class IdleUnitButton internal constructor(internal val worldScreen: WorldScreen) : TextButton("Select next idle unit", CameraStageBaseScreen.skin) {
init { init {
setPosition(worldScreen.stage.width / 2 - width / 2, 5f)
addClickListener { 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 val tileToSelect: TileInfo
if (!tilesWithIdleUnits.contains(worldScreen.tileMapHolder.selectedTile)) if (!tilesWithIdleUnits.contains(worldScreen.tileMapHolder.selectedTile))
@ -22,18 +22,18 @@ class IdleUnitButton internal constructor(internal val worldScreen: WorldScreen)
tileToSelect = tilesWithIdleUnits[index] tileToSelect = tilesWithIdleUnits[index]
} }
worldScreen.tileMapHolder.setCenterPosition(tileToSelect.position) worldScreen.tileMapHolder.setCenterPosition(tileToSelect.position)
worldScreen.tileMapHolder.selectedTile = tileToSelect
worldScreen.update() worldScreen.update()
} }
} }
internal fun update() { internal fun update() {
if (worldScreen.civInfo.gameInfo.tileMap.values.any { arg0 -> arg0.hasIdleUnit() }) { if (worldScreen.civInfo.gameInfo.tileMap.values.any { it.hasIdleUnit() }) {
worldScreen.idleUnitButton.color = Color.WHITE color = Color.WHITE
worldScreen.idleUnitButton.touchable = Touchable.enabled touchable = Touchable.enabled
} else { } else {
worldScreen.idleUnitButton.color = Color.GRAY color = Color.GRAY
worldScreen.idleUnitButton.touchable = Touchable.disabled touchable = Touchable.disabled
} }
} }
} }

View File

@ -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.graphics.Color
import com.badlogic.gdx.scenes.scene2d.Touchable import com.badlogic.gdx.scenes.scene2d.Touchable
import com.badlogic.gdx.scenes.scene2d.ui.TextButton 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.MapUnit
import com.unciv.logic.map.TileInfo import com.unciv.logic.map.TileInfo
import com.unciv.models.gamebasics.Building 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.models.linq.Linq
import com.unciv.ui.UnCivGame import com.unciv.ui.UnCivGame
import com.unciv.ui.cityscreen.addClickListener import com.unciv.ui.cityscreen.addClickListener
import com.unciv.ui.pickerscreens.ImprovementPickerScreen
import com.unciv.ui.pickerscreens.TechPickerScreen import com.unciv.ui.pickerscreens.TechPickerScreen
import com.unciv.ui.utils.CameraStageBaseScreen 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 { private fun constructImprovementAndDestroyUnit(tileInfo: TileInfo, improvementName: String): () -> Unit {
return { return {
@ -24,15 +24,42 @@ public class UnitActions {
} }
} }
fun getUnitActions(unit: MapUnit, tile: TileInfo, civInfo: CivilizationInfo): List<TextButton> { fun getUnitActions(tile: TileInfo): List<TextButton> {
val unit = tile.unit!!
val worldScreen = UnCivGame.Current.worldScreen!! val worldScreen = UnCivGame.Current.worldScreen!!
val tileMapHolder = worldScreen.tileMapHolder
val unitTable = worldScreen.unitTable
val actionList = ArrayList<TextButton>() val actionList = ArrayList<TextButton>()
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") { if (unit.name == "Settler") {
actionList += getUnitActionButton(unit, "Found City", 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<String>() val tutorial = Linq<String>()
tutorial.add("You have founded a city!" + tutorial.add("You have founded a city!" +
@ -48,9 +75,8 @@ public class UnitActions {
worldScreen.displayTutorials("CityFounded", tutorial) worldScreen.displayTutorials("CityFounded", tutorial)
civInfo.addCity(tile.position) unit.civInfo.addCity(tile.position)
if (worldScreen.tileMapHolder.unitTile == tile) unitTable.currentlyExecutingAction = null // In case the settler was in the middle of doing something and we then founded a city with it
worldScreen.tileMapHolder.unitTile = null // The settler was in the middle of moving and we then founded a city with it
tile.unit = null // Remove settler! tile.unit = null // Remove settler!
worldScreen.update() worldScreen.update()
}) })
@ -60,25 +86,30 @@ public class UnitActions {
val improvementButtonText = val improvementButtonText =
if (tile.improvementInProgress == null) "Construct\r\nimprovement" if (tile.improvementInProgress == null) "Construct\r\nimprovement"
else tile.improvementInProgress!! + "\r\nin progress" else tile.improvementInProgress!! + "\r\nin progress"
actionList += getUnitActionButton(unit, improvementButtonText, !tile.isCityCenter || GameBasics.TileImprovements.linqValues().any { arg0 -> tile.canBuildImprovement(arg0, civInfo) }, actionList += getUnitActionButton(unit, improvementButtonText,
{ worldScreen.game.screen = com.unciv.ui.pickerscreens.ImprovementPickerScreen(tile) }) !tile.isCityCenter || GameBasics.TileImprovements.linqValues().any { tile.canBuildImprovement(it, unit.civInfo) },
actionList += getUnitActionButton(unit, if ("automation" == tile.unit!!.action) "Stop automation" else "Automate", true, { { worldScreen.game.screen = ImprovementPickerScreen(tile) })
if ("automation" == tile.unit!!.action)
tile.unit!!.action = null if("automation" == tile.unit!!.action){
else { actionList += getUnitActionButton(unit,"Stop automation",true,
tile.unit!!.action = "automation" {tile.unit!!.action = null})
tile.unit!!.doAutomatedAction(tile) }
} else {
worldScreen.update() actionList += getUnitActionButton(unit, "Automate", true,
}) {
tile.unit!!.action = "automation"
tile.unit!!.doAutomatedAction(tile)
}
)
}
} }
if (unit.name == "Great Scientist") { if (unit.name == "Great Scientist") {
actionList += getUnitActionButton(unit, "Discover Technology", true, actionList += getUnitActionButton(unit, "Discover Technology", true,
{ {
civInfo.tech.freeTechs += 1 unit.civInfo.tech.freeTechs += 1
tile.unit = null// destroy! tile.unit = null// destroy!
worldScreen.game.screen = TechPickerScreen(true, civInfo) worldScreen.game.screen = TechPickerScreen(true, unit.civInfo)
}) })
actionList += getUnitActionButton(unit, "Construct Academy", true, actionList += getUnitActionButton(unit, "Construct Academy", true,
@ -88,7 +119,7 @@ public class UnitActions {
if (unit.name == "Great Artist") { if (unit.name == "Great Artist") {
actionList += getUnitActionButton(unit, "Start Golden Age", true, actionList += getUnitActionButton(unit, "Start Golden Age", true,
{ {
civInfo.goldenAges.enterGoldenAge() unit.civInfo.goldenAges.enterGoldenAge()
tile.unit = null// destroy! tile.unit = null// destroy!
worldScreen.update() worldScreen.update()
} }
@ -112,7 +143,7 @@ public class UnitActions {
if (unit.name == "Great Merchant") { if (unit.name == "Great Merchant") {
actionList += getUnitActionButton(unit, "Conduct Trade Mission", true, 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! tile.unit = null // destroy!
}) })
actionList += getUnitActionButton(unit, "Construct Customs House", true, actionList += getUnitActionButton(unit, "Construct Customs House", true,

View File

@ -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<TileInfo, Float> {
return worldScreen.tileMapHolder.tileMap.getDistanceToTilesWithinTurn(selectedUnitTile!!.position,
getSelectedUnit().currentMovement,
getSelectedUnit().civInfo.tech.isResearched("Machinery"))
}
fun getViewablePositionsForExecutingAction(): List<Vector2>
{
if(currentlyExecutingAction == "moveTo")
return getDistanceToTiles().keys.map { it.position }
return emptyList()
}
}