Added GetTile function to MapUnit, which simplifies and normalizes a lot of the unit logic

Battle simulation and actual battle work as expected!
This commit is contained in:
Yair Morgenstern 2018-04-02 15:16:28 +03:00
parent bd1a191b15
commit 5d00adb7fe
16 changed files with 291 additions and 134 deletions

View file

@ -3,13 +3,15 @@
name:"Worker",
description: "Can build improvements on tiles",
movement:2,
unitType:"Civilian",
hurryCostModifier:20,
cost:60
cost:70
},
{
name:"Settler",
description: "Founds a new city",
movement:2,
unitType:"Civilian",
cost:106,
hurryCostModifier:20
},
@ -17,30 +19,43 @@
name:"Scout",
description: "Has no abilites, can only explore",
unbuildable:true,
unitType:"Melee",
movement:2
},
{
name:"Warrior",
description: "A basic fighting unit",
unitType:"Melee",
movement:2,
cost: 40,
hurryCostModifier:20
},
{
name:"Great Artist",
description: "Can start an 8-turn golden age or construcct a landmark (+5 culture)",
unbuildable:true,
unitType:"Civilian",
movement:2
},
{
name:"Great Scientist",
description: "Can discover a technology, or construct an academy (+4 science(",
unbuildable:true,
unitType:"Civilian",
movement:2
},
{
name:"Great Merchant",
description: "Can undertake a trade mission, giving a large sum of gold, or construct a ?",
unbuildable:true,
unitType:"Civilian",
movement:2
},
{
name:"Great Engineer",
description: "Can speed up construction of a wonder, or construct a refinery, giving +? production?",
unbuildable:true,
unitType:"Civilian",
movement:2
},

View file

@ -1,6 +1,7 @@
package com.unciv.logic
import com.unciv.logic.map.MapUnit
import com.unciv.logic.map.UnitType
/**
* Created by LENOVO on 3/26/2018.
@ -8,6 +9,10 @@ import com.unciv.logic.map.MapUnit
class Battle(){
fun calculateDamage(attacker:MapUnit, defender:MapUnit): Int {
return (attacker.strength*attacker.health*5) / (defender.strength*defender.health)
val attackerStrength =
if (attacker.getBaseUnit().unitType ==UnitType.Ranged)
attacker.getBaseUnit().rangedStrength
else attacker.getBaseUnit().strength
return (attackerStrength*attacker.health*50) / (defender.getBaseUnit().strength*defender.health)
}
}

View file

@ -25,7 +25,7 @@ class GameInfo {
for (civInfo in civilizations) civInfo.nextTurn()
for (tile in tileMap.values.filter { it.unit != null })
for (tile in tileMap.values)
tile.nextTurn()
// We need to update the stats after ALL the cities are done updating because

View file

@ -4,6 +4,7 @@ import com.badlogic.gdx.math.Vector2
import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.models.gamebasics.GameBasics
import com.unciv.models.gamebasics.TileImprovement
import com.unciv.models.gamebasics.Unit
import java.text.DecimalFormat
@ -17,24 +18,31 @@ class MapUnit {
@Transient
lateinit var civInfo: CivilizationInfo
var owner: String? = null
var name: String? = null
lateinit var owner: String
lateinit var name: String
var maxMovement: Int = 0
var currentMovement: Float = 0f
lateinit var unitType:UnitType
var health:Int = 10
var strength:Int = 1
var rangedStrength:Int = 0
var health:Int = 100
var action: String? = null // work, automation, fortifying, I dunno what.
fun getBaseUnit(): Unit = GameBasics.Units[name]!!
fun getMovementString(): String = DecimalFormat("0.#").format(currentMovement.toDouble()) + "/" + maxMovement
fun getTile(): TileInfo {
return civInfo.gameInfo.tileMap.values.first{it.unit==this}
}
fun getDistanceToTiles(): HashMap<TileInfo, Float> {
val tile = getTile()
return tile.tileMap.getDistanceToTilesWithinTurn(tile.position,currentMovement,
civInfo.tech.isResearched("Machinery"))
}
fun doPreTurnAction(tile: TileInfo) {
if (currentMovement == 0f) return // We've already done stuff this turn, and can't do any more stuff
if (action != null && action!!.startsWith("moveTo")) {
val destination = action!!.replace("moveTo ", "").split(",").dropLastWhile { it.isEmpty() }.toTypedArray()
val destinationVector = Vector2(Integer.parseInt(destination[0]).toFloat(), Integer.parseInt(destination[1]).toFloat())
val gotTo = headTowards(tile.position, destinationVector)
val gotTo = headTowards(destinationVector)
if(gotTo==tile) // We didn't move at all
return
if (gotTo.position == destinationVector) action = null
@ -42,7 +50,7 @@ class MapUnit {
return
}
if ("automation" == action) doAutomatedAction(tile)
if ("automation" == action) doAutomatedAction()
}
private fun doPostTurnAction(tile: TileInfo) {
@ -80,11 +88,11 @@ class MapUnit {
else return currentTile
}
fun doAutomatedAction(tile: TileInfo) {
var tile = tile
fun doAutomatedAction() {
var tile = getTile()
val tileToWork = findTileToWork(tile)
if (tileToWork != tile) {
tile = headTowards(tile.position, tileToWork.position)
tile = headTowards(tileToWork.position)
doPreTurnAction(tile)
return
}
@ -116,34 +124,75 @@ class MapUnit {
}
/**
*
* @param origin
* @param destination
* @return The tile that we reached this turn
*/
fun headTowards(origin: Vector2, destination: Vector2): TileInfo {
val tileMap = civInfo.gameInfo.tileMap
fun headTowards(destination: Vector2): TileInfo {
val currentTile = getTile()
val tileMap = currentTile.tileMap
val finalDestinationTile = tileMap.get(destination)
val isMachineryResearched = civInfo.tech.isResearched("Machinery")
val distanceToTiles = tileMap.getDistanceToTilesWithinTurn(origin, currentMovement, isMachineryResearched)
val distanceToTiles = getDistanceToTiles()
val destinationTileThisTurn:TileInfo
if (distanceToTiles.containsKey(tileMap.get(destination)))
destinationTileThisTurn = tileMap.get(destination)
if (distanceToTiles.containsKey(finalDestinationTile)) { // we can get there this turn
if (finalDestinationTile.unit == null)
destinationTileThisTurn = finalDestinationTile
else // Someone is blocking to the path to the final tile...
{
val destinationNeighbors = tileMap[destination].neighbors
if(destinationNeighbors.contains(currentTile)) // We're right nearby anyway, no need to move
return currentTile
val reachableDestinationNeighbors = destinationNeighbors.filter { distanceToTiles.containsKey(it) && it.unit==null }
if(reachableDestinationNeighbors.isEmpty()) // We can't get closer...
return currentTile
destinationTileThisTurn = reachableDestinationNeighbors.minBy { distanceToTiles[it]!! }!!
}
}
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)
val path = tileMap.getShortestPath(currentTile.position, 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)
moveToTile(destinationTileThisTurn)
return destinationTileThisTurn
}
fun nextTurn(tileInfo: TileInfo) {
doPostTurnAction(tileInfo)
private fun heal(){
val tile = getTile()
health += when{
tile.isCityCenter -> 20
tile.owner == owner -> 15 // home territory
tile.owner == null -> 10 // no man's land (neutral)
else -> 5 // enemy territory
}
if(health>100) health=100
}
fun moveToTile(otherTile: TileInfo) {
val distanceToTiles = getDistanceToTiles()
if (!distanceToTiles.containsKey(otherTile)) throw Exception("You can't get there from here!")
currentMovement -= distanceToTiles[otherTile]!!
if (currentMovement < 0.1) currentMovement = 0f // silly floats which are "almost zero"
getTile().unit = null
otherTile.unit = this
}
fun nextTurn() {
val tile = getTile()
doPostTurnAction(tile)
if(currentMovement==maxMovement.toFloat()){
heal()
}
currentMovement = maxMovement.toFloat()
doPreTurnAction(tileInfo)
doPreTurnAction(tile)
}
}

View file

@ -10,7 +10,7 @@ import com.unciv.models.gamebasics.TileResource
import com.unciv.models.stats.Stats
class TileInfo {
@Transient @JvmField var tileMap: TileMap? = null
@Transient lateinit var tileMap: TileMap
@JvmField var unit: MapUnit? = null
@JvmField var position: Vector2 = Vector2.Zero
@ -140,7 +140,7 @@ class TileInfo {
}
fun nextTurn() {
if (unit != null) unit!!.nextTurn(this)
if (unit != null) unit!!.nextTurn()
}
override fun toString(): String {
@ -154,7 +154,7 @@ class TileInfo {
if (roadStatus !== RoadStatus.None && !isCityCenter) SB.appendln(roadStatus)
if (improvement != null) SB.appendln(improvement!!)
if (improvementInProgress != null) SB.appendln("$improvementInProgress in ${this.turnsToImprovement} turns")
if (unit != null) SB.appendln(unit!!.name + "(" + unit!!.getMovementString() + ")")
if (unit != null) SB.appendln(unit!!.name + "(" + unit!!.health + ")")
return SB.toString()
}
@ -169,11 +169,4 @@ class TileInfo {
return true
}
fun moveUnitToTile(otherTile: TileInfo, movementDistance: Float) {
if (otherTile.unit != null) return // Fail.
unit!!.currentMovement -= movementDistance
if (unit!!.currentMovement < 0.1) unit!!.currentMovement = 0f // silly floats which are "almost zero"
otherTile.unit = unit
unit = null
}
}

View file

@ -112,7 +112,7 @@ class TileMap {
}
fun placeUnitNearTile(position: Vector2, unitName: String, civInfo: CivilizationInfo) {
val unit = GameBasics.Units[unitName]!!.mapUnit
val unit = GameBasics.Units[unitName]!!.getMapUnit()
unit.owner = civInfo.civName
unit.civInfo = civInfo
val tilesInDistance = getTilesInDistance(position, 2)

View file

@ -3,27 +3,30 @@ package com.unciv.models.gamebasics
import com.unciv.logic.city.CityConstructions
import com.unciv.logic.city.IConstruction
import com.unciv.logic.map.MapUnit
import com.unciv.logic.map.UnitType
import com.unciv.models.stats.INamed
class Unit : INamed, IConstruction {
override lateinit var name: String
@JvmField var description: String? = null
@JvmField var cost: Int = 0
@JvmField var hurryCostModifier: Int = 0
@JvmField var movement: Int = 0
@JvmField internal var unbuildable: Boolean = false // for special units like great people
var description: String? = null
var cost: Int = 0
var hurryCostModifier: Int = 0
var movement: Int = 0
var strength:Int = 1
var rangedStrength:Int = 0
lateinit var unitType: UnitType
internal var unbuildable: Boolean = false // for special units like great people
val isConstructable: Boolean
get() = !unbuildable
val mapUnit: MapUnit
get() {
val unit = MapUnit()
unit.name = name
unit.maxMovement = movement
unit.currentMovement = movement.toFloat()
return unit
}
fun getMapUnit(): MapUnit {
val unit = MapUnit()
unit.name = name
unit.maxMovement = movement
unit.currentMovement = movement.toFloat()
return unit
}
override fun getProductionCost(adoptedPolicies: List<String>): Int {

View file

@ -40,8 +40,14 @@ class UnCivGame : Game() {
setWorldScreen()
}
fun startNewGame() {
gameInfo = GameInfo()
fun startNewGame(saveTutorialState:Boolean = false) {
if(saveTutorialState) {
val tutorials = gameInfo.tutorial
gameInfo = GameInfo()
gameInfo.tutorial = tutorials
}
else gameInfo = GameInfo()
gameInfo.tileMap = TileMap(20)
gameInfo.civilizations.add(CivilizationInfo("Babylon", Vector2.Zero, gameInfo))
val barbarians = CivilizationInfo()

View file

@ -55,7 +55,12 @@ class WorldTileGroup(tileInfo: TileInfo) : TileGroup(tileInfo) {
}
if (tileInfo.unit != null && unitImage == null) {
if (unitImage != null) { // The unit can change within one update - for instance, when attacking, the attacker replaces the defender!
unitImage!!.remove()
unitImage = null
}
if (tileInfo.unit != null) {
val unit = tileInfo.unit!!
unitImage = getUnitImage(unit.name!!, unit.civInfo.getCivilization().getColor())
addActor(unitImage!!)
@ -64,10 +69,6 @@ class WorldTileGroup(tileInfo: TileInfo) : TileGroup(tileInfo) {
height/2 - unitImage!!.height/2 +20) // top
}
if (tileInfo.unit == null && unitImage != null) {
unitImage!!.remove()
unitImage = null
}
if (unitImage != null) {
if (!tileInfo.hasIdleUnit())

View file

@ -0,0 +1,123 @@
package com.unciv.ui.worldscreen
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.unciv.logic.Battle
import com.unciv.logic.map.MapUnit
import com.unciv.logic.map.UnitType
import com.unciv.ui.cityscreen.addClickListener
import com.unciv.ui.utils.CameraStageBaseScreen
import com.unciv.ui.utils.disable
import java.util.*
class BattleTable(val worldScreen: WorldScreen): Table() {
private val battle = Battle()
fun simulateBattle(attacker: MapUnit, defender: MapUnit){
clear()
val attackerLabel = Label(attacker.name, CameraStageBaseScreen.skin)
attackerLabel.style= Label.LabelStyle(attackerLabel.style)
attackerLabel.style.fontColor=attacker.civInfo.getCivilization().getColor()
add(attackerLabel)
val defenderLabel = Label(attacker.name, CameraStageBaseScreen.skin)
defenderLabel.style= Label.LabelStyle(defenderLabel.style)
defenderLabel.style.fontColor=defender.civInfo.getCivilization().getColor()
add(defenderLabel)
row()
// todo: when damage exceeds health, it shows negative health numbers! Also not indicative of who is more likely to win
var damageToDefender = battle.calculateDamage(attacker,defender)
var damageToAttacker = battle.calculateDamage(defender,attacker)
when {
damageToAttacker>attacker.health && damageToDefender>defender.health -> // when damage exceeds health, we don't want to show negative health numbers
// Also if both parties are supposed to die it's not indicative of who is more likely to win
// So we "normalize" the damages until one dies
if(damageToDefender/defender.health.toFloat() > damageToAttacker/attacker.health.toFloat()) // defender dies quicker ie first
{
// Both damages *= (defender.health/damageToDefender)
damageToDefender = defender.health
damageToAttacker *= (defender.health/damageToDefender.toFloat()).toInt()
}
else{ // attacker dies first
// Both damages *= (attacker.health/damageToAttacker)
damageToAttacker = attacker.health
damageToDefender *= (attacker.health/damageToAttacker.toFloat()).toInt()
}
damageToAttacker>attacker.health -> damageToAttacker=attacker.health
damageToDefender>defender.health -> damageToDefender=defender.health
}
val attackLabel = Label(attacker.health.toString() + " -> "
+ (attacker.health - damageToAttacker), CameraStageBaseScreen.skin)
add(attackLabel)
val defendLabel = Label(defender.health.toString() + " -> "
+ (defender.health - damageToDefender),
CameraStageBaseScreen.skin)
add(defendLabel)
row()
val attackButton = TextButton("Attack",CameraStageBaseScreen.skin)
attackButton.addClickListener {
attack(attacker,defender)
}
val attackerCanReachDefender = attacker.getDistanceToTiles().containsKey(defender.getTile())
if(attacker.currentMovement==0f || !attackerCanReachDefender) attackButton.disable()
add(attackButton).colspan(2)
pack()
setPosition(worldScreen.stage.width/2-width/2,
5f)
}
fun attack(attacker: MapUnit, defender: MapUnit){
var damageToDefender = battle.calculateDamage(attacker,defender)
var damageToAttacker = battle.calculateDamage(defender,attacker)
// randomize things so
if(attacker.getBaseUnit().unitType == UnitType.Ranged) defender.health -= damageToDefender // straight up
else { //melee attack is complicated, because either side may defeat the other midway
//so...for each round, we randomize who gets the attack in. Seems to be a good way to work for now.
//attacker..moveUnitToTile()
attacker.headTowards(defender.getTile().position)
while(damageToDefender+damageToAttacker>0) {
if (Random().nextInt(damageToDefender + damageToAttacker) < damageToDefender) {
damageToDefender--
defender.health--
if(defender.health==0) {
val defenderTile = defender.getTile()
defenderTile.unit = null // Ded
attacker.moveToTile(defenderTile)
break
}
}
else{
damageToAttacker--
attacker.health--
if(attacker.health==0) {
attacker.getTile().unit = null
break
}
}
}
}
attacker.currentMovement=0f
worldScreen.update()
}
}

View file

@ -39,13 +39,6 @@ class TileInfoTable(private val worldScreen: WorldScreen, internal val civInfo:
}
}
// if (tile.unit != null) {
// for (button in UnitActions().getUnitActions(tile))
// add(button).colspan(2)
// .size(button.width * worldScreen.buttonScale, button.height * worldScreen.buttonScale).row()
// }
pack()
setPosition(worldScreen.stage.width - 10f - width, 10f)

View file

@ -105,7 +105,7 @@ class TileMapHolder(internal val worldScreen: WorldScreen, internal val tileMap:
fun setCenterPosition(vector: Vector2) {
val tileGroup = tileGroups.values.first { it.tileInfo.position == vector }
selectedTile = tileGroup.tileInfo
if(selectedTile!!.unit!=null) worldScreen.unitTable.selectedUnitTile = selectedTile
worldScreen.unitTable.tileSelected(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 (== filter the screen starts) needs to be half a screen away

View file

@ -2,11 +2,9 @@ package com.unciv.ui.worldscreen
import com.badlogic.gdx.math.Vector2
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.unciv.logic.Battle
import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.logic.map.MapUnit
import com.unciv.logic.map.UnitType
import com.unciv.ui.cityscreen.addClickListener
import com.unciv.ui.pickerscreens.PolicyPickerScreen
import com.unciv.ui.pickerscreens.TechPickerScreen
@ -28,7 +26,7 @@ class WorldScreen : CameraStageBaseScreen() {
internal val optionsTable: WorldScreenOptionsTable
private val notificationsScroll: NotificationsScroll
internal val unitTable = UnitTable(this)
internal val battleTable = BattleTable(this)
private val battleTable = BattleTable(this)
init {
val gameInfo = game.gameInfo
@ -84,9 +82,10 @@ class WorldScreen : CameraStageBaseScreen() {
if(tileMapHolder.selectedTile!=null
&& tileMapHolder.selectedTile!!.unit!=null
&& tileMapHolder.selectedTile!!.unit!!.owner!=civInfo.civName
&& unitTable.selectedUnitTile!=null)
battleTable.simulateBattle(unitTable.getSelectedUnit(), tileMapHolder.selectedTile!!.unit!!)
&& tileMapHolder.selectedTile!!.unit!!.owner!=civInfo.civName // enemy unit on selected tile,
&& unitTable.selectedUnit!=null
&& unitTable.selectedUnit!!.getBaseUnit().unitType!=UnitType.Civilian) // and non-civilian unit selected for us
battleTable.simulateBattle(unitTable.selectedUnit!!, tileMapHolder.selectedTile!!.unit!!)
else battleTable.clear()
}
@ -124,7 +123,6 @@ class WorldScreen : CameraStageBaseScreen() {
}
game.gameInfo.nextTurn()
unitTable.selectedUnitTile = null
unitTable.currentlyExecutingAction = null
GameSaver.SaveGame(game, "Autosave")
update()
@ -142,28 +140,4 @@ class WorldScreen : CameraStageBaseScreen() {
game.setWorldScreen()
}
}
}
class BattleTable(val worldScreen: WorldScreen): Table() {
fun simulateBattle(attacker:MapUnit,defender:MapUnit){
clear()
add(Label(attacker.name, CameraStageBaseScreen.skin))
add(Label(defender.name, CameraStageBaseScreen.skin))
row()
val battle = Battle()
val damageToAttacker = battle.calculateDamage(attacker,defender)
add(Label(attacker.health.toString()+"/10 -> "
+(attacker.health-damageToAttacker)+"/10",
CameraStageBaseScreen.skin))
val damageToDefender = battle.calculateDamage(defender,attacker)
add(Label(defender.health.toString()+"/10 -> "
+(defender.health-damageToDefender)+"/10",
CameraStageBaseScreen.skin))
pack()
setPosition(worldScreen.stage.width/2-width/2,
5f)
}
}
}

View file

@ -29,7 +29,7 @@ class WorldScreenOptionsTable internal constructor(worldScreen: WorldScreen, pri
row()
val StartNewGameButton = TextButton("Start new game", CameraStageBaseScreen.skin)
StartNewGameButton.addClickListener { worldScreen.game.startNewGame() }
StartNewGameButton.addClickListener { worldScreen.game.startNewGame(true) }
add(StartNewGameButton).pad(10f)
row()

View file

@ -25,9 +25,10 @@ class UnitActions {
}
}
fun getUnitActions(tile: TileInfo, worldScreen: WorldScreen): List<TextButton> {
fun getUnitActions(unit:MapUnit,worldScreen: WorldScreen): List<TextButton> {
val tile = unit.getTile()
val unit = tile.unit!!
val tileMapHolder = worldScreen.tileMapHolder
val unitTable = worldScreen.unitTable
@ -40,10 +41,7 @@ class UnitActions {
// Set all tiles transparent except those in unit range
for (TG in tileMapHolder.tileGroups.values) TG.setColor(0f, 0f, 0f, 0.3f)
val distanceToTiles = tileMapHolder.tileMap.getDistanceToTilesWithinTurn(
unitTable.selectedUnitTile!!.position,
unitTable.getSelectedUnit().currentMovement,
unit.civInfo.tech.isResearched("Machinery"))
val distanceToTiles = unitTable.selectedUnit!!.getDistanceToTiles()
for (tileInRange in distanceToTiles.keys) {
tileMapHolder.tileGroups[tileInRange.position.toString()]!!.color = Color.WHITE
@ -62,7 +60,7 @@ class UnitActions {
}
if (unit.name == "Settler") {
actionList += getUnitActionButton(unit, "Found City",
actionList += getUnitActionButton(unit, "Found city",
!tileMapHolder.tileMap.getTilesInDistance(tile.position, 2).any { it.isCityCenter },
{
worldScreen.displayTutorials("CityFounded")
@ -75,16 +73,16 @@ class UnitActions {
}
if (unit.name == "Worker") {
val improvementButtonText =
if (tile.improvementInProgress == null) "Construct\r\nimprovement"
else tile.improvementInProgress!! + "\r\nin progress"
val improvementButtonText: String
if (tile.improvementInProgress == null) improvementButtonText = "Construct\r\nimprovement"
else improvementButtonText = tile.improvementInProgress!! + "\r\nin progress"
actionList += getUnitActionButton(unit, improvementButtonText,
!tile.isCityCenter || GameBasics.TileImprovements.values.any { tile.canBuildImprovement(it, unit.civInfo) },
{ worldScreen.game.screen = ImprovementPickerScreen(tile) })
if("automation" == tile.unit!!.action){
if("automation" == unit.action){
val automationAction = getUnitActionButton(unit,"Stop automation",true,
{tile.unit!!.action = null})
{unit.action = null})
automationAction.enable() // Stopping automation is always enabled;
actionList += automationAction
}
@ -92,7 +90,7 @@ class UnitActions {
actionList += getUnitActionButton(unit, "Automate", true,
{
tile.unit!!.action = "automation"
tile.unit!!.doAutomatedAction(tile)
tile.unit!!.doAutomatedAction()
}
)
}

View file

@ -13,16 +13,11 @@ 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 selectedUnit : MapUnit? = 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))
@ -37,11 +32,19 @@ class UnitTable(val worldScreen: WorldScreen) : Table(){
fun update() {
idleUnitButton.update()
unitActionsTable.clear()
if(selectedUnitTile!=null && selectedUnitTile!!.unit==null) selectedUnitTile=null // The unit that was there no longer exists
if(selectedUnit!=null)
{
try{ selectedUnit!!.getTile()}
catch(ex:Exception) {selectedUnit=null} // The unit that was there no longer exists}
}
if(selectedUnitTile!=null) {
unitLabel.setText(getSelectedUnit().name+" "+getSelectedUnit().getMovementString())
for (button in UnitActions().getUnitActions(selectedUnitTile!!,worldScreen))
if(selectedUnit!=null) {
val unit = selectedUnit!!
unitLabel.setText(unit.name
+"\r\nMovement: " +unit.getMovementString()
+"\r\nHealth: "+unit.health
)
for (button in UnitActions().getUnitActions(selectedUnit!!, worldScreen))
unitActionsTable.add(button).colspan(2).pad(5f)
.size(button.width * worldScreen.buttonScale, button.height * worldScreen.buttonScale).row()
}
@ -54,27 +57,21 @@ class UnitTable(val worldScreen: WorldScreen) : Table(){
fun tileSelected(selectedTile: TileInfo) {
if(currentlyExecutingAction=="moveTo"){
val reachedTile = getSelectedUnit().headTowards(selectedUnitTile!!.position, selectedTile.position)
selectedUnitTile = reachedTile
val reachedTile = selectedUnit!!.headTowards(selectedTile.position)
if(reachedTile!=selectedTile) // Didn't get all the way there
getSelectedUnit().action = "moveTo " + selectedTile.position.x.toInt() + "," + selectedTile.position.y.toInt()
selectedUnit!!.action = "moveTo " + selectedTile.position.x.toInt() + "," + selectedTile.position.y.toInt()
currentlyExecutingAction = null
}
if(selectedTile.unit!=null && selectedTile.unit!!.civInfo == worldScreen.civInfo)
selectedUnitTile = selectedTile
}
private fun getDistanceToTiles(): HashMap<TileInfo, Float> {
return worldScreen.tileMapHolder.tileMap.getDistanceToTilesWithinTurn(selectedUnitTile!!.position,
getSelectedUnit().currentMovement,
getSelectedUnit().civInfo.tech.isResearched("Machinery"))
selectedUnit= selectedTile.unit
}
fun getViewablePositionsForExecutingAction(): List<Vector2>
{
if(currentlyExecutingAction == "moveTo")
return getDistanceToTiles().keys.map { it.position }
return selectedUnit!!.getDistanceToTiles().keys.map { it.position }
return emptyList()
}
}