All constructions are now in the queue - no more separate "current construction" and "construction queue" - #2428

That went pretty simply, compared to the magnitude of the change
This commit is contained in:
Yair Morgenstern 2020-04-16 13:01:45 +03:00
parent 3ba20dca52
commit 7d3a10b6ab
12 changed files with 102 additions and 98 deletions

View file

@ -233,10 +233,10 @@ class GameInfo {
// Renames as of version 3.1.8, because of translation conflicts with the property "Range" and the difficulty "Immortal"
// Needs to be BEFORE tileMap.setTransients, because the units' setTransients is called from there
for(tile in tileMap.values)
for(unit in tile.getUnits()){
if(unit.name=="Immortal") unit.name="Persian Immortal"
if(unit.promotions.promotions.contains("Range")){
for (tile in tileMap.values)
for (unit in tile.getUnits()) {
if (unit.name == "Immortal") unit.name = "Persian Immortal"
if (unit.promotions.promotions.contains("Range")) {
unit.promotions.promotions.remove("Range")
unit.promotions.promotions.add("Extended Range")
}
@ -244,8 +244,8 @@ class GameInfo {
tileMap.setTransients(ruleSet)
if(currentPlayer=="") currentPlayer=civilizations.first { it.isPlayerCivilization() }.civName
currentPlayerCiv=getCivilization(currentPlayer)
if (currentPlayer == "") currentPlayer = civilizations.first { it.isPlayerCivilization() }.civName
currentPlayerCiv = getCivilization(currentPlayer)
// this is separated into 2 loops because when we activate updateVisibleTiles in civ.setTransients,
// we try to find new civs, and we check if civ is barbarian, which we can't know unless the gameInfo is already set.
@ -259,7 +259,7 @@ class GameInfo {
// which can fail if there's an "unregistered" building anywhere
for (civInfo in civilizations) {
// As of 3.3.7, Facism -> Fascism
if(civInfo.policies.adoptedPolicies.contains("Facism")){
if (civInfo.policies.adoptedPolicies.contains("Facism")) {
civInfo.policies.adoptedPolicies.remove("Facism")
civInfo.policies.adoptedPolicies.add("Fascism")
}
@ -267,7 +267,7 @@ class GameInfo {
// This doesn't HAVE to go here, but why not.
// As of version 3.1.3, trade offers of "Declare war on X" and "Introduction to X" were changed to X,
// with the extra text being added only on UI display (solved a couple of problems).
for(trade in civInfo.tradeRequests.map { it.trade }) {
for (trade in civInfo.tradeRequests.map { it.trade }) {
for (offer in trade.theirOffers.union(trade.ourOffers)) {
offer.name = offer.name.removePrefix("Declare war on ")
offer.name = offer.name.removePrefix("Introduction to ")
@ -276,15 +276,15 @@ class GameInfo {
// As of 3.4.9 cities are referenced by id, not by name
// So try to update every tradeRequest (if there are no conflicting names)
for(tradeRequest in civInfo.tradeRequests) {
for (tradeRequest in civInfo.tradeRequests) {
val trade = tradeRequest.trade
val toRemove = ArrayList<TradeOffer>()
for (offer in trade.ourOffers) {
if (offer.type == TradeType.City) {
val countNames = civInfo.cities.count { it.name == offer.name}
val countNames = civInfo.cities.count { it.name == offer.name }
if (countNames == 1)
offer.name = civInfo.cities.first { it.name == offer.name}.id
offer.name = civInfo.cities.first { it.name == offer.name }.id
// There are conflicting names: we can't guess what city was being offered
else if (countNames > 1)
toRemove.add(offer)
@ -297,10 +297,10 @@ class GameInfo {
val themCivInfo = getCivilization(tradeRequest.requestingCiv)
for (offer in trade.theirOffers) {
if (offer.type == TradeType.City) {
val countNames = themCivInfo.cities.count { it.name == offer.name}
val countNames = themCivInfo.cities.count { it.name == offer.name }
if (countNames == 1)
offer.name = themCivInfo.cities.first { it.name == offer.name}.id
offer.name = themCivInfo.cities.first { it.name == offer.name }.id
// There are conflicting names: we can't guess what city was being offered
else if (countNames > 1)
toRemove.add(offer)
@ -329,8 +329,8 @@ class GameInfo {
for (civInfo in civilizations) civInfo.setTransients()
for (civInfo in civilizations) civInfo.updateSightAndResources()
for (civInfo in civilizations){
for(unit in civInfo.getCivUnits())
for (civInfo in civilizations) {
for (unit in civInfo.getCivUnits())
unit.updateVisibleTiles() // this needs to be done after all the units are assigned to their civs and all other transients are set
// Since this depends on the cities of ALL civilizations,
@ -339,9 +339,19 @@ class GameInfo {
civInfo.initialSetCitiesConnectedToCapitalTransients()
// We need to determine the GLOBAL happiness state in order to determine the city stats
for(cityInfo in civInfo.cities) cityInfo.cityStats.updateCityHappiness()
for (cityInfo in civInfo.cities) cityInfo.cityStats.updateCityHappiness()
for (cityInfo in civInfo.cities) cityInfo.cityStats.update()
for (cityInfo in civInfo.cities) {
if(cityInfo.cityConstructions.currentConstruction!="") { // move it to the top of the queue
val constructionQueue = cityInfo.cityConstructions.constructionQueue
val itemsInQueue = constructionQueue.toList()
constructionQueue.clear()
constructionQueue.add(cityInfo.cityConstructions.currentConstruction)
constructionQueue.addAll(itemsInQueue)
cityInfo.cityConstructions.currentConstruction = ""
}
cityInfo.cityStats.update()
}
}
}
@ -350,8 +360,7 @@ class GameInfo {
cityConstructions.builtBuildings.remove(oldBuildingName)
cityConstructions.builtBuildings.add(newBuildingName)
}
if (cityConstructions.currentConstruction == oldBuildingName)
cityConstructions.currentConstruction = newBuildingName
cityConstructions.constructionQueue.replaceAll { if(it==oldBuildingName) newBuildingName else it }
if (cityConstructions.inProgressConstructions.containsKey(oldBuildingName)) {
cityConstructions.inProgressConstructions[newBuildingName] = cityConstructions.inProgressConstructions[oldBuildingName]!!
cityConstructions.inProgressConstructions.remove(oldBuildingName)

View file

@ -55,13 +55,13 @@ object Automation {
fun trainMilitaryUnit(city: CityInfo) {
val name = chooseMilitaryUnit(city)
city.cityConstructions.currentConstruction = name
city.cityConstructions.currentConstructionFromQueue = name
}
fun chooseMilitaryUnit(city: CityInfo) : String {
var militaryUnits = city.cityConstructions.getConstructableUnits().filter { !it.unitType.isCivilian() }
if (militaryUnits.map { it.name }.contains(city.cityConstructions.currentConstruction))
return city.cityConstructions.currentConstruction
if (militaryUnits.map { it.name }.contains(city.cityConstructions.currentConstructionFromQueue))
return city.cityConstructions.currentConstructionFromQueue
val findWaterConnectedCitiesAndEnemies = BFS(city.getCenterTile()){it.isWater || it.isCityCenter()}
findWaterConnectedCitiesAndEnemies.stepToEnd()

View file

@ -89,7 +89,7 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){
else theChosenOne = relativeCostEffectiveness.minBy { it.remainingWork }!!.choice
civInfo.addNotification("Work has started on [$theChosenOne]", Color.BROWN, CityAction(cityInfo.location))
cityConstructions.currentConstruction = theChosenOne
cityConstructions.currentConstructionFromQueue = theChosenOne
}
private fun addMilitaryUnitChoice() {

View file

@ -10,7 +10,6 @@ import com.unciv.logic.civilization.diplomacy.DiplomaticStatus
import com.unciv.logic.civilization.diplomacy.RelationshipLevel
import com.unciv.logic.map.MapUnit
import com.unciv.logic.trade.*
import com.unciv.models.metadata.GameSpeed
import com.unciv.models.ruleset.VictoryType
import com.unciv.models.ruleset.tech.Technology
import com.unciv.models.translations.tr
@ -459,11 +458,11 @@ object NextTurnAutomation{
if (civInfo.cities.any()
&& civInfo.getHappiness() > civInfo.cities.size + 5
&& civInfo.getCivUnits().none { it.name == Constants.settler }
&& civInfo.cities.none { it.cityConstructions.currentConstruction == Constants.settler }) {
&& civInfo.cities.none { it.cityConstructions.currentConstructionFromQueue == Constants.settler }) {
val bestCity = civInfo.cities.maxBy { it.cityStats.currentCityStats.production }!!
if (bestCity.cityConstructions.builtBuildings.size > 1) // 2 buildings or more, otherwise focus on self first
bestCity.cityConstructions.currentConstruction = Constants.settler
bestCity.cityConstructions.currentConstructionFromQueue = Constants.settler
}
}

View file

@ -19,8 +19,8 @@ import kotlin.math.roundToInt
* City constructions manager.
*
* @property cityInfo the city it refers to
* @property currentConstruction the name of the construction is currently worked, default = "Monument"
* @property currentConstructionIsUserSet a flag indicating if the [currentConstruction] has been set by the user or by the AI
* @property currentConstructionFromQueue the name of the construction is currently worked, default = "Monument"
* @property currentConstructionIsUserSet a flag indicating if the [currentConstructionFromQueue] has been set by the user or by the AI
* @property constructionQueue a list of constructions names enqueued
*/
class CityConstructions {
@ -29,7 +29,13 @@ class CityConstructions {
var builtBuildings = HashSet<String>()
val inProgressConstructions = HashMap<String, Int>()
var currentConstruction: String = "Monument"
@Deprecated("As of 3.7.5, all constructions are in the queue")
var currentConstruction=""
var currentConstructionFromQueue: String
get() {
if(constructionQueue.isEmpty()) return "" else return constructionQueue.first()
}
set(value) { if(constructionQueue.isEmpty()) constructionQueue.add(value) else constructionQueue[0]=value }
var currentConstructionIsUserSet = false
var constructionQueue = mutableListOf<String>()
val queueMaxSize = 10
@ -39,7 +45,6 @@ class CityConstructions {
val toReturn = CityConstructions()
toReturn.builtBuildings.addAll(builtBuildings)
toReturn.inProgressConstructions.putAll(inProgressConstructions)
toReturn.currentConstruction=currentConstruction
toReturn.currentConstructionIsUserSet=currentConstructionIsUserSet
toReturn.constructionQueue.addAll(constructionQueue)
return toReturn
@ -89,13 +94,13 @@ class CityConstructions {
}
fun getCityProductionTextForCityButton(): String {
val currentConstructionSnapshot = currentConstruction // See below
val currentConstructionSnapshot = currentConstructionFromQueue // See below
var result = currentConstructionSnapshot.tr()
if (currentConstructionSnapshot != "") {
val construction = PerpetualConstruction.perpetualConstructionsMap[currentConstructionSnapshot]
if (construction == null) {
val turnsLeft = turnsToConstruction(currentConstructionSnapshot)
result += ("\r\n" + "Cost".tr() + " " + getConstruction(currentConstruction).getProductionCost(cityInfo.civInfo).toString()).tr()
result += ("\r\n" + "Cost".tr() + " " + getConstruction(currentConstructionFromQueue).getProductionCost(cityInfo.civInfo).toString()).tr()
result += ConstructionInfoTable.turnOrTurns(turnsLeft)
} else {
result += construction.getProductionTooltip(cityInfo)
@ -107,7 +112,7 @@ class CityConstructions {
fun getProductionForTileInfo(): String {
/* this is because there were rare errors tht I assume were caused because
currentContruction changed on another thread */
val currentConstructionSnapshot = currentConstruction
val currentConstructionSnapshot = currentConstructionFromQueue
var result = currentConstructionSnapshot.tr()
if (currentConstructionSnapshot!=""
&& !PerpetualConstruction.perpetualConstructionsMap.containsKey(currentConstructionSnapshot)) {
@ -117,16 +122,14 @@ class CityConstructions {
return result
}
fun getCurrentConstruction(): IConstruction = getConstruction(currentConstruction)
fun getIConstructionQueue(): List<IConstruction> = constructionQueue.map{ getConstruction(it) }
fun getCurrentConstruction(): IConstruction = getConstruction(currentConstructionFromQueue)
fun isBuilt(buildingName: String): Boolean = builtBuildings.contains(buildingName)
fun isBeingConstructed(constructionName: String): Boolean = currentConstruction == constructionName
fun isBeingConstructed(constructionName: String): Boolean = currentConstructionFromQueue == constructionName
fun isEnqueued(constructionName: String): Boolean = constructionQueue.contains(constructionName)
fun isBeingConstructedOrEnqueued(constructionName: String): Boolean = isBeingConstructed(constructionName) || isEnqueued(constructionName)
fun isQueueFull(): Boolean = constructionQueue.size == queueMaxSize
fun isQueueEmpty(): Boolean = constructionQueue.isEmpty()
fun isBuildingWonder(): Boolean {
val currentConstruction = getCurrentConstruction()
@ -135,13 +138,8 @@ class CityConstructions {
/** If the city is constructing multiple units of the same type, subsequent units will require the full cost */
fun isFirstConstructionOfItsKind(constructionQueueIndex: Int, name: String): Boolean {
// idx = 1 is the currentConstruction, so it is the first
if (constructionQueueIndex == -1)
return true
// if the construction name is the same as the current construction, it isn't the first
return !isBeingConstructed(name) &&
constructionQueueIndex == constructionQueue.indexOfFirst{it == name}
return constructionQueueIndex == constructionQueue.indexOfFirst { it == name }
}
@ -150,10 +148,10 @@ class CityConstructions {
when {
gameBasics.buildings.containsKey(constructionName) -> return gameBasics.buildings[constructionName]!!
gameBasics.units.containsKey(constructionName) -> return gameBasics.units[constructionName]!!
constructionName=="" -> return getConstruction("Nothing")
constructionName == "" -> return getConstruction("Nothing")
else -> {
val special = PerpetualConstruction.perpetualConstructionsMap[constructionName]
if(special!=null) return special
if (special != null) return special
}
}
@ -185,19 +183,23 @@ class CityConstructions {
if(workLeft < 0) // we've done more work than actually necessary - possible if circumstances cause buildings to be cheaper later
return 1 // we'll finish this next turn
val currConstruction = currentConstruction
val cityStatsForConstruction: Stats
if (currentConstruction == constructionName) cityStatsForConstruction = cityInfo.cityStats.currentCityStats
if (currentConstructionFromQueue == constructionName) cityStatsForConstruction = cityInfo.cityStats.currentCityStats
else {
// The ol' Switcharoo - what would our stats be if that was our current construction?
// Since this is only ever used for UI purposes, I feel fine with having it be a bit inefficient
// and recalculating the entire city stats
currentConstruction = constructionName
// We don't want to change our current construction queue - what if we have an empty queue, too many changes to check for -
// So we ust clone it and see what would happen f that was our construction
val cityConstructionsClone = clone()
cityConstructionsClone.currentConstructionFromQueue = constructionName
cityConstructionsClone.cityInfo = cityInfo
cityConstructionsClone.setTransients()
cityInfo.cityConstructions = cityConstructionsClone
cityInfo.cityStats.update()
cityStatsForConstruction = cityInfo.cityStats.currentCityStats
// revert!
currentConstruction = currConstruction
cityInfo.cityConstructions = this
cityInfo.cityStats.update()
}
@ -215,19 +217,19 @@ class CityConstructions {
}
fun addProductionPoints(productionToAdd: Int) {
if (!inProgressConstructions.containsKey(currentConstruction)) inProgressConstructions[currentConstruction] = 0
inProgressConstructions[currentConstruction] = inProgressConstructions[currentConstruction]!! + productionToAdd
if (!inProgressConstructions.containsKey(currentConstructionFromQueue)) inProgressConstructions[currentConstructionFromQueue] = 0
inProgressConstructions[currentConstructionFromQueue] = inProgressConstructions[currentConstructionFromQueue]!! + productionToAdd
}
fun constructIfEnough(){
stopUnbuildableConstruction()
val construction = getConstruction(currentConstruction)
val construction = getConstruction(currentConstructionFromQueue)
if(construction is PerpetualConstruction) chooseNextConstruction() // check every turn if we could be doing something better, because this doesn't end by itself
else {
val productionCost = construction.getProductionCost(cityInfo.civInfo)
if (inProgressConstructions.containsKey(currentConstruction)
&& inProgressConstructions[currentConstruction]!! >= productionCost) {
if (inProgressConstructions.containsKey(currentConstructionFromQueue)
&& inProgressConstructions[currentConstructionFromQueue]!! >= productionCost) {
constructionComplete(construction)
cancelCurrentConstruction()
}
@ -238,22 +240,22 @@ class CityConstructions {
stopUnbuildableConstruction()
validateConstructionQueue()
if(getConstruction(currentConstruction) !is PerpetualConstruction)
if(getConstruction(currentConstructionFromQueue) !is PerpetualConstruction)
addProductionPoints(cityStats.production.roundToInt())
}
private fun stopUnbuildableConstruction() {
// Let's try to remove the building from the city, and see if we can still build it (we need to remove because of wonders etc.)
val construction = getConstruction(currentConstruction)
val construction = getConstruction(currentConstructionFromQueue)
val saveCurrentConstruction = currentConstruction
currentConstruction = ""
val saveCurrentConstruction = currentConstructionFromQueue
currentConstructionFromQueue = ""
if (!construction.isBuildable(this)) {
// We can't build this building anymore! (Wonder has been built / resource is gone / etc.)
cityInfo.civInfo.addNotification("[${cityInfo.name}] cannot continue work on [$saveCurrentConstruction]", cityInfo.location, Color.BROWN)
cancelCurrentConstruction()
} else
currentConstruction = saveCurrentConstruction
currentConstructionFromQueue = saveCurrentConstruction
}
private fun validateConstructionQueue() {
@ -266,7 +268,7 @@ class CityConstructions {
}
// remove obsolete stuff from in progress constructions - happens often and leaves clutter in memory and save files
// should have NO visible consequences - any accumulated points that may be reused later should stay (nukes when manhattan project city lost, nat wonder when conquered an empty city...)
val inProgressSnapshot = inProgressConstructions.keys.filter { it != currentConstruction }
val inProgressSnapshot = inProgressConstructions.keys.filter { it != currentConstructionFromQueue }
for (constructionName in inProgressSnapshot) {
val rejectionReason:String =
when (val construction = getConstruction(constructionName)) {
@ -317,7 +319,7 @@ class CityConstructions {
return false // nothing built - no pay
cityInfo.civInfo.gold -= getConstruction(constructionName).getGoldCost(cityInfo.civInfo)
if (currentConstruction == constructionName)
if (currentConstructionFromQueue == constructionName)
cancelCurrentConstruction()
return true
@ -351,7 +353,7 @@ class CityConstructions {
private fun cancelCurrentConstruction() {
currentConstructionIsUserSet = false
currentConstruction = ""
constructionQueue.removeAt(0)
chooseNextConstruction()
}
@ -359,12 +361,10 @@ class CityConstructions {
if(currentConstructionIsUserSet) return
if (constructionQueue.isNotEmpty()) {
currentConstructionIsUserSet = true
currentConstruction = constructionQueue.removeAt(0)
stopUnbuildableConstruction()
if (currentConstruction != "") return
if (currentConstructionFromQueue != "") return
}
ConstructionAutomation(this).chooseNextConstruction()
@ -372,8 +372,8 @@ class CityConstructions {
fun addToQueue(constructionName: String) {
if (isQueueFull()) return
if (isQueueEmpty() && currentConstruction == "" || currentConstruction == "Nothing") {
currentConstruction = constructionName
if (currentConstructionFromQueue == "" || currentConstructionFromQueue == "Nothing") {
currentConstructionFromQueue = constructionName
currentConstructionIsUserSet = true
} else
constructionQueue.add(constructionName)
@ -395,14 +395,8 @@ class CityConstructions {
}
fun raisePriority(constructionQueueIndex: Int) {
// change current construction
if(constructionQueueIndex == 0) {
// Add current construction to queue after the first element
constructionQueue.add(1, currentConstruction)
cancelCurrentConstruction()
}
else
constructionQueue.swap(constructionQueueIndex-1, constructionQueueIndex)
constructionQueue.swap(constructionQueueIndex - 1, constructionQueueIndex)
}
// Lowering == Highering next element in queue

View file

@ -88,7 +88,7 @@ class CityInfo {
if (civInfo.cities.size == 1) {
cityConstructions.addBuilding("Palace")
cityConstructions.currentConstruction = Constants.worker // Default for first city only!
cityConstructions.currentConstructionFromQueue = Constants.worker // Default for first city only!
}
if (civInfo.policies.isAdopted("Legalism"))
@ -213,7 +213,7 @@ class CityInfo {
}
fun isGrowing(): Boolean {
return foodForNextTurn() > 0 && cityConstructions.currentConstruction != Constants.settler
return foodForNextTurn() > 0 && cityConstructions.currentConstructionFromQueue != Constants.settler
}
fun isStarving(): Boolean = foodForNextTurn() < 0

View file

@ -60,7 +60,7 @@ class CityStats {
private fun getStatsFromProduction(production: Float): Stats {
val stats = Stats()
when (cityInfo.cityConstructions.currentConstruction) {
when (cityInfo.cityConstructions.currentConstructionFromQueue) {
"Gold" -> stats.gold += production / 4
"Science" -> {
var scienceProduced = production / 4
@ -476,7 +476,7 @@ class CityStats {
newFinalStatList["Maintenance"] = Stats().apply { gold -= buildingsMaintenance.toInt() }
if (cityInfo.cityConstructions.currentConstruction == Constants.settler && totalFood > 0) {
if (cityInfo.cityConstructions.currentConstructionFromQueue == Constants.settler && totalFood > 0) {
newFinalStatList["Excess food to production"] =
Stats().apply { production=totalFood; food=-totalFood }
}

View file

@ -256,11 +256,12 @@ class TechManager {
}
}
val obsoleteUnits = getRuleset().units.values.filter { it.obsoleteTech == techName }
val obsoleteUnits = getRuleset().units.values.filter { it.obsoleteTech == techName }.map { it.name }
for (city in civInfo.cities)
if (city.cityConstructions.getCurrentConstruction() in obsoleteUnits) {
val currentConstructionUnit = city.cityConstructions.getCurrentConstruction() as BaseUnit
city.cityConstructions.currentConstruction = currentConstructionUnit.upgradesTo!!
for(constructionName in city.cityConstructions.constructionQueue.toList()){ // copy, since we're changing the queue
if(constructionName !in obsoleteUnits) continue
val constructionUnit = city.cityConstructions.getCurrentConstruction() as BaseUnit
city.cityConstructions.constructionQueue.replaceAll { if(it==constructionName) constructionUnit.upgradesTo!! else it }
}
if(techName=="Writing" && civInfo.nation.unique == UniqueAbility.INGENUITY

View file

@ -68,7 +68,7 @@ class CityStatsTable(val cityScreen: CityScreen): Table() {
when {
cityInfo.isGrowing() -> "[${cityInfo.getNumTurnsToNewPopulation()}] turns to new population".tr()
cityInfo.isStarving() -> "[${cityInfo.getNumTurnsToStarvation()}] turns to lose population".tr()
cityInfo.cityConstructions.currentConstruction == Constants.settler -> "Food converts to production".tr()
cityInfo.cityConstructions.currentConstructionFromQueue == Constants.settler -> "Food converts to production".tr()
else -> "Stopped population growth".tr()
}
turnsToPopString += " (" + cityInfo.population.foodStored + "/" + cityInfo.population.getFoodToNextPopulation() + ")"

View file

@ -92,7 +92,7 @@ class ConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBaseScre
private fun updateConstructionQueue() {
val city = cityScreen.city
val cityConstructions = city.cityConstructions
val currentConstruction = cityConstructions.currentConstruction
val currentConstruction = cityConstructions.currentConstructionFromQueue
val queue = cityConstructions.constructionQueue
constructionsQueueTable.defaults().pad(0f)
@ -100,7 +100,7 @@ class ConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBaseScre
constructionsQueueTable.addSeparator()
if (currentConstruction != "")
constructionsQueueTable.add(getQueueEntry(-1, currentConstruction, queue.isEmpty(), isSelectedCurrentConstruction()))
constructionsQueueTable.add(getQueueEntry(0, currentConstruction))
.expandX().fillX().row()
else
constructionsQueueTable.add("Pick a construction".toLabel()).pad(2f).row()
@ -111,7 +111,8 @@ class ConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBaseScre
if (queue.isNotEmpty()) {
queue.forEachIndexed { i, constructionName ->
constructionsQueueTable.add(getQueueEntry(i, constructionName, i == queue.size - 1, i == selectedQueueEntry))
if (i != 0) // This is already displayed as "Current construction"
constructionsQueueTable.add(getQueueEntry(i, constructionName))
.expandX().fillX().row()
if (i != queue.size - 1)
constructionsQueueTable.addSeparator()
@ -171,7 +172,7 @@ class ConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBaseScre
availableConstructionsTable.addCategory("Other", specialConstructions)
}
private fun getQueueEntry(constructionQueueIndex: Int, name: String, isLast: Boolean, isSelected: Boolean): Table {
private fun getQueueEntry(constructionQueueIndex: Int, name: String): Table {
val city = cityScreen.city
val cityConstructions = city.cityConstructions
@ -179,7 +180,7 @@ class ConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBaseScre
table.align(Align.left).pad(5f)
table.background = ImageGetter.getBackground(Color.BLACK)
if (isSelected)
if (constructionQueueIndex == selectedQueueEntry)
table.background = ImageGetter.getBackground(Color.GREEN.cpy().lerp(Color.BLACK, 0.5f))
val isFirstConstructionOfItsKind = cityConstructions.isFirstConstructionOfItsKind(constructionQueueIndex, name)
@ -197,14 +198,15 @@ class ConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBaseScre
table.add(ImageGetter.getConstructionImage(name).surroundWithCircle(40f)).padRight(10f)
table.add(text.toLabel()).expandX().fillX().left()
if (constructionQueueIndex >= 0) table.add(getRaisePriorityButton(constructionQueueIndex, name, city)).right()
if (constructionQueueIndex > 0) table.add(getRaisePriorityButton(constructionQueueIndex, name, city)).right()
else table.add().right()
if (!isLast) table.add(getLowerPriorityButton(constructionQueueIndex, name, city)).right()
if (constructionQueueIndex != cityConstructions.constructionQueue.lastIndex)
table.add(getLowerPriorityButton(constructionQueueIndex, name, city)).right()
else table.add().right()
table.touchable = Touchable.enabled
table.onClick {
cityScreen.selectedConstruction = cityScreen.city.cityConstructions.getConstruction(name)
cityScreen.selectedConstruction = cityConstructions.getConstruction(name)
cityScreen.selectedTile = null
selectedQueueEntry = constructionQueueIndex
cityScreen.update()
@ -256,7 +258,6 @@ class ConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBaseScre
}
private fun isSelectedQueueEntry(): Boolean = selectedQueueEntry > -2
private fun isSelectedCurrentConstruction(): Boolean = selectedQueueEntry == -1
private fun getQueueButton(construction: IConstruction?): TextButton {
val city = cityScreen.city
@ -303,7 +304,7 @@ class ConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBaseScre
val cityConstructions = city.cityConstructions
// We can't trust the isSelectedQueueEntry because that fails when we have the same unit as both the current construction and in the queue,
// and then we purchase the unit from the queue - see #2157
val constructionIsCurrentConstruction = construction.name==cityConstructions.currentConstruction
val constructionIsCurrentConstruction = construction.name==cityConstructions.currentConstructionFromQueue
if (!cityConstructions.purchaseConstruction(construction.name)) {
Popup(cityScreen).apply {

View file

@ -320,7 +320,7 @@ class CityButton(val city: CityInfo, private val tileGroup: WorldTileGroup, skin
val circle = ImageGetter.getCircle()
circle.setSize(25f,25f)
val image = ImageGetter.getConstructionImage(cityConstructions.currentConstruction)
val image = ImageGetter.getConstructionImage(cityConstructions.currentConstructionFromQueue)
image.setSize(18f,18f)
image.centerY(group)
image.x = group.width-image.width

View file

@ -527,10 +527,10 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
}
}
viewingCiv.cities.any { it.cityConstructions.currentConstruction == "" } ->
viewingCiv.cities.any { it.cityConstructions.currentConstructionFromQueue == "" } ->
NextTurnAction("Pick construction", Color.CORAL) {
val cityWithNoProductionSet = viewingCiv.cities
.firstOrNull { it.cityConstructions.currentConstruction == "" }
.firstOrNull { it.cityConstructions.currentConstructionFromQueue == "" }
if (cityWithNoProductionSet != null) game.setScreen(CityScreen(cityWithNoProductionSet))
}