Don't allow constructing stockpiled-resource-requiring constructions when lacking the resources

This commit is contained in:
yairm210
2024-08-29 10:32:31 +03:00
parent 3c42d44ec4
commit 3536218fc8
3 changed files with 27 additions and 12 deletions

View File

@ -259,6 +259,7 @@ class Building : RulesetStatsObject(), INonPerpetualConstruction {
override fun getRejectionReasons(cityConstructions: CityConstructions): Sequence<RejectionReason> = sequence {
val cityCenter = cityConstructions.city.getCenterTile()
val civ = cityConstructions.city.civ
val stateForConditionals = StateForConditionals(civ, cityConstructions.city)
if (cityConstructions.isBuilt(name))
yield(RejectionReasonType.AlreadyBuilt.toInstance())
@ -276,7 +277,7 @@ class Building : RulesetStatsObject(), INonPerpetualConstruction {
// EXCEPT for [UniqueType.OnlyAvailable] and [UniqueType.CanOnlyBeBuiltInCertainCities]
// since they trigger (reject) only if conditionals ARE NOT met
if (unique.type != UniqueType.OnlyAvailable && unique.type != UniqueType.CanOnlyBeBuiltWhen &&
!unique.conditionalsApply(StateForConditionals(civ, cityConstructions.city))) continue
!unique.conditionalsApply(stateForConditionals)) continue
when (unique.type) {
// for buildings that are created as side effects of other things, and not directly built,
@ -380,14 +381,20 @@ class Building : RulesetStatsObject(), INonPerpetualConstruction {
yield(RejectionReasonType.RequiresBuildingInThisCity.toInstance("Requires a [${civ.getEquivalentBuilding(requiredBuilding!!)}] in this city"))
}
for ((resourceName, requiredAmount) in getResourceRequirementsPerTurn(
StateForConditionals(cityConstructions.city.civ, cityConstructions.city))
) {
for ((resourceName, requiredAmount) in getResourceRequirementsPerTurn(stateForConditionals)) {
val availableAmount = cityConstructions.city.getAvailableResourceAmount(resourceName)
if (availableAmount < requiredAmount) {
yield(RejectionReasonType.ConsumesResources.toInstance(resourceName.getNeedMoreAmountString(requiredAmount - availableAmount)))
}
}
for (unique in getMatchingUniques(UniqueType.CostsResources, stateForConditionals)) {
val amount = unique.params[0].toInt()
val resourceName = unique.params[1]
val availableResources = cityConstructions.city.getAvailableResourceAmount(resourceName)
if (availableResources < amount)
yield(RejectionReasonType.ConsumesResources.toInstance(resourceName.getNeedMoreAmountString(amount - availableResources)))
}
if (requiredNearbyImprovedResources != null) {
val containsResourceWithImprovement = cityConstructions.city.getWorkableTiles()

View File

@ -202,6 +202,7 @@ class BaseUnit : RulesetObject(), INonPerpetualConstruction {
for (requiredTech: String in requiredTechs())
if (!civ.tech.isResearched(requiredTech))
yield(RejectionReasonType.RequiresTech.toInstance("$requiredTech not researched"))
for (obsoleteTech: String in techsAtWhichNoLongerAvailable())
if (civ.tech.isResearched(obsoleteTech))
yield(RejectionReasonType.Obsoleted.toInstance("Obsolete by $obsoleteTech"))
@ -234,6 +235,14 @@ class BaseUnit : RulesetObject(), INonPerpetualConstruction {
yield(RejectionReasonType.ConsumesResources.toInstance(message))
}
}
for (unique in getMatchingUniques(UniqueType.CostsResources, stateForConditionals)) {
val amount = unique.params[0].toInt()
val resourceName = unique.params[1]
val availableResources = city?.getAvailableResourceAmount(resourceName) ?: civ.getResourceAmount(resourceName)
if (availableResources < amount)
yield(RejectionReasonType.ConsumesResources.toInstance(resourceName.getNeedMoreAmountString(amount - availableResources)))
}
}
for (unique in civ.getMatchingUniques(UniqueType.CannotBuildUnits, stateForConditionals))

View File

@ -304,18 +304,17 @@ class ResourceTests {
game.gameInfo.nextTurn()
assert(civInfo.getCivResourcesByName()[resource.name] == 1) // 1 was consumed because production started
}
@Test
fun stockpiledResourcesConsumedWhenConstructionPurchased() {
fun constructionsRequiringStockpiledResourcesUnconstructableWithoutThem() {
// given
val resource = game.createResource(UniqueType.Stockpiled.text)
val consumingBuilding = game.createBuilding("Costs [1] [${resource.name}]")
assert(!consumingBuilding.isBuildable(city.cityConstructions))
val building = game.createBuilding("Instantly provides [2] [${resource.name}]")
city.cityConstructions.addBuilding(building)
assert(civInfo.getCivResourcesByName()[resource.name] == 2)
val consumingBuilding = game.createBuilding("Costs [1] [${resource.name}]")
assert(civInfo.getCivResourcesByName()[resource.name] == 2) // no change yet
city.cityConstructions.purchaseConstruction(consumingBuilding.name, -1, false)
assert(civInfo.getCivResourcesByName()[resource.name] == 1) // 1 was consumed because production started
assert(consumingBuilding.isBuildable(city.cityConstructions))
}
}