mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-28 22:37:02 -04:00
Merge branch 'roadOnLongClick'
This commit is contained in:
commit
7e6b102f27
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Before Width: | Height: | Size: 988 KiB After Width: | Height: | Size: 988 KiB |
@ -227,6 +227,10 @@
|
|||||||
Japanese:"自動化を停止"
|
Japanese:"自動化を停止"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"Construct road": {
|
||||||
|
"German": "Straße bauen"
|
||||||
|
}
|
||||||
|
|
||||||
"Fortify":{
|
"Fortify":{
|
||||||
Italian:"Fortifica"
|
Italian:"Fortifica"
|
||||||
Russian:"Укрепить"
|
Russian:"Укрепить"
|
||||||
@ -258,7 +262,7 @@
|
|||||||
Romanian:"Dormi"
|
Romanian:"Dormi"
|
||||||
Simplified_Chinese:"休眠"
|
Simplified_Chinese:"休眠"
|
||||||
Portuguese:"Dormir"
|
Portuguese:"Dormir"
|
||||||
German:"Schlafen legen"
|
German:"Schlafen"
|
||||||
French:"Dormir"
|
French:"Dormir"
|
||||||
Japanese:"睡眠"
|
Japanese:"睡眠"
|
||||||
Russian:"Спать"
|
Russian:"Спать"
|
||||||
@ -266,6 +270,10 @@
|
|||||||
Spanish:"Dormir"
|
Spanish:"Dormir"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"Moving": {
|
||||||
|
"German": "Bewegen"
|
||||||
|
}
|
||||||
|
|
||||||
"Set up":{ // For siege units
|
"Set up":{ // For siege units
|
||||||
Italian:"Monta"
|
Italian:"Monta"
|
||||||
Russian:"Подготовится"
|
Russian:"Подготовится"
|
||||||
|
@ -49,23 +49,20 @@ class WorkerAutomation(val unit: MapUnit) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
fun tryConnectingCities():Boolean{ // returns whether we actually did anything
|
fun tryConnectingCities():Boolean { // returns whether we actually did anything
|
||||||
val techEnablingRailroad = GameBasics.TileImprovements["Railroad"]!!.techRequired!!
|
|
||||||
val canBuildRailroad = unit.civInfo.tech.isResearched(techEnablingRailroad)
|
|
||||||
|
|
||||||
val targetRoadName = if (canBuildRailroad) "Railroad" else "Road"
|
val targetRoad = unit.civInfo.tech.getBestRoadAvailable()
|
||||||
val targetStatus = if (canBuildRailroad) RoadStatus.Railroad else RoadStatus.Road
|
|
||||||
|
|
||||||
val citiesThatNeedConnecting = unit.civInfo.cities
|
val citiesThatNeedConnecting = unit.civInfo.cities
|
||||||
.filter { it.population.population>3 && !it.isCapital()
|
.filter { it.population.population>3 && !it.isCapital()
|
||||||
&& !it.cityStats.isConnectedToCapital(targetStatus) }
|
&& !it.cityStats.isConnectedToCapital(targetRoad) }
|
||||||
if(citiesThatNeedConnecting.isEmpty()) return false // do nothing.
|
if(citiesThatNeedConnecting.isEmpty()) return false // do nothing.
|
||||||
|
|
||||||
val citiesThatNeedConnectingBfs = citiesThatNeedConnecting
|
val citiesThatNeedConnectingBfs = citiesThatNeedConnecting
|
||||||
.map { city -> BFS(city.getCenterTile()){it.isLand && unit.canPassThrough(it)} }
|
.map { city -> BFS(city.getCenterTile()){it.isLand && unit.canPassThrough(it)} }
|
||||||
.toMutableList()
|
.toMutableList()
|
||||||
|
|
||||||
val connectedCities = unit.civInfo.cities.filter { it.isCapital() || it.cityStats.isConnectedToCapital(targetStatus) }
|
val connectedCities = unit.civInfo.cities.filter { it.isCapital() || it.cityStats.isConnectedToCapital(targetRoad) }
|
||||||
.map { it.getCenterTile() }
|
.map { it.getCenterTile() }
|
||||||
|
|
||||||
while(citiesThatNeedConnectingBfs.any()){
|
while(citiesThatNeedConnectingBfs.any()){
|
||||||
@ -78,7 +75,7 @@ class WorkerAutomation(val unit: MapUnit) {
|
|||||||
for(city in connectedCities)
|
for(city in connectedCities)
|
||||||
if(bfs.tilesToCheck.contains(city)) { // we have a winner!
|
if(bfs.tilesToCheck.contains(city)) { // we have a winner!
|
||||||
val pathToCity = bfs.getPathTo(city)
|
val pathToCity = bfs.getPathTo(city)
|
||||||
val roadableTiles = pathToCity.filter { it.roadStatus < targetStatus }
|
val roadableTiles = pathToCity.filter { it.roadStatus < targetRoad }
|
||||||
val tileToConstructRoadOn :TileInfo
|
val tileToConstructRoadOn :TileInfo
|
||||||
if(unit.currentTile in roadableTiles) tileToConstructRoadOn = unit.currentTile
|
if(unit.currentTile in roadableTiles) tileToConstructRoadOn = unit.currentTile
|
||||||
else{
|
else{
|
||||||
@ -88,8 +85,8 @@ class WorkerAutomation(val unit: MapUnit) {
|
|||||||
unit.movementAlgs().headTowards(tileToConstructRoadOn)
|
unit.movementAlgs().headTowards(tileToConstructRoadOn)
|
||||||
}
|
}
|
||||||
if(unit.currentMovement>0 && unit.currentTile==tileToConstructRoadOn
|
if(unit.currentMovement>0 && unit.currentTile==tileToConstructRoadOn
|
||||||
&& unit.currentTile.improvementInProgress!=targetRoadName)
|
&& unit.currentTile.improvementInProgress!=targetRoad.name)
|
||||||
tileToConstructRoadOn.startWorkingOnImprovement(GameBasics.TileImprovements[targetRoadName]!!,unit.civInfo)
|
tileToConstructRoadOn.startWorkingOnImprovement(targetRoad.improvement()!!,unit.civInfo)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package com.unciv.logic.civilization
|
|||||||
|
|
||||||
|
|
||||||
import com.badlogic.gdx.graphics.Color
|
import com.badlogic.gdx.graphics.Color
|
||||||
|
import com.unciv.logic.map.RoadStatus
|
||||||
import com.unciv.models.gamebasics.GameBasics
|
import com.unciv.models.gamebasics.GameBasics
|
||||||
import com.unciv.models.gamebasics.tech.Technology
|
import com.unciv.models.gamebasics.tech.Technology
|
||||||
import com.unciv.models.gamebasics.tr
|
import com.unciv.models.gamebasics.tr
|
||||||
@ -196,4 +197,13 @@ class TechManager {
|
|||||||
if(researchedTechUniques.contains("Enables embarked units to enter ocean tiles")) embarkedUnitsCanEnterOcean=true
|
if(researchedTechUniques.contains("Enables embarked units to enter ocean tiles")) embarkedUnitsCanEnterOcean=true
|
||||||
if(researchedTechUniques.contains("Improves movement speed on roads")) movementSpeedOnRoadsImproved = true
|
if(researchedTechUniques.contains("Improves movement speed on roads")) movementSpeedOnRoadsImproved = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getBestRoadAvailable(): RoadStatus {
|
||||||
|
if (!isResearched(RoadStatus.Road.improvement()!!.techRequired!!)) return RoadStatus.None
|
||||||
|
|
||||||
|
val techEnablingRailroad = RoadStatus.Railroad.improvement()!!.techRequired!!
|
||||||
|
val canBuildRailroad = isResearched(techEnablingRailroad)
|
||||||
|
|
||||||
|
return if (canBuildRailroad) RoadStatus.Railroad else RoadStatus.Road
|
||||||
|
}
|
||||||
}
|
}
|
@ -18,9 +18,10 @@ class BFS(val startingPoint: TileInfo, val predicate : (TileInfo) -> Boolean){
|
|||||||
nextStep()
|
nextStep()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun stepUntilDestination(destination: TileInfo){
|
fun stepUntilDestination(destination: TileInfo): BFS {
|
||||||
while(!tilesReached.containsKey(destination) && tilesToCheck.isNotEmpty())
|
while(!tilesReached.containsKey(destination) && tilesToCheck.isNotEmpty())
|
||||||
nextStep()
|
nextStep()
|
||||||
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun nextStep(){
|
fun nextStep(){
|
||||||
@ -39,8 +40,10 @@ class BFS(val startingPoint: TileInfo, val predicate : (TileInfo) -> Boolean){
|
|||||||
path.add(destination)
|
path.add(destination)
|
||||||
var currentNode = destination
|
var currentNode = destination
|
||||||
while(currentNode != startingPoint){
|
while(currentNode != startingPoint){
|
||||||
currentNode = tilesReached[currentNode]!!
|
tilesReached[currentNode]?.let {
|
||||||
path.add(currentNode)
|
currentNode = it
|
||||||
|
path.add(currentNode)
|
||||||
|
} ?: return ArrayList() // destination is not in our path
|
||||||
}
|
}
|
||||||
return path
|
return path
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,8 @@ import com.unciv.Constants
|
|||||||
import com.unciv.logic.automation.UnitAutomation
|
import com.unciv.logic.automation.UnitAutomation
|
||||||
import com.unciv.logic.automation.WorkerAutomation
|
import com.unciv.logic.automation.WorkerAutomation
|
||||||
import com.unciv.logic.civilization.CivilizationInfo
|
import com.unciv.logic.civilization.CivilizationInfo
|
||||||
|
import com.unciv.logic.map.action.MapUnitAction
|
||||||
|
import com.unciv.logic.map.action.StringAction
|
||||||
import com.unciv.models.gamebasics.GameBasics
|
import com.unciv.models.gamebasics.GameBasics
|
||||||
import com.unciv.models.gamebasics.tech.TechEra
|
import com.unciv.models.gamebasics.tech.TechEra
|
||||||
import com.unciv.models.gamebasics.tile.TerrainType
|
import com.unciv.models.gamebasics.tile.TerrainType
|
||||||
@ -16,6 +18,7 @@ import java.util.*
|
|||||||
import kotlin.collections.ArrayList
|
import kotlin.collections.ArrayList
|
||||||
|
|
||||||
class MapUnit {
|
class MapUnit {
|
||||||
|
|
||||||
@Transient lateinit var civInfo: CivilizationInfo
|
@Transient lateinit var civInfo: CivilizationInfo
|
||||||
@Transient lateinit var baseUnit: BaseUnit
|
@Transient lateinit var baseUnit: BaseUnit
|
||||||
@Transient internal lateinit var currentTile :TileInfo
|
@Transient internal lateinit var currentTile :TileInfo
|
||||||
@ -32,7 +35,15 @@ class MapUnit {
|
|||||||
lateinit var name: String
|
lateinit var name: String
|
||||||
var currentMovement: Float = 0f
|
var currentMovement: Float = 0f
|
||||||
var health:Int = 100
|
var health:Int = 100
|
||||||
var action: String? = null // work, automation, fortifying, I dunno what.
|
|
||||||
|
var mapUnitAction : MapUnitAction? = null
|
||||||
|
|
||||||
|
var action: String? // work, automation, fortifying, I dunno what.
|
||||||
|
// getter and setter for compatibility: make sure string-based actions still work
|
||||||
|
get() = (mapUnitAction as? StringAction)?.action ?: mapUnitAction?.let { "" } // null if no action is assigned.
|
||||||
|
set(value) { mapUnitAction = value?.let{ StringAction(this, value) } } // wrap traditional string-encoded actions into StringAction
|
||||||
|
|
||||||
|
|
||||||
var attacksThisTurn = 0
|
var attacksThisTurn = 0
|
||||||
var promotions = UnitPromotions()
|
var promotions = UnitPromotions()
|
||||||
var due: Boolean = true
|
var due: Boolean = true
|
||||||
@ -169,7 +180,8 @@ class MapUnit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Designates whether we can walk to the tile - without attacking
|
* Designates whether we can enter the tile - without attacking
|
||||||
|
* DOES NOT designate whether we can reach that tile in the current turn
|
||||||
*/
|
*/
|
||||||
fun canMoveTo(tile: TileInfo): Boolean {
|
fun canMoveTo(tile: TileInfo): Boolean {
|
||||||
if(!canPassThrough(tile)) return false
|
if(!canPassThrough(tile)) return false
|
||||||
@ -275,6 +287,7 @@ class MapUnit {
|
|||||||
//region state-changing functions
|
//region state-changing functions
|
||||||
fun setTransients(){
|
fun setTransients(){
|
||||||
promotions.unit=this
|
promotions.unit=this
|
||||||
|
mapUnitAction?.unit = this
|
||||||
baseUnit=GameBasics.Units[name]!!
|
baseUnit=GameBasics.Units[name]!!
|
||||||
updateUniques()
|
updateUniques()
|
||||||
}
|
}
|
||||||
@ -292,10 +305,13 @@ class MapUnit {
|
|||||||
val enemyUnitsInWalkingDistance = getDistanceToTiles().keys
|
val enemyUnitsInWalkingDistance = getDistanceToTiles().keys
|
||||||
.filter { it.militaryUnit!=null && civInfo.isAtWarWith(it.militaryUnit!!.civInfo)}
|
.filter { it.militaryUnit!=null && civInfo.isAtWarWith(it.militaryUnit!!.civInfo)}
|
||||||
if(enemyUnitsInWalkingDistance.isNotEmpty()) {
|
if(enemyUnitsInWalkingDistance.isNotEmpty()) {
|
||||||
if (action != null && action!!.startsWith("moveTo")) action=null
|
if (mapUnitAction?.shouldStopOnEnemyInSight()==true)
|
||||||
|
mapUnitAction=null
|
||||||
return // Don't you dare move.
|
return // Don't you dare move.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mapUnitAction?.doPreTurnAction()
|
||||||
|
|
||||||
if (action != null && action!!.startsWith("moveTo")) {
|
if (action != null && action!!.startsWith("moveTo")) {
|
||||||
val destination = action!!.replace("moveTo ", "").split(",").dropLastWhile { it.isEmpty() }.toTypedArray()
|
val destination = action!!.replace("moveTo ", "").split(",").dropLastWhile { it.isEmpty() }.toTypedArray()
|
||||||
val destinationVector = Vector2(Integer.parseInt(destination[0]).toFloat(), Integer.parseInt(destination[1]).toFloat())
|
val destinationVector = Vector2(Integer.parseInt(destination[0]).toFloat(), Integer.parseInt(destination[1]).toFloat())
|
||||||
@ -368,22 +384,19 @@ class MapUnit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return The tile that we reached this turn
|
|
||||||
*/
|
|
||||||
fun moveToTile(otherTile: TileInfo) {
|
fun moveToTile(otherTile: TileInfo) {
|
||||||
if(otherTile==getTile()) return // already here!
|
if(otherTile==getTile()) return // already here!
|
||||||
val distanceToTiles = getDistanceToTiles()
|
val distanceToTiles = getDistanceToTiles()
|
||||||
|
|
||||||
class YouCantGetThereFromHereException : Exception()
|
class YouCantGetThereFromHereException(msg: String) : Exception(msg)
|
||||||
if (!distanceToTiles.containsKey(otherTile))
|
if (!distanceToTiles.containsKey(otherTile))
|
||||||
|
throw YouCantGetThereFromHereException("$this can't get from ${currentTile.position} to ${otherTile.position}.")
|
||||||
|
|
||||||
throw YouCantGetThereFromHereException()
|
class CantEnterThisTileException(msg: String) : Exception(msg)
|
||||||
|
|
||||||
class CantEnterThisTileException : Exception()
|
|
||||||
if(!canMoveTo(otherTile))
|
if(!canMoveTo(otherTile))
|
||||||
throw CantEnterThisTileException()
|
throw CantEnterThisTileException("$this can't enter $otherTile")
|
||||||
if(otherTile.isCityCenter() && otherTile.getOwner()!=civInfo) throw Exception("This is an enemy city, you can't go here!")
|
if(otherTile.isCityCenter() && otherTile.getOwner()!=civInfo)
|
||||||
|
throw Exception("This is an enemy city, you can't go here!")
|
||||||
|
|
||||||
currentMovement -= distanceToTiles[otherTile]!!
|
currentMovement -= distanceToTiles[otherTile]!!
|
||||||
if (currentMovement < 0.1) currentMovement = 0f // silly floats which are "almost zero"
|
if (currentMovement < 0.1) currentMovement = 0f // silly floats which are "almost zero"
|
||||||
|
@ -1,7 +1,18 @@
|
|||||||
package com.unciv.logic.map
|
package com.unciv.logic.map
|
||||||
|
|
||||||
|
import com.unciv.models.gamebasics.GameBasics
|
||||||
|
|
||||||
|
/**
|
||||||
|
* You can use RoadStatus.name to identify [Road] and [Railroad]
|
||||||
|
* in string-based identification, as done in [improvement].
|
||||||
|
*/
|
||||||
enum class RoadStatus {
|
enum class RoadStatus {
|
||||||
|
|
||||||
None,
|
None,
|
||||||
Road,
|
Road,
|
||||||
Railroad
|
Railroad;
|
||||||
|
|
||||||
|
/** returns null for [None] */
|
||||||
|
fun improvement() = GameBasics.TileImprovements[this.name]
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -137,7 +137,7 @@ class UnitMovementAlgorithms(val unit:MapUnit) {
|
|||||||
*/
|
*/
|
||||||
fun headTowards(destination: TileInfo): TileInfo {
|
fun headTowards(destination: TileInfo): TileInfo {
|
||||||
val currentTile = unit.getTile()
|
val currentTile = unit.getTile()
|
||||||
if(currentTile==destination) return currentTile
|
if (currentTile == destination) return currentTile
|
||||||
|
|
||||||
val distanceToTiles = unit.getDistanceToTiles()
|
val distanceToTiles = unit.getDistanceToTiles()
|
||||||
|
|
||||||
@ -152,7 +152,7 @@ class UnitMovementAlgorithms(val unit:MapUnit) {
|
|||||||
return currentTile
|
return currentTile
|
||||||
|
|
||||||
val reachableDestinationNeighbors = destinationNeighbors
|
val reachableDestinationNeighbors = destinationNeighbors
|
||||||
.filter { distanceToTiles.containsKey(it) && unit.canMoveTo(it)}
|
.filter { distanceToTiles.containsKey(it) && unit.canMoveTo(it) }
|
||||||
if (reachableDestinationNeighbors.isEmpty()) // We can't get closer...
|
if (reachableDestinationNeighbors.isEmpty()) // We can't get closer...
|
||||||
return currentTile
|
return currentTile
|
||||||
|
|
||||||
@ -160,8 +160,8 @@ class UnitMovementAlgorithms(val unit:MapUnit) {
|
|||||||
}
|
}
|
||||||
} else { // If the tile is far away, we need to build a path how to get there, and then take the first step
|
} 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 = getShortestPath(destination)
|
val path = getShortestPath(destination)
|
||||||
class UnreachableDestinationException:Exception()
|
class UnreachableDestinationException : Exception()
|
||||||
if(path.isEmpty()) throw UnreachableDestinationException()
|
if (path.isEmpty()) throw UnreachableDestinationException()
|
||||||
destinationTileThisTurn = path.first()
|
destinationTileThisTurn = path.first()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
103
core/src/com/unciv/logic/map/action/BuildLongRoadAction.kt
Normal file
103
core/src/com/unciv/logic/map/action/BuildLongRoadAction.kt
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
package com.unciv.logic.map.action
|
||||||
|
|
||||||
|
import com.badlogic.gdx.graphics.Color
|
||||||
|
import com.unciv.logic.map.BFS
|
||||||
|
import com.unciv.logic.map.MapUnit
|
||||||
|
import com.unciv.logic.map.RoadStatus
|
||||||
|
import com.unciv.logic.map.TileInfo
|
||||||
|
|
||||||
|
class BuildLongRoadAction(
|
||||||
|
mapUnit: MapUnit = MapUnit(),
|
||||||
|
val target: TileInfo = TileInfo()
|
||||||
|
) : MapUnitAction(mapUnit) {
|
||||||
|
|
||||||
|
override fun name(): String = "Build Long Road"
|
||||||
|
|
||||||
|
override fun shouldStopOnEnemyInSight(): Boolean = true
|
||||||
|
|
||||||
|
override fun isAvailable(): Boolean
|
||||||
|
= unit.hasUnique("Can build improvements on tiles")
|
||||||
|
&& getPath(target).isNotEmpty()
|
||||||
|
&& unit.civInfo.tech.getBestRoadAvailable() != RoadStatus.None
|
||||||
|
|
||||||
|
override fun doPreTurnAction() {
|
||||||
|
|
||||||
|
// we're working!
|
||||||
|
if (unit.currentTile.improvementInProgress != null)
|
||||||
|
return
|
||||||
|
|
||||||
|
if (startWorkingOnRoad())
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
// we reached our target? And road is finished?
|
||||||
|
if (unit.currentTile.position == target.position
|
||||||
|
&& isRoadFinished(unit.currentTile)) {
|
||||||
|
unit.action = null
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// move one step forward - and start building
|
||||||
|
if (stepForward(target)) {
|
||||||
|
startWorkingOnRoad()
|
||||||
|
} else if (unit.currentMovement > 1f) {
|
||||||
|
unit.civInfo.addNotification("[${unit.name}] canceled building road: can't move forward.", unit.currentTile.position, Color.GRAY)
|
||||||
|
unit.action = null
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// because the unit is building a road, we need to use a shortest path that is
|
||||||
|
// independent of movement costs, but should respect impassable terrain like water and enemy territory
|
||||||
|
private fun stepForward(destination: TileInfo): Boolean {
|
||||||
|
var success = false
|
||||||
|
val tilesUnitCanCurrentlyReach = unit.getDistanceToTiles().keys
|
||||||
|
for (step in getPath(destination).drop(1)) {
|
||||||
|
if(step !in tilesUnitCanCurrentlyReach) return false // we're out of tiles in reachable distance, no need to check any further
|
||||||
|
|
||||||
|
if (unit.currentMovement > 0f) {
|
||||||
|
if(unit.canMoveTo(step)) {
|
||||||
|
unit.moveToTile(step)
|
||||||
|
success = true
|
||||||
|
// if there is a road already, take multiple steps, otherwise this is where we're going to build a road
|
||||||
|
if (!isRoadFinished(step)) return true
|
||||||
|
}
|
||||||
|
else if(!isRoadFinished(step)){
|
||||||
|
unit.civInfo.addNotification("[${unit.name}] skipped building road. It can't move here.", step.position, Color.GRAY)
|
||||||
|
}
|
||||||
|
// worker moves on even if the current step is blocked
|
||||||
|
} else break
|
||||||
|
}
|
||||||
|
return success
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isRoadFinished(tile: TileInfo): Boolean {
|
||||||
|
return tile.roadStatus >= unit.civInfo.tech.getBestRoadAvailable()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getPath(destination: TileInfo): List<TileInfo> {
|
||||||
|
// BFS is not very efficient
|
||||||
|
return BFS(unit.currentTile) { isRoadableTile(it) }
|
||||||
|
.stepUntilDestination(destination)
|
||||||
|
.getPathTo(destination).reversed()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isRoadableTile(it: TileInfo) = it.isLand && unit.canPassThrough(it)
|
||||||
|
|
||||||
|
private fun startWorkingOnRoad(): Boolean {
|
||||||
|
val tile = unit.currentTile
|
||||||
|
if (unit.currentMovement > 0 && isRoadableTile(tile)) {
|
||||||
|
val roadToBuild = unit.civInfo.tech.getBestRoadAvailable()
|
||||||
|
roadToBuild.improvement()?.let { improvement ->
|
||||||
|
if (tile.roadStatus < roadToBuild && tile.improvementInProgress != improvement.name) {
|
||||||
|
tile.startWorkingOnImprovement(improvement, unit.civInfo)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
15
core/src/com/unciv/logic/map/action/MapUnitAction.kt
Normal file
15
core/src/com/unciv/logic/map/action/MapUnitAction.kt
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
package com.unciv.logic.map.action
|
||||||
|
|
||||||
|
import com.unciv.logic.map.MapUnit
|
||||||
|
|
||||||
|
open class MapUnitAction(
|
||||||
|
@Transient var unit: MapUnit = MapUnit()
|
||||||
|
) {
|
||||||
|
open fun name(): String = ""
|
||||||
|
/** return true if this action is possible in the given conditions */
|
||||||
|
open fun isAvailable(): Boolean = true
|
||||||
|
open fun doPreTurnAction() {}
|
||||||
|
open fun shouldStopOnEnemyInSight(): Boolean = false
|
||||||
|
}
|
||||||
|
|
||||||
|
|
27
core/src/com/unciv/logic/map/action/StringAction.kt
Normal file
27
core/src/com/unciv/logic/map/action/StringAction.kt
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
package com.unciv.logic.map.action
|
||||||
|
|
||||||
|
import com.unciv.logic.map.MapUnit
|
||||||
|
|
||||||
|
/**
|
||||||
|
* this class represents all actions that are identified by string only.
|
||||||
|
* this is the traditional way of handling actions in UnCiv: by coding relevant information
|
||||||
|
* into a string. This class is here to maintain compatibility to that method, preventing from a huge
|
||||||
|
* refactoring going on here.
|
||||||
|
*/
|
||||||
|
class StringAction(
|
||||||
|
unit: MapUnit = MapUnit(),
|
||||||
|
val action: String = "" // traditional string-encoded action like "moveTo x,y"
|
||||||
|
) : MapUnitAction(unit) {
|
||||||
|
|
||||||
|
override fun shouldStopOnEnemyInSight(): Boolean = action.startsWith("moveTo")
|
||||||
|
|
||||||
|
override fun name(): String {
|
||||||
|
return when {
|
||||||
|
// translate string-encoded actions to user-readable names
|
||||||
|
action.startsWith("moveTo") -> "Moving"
|
||||||
|
else -> action
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -103,7 +103,7 @@ class EmpireOverviewScreen : CameraStageBaseScreen(){
|
|||||||
generalTable.add(createOffersTable(otherCiv, trade.theirOffers, trade.ourOffers.size))
|
generalTable.add(createOffersTable(otherCiv, trade.theirOffers, trade.ourOffers.size))
|
||||||
return generalTable
|
return generalTable
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createOffersTable(civ: CivilizationInfo, offersList: TradeOffersList, numberOfOtherSidesOffers: Int): Table {
|
private fun createOffersTable(civ: CivilizationInfo, offersList: TradeOffersList, numberOfOtherSidesOffers: Int): Table {
|
||||||
val table = Table()
|
val table = Table()
|
||||||
table.defaults().pad(10f)
|
table.defaults().pad(10f)
|
||||||
@ -259,6 +259,7 @@ class EmpireOverviewScreen : CameraStageBaseScreen(){
|
|||||||
fun getUnitTable(): Table {
|
fun getUnitTable(): Table {
|
||||||
val table=Table(skin).apply { defaults().pad(5f) }
|
val table=Table(skin).apply { defaults().pad(5f) }
|
||||||
table.add("Name".tr())
|
table.add("Name".tr())
|
||||||
|
table.add("Action".tr())
|
||||||
table.add("Strength".tr())
|
table.add("Strength".tr())
|
||||||
table.add("Ranged strength".tr())
|
table.add("Ranged strength".tr())
|
||||||
table.add("Movement".tr())
|
table.add("Movement".tr())
|
||||||
@ -274,6 +275,8 @@ class EmpireOverviewScreen : CameraStageBaseScreen(){
|
|||||||
UnCivGame.Current.worldScreen.tileMapHolder.setCenterPosition(unit.currentTile.position)
|
UnCivGame.Current.worldScreen.tileMapHolder.setCenterPosition(unit.currentTile.position)
|
||||||
}
|
}
|
||||||
table.add(button).left()
|
table.add(button).left()
|
||||||
|
val mapUnitAction = unit.mapUnitAction
|
||||||
|
if (mapUnitAction != null) table.add(mapUnitAction.name().tr()) else table.add()
|
||||||
if(baseUnit.strength>0) table.add(baseUnit.strength.toString()) else table.add()
|
if(baseUnit.strength>0) table.add(baseUnit.strength.toString()) else table.add()
|
||||||
if(baseUnit.rangedStrength>0) table.add(baseUnit.rangedStrength.toString()) else table.add()
|
if(baseUnit.rangedStrength>0) table.add(baseUnit.rangedStrength.toString()) else table.add()
|
||||||
table.add(DecimalFormat("0.#").format(unit.currentMovement)+"/"+unit.getMaxMovement())
|
table.add(DecimalFormat("0.#").format(unit.currentMovement)+"/"+unit.getMaxMovement())
|
||||||
|
@ -30,7 +30,7 @@ class GreatPersonPickerScreen : PickerScreen() {
|
|||||||
pick("Get " +unit.name)
|
pick("Get " +unit.name)
|
||||||
descriptionLabel.setText(unit.uniques.joinToString())
|
descriptionLabel.setText(unit.uniques.joinToString())
|
||||||
}
|
}
|
||||||
topTable.add(button).pad(10f)
|
topTable.add(button).pad(10f).row()
|
||||||
}
|
}
|
||||||
|
|
||||||
rightSideButton.onClick("choir") {
|
rightSideButton.onClick("choir") {
|
||||||
|
@ -20,6 +20,7 @@ import com.unciv.logic.map.TileMap
|
|||||||
import com.unciv.models.gamebasics.unit.UnitType
|
import com.unciv.models.gamebasics.unit.UnitType
|
||||||
import com.unciv.ui.tilegroups.WorldTileGroup
|
import com.unciv.ui.tilegroups.WorldTileGroup
|
||||||
import com.unciv.ui.utils.*
|
import com.unciv.ui.utils.*
|
||||||
|
import com.unciv.ui.worldscreen.unit.UnitContextMenu
|
||||||
import kotlin.concurrent.thread
|
import kotlin.concurrent.thread
|
||||||
|
|
||||||
class TileMapHolder(internal val worldScreen: WorldScreen, internal val tileMap: TileMap) : ScrollPane(null) {
|
class TileMapHolder(internal val worldScreen: WorldScreen, internal val tileMap: TileMap) : ScrollPane(null) {
|
||||||
@ -41,7 +42,15 @@ class TileMapHolder(internal val worldScreen: WorldScreen, internal val tileMap:
|
|||||||
val allTiles = TileGroupMap(daTileGroups,worldScreen.stage.width)
|
val allTiles = TileGroupMap(daTileGroups,worldScreen.stage.width)
|
||||||
|
|
||||||
for(tileGroup in tileGroups.values){
|
for(tileGroup in tileGroups.values){
|
||||||
tileGroup.onClick{ onTileClicked(tileGroup.tileInfo)}
|
tileGroup.addListener (object: ActorGestureListener() {
|
||||||
|
override fun tap(event: InputEvent?, x: Float, y: Float, count: Int, button: Int) {
|
||||||
|
onTileClicked(tileGroup.tileInfo)
|
||||||
|
}
|
||||||
|
override fun longPress(actor: Actor?, x: Float, y: Float): Boolean {
|
||||||
|
return onTileLongClicked(tileGroup.tileInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
actor = allTiles
|
actor = allTiles
|
||||||
@ -77,7 +86,7 @@ class TileMapHolder(internal val worldScreen: WorldScreen, internal val tileMap:
|
|||||||
|
|
||||||
private fun onTileClicked(tileInfo: TileInfo) {
|
private fun onTileClicked(tileInfo: TileInfo) {
|
||||||
worldScreen.displayTutorials("TileClicked")
|
worldScreen.displayTutorials("TileClicked")
|
||||||
if (unitActionOverlay != null) unitActionOverlay!!.remove()
|
unitActionOverlay?.remove()
|
||||||
selectedTile = tileInfo
|
selectedTile = tileInfo
|
||||||
|
|
||||||
val selectedUnit = worldScreen.bottomBar.unitTable.selectedUnit
|
val selectedUnit = worldScreen.bottomBar.unitTable.selectedUnit
|
||||||
@ -121,7 +130,7 @@ class TileMapHolder(internal val worldScreen: WorldScreen, internal val tileMap:
|
|||||||
} else {
|
} else {
|
||||||
// add "move to" button
|
// add "move to" button
|
||||||
val moveHereButtonDto = MoveHereButtonDto(selectedUnit, tileInfo, turnsToGetThere)
|
val moveHereButtonDto = MoveHereButtonDto(selectedUnit, tileInfo, turnsToGetThere)
|
||||||
addMoveHereButtonToTile(moveHereButtonDto, tileGroups[moveHereButtonDto.tileInfo]!!)
|
addMoveHereButtonToTile(moveHereButtonDto)
|
||||||
}
|
}
|
||||||
worldScreen.shouldUpdate = true
|
worldScreen.shouldUpdate = true
|
||||||
}
|
}
|
||||||
@ -130,7 +139,7 @@ class TileMapHolder(internal val worldScreen: WorldScreen, internal val tileMap:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun addMoveHereButtonToTile(dto: MoveHereButtonDto, tileGroup: WorldTileGroup) {
|
private fun addMoveHereButtonToTile(dto: MoveHereButtonDto) {
|
||||||
val size = 60f
|
val size = 60f
|
||||||
val moveHereButton = Group().apply { width = size;height = size; }
|
val moveHereButton = Group().apply { width = size;height = size; }
|
||||||
moveHereButton.addActor(ImageGetter.getCircle().apply { width = size; height = size })
|
moveHereButton.addActor(ImageGetter.getCircle().apply { width = size; height = size })
|
||||||
@ -147,48 +156,45 @@ class TileMapHolder(internal val worldScreen: WorldScreen, internal val tileMap:
|
|||||||
moveHereButton.addActor(unitIcon)
|
moveHereButton.addActor(unitIcon)
|
||||||
|
|
||||||
if (dto.unit.currentMovement > 0)
|
if (dto.unit.currentMovement > 0)
|
||||||
moveHereButton.onClick(""){onMoveButtonClick(dto)}
|
moveHereButton.onClick(""){
|
||||||
|
UnitContextMenu(this, dto.unit, dto.tileInfo).onMoveButtonClick()
|
||||||
else moveHereButton.color.a = 0.5f
|
|
||||||
addOverlayOnTileGroup(tileGroup, moveHereButton)
|
|
||||||
moveHereButton.y += tileGroup.height
|
|
||||||
unitActionOverlay = moveHereButton
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun onMoveButtonClick(dto: MoveHereButtonDto) {
|
|
||||||
// this can take a long time, because of the unit-to-tile calculation needed, so we put it in a different thread
|
|
||||||
thread {
|
|
||||||
if (dto.unit.movementAlgs().canReach(dto.tileInfo)) {
|
|
||||||
try {
|
|
||||||
// Because this is darned concurrent (as it MUST be to avoid ANRs),
|
|
||||||
// there are edge cases where the canReach is true,
|
|
||||||
// but until it reaches the headTowards the board has changed and so the headTowards fails.
|
|
||||||
// I can't think of any way to avoid this,
|
|
||||||
// but it's so rare and edge-case-y that ignoring its failure is actually acceptable, hence the empty catch
|
|
||||||
dto.unit.movementAlgs().headTowards(dto.tileInfo)
|
|
||||||
Sounds.play("whoosh")
|
|
||||||
if (dto.unit.currentTile != dto.tileInfo)
|
|
||||||
dto.unit.action = "moveTo " + dto.tileInfo.position.x.toInt() + "," + dto.tileInfo.position.y.toInt()
|
|
||||||
if(dto.unit.currentMovement>0){
|
|
||||||
worldScreen.bottomBar.unitTable.selectedUnit=dto.unit
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// we don't update it directly because we're on a different thread; instead, we tell it to update itself
|
else moveHereButton.color.a = 0.5f
|
||||||
worldScreen.shouldUpdate = true
|
addOverlayOnTileGroup(dto.tileInfo, moveHereButton)
|
||||||
|
|
||||||
removeUnitActionOverlay=true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addOverlayOnTileGroup(group:WorldTileGroup, actor: Actor) {
|
|
||||||
|
|
||||||
|
fun onTileLongClicked(tileInfo: TileInfo): Boolean {
|
||||||
|
|
||||||
|
unitActionOverlay?.remove()
|
||||||
|
selectedTile = tileInfo
|
||||||
|
val selectedUnit = worldScreen.bottomBar.unitTable.selectedUnit
|
||||||
|
worldScreen.bottomBar.unitTable.tileSelected(tileInfo)
|
||||||
|
worldScreen.shouldUpdate = true
|
||||||
|
|
||||||
|
if (selectedUnit != null) {
|
||||||
|
addOverlayOnTileGroup(tileInfo, UnitContextMenu(this, selectedUnit, tileInfo))
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addOverlayOnTileGroup(tileInfo: TileInfo, actor: Actor) {
|
||||||
|
|
||||||
|
val group = tileGroups[tileInfo]!!
|
||||||
|
|
||||||
actor.center(group)
|
actor.center(group)
|
||||||
actor.x+=group.x
|
actor.x+=group.x
|
||||||
actor.y+=group.y
|
actor.y+=group.y
|
||||||
group.parent.addActor(actor)
|
group.parent.addActor(actor)
|
||||||
actor.toFront()
|
actor.toFront()
|
||||||
|
|
||||||
|
actor.y += actor.height
|
||||||
|
unitActionOverlay = actor
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun updateTiles(civInfo: CivilizationInfo) {
|
internal fun updateTiles(civInfo: CivilizationInfo) {
|
||||||
@ -216,20 +222,23 @@ class TileMapHolder(internal val worldScreen: WorldScreen, internal val tileMap:
|
|||||||
tileGroup.showCircle(Color.RED) // Display ALL viewable enemies with a red circle so that users don't need to go "hunting" for enemy units
|
tileGroup.showCircle(Color.RED) // Display ALL viewable enemies with a red circle so that users don't need to go "hunting" for enemy units
|
||||||
}
|
}
|
||||||
|
|
||||||
if (worldScreen.bottomBar.unitTable.selectedCity!=null){
|
val unitTable = worldScreen.bottomBar.unitTable
|
||||||
val city = worldScreen.bottomBar.unitTable.selectedCity!!
|
when {
|
||||||
updateTilegroupsForSelectedCity(city, playerViewableTilePositions)
|
unitTable.selectedCity!=null -> {
|
||||||
} else if(worldScreen.bottomBar.unitTable.selectedUnit!=null){
|
val city = unitTable.selectedCity!!
|
||||||
val unit = worldScreen.bottomBar.unitTable.selectedUnit!!
|
updateTilegroupsForSelectedCity(city, playerViewableTilePositions)
|
||||||
updateTilegroupsForSelectedUnit(unit, playerViewableTilePositions)
|
}
|
||||||
}
|
unitTable.selectedUnit!=null -> {
|
||||||
else if(unitActionOverlay!=null){
|
val unit = unitTable.selectedUnit!!
|
||||||
unitActionOverlay!!.remove()
|
updateTilegroupsForSelectedUnit(unit, playerViewableTilePositions)
|
||||||
unitActionOverlay=null
|
}
|
||||||
|
unitActionOverlay!=null -> {
|
||||||
|
unitActionOverlay!!.remove()
|
||||||
|
unitActionOverlay=null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(selectedTile!=null)
|
tileGroups[selectedTile]?.showCircle(Color.WHITE)
|
||||||
tileGroups[selectedTile!!]!!.showCircle(Color.WHITE)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateTilegroupsForSelectedUnit(unit: MapUnit, playerViewableTilePositions: HashSet<Vector2>) {
|
private fun updateTilegroupsForSelectedUnit(unit: MapUnit, playerViewableTilePositions: HashSet<Vector2>) {
|
||||||
|
@ -246,8 +246,6 @@ class WorldScreen : CameraStageBaseScreen() {
|
|||||||
return@onClick
|
return@onClick
|
||||||
}
|
}
|
||||||
|
|
||||||
bottomBar.unitTable.currentlyExecutingAction = null
|
|
||||||
|
|
||||||
Gdx.input.inputProcessor = null // remove input processing - nothing will be clicked!
|
Gdx.input.inputProcessor = null // remove input processing - nothing will be clicked!
|
||||||
nextTurnButton.disable()
|
nextTurnButton.disable()
|
||||||
nextTurnButton.setText("Working...".tr())
|
nextTurnButton.setText("Working...".tr())
|
||||||
|
@ -34,7 +34,6 @@ class UnitActions {
|
|||||||
if(unit.action!=null && unit.action!!.startsWith("moveTo")) {
|
if(unit.action!=null && unit.action!!.startsWith("moveTo")) {
|
||||||
actionList +=
|
actionList +=
|
||||||
UnitAction("Stop movement", true) {
|
UnitAction("Stop movement", true) {
|
||||||
unitTable.currentlyExecutingAction = null
|
|
||||||
unit.action = null
|
unit.action = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -146,7 +145,6 @@ class UnitActions {
|
|||||||
|
|
||||||
unit.civInfo.addCity(tile.position)
|
unit.civInfo.addCity(tile.position)
|
||||||
tile.improvement = null
|
tile.improvement = null
|
||||||
unitTable.currentlyExecutingAction = null // In case the settler was in the middle of doing something and we then founded a city with it
|
|
||||||
unit.destroy()
|
unit.destroy()
|
||||||
}.sound("chimes")
|
}.sound("chimes")
|
||||||
}
|
}
|
||||||
|
85
core/src/com/unciv/ui/worldscreen/unit/UnitContextMenu.kt
Normal file
85
core/src/com/unciv/ui/worldscreen/unit/UnitContextMenu.kt
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
package com.unciv.ui.worldscreen.unit
|
||||||
|
|
||||||
|
import com.badlogic.gdx.scenes.scene2d.Actor
|
||||||
|
import com.badlogic.gdx.scenes.scene2d.ui.Button
|
||||||
|
import com.badlogic.gdx.scenes.scene2d.ui.VerticalGroup
|
||||||
|
import com.unciv.logic.map.MapUnit
|
||||||
|
import com.unciv.logic.map.TileInfo
|
||||||
|
import com.unciv.ui.utils.CameraStageBaseScreen
|
||||||
|
import com.unciv.ui.utils.ImageGetter
|
||||||
|
import com.unciv.ui.utils.Sounds
|
||||||
|
import com.unciv.ui.utils.onClick
|
||||||
|
import com.unciv.ui.worldscreen.TileMapHolder
|
||||||
|
import com.unciv.logic.map.action.BuildLongRoadAction
|
||||||
|
import com.unciv.logic.map.action.MapUnitAction
|
||||||
|
import kotlin.concurrent.thread
|
||||||
|
|
||||||
|
class UnitContextMenu(val tileMapHolder: TileMapHolder, val selectedUnit: MapUnit, val targetTile: TileInfo) : VerticalGroup() {
|
||||||
|
|
||||||
|
init {
|
||||||
|
|
||||||
|
space(10f)
|
||||||
|
|
||||||
|
addButton(ImageGetter.getStatIcon("Movement"), "Move unit") {
|
||||||
|
onMoveButtonClick()
|
||||||
|
}
|
||||||
|
|
||||||
|
addButton(
|
||||||
|
ImageGetter.getImprovementIcon("Road"),
|
||||||
|
"Construct road",
|
||||||
|
BuildLongRoadAction(selectedUnit, targetTile)
|
||||||
|
)
|
||||||
|
|
||||||
|
pack()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addButton(icon: Actor, label: String, action: MapUnitAction) {
|
||||||
|
if (action.isAvailable()) {
|
||||||
|
addButton(icon, label) {
|
||||||
|
selectedUnit.mapUnitAction = action
|
||||||
|
selectedUnit.mapUnitAction?.doPreTurnAction()
|
||||||
|
tileMapHolder.removeUnitActionOverlay = true
|
||||||
|
tileMapHolder.worldScreen.shouldUpdate = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addButton(icon: Actor, label: String, action: () -> Unit) {
|
||||||
|
val skin = CameraStageBaseScreen.skin
|
||||||
|
val button = Button(skin)
|
||||||
|
button.add(icon).size(20f).padRight(10f)
|
||||||
|
button.add(label)
|
||||||
|
addActor(button)
|
||||||
|
button.onClick { action() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onMoveButtonClick() {
|
||||||
|
// this can take a long time, because of the unit-to-tile calculation needed, so we put it in a different thread
|
||||||
|
thread {
|
||||||
|
if (selectedUnit.movementAlgs().canReach(targetTile)) {
|
||||||
|
try {
|
||||||
|
// Because this is darned concurrent (as it MUST be to avoid ANRs),
|
||||||
|
// there are edge cases where the canReach is true,
|
||||||
|
// but until it reaches the headTowards the board has changed and so the headTowards fails.
|
||||||
|
// I can't think of any way to avoid this,
|
||||||
|
// but it's so rare and edge-case-y that ignoring its failure is actually acceptable, hence the empty catch
|
||||||
|
selectedUnit.movementAlgs().headTowards(targetTile)
|
||||||
|
Sounds.play("whoosh")
|
||||||
|
if (selectedUnit.currentTile != targetTile)
|
||||||
|
selectedUnit.action = "moveTo " + targetTile.position.x.toInt() + "," + targetTile.position.y.toInt()
|
||||||
|
if(selectedUnit.currentMovement>0){
|
||||||
|
tileMapHolder.worldScreen.bottomBar.unitTable.selectedUnit=selectedUnit
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// we don't update it directly because we're on a different thread; instead, we tell it to update itself
|
||||||
|
tileMapHolder.worldScreen.shouldUpdate = true
|
||||||
|
|
||||||
|
tileMapHolder.removeUnitActionOverlay=true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -22,8 +22,6 @@ class UnitTable(val worldScreen: WorldScreen) : Table(){
|
|||||||
private val unitDescriptionTable = Table(CameraStageBaseScreen.skin)
|
private val unitDescriptionTable = Table(CameraStageBaseScreen.skin)
|
||||||
var selectedUnit : MapUnit? = null
|
var selectedUnit : MapUnit? = null
|
||||||
var selectedCity : CityInfo? = null
|
var selectedCity : CityInfo? = null
|
||||||
var currentlyExecutingAction : String? = null
|
|
||||||
var lastSelectedCityButton : Boolean = false
|
|
||||||
val deselectUnitButton = Table()
|
val deselectUnitButton = Table()
|
||||||
val helpUnitButton = Table()
|
val helpUnitButton = Table()
|
||||||
|
|
||||||
@ -88,12 +86,10 @@ class UnitTable(val worldScreen: WorldScreen) : Table(){
|
|||||||
if (selectedUnit!!.civInfo != worldScreen.currentPlayerCiv) { // The unit that was selected, was captured. It exists but is no longer ours.
|
if (selectedUnit!!.civInfo != worldScreen.currentPlayerCiv) { // The unit that was selected, was captured. It exists but is no longer ours.
|
||||||
selectedUnit = null
|
selectedUnit = null
|
||||||
selectedCity = null
|
selectedCity = null
|
||||||
currentlyExecutingAction = null
|
|
||||||
selectedUnitHasChanged = true
|
selectedUnitHasChanged = true
|
||||||
} else if (selectedUnit!! !in selectedUnit!!.getTile().getUnits()) { // The unit that was there no longer exists}
|
} else if (selectedUnit!! !in selectedUnit!!.getTile().getUnits()) { // The unit that was there no longer exists}
|
||||||
selectedUnit = null
|
selectedUnit = null
|
||||||
selectedCity = null
|
selectedCity = null
|
||||||
currentlyExecutingAction = null
|
|
||||||
selectedUnitHasChanged = true
|
selectedUnitHasChanged = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -190,20 +186,7 @@ class UnitTable(val worldScreen: WorldScreen) : Table(){
|
|||||||
fun tileSelected(selectedTile: TileInfo) {
|
fun tileSelected(selectedTile: TileInfo) {
|
||||||
|
|
||||||
val previouslySelectedUnit = selectedUnit
|
val previouslySelectedUnit = selectedUnit
|
||||||
if(currentlyExecutingAction=="moveTo"){
|
if(selectedTile.militaryUnit!=null && selectedTile.militaryUnit!!.civInfo == worldScreen.currentPlayerCiv
|
||||||
if(selectedUnit!!.movementAlgs()
|
|
||||||
.getShortestPath(selectedTile).isEmpty())
|
|
||||||
return // can't reach there with the selected unit, watcha want me to do?
|
|
||||||
|
|
||||||
val reachedTile = selectedUnit!!.movementAlgs().headTowards(selectedTile)
|
|
||||||
|
|
||||||
selectedUnit!!.action=null // Disable any prior action (automation, fortification...)
|
|
||||||
if(reachedTile!=selectedTile) // Didn't get all the way there
|
|
||||||
selectedUnit!!.action = "moveTo " + selectedTile.position.x.toInt() + "," + selectedTile.position.y.toInt()
|
|
||||||
currentlyExecutingAction = null
|
|
||||||
}
|
|
||||||
|
|
||||||
else if(selectedTile.militaryUnit!=null && selectedTile.militaryUnit!!.civInfo == worldScreen.currentPlayerCiv
|
|
||||||
&& selectedUnit!=selectedTile.militaryUnit
|
&& selectedUnit!=selectedTile.militaryUnit
|
||||||
&& (selectedTile.civilianUnit==null || selectedUnit!=selectedTile.civilianUnit)){
|
&& (selectedTile.civilianUnit==null || selectedUnit!=selectedTile.civilianUnit)){
|
||||||
selectedUnit = selectedTile.militaryUnit
|
selectedUnit = selectedTile.militaryUnit
|
||||||
|
@ -17,7 +17,7 @@ class DesktopLauncher {
|
|||||||
// This is so they don't look all pixelated
|
// This is so they don't look all pixelated
|
||||||
settings.filterMag = Texture.TextureFilter.MipMapLinearLinear;
|
settings.filterMag = Texture.TextureFilter.MipMapLinearLinear;
|
||||||
settings.filterMin = Texture.TextureFilter.MipMapLinearLinear;
|
settings.filterMin = Texture.TextureFilter.MipMapLinearLinear;
|
||||||
TexturePacker.process(settings, "../images", ".", "game");
|
TexturePacker.process(settings, "../Images", ".", "game");
|
||||||
|
|
||||||
LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();
|
LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();
|
||||||
new LwjglApplication(new UnCivGame("Desktop"), config);
|
new LwjglApplication(new UnCivGame("Desktop"), config);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user