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:
parent
bd1a191b15
commit
5d00adb7fe
16 changed files with 291 additions and 134 deletions
|
@ -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
|
||||
},
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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())
|
||||
|
|
123
core/src/com/unciv/ui/worldscreen/BattleTable.kt
Normal file
123
core/src/com/unciv/ui/worldscreen/BattleTable.kt
Normal 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()
|
||||
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue