WIP Construction Queue (#1648)

* Construction Queue

* Added constructionQueue in addition to currentConstruction: if currentConstruction is done, next construction from Queue is started; if Queue is empty invoke ConstructionAutomation
* Queue utility methods: add, remove, higher prio, lower prio
* Icons to move constructions in queue
* Top left city stats moved to top right panel
* Added current construction and queue construction to top left
* Extended selected construction (containing description) moved to bottom right, it is now displayed alternatively to selected tile
* Max queue size, cannot change queue in puppet city or in other player turn
* Queue and current construction reset on puppeting city

* Cleanup again

* CityStatsTable is a separate class so we can play around with where it's located with minimal code changes

* Rejection reason wrap & removing nothing on enqueue a construction

* Crude UI proposal

* Tutorial updates for queues

Co-authored-by: Yair Morgenstern <yairm210@hotmail.com>
This commit is contained in:
r3versi 2020-01-10 10:41:43 +01:00 committed by Yair Morgenstern
parent 12a98aa4bb
commit 2daf27278d
11 changed files with 625 additions and 550 deletions

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 884 KiB

After

Width:  |  Height:  |  Size: 885 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 309 KiB

After

Width:  |  Height:  |  Size: 317 KiB

View File

@ -5,7 +5,7 @@ Move a unit!\nClick on a unit > Click on a destination > Click the arrow popup =
Found a city!\nSelect the Settler (flag unit) > Click on 'Found city' (bottom-left corner) = Found a city!\nSelect the Settler (flag unit) > Click on 'Found city' (bottom-left corner) =
Enter the city screen!\nClick the city button twice = Enter the city screen!\nClick the city button twice =
Pick a technology to research!\nClick on the tech button (greenish, top left) > \n select technology > click 'Research' (bottom right) = Pick a technology to research!\nClick on the tech button (greenish, top left) > \n select technology > click 'Research' (bottom right) =
Pick a construction!\nEnter city screen > Click on a unit or building (left side) = Pick a construction!\nEnter city screen > Click on a unit or building (bottom left side) > \n click 'add to queue' =
Pass a turn!\nCycle through units with 'Next unit' > Click 'Next turn' = Pass a turn!\nCycle through units with 'Next unit' > Click 'Next turn' =
Reassign worked tiles!\nEnter city screen > click the assigned (green) tile to unassign > \n click an unassigned tile to assign population = Reassign worked tiles!\nEnter city screen > click the assigned (green) tile to unassign > \n click an unassigned tile to assign population =
Meet another civilization!\nExplore the map until you encounter another civilization! = Meet another civilization!\nExplore the map until you encounter another civilization! =

View File

@ -37,7 +37,7 @@ class UncivGame(
/** For when you need to test something in an advanced game and don't have time to faff around */ /** For when you need to test something in an advanced game and don't have time to faff around */
val superchargedForDebug = false val superchargedForDebug = false
var rewriteTranslationFiles = true var rewriteTranslationFiles = false
lateinit var worldScreen: WorldScreen lateinit var worldScreen: WorldScreen

View File

@ -107,6 +107,7 @@ class CityConstructions {
fun isEnqueued(constructionName: String): Boolean = constructionQueue.contains(constructionName) fun isEnqueued(constructionName: String): Boolean = constructionQueue.contains(constructionName)
fun isQueueFull(): Boolean = constructionQueue.size == queueMaxSize fun isQueueFull(): Boolean = constructionQueue.size == queueMaxSize
fun isQueueEmpty(): Boolean = constructionQueue.isEmpty()
fun isBuildingWonder(): Boolean { fun isBuildingWonder(): Boolean {
val currentConstruction = getCurrentConstruction() val currentConstruction = getCurrentConstruction()
@ -309,8 +310,13 @@ class CityConstructions {
} }
fun addToQueue(constructionName: String) { fun addToQueue(constructionName: String) {
if (!isQueueFull()) if (!isQueueFull()) {
constructionQueue.add(constructionName) if (isQueueEmpty() && currentConstruction == "Nothing") {
currentConstruction = constructionName
currentConstructionIsUserSet = true
} else
constructionQueue.add(constructionName)
}
} }
fun removeFromQueue(idx: Int) { fun removeFromQueue(idx: Int) {

View File

@ -2,47 +2,57 @@ package com.unciv.ui.cityscreen
import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.scenes.scene2d.Touchable import com.badlogic.gdx.scenes.scene2d.Touchable
import com.badlogic.gdx.scenes.scene2d.ui.Image import com.badlogic.gdx.scenes.scene2d.ui.*
import com.badlogic.gdx.scenes.scene2d.ui.Skin
import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.badlogic.gdx.scenes.scene2d.ui.TextButton
import com.badlogic.gdx.scenes.scene2d.ui.Label
import com.badlogic.gdx.utils.Align import com.badlogic.gdx.utils.Align
import com.unciv.Constants
import com.unciv.UncivGame import com.unciv.UncivGame
import com.unciv.logic.city.CityInfo import com.unciv.logic.city.CityInfo
import com.unciv.logic.civilization.GreatPersonManager import com.unciv.logic.civilization.GreatPersonManager
import com.unciv.models.ruleset.Building import com.unciv.models.ruleset.Building
import com.unciv.models.translations.tr
import com.unciv.models.stats.Stat import com.unciv.models.stats.Stat
import com.unciv.models.stats.Stats import com.unciv.models.translations.tr
import com.unciv.ui.utils.* import com.unciv.ui.utils.*
import com.unciv.ui.worldscreen.optionstable.YesNoPopupTable import com.unciv.ui.worldscreen.optionstable.YesNoPopupTable
import java.text.DecimalFormat import java.text.DecimalFormat
import kotlin.math.ceil
import kotlin.math.floor
import kotlin.math.round
class CityInfoTable(private val cityScreen: CityScreen) : Table(CameraStageBaseScreen.skin) { class CityInfoTable(private val cityScreen: CityScreen) : Table(CameraStageBaseScreen.skin) {
val pad = 5f private val pad = 10f
private val showConstructionsTableButton = TextButton("Show construction queue", skin)
private val cityInfoScrollPane: ScrollPane
private val cityInfoTable = Table(skin)
init { init {
defaults().pad(pad) showConstructionsTableButton.onClick {
width = cityScreen.stage.width/4 cityScreen.showConstructionsTable = true
cityScreen.update()
}
cityInfoTable.width = cityScreen.stage.width/4
cityInfoTable.background = ImageGetter.getBackground(ImageGetter.getBlue().lerp(Color.BLACK,0.5f))
cityInfoScrollPane = ScrollPane(cityInfoTable.addBorder(2f, Color.WHITE))
cityInfoScrollPane.setOverscroll(false, false)
add(showConstructionsTableButton).left().padLeft(pad).padBottom(pad).row()
add(cityInfoScrollPane).left().row()
} }
internal fun update() { internal fun update() {
clear()
val cityInfo = cityScreen.city val cityInfo = cityScreen.city
addCityStats(cityInfo) cityInfoTable.clear()
addBuildingsInfo(cityInfo)
addStatInfo()
addGreatPersonPointInfo(cityInfo)
//TODO: Sorry, this is a hack, i'm getting tired and needed some content to test the idea
cityInfoTable.apply {
addBuildingsInfo(cityInfo)
addStatInfo()
addGreatPersonPointInfo(cityInfo)
}
getCell(cityInfoScrollPane).maxHeight(stage.height - showConstructionsTableButton.height - pad - 10f)
pack() pack()
} }
private fun addCategory(str: String, showHideTable: Table) { private fun Table.addCategory(str: String, showHideTable: Table) {
val titleTable = Table().background(ImageGetter.getBackground(ImageGetter.getBlue())) val titleTable = Table().background(ImageGetter.getBackground(ImageGetter.getBlue()))
val width = cityScreen.stage.width/4 - 2*pad val width = cityScreen.stage.width/4 - 2*pad
val showHideTableWrapper = Table() val showHideTableWrapper = Table()
@ -56,7 +66,7 @@ class CityInfoTable(private val cityScreen: CityScreen) : Table(CameraStageBaseS
add(showHideTableWrapper).row() add(showHideTableWrapper).row()
} }
fun addBuildingInfo(building: Building, wondersTable: Table){ private fun Table.addBuildingInfo(building: Building, wondersTable: Table){
val wonderNameAndIconTable = Table() val wonderNameAndIconTable = Table()
wonderNameAndIconTable.touchable = Touchable.enabled wonderNameAndIconTable.touchable = Touchable.enabled
wonderNameAndIconTable.add(ImageGetter.getConstructionImage(building.name).surroundWithCircle(30f)) wonderNameAndIconTable.add(ImageGetter.getConstructionImage(building.name).surroundWithCircle(30f))
@ -96,66 +106,7 @@ class CityInfoTable(private val cityScreen: CityScreen) : Table(CameraStageBaseS
} }
} }
private fun addCityStats(cityInfo: CityInfo) { private fun Table.addBuildingsInfo(cityInfo: CityInfo) {
val statsTable = Table().align(Align.center)
addCategory("Stats", statsTable)
val columns = Stats().toHashMap().size
statsTable.add(Label("{Unassigned population}:".tr()
+" "+cityInfo.population.getFreePopulation().toString() + "/" + cityInfo.population.population, skin))
.pad(5f).row()
val turnsToExpansionString : String
if (cityInfo.cityStats.currentCityStats.culture > 0) {
var turnsToExpansion = ceil((cityInfo.expansion.getCultureToNextTile() - cityInfo.expansion.cultureStored)
/ cityInfo.cityStats.currentCityStats.culture).toInt()
if (turnsToExpansion < 1) turnsToExpansion = 1
turnsToExpansionString = "[$turnsToExpansion] turns to expansion".tr()
} else {
turnsToExpansionString = "Stopped expansion".tr()
}
statsTable.add(Label(turnsToExpansionString + " (" + cityInfo.expansion.cultureStored + "/" + cityInfo.expansion.getCultureToNextTile() + ")",
skin)).pad(5f).row()
val turnsToPopString : String
if (cityInfo.cityStats.currentCityStats.food > 0) {
if (cityInfo.cityConstructions.currentConstruction == Constants.settler) {
turnsToPopString = "Food converts to production".tr()
} else {
var turnsToPopulation = ceil((cityInfo.population.getFoodToNextPopulation()-cityInfo.population.foodStored)
/ cityInfo.cityStats.currentCityStats.food).toInt()
if (turnsToPopulation < 1) turnsToPopulation = 1
turnsToPopString = "[$turnsToPopulation] turns to new population".tr()
}
} else if (cityInfo.cityStats.currentCityStats.food < 0) {
val turnsToStarvation = floor(cityInfo.population.foodStored / -cityInfo.cityStats.currentCityStats.food).toInt() + 1
turnsToPopString = "[$turnsToStarvation] turns to lose population".tr()
} else {
turnsToPopString = "Stopped population growth".tr()
}
statsTable.add(Label(turnsToPopString + " (" + cityInfo.population.foodStored + "/" + cityInfo.population.getFoodToNextPopulation() + ")"
,skin)).pad(5f).row()
if (cityInfo.resistanceCounter > 0) {
statsTable.add(Label("In resistance for another [${cityInfo.resistanceCounter}] turns".tr(),skin)).pad(5f).row()
}
statsTable.addSeparator()
val ministatsTable = Table().pad(5f)
ministatsTable.defaults()
statsTable.add(ministatsTable)
for(stat in cityInfo.cityStats.currentCityStats.toHashMap()) {
if(stat.key == Stat.Happiness) continue
ministatsTable.add(ImageGetter.getStatIcon(stat.key.name)).size(20f).padRight(3f)
ministatsTable.add(round(stat.value).toInt().toString().toLabel()).padRight(13f)
}
}
private fun addBuildingsInfo(cityInfo: CityInfo) {
val wonders = mutableListOf<Building>() val wonders = mutableListOf<Building>()
val specialistBuildings = mutableListOf<Building>() val specialistBuildings = mutableListOf<Building>()
val otherBuildings = mutableListOf<Building>() val otherBuildings = mutableListOf<Building>()
@ -200,7 +151,7 @@ class CityInfoTable(private val cityScreen: CityScreen) : Table(CameraStageBaseS
} }
} }
private fun addStatInfo() { private fun Table.addStatInfo() {
val cityStats = cityScreen.city.cityStats val cityStats = cityScreen.city.cityStats
for(stat in Stat.values().filter { it!=Stat.Happiness }){ for(stat in Stat.values().filter { it!=Stat.Happiness }){
@ -257,7 +208,7 @@ class CityInfoTable(private val cityScreen: CityScreen) : Table(CameraStageBaseS
} }
} }
private fun addGreatPersonPointInfo(cityInfo: CityInfo) { private fun Table.addGreatPersonPointInfo(cityInfo: CityInfo) {
val greatPersonPoints = cityInfo.getGreatPersonMap() val greatPersonPoints = cityInfo.getGreatPersonMap()
val statToGreatPerson = GreatPersonManager().statToGreatPersonMapping val statToGreatPerson = GreatPersonManager().statToGreatPersonMapping
for (stat in Stat.values()) { for (stat in Stat.values()) {
@ -276,7 +227,7 @@ class CityInfoTable(private val cityScreen: CityScreen) : Table(CameraStageBaseS
} }
} }
private fun addSpecialistAllocation(skin: Skin, cityInfo: CityInfo) { private fun Table.addSpecialistAllocation(skin: Skin, cityInfo: CityInfo) {
val specialistAllocationTable = Table() val specialistAllocationTable = Table()
addCategory("Specialist Allocation", specialistAllocationTable) // todo WRONG, BAD - table should contain all the below specialist stuff addCategory("Specialist Allocation", specialistAllocationTable) // todo WRONG, BAD - table should contain all the below specialist stuff
@ -346,5 +297,4 @@ class CityInfoTable(private val cityScreen: CityScreen) : Table(CameraStageBaseS
return specialist return specialist
} }
} }

View File

@ -16,23 +16,26 @@ import com.unciv.ui.map.TileGroupMap
import com.unciv.ui.tilegroups.TileSetStrings import com.unciv.ui.tilegroups.TileSetStrings
import com.unciv.ui.utils.* import com.unciv.ui.utils.*
import java.util.* import java.util.*
import kotlin.math.ceil
import kotlin.math.round
class CityScreen(internal val city: CityInfo): CameraStageBaseScreen() { class CityScreen(internal val city: CityInfo): CameraStageBaseScreen() {
var selectedTile: TileInfo? = null var selectedTile: TileInfo? = null
var selectedConstruction: IConstruction? = null var selectedConstruction: IConstruction? = null
/** Toggle between Constructions and cityInfo (buildings, specialists etc. */
var showConstructionsTable = true
// Clockwise from the top-left // Clockwise from the top-left
/** Displays current production, production queue and available productions list - sits on LEFT */ /** Displays current production, production queue and available productions list - sits on LEFT */
private var constructionsTable = ConstructionsTable(this) private var constructionsTable = ConstructionsTable(this)
/** Displays stats, buildings, specialists and stats drilldown - sits on TOP RIGHT */
private var cityInfoTable = CityInfoTable(this)
/** Displays raze city button - sits on TOP CENTER */ /** Displays raze city button - sits on TOP CENTER */
private var razeCityButtonHolder = Table() private var razeCityButtonHolder = Table()
/** Displays stats, buildings, specialists and stats drilldown - sits on TOP RIGHT */ /** Displays city stats info */
private var cityInfoTable = CityInfoTable(this) private var cityStatsTable = CityStatsTable(this.city)
/** Displays tile info, alternate with selectedConstructionTable - sits on BOTTOM RIGHT */ /** Displays tile info, alternate with selectedConstructionTable - sits on BOTTOM RIGHT */
private var tileTable = CityScreenTileTable(city) private var tileTable = CityScreenTileTable(city)
@ -49,34 +52,36 @@ class CityScreen(internal val city: CityInfo): CameraStageBaseScreen() {
init { init {
onBackButtonClicked { game.setWorldScreen() } onBackButtonClicked { game.setWorldScreen() }
UncivGame.Current.settings.addCompletedTutorialTask("Enter city screen") UncivGame.Current.settings.addCompletedTutorialTask("Enter city screen")
addTiles() addTiles()
var buildingsTableContainer = Table()
buildingsTableContainer.pad(3f)
buildingsTableContainer.background = ImageGetter.getBackground(ImageGetter.getBlue().lerp(Color.BLACK,0.5f))
cityInfoTable.update()
val buildingsScroll = ScrollPane(cityInfoTable)
buildingsTableContainer.add(buildingsScroll).size(stage.width/4,stage.height / 2)
buildingsTableContainer = buildingsTableContainer.addBorder(2f, Color.WHITE)
buildingsTableContainer.setPosition( stage.width - 5f, stage.height - 5f, Align.topRight)
//stage.setDebugTableUnderMouse(true) //stage.setDebugTableUnderMouse(true)
stage.addActor(cityStatsTable)
stage.addActor(constructionsTable) stage.addActor(constructionsTable)
stage.addActor(tileTable) stage.addActor(tileTable)
stage.addActor(selectedConstructionTable) stage.addActor(selectedConstructionTable)
stage.addActor(cityPickerTable) stage.addActor(cityPickerTable)
stage.addActor(buildingsTableContainer) stage.addActor(cityInfoTable)
update() update()
} }
internal fun update() { internal fun update() {
if (showConstructionsTable) {
constructionsTable.isVisible = true
cityInfoTable.isVisible = false
} else {
constructionsTable.isVisible = false
cityInfoTable.isVisible = true
}
city.cityStats.update() city.cityStats.update()
constructionsTable.update(selectedConstruction) constructionsTable.update(selectedConstruction)
constructionsTable.setPosition(5f, stage.height - 5f, Align.topLeft) constructionsTable.setPosition(5f, stage.height - 5f, Align.topLeft)
cityInfoTable.update()
cityInfoTable.setPosition(5f, stage.height - 5f, Align.topLeft)
cityPickerTable.update() cityPickerTable.update()
cityPickerTable.centerX(stage) cityPickerTable.centerX(stage)
@ -86,7 +91,8 @@ class CityScreen(internal val city: CityInfo): CameraStageBaseScreen() {
selectedConstructionTable.update(selectedConstruction) selectedConstructionTable.update(selectedConstruction)
selectedConstructionTable.setPosition(stage.width - 5f, 5f, Align.bottomRight) selectedConstructionTable.setPosition(stage.width - 5f, 5f, Align.bottomRight)
cityInfoTable.update() cityStatsTable.update()
cityStatsTable.setPosition( stage.width - 5f, stage.height - 5f, Align.topRight)
updateAnnexAndRazeCityButton() updateAnnexAndRazeCityButton()
updateTileGroups() updateTileGroups()

View File

@ -0,0 +1,76 @@
package com.unciv.ui.cityscreen
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.unciv.Constants
import com.unciv.logic.city.CityInfo
import com.unciv.models.stats.Stat
import com.unciv.models.translations.tr
import com.unciv.ui.utils.ImageGetter
import com.unciv.ui.utils.addSeparator
import com.unciv.ui.utils.colorFromRGB
import com.unciv.ui.utils.toLabel
import kotlin.math.ceil
import kotlin.math.round
class CityStatsTable(val cityInfo: CityInfo): Table() {
private val innerTable = Table()
init {
pad(2f)
background = ImageGetter.getBackground(colorFromRGB(194,180,131))
innerTable.pad(5f)
innerTable.defaults().pad(5f)
innerTable.background = ImageGetter.getBackground(Color.BLACK.cpy().apply { a=0.8f })
add(innerTable).fill()
}
fun update() {
innerTable.clear()
val unassignedPopString = "{Unassigned population}:".tr()+
" "+cityInfo.population.getFreePopulation().toString() + "/" + cityInfo.population.population
var turnsToExpansionString =
if (cityInfo.cityStats.currentCityStats.culture > 0) {
val remainingCulture = cityInfo.expansion.getCultureToNextTile() - cityInfo.expansion.cultureStored
var turnsToExpansion = ceil(remainingCulture / cityInfo.cityStats.currentCityStats.culture).toInt()
if (turnsToExpansion < 1) turnsToExpansion = 1
"[$turnsToExpansion] turns to expansion".tr()
} else {
"Stopped expansion".tr()
}
turnsToExpansionString += " (" + cityInfo.expansion.cultureStored + "/" +
cityInfo.expansion.getCultureToNextTile() + ")"
var turnsToPopString =
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()
else -> "Stopped population growth".tr()
}
turnsToPopString += " (" + cityInfo.population.foodStored + "/" + cityInfo.population.getFoodToNextPopulation() + ")"
val ministatsTable = Table().pad(5f)
ministatsTable.defaults()
for(stat in cityInfo.cityStats.currentCityStats.toHashMap()) {
if(stat.key == Stat.Happiness) continue
ministatsTable.add(ImageGetter.getStatIcon(stat.key.name)).size(20f).padRight(3f)
ministatsTable.add(round(stat.value).toInt().toString().toLabel()).padRight(13f)
}
innerTable.add(unassignedPopString.toLabel()).row()
innerTable.add(turnsToExpansionString.toLabel()).row()
innerTable.add(turnsToPopString.toLabel()).row()
if (cityInfo.isInResistance())
innerTable.add("In resistance for another [${cityInfo.resistanceCounter}] turns".toLabel()).row()
innerTable.addSeparator()
innerTable.add(ministatsTable)
pack()
}
}

View File

@ -2,17 +2,17 @@ package com.unciv.ui.cityscreen
import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.scenes.scene2d.Touchable import com.badlogic.gdx.scenes.scene2d.Touchable
import com.badlogic.gdx.scenes.scene2d.ui.* import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane
import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.badlogic.gdx.scenes.scene2d.ui.TextButton
import com.badlogic.gdx.utils.Align import com.badlogic.gdx.utils.Align
import com.unciv.UncivGame import com.unciv.UncivGame
import com.unciv.logic.city.CityInfo import com.unciv.logic.city.CityInfo
import com.unciv.logic.city.IConstruction import com.unciv.logic.city.IConstruction
import com.unciv.logic.city.SpecialConstruction import com.unciv.logic.city.SpecialConstruction
import com.unciv.models.UncivSound import com.unciv.models.UncivSound
import com.unciv.models.ruleset.Building
import com.unciv.models.ruleset.unit.BaseUnit
import com.unciv.models.translations.tr
import com.unciv.models.stats.Stat import com.unciv.models.stats.Stat
import com.unciv.models.translations.tr
import com.unciv.ui.utils.* import com.unciv.ui.utils.*
import com.unciv.ui.worldscreen.optionstable.YesNoPopupTable import com.unciv.ui.worldscreen.optionstable.YesNoPopupTable
@ -20,6 +20,7 @@ class ConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBaseScre
/* -2 = Nothing, -1 = current construction, >= 0 queue entry */ /* -2 = Nothing, -1 = current construction, >= 0 queue entry */
private var selectedQueueEntry = -2 // None private var selectedQueueEntry = -2 // None
private val showCityInfoTableButton: TextButton
private val constructionsQueueScrollPane: ScrollPane private val constructionsQueueScrollPane: ScrollPane
private val availableConstructionsScrollPane: ScrollPane private val availableConstructionsScrollPane: ScrollPane
@ -30,12 +31,21 @@ class ConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBaseScre
private val pad = 10f private val pad = 10f
init { init {
showCityInfoTableButton = TextButton("Show stats drilldown", skin)
showCityInfoTableButton.onClick {
cityScreen.showConstructionsTable = false
cityScreen.update()
}
constructionsQueueScrollPane = ScrollPane(constructionsQueueTable.addBorder(2f, Color.WHITE)) constructionsQueueScrollPane = ScrollPane(constructionsQueueTable.addBorder(2f, Color.WHITE))
constructionsQueueScrollPane.setOverscroll(false,false)
availableConstructionsScrollPane = ScrollPane(availableConstructionsTable.addBorder(2f, Color.WHITE)) availableConstructionsScrollPane = ScrollPane(availableConstructionsTable.addBorder(2f, Color.WHITE))
availableConstructionsScrollPane.setOverscroll(false,false)
constructionsQueueTable.background = ImageGetter.getBackground(Color.BLACK) constructionsQueueTable.background = ImageGetter.getBackground(Color.BLACK)
availableConstructionsTable.background = ImageGetter.getBackground(Color.BLACK) availableConstructionsTable.background = ImageGetter.getBackground(Color.BLACK)
add(showCityInfoTableButton).left().padLeft(pad).padBottom(pad).row()
add(constructionsQueueScrollPane).left().padBottom(pad).row() add(constructionsQueueScrollPane).left().padBottom(pad).row()
add(buttons).center().bottom().padBottom(pad).row() add(buttons).center().bottom().padBottom(pad).row()
add(availableConstructionsScrollPane).left().bottom().row() add(availableConstructionsScrollPane).left().bottom().row()
@ -57,7 +67,7 @@ class ConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBaseScre
// Need to pack before computing space left for bottom panel // Need to pack before computing space left for bottom panel
pack() pack()
val usedHeight = constructionsQueueScrollPane.height + buttons.height + 2f * pad + 10f val usedHeight = showCityInfoTableButton.height + constructionsQueueScrollPane.height + buttons.height + 3f * pad + 10f
updateAvailableConstructions() updateAvailableConstructions()
availableConstructionsScrollPane.layout() availableConstructionsScrollPane.layout()
@ -103,7 +113,8 @@ class ConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBaseScre
queue.forEachIndexed { i, constructionName -> queue.forEachIndexed { i, constructionName ->
constructionsQueueTable.add(getQueueEntry(i, constructionName, i == queue.size - 1, i == selectedQueueEntry)) constructionsQueueTable.add(getQueueEntry(i, constructionName, i == queue.size - 1, i == selectedQueueEntry))
.expandX().fillX().row() .expandX().fillX().row()
constructionsQueueTable.addSeparator() if (i != queue.size - 1)
constructionsQueueTable.addSeparator()
} }
} else } else
constructionsQueueTable.add("Queue empty".toLabel()).pad(2f).row() constructionsQueueTable.add("Queue empty".toLabel()).pad(2f).row()
@ -206,7 +217,8 @@ class ConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBaseScre
} else { } else {
pickProductionButton.color = Color.GRAY pickProductionButton.color = Color.GRAY
pickProductionButton.row() pickProductionButton.row()
pickProductionButton.add(rejectionReason.toLabel(Color.RED)).colspan(pickProductionButton.columns).fillX().left().padTop(2f) pickProductionButton.add(rejectionReason.toLabel(Color.RED).apply{ setWrap(true)} )
.colspan(pickProductionButton.columns).fillX().left().padTop(2f)
} }
return pickProductionButton return pickProductionButton
@ -259,10 +271,14 @@ class ConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBaseScre
if (construction != null if (construction != null
&& construction.canBePurchased() && construction.canBePurchased()
&& UncivGame.Current.worldScreen.isPlayersTurn && UncivGame.Current.worldScreen.isPlayersTurn
&& !city.isPuppet) { && !city.isPuppet
&& !city.isInResistance()) {
val constructionGoldCost = construction.getGoldCost(city.civInfo) val constructionGoldCost = construction.getGoldCost(city.civInfo)
purchaseConstructionButton = TextButton("Buy for [$constructionGoldCost] gold".tr(), CameraStageBaseScreen.skin) button.setText("Buy".tr() + " " + constructionGoldCost)
purchaseConstructionButton.onClick(UncivSound.Coin) { button.add(ImageGetter.getStatIcon(Stat.Gold.name)).size(20f).padBottom(2f)
button.onClick(UncivSound.Coin) {
YesNoPopupTable("Would you like to purchase [${construction.name}] for [$constructionGoldCost] gold?".tr(), { YesNoPopupTable("Would you like to purchase [${construction.name}] for [$constructionGoldCost] gold?".tr(), {
cityConstructions.purchaseConstruction(construction.name) cityConstructions.purchaseConstruction(construction.name)
if (isSelectedQueueEntry()) { if (isSelectedQueueEntry()) {

View File

@ -26,15 +26,7 @@ import com.unciv.ui.pickerscreens.PolicyPickerScreen
import com.unciv.ui.pickerscreens.TechButton import com.unciv.ui.pickerscreens.TechButton
import com.unciv.ui.pickerscreens.TechPickerScreen import com.unciv.ui.pickerscreens.TechPickerScreen
import com.unciv.ui.trade.DiplomacyScreen import com.unciv.ui.trade.DiplomacyScreen
import com.unciv.ui.utils.CameraStageBaseScreen import com.unciv.ui.utils.*
import com.unciv.ui.utils.ImageGetter
import com.unciv.ui.utils.centerX
import com.unciv.ui.utils.colorFromRGB
import com.unciv.ui.utils.disable
import com.unciv.ui.utils.enable
import com.unciv.ui.utils.onClick
import com.unciv.ui.utils.setFontSize
import com.unciv.ui.utils.toLabel
import com.unciv.ui.worldscreen.bottombar.BattleTable import com.unciv.ui.worldscreen.bottombar.BattleTable
import com.unciv.ui.worldscreen.bottombar.TileInfoTable import com.unciv.ui.worldscreen.bottombar.TileInfoTable
import com.unciv.ui.worldscreen.optionstable.OnlineMultiplayer import com.unciv.ui.worldscreen.optionstable.OnlineMultiplayer
@ -234,7 +226,8 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
return "Pick a technology to research!\nClick on the tech button (greenish, top left) > " + return "Pick a technology to research!\nClick on the tech button (greenish, top left) > " +
"\n select technology > click 'Research' (bottom right)" "\n select technology > click 'Research' (bottom right)"
if(!completedTasks.contains("Pick construction")) if(!completedTasks.contains("Pick construction"))
return "Pick a construction!\nEnter city screen > Click on a unit or building (left side)" return "Pick a construction!\nEnter city screen > Click on a unit or building (bottom left side) >" +
" \n click 'add to queue'"
if(!completedTasks.contains("Pass a turn")) if(!completedTasks.contains("Pass a turn"))
return "Pass a turn!\nCycle through units with 'Next unit' > Click 'Next turn'" return "Pass a turn!\nCycle through units with 'Next unit' > Click 'Next turn'"
if(!completedTasks.contains("Reassign worked tiles")) if(!completedTasks.contains("Reassign worked tiles"))