mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-23 06:08:46 +07:00
Spruced up Civilopedia - phase 6 - uniques (#4587)
This commit is contained in:
@ -29,7 +29,7 @@ class Building : NamedStats(), IConstruction, ICivilopediaText {
|
||||
private var percentStatBonus: Stats? = null
|
||||
var specialistSlots: Counter<String>? = null
|
||||
fun newSpecialists(): Counter<String> {
|
||||
if (specialistSlots == null) return Counter<String>()
|
||||
if (specialistSlots == null) return Counter()
|
||||
// Could have old specialist values of "gold", "science" etc - change them to the new specialist names
|
||||
val counter = Counter<String>()
|
||||
for ((entry, amount) in specialistSlots!!) {
|
||||
@ -90,18 +90,24 @@ class Building : NamedStats(), IConstruction, ICivilopediaText {
|
||||
return infoList.joinToString("; ") { it.tr() }
|
||||
}
|
||||
|
||||
fun getUniquesStrings(): ArrayList<String> {
|
||||
private fun getUniquesStrings() = sequence {
|
||||
val tileBonusHashmap = HashMap<String, ArrayList<String>>()
|
||||
val finalUniques = ArrayList<String>()
|
||||
for (unique in uniqueObjects)
|
||||
if (unique.placeholderText == "[] from [] tiles []" && unique.params[2] == "in this city") {
|
||||
for (unique in uniqueObjects) when {
|
||||
unique.placeholderText == "[] from [] tiles []" && unique.params[2] == "in this city" -> {
|
||||
val stats = unique.params[0]
|
||||
if (!tileBonusHashmap.containsKey(stats)) tileBonusHashmap[stats] = ArrayList()
|
||||
tileBonusHashmap[stats]!!.add(unique.params[1])
|
||||
} else if (unique.placeholderText != "Consumes [] []") finalUniques += unique.text
|
||||
}
|
||||
unique.placeholderText == "Consumes [] []" -> Unit // skip these,
|
||||
else -> yield(unique.text)
|
||||
}
|
||||
for ((key, value) in tileBonusHashmap)
|
||||
finalUniques += "[stats] from [tileFilter] tiles in this city".fillPlaceholders(key, value.joinToString { it.tr() })
|
||||
return finalUniques
|
||||
yield( "[stats] from [tileFilter] tiles in this city"
|
||||
.fillPlaceholders( key,
|
||||
// A single tileFilter will be properly translated later due to being within []
|
||||
// advantage to not translate prematurely: FormatLine.formatUnique will recognize it
|
||||
if (value.size == 1) value[0] else value.joinToString { it.tr() }
|
||||
))
|
||||
}
|
||||
|
||||
fun getDescription(cityInfo: CityInfo?, ruleset: Ruleset): String {
|
||||
@ -118,7 +124,7 @@ class Building : NamedStats(), IConstruction, ICivilopediaText {
|
||||
stringBuilder.appendLine("Provides a free [$providesFreeBuilding] in the city".tr())
|
||||
if (uniques.isNotEmpty()) {
|
||||
if (replacementTextForUniques != "") stringBuilder.appendLine(replacementTextForUniques)
|
||||
else stringBuilder.appendLine(getUniquesStrings().asSequence().map { it.tr() }.joinToString("\n"))
|
||||
else stringBuilder.appendLine(getUniquesStrings().map { it.tr() }.joinToString("\n"))
|
||||
}
|
||||
if (!stats.isEmpty())
|
||||
stringBuilder.appendLine(stats.toString())
|
||||
@ -180,8 +186,7 @@ class Building : NamedStats(), IConstruction, ICivilopediaText {
|
||||
|
||||
fun getStatPercentageBonuses(cityInfo: CityInfo?): Stats {
|
||||
val stats = if (percentStatBonus == null) Stats() else percentStatBonus!!.clone()
|
||||
val civInfo = cityInfo?.civInfo
|
||||
if (civInfo == null) return stats // initial stats
|
||||
val civInfo = cityInfo?.civInfo ?: return stats // initial stats
|
||||
|
||||
val baseBuildingName = getBaseBuilding(civInfo.gameInfo.ruleSet).name
|
||||
|
||||
@ -262,7 +267,8 @@ class Building : NamedStats(), IConstruction, ICivilopediaText {
|
||||
if (replacementTextForUniques.isNotEmpty())
|
||||
textList += FormattedLine(replacementTextForUniques)
|
||||
else
|
||||
for (unique in getUniquesStrings()) textList += FormattedLine(unique)
|
||||
for (unique in getUniquesStrings())
|
||||
textList += FormattedLine(Unique(unique))
|
||||
}
|
||||
|
||||
if (!stats.isEmpty()) {
|
||||
@ -504,8 +510,8 @@ class Building : NamedStats(), IConstruction, ICivilopediaText {
|
||||
|
||||
for ((resource, amount) in getResourceRequirements())
|
||||
if (civInfo.getCivResourcesByName()[resource]!! < amount) {
|
||||
if (amount == 1) return "Consumes 1 [$resource]" // Again, to preserve existing translations
|
||||
else return "Consumes [$amount] [$resource]"
|
||||
return if (amount == 1) "Consumes 1 [$resource]" // Again, to preserve existing translations
|
||||
else "Consumes [$amount] [$resource]"
|
||||
}
|
||||
|
||||
if (requiredNearbyImprovedResources != null) {
|
||||
@ -599,14 +605,14 @@ class Building : NamedStats(), IConstruction, ICivilopediaText {
|
||||
}
|
||||
|
||||
fun getBaseBuilding(ruleset: Ruleset): Building {
|
||||
if (replaces == null) return this
|
||||
else return ruleset.buildings[replaces!!]!!
|
||||
return if (replaces == null) this
|
||||
else ruleset.buildings[replaces!!]!!
|
||||
}
|
||||
|
||||
fun getImprovement(ruleset: Ruleset): TileImprovement? {
|
||||
val improvementUnique = uniqueObjects
|
||||
.firstOrNull { it.placeholderText == "Creates a [] improvement on a specific tile" }
|
||||
if (improvementUnique == null) return null
|
||||
.firstOrNull { it.placeholderText == "Creates a [] improvement on a specific tile" }
|
||||
?: return null
|
||||
return ruleset.tileImprovements[improvementUnique.params[0]]
|
||||
}
|
||||
|
||||
|
@ -103,14 +103,8 @@ class BaseUnit : INamed, IConstruction, CivilopediaText() {
|
||||
textList += FormattedLine(replacementTextForUniques)
|
||||
} else if (uniques.isNotEmpty()) {
|
||||
textList += FormattedLine()
|
||||
for (uniqueObject in uniqueObjects.sortedBy { it.text }) {
|
||||
if (uniqueObject.placeholderText == "Can construct []") {
|
||||
val improvement = uniqueObject.params[0]
|
||||
textList += FormattedLine(uniqueObject.text, link="Improvement/$improvement")
|
||||
} else {
|
||||
textList += FormattedLine(uniqueObject.text)
|
||||
}
|
||||
}
|
||||
for (uniqueObject in uniqueObjects.sortedBy { it.text })
|
||||
textList += FormattedLine(uniqueObject)
|
||||
}
|
||||
|
||||
val resourceRequirements = getResourceRequirements()
|
||||
|
@ -5,7 +5,9 @@ import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.scenes.scene2d.Actor
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||
import com.badlogic.gdx.utils.Align
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.models.ruleset.Ruleset
|
||||
import com.unciv.models.ruleset.Unique
|
||||
import com.unciv.models.stats.INamed
|
||||
import com.unciv.ui.utils.*
|
||||
import kotlin.math.max
|
||||
@ -66,6 +68,9 @@ class FormattedLine (
|
||||
// from json in the primary constructor parameters above. Everything else should be a fun(),
|
||||
// have no backing field, be `by lazy` or use @Transient, Thank you.
|
||||
|
||||
/** Looks for linkable ruleset objects in [Unique] parameters and returns a linked [FormattedLine] if successful, a plain one otherwise */
|
||||
constructor(unique: Unique) : this(unique.text, getUniqueLink(unique))
|
||||
|
||||
/** Link types that can be used for [FormattedLine.link] */
|
||||
enum class LinkType {
|
||||
None,
|
||||
@ -133,6 +138,43 @@ class FormattedLine (
|
||||
const val iconPad = 5f
|
||||
/** Padding distance per [indent] level */
|
||||
const val indentPad = 30f
|
||||
|
||||
// Helper for constructor(Unique)
|
||||
private fun getUniqueLink(unique: Unique): String {
|
||||
for (parameter in unique.params) {
|
||||
val category = allObjectNamesCategoryMap[parameter] ?: continue
|
||||
return category.name + "/" + parameter
|
||||
}
|
||||
return ""
|
||||
}
|
||||
// Cache to quickly match Categories to names. Takes a few ms to build on a slower desktop and will use just a few 10k bytes.
|
||||
private val allObjectNamesCategoryMap: HashMap<String, CivilopediaCategories> by lazy {
|
||||
//val startTime = System.nanoTime()
|
||||
val ruleSet = UncivGame.Current.gameInfo.ruleSet
|
||||
// order these with the categories that should take precedence in case of name conflicts (e.g. Railroad) _last_
|
||||
val allObjectMapsSequence = sequence {
|
||||
yield(CivilopediaCategories.Difficulty to ruleSet.difficulties)
|
||||
yield(CivilopediaCategories.Promotion to ruleSet.unitPromotions)
|
||||
yield(CivilopediaCategories.Policy to ruleSet.policies)
|
||||
yield(CivilopediaCategories.Terrain to ruleSet.terrains)
|
||||
yield(CivilopediaCategories.Improvement to ruleSet.tileImprovements)
|
||||
yield(CivilopediaCategories.Resource to ruleSet.tileResources)
|
||||
yield(CivilopediaCategories.Nation to ruleSet.nations)
|
||||
yield(CivilopediaCategories.Unit to ruleSet.units)
|
||||
yield(CivilopediaCategories.Technology to ruleSet.technologies)
|
||||
yield(CivilopediaCategories.Building to ruleSet.buildings.filter { !it.value.isAnyWonder() })
|
||||
yield(CivilopediaCategories.Wonder to ruleSet.buildings.filter { it.value.isAnyWonder() })
|
||||
}
|
||||
val result = HashMap<String,CivilopediaCategories>()
|
||||
allObjectMapsSequence.filter { !it.first.hide }
|
||||
.flatMap { pair -> pair.second.keys.asSequence().map { key -> pair.first to key } }
|
||||
.forEach {
|
||||
result[it.second] = it.first
|
||||
//println(" ${it.second} is a ${it.first}")
|
||||
}
|
||||
//println("allObjectNamesCategoryMap took ${System.nanoTime()-startTime}ns to initialize")
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
/** Extension: determines if a [String] looks like a link understood by the OS */
|
||||
|
Reference in New Issue
Block a user