mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-24 03:53:12 -04:00
Added chariot archer - includes adding requiredTech, requiredResource, and uniques to units
This commit is contained in:
parent
8350d000b1
commit
8b748384af
BIN
android/assets/UnitIcons/Chariot Archer.png
Normal file
BIN
android/assets/UnitIcons/Chariot Archer.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.1 KiB |
@ -21,6 +21,7 @@
|
||||
unbuildable:true,
|
||||
unitType:"Melee",
|
||||
strength:5,
|
||||
uniques:["Ignores terrain cost"]
|
||||
movement:2
|
||||
},
|
||||
{
|
||||
@ -42,6 +43,22 @@
|
||||
cost: 40,
|
||||
hurryCostModifier:20
|
||||
},
|
||||
{
|
||||
name:"Chariot Archer",
|
||||
baseDescription: "",
|
||||
unitType:"Ranged",
|
||||
movement:4,
|
||||
strength:6,
|
||||
rangedStrength:10,
|
||||
cost: 56,
|
||||
requiredTech:"The Wheel",
|
||||
requiredResource:"Horses",
|
||||
uniques:["No Defensive Terrain Bonus","Rough Terrain Penalty"],
|
||||
hurryCostModifier:20
|
||||
},
|
||||
|
||||
|
||||
|
||||
{
|
||||
name:"Great Artist",
|
||||
baseDescription: "Can start an 8-turn golden age or construct a Landmark (+6 culture)",
|
||||
|
@ -21,8 +21,8 @@ android {
|
||||
applicationId "com.unciv.game"
|
||||
minSdkVersion 14
|
||||
targetSdkVersion 26
|
||||
versionCode 46
|
||||
versionName "2.0.3"
|
||||
versionCode 47
|
||||
versionName "2.0.4"
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
|
@ -7,11 +7,11 @@ import com.unciv.logic.map.UnitMovementAlgorithms
|
||||
import com.unciv.models.gamebasics.GameBasics
|
||||
import com.unciv.models.gamebasics.TileImprovement
|
||||
|
||||
public class WorkerAutomation(){
|
||||
class WorkerAutomation {
|
||||
|
||||
fun automateWorkerAction(unit: MapUnit) {
|
||||
var tile = unit.getTile()
|
||||
val tileToWork = findTileToWork(tile, unit.civInfo)
|
||||
val tileToWork = findTileToWork(unit)
|
||||
if (tileToWork != tile) {
|
||||
tile = unit.headTowards(tileToWork.position)
|
||||
unit.doPreTurnAction(tile)
|
||||
@ -25,27 +25,28 @@ public class WorkerAutomation(){
|
||||
}
|
||||
}
|
||||
|
||||
private fun findTileToWork(currentTile: TileInfo, civInfo: CivilizationInfo): TileInfo {
|
||||
private fun findTileToWork(worker:MapUnit): TileInfo {
|
||||
val currentTile=worker.getTile()
|
||||
val workableTiles = currentTile.getTilesInDistance(4)
|
||||
.filter {
|
||||
(it.unit == null || it == currentTile)
|
||||
&& it.improvement == null
|
||||
&& it.canBuildImprovement(chooseImprovement(it), civInfo)
|
||||
&& {val city=it.getCity(); city==null || it.getCity()?.civInfo == civInfo}() // don't work tiles belonging to another civ
|
||||
}.sortedByDescending { getPriority(it, civInfo) }.toMutableList()
|
||||
&& 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
|
||||
}.sortedByDescending { getPriority(it, worker.civInfo) }.toMutableList()
|
||||
|
||||
// the tile needs to be actually reachable - more difficult than it seems,
|
||||
// which is why we DON'T calculate this for every possible tile in the radius,
|
||||
// but only for the tile that's about to be chosen.
|
||||
val selectedTile = workableTiles.firstOrNull{
|
||||
UnitMovementAlgorithms(currentTile.tileMap)
|
||||
.getShortestPath(currentTile.position, workableTiles.first().position,2f, 2, civInfo)
|
||||
.getShortestPath(currentTile.position, workableTiles.first().position,worker)
|
||||
.isNotEmpty()}
|
||||
|
||||
if (selectedTile != null
|
||||
&& getPriority(selectedTile, civInfo)>1
|
||||
&& getPriority(selectedTile, worker.civInfo)>1
|
||||
&& (!workableTiles.contains(currentTile)
|
||||
|| getPriority(selectedTile, civInfo) > getPriority(currentTile,civInfo)))
|
||||
|| getPriority(selectedTile, worker.civInfo) > getPriority(currentTile,worker.civInfo)))
|
||||
return selectedTile
|
||||
else return currentTile
|
||||
}
|
||||
|
@ -25,8 +25,10 @@ class Battle(val gameInfo:GameInfo) {
|
||||
|
||||
fun getDefenceModifiers(attacker: ICombatant, defender: ICombatant): HashMap<String, Float> {
|
||||
val modifiers = HashMap<String,Float>()
|
||||
val tileDefenceBonus = defender.getTile().getDefensiveBonus()
|
||||
if(tileDefenceBonus > 0) modifiers["Terrain"] = tileDefenceBonus
|
||||
if(!(defender is MapUnitCombatant && defender.unit.getBaseUnit().hasUnique("No Defensive Terrain Bonus"))){
|
||||
val tileDefenceBonus = defender.getTile().getDefensiveBonus()
|
||||
if (tileDefenceBonus > 0) modifiers["Terrain"] = tileDefenceBonus
|
||||
}
|
||||
return modifiers
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,9 @@ class CityConstructions {
|
||||
internal fun getBuildableBuildings(): List<String> = GameBasics.Buildings.values
|
||||
.filter { it.isBuildable(this) }.map { it.name }
|
||||
|
||||
fun getConstructableUnits() = GameBasics.Units.values
|
||||
.filter { it.isBuildable(this) }.map { it.name }
|
||||
|
||||
// Library and public school unique (not actualy unique, though...hmm)
|
||||
fun getStats(): Stats {
|
||||
val stats = Stats()
|
||||
|
@ -34,7 +34,7 @@ class MapUnit {
|
||||
fun getDistanceToTiles(): HashMap<TileInfo, Float> {
|
||||
val tile = getTile()
|
||||
return UnitMovementAlgorithms(tile.tileMap).getDistanceToTilesWithinTurn(tile.position,currentMovement,
|
||||
civInfo)
|
||||
this)
|
||||
}
|
||||
|
||||
fun doPreTurnAction(tile: TileInfo) {
|
||||
@ -102,7 +102,7 @@ class MapUnit {
|
||||
|
||||
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 = UnitMovementAlgorithms(tileMap)
|
||||
.getShortestPath(currentTile.position, destination, currentMovement, maxMovement, civInfo)
|
||||
.getShortestPath(currentTile.position, destination, this)
|
||||
destinationTileThisTurn = path.first()
|
||||
}
|
||||
|
||||
|
@ -1,38 +1,49 @@
|
||||
package com.unciv.logic.map
|
||||
|
||||
import com.badlogic.gdx.math.Vector2
|
||||
import com.unciv.logic.civilization.CivilizationInfo
|
||||
|
||||
class UnitMovementAlgorithms(val tileMap: TileMap){
|
||||
private fun getMovementCostBetweenAdjacentTiles(from:TileInfo, to:TileInfo, unit:MapUnit): Float {
|
||||
if (from.roadStatus === RoadStatus.Railroad && to.roadStatus === RoadStatus.Railroad)
|
||||
return 1 / 10f
|
||||
|
||||
fun getDistanceToTilesWithinTurn(origin: Vector2, unitMovement:Float, civInfo:CivilizationInfo): HashMap<TileInfo, Float> {
|
||||
if (from.roadStatus !== RoadStatus.None && to.roadStatus !== RoadStatus.None) //Road
|
||||
{
|
||||
if(unit.civInfo.tech.isResearched("Machinery")) return 1/3f
|
||||
else return 1/2f
|
||||
}
|
||||
if(unit.getBaseUnit().hasUnique("Ignores terrain cost")) return 1f;
|
||||
|
||||
if(unit.getBaseUnit().hasUnique("Rough Terrain Penalty")
|
||||
&& (to.baseTerrain=="Hill" || to.terrainFeature=="Forest" || to.terrainFeature=="Jungle"))
|
||||
return 4f
|
||||
|
||||
return to.lastTerrain.movementCost.toFloat() // no road
|
||||
}
|
||||
|
||||
fun getDistanceToTilesWithinTurn(origin: Vector2, unitMovement:Float, unit: MapUnit): HashMap<TileInfo, Float> {
|
||||
val distanceToTiles = HashMap<TileInfo, Float>()
|
||||
val unitTile = tileMap[origin]
|
||||
distanceToTiles[unitTile] = 0f
|
||||
var tilesToCheck = listOf(unitTile)
|
||||
val isMachineryResearched = civInfo.tech.isResearched("Machinery")
|
||||
|
||||
while (!tilesToCheck.isEmpty()) {
|
||||
val updatedTiles = ArrayList<TileInfo>()
|
||||
for (tileToCheck in tilesToCheck)
|
||||
for (maybeUpdatedTile in tileToCheck.neighbors) {
|
||||
if(maybeUpdatedTile.getOwner() != null && maybeUpdatedTile.getOwner() != civInfo && maybeUpdatedTile.isCityCenter())
|
||||
for (neighbor in tileToCheck.neighbors) {
|
||||
if(neighbor.getOwner() != null && neighbor.getOwner() != unit.civInfo
|
||||
&& neighbor.isCityCenter())
|
||||
continue // Enemy city, can't move through it!
|
||||
|
||||
var distanceBetweenTiles = maybeUpdatedTile.lastTerrain.movementCost.toFloat() // no road
|
||||
if (tileToCheck.roadStatus !== RoadStatus.None && maybeUpdatedTile.roadStatus !== RoadStatus.None) //Road
|
||||
distanceBetweenTiles = if (isMachineryResearched) 1 / 3f else 1 / 2f
|
||||
|
||||
if (tileToCheck.roadStatus === RoadStatus.Railroad && maybeUpdatedTile.roadStatus === RoadStatus.Railroad) // Railroad
|
||||
distanceBetweenTiles = 1 / 10f
|
||||
var distanceBetweenTiles = getMovementCostBetweenAdjacentTiles(tileToCheck,neighbor,unit)
|
||||
|
||||
var totalDistanceToTile = distanceToTiles[tileToCheck]!! + distanceBetweenTiles
|
||||
if (!distanceToTiles.containsKey(maybeUpdatedTile) || distanceToTiles[maybeUpdatedTile]!! > totalDistanceToTile) {
|
||||
if (!distanceToTiles.containsKey(neighbor) || distanceToTiles[neighbor]!! > totalDistanceToTile) {
|
||||
if (totalDistanceToTile < unitMovement)
|
||||
updatedTiles += maybeUpdatedTile
|
||||
updatedTiles += neighbor
|
||||
else
|
||||
totalDistanceToTile = unitMovement
|
||||
distanceToTiles[maybeUpdatedTile] = totalDistanceToTile
|
||||
distanceToTiles[neighbor] = totalDistanceToTile
|
||||
}
|
||||
}
|
||||
|
||||
@ -42,8 +53,7 @@ class UnitMovementAlgorithms(val tileMap: TileMap){
|
||||
return distanceToTiles
|
||||
}
|
||||
|
||||
|
||||
fun getShortestPath(origin: Vector2, destination: Vector2, currentMovement: Float, maxMovement: Int, civInfo: CivilizationInfo): List<TileInfo> {
|
||||
fun getShortestPath(origin: Vector2, destination: Vector2, unit:MapUnit): List<TileInfo> {
|
||||
if(origin.equals(destination)) return listOf(tileMap[origin]) // edge case that's needed, so that workers will know that they can reach their own tile. *sig
|
||||
|
||||
var tilesToCheck: List<TileInfo> = listOf(tileMap[origin])
|
||||
@ -54,9 +64,9 @@ class UnitMovementAlgorithms(val tileMap: TileMap){
|
||||
while (true) {
|
||||
val newTilesToCheck = ArrayList<TileInfo>()
|
||||
val distanceToDestination = HashMap<TileInfo, Float>()
|
||||
val movementThisTurn = if (distance == 1) currentMovement else maxMovement.toFloat()
|
||||
val movementThisTurn = if (distance == 1) unit.currentMovement else unit.maxMovement.toFloat()
|
||||
for (tileToCheck in tilesToCheck) {
|
||||
val distanceToTilesThisTurn = getDistanceToTilesWithinTurn(tileToCheck.position, movementThisTurn, civInfo)
|
||||
val distanceToTilesThisTurn = getDistanceToTilesWithinTurn(tileToCheck.position, movementThisTurn, unit)
|
||||
for (reachableTile in distanceToTilesThisTurn.keys) {
|
||||
if(reachableTile.position == destination)
|
||||
distanceToDestination[tileToCheck] = distanceToTilesThisTurn[reachableTile]!!
|
||||
|
@ -28,6 +28,8 @@ class Unit : INamed, IConstruction, ICivilopedia {
|
||||
lateinit var unitType: UnitType
|
||||
internal var unbuildable: Boolean = false // for special units like great people
|
||||
var requiredTech:String? = null
|
||||
var requiredResource:String? = null
|
||||
var uniques:HashSet<String>?=null
|
||||
|
||||
fun getMapUnit(): MapUnit {
|
||||
val unit = MapUnit()
|
||||
@ -37,6 +39,7 @@ class Unit : INamed, IConstruction, ICivilopedia {
|
||||
return unit
|
||||
}
|
||||
|
||||
fun hasUnique(unique:String) = uniques!=null && uniques!!.contains(unique)
|
||||
|
||||
override fun getProductionCost(adoptedPolicies: HashSet<String>): Int = cost
|
||||
|
||||
@ -45,7 +48,11 @@ class Unit : INamed, IConstruction, ICivilopedia {
|
||||
}
|
||||
|
||||
override fun isBuildable(construction: CityConstructions): Boolean {
|
||||
return !unbuildable
|
||||
val civInfo = construction.cityInfo.civInfo
|
||||
if (unbuildable) return false
|
||||
if (requiredTech!=null && !civInfo.tech.isResearched(requiredTech!!)) return false
|
||||
if (requiredResource!=null && !civInfo.getCivResources().keys.any { it.name == requiredResource }) return false
|
||||
return true
|
||||
}
|
||||
|
||||
override fun postBuildEvent(construction: CityConstructions) {
|
||||
|
@ -18,6 +18,7 @@ class BattleTable(val worldScreen: WorldScreen): Table() {
|
||||
private val battle = Battle(worldScreen.civInfo.gameInfo)
|
||||
init{
|
||||
skin = CameraStageBaseScreen.skin
|
||||
pad(10f)
|
||||
}
|
||||
|
||||
fun hide(){
|
||||
@ -157,7 +158,7 @@ class BattleTable(val worldScreen: WorldScreen): Table() {
|
||||
pack()
|
||||
|
||||
val tileTableBackground = ImageGetter.getDrawable("skin/tileTableBackground.png")
|
||||
.tint(Color(0x004085bf))
|
||||
.tint(Color(0x004085ff))
|
||||
tileTableBackground.minHeight = 0f
|
||||
tileTableBackground.minWidth = 0f
|
||||
background = tileTableBackground
|
||||
|
@ -31,12 +31,8 @@ class UnitActions {
|
||||
}
|
||||
|
||||
fun getUnitActions(unit:MapUnit,worldScreen: WorldScreen): List<UnitAction> {
|
||||
|
||||
val tile = unit.getTile()
|
||||
|
||||
val tileMapHolder = worldScreen.tileMapHolder
|
||||
val unitTable = worldScreen.unitTable
|
||||
|
||||
val actionList = ArrayList<UnitAction>()
|
||||
|
||||
if (unitTable.currentlyExecutingAction != "moveTo"
|
||||
@ -51,7 +47,7 @@ class UnitActions {
|
||||
UnitAction("Stop movement", {
|
||||
unitTable.currentlyExecutingAction = null
|
||||
unit.action=null
|
||||
},unit.currentMovement != 0f)
|
||||
},true)
|
||||
}
|
||||
|
||||
if (unit.name == "Settler") {
|
||||
@ -78,7 +74,7 @@ class UnitActions {
|
||||
|
||||
if("automation" == unit.action){
|
||||
actionList += UnitAction("Stop automation",
|
||||
{unit.action = null},unit.currentMovement != 0f)
|
||||
{unit.action = null},true)
|
||||
}
|
||||
else {
|
||||
actionList += UnitAction("Automate",
|
||||
|
Loading…
x
Reference in New Issue
Block a user