Units & buildings requiring resources or other needs are now displayed, but not selectable, from the city screen as constructions

This commit is contained in:
Yair Morgenstern 2019-03-29 18:03:18 +03:00
parent a5e1978a71
commit 9eb9176b2a
5 changed files with 101 additions and 49 deletions

View File

@ -21,8 +21,8 @@ android {
applicationId "com.unciv.app"
minSdkVersion 14
targetSdkVersion 28
versionCode 220
versionName "2.14.1.patch1"
versionCode 221
versionName "2.14.2"
}
// Had to add this crap for Travis to build, it wanted to sign the app

View File

@ -7,6 +7,7 @@ interface IConstruction : INamed, ICivilopedia {
fun getProductionCost(adoptedPolicies: HashSet<String>): Int
fun getGoldCost(adoptedPolicies: HashSet<String>): Int
fun isBuildable(construction: CityConstructions): Boolean
fun shouldBeDisplayed(construction: CityConstructions): Boolean
fun postBuildEvent(construction: CityConstructions) // Yes I'm hilarious.
fun canBePurchased(): Boolean
}
@ -14,6 +15,9 @@ interface IConstruction : INamed, ICivilopedia {
open class SpecialConstruction(override var name: String, override val description: String) : IConstruction{
override fun shouldBeDisplayed(construction: CityConstructions): Boolean {
return isBuildable(construction)
}
companion object {
fun getSpecialConstructions(): List<SpecialConstruction> {

View File

@ -8,6 +8,7 @@ import com.unciv.models.stats.Stats
import com.unciv.ui.utils.getRandom
class Building : NamedStats(), IConstruction{
override val description: String
get() = getDescription(false, hashSetOf())
@ -167,43 +168,63 @@ class Building : NamedStats(), IConstruction{
return (cost / 10).toInt() * 10
}
override fun isBuildable(construction: CityConstructions): Boolean {
if (construction.isBuilt(name)) return false
override fun shouldBeDisplayed(construction: CityConstructions): Boolean {
val rejectionReason = getRejectionReason(construction)
return rejectionReason==""
|| rejectionReason.startsWith("Requires")
|| rejectionReason == "Wonder is being built elsewhere"
}
fun getRejectionReason(construction: CityConstructions):String{
if (construction.isBuilt(name)) return "Already built"
val civInfo = construction.cityInfo.civInfo
if (uniqueTo!=null && uniqueTo!=civInfo.civName) return false
if (GameBasics.Buildings.values.any { it.uniqueTo==civInfo.civName && it.replaces==name }) return false
if (requiredTech != null && !civInfo.tech.isResearched(requiredTech!!)) return false
if (uniqueTo!=null && uniqueTo!=civInfo.civName) return "Unique to $uniqueTo"
if (GameBasics.Buildings.values.any { it.uniqueTo==civInfo.civName && it.replaces==name }) return "Our unique building replaces this"
if (requiredTech != null && !civInfo.tech.isResearched(requiredTech!!)) return "$requiredTech not researched"
// Regular wonders
if (isWonder && requiredBuildingInAllCities==null){
if(civInfo.gameInfo.civilizations.flatMap { it.cities }
.any {it.cityConstructions.isBuilt(name)})
return false
return "Wonder is already built"
if(civInfo.cities.any { it!=construction.cityInfo && it.cityConstructions.isBeingConstructed(name) })
return false
return "Wonder is being built elsewhere"
}
if (requiredBuilding != null && !construction.containsBuildingOrEquivalent(requiredBuilding!!)) return false
if (requiredBuildingInAllCities != null && civInfo.cities.any { !it.cityConstructions.containsBuildingOrEquivalent(requiredBuildingInAllCities!!) })
return false
if(requiredBuildingInAllCities!=null && civInfo.cities.any {
it.cityConstructions.isBeingConstructed(name) || it.cityConstructions.isBuilt(name)
})
return false
if (cannotBeBuiltWith != null && construction.isBuilt(cannotBeBuiltWith!!)) return false
// National wonders
if(requiredBuildingInAllCities!=null) {
if (civInfo.cities.any { !it.cityConstructions.containsBuildingOrEquivalent(requiredBuildingInAllCities!!) })
return "Requires a $requiredBuildingInAllCities in all cities"
if (civInfo.cities.any {it.cityConstructions.isBuilt(name) })
return "Wonder is already built"
if (civInfo.cities.any {it.cityConstructions.isBeingConstructed(name) })
return "Wonder is being built elsewhere"
}
if (requiredBuilding != null && !construction.containsBuildingOrEquivalent(requiredBuilding!!))
return "Requires a $requiredBuilding in this city"
if (cannotBeBuiltWith != null && construction.isBuilt(cannotBeBuiltWith!!))
return "Cannot be built with $cannotBeBuiltWith"
if ("Must be next to desert" in uniques
&& !construction.cityInfo.getCenterTile().getTilesInDistance(1).any { it.baseTerrain == "Desert" })
return false
return "Must be next to desert"
if ("Must be next to mountain" in uniques
&& !construction.cityInfo.getCenterTile().getTilesInDistance(1).any { it.baseTerrain == "Mountain" })
return false
return "Must be next to mountain"
if("Can only be built in coastal cities" in uniques
&& construction.cityInfo.getCenterTile().neighbors.none { it.baseTerrain=="Coast" })
return false
if (requiredResource != null && !civInfo.hasResource(requiredResource!!))
return false
return "Can only be built in coastal cities"
if (requiredResource != null && !civInfo.hasResource(requiredResource!!))
return "Requires $requiredResource"
if (requiredNearbyImprovedResources != null) {
val containsResourceWithImprovement = construction.cityInfo.getTilesInRange()
@ -213,14 +234,18 @@ class Building : NamedStats(), IConstruction{
&& it.getTileResource().improvement == it.improvement
&& it.getOwner() == civInfo
}
if (!containsResourceWithImprovement) return false
if (!containsResourceWithImprovement) return "Nearby $requiredNearbyImprovedResources required"
}
if ("Spaceship part" in uniques) {
if (!civInfo.getBuildingUniques().contains("Enables construction of Spaceship parts")) return false
if (civInfo.victoryManager.unconstructedSpaceshipParts()[name] == 0) return false // Don't need to build any more of these!
if (!civInfo.getBuildingUniques().contains("Enables construction of Spaceship parts")) return "Apollo project not built!"
if (civInfo.victoryManager.unconstructedSpaceshipParts()[name] == 0) return "Don't need to build any more of these!"
}
return true
return ""
}
override fun isBuildable(construction: CityConstructions): Boolean {
return getRejectionReason(construction)==""
}
override fun postBuildEvent(construction: CityConstructions) {

View File

@ -108,22 +108,33 @@ class BaseUnit : INamed, IConstruction, ICivilopedia {
fun getDisbandGold() = getBaseGoldCost().toInt()/20
fun isBuildable(civInfo:CivilizationInfo): Boolean {
if (unbuildable) return false
if (requiredTech!=null && !civInfo.tech.isResearched(requiredTech!!)) return false
if (obsoleteTech!=null && civInfo.tech.isResearched(obsoleteTech!!)) return false
if (uniqueTo!=null && uniqueTo!=civInfo.civName) return false
if (GameBasics.Units.values.any { it.uniqueTo==civInfo.civName && it.replaces==name }) return false
if (requiredResource!=null && !civInfo.hasResource(requiredResource!!)) return false
return true
override fun shouldBeDisplayed(construction: CityConstructions): Boolean {
val rejectionReason = getRejectionReason(construction)
return rejectionReason=="" || rejectionReason.startsWith("Requires")
}
override fun isBuildable(construction: CityConstructions): Boolean {
if(!isBuildable(construction.cityInfo.civInfo)) return false
fun getRejectionReason(construction: CityConstructions): String {
val civRejectionReason = getRejectionReason(construction.cityInfo.civInfo)
if(civRejectionReason!="") return civRejectionReason
if(unitType.isWaterUnit() && construction.cityInfo.getCenterTile().neighbors.none { it.baseTerrain=="Coast" })
return false
return true
return "Can't build water units by the coast"
return ""
}
fun getRejectionReason(civInfo: CivilizationInfo): String {
if (unbuildable) return "Unbuildable"
if (requiredTech!=null && !civInfo.tech.isResearched(requiredTech!!)) return "$requiredTech not researched"
if (obsoleteTech!=null && civInfo.tech.isResearched(obsoleteTech!!)) return "Obsolete by $obsoleteTech"
if (uniqueTo!=null && uniqueTo!=civInfo.civName) return "Unique to $uniqueTo"
if (GameBasics.Units.values.any { it.uniqueTo==civInfo.civName && it.replaces==name }) return "Our unique unit replaces this"
if (requiredResource!=null && !civInfo.hasResource(requiredResource!!)) return "Requires $requiredResource"
return ""
}
fun isBuildable(civInfo: CivilizationInfo) = getRejectionReason(civInfo)==""
override fun isBuildable(construction: CityConstructions): Boolean {
return getRejectionReason(construction) == ""
}
override fun postBuildEvent(construction: CityConstructions) {

View File

@ -19,7 +19,7 @@ class ConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBaseScre
var constructionScrollPane:ScrollPane?=null
private fun getProductionButton(construction: String, buttonText: String): Table {
private fun getProductionButton(construction: String, buttonText: String, rejectionReason: String=""): Table {
val pickProductionButton = Table()
pickProductionButton.touchable = Touchable.enabled
pickProductionButton.align(Align.left)
@ -32,11 +32,20 @@ class ConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBaseScre
pickProductionButton.add(ImageGetter.getConstructionImage(construction).surroundWithCircle(40f)).padRight(10f)
pickProductionButton.add(buttonText.toLabel().setFontColor(Color.WHITE))
pickProductionButton.onClick {
cityScreen.city.cityConstructions.currentConstruction = construction
cityScreen.city.cityStats.update()
cityScreen.update()
if(rejectionReason=="") {
pickProductionButton.onClick {
cityScreen.city.cityConstructions.currentConstruction = construction
cityScreen.city.cityStats.update()
cityScreen.update()
}
}
else {
pickProductionButton.color = Color.GRAY
pickProductionButton.row()
pickProductionButton.add(rejectionReason.toLabel().setFontColor(Color.RED))
}
if(construction==cityScreen.city.cityConstructions.currentConstruction)
pickProductionButton.color= Color.GREEN
return pickProductionButton
@ -77,18 +86,21 @@ class ConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBaseScre
constructionPickerTable.background = ImageGetter.getBackground(Color.BLACK)
val units = ArrayList<Table>()
for (unit in GameBasics.Units.values.filter { it.isBuildable(cityConstructions) })
for (unit in GameBasics.Units.values.filter { it.shouldBeDisplayed(cityConstructions) })
units += getProductionButton(unit.name,
unit.name.tr() + "\r\n" + cityConstructions.turnsToConstruction(unit.name) + " {turns}".tr())
unit.name.tr() + "\r\n" + cityConstructions.turnsToConstruction(unit.name) + " {turns}".tr(),
unit.getRejectionReason(cityConstructions))
constructionPickerTable.addCategory("Units",units)
val buildableWonders = ArrayList<Table>()
val buildableBuildings = ArrayList<Table>()
for (building in GameBasics.Buildings.values) {
if (!building.isBuildable(cityConstructions) && building.name != cityConstructions.currentConstruction) continue
if (!building.shouldBeDisplayed(cityConstructions) && building.name != cityConstructions.currentConstruction) continue
val productionTextButton = getProductionButton(building.name,
building.name + "\r\n" + cityConstructions.turnsToConstruction(building.name) + " {turns}".tr())
building.name + "\r\n" + cityConstructions.turnsToConstruction(building.name) + " {turns}".tr(),
building.getRejectionReason(cityConstructions)
)
if (building.isWonder)
buildableWonders += productionTextButton
else
@ -99,7 +111,7 @@ class ConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBaseScre
constructionPickerTable.addCategory("Buildings",buildableBuildings)
val specialConstructions = ArrayList<Table>()
for (specialConstruction in SpecialConstruction.getSpecialConstructions().filter { it.isBuildable(cityConstructions) }) {
for (specialConstruction in SpecialConstruction.getSpecialConstructions().filter { it.shouldBeDisplayed(cityConstructions) }) {
specialConstructions += getProductionButton(specialConstruction.name,
"Produce [${specialConstruction.name}]".tr())
}