Added improvement-constructing buildings

This commit is contained in:
Yair Morgenstern 2021-02-03 21:09:29 +02:00
parent e56fa6559f
commit 9d647447bc
8 changed files with 103 additions and 27 deletions

View File

@ -39,7 +39,7 @@ Requires a [buildingName] in all cities =
Requires a [buildingName] in this city =
Consumes 1 [resource] =
Required tech: [requiredTech] =
Requires [PolicyOrNationalWonder] =
Requires [PolicyOrNationalWonder] =
Cannot be purchased =
Current construction =
@ -504,6 +504,8 @@ Start Golden Age =
Yes =
No =
Acquire =
Under construction =
Science =
Happiness =
Production =
@ -517,6 +519,7 @@ Golden Age =
[year] BC =
[year] AD =
Civilopedia =
Start new game =
Save game =
Load game =

View File

@ -413,7 +413,17 @@ class CityConstructions {
/** If this was done automatically, we should automatically try to choose a new construction and treat it as such */
fun removeFromQueue(constructionQueueIndex: Int, automatic: Boolean) {
constructionQueue.removeAt(constructionQueueIndex)
val constructionName = constructionQueue.removeAt(constructionQueueIndex)
val construction = getConstruction(constructionName)
if (construction is Building) {
val improvement = construction.getImprovement(cityInfo.getRuleset())
if (improvement != null) {
val tileWithImprovement = cityInfo.getTiles().firstOrNull { it.improvementInProgress == improvement.name }
tileWithImprovement?.improvementInProgress = null
tileWithImprovement?.turnsToImprovement = 0
}
}
if (constructionQueue.isEmpty()) {
if (automatic) chooseNextConstruction()
else constructionQueue.add("Nothing") // To prevent Construction Automation

View File

@ -85,8 +85,10 @@ class CivilizationInfo {
private var allyCivName = ""
var naturalWonders = ArrayList<String>()
//** for trades here, ourOffers is the current civ's offers, and theirOffers is what the requesting civ offers */
/** for trades here, ourOffers is the current civ's offers, and theirOffers is what the requesting civ offers */
val tradeRequests = ArrayList<TradeRequest>()
/** See DiplomacyManager.flagsCountdown to why not eEnum */
private var flagsCountdown = HashMap<String,Int>()
// if we only use lists, and change the list each time the cities are changed,
// we won't get concurrent modification exceptions.
@ -128,6 +130,7 @@ class CivilizationInfo {
toReturn.tradeRequests.addAll(tradeRequests)
toReturn.naturalWonders.addAll(naturalWonders)
toReturn.cityStatePersonality = cityStatePersonality
toReturn.flagsCountdown.putAll(flagsCountdown)
return toReturn
}

View File

@ -442,10 +442,14 @@ open class TileInfo {
if (terrainFeature != null) lineList += terrainFeature!!.tr()
if (resource != null && (viewingCiv == null || hasViewableResource(viewingCiv))) lineList += resource!!.tr()
if (naturalWonder != null) lineList += naturalWonder!!.tr()
if (roadStatus !== RoadStatus.None && !isCityCenter()) lineList += roadStatus.toString().tr()
if (roadStatus !== RoadStatus.None && !isCityCenter()) lineList += roadStatus.name.tr()
if (improvement != null) lineList += improvement!!.tr()
if (improvementInProgress != null && isViewableToPlayer)
lineList += "{$improvementInProgress} - $turnsToImprovement${Fonts.turn}".tr()
if (improvementInProgress != null && isViewableToPlayer) {
var line = "{$improvementInProgress}"
if (turnsToImprovement > 0) line += " - $turnsToImprovement${Fonts.turn}"
else line += " ({Under construction})"
lineList += line.tr()
}
if (civilianUnit != null && isViewableToPlayer)
lineList += civilianUnit!!.name.tr() + " - " + civilianUnit!!.civInfo.civName.tr()
if (militaryUnit != null && isViewableToPlayer) {

View File

@ -5,6 +5,7 @@ import com.unciv.logic.city.CityConstructions
import com.unciv.logic.city.IConstruction
import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.models.Counter
import com.unciv.models.ruleset.tile.TileImprovement
import com.unciv.models.stats.NamedStats
import com.unciv.models.stats.Stat
import com.unciv.models.stats.Stats
@ -108,7 +109,7 @@ class Building : NamedStats(), IConstruction {
stringBuilder.appendln("Consumes 1 [$requiredResource]".tr())
if (providesFreeBuilding != null)
stringBuilder.appendln("Provides a free [$providesFreeBuilding] in the city".tr())
if (uniques.isNotEmpty()){
if (uniques.isNotEmpty()) {
if (replacementTextForUniques != "") stringBuilder.appendln(replacementTextForUniques)
else stringBuilder.appendln(uniques.asSequence().map { it.tr() }.joinToString("\n"))
}
@ -298,7 +299,7 @@ class Building : NamedStats(), IConstruction {
if (requiredTech != null && !civInfo.tech.isResearched(requiredTech!!)) return "$requiredTech not researched"
for (unique in uniqueObjects.filter { it.placeholderText == "Unlocked with []" })
if(civInfo.tech.researchedTechnologies.none { it.era() == unique.params[0] || it.name == unique.params[0] }
if (civInfo.tech.researchedTechnologies.none { it.era() == unique.params[0] || it.name == unique.params[0] }
&& !civInfo.policies.isAdopted(unique.params[0]))
return unique.text
@ -404,6 +405,18 @@ class Building : NamedStats(), IConstruction {
}
cityConstructions.addBuilding(name)
val improvement = getImprovement(civInfo.gameInfo.ruleSet)
if (improvement != null) {
val tileWithImprovement = cityConstructions.cityInfo.getTiles().firstOrNull { it.improvementInProgress == improvement.name }
if (tileWithImprovement != null) {
tileWithImprovement.turnsToImprovement = 0
tileWithImprovement.improvementInProgress = null
tileWithImprovement.improvement = improvement.name
}
}
if (providesFreeBuilding != null && !cityConstructions.containsBuildingOrEquivalent(providesFreeBuilding!!)) {
var buildingToAdd = providesFreeBuilding!!
@ -444,4 +457,13 @@ class Building : NamedStats(), IConstruction {
if (replaces == null) return this
else return ruleset.buildings[replaces!!]!!
}
fun getImprovement(ruleset: Ruleset): TileImprovement? {
val improvementUnique = uniqueObjects
.firstOrNull { it.placeholderText == "Creates a [] improvement on a specific tile" }
if (improvementUnique == null) return null
return ruleset.tileImprovements[improvementUnique.params[0]]!!
}
fun isSellable() = !isWonder && !isNationalWonder
}

View File

@ -96,7 +96,7 @@ class CityInfoTable(private val cityScreen: CityScreen) : Table(CameraStageBaseS
cityScreen.city.civInfo, cityScreen.city.civInfo.gameInfo.ruleSet)
wonderDetailsTable.add(detailsString.toLabel().apply { wrap = true })
.width(cityScreen.stage.width / 4 - 2 * pad).row() // when you set wrap, then you need to manually set the size of the label
if (!building.isWonder && !building.isNationalWonder) {
if (building.isSellable()) {
val sellAmount = cityScreen.city.getGoldForSellingBuilding(building.name)
val sellBuildingButton = "Sell for [$sellAmount] gold".toTextButton()
wonderDetailsTable.add(sellBuildingButton).pad(5f).row()

View File

@ -11,6 +11,8 @@ import com.unciv.logic.HexMath
import com.unciv.logic.city.CityInfo
import com.unciv.logic.city.IConstruction
import com.unciv.logic.map.TileInfo
import com.unciv.models.ruleset.Building
import com.unciv.models.ruleset.tile.TileImprovement
import com.unciv.ui.map.TileGroupMap
import com.unciv.ui.tilegroups.TileSetStrings
import com.unciv.ui.utils.*
@ -101,7 +103,7 @@ class CityScreen(internal val city: CityInfo): CameraStageBaseScreen() {
exitCityButton.y = 10f
cityPickerTable.update()
cityPickerTable.centerX(stage)
cityPickerTable.setY(exitCityButton.top+10f, Align.bottom)
cityPickerTable.setY(exitCityButton.top + 10f, Align.bottom)
tileTable.update(selectedTile)
tileTable.setPosition(stage.width - 5f, 5f, Align.bottomRight)
@ -110,7 +112,7 @@ class CityScreen(internal val city: CityInfo): CameraStageBaseScreen() {
selectedConstructionTable.setPosition(stage.width - 5f, 5f, Align.bottomRight)
cityStatsTable.update()
cityStatsTable.setPosition( stage.width - 5f, stage.height - 5f, Align.topRight)
cityStatsTable.setPosition(stage.width - 5f, stage.height - 5f, Align.topRight)
updateAnnexAndRazeCityButton()
updateTileGroups()
@ -120,9 +122,17 @@ class CityScreen(internal val city: CityInfo): CameraStageBaseScreen() {
val nextTile = city.expansion.chooseNewTileToOwn()
for (tileGroup in tileGroups) {
tileGroup.update()
if(tileGroup.tileInfo == nextTile){
tileGroup.hideCircle()
if (city.tiles.contains(tileGroup.tileInfo.position)
&& constructionsTable.improvementBuildingToConstruct != null) {
val improvement = constructionsTable.improvementBuildingToConstruct!!.getImprovement(city.getRuleset())!!
if (tileGroup.tileInfo.canBuildImprovement(improvement, city.civInfo))
tileGroup.showCircle(Color.GREEN)
else tileGroup.showCircle(Color.RED)
}
if (tileGroup.tileInfo == nextTile) {
tileGroup.showCircle(Color.PURPLE)
tileGroup.setColor(0f,0f,0f,0.7f)
tileGroup.setColor(0f, 0f, 0f, 0.7f)
}
}
}
@ -130,7 +140,7 @@ class CityScreen(internal val city: CityInfo): CameraStageBaseScreen() {
private fun updateAnnexAndRazeCityButton() {
razeCityButtonHolder.clear()
if(city.isPuppet) {
if (city.isPuppet) {
val annexCityButton = "Annex city".toTextButton()
annexCityButton.labelCell.pad(10f)
annexCityButton.onClick {
@ -139,19 +149,19 @@ class CityScreen(internal val city: CityInfo): CameraStageBaseScreen() {
}
if (!canChangeState) annexCityButton.disable()
razeCityButtonHolder.add(annexCityButton).colspan(cityPickerTable.columns)
} else if(!city.isBeingRazed) {
} else if (!city.isBeingRazed) {
val razeCityButton = "Raze city".toTextButton()
razeCityButton.labelCell.pad(10f)
razeCityButton.onClick { city.isBeingRazed=true; update() }
if(!canChangeState || city.isOriginalCapital)
razeCityButton.onClick { city.isBeingRazed = true; update() }
if (!canChangeState || city.isOriginalCapital)
razeCityButton.disable()
razeCityButtonHolder.add(razeCityButton).colspan(cityPickerTable.columns)
} else {
val stopRazingCityButton = "Stop razing city".toTextButton()
stopRazingCityButton.labelCell.pad(10f)
stopRazingCityButton.onClick { city.isBeingRazed=false; update() }
if(!canChangeState) stopRazingCityButton.disable()
stopRazingCityButton.onClick { city.isBeingRazed = false; update() }
if (!canChangeState) stopRazingCityButton.disable()
razeCityButtonHolder.add(stopRazingCityButton).colspan(cityPickerTable.columns)
}
razeCityButtonHolder.pack()
@ -175,6 +185,21 @@ class CityScreen(internal val city: CityInfo): CameraStageBaseScreen() {
tileGroup.onClick {
if (city.isPuppet) return@onClick
if (constructionsTable.improvementBuildingToConstruct != null) {
val improvement = constructionsTable.improvementBuildingToConstruct!!.getImprovement(city.getRuleset())!!
if (tileInfo.canBuildImprovement(improvement, cityInfo.civInfo)) {
tileInfo.improvementInProgress = improvement.name
tileInfo.turnsToImprovement = -1
constructionsTable.improvementBuildingToConstruct = null
cityInfo.cityConstructions.addToQueue(improvement.name)
update()
} else {
constructionsTable.improvementBuildingToConstruct = null
update()
}
return@onClick
}
selectedTile = tileInfo
selectedConstruction = null
if (tileGroup.isWorkable && canChangeState) {
@ -196,16 +221,16 @@ class CityScreen(internal val city: CityInfo): CameraStageBaseScreen() {
stage.height / 2 + positionalVector.y * 0.8f * groupSize.toFloat())
}
val tileMapGroup = TileGroupMap(tileGroups,stage.width/2)
val tileMapGroup = TileGroupMap(tileGroups, stage.width / 2)
val scrollPane = ScrollPane(tileMapGroup)
scrollPane.setSize(stage.width,stage.height)
scrollPane.setSize(stage.width, stage.height)
scrollPane.setOrigin(stage.width / 2, stage.height / 2)
scrollPane.center(stage)
stage.addActor(scrollPane)
scrollPane.layout() // center scrolling
scrollPane.scrollPercentX=0.5f
scrollPane.scrollPercentY=0.5f
scrollPane.scrollPercentX = 0.5f
scrollPane.scrollPercentY = 0.5f
scrollPane.updateVisualScroll()
}
@ -233,7 +258,7 @@ class CityScreen(internal val city: CityInfo): CameraStageBaseScreen() {
private fun getKeyboardListener(): InputListener = object : InputListener() {
override fun keyDown(event: InputEvent?, keyCode: Int): Boolean {
if (event == null) return super.keyDown(event, keyCode)
when(event.keyCode) {
when (event.keyCode) {
Input.Keys.LEFT -> page(-1)
Input.Keys.RIGHT -> page(1)
else -> return super.keyDown(event, keyCode)
@ -241,4 +266,4 @@ class CityScreen(internal val city: CityInfo): CameraStageBaseScreen() {
return true
}
}
}
}

View File

@ -31,9 +31,11 @@ class ConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBaseScre
private val constructionsQueueTable = Table()
private val availableConstructionsTable = Table()
private val buttons = Table()
private val pad = 10f
var improvementBuildingToConstruct:Building?=null
init {
showCityInfoTableButton = "Show stats drilldown".toTextButton()
showCityInfoTableButton.onClick {
@ -347,8 +349,15 @@ class ConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBaseScre
}
fun addConstructionToQueue(construction: IConstruction, cityConstructions: CityConstructions) {
if (construction is Building && construction.uniqueObjects.any { it.placeholderText=="Creates a [] improvement on a specific tile" }){
cityScreen.selectedTile
improvementBuildingToConstruct = construction
return
}
cityConstructions.addToQueue(construction.name)
if (!construction.shouldBeDisplayed(cityConstructions)) cityScreen.selectedConstruction = null
if (!construction.shouldBeDisplayed(cityConstructions)) // For buildings - unlike units which can be queued multiple times
cityScreen.selectedConstruction = null
cityScreen.update()
cityScreen.game.settings.addCompletedTutorialTask("Pick construction")
}