mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-25 21:03:15 -04:00
Global Constructions Blacklist (#10061)
* Improved handling of "Nothing" construction * Suppress "All" entries when you have only one city * Global Construction Blacklist * Reviews * Reviews - missed renames
This commit is contained in:
parent
8aeae30050
commit
8e3ebc7724
@ -1245,6 +1245,8 @@ Add to the top of the queue =
|
||||
Add to the queue in all cities =
|
||||
Add or move to the top in all cities =
|
||||
Remove from the queue in all cities =
|
||||
Disable =
|
||||
Enable =
|
||||
|
||||
# Specialized Popups - Ask for text or numbers, file picker
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.unciv.logic.automation.city
|
||||
|
||||
import com.unciv.GUI
|
||||
import com.unciv.logic.automation.Automation
|
||||
import com.unciv.logic.automation.civilization.NextTurnAutomation
|
||||
import com.unciv.logic.city.CityConstructions
|
||||
@ -24,9 +25,14 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){
|
||||
private val city = cityConstructions.city
|
||||
private val civInfo = city.civ
|
||||
|
||||
private val disabledAutoAssignConstructions: Set<String> =
|
||||
if (civInfo.isHuman()) GUI.getSettings().disabledAutoAssignConstructions
|
||||
else emptySet()
|
||||
|
||||
private val buildableBuildings = hashMapOf<String, Boolean>()
|
||||
private val buildableUnits = hashMapOf<String, Boolean>()
|
||||
private val buildings = city.getRuleset().buildings.values.asSequence()
|
||||
.filterNot { it.name in disabledAutoAssignConstructions }
|
||||
|
||||
private val nonWonders = buildings.filterNot { it.isAnyWonder() }
|
||||
.filterNot { buildableBuildings[it.name] == false } // if we already know that this building can't be built here then don't even consider it
|
||||
@ -35,6 +41,7 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){
|
||||
|
||||
private val units = city.getRuleset().units.values.asSequence()
|
||||
.filterNot { buildableUnits[it.name] == false } // if we already know that this unit can't be built here then don't even consider it
|
||||
.filterNot { it.name in disabledAutoAssignConstructions }
|
||||
|
||||
private val civUnits = civInfo.units.getCivUnits()
|
||||
private val militaryUnits = civUnits.count { it.baseUnit.isMilitary() }
|
||||
|
@ -232,7 +232,7 @@ class CityConstructions : IsPartOfGameInfoSerialization {
|
||||
internal fun getConstruction(constructionName: String): IConstruction {
|
||||
val gameBasics = city.getRuleset()
|
||||
when {
|
||||
constructionName == "" -> return getConstruction("Nothing")
|
||||
constructionName == "" -> return PerpetualConstruction.idle
|
||||
gameBasics.buildings.containsKey(constructionName) -> return gameBasics.buildings[constructionName]!!
|
||||
gameBasics.units.containsKey(constructionName) -> return gameBasics.units[constructionName]!!
|
||||
else -> {
|
||||
@ -735,10 +735,9 @@ class CityConstructions : IsPartOfGameInfoSerialization {
|
||||
|
||||
fun chooseNextConstruction() {
|
||||
validateConstructionQueue()
|
||||
if (constructionQueue.isNotEmpty()) {
|
||||
if (currentConstructionFromQueue != ""
|
||||
// If the USER set a perpetual construction, then keep it!
|
||||
&& (getConstruction(currentConstructionFromQueue) !is PerpetualConstruction || currentConstructionIsUserSet)) return
|
||||
if (!isQueueEmptyOrIdle()) {
|
||||
// If the USER set a perpetual construction, then keep it!
|
||||
if (getConstruction(currentConstructionFromQueue) !is PerpetualConstruction || currentConstructionIsUserSet) return
|
||||
}
|
||||
|
||||
val isCurrentPlayersTurn = city.civ.gameInfo.isUsersTurn()
|
||||
@ -765,6 +764,9 @@ class CityConstructions : IsPartOfGameInfoSerialization {
|
||||
PerpetualConstruction.isNamePerpetual(constructionQueue.last())
|
||||
// `getConstruction(constructionQueue.last()) is PerpetualConstruction` is clear but more expensive
|
||||
|
||||
fun isQueueEmptyOrIdle() = currentConstructionFromQueue.isEmpty()
|
||||
|| currentConstructionFromQueue == PerpetualConstruction.idle.name
|
||||
|
||||
/** Add [construction] to the end or top (controlled by [addToTop]) of the queue with all checks (does nothing if not possible)
|
||||
*
|
||||
* Note: Overload with string parameter `constructionName` exists as well.
|
||||
@ -773,7 +775,7 @@ class CityConstructions : IsPartOfGameInfoSerialization {
|
||||
if (!canAddToQueue(construction)) return
|
||||
val constructionName = construction.name
|
||||
when {
|
||||
currentConstructionFromQueue.isEmpty() || currentConstructionFromQueue == "Nothing" ->
|
||||
isQueueEmptyOrIdle() ->
|
||||
currentConstructionFromQueue = constructionName
|
||||
addToTop && construction is PerpetualConstruction && PerpetualConstruction.isNamePerpetual(currentConstructionFromQueue) ->
|
||||
currentConstructionFromQueue = constructionName // perpetual constructions will replace each other
|
||||
@ -817,7 +819,7 @@ class CityConstructions : IsPartOfGameInfoSerialization {
|
||||
|
||||
currentConstructionIsUserSet = if (constructionQueue.isEmpty()) {
|
||||
if (automatic) chooseNextConstruction()
|
||||
else constructionQueue.add("Nothing") // To prevent Construction Automation
|
||||
else constructionQueue.add(PerpetualConstruction.idle.name) // To prevent Construction Automation
|
||||
false
|
||||
} else true // we're just continuing the regular queue
|
||||
}
|
||||
@ -828,7 +830,7 @@ class CityConstructions : IsPartOfGameInfoSerialization {
|
||||
* If the queue is emptied, no automatic: getSettings().autoAssignCityProduction is ignored! (parameter to be added when needed)
|
||||
*/
|
||||
fun removeAllByName(constructionName: String) {
|
||||
while (true) {
|
||||
while (!isQueueEmptyOrIdle()) {
|
||||
val index = constructionQueue.indexOf(constructionName)
|
||||
if (index < 0) return
|
||||
removeFromQueue(index, false)
|
||||
@ -904,7 +906,7 @@ class CityConstructions : IsPartOfGameInfoSerialization {
|
||||
constructionQueue.removeAt(indexToRemove)
|
||||
|
||||
currentConstructionIsUserSet = if (constructionQueue.isEmpty()) {
|
||||
constructionQueue.add("Nothing")
|
||||
constructionQueue.add(PerpetualConstruction.idle.name)
|
||||
false
|
||||
} else true
|
||||
}
|
||||
|
@ -68,6 +68,13 @@ class GameSettings {
|
||||
var skin: String = Constants.defaultSkin
|
||||
var showTutorials: Boolean = true
|
||||
var autoAssignCityProduction: Boolean = true
|
||||
|
||||
/** This set of construction names has two effects:
|
||||
* * Matching constructions are no longer candidates for [autoAssignCityProduction]
|
||||
* * Matching constructions are offered in a separate 'Disabled' category in CityScreen
|
||||
*/
|
||||
var disabledAutoAssignConstructions = HashSet<String>()
|
||||
|
||||
var autoBuildingRoads: Boolean = true
|
||||
var automatedWorkersReplaceImprovements = true
|
||||
var automatedUnitsMoveOnTurnStart: Boolean = false
|
||||
|
@ -136,6 +136,7 @@ enum class KeyboardBinding(
|
||||
BuildWonders(Category.CityScreen, "Buildable Wonders", 'w'),
|
||||
BuildNationalWonders(Category.CityScreen, "Buildable National Wonders", 'n'),
|
||||
BuildOther(Category.CityScreen, "Other Constructions", 'o'),
|
||||
BuildDisabled(Category.CityScreen, "Disabled Constructions", KeyCharAndCode.ctrl('h')),
|
||||
NextCity(Category.CityScreen, Input.Keys.RIGHT),
|
||||
PreviousCity(Category.CityScreen, Input.Keys.LEFT),
|
||||
ShowStats(Category.CityScreen, 's'),
|
||||
|
@ -3,6 +3,7 @@ package com.unciv.ui.popups
|
||||
import com.badlogic.gdx.scenes.scene2d.Actor
|
||||
import com.badlogic.gdx.scenes.scene2d.Stage
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||
import com.unciv.GUI
|
||||
import com.unciv.logic.city.City
|
||||
import com.unciv.logic.city.CityConstructions
|
||||
import com.unciv.models.ruleset.Building
|
||||
@ -36,12 +37,17 @@ class CityScreenConstructionMenu(
|
||||
cityConstructions.constructionQueue
|
||||
.count { it !in PerpetualConstruction.perpetualConstructionsMap }
|
||||
private val myIndex = cityConstructions.constructionQueue.indexOf(constructionName)
|
||||
private fun anyCity(predicate: (CityConstructions) -> Boolean) =
|
||||
/** Check whether an "All cities" menu makes sense: `true` if there's more than one city, it's not a Wonder, and any city's queue matches [predicate]. */
|
||||
private fun allCitiesEntryValid(predicate: (CityConstructions) -> Boolean) =
|
||||
city.civ.cities.size > 1 &&
|
||||
(construction as? Building)?.isAnyWonder() != true &&
|
||||
city.civ.cities.map { it.cityConstructions }.any(predicate)
|
||||
private fun forAllCities(action: (CityConstructions) -> Unit) =
|
||||
city.civ.cities.map { it.cityConstructions }.forEach(action)
|
||||
|
||||
private val settings = GUI.getSettings()
|
||||
private val disabledAutoAssignConstructions = settings.disabledAutoAssignConstructions
|
||||
|
||||
init {
|
||||
closeListeners.add {
|
||||
if (anyButtonWasClicked) onButtonClicked()
|
||||
@ -62,6 +68,10 @@ class CityScreenConstructionMenu(
|
||||
table.add(getButton("Add or move to the top in all cities", KeyboardBinding.AddConstructionAllTop, ::addAllQueuesTop)).row()
|
||||
if (canRemoveAllQueues())
|
||||
table.add(getButton("Remove from the queue in all cities", KeyboardBinding.RemoveConstructionAll, ::removeAllQueues)).row()
|
||||
if (canDisable())
|
||||
table.add(getButton("Disable", KeyboardBinding.BuildDisabled, ::disableEntry)).row()
|
||||
if (canEnable())
|
||||
table.add(getButton("Enable", KeyboardBinding.BuildDisabled, ::enableEntry)).row()
|
||||
return table.takeUnless { it.cells.isEmpty }
|
||||
}
|
||||
|
||||
@ -83,7 +93,7 @@ class CityScreenConstructionMenu(
|
||||
cityConstructions.canAddToQueue(construction)
|
||||
private fun addQueueTop() = cityConstructions.addToQueue(construction, addToTop = true)
|
||||
|
||||
private fun canAddAllQueues() = anyCity {
|
||||
private fun canAddAllQueues() = allCitiesEntryValid {
|
||||
it.canAddToQueue(construction) &&
|
||||
// A Perpetual that is already queued can still be added says canAddToQueue, but here we don't want to count that
|
||||
!(construction is PerpetualConstruction && it.isBeingConstructedOrEnqueued(constructionName))
|
||||
@ -91,7 +101,7 @@ class CityScreenConstructionMenu(
|
||||
private fun addAllQueues() = forAllCities { it.addToQueue(construction) }
|
||||
|
||||
private fun canAddAllQueuesTop() = construction !is PerpetualConstruction &&
|
||||
anyCity { it.canAddToQueue(construction) || it.isEnqueuedForLater(constructionName) }
|
||||
allCitiesEntryValid { it.canAddToQueue(construction) || it.isEnqueuedForLater(constructionName) }
|
||||
private fun addAllQueuesTop() = forAllCities {
|
||||
val index = it.constructionQueue.indexOf(constructionName)
|
||||
if (index > 0)
|
||||
@ -100,6 +110,19 @@ class CityScreenConstructionMenu(
|
||||
it.addToQueue(construction, true)
|
||||
}
|
||||
|
||||
private fun canRemoveAllQueues() = anyCity { it.isBeingConstructedOrEnqueued(constructionName) }
|
||||
private fun canRemoveAllQueues() = allCitiesEntryValid { it.isBeingConstructedOrEnqueued(constructionName) }
|
||||
private fun removeAllQueues() = forAllCities { it.removeAllByName(constructionName) }
|
||||
|
||||
private fun canDisable() = constructionName !in disabledAutoAssignConstructions &&
|
||||
construction != PerpetualConstruction.idle
|
||||
private fun disableEntry() {
|
||||
disabledAutoAssignConstructions.add(constructionName)
|
||||
settings.save()
|
||||
}
|
||||
|
||||
private fun canEnable() = constructionName in disabledAutoAssignConstructions
|
||||
private fun enableEntry() {
|
||||
disabledAutoAssignConstructions.remove(constructionName)
|
||||
settings.save()
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.TextButton
|
||||
import com.badlogic.gdx.utils.Align
|
||||
import com.unciv.Constants
|
||||
import com.unciv.GUI
|
||||
import com.unciv.logic.city.City
|
||||
import com.unciv.logic.city.CityConstructions
|
||||
import com.unciv.logic.map.tile.Tile
|
||||
@ -255,6 +256,8 @@ class CityConstructionsTable(private val cityScreen: CityScreen) {
|
||||
val buildableNationalWonders = ArrayList<Table>()
|
||||
val buildableBuildings = ArrayList<Table>()
|
||||
val specialConstructions = ArrayList<Table>()
|
||||
val blacklisted = ArrayList<Table>()
|
||||
val disabledAutoAssignConstructions: Set<String> = GUI.getSettings().disabledAutoAssignConstructions
|
||||
|
||||
var maxButtonWidth = constructionsQueueTable.width
|
||||
for (dto in constructionButtonDTOList) {
|
||||
@ -268,7 +271,9 @@ class CityConstructionsTable(private val cityScreen: CityScreen) {
|
||||
continue
|
||||
|
||||
val constructionButton = getConstructionButton(dto)
|
||||
when (dto.construction) {
|
||||
if (dto.construction.name in disabledAutoAssignConstructions)
|
||||
blacklisted.add(constructionButton)
|
||||
else when (dto.construction) {
|
||||
is BaseUnit -> units.add(constructionButton)
|
||||
is Building -> {
|
||||
when {
|
||||
@ -290,6 +295,7 @@ class CityConstructionsTable(private val cityScreen: CityScreen) {
|
||||
addCategory("Wonders", buildableWonders, maxButtonWidth, KeyboardBinding.BuildWonders)
|
||||
addCategory("National Wonders", buildableNationalWonders, maxButtonWidth, KeyboardBinding.BuildNationalWonders)
|
||||
addCategory("Other", specialConstructions, maxButtonWidth, KeyboardBinding.BuildOther)
|
||||
addCategory("Disabled", blacklisted, maxButtonWidth, KeyboardBinding.BuildDisabled, startsOutOpened = false)
|
||||
pack()
|
||||
}
|
||||
|
||||
@ -799,12 +805,19 @@ class CityConstructionsTable(private val cityScreen: CityScreen) {
|
||||
lowerTable.pack()
|
||||
}
|
||||
|
||||
private fun Table.addCategory(title: String, list: ArrayList<Table>, prefWidth: Float, toggleKey: KeyboardBinding) {
|
||||
private fun Table.addCategory(
|
||||
title: String,
|
||||
list: ArrayList<Table>,
|
||||
prefWidth: Float,
|
||||
toggleKey: KeyboardBinding,
|
||||
startsOutOpened: Boolean = true
|
||||
) {
|
||||
if (list.isEmpty()) return
|
||||
|
||||
if (rows > 0) addSeparator()
|
||||
val expander = ExpanderTab(
|
||||
title,
|
||||
startsOutOpened = startsOutOpened,
|
||||
defaultPad = 0f,
|
||||
expanderWidth = prefWidth,
|
||||
persistenceID = "CityConstruction.$title",
|
||||
|
Loading…
x
Reference in New Issue
Block a user