Massive change - Unit in TileInfo now spit to CivilianUnit and MilitaryUnit!

This commit is contained in:
Yair Morgenstern 2018-05-31 17:23:46 +03:00
parent c50a919e2a
commit f6ca98b1d7
20 changed files with 187 additions and 164 deletions

View File

@ -12,6 +12,7 @@ class GameStarter(){
val gameInfo = GameInfo()
gameInfo.tileMap = TileMap(mapRadius)
gameInfo.tileMap.gameInfo = gameInfo // need to set this transient before placing units in the map
gameInfo.civilizations.add(CivilizationInfo(civilization, Vector2.Zero, gameInfo)) // first one is player civ
val freeTiles = gameInfo.tileMap.values.toMutableList()

View File

@ -57,7 +57,7 @@ class GameInfo {
var tile = tileToPlace
if(tileToPlace==null) {
val playerViewableTiles = getPlayerCivilization().getViewableTiles().toHashSet()
val viableTiles = tileMap.values.filterNot { playerViewableTiles.contains(it) || it.unit != null }
val viableTiles = tileMap.values.filterNot { playerViewableTiles.contains(it) || it.militaryUnit != null || it.civilianUnit!=null}
tile=viableTiles.getRandom()
}
tileMap.placeUnitNearTile(tile!!.position,"Warrior",getBarbarianCivilization())
@ -72,8 +72,12 @@ class GameInfo {
civInfo.setTransients()
}
for (tile in tileMap.values.filter { it.unit!=null })
tile.unit!!.civInfo = civilizations.first { it.civName == tile.unit!!.owner }
val civNameToCiv = civilizations.associateBy ({ it.civName},{it})
for (tile in tileMap.values) {
if (tile.militaryUnit != null) tile.militaryUnit!!.civInfo = civNameToCiv[tile.militaryUnit!!.owner]!!
if (tile.civilianUnit!= null) tile.civilianUnit!!.civInfo = civNameToCiv[tile.civilianUnit!!.owner]!!
}
for (civInfo in civilizations)

View File

@ -68,7 +68,7 @@ class Automation {
private fun trainCombatUnit(city: CityInfo) {
val combatUnits = city.cityConstructions.getConstructableUnits().filter { it.unitType != UnitType.Civilian }
val chosenUnit:Unit
if(city.civInfo.cities.any { it.getCenterTile().unit==null}
if(city.civInfo.cities.any { it.getCenterTile().militaryUnit==null}
&& combatUnits.any { it.unitType==UnitType.Archery }) // this is for city defence so get an archery unit if we can
chosenUnit = combatUnits.filter { it.unitType==UnitType.Archery }.maxBy { it.cost }!!

View File

@ -1,15 +1,11 @@
package com.unciv.logic.automation
import com.badlogic.gdx.graphics.Color
import com.unciv.UnCivGame
import com.unciv.logic.battle.Battle
import com.unciv.logic.battle.CityCombatant
import com.unciv.logic.battle.ICombatant
import com.unciv.logic.battle.MapUnitCombatant
import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.logic.map.MapUnit
import com.unciv.logic.map.TileInfo
import com.unciv.logic.map.UnitType
import com.unciv.ui.utils.getRandom
import com.unciv.ui.worldscreen.unit.UnitActions
@ -22,14 +18,14 @@ class UnitAutomation{
val unitTile = unit.getTile()
// Go to friendly tile if within distance - better healing!
val friendlyTile = tilesInDistance.firstOrNull { it.getOwner()?.civName == unit.owner && it.unit == null }
val friendlyTile = tilesInDistance.firstOrNull { it.getOwner()?.civName == unit.owner && unit.canMoveTo(it) }
if (unitTile.getOwner()?.civName != unit.owner && friendlyTile != null) {
unit.moveToTile(friendlyTile)
return
}
// Or at least get out of enemy territory yaknow
val neutralTile = tilesInDistance.firstOrNull { it.getOwner() == null && it.unit == null }
val neutralTile = tilesInDistance.firstOrNull { it.getOwner() == null && unit.canMoveTo(it)}
if (unitTile.getOwner()?.civName != unit.owner && unitTile.getOwner() != null && neutralTile != null) {
unit.moveToTile(neutralTile)
return
@ -37,8 +33,9 @@ class UnitAutomation{
}
fun containsAttackableEnemy(tile: TileInfo, civInfo: CivilizationInfo): Boolean {
return (tile.unit != null && tile.unit!!.owner != civInfo.civName)
|| (tile.isCityCenter() && tile.getCity()!!.civInfo!=civInfo)
val tileCombatant = Battle().getMapCombatantOfTile(tile)
if(tileCombatant==null) return false
return tileCombatant.getCivilization()!=civInfo
}
fun getAttackableEnemies(unit: MapUnit): List<TileInfo> {
@ -53,7 +50,7 @@ class UnitAutomation{
return attackableTiles.filter {
it.neighbors.any {
unit.getTile()==it || // We're already right nearby
it.unit == null
unit.canMoveTo(it)
&& distanceToTiles.containsKey(it)
&& distanceToTiles[it]!! < unit.currentMovement // We can get there
}
@ -89,23 +86,7 @@ class UnitAutomation{
val enemyTileToAttack = getAttackableEnemies(unit).firstOrNull()
if (enemyTileToAttack != null) {
val enemy:ICombatant
if(enemyTileToAttack.isCityCenter()){
enemy = CityCombatant(enemyTileToAttack.getCity()!!)
}
else {
val unitToAttack = enemyTileToAttack.unit!!
if (unitToAttack.getBaseUnit().unitType == UnitType.Civilian) { // kill
unitToAttack.civInfo.addNotification("Our " + unitToAttack.name + " was destroyed by an enemy " + unit.name + "!", enemyTileToAttack.position, Color.RED)
enemyTileToAttack.unit = null
unit.movementAlgs().headTowards(enemyTileToAttack)
return
}
enemy=MapUnitCombatant(unitToAttack)
}
val enemy = Battle().getMapCombatantOfTile(enemyTileToAttack)!!
val damageToAttacker = Battle(unit.civInfo.gameInfo).calculateDamageToAttacker(MapUnitCombatant(unit), enemy)
if (damageToAttacker < unit.health) { // don't attack if we'll die from the attack
@ -118,7 +99,8 @@ class UnitAutomation{
if(unit.getTile().isCityCenter()) return // It's always good to have a unit in the city center, so if you havn't found annyonw aroud to attack, forget it.
val reachableCitiesWithoutUnits = unit.civInfo.cities.filter { it.getCenterTile().unit==null
val reachableCitiesWithoutUnits = unit.civInfo.cities.filter {
unit.canMoveTo(it.getCenterTile())
&& unit.movementAlgs().canReach(it.getCenterTile()) }
if(reachableCitiesWithoutUnits.isNotEmpty()){
val closestCityWithoutUnit = reachableCitiesWithoutUnits
@ -153,7 +135,7 @@ class UnitAutomation{
// else, go to a random space
val reachableTiles = unit.getDistanceToTiles()
.filter { it.key.unit == null} // at edge of walking distance
.filter { unit.canMoveTo(it.key)}
val reachableTilesMaxWalkingDistance = reachableTiles.filter { it.value==unit.currentMovement}
if(reachableTilesMaxWalkingDistance.any()) unit.moveToTile(reachableTilesMaxWalkingDistance.toList().getRandom().first)
else if(reachableTiles.any()) unit.moveToTile(reachableTiles.toList().getRandom().first)
@ -184,7 +166,7 @@ class UnitAutomation{
if(possibleTiles.isEmpty()) // We got a badass over here, all tiles within 5 are taken? Screw it, random walk.
{
unit.moveToTile(unit.getDistanceToTiles()
.filter { it.key.unit == null && it.value==unit.currentMovement } // at edge of walking distance
.filter { unit.canMoveTo(it.key) && it.value==unit.currentMovement } // at edge of walking distance
.toList().getRandom().first)
return
}

View File

@ -10,7 +10,7 @@ class WorkerAutomation {
fun automateWorkerAction(unit: MapUnit) {
val enemyUnitsInWalkingDistance = unit.getDistanceToTiles().keys
.filter { it.unit!=null && it.unit!!.civInfo!=unit.civInfo }
.filter { it.militaryUnit!=null && it.militaryUnit!!.civInfo!=unit.civInfo }
if(enemyUnitsInWalkingDistance.isNotEmpty()) return // Don't you dare move.
@ -33,7 +33,7 @@ class WorkerAutomation {
val currentTile=worker.getTile()
val workableTiles = currentTile.getTilesInDistance(4)
.filter {
(it.unit == null || it == currentTile)
(it.civilianUnit== null || it == currentTile)
&& it.improvement == null
&& it.canBuildImprovement(chooseImprovement(it), worker.civInfo)
&& {val city=it.getCity(); city==null || it.getCity()?.civInfo == worker.civInfo}() // don't work tiles belonging to another civ

View File

@ -1,6 +1,7 @@
package com.unciv.logic.battle
import com.badlogic.gdx.graphics.Color
import com.unciv.UnCivGame
import com.unciv.logic.GameInfo
import com.unciv.logic.city.CityInfo
import com.unciv.logic.map.TileInfo
@ -12,7 +13,7 @@ import kotlin.math.max
/**
* Damage calculations according to civ v wiki and https://steamcommunity.com/sharedfiles/filedetails/?id=170194443
*/
class Battle(val gameInfo:GameInfo) {
class Battle(val gameInfo:GameInfo=UnCivGame.Current.gameInfo) {
private fun getGeneralModifiers(combatant: ICombatant, enemy: ICombatant): HashMap<String, Float> {
val modifiers = HashMap<String, Float>()
@ -47,9 +48,9 @@ class Battle(val gameInfo:GameInfo) {
val modifiers = getGeneralModifiers(attacker, defender)
if (attacker.isMelee()) {
val numberOfAttackersSurroundingDefender = defender.getTile().neighbors.count {
it.unit != null
&& it.unit!!.owner == attacker.getCivilization().civName
&& MapUnitCombatant(it.unit!!).isMelee()
it.militaryUnit != null
&& it.militaryUnit!!.owner == attacker.getCivilization().civName
&& MapUnitCombatant(it.militaryUnit!!).isMelee()
}
if (numberOfAttackersSurroundingDefender > 1)
modifiers["Flanking"] = 0.1f * (numberOfAttackersSurroundingDefender-1) //https://www.carlsguides.com/strategy/civilization5/war/combatbonuses.php
@ -101,6 +102,7 @@ class Battle(val gameInfo:GameInfo) {
fun calculateDamageToAttacker(attacker: ICombatant, defender: ICombatant): Int {
if(attacker.isRanged()) return 0
if(defender.getUnitType()==UnitType.Civilian) return 0
val ratio = getDefendingStrength(attacker,defender) / getAttackingStrength(attacker,defender)
return (ratio * 30 * getHealthDependantDamageRatio(defender)).toInt()
}
@ -180,7 +182,11 @@ class Battle(val gameInfo:GameInfo) {
attacker.getCivilization().cities.add(city)
city.civInfo = attacker.getCivilization()
city.health = city.getMaxHealth() / 2 // I think that cities recover to half health?
city.getCenterTile().unit = null
city.getCenterTile().apply {
militaryUnit = null
civilianUnit=null
}
city.expansion.cultureStored = 0
city.expansion.reset()
@ -201,4 +207,11 @@ class Battle(val gameInfo:GameInfo) {
(attacker as MapUnitCombatant).unit.moveToTile(city.getCenterTile())
city.civInfo.gameInfo.updateTilesToCities()
}
fun getMapCombatantOfTile(tile:TileInfo): ICombatant? {
if(tile.isCityCenter()) return CityCombatant(tile.getCity()!!)
if(tile.militaryUnit!=null) return MapUnitCombatant(tile.militaryUnit!!)
if(tile.civilianUnit!=null) return MapUnitCombatant(tile.civilianUnit!!)
return null
}
}

View File

@ -14,7 +14,7 @@ class MapUnitCombatant(val unit: MapUnit) : ICombatant {
override fun takeDamage(damage: Int) {
unit.health -= damage
if(isDefeated()) unit.getTile().unit=null
if(isDefeated()) unit.removeFromTile()
}
override fun getAttackingStrength(defender: ICombatant): Int {

View File

@ -174,16 +174,15 @@ class CivilizationInfo {
}
fun getCivUnits(): List<MapUnit> {
return gameInfo.tileMap.values.filter { it.unit!=null && it.unit!!.owner==civName }.map { it.unit!! }
return gameInfo.tileMap.values.flatMap { it.getUnits() }.filter { it.civInfo==this }
}
fun getViewableTiles(): List<TileInfo> {
var viewablePositions = emptyList<TileInfo>()
viewablePositions += cities.flatMap { it.getTiles() }
.flatMap { it.neighbors } // tiles adjacent to city tiles
viewablePositions += gameInfo.tileMap.values
.filter { it.unit != null && it.unit!!.owner == civName }
.flatMap { it.getViewableTiles(it.unit!!.getVisibilityRange())} // Tiles within 2 tiles of units
viewablePositions += getCivUnits()
.flatMap { it.getViewableTiles()} // Tiles within 2 tiles of units
viewablePositions.map { it.position }.filterNot { exploredTiles.contains(it) }.toCollection(exploredTiles)
return viewablePositions
}

View File

@ -21,7 +21,7 @@ class MapUnit {
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}
return civInfo.gameInfo.tileMap.values.first{it.militaryUnit==this || it.civilianUnit==this}
}
fun getDistanceToTiles(): HashMap<TileInfo, Float> {
@ -34,7 +34,7 @@ class MapUnit {
if (currentMovement == 0f) return // We've already done stuff this turn, and can't do any more stuff
val enemyUnitsInWalkingDistance = getDistanceToTiles().keys
.filter { it.unit!=null && it.unit!!.civInfo!=civInfo }
.filter { it.militaryUnit!=null && it.militaryUnit!!.civInfo!=civInfo }
if(enemyUnitsInWalkingDistance.isNotEmpty()) return // Don't you dare move.
if (action != null && action!!.startsWith("moveTo")) {
@ -88,23 +88,17 @@ class MapUnit {
if(health>100) health=100
}
fun canMove(tile: TileInfo): Boolean {
if(tile.unit!=null) return false
if(tile.isCityCenter() && tile.getOwner()!=civInfo) return false
return true
}
fun moveToTile(otherTile: TileInfo) {
val distanceToTiles = getDistanceToTiles()
if (!distanceToTiles.containsKey(otherTile))
throw Exception("You can't get there from here!")
if (otherTile.unit != null ) throw Exception("Tile already contains a unit!")
if(!canMoveTo(otherTile)) throw Exception("Can't enter this tile!")
if(otherTile.isCityCenter() && otherTile.getOwner()!=civInfo) throw Exception("This is an enemy city, you can't go here!")
currentMovement -= distanceToTiles[otherTile]!!
if (currentMovement < 0.1) currentMovement = 0f // silly floats which are "almost zero"
getTile().unit = null
otherTile.unit = this
removeFromTile()
putInTile(otherTile)
}
fun endTurn() {
@ -130,10 +124,10 @@ class MapUnit {
return "$name - $owner"
}
fun getVisibilityRange(): Int {
fun getViewableTiles(): MutableList<TileInfo> {
var visibilityRange = 2
if(hasUnique("Limited Visibility")) visibilityRange-=1
return visibilityRange
return getTile().getViewableTiles(visibilityRange)
}
fun isFortified(): Boolean {
@ -144,4 +138,33 @@ class MapUnit {
if(!isFortified()) return 0
return action!!.split(" ")[1].toInt()
}
fun removeFromTile(){
if (getBaseUnit().unitType==UnitType.Civilian) getTile().civilianUnit=null
else getTile().militaryUnit=null
}
fun putInTile(tile:TileInfo){
if(!canMoveTo(tile)) throw Exception("I can't go there!")
if(getBaseUnit().unitType==UnitType.Civilian)
tile.civilianUnit=this
else tile.militaryUnit=this
}
/**
* Designates whether we can walk to the tile - without attacking
*/
fun canMoveTo(tile: TileInfo): Boolean {
if(tile.isCityCenter() && tile.getOwner()!!.civName!=owner) return false
if (getBaseUnit().unitType==UnitType.Civilian)
return tile.civilianUnit==null && (tile.militaryUnit==null || tile.militaryUnit!!.owner==owner)
else return tile.militaryUnit==null
}
fun isIdle(): Boolean {
if (currentMovement == 0f) return false
if (name == "Worker" && getTile().improvementInProgress != null) return false
if (isFortified()) return false
return true
}
}

View File

@ -10,10 +10,14 @@ import com.unciv.models.gamebasics.TileImprovement
import com.unciv.models.gamebasics.TileResource
import com.unciv.models.stats.Stats
class TileInfo {
open class TileInfo {
@Transient lateinit var tileMap: TileMap
var unit: MapUnit? = null
var unit:MapUnit?=null
var militaryUnit:MapUnit?=null
var civilianUnit:MapUnit?=null
fun getUnits()= listOf(militaryUnit,civilianUnit).filterNotNull()
var position: Vector2 = Vector2.Zero
var baseTerrain: String? = null
var terrainFeature: String? = null
@ -153,10 +157,12 @@ 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 && UnCivGame.Current.gameInfo.getPlayerCivilization().getViewableTiles().contains(this)){
var unitString = unit!!.name
if(unit!!.getBaseUnit().unitType!=UnitType.Civilian && unit!!.health<100) unitString += "(" + unit!!.health + ")"
SB.appendln(unitString)
val isViewableToPlayer = UnCivGame.Current.gameInfo.getPlayerCivilization().getViewableTiles().contains(this)
if (civilianUnit != null && isViewableToPlayer) SB.appendln(civilianUnit!!.name)
if(militaryUnit!=null && isViewableToPlayer){
var milUnitString = militaryUnit!!.name
if(militaryUnit!!.health<100) milUnitString += "(" + militaryUnit!!.health + ")"
SB.appendln(milUnitString)
}
return SB.toString().trim()
}
@ -166,11 +172,7 @@ class TileInfo {
}
fun hasIdleUnit(): Boolean {
if (unit == null) return false
if (unit!!.currentMovement == 0f) return false
if (unit!!.name == "Worker" && improvementInProgress != null) return false
if (unit!!.isFortified()) return false
return true
return getUnits().any{it.isIdle()}
}
fun getViewableTiles(distance:Int): MutableList<TileInfo> {
@ -191,5 +193,4 @@ class TileInfo {
val city = getCity()
return city!=null && city.workedTiles.contains(position)
}
}

View File

@ -47,8 +47,8 @@ class TileMap {
unit.owner = civInfo.civName
unit.civInfo = civInfo
val tilesInDistance = getTilesInDistance(position, 2)
val unitToPlaceTile = tilesInDistance.firstOrNull { it.unit == null }
if(unitToPlaceTile!=null) unitToPlaceTile.unit = unit // And if there's none, then kill me.
val unitToPlaceTile = tilesInDistance.firstOrNull { unit.canMoveTo(it) }
if(unitToPlaceTile!=null) unit.putInTile(unitToPlaceTile)
return unit
}
@ -65,7 +65,13 @@ class TileMap {
}
fun setTransients() {
for (tileInfo in values) tileInfo.tileMap = this
for (tileInfo in values){
tileInfo.tileMap = this
if(tileInfo.unit!=null){
tileInfo.unit!!.putInTile(tileInfo)
tileInfo.unit=null
}
}
}
}

View File

@ -37,7 +37,7 @@ class UnitMovementAlgorithms(val unit:MapUnit) {
var totalDistanceToTile:Float
if ((neighbor.getOwner() != unit.civInfo && neighbor.isCityCenter())// Enemy city,
|| neighbor.unit!=null && neighbor.unit!!.civInfo!=unit.civInfo) // Enemy unit
|| neighbor.getUnits().isNotEmpty() && neighbor.getUnits().first().civInfo!=unit.civInfo) // Enemy unit
totalDistanceToTile = unitMovement // can't move through it - we'll be "stuck" there
else {
@ -80,7 +80,7 @@ class UnitMovementAlgorithms(val unit:MapUnit) {
distanceToDestination[tileToCheck] = distanceToTilesThisTurn[reachableTile]!!
else {
if (movementTreeParents.containsKey(reachableTile)) continue // We cannot be faster than anything existing...
if (!unit.canMove(reachableTile)) continue // This is a tile that we can''t actually enter - either an intermediary tile containing our unit, or an enemy unit/city
if (!unit.canMoveTo(reachableTile)) continue // This is a tile that we can''t actually enter - either an intermediary tile containing our unit, or an enemy unit/city
movementTreeParents[reachableTile] = tileToCheck
newTilesToCheck.add(reachableTile)
}
@ -121,7 +121,7 @@ class UnitMovementAlgorithms(val unit:MapUnit) {
val destinationTileThisTurn: TileInfo
if (distanceToTiles.containsKey(destination)) { // we can get there this turn
if (unit.canMove(destination))
if (unit.canMoveTo(destination))
destinationTileThisTurn = destination
else // Someone is blocking to the path to the final tile...
{
@ -130,7 +130,7 @@ class UnitMovementAlgorithms(val unit:MapUnit) {
return currentTile
val reachableDestinationNeighbors = destinationNeighbors
.filter { distanceToTiles.containsKey(it) && unit.canMove(it)}
.filter { distanceToTiles.containsKey(it) && unit.canMoveTo(it)}
if (reachableDestinationNeighbors.isEmpty()) // We can't get closer...
return currentTile

View File

@ -6,7 +6,6 @@ import com.unciv.logic.city.CityInfo
import com.unciv.logic.map.TileInfo
import com.unciv.ui.tilegroups.TileGroup
import com.unciv.ui.utils.ImageGetter
import com.unciv.ui.utils.center
import com.unciv.ui.utils.centerX
class CityTileGroup(private val city: CityInfo, tileInfo: TileInfo) : TileGroup(tileInfo) {
@ -25,12 +24,6 @@ class CityTileGroup(private val city: CityInfo, tileInfo: TileInfo) : TileGroup(
fun update() {
super.update(true)
updateUnitImage(true)
if(unitImage!=null) {
unitImage!!.center(this)
unitImage!!.y += 20 // top
}
updatePopulationImage()
if (improvementImage != null) improvementImage!!.setColor(1f, 1f, 1f, 0.5f)
if (resourceImage != null) resourceImage!!.setColor(1f, 1f, 1f, 0.5f)

View File

@ -29,7 +29,8 @@ open class TileGroup(var tileInfo: TileInfo) : Group() {
var populationImage: Image? = null
private val roadImages = HashMap<String, Image>()
private val borderImages = ArrayList<Image>()
protected var unitImage: Group? = null
protected var civilianUnitImage: Group? = null
protected var militaryUnitImage: Group? = null
private val circleImage = ImageGetter.getImage("OtherIcons/Circle.png") // for blue and red circles on the tile
private val fogImage = ImageGetter.getImage("TerrainIcons/Fog.png")
@ -71,8 +72,8 @@ open class TileGroup(var tileInfo: TileInfo) : Group() {
populationImage!!.run {
setSize(20f, 20f)
center(this@TileGroup)
y -= 20
} // top left
x += 20 // right
}
addActor(populationImage)
}
@ -96,6 +97,9 @@ open class TileGroup(var tileInfo: TileInfo) : Group() {
updateResourceImage(isViewable)
updateImprovementImage(isViewable)
civilianUnitImage = newUnitImage(tileInfo.civilianUnit,civilianUnitImage,isViewable,-20f)
militaryUnitImage = newUnitImage(tileInfo.militaryUnit,militaryUnitImage,isViewable,20f)
updateRoadImages()
updateBorderImages()
@ -202,7 +206,8 @@ open class TileGroup(var tileInfo: TileInfo) : Group() {
improvementImage!!.run {
setSize(20f, 20f)
center(this@TileGroup)
this.x+=20 // right
this.x -= 22 // left
this.y -= 10 // bottom
}
improvementType = tileInfo.improvement
}
@ -218,7 +223,8 @@ open class TileGroup(var tileInfo: TileInfo) : Group() {
resourceImage = ImageGetter.getImage(fileName)
resourceImage!!.setSize(20f, 20f)
resourceImage!!.center(this)
resourceImage!!.x -= 20 // left
resourceImage!!.x -= 22 // left
resourceImage!!.y += 10 // top
addActor(resourceImage!!)
}
if(resourceImage!=null){
@ -228,41 +234,35 @@ open class TileGroup(var tileInfo: TileInfo) : Group() {
}
protected fun updateUnitImage(isViewable: Boolean) {
if (unitImage != null) { // The unit can change within one update - for instance, when attacking, the attacker replaces the defender!
unitImage!!.remove()
unitImage = null
protected fun newUnitImage(unit:MapUnit?, currentImage:Group?, isViewable: Boolean, yFromCenter:Float): Group? {
var newImage:Group? = null
if (currentImage!= null) { // The unit can change within one update - for instance, when attacking, the attacker replaces the defender!
currentImage.remove()
}
if (tileInfo.unit != null && (isViewable || viewEntireMapForDebug)) { // Tile is visible
val unit = tileInfo.unit!!
unitImage = getUnitImage(unit, unit.civInfo.getCivilization().getColor())
addActor(unitImage!!)
unitImage!!.setSize(20f, 20f)
}
if (unitImage != null) {
if (!tileInfo.hasIdleUnit())
unitImage!!.color = Color(1f, 1f, 1f, 0.5f)
else
unitImage!!.color = Color.WHITE
if (unit != null && (isViewable || viewEntireMapForDebug)) { // Tile is visible
newImage = getUnitImage(unit, unit.civInfo.getCivilization().getColor(), 25f)
addActor(newImage)
newImage.center(this)
newImage.y+=yFromCenter
if(!unit.isIdle()) newImage.color = Color(1f, 1f, 1f, 0.5f)
}
return newImage
}
private fun getUnitImage(unit: MapUnit, color:Color): Group {
private fun getUnitImage(unit: MapUnit, color: Color, size: Float): Group {
val unitBaseImage = ImageGetter.getUnitIcon(unit.name)
.apply { setSize(15f,15f) }
.apply { setSize(20f,20f) }
val background = if(unit.isFortified()) ImageGetter.getImage("OtherIcons/Shield.png")
else ImageGetter.getImage("OtherIcons/Circle.png")
background.apply {
this.color = color
setSize(20f,20f)
setSize(size,size)
}
val group = Group().apply {
setSize(background.width,background.height)
setSize(size,size)
addActor(background)
}
unitBaseImage.center(group)

View File

@ -7,7 +7,9 @@ import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.badlogic.gdx.utils.Align
import com.unciv.UnCivGame
import com.unciv.logic.city.CityInfo
import com.unciv.logic.map.MapUnit
import com.unciv.logic.map.TileInfo
import com.unciv.logic.map.UnitType
import com.unciv.ui.cityscreen.CityScreen
import com.unciv.ui.cityscreen.addClickListener
import com.unciv.ui.utils.CameraStageBaseScreen
@ -19,33 +21,28 @@ import com.unciv.ui.utils.setFontColor
class WorldTileGroup(tileInfo: TileInfo) : TileGroup(tileInfo) {
var cityButton: Table? = null
fun addWhiteHaloAroundUnit(){
val whiteHalo = if(tileInfo.unit!!.isFortified()) ImageGetter.getImage("OtherIcons/Shield.png")
fun addWhiteHaloAroundUnit(unit: MapUnit) {
val whiteHalo = if(unit.isFortified()) ImageGetter.getImage("OtherIcons/Shield.png")
else ImageGetter.getImage("OtherIcons/Circle.png")
whiteHalo.setSize(25f,25f)
whiteHalo.center(unitImage!!)
unitImage!!.addActor(whiteHalo)
whiteHalo.setSize(30f,30f)
val unitImage = if(unit.getBaseUnit().unitType==UnitType.Civilian) civilianUnitImage!!
else militaryUnitImage!!
whiteHalo.center(unitImage)
unitImage.addActor(whiteHalo)
whiteHalo.toBack()
}
override fun update(isViewable: Boolean) {
super.update(isViewable)
if (!tileInfo.tileMap.gameInfo.getPlayerCivilization().exploredTiles.contains(tileInfo.position)
&& !viewEntireMapForDebug) return
if (populationImage != null) removePopulationIcon()
val city = tileInfo.getCity()
if (tileInfo.isWorked() && city!!.civInfo.isPlayerCivilization() && populationImage == null)
if (isViewable && tileInfo.isWorked() && city!!.civInfo.isPlayerCivilization() && populationImage == null)
addPopulationIcon()
updateCityButton(city)
updateUnitImage(isViewable)
if(unitImage!=null) {
unitImage!!.center(this)
unitImage!!.y += 20 // top
}
if (tileInfo.tileMap.gameInfo.getPlayerCivilization().exploredTiles.contains(tileInfo.position)
|| viewEntireMapForDebug) updateCityButton(city) // needs to be before the update so the units will be above the city button
super.update(isViewable)
}
private fun updateCityButton(city: CityInfo?) {

View File

@ -5,7 +5,6 @@ import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.badlogic.gdx.scenes.scene2d.ui.TextButton
import com.unciv.logic.automation.UnitAutomation
import com.unciv.logic.battle.Battle
import com.unciv.logic.battle.CityCombatant
import com.unciv.logic.battle.ICombatant
import com.unciv.logic.battle.MapUnitCombatant
import com.unciv.logic.map.UnitType
@ -42,15 +41,11 @@ class BattleTable(val worldScreen: WorldScreen): Table() {
if (worldScreen.tileMapHolder.selectedTile == null) return
val selectedTile = worldScreen.tileMapHolder.selectedTile!!
val defender: ICombatant
if (attacker.getCivilization().exploredTiles.contains(selectedTile.position)
&& selectedTile.isCityCenter() && selectedTile.getOwner() != worldScreen.civInfo)
defender = CityCombatant(selectedTile.getCity()!!)
else if (selectedTile.unit != null
&& selectedTile.unit!!.owner != worldScreen.civInfo.civName // enemy unit on selected tile,
&& worldScreen.civInfo.getViewableTiles().contains(selectedTile))
defender = MapUnitCombatant(selectedTile.unit!!)
else {
val defender: ICombatant? = Battle().getMapCombatantOfTile(selectedTile)
if(defender==null || defender.getCivilization()==worldScreen.civInfo
|| !attacker.getCivilization().exploredTiles.contains(selectedTile.position)) {
hide()
return
}

View File

@ -93,20 +93,26 @@ class TileMapHolder(internal val worldScreen: WorldScreen, internal val tileMap:
if(worldScreen.bottomBar.unitTable.selectedUnit!=null){
val unit = worldScreen.bottomBar.unitTable.selectedUnit!!
tileGroups[unit.getTile()]!!.addWhiteHaloAroundUnit()
tileGroups[unit.getTile()]!!.addWhiteHaloAroundUnit(unit)
for(tile: TileInfo in unit.getDistanceToTiles().keys)
tileGroups[tile]!!.showCircle(colorFromRGB(0, 120, 215))
val attackableTiles: List<TileInfo> = when(unit.getBaseUnit().unitType){
UnitType.Civilian -> listOf()
UnitType.Civilian -> unit.getDistanceToTiles().keys.toList()
UnitType.Melee, UnitType.Mounted -> unit.getDistanceToTiles().keys.toList()
UnitType.Archery, UnitType.Siege -> unit.getTile().getTilesInDistance(2)
UnitType.City -> throw Exception("A unit shouldn't have a City unittype!")
}
for(tile: TileInfo in unit.getDistanceToTiles().keys)
tileGroups[tile]!!.showCircle(colorFromRGB(0, 120, 215))
for (tile in attackableTiles.filter { it.unit!=null && it.unit!!.owner != unit.owner && civViewableTiles.contains(it)})
tileGroups[tile]!!.showCircle(colorFromRGB(237, 41, 57))
for (tile in attackableTiles.filter {
it.getUnits().isNotEmpty()
&& it.getUnits().first().owner != unit.owner
&& civViewableTiles.contains(it)}) {
if(unit.getBaseUnit().unitType==UnitType.Civilian) tileGroups[tile]!!.hideCircle()
else tileGroups[tile]!!.showCircle(colorFromRGB(237, 41, 57))
}
}
if(selectedTile!=null)

View File

@ -13,7 +13,7 @@ class IdleUnitButton internal constructor(internal val unitTable: UnitTable,
: TextButton(if(previous)"<" else ">", CameraStageBaseScreen.skin) {
fun getTilesWithIdleUnits() = tileMapHolder.tileMap.values
.filter { it.hasIdleUnit() && it.unit!!.owner == unitTable.worldScreen.civInfo.civName }
.filter { it.hasIdleUnit() && it.getUnits().first().owner == unitTable.worldScreen.civInfo.civName }
init {
addClickListener {
val tilesWithIdleUnits = getTilesWithIdleUnits()

View File

@ -2,7 +2,6 @@ package com.unciv.ui.worldscreen.unit
import com.unciv.logic.automation.WorkerAutomation
import com.unciv.logic.map.MapUnit
import com.unciv.logic.map.TileInfo
import com.unciv.logic.map.UnitType
import com.unciv.models.gamebasics.Building
import com.unciv.models.gamebasics.GameBasics
@ -15,10 +14,10 @@ class UnitAction(var name: String, var action:()->Unit, var canAct:Boolean)
class UnitActions {
private fun constructImprovementAndDestroyUnit(tileInfo: TileInfo, improvementName: String): () -> Unit {
private fun constructImprovementAndDestroyUnit(unit:MapUnit, improvementName: String): () -> Unit {
return {
tileInfo.improvement = improvementName
tileInfo.unit = null// destroy!
unit.getTile().improvement = improvementName
unit.removeFromTile()
}
}
@ -56,7 +55,7 @@ class UnitActions {
{
unit.civInfo.gold -= goldCostOfUpgrade
val unitTile = unit.getTile()
unitTile.unit = null
unit.removeFromTile()
val newunit = unit.civInfo.placeUnitNearTile(unitTile.position, upgradedUnit.name)
newunit.health = unit.health
newunit.currentMovement=0f
@ -74,7 +73,7 @@ class UnitActions {
unit.civInfo.addCity(tile.position)
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
tile.unit = null // Remove settler!
unit.removeFromTile()
},
unit.currentMovement != 0f &&
!tile.getTilesInDistance(2).any { it.isCityCenter() })
@ -94,8 +93,8 @@ class UnitActions {
else {
actionList += UnitAction("Automate",
{
tile.unit!!.action = "automation"
WorkerAutomation().automateWorkerAction(tile.unit!!)
unit.action = "automation"
WorkerAutomation().automateWorkerAction(unit)
},unit.currentMovement != 0f
)
}
@ -105,30 +104,30 @@ class UnitActions {
actionList += UnitAction( "Discover Technology",
{
unit.civInfo.tech.freeTechs += 1
tile.unit = null// destroy!
unit.removeFromTile()
worldScreen.game.screen = TechPickerScreen(true, unit.civInfo)
},unit.currentMovement != 0f)
actionList += UnitAction("Construct Academy",
constructImprovementAndDestroyUnit(tile, "Academy"),unit.currentMovement != 0f)
constructImprovementAndDestroyUnit(unit, "Academy"),unit.currentMovement != 0f)
}
if (unit.name == "Great Artist") {
actionList += UnitAction( "Start Golden Age",
{
unit.civInfo.goldenAges.enterGoldenAge()
tile.unit = null// destroy!
unit.removeFromTile()
},unit.currentMovement != 0f
)
actionList += UnitAction("Construct Landmark",
constructImprovementAndDestroyUnit(tile, "Landmark"),unit.currentMovement != 0f)
constructImprovementAndDestroyUnit(unit, "Landmark"),unit.currentMovement != 0f)
}
if (unit.name == "Great Engineer") {
actionList += UnitAction( "Hurry Wonder",
{
tile.getCity()!!.cityConstructions.addConstruction(300 + 30 * tile.getCity()!!.population.population) //http://civilization.wikia.com/wiki/Great_engineer_(Civ5)
tile.unit = null // destroy!
unit.removeFromTile()
},
unit.currentMovement != 0f &&
tile.isCityCenter() &&
@ -136,17 +135,17 @@ class UnitActions {
(tile.getCity()!!.cityConstructions.getCurrentConstruction() as Building).isWonder)
actionList += UnitAction("Construct Manufactory",
constructImprovementAndDestroyUnit(tile, "Manufactory"),unit.currentMovement != 0f)
constructImprovementAndDestroyUnit(unit, "Manufactory"),unit.currentMovement != 0f)
}
if (unit.name == "Great Merchant") {
actionList += UnitAction("Conduct Trade Mission",
{
unit.civInfo.gold += 350 // + 50 * era_number - todo!
tile.unit = null // destroy!
unit.removeFromTile()
},unit.currentMovement != 0f)
actionList += UnitAction( "Construct Customs House",
constructImprovementAndDestroyUnit(tile, "Customs house"),
constructImprovementAndDestroyUnit(unit, "Customs house"),
unit.currentMovement != 0f)
}

View File

@ -73,7 +73,6 @@ class UnitTable(val worldScreen: WorldScreen) : Table(){
fun tileSelected(selectedTile: TileInfo) {
if(currentlyExecutingAction=="moveTo"){
if(selectedUnit!!.movementAlgs()
.getShortestPath(selectedTile).isEmpty())
return // can't reach there with the selected unit, watcha want me to do?
@ -86,8 +85,13 @@ class UnitTable(val worldScreen: WorldScreen) : Table(){
currentlyExecutingAction = null
}
if(selectedTile.unit!=null && selectedTile.unit!!.civInfo == worldScreen.civInfo)
selectedUnit= selectedTile.unit
if(selectedTile.militaryUnit!=null && selectedTile.militaryUnit!!.civInfo == worldScreen.civInfo
&& selectedUnit!=selectedTile.militaryUnit)
selectedUnit = selectedTile.militaryUnit
else if (selectedTile.civilianUnit!=null && selectedTile.civilianUnit!!.civInfo == worldScreen.civInfo
&& selectedUnit!=selectedTile.civilianUnit)
selectedUnit = selectedTile.civilianUnit
}
}