Resolved #6335 - now shows conditionals precluding construction of units (#6346)

* Resolved #6335 - now shows conditionals precluding construction of units

Built simply so that if we decide to expand the conditionals that should be shown it will simply be building a hashset of conditionalsToShow

* Added an instance wrapper, so the enum has the default values and the class has the actual values

* minor lint
This commit is contained in:
Yair Morgenstern
2022-03-13 22:45:39 +02:00
committed by GitHub
parent cea63eb114
commit 97787bd397
7 changed files with 115 additions and 96 deletions

View File

@ -39,178 +39,185 @@ FlagIcons/English
orig: 128, 128 orig: 128, 128
offset: 0, 0 offset: 0, 0
index: -1 index: -1
FlagIcons/Finnish FlagIcons/Filipino
rotate: false rotate: false
xy: 276, 276 xy: 276, 276
size: 128, 128 size: 128, 128
orig: 128, 128 orig: 128, 128
offset: 0, 0 offset: 0, 0
index: -1 index: -1
FlagIcons/French FlagIcons/Finnish
rotate: false rotate: false
xy: 140, 4 xy: 140, 4
size: 128, 128 size: 128, 128
orig: 128, 128 orig: 128, 128
offset: 0, 0 offset: 0, 0
index: -1 index: -1
FlagIcons/German FlagIcons/French
rotate: false rotate: false
xy: 276, 140 xy: 276, 140
size: 128, 128 size: 128, 128
orig: 128, 128 orig: 128, 128
offset: 0, 0 offset: 0, 0
index: -1 index: -1
FlagIcons/Greek FlagIcons/German
rotate: false rotate: false
xy: 412, 276 xy: 412, 276
size: 128, 128 size: 128, 128
orig: 128, 128 orig: 128, 128
offset: 0, 0 offset: 0, 0
index: -1 index: -1
FlagIcons/Hungarian FlagIcons/Greek
rotate: false rotate: false
xy: 276, 4 xy: 276, 4
size: 128, 128 size: 128, 128
orig: 128, 128 orig: 128, 128
offset: 0, 0 offset: 0, 0
index: -1 index: -1
FlagIcons/Indonesian FlagIcons/Hungarian
rotate: false rotate: false
xy: 412, 140 xy: 412, 140
size: 128, 128 size: 128, 128
orig: 128, 128 orig: 128, 128
offset: 0, 0 offset: 0, 0
index: -1 index: -1
FlagIcons/Italian FlagIcons/Indonesian
rotate: false rotate: false
xy: 548, 276 xy: 548, 276
size: 128, 128 size: 128, 128
orig: 128, 128 orig: 128, 128
offset: 0, 0 offset: 0, 0
index: -1 index: -1
FlagIcons/Japanese FlagIcons/Italian
rotate: false rotate: false
xy: 412, 4 xy: 412, 4
size: 128, 128 size: 128, 128
orig: 128, 128 orig: 128, 128
offset: 0, 0 offset: 0, 0
index: -1 index: -1
FlagIcons/Korean FlagIcons/Japanese
rotate: false rotate: false
xy: 548, 140 xy: 548, 140
size: 128, 128 size: 128, 128
orig: 128, 128 orig: 128, 128
offset: 0, 0 offset: 0, 0
index: -1 index: -1
FlagIcons/Lithuanian FlagIcons/Korean
rotate: false rotate: false
xy: 684, 276 xy: 684, 276
size: 128, 128 size: 128, 128
orig: 128, 128 orig: 128, 128
offset: 0, 0 offset: 0, 0
index: -1 index: -1
FlagIcons/Malay FlagIcons/Lithuanian
rotate: false rotate: false
xy: 548, 4 xy: 548, 4
size: 128, 128 size: 128, 128
orig: 128, 128 orig: 128, 128
offset: 0, 0 offset: 0, 0
index: -1 index: -1
FlagIcons/Malay
rotate: false
xy: 684, 140
size: 128, 128
orig: 128, 128
offset: 0, 0
index: -1
FlagIcons/Persian_(Pinglish-DIN) FlagIcons/Persian_(Pinglish-DIN)
rotate: false
xy: 684, 140
size: 128, 128
orig: 128, 128
offset: 0, 0
index: -1
FlagIcons/Persian_(Pinglish-UN)
rotate: false
xy: 684, 140
size: 128, 128
orig: 128, 128
offset: 0, 0
index: -1
FlagIcons/Polish
rotate: false rotate: false
xy: 820, 276 xy: 820, 276
size: 128, 128 size: 128, 128
orig: 128, 128 orig: 128, 128
offset: 0, 0 offset: 0, 0
index: -1 index: -1
FlagIcons/Portuguese FlagIcons/Persian_(Pinglish-UN)
rotate: false
xy: 820, 276
size: 128, 128
orig: 128, 128
offset: 0, 0
index: -1
FlagIcons/Polish
rotate: false rotate: false
xy: 684, 4 xy: 684, 4
size: 128, 128 size: 128, 128
orig: 128, 128 orig: 128, 128
offset: 0, 0 offset: 0, 0
index: -1 index: -1
FlagIcons/Romanian FlagIcons/Portuguese
rotate: false rotate: false
xy: 820, 140 xy: 820, 140
size: 128, 128 size: 128, 128
orig: 128, 128 orig: 128, 128
offset: 0, 0 offset: 0, 0
index: -1 index: -1
FlagIcons/Russian FlagIcons/Romanian
rotate: false rotate: false
xy: 956, 276 xy: 956, 276
size: 128, 128 size: 128, 128
orig: 128, 128 orig: 128, 128
offset: 0, 0 offset: 0, 0
index: -1 index: -1
FlagIcons/Simplified_Chinese FlagIcons/Russian
rotate: false rotate: false
xy: 820, 4 xy: 820, 4
size: 128, 128 size: 128, 128
orig: 128, 128 orig: 128, 128
offset: 0, 0 offset: 0, 0
index: -1 index: -1
FlagIcons/Spanish FlagIcons/Simplified_Chinese
rotate: false rotate: false
xy: 956, 140 xy: 956, 140
size: 128, 128 size: 128, 128
orig: 128, 128 orig: 128, 128
offset: 0, 0 offset: 0, 0
index: -1 index: -1
FlagIcons/Swedish FlagIcons/Spanish
rotate: false rotate: false
xy: 1092, 276 xy: 1092, 276
size: 128, 128 size: 128, 128
orig: 128, 128 orig: 128, 128
offset: 0, 0 offset: 0, 0
index: -1 index: -1
FlagIcons/Thai FlagIcons/Swedish
rotate: false rotate: false
xy: 956, 4 xy: 956, 4
size: 128, 128 size: 128, 128
orig: 128, 128 orig: 128, 128
offset: 0, 0 offset: 0, 0
index: -1 index: -1
FlagIcons/Traditional_Chinese FlagIcons/Thai
rotate: false rotate: false
xy: 1092, 140 xy: 1092, 140
size: 128, 128 size: 128, 128
orig: 128, 128 orig: 128, 128
offset: 0, 0 offset: 0, 0
index: -1 index: -1
FlagIcons/Turkish FlagIcons/Traditional_Chinese
rotate: false rotate: false
xy: 1228, 276 xy: 1228, 276
size: 128, 128 size: 128, 128
orig: 128, 128 orig: 128, 128
offset: 0, 0 offset: 0, 0
index: -1 index: -1
FlagIcons/Ukrainian FlagIcons/Turkish
rotate: false rotate: false
xy: 1092, 4 xy: 1092, 4
size: 128, 128 size: 128, 128
orig: 128, 128 orig: 128, 128
offset: 0, 0 offset: 0, 0
index: -1 index: -1
FlagIcons/Vietnamese FlagIcons/Ukrainian
rotate: false rotate: false
xy: 1228, 140 xy: 1228, 140
size: 128, 128 size: 128, 128
orig: 128, 128 orig: 128, 128
offset: 0, 0 offset: 0, 0
index: -1 index: -1
FlagIcons/Vietnamese
rotate: false
xy: 1364, 276
size: 128, 128
orig: 128, 128
offset: 0, 0
index: -1

Binary file not shown.

Before

Width:  |  Height:  |  Size: 148 KiB

After

Width:  |  Height:  |  Size: 158 KiB

View File

@ -378,7 +378,7 @@ class CityConstructions {
} }
} else if (construction is BaseUnit) { } else if (construction is BaseUnit) {
// Production put into upgradable units gets put into upgraded version // Production put into upgradable units gets put into upgraded version
if (rejectionReasons.all { it == RejectionReason.Obsoleted } && construction.upgradesTo != null) { if (rejectionReasons.all { it.rejectionReason == RejectionReason.Obsoleted } && construction.upgradesTo != null) {
inProgressConstructions[construction.upgradesTo!!] = inProgressConstructions[construction.upgradesTo!!] =
(inProgressConstructions[construction.upgradesTo!!] ?: 0) + workDone (inProgressConstructions[construction.upgradesTo!!] ?: 0) + workDone
} }

View File

@ -44,7 +44,7 @@ interface INonPerpetualConstruction : IConstruction, INamed, IHasUniques {
/** Checks if the construction should be purchasable, not whether it can be bought with a stat at all */ /** Checks if the construction should be purchasable, not whether it can be bought with a stat at all */
fun isPurchasable(cityConstructions: CityConstructions): Boolean { fun isPurchasable(cityConstructions: CityConstructions): Boolean {
val rejectionReasons = getRejectionReasons(cityConstructions) val rejectionReasons = getRejectionReasons(cityConstructions)
return rejectionReasons.all { it == RejectionReason.Unbuildable } return rejectionReasons.all { it.rejectionReason == RejectionReason.Unbuildable }
} }
fun canBePurchasedWithAnyStat(cityInfo: CityInfo): Boolean { fun canBePurchasedWithAnyStat(cityInfo: CityInfo): Boolean {
@ -82,18 +82,22 @@ interface INonPerpetualConstruction : IConstruction, INamed, IHasUniques {
class RejectionReasons: HashSet<RejectionReason>() { class RejectionReasons: HashSet<RejectionReasonInstance>() {
fun add(rejectionReason: RejectionReason) = add(RejectionReasonInstance(rejectionReason))
fun contains(rejectionReason: RejectionReason) = any { it.rejectionReason == rejectionReason }
fun filterTechPolicyEraWonderRequirements(): HashSet<RejectionReason> { fun filterTechPolicyEraWonderRequirements(): List<RejectionReasonInstance> {
return filterNot { it in techPolicyEraWonderRequirements }.toHashSet() return filterNot { it.rejectionReason in techPolicyEraWonderRequirements }
} }
fun hasAReasonToBeRemovedFromQueue(): Boolean { fun hasAReasonToBeRemovedFromQueue(): Boolean {
return any { it in reasonsToDefinitivelyRemoveFromQueue } return any { it.rejectionReason in reasonsToDefinitivelyRemoveFromQueue }
} }
fun getMostImportantRejectionReason(): String? { fun getMostImportantRejectionReason(): String? {
return orderOfErrorMessages.firstOrNull { it in this }?.errorMessage return orderOfErrorMessages.firstOrNull { contains(it) }?.errorMessage
} }
// Used for constant variables in the functions above // Used for constant variables in the functions above
@ -127,9 +131,7 @@ class RejectionReasons: HashSet<RejectionReason>() {
} }
// TODO: Put a wrapper class around this containing the errorMessage, so that we don't enum class RejectionReason(val shouldShow: Boolean, val errorMessage: String) {
// change the value of a enum constant sometimes.
enum class RejectionReason(val shouldShow: Boolean, var errorMessage: String) {
AlreadyBuilt(false, "Building already built in this city"), AlreadyBuilt(false, "Building already built in this city"),
Unbuildable(false, "Unbuildable"), Unbuildable(false, "Unbuildable"),
CanOnlyBePurchased(true, "Can only be purchased"), CanOnlyBePurchased(true, "Can only be purchased"),
@ -178,9 +180,18 @@ enum class RejectionReason(val shouldShow: Boolean, var errorMessage: String) {
PopulationRequirement(true, "Requires more population"), PopulationRequirement(true, "Requires more population"),
NoSettlerForOneCityPlayers(false, "No settlers for city-states or one-city challengers"), NoSettlerForOneCityPlayers(false, "No settlers for city-states or one-city challengers");
fun toInstance(errorMessage: String = this.errorMessage,
shouldShow: Boolean = this.shouldShow): RejectionReasonInstance {
return RejectionReasonInstance(this, errorMessage, shouldShow)
}
} }
data class RejectionReasonInstance(val rejectionReason:RejectionReason,
val errorMessage: String = rejectionReason.errorMessage,
val shouldShow: Boolean = rejectionReason.shouldShow)
open class PerpetualConstruction(override var name: String, val description: String) : IConstruction { open class PerpetualConstruction(override var name: String, val description: String) : IConstruction {

View File

@ -434,7 +434,7 @@ class Building : RulesetStatsObject(), INonPerpetualConstruction {
return rejectionReasons.none { !it.shouldShow } return rejectionReasons.none { !it.shouldShow }
|| ( || (
canBePurchasedWithAnyStat(cityConstructions.cityInfo) canBePurchasedWithAnyStat(cityConstructions.cityInfo)
&& rejectionReasons.all { it == RejectionReason.Unbuildable } && rejectionReasons.all { it.rejectionReason == RejectionReason.Unbuildable }
) )
} }
@ -471,25 +471,25 @@ class Building : RulesetStatsObject(), INonPerpetualConstruction {
UniqueType.MustBeOn -> UniqueType.MustBeOn ->
if (!cityCenter.matchesTerrainFilter(unique.params[0], civInfo)) if (!cityCenter.matchesTerrainFilter(unique.params[0], civInfo))
rejectionReasons.add(RejectionReason.MustBeOnTile.apply { errorMessage = unique.text }) rejectionReasons.add(RejectionReason.MustBeOnTile.toInstance(unique.text))
UniqueType.MustNotBeOn -> UniqueType.MustNotBeOn ->
if (cityCenter.matchesTerrainFilter(unique.params[0], civInfo)) if (cityCenter.matchesTerrainFilter(unique.params[0], civInfo))
rejectionReasons.add(RejectionReason.MustNotBeOnTile.apply { errorMessage = unique.text }) rejectionReasons.add(RejectionReason.MustNotBeOnTile.toInstance(unique.text))
UniqueType.MustBeNextTo -> UniqueType.MustBeNextTo ->
if (!cityCenter.isAdjacentTo(unique.params[0])) if (!cityCenter.isAdjacentTo(unique.params[0]))
rejectionReasons.add(RejectionReason.MustBeNextToTile.apply { errorMessage = unique.text }) rejectionReasons.add(RejectionReason.MustBeNextToTile.toInstance(unique.text))
UniqueType.MustNotBeNextTo -> UniqueType.MustNotBeNextTo ->
if (cityCenter.getTilesInDistance(1).any { it.matchesFilter(unique.params[0], civInfo) }) if (cityCenter.getTilesInDistance(1).any { it.matchesFilter(unique.params[0], civInfo) })
rejectionReasons.add(RejectionReason.MustNotBeNextToTile.apply { errorMessage = unique.text }) rejectionReasons.add(RejectionReason.MustNotBeNextToTile.toInstance(unique.text))
UniqueType.MustHaveOwnedWithinTiles -> UniqueType.MustHaveOwnedWithinTiles ->
if (cityCenter.getTilesInDistance(unique.params[1].toInt()) if (cityCenter.getTilesInDistance(unique.params[1].toInt())
.none { it.matchesFilter(unique.params[0], civInfo) && it.getOwner() == cityConstructions.cityInfo.civInfo } .none { it.matchesFilter(unique.params[0], civInfo) && it.getOwner() == cityConstructions.cityInfo.civInfo }
) )
rejectionReasons.add(RejectionReason.MustOwnTile.apply { errorMessage = unique.text }) rejectionReasons.add(RejectionReason.MustOwnTile.toInstance(unique.text))
// Deprecated since 3.16.11 // Deprecated since 3.16.11
UniqueType.CanOnlyBeBuiltInAnnexedCities -> UniqueType.CanOnlyBeBuiltInAnnexedCities ->
@ -497,16 +497,16 @@ class Building : RulesetStatsObject(), INonPerpetualConstruction {
cityConstructions.cityInfo.isPuppet cityConstructions.cityInfo.isPuppet
|| cityConstructions.cityInfo.civInfo.civName == cityConstructions.cityInfo.foundingCiv || cityConstructions.cityInfo.civInfo.civName == cityConstructions.cityInfo.foundingCiv
) )
rejectionReasons.add(RejectionReason.CanOnlyBeBuiltInSpecificCities.apply { errorMessage = unique.text }) rejectionReasons.add(RejectionReason.CanOnlyBeBuiltInSpecificCities.toInstance(unique.text))
// //
UniqueType.CanOnlyBeBuiltInCertainCities -> UniqueType.CanOnlyBeBuiltInCertainCities ->
if (!cityConstructions.cityInfo.matchesFilter(unique.params[0])) if (!cityConstructions.cityInfo.matchesFilter(unique.params[0]))
rejectionReasons.add(RejectionReason.CanOnlyBeBuiltInSpecificCities.apply { errorMessage = unique.text }) rejectionReasons.add(RejectionReason.CanOnlyBeBuiltInSpecificCities.toInstance(unique.text))
UniqueType.ObsoleteWith -> UniqueType.ObsoleteWith ->
if (civInfo.tech.isResearched(unique.params[0])) if (civInfo.tech.isResearched(unique.params[0]))
rejectionReasons.add(RejectionReason.Obsoleted.apply { errorMessage = unique.text }) rejectionReasons.add(RejectionReason.Obsoleted.toInstance(unique.text))
UniqueType.HiddenWithoutReligion -> UniqueType.HiddenWithoutReligion ->
if (!civInfo.gameInfo.isReligionEnabled()) if (!civInfo.gameInfo.isReligionEnabled())
@ -522,22 +522,22 @@ class Building : RulesetStatsObject(), INonPerpetualConstruction {
when { when {
ruleSet.technologies.contains(filter) -> ruleSet.technologies.contains(filter) ->
if (!civInfo.tech.isResearched(filter)) if (!civInfo.tech.isResearched(filter))
rejectionReasons.add(RejectionReason.RequiresTech.apply { errorMessage = unique.text }) rejectionReasons.add(RejectionReason.RequiresTech.toInstance(unique.text))
ruleSet.policies.contains(filter) -> ruleSet.policies.contains(filter) ->
if (!civInfo.policies.isAdopted(filter)) if (!civInfo.policies.isAdopted(filter))
rejectionReasons.add(RejectionReason.RequiresPolicy.apply { errorMessage = unique.text }) rejectionReasons.add(RejectionReason.RequiresPolicy.toInstance(unique.text))
ruleSet.eras.contains(filter) -> ruleSet.eras.contains(filter) ->
if (civInfo.getEraNumber() < ruleSet.eras[filter]!!.eraNumber) if (civInfo.getEraNumber() < ruleSet.eras[filter]!!.eraNumber)
rejectionReasons.add(RejectionReason.UnlockedWithEra.apply { errorMessage = unique.text }) rejectionReasons.add(RejectionReason.UnlockedWithEra.toInstance(unique.text))
ruleSet.buildings.contains(filter) -> ruleSet.buildings.contains(filter) ->
if (civInfo.cities.none { it.cityConstructions.containsBuildingOrEquivalent(filter) }) if (civInfo.cities.none { it.cityConstructions.containsBuildingOrEquivalent(filter) })
rejectionReasons.add(RejectionReason.RequiresBuildingInSomeCity.apply { errorMessage = unique.text }) rejectionReasons.add(RejectionReason.RequiresBuildingInSomeCity.toInstance(unique.text))
} }
} }
UniqueType.SpaceshipPart -> { UniqueType.SpaceshipPart -> {
if (!civInfo.hasUnique(UniqueType.EnablesConstructionOfSpaceshipParts)) if (!civInfo.hasUnique(UniqueType.EnablesConstructionOfSpaceshipParts))
rejectionReasons.add(RejectionReason.RequiresBuildingInSomeCity.apply { errorMessage = "Apollo project not built!" }) rejectionReasons.add(RejectionReason.RequiresBuildingInSomeCity.toInstance("Apollo project not built!"))
if (civInfo.victoryManager.unconstructedSpaceshipParts()[name] == 0) if (civInfo.victoryManager.unconstructedSpaceshipParts()[name] == 0)
rejectionReasons.add(RejectionReason.ReachedBuildCap) rejectionReasons.add(RejectionReason.ReachedBuildCap)
} }
@ -547,7 +547,7 @@ class Building : RulesetStatsObject(), INonPerpetualConstruction {
if (civInfo.gameInfo.ruleSet.buildings.containsKey(filter) && !cityConstructions.containsBuildingOrEquivalent(filter)) if (civInfo.gameInfo.ruleSet.buildings.containsKey(filter) && !cityConstructions.containsBuildingOrEquivalent(filter))
rejectionReasons.add( rejectionReasons.add(
// replace with civ-specific building for user // replace with civ-specific building for user
RejectionReason.RequiresBuildingInThisCity.apply { errorMessage = "Requires a [${civInfo.getEquivalentBuilding(filter)}] in this city" } RejectionReason.RequiresBuildingInThisCity.toInstance("Requires a [${civInfo.getEquivalentBuilding(filter)}] in this city")
) )
} }
@ -561,11 +561,10 @@ class Building : RulesetStatsObject(), INonPerpetualConstruction {
val equivalentBuildingName = civInfo.getEquivalentBuilding(buildingName).name val equivalentBuildingName = civInfo.getEquivalentBuilding(buildingName).name
rejectionReasons.add( rejectionReasons.add(
// replace with civ-specific building for user // replace with civ-specific building for user
RejectionReason.RequiresBuildingInAllCities.apply { RejectionReason.RequiresBuildingInAllCities.toInstance(
errorMessage = unique.text.fillPlaceholders(equivalentBuildingName, numberOfCitiesRequired.toString()) + unique.text.fillPlaceholders(equivalentBuildingName, numberOfCitiesRequired.toString()) +
" ($numberOfCitiesWithBuilding/$numberOfCitiesRequired)" " ($numberOfCitiesWithBuilding/$numberOfCitiesRequired)"
} ) )
)
} }
} }
@ -578,33 +577,33 @@ class Building : RulesetStatsObject(), INonPerpetualConstruction {
) { ) {
rejectionReasons.add( rejectionReasons.add(
// replace with civ-specific building for user // replace with civ-specific building for user
RejectionReason.RequiresBuildingInAllCities.apply { RejectionReason.RequiresBuildingInAllCities.toInstance(
errorMessage = "Requires a [${civInfo.getEquivalentBuilding(unique.params[0])}] in all cities" "Requires a [${civInfo.getEquivalentBuilding(unique.params[0])}] in all cities"
} )
) )
} }
} }
UniqueType.HiddenBeforeAmountPolicies -> { UniqueType.HiddenBeforeAmountPolicies -> {
if (cityConstructions.cityInfo.civInfo.getCompletedPolicyBranchesCount() < unique.params[0].toInt()) if (cityConstructions.cityInfo.civInfo.getCompletedPolicyBranchesCount() < unique.params[0].toInt())
rejectionReasons.add(RejectionReason.MorePolicyBranches.apply { errorMessage = unique.text }) rejectionReasons.add(RejectionReason.MorePolicyBranches.toInstance(unique.text))
} }
UniqueType.HiddenWithoutVictoryType -> { UniqueType.HiddenWithoutVictoryType -> {
if (!civInfo.gameInfo.gameParameters.victoryTypes.contains(VictoryType.valueOf(unique.params[0]))) if (!civInfo.gameInfo.gameParameters.victoryTypes.contains(VictoryType.valueOf(unique.params[0])))
rejectionReasons.add(RejectionReason.HiddenWithoutVictory.apply { errorMessage = unique.text }) rejectionReasons.add(RejectionReason.HiddenWithoutVictory.toInstance(unique.text))
} }
} }
} }
if (uniqueTo != null && uniqueTo != civInfo.civName) if (uniqueTo != null && uniqueTo != civInfo.civName)
rejectionReasons.add(RejectionReason.UniqueToOtherNation.apply { errorMessage = "Unique to $uniqueTo"}) rejectionReasons.add(RejectionReason.UniqueToOtherNation.toInstance("Unique to $uniqueTo"))
if (civInfo.gameInfo.ruleSet.buildings.values.any { it.uniqueTo == civInfo.civName && it.replaces == name }) if (civInfo.gameInfo.ruleSet.buildings.values.any { it.uniqueTo == civInfo.civName && it.replaces == name })
rejectionReasons.add(RejectionReason.ReplacedByOurUnique) rejectionReasons.add(RejectionReason.ReplacedByOurUnique)
if (requiredTech != null && !civInfo.tech.isResearched(requiredTech!!)) if (requiredTech != null && !civInfo.tech.isResearched(requiredTech!!))
rejectionReasons.add(RejectionReason.RequiresTech.apply { "$requiredTech not researched!"}) rejectionReasons.add(RejectionReason.RequiresTech.toInstance("$requiredTech not researched!"))
// Regular wonders // Regular wonders
if (isWonder) { if (isWonder) {
@ -635,19 +634,17 @@ class Building : RulesetStatsObject(), INonPerpetualConstruction {
} }
if (requiredBuilding != null && !cityConstructions.containsBuildingOrEquivalent(requiredBuilding!!)) { if (requiredBuilding != null && !cityConstructions.containsBuildingOrEquivalent(requiredBuilding!!)) {
rejectionReasons.add(RejectionReason.RequiresBuildingInThisCity.apply { errorMessage = "Requires a [${civInfo.getEquivalentBuilding(requiredBuilding!!)}] in this city"}) rejectionReasons.add(RejectionReason.RequiresBuildingInThisCity.toInstance("Requires a [${civInfo.getEquivalentBuilding(requiredBuilding!!)}] in this city"))
} }
val cannotBeBuiltWithUnique = uniqueObjects val cannotBeBuiltWithUnique = uniqueObjects
.firstOrNull { it.isOfType(UniqueType.CannotBeBuiltWith) } .firstOrNull { it.isOfType(UniqueType.CannotBeBuiltWith) }
if (cannotBeBuiltWithUnique != null && cityConstructions.containsBuildingOrEquivalent(cannotBeBuiltWithUnique.params[0])) if (cannotBeBuiltWithUnique != null && cityConstructions.containsBuildingOrEquivalent(cannotBeBuiltWithUnique.params[0]))
rejectionReasons.add(RejectionReason.CannotBeBuiltWith.apply { errorMessage = cannotBeBuiltWithUnique.text }) rejectionReasons.add(RejectionReason.CannotBeBuiltWith.toInstance(cannotBeBuiltWithUnique.text))
for ((resource, amount) in getResourceRequirements()) for ((resource, amount) in getResourceRequirements())
if (civInfo.getCivResourcesByName()[resource]!! < amount) { if (civInfo.getCivResourcesByName()[resource]!! < amount) {
rejectionReasons.add(RejectionReason.ConsumesResources.apply { rejectionReasons.add(RejectionReason.ConsumesResources.toInstance("Consumes [$amount] [$resource]" ))
errorMessage = "Consumes [$amount] [$resource]"
})
} }
if (requiredNearbyImprovedResources != null) { if (requiredNearbyImprovedResources != null) {
@ -661,7 +658,7 @@ class Building : RulesetStatsObject(), INonPerpetualConstruction {
) )
} }
if (!containsResourceWithImprovement) if (!containsResourceWithImprovement)
rejectionReasons.add(RejectionReason.RequiresNearbyResource.apply { errorMessage = "Nearby $requiredNearbyImprovedResources required" }) rejectionReasons.add(RejectionReason.RequiresNearbyResource.toInstance("Nearby $requiredNearbyImprovedResources required"))
} }
return rejectionReasons return rejectionReasons

View File

@ -342,7 +342,7 @@ class BaseUnit : RulesetObject(), INonPerpetualConstruction {
return rejectionReasons.none { !it.shouldShow } return rejectionReasons.none { !it.shouldShow }
|| ( || (
canBePurchasedWithAnyStat(cityConstructions.cityInfo) canBePurchasedWithAnyStat(cityConstructions.cityInfo)
&& rejectionReasons.all { it == RejectionReason.Unbuildable } && rejectionReasons.all { it.rejectionReason == RejectionReason.Unbuildable }
) )
} }
@ -365,7 +365,7 @@ class BaseUnit : RulesetObject(), INonPerpetualConstruction {
} }
UniqueType.RequiresPopulation -> if (unique.params[0].toInt() > cityConstructions.cityInfo.population.population) UniqueType.RequiresPopulation -> if (unique.params[0].toInt() > cityConstructions.cityInfo.population.population)
rejectionReasons.add(RejectionReason.PopulationRequirement.apply { errorMessage = unique.text }) rejectionReasons.add(RejectionReason.PopulationRequirement.toInstance(unique.text))
} }
} }
@ -381,14 +381,14 @@ class BaseUnit : RulesetObject(), INonPerpetualConstruction {
val ruleSet = civInfo.gameInfo.ruleSet val ruleSet = civInfo.gameInfo.ruleSet
if (requiredTech != null && !civInfo.tech.isResearched(requiredTech!!)) if (requiredTech != null && !civInfo.tech.isResearched(requiredTech!!))
rejectionReasons.add(RejectionReason.RequiresTech.apply { this.errorMessage = "$requiredTech not researched" }) rejectionReasons.add(RejectionReason.RequiresTech.toInstance("$requiredTech not researched"))
if (obsoleteTech != null && civInfo.tech.isResearched(obsoleteTech!!)) if (obsoleteTech != null && civInfo.tech.isResearched(obsoleteTech!!))
rejectionReasons.add(RejectionReason.Obsoleted.apply { this.errorMessage = "Obsolete by $obsoleteTech" }) rejectionReasons.add(RejectionReason.Obsoleted.toInstance("Obsolete by $obsoleteTech"))
if (uniqueTo != null && uniqueTo != civInfo.civName) if (uniqueTo != null && uniqueTo != civInfo.civName)
rejectionReasons.add(RejectionReason.UniqueToOtherNation.apply { this.errorMessage = "Unique to $uniqueTo" }) rejectionReasons.add(RejectionReason.UniqueToOtherNation.toInstance("Unique to $uniqueTo"))
if (ruleSet.units.values.any { it.uniqueTo == civInfo.civName && it.replaces == name }) if (ruleSet.units.values.any { it.uniqueTo == civInfo.civName && it.replaces == name })
rejectionReasons.add(RejectionReason.ReplacedByOurUnique.apply { this.errorMessage = "Our unique unit replaces this" }) rejectionReasons.add(RejectionReason.ReplacedByOurUnique.toInstance("Our unique unit replaces this"))
if (!civInfo.gameInfo.gameParameters.nuclearWeaponsEnabled && isNuclearWeapon()) if (!civInfo.gameInfo.gameParameters.nuclearWeaponsEnabled && isNuclearWeapon())
rejectionReasons.add(RejectionReason.DisabledBySetting) rejectionReasons.add(RejectionReason.DisabledBySetting)
@ -404,16 +404,16 @@ class BaseUnit : RulesetObject(), INonPerpetualConstruction {
when { when {
ruleSet.technologies.contains(filter) -> ruleSet.technologies.contains(filter) ->
if (!civInfo.tech.isResearched(filter)) if (!civInfo.tech.isResearched(filter))
rejectionReasons.add(RejectionReason.RequiresTech.apply { errorMessage = unique.text }) rejectionReasons.add(RejectionReason.RequiresTech.toInstance(unique.text))
ruleSet.policies.contains(filter) -> ruleSet.policies.contains(filter) ->
if (!civInfo.policies.isAdopted(filter)) if (!civInfo.policies.isAdopted(filter))
rejectionReasons.add(RejectionReason.RequiresPolicy.apply { errorMessage = unique.text }) rejectionReasons.add(RejectionReason.RequiresPolicy.toInstance(unique.text))
ruleSet.eras.contains(filter) -> ruleSet.eras.contains(filter) ->
if (civInfo.getEraNumber() < ruleSet.eras[filter]!!.eraNumber) if (civInfo.getEraNumber() < ruleSet.eras[filter]!!.eraNumber)
rejectionReasons.add(RejectionReason.UnlockedWithEra.apply { errorMessage = unique.text }) rejectionReasons.add(RejectionReason.UnlockedWithEra.toInstance(unique.text))
ruleSet.buildings.contains(filter) -> ruleSet.buildings.contains(filter) ->
if (civInfo.cities.none { it.cityConstructions.containsBuildingOrEquivalent(filter) }) if (civInfo.cities.none { it.cityConstructions.containsBuildingOrEquivalent(filter) })
rejectionReasons.add(RejectionReason.RequiresBuildingInSomeCity.apply { errorMessage = unique.text }) rejectionReasons.add(RejectionReason.RequiresBuildingInSomeCity.toInstance(unique.text))
} }
} }
@ -428,15 +428,19 @@ class BaseUnit : RulesetObject(), INonPerpetualConstruction {
if (!civInfo.isBarbarian()) { // Barbarians don't need resources if (!civInfo.isBarbarian()) { // Barbarians don't need resources
for ((resource, amount) in getResourceRequirements()) for ((resource, amount) in getResourceRequirements())
if (civInfo.getCivResourcesByName()[resource]!! < amount) { if (civInfo.getCivResourcesByName()[resource]!! < amount) {
rejectionReasons.add(RejectionReason.ConsumesResources.apply { rejectionReasons.add(RejectionReason.ConsumesResources.toInstance("Consumes [$amount] [$resource]"))
errorMessage = "Consumes [$amount] [$resource]"
})
} }
} }
if (civInfo.getMatchingUniques(UniqueType.CannotBuildUnits).any { matchesFilter(it.params[0]) }) { for (unique in civInfo.getMatchingUniques(UniqueType.CannotBuildUnits))
rejectionReasons.add(RejectionReason.CannotBeBuilt) if (this.matchesFilter(unique.params[0])) {
} val rejectionReason = RejectionReason.CannotBeBuilt.toInstance()
if (unique.conditionals.any { it.type == UniqueType.ConditionalBelowHappiness }){
rejectionReasons.add(RejectionReason.CannotBeBuilt.toInstance(unique.text, true))
}
else rejectionReasons.add(RejectionReason.CannotBeBuilt)
}
return rejectionReasons return rejectionReasons
} }

View File

@ -166,7 +166,7 @@ object UnitActions {
* (no movement left, too close to another city). * (no movement left, too close to another city).
*/ */
fun getFoundCityAction(unit: MapUnit, tile: TileInfo): UnitAction? { fun getFoundCityAction(unit: MapUnit, tile: TileInfo): UnitAction? {
if (!(unit.hasUnique(UniqueType.FoundCity)) if (!unit.hasUnique(UniqueType.FoundCity)
|| tile.isWater || tile.isImpassible()) return null || tile.isWater || tile.isImpassible()) return null
// Spain should still be able to build Conquistadors in a one city challenge - but can't settle them // Spain should still be able to build Conquistadors in a one city challenge - but can't settle them
if (unit.civInfo.isOneCityChallenger() && unit.civInfo.hasEverOwnedOriginalCapital == true) return null if (unit.civInfo.isOneCityChallenger() && unit.civInfo.hasEverOwnedOriginalCapital == true) return null