Miscellaneous linting, Unique typifying, refactoring, bugfix/consistency to avoid broken links to disabled religious UBs. (#6012)

* Remove unused Constants.

* Remove outdated comments.

* Typified "Will not be displayed in Civilopedia" Unique.

* Fix pre-existing inconsistency that would display religious UBs with broken links in the Civilopedia when religion was disabled.

* Use Sequences, and fewer function params, in Nations' Civilopedia texts.

* Accidentally hid a Unique that should be visible.

* Oops… Missed a negation.

* Unhide limitations on Religious Ruin rewards— But I'm not sure they'll be displayed anywhere even so.
This commit is contained in:
will-ca
2022-01-23 09:08:26 -08:00
committed by GitHub
parent 2b7e279b4d
commit da748a96f9
9 changed files with 70 additions and 78 deletions

View File

@ -6,7 +6,6 @@ object Constants {
const val eraSpecificUnit = "Era Starting Unit"
const val spreadReligionAbilityCount = "Spread Religion"
const val removeHeresyAbilityCount = "Remove Foreign religions from your own cities"
const val hideFromCivilopediaUnique = "Will not be displayed in Civilopedia"
const val impassable = "Impassable"
const val ocean = "Ocean"
@ -23,9 +22,6 @@ object Constants {
const val forest = "Forest"
const val jungle = "Jungle"
const val marsh = "Marsh"
const val oasis = "Oasis"
const val atoll = "Atoll"
const val ice = "Ice"
const val floodPlains = "Flood plains"
val vegetation = arrayOf(forest, jungle)
@ -41,7 +37,6 @@ object Constants {
const val fort = "Fort"
const val citadel = "Citadel"
const val tradingPost = "Trading post"
const val futureTech = "Future Tech"
// Easter egg name. Hopefully is to hopefully avoid conflicts when later players can name their own religions.
@ -55,8 +50,6 @@ object Constants {
const val close = "Close"
const val yes = "Yes"
const val no = "No"
const val enabled = "enabled"
const val disabled = "disabled"
const val barbarians = "Barbarians"
const val spectator = "Spectator"

View File

@ -332,7 +332,6 @@ class WorkerAutomation(
*/
private fun chooseImprovement(unit: MapUnit, tile: TileInfo): TileImprovement? {
// turnsToBuild is what defines them as buildable
val potentialTileImprovements = ruleSet.tileImprovements.filter {
unit.canBuildImprovement(it.value, tile)
&& tile.canImprovementBeBuiltHere(it.value, tile.hasViewableResource(civInfo))

View File

@ -598,7 +598,6 @@ class UnitMovementAlgorithms(val unit:MapUnit) {
}
if (tile.isLand
&& unit.baseUnit.isWaterUnit()
// Check that the tile is not a coastal city's center
&& !tile.isCityCenter())
return false

View File

@ -96,11 +96,9 @@ class Building : RulesetStatsObject(), INonPerpetualConstruction {
/**
* @param filterUniques If provided, include only uniques for which this function returns true.
*/
private fun getUniquesStringsWithoutDisablers(filterUniques: ((Unique) -> Boolean)? = null) = getUniquesStrings(filterUniques=filterUniques)
.filterNot {
it.startsWith("Hidden ") && it.endsWith(" disabled") ||
it == UniqueType.Unbuildable.text ||
it == Constants.hideFromCivilopediaUnique
private fun getUniquesStringsWithoutDisablers(filterUniques: ((Unique) -> Boolean)? = null) = getUniquesStrings {
!it.hasFlag(UniqueFlag.HiddenToUsers)
&& filterUniques?.invoke(it) ?: true
}
/** used in CityScreen (CityInfoTable and ConstructionInfoTable) */
@ -474,7 +472,7 @@ class Building : RulesetStatsObject(), INonPerpetualConstruction {
rejectionReasons.add(RejectionReason.Unbuildable)
for (unique in uniqueObjects) {
when (unique.placeholderText) {
when (unique.placeholderText) { // TODO: Lots of typification…
// Deprecated since 3.16.11, replace with "Not displayed [...] construction without []"
UniqueType.NotDisplayedUnlessOtherBuildingBuilt.placeholderText ->
if (!cityConstructions.containsBuildingOrEquivalent(unique.params[0]))

View File

@ -138,9 +138,9 @@ class Nation : RulesetObject() {
}
textList += FormattedLine()
}
addUniqueBuildingsText(textList, ruleset)
addUniqueUnitsText(textList, ruleset)
addUniqueImprovementsText(textList, ruleset)
textList += getUniqueBuildingsText(ruleset)
textList += getUniqueUnitsText(ruleset)
textList += getUniqueImprovementsText(ruleset)
return textList
}
@ -193,102 +193,106 @@ class Nation : RulesetObject() {
return textList
}
private fun addUniqueBuildingsText(textList: ArrayList<FormattedLine>, ruleset: Ruleset) {
private fun getUniqueBuildingsText(ruleset: Ruleset) = sequence {
for (building in ruleset.buildings.values) {
if (building.uniqueTo != name || Constants.hideFromCivilopediaUnique in building.uniques) continue
textList += FormattedLine("{${building.name}} -", link=building.makeLink())
when {
building.uniqueTo != name -> continue
building.hasUnique(UniqueType.HiddenFromCivilopedia) -> continue
UncivGame.Current.isGameInfoInitialized() && !UncivGame.Current.gameInfo.isReligionEnabled() && building.hasUnique(UniqueType.HiddenWithoutReligion) -> continue // This seems consistent with existing behaviour of CivilopediaScreen's init.<locals>.shouldBeDisplayed(), and Technology().getEnabledUnits(). Otherwise there are broken links in the Civilopedia (E.G. to "Pyramid" and "Shrine", from "The Maya").
}
yield(FormattedLine("{${building.name}} -", link=building.makeLink()))
if (building.replaces != null && ruleset.buildings.containsKey(building.replaces!!)) {
val originalBuilding = ruleset.buildings[building.replaces!!]!!
textList += FormattedLine("Replaces [${originalBuilding.name}]", link=originalBuilding.makeLink(), indent=1)
yield(FormattedLine("Replaces [${originalBuilding.name}]", link=originalBuilding.makeLink(), indent=1))
for ((key, value) in building)
if (value != originalBuilding[key])
textList += FormattedLine( key.name.tr() + " " +"[${value.toInt()}] vs [${originalBuilding[key].toInt()}]".tr(), indent=1)
yield(FormattedLine( key.name.tr() + " " +"[${value.toInt()}] vs [${originalBuilding[key].toInt()}]".tr(), indent=1))
for (unique in building.uniques.filter { it !in originalBuilding.uniques })
textList += FormattedLine(unique, indent=1)
yield(FormattedLine(unique, indent=1))
if (building.maintenance != originalBuilding.maintenance)
textList += FormattedLine("{Maintenance} ".tr() + "[${building.maintenance}] vs [${originalBuilding.maintenance}]".tr(), indent=1)
yield(FormattedLine("{Maintenance} ".tr() + "[${building.maintenance}] vs [${originalBuilding.maintenance}]".tr(), indent=1))
if (building.cost != originalBuilding.cost)
textList += FormattedLine("{Cost} ".tr() + "[${building.cost}] vs [${originalBuilding.cost}]".tr(), indent=1)
yield(FormattedLine("{Cost} ".tr() + "[${building.cost}] vs [${originalBuilding.cost}]".tr(), indent=1))
if (building.cityStrength != originalBuilding.cityStrength)
textList += FormattedLine("{City strength} ".tr() + "[${building.cityStrength}] vs [${originalBuilding.cityStrength}]".tr(), indent=1)
yield(FormattedLine("{City strength} ".tr() + "[${building.cityStrength}] vs [${originalBuilding.cityStrength}]".tr(), indent=1))
if (building.cityHealth != originalBuilding.cityHealth)
textList += FormattedLine("{City health} ".tr() + "[${building.cityHealth}] vs [${originalBuilding.cityHealth}]".tr(), indent=1)
textList += FormattedLine()
yield(FormattedLine("{City health} ".tr() + "[${building.cityHealth}] vs [${originalBuilding.cityHealth}]".tr(), indent=1))
yield(FormattedLine())
} else if (building.replaces != null) {
textList += FormattedLine("Replaces [${building.replaces}], which is not found in the ruleset!", indent=1)
yield(FormattedLine("Replaces [${building.replaces}], which is not found in the ruleset!", indent=1))
} else {
textList += FormattedLine(building.getShortDescription(ruleset), indent=1)
yield(FormattedLine(building.getShortDescription(ruleset), indent=1))
}
}
}
private fun addUniqueUnitsText(textList: ArrayList<FormattedLine>, ruleset: Ruleset) {
private fun getUniqueUnitsText(ruleset: Ruleset) = sequence {
for (unit in ruleset.units.values) {
if (unit.uniqueTo != name || Constants.hideFromCivilopediaUnique in unit.uniques) continue
textList += FormattedLine("{${unit.name}} -", link="Unit/${unit.name}")
if (unit.uniqueTo != name || unit.hasUnique(UniqueType.HiddenFromCivilopedia)) continue
yield(FormattedLine("{${unit.name}} -", link="Unit/${unit.name}"))
if (unit.replaces != null && ruleset.units.containsKey(unit.replaces!!)) {
val originalUnit = ruleset.units[unit.replaces!!]!!
textList += FormattedLine("Replaces [${originalUnit.name}]", link="Unit/${originalUnit.name}", indent=1)
yield(FormattedLine("Replaces [${originalUnit.name}]", link="Unit/${originalUnit.name}", indent=1))
if (unit.cost != originalUnit.cost)
textList += FormattedLine("{Cost} ".tr() + "[${unit.cost}] vs [${originalUnit.cost}]".tr(), indent=1)
yield(FormattedLine("{Cost} ".tr() + "[${unit.cost}] vs [${originalUnit.cost}]".tr(), indent=1))
if (unit.strength != originalUnit.strength)
textList += FormattedLine("${Fonts.strength} " + "[${unit.strength}] vs [${originalUnit.strength}]".tr(), indent=1)
yield(FormattedLine("${Fonts.strength} " + "[${unit.strength}] vs [${originalUnit.strength}]".tr(), indent=1))
if (unit.rangedStrength != originalUnit.rangedStrength)
textList += FormattedLine("${Fonts.rangedStrength} " + "[${unit.rangedStrength}] vs [${originalUnit.rangedStrength}]".tr(), indent=1)
yield(FormattedLine("${Fonts.rangedStrength} " + "[${unit.rangedStrength}] vs [${originalUnit.rangedStrength}]".tr(), indent=1))
if (unit.range != originalUnit.range)
textList += FormattedLine("${Fonts.range} " + "[${unit.range}] vs [${originalUnit.range}]".tr(), indent=1)
yield(FormattedLine("${Fonts.range} " + "[${unit.range}] vs [${originalUnit.range}]".tr(), indent=1))
if (unit.movement != originalUnit.movement)
textList += FormattedLine("${Fonts.movement} " + "[${unit.movement}] vs [${originalUnit.movement}]".tr(), indent=1)
yield(FormattedLine("${Fonts.movement} " + "[${unit.movement}] vs [${originalUnit.movement}]".tr(), indent=1))
for (resource in originalUnit.getResourceRequirements().keys)
if (!unit.getResourceRequirements().containsKey(resource)) {
textList += FormattedLine("[$resource] not required", link="Resource/$resource", indent=1)
yield(FormattedLine("[$resource] not required", link="Resource/$resource", indent=1))
}
// This does not use the auto-linking FormattedLine(Unique) for two reasons:
// would look a little chaotic as unit uniques unlike most uniques are a HashSet and thus do not preserve order
// No .copy() factory on FormattedLine and no FormattedLine(Unique, all other val's) constructor either
for (unique in unit.uniqueObjects.filterNot { it.text in originalUnit.uniques || it.hasFlag(UniqueFlag.HiddenToUsers) }) {
textList += FormattedLine(unique.text.tr(), indent = 1)
yield(FormattedLine(unique.text.tr(), indent = 1))
}
for (unique in originalUnit.uniqueObjects.filterNot { it.text in unit.uniques || it.hasFlag(UniqueFlag.HiddenToUsers) }) {
textList += FormattedLine("Lost ability".tr() + " (" + "vs [${originalUnit.name}]".tr() + "): " +
unique.text.tr(), indent = 1)
yield(FormattedLine("Lost ability".tr() + " (" + "vs [${originalUnit.name}]".tr() + "): " +
unique.text.tr(), indent = 1))
}
for (promotion in unit.promotions.filter { it !in originalUnit.promotions }) {
val effect = ruleset.unitPromotions[promotion]!!.uniques
// "{$promotion} ({$effect})" won't work as effect may contain [] and tr() does not support that kind of nesting
textList += FormattedLine(
yield(FormattedLine(
"${promotion.tr()} (${effect.joinToString(",") { it.tr() }})",
link = "Promotion/$promotion", indent = 1 )
link = "Promotion/$promotion", indent = 1 ))
}
} else if (unit.replaces != null) {
textList += FormattedLine("Replaces [${unit.replaces}], which is not found in the ruleset!", indent = 1)
yield(FormattedLine("Replaces [${unit.replaces}], which is not found in the ruleset!", indent = 1))
} else {
textList += unit.getCivilopediaTextLines(ruleset).map {
yieldAll(unit.getCivilopediaTextLines(ruleset).map {
FormattedLine(it.text, link = it.link, indent = it.indent + 1, color = it.color)
}
})
}
textList += FormattedLine()
yield(FormattedLine())
}
}
private fun addUniqueImprovementsText(textList: ArrayList<FormattedLine>, ruleset: Ruleset) {
private fun getUniqueImprovementsText(ruleset: Ruleset) = sequence {
for (improvement in ruleset.tileImprovements.values) {
if (improvement.uniqueTo != name) continue
textList += FormattedLine(improvement.name, link = "Improvement/${improvement.name}")
textList += FormattedLine(improvement.cloneStats().toString(), indent = 1) // = (improvement as Stats).toString minus import plus copy overhead
yield(FormattedLine(improvement.name, link = "Improvement/${improvement.name}"))
yield(FormattedLine(improvement.cloneStats().toString(), indent = 1)) // = (improvement as Stats).toString minus import plus copy overhead
if (improvement.terrainsCanBeBuiltOn.isNotEmpty()) {
improvement.terrainsCanBeBuiltOn.withIndex().forEach {
textList += FormattedLine(if (it.index == 0) "{Can be built on} {${it.value}}" else "or [${it.value}]",
link = "Terrain/${it.value}", indent = if (it.index == 0) 1 else 2)
yield(FormattedLine(if (it.index == 0) "{Can be built on} {${it.value}}" else "or [${it.value}]",
link = "Terrain/${it.value}", indent = if (it.index == 0) 1 else 2))
}
}
for (unique in improvement.uniques)
textList += FormattedLine(unique, indent = 1)
yield(FormattedLine(unique, indent = 1))
}
}

View File

@ -120,7 +120,7 @@ class Technology: RulesetObject() {
&& (it.uniqueTo == civInfo.civName || it.uniqueTo==null && civInfo.getEquivalentBuilding(it) == it)
&& (nuclearWeaponsEnabled || "Enables nuclear weapon" !in it.uniques)
&& (religionEnabled || !it.hasUnique(UniqueType.HiddenWithoutReligion))
&& Constants.hideFromCivilopediaUnique !in it.uniques
&& !it.hasUnique(UniqueType.HiddenFromCivilopedia)
}
}
@ -128,7 +128,7 @@ class Technology: RulesetObject() {
* Returns a Sequence of [BaseUnit]s enabled by this Technology, filtered for [civInfo]'s uniques,
* nuclear weapons and religion settings, and without those expressly hidden from Civilopedia.
*/
// Used for Civilopedia, Alert and Picker, so if any of these decide to ignore the "Will not be displayed in Civilopedia" unique this needs refactoring
// Used for Civilopedia, Alert and Picker, so if any of these decide to ignore the "Will not be displayed in Civilopedia"/HiddenFromCivilopedia unique this needs refactoring
fun getEnabledUnits(civInfo: CivilizationInfo): Sequence<BaseUnit> {
val nuclearWeaponsEnabled = civInfo.gameInfo.gameParameters.nuclearWeaponsEnabled
val religionEnabled = civInfo.gameInfo.isReligionEnabled()
@ -139,7 +139,7 @@ class Technology: RulesetObject() {
&& (it.uniqueTo == civInfo.civName || it.uniqueTo==null && civInfo.getEquivalentUnit(it) == it)
&& (nuclearWeaponsEnabled || it.uniqueObjects.none { unique -> unique.placeholderText == "Nuclear weapon of Strength []" })
&& (religionEnabled || !it.hasUnique(UniqueType.HiddenWithoutReligion))
&& Constants.hideFromCivilopediaUnique !in it.uniques
&& !it.hasUnique(UniqueType.HiddenFromCivilopedia)
}
}

View File

@ -8,7 +8,7 @@ import kotlin.collections.HashSet
/** inheritsFrom means that all such uniques are acceptable as well.
* For example, all Global uniques are acceptable for Nations, Eras, etc. */
enum class UniqueTarget(val inheritsFrom:UniqueTarget?=null) {
enum class UniqueTarget(val inheritsFrom: UniqueTarget? = null) {
/** Buildings, units, nations, policies, religions, techs etc.
* Basically anything caught by CivInfo.getMatchingUniques. */
@ -59,7 +59,7 @@ enum class UniqueFlag {
HiddenToUsers,
}
enum class UniqueType(val text:String, vararg targets: UniqueTarget, val flags: List<UniqueFlag> = emptyList()) {
enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags: List<UniqueFlag> = emptyList()) {
//////////////////////////////////////// region GLOBAL UNIQUES ////////////////////////////////////////
@ -574,13 +574,13 @@ enum class UniqueType(val text:String, vararg targets: UniqueTarget, val flags:
///////////////////////////////////////////// META /////////////////////////////////////////////
HiddenWithoutReligion("Hidden when religion is disabled", UniqueTarget.Unit, UniqueTarget.Building, UniqueTarget.Ruins),
AvailableAfterCertainTurns("Only available after [amount] turns", UniqueTarget.Ruins),
HiddenWithoutReligion("Hidden when religion is disabled", UniqueTarget.Unit, UniqueTarget.Building, UniqueTarget.Ruins, flags = listOf(UniqueFlag.HiddenToUsers)),
HiddenBeforePantheon("Hidden before founding a Pantheon", UniqueTarget.Ruins),
HiddenAfterPantheon("Hidden after founding a Pantheon", UniqueTarget.Ruins),
HiddenAfterGreatProphet("Hidden after generating a Great Prophet", UniqueTarget.Ruins),
AvailableAfterCertainTurns("Only available after [amount] turns", UniqueTarget.Ruins),
HiddenWithoutVictoryType("Hidden when [victoryType] Victory is disabled", UniqueTarget.Building, UniqueTarget.Unit),
HiddenWithoutVictoryType("Hidden when [victoryType] Victory is disabled", UniqueTarget.Building, UniqueTarget.Unit, flags = listOf(UniqueFlag.HiddenToUsers)),
HiddenFromCivilopedia("Will not be displayed in Civilopedia", *UniqueTarget.values(), flags = listOf(UniqueFlag.HiddenToUsers)),
// region DEPRECATED AND REMOVED

View File

@ -173,16 +173,15 @@ class CivilopediaScreen(
val imageSize = 50f
onBackButtonClicked { game.setScreen(previousScreen) }
val hideReligionItems = !game.gameInfo.isReligionEnabled()
val religionEnabled = game.gameInfo.isReligionEnabled()
fun shouldBeDisplayed(uniqueObjects: List<Unique>): Boolean {
val uniques = uniqueObjects.map { it.placeholderText }
return Constants.hideFromCivilopediaUnique !in uniques
&& !(hideReligionItems && uniqueObjects.any { it.isOfType(UniqueType.HiddenWithoutReligion) } )
&& !(uniqueObjects.filter { unique -> unique.placeholderText == "Hidden when [] Victory is disabled"}.any {
unique -> !game.gameInfo.gameParameters.victoryTypes.contains(VictoryType.valueOf(unique.params[0] ))
})
fun shouldBeDisplayed(obj: IHasUniques): Boolean {
return when {
obj.hasUnique(UniqueType.HiddenFromCivilopedia) -> false
(!religionEnabled && obj.hasUnique(UniqueType.HiddenWithoutReligion)) -> false
obj.getMatchingUniques(UniqueType.HiddenWithoutVictoryType).any { !game.gameInfo.gameParameters.victoryTypes.contains(VictoryType.valueOf(it.params[0] )) } -> false
else -> true
}
}
fun getCategoryIterator(category: CivilopediaCategories): Collection<ICivilopediaText> =
@ -205,10 +204,10 @@ class CivilopediaScreen(
for (loopCategory in CivilopediaCategories.values()) {
if (loopCategory.hide) continue
if (hideReligionItems && loopCategory == CivilopediaCategories.Belief) continue
if (!religionEnabled && loopCategory == CivilopediaCategories.Belief) continue
categoryToEntries[loopCategory] =
getCategoryIterator(loopCategory)
.filter { (it as? IHasUniques)?.let { obj -> shouldBeDisplayed(obj.uniqueObjects) } ?: true }
.filter { (it as? IHasUniques)?.let { obj -> shouldBeDisplayed(obj) } ?: true }
.map { CivilopediaEntry(
(it as INamed).name,
loopCategory.getImage?.invoke(it.getIconName(), imageSize),

View File

@ -85,7 +85,7 @@ class WonderOverviewTable(
}
private fun shouldBeDisplayed(wonder: Building, wonderEra: Int) = when {
Constants.hideFromCivilopediaUnique in wonder.uniques -> false
wonder.hasUnique(UniqueType.HiddenFromCivilopedia) -> false
wonder.hasUnique(UniqueType.HiddenWithoutReligion) && hideReligionItems -> false
wonder.name in startingObsolete -> false
wonder.getMatchingUniques(UniqueType.HiddenWithoutVictoryType)