Civilopedia phase 8 - Nations and Promotions (#4657)

* Civilopedia phase 8 - Nations and Promotions

* Civilopedia phase 8 - Nations and Promotions - AS insubordination

* Civilopedia phase 8 - Nations and Promotions - OR template

* Civilopedia phase 8 - Nations and Promotions - proofread

* Civilopedia phase 8 - Nations and Promotions - revert OR
This commit is contained in:
SomeTroglodyte 2021-07-30 14:55:17 +02:00 committed by GitHub
parent 4bcf821879
commit 130c318ae0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 311 additions and 52 deletions

View File

@ -152,8 +152,7 @@
{
"name": "Medic II",
"prerequisites": ["Medic"],
"uniques": ["[+5] HP when healing", "All adjacent units heal [5] HP when healing",
"[+5] HP when healing in [Foreign Land] tiles"],
"uniques": ["[+5] HP when healing", "[+5] HP when healing in [Foreign Land] tiles", "All adjacent units heal [5] HP when healing"],
"unitTypes": ["Melee","Mounted","Scout"]
},

View File

@ -48,6 +48,7 @@ Required tech: [requiredTech] = Benötigt Technologie: [requiredTech]
Requires [PolicyOrNationalWonder] = Benötigt [PolicyOrNationalWonder]
Cannot be purchased = Kann nicht gekauft werden
See also = Siehe auch
Requires at least one of the following: = Benötigt eine der folgenden Vorraussetzungen:
Current construction = Aktuelle Produktion
Construction queue = Produktionswarteschlange
@ -852,6 +853,7 @@ Buildings that consume this resource = Gebäude welche diese Ressource verbrauch
Buildings that require this resource worked near the city = Gebäude welche diese Ressource bewirtschaftet in der Nähe der Stadt benötigen
Units that consume this resource = Einheiten welche diese Ressource verbrauchen
Can be built on = Kann gebaut werden auf
or [terrainType] = oder [terrainType]
Can be constructed by = Kann erbaut werden von
Defence bonus = Verteidigungsbonus
Movement cost = Bewegungskosten
@ -922,9 +924,13 @@ Gold reward for clearing barbarian camps = Gold-Belohnung für das Räumen von B
# Other civilopedia things
Nations = Nationen
Available for [unitTypes] = Verfügbar für [unitTypes]
Available for: = Verfügbar für:
Free promotion: = Freie Beförderung:
Free promotions: = Freie Beförderungen:
Free for [units] = Frei für [units]
Free for: = Frei für:
Granted by [param] = Von [param] erteilt
Granted by: = Erteilt von:
[bonus] with [tech] = [bonus] mit [tech]
Difficulty levels = Schwierigkeitsgrade
@ -978,7 +984,7 @@ Siege = Belagerung
WaterCivilian = Wasser-Zivilist
WaterMelee = Wassernahkampf
WaterRanged = Wasserfernkampf
WaterSubmarine = Wasser-U-Boot
WaterSubmarine = U-Boote
WaterAircraftCarrier = Flugzeugträger
Fighter = Jagdflugzeug
@ -1196,7 +1202,8 @@ Paper Maker = Papiermacher
'Libraries are as the shrine where all the relics of the ancient saints, full of true virtue, and all that without delusion or imposture are preserved and reposed.' - Sir Francis Bacon = 'Bibliotheken sind wie der Schrein, wo alle Reliquien der Heiligen vergangener Tage, voll der wahren Tugend, ruhen und bewahrt werden, und zwar ganz ohne Irreführung und Betrug.' - Sir Francis Bacon
Free Technology = Kostenlose Technologie
Provides a free [building] [cityFilter] = Stellt das Gebäude [building] [cityFilter] bereit
# Requires translation!
Provides a free [building] [cityFilter] = Stellt das Gebäude [building] [cityFilter] kostenlos bereit
The Great Library = Die Große Bibliothek
Circus = Zirkus
@ -2346,7 +2353,7 @@ You have defeated us... but our spirits will never be vanquished! We shall retur
Greetings, stranger. I am Hiawatha, speaker for the Iroquois. We seek peace with all, but we do not shrink from war. = Seid gegrüßt, Fremder. Ich bin Hiawatha, Sprecher der Irokesen. Wir streben nach Frieden, doch wenn es sein muss, scheuen wir nicht den Krieg.
Does this trade work for you, my friend? = Ist dieser Tausch für dich ok, mein Freund?
The Great Warpath = Auf dem Großen Kriegspfad
All units move through Forest and Jungle Tiles in friendly territory as if they have roads. These tiles can be used to establish City Connections upon researching the Wheel. = Alle Einheiten bewegen sich durch verbündete Wald- und Dschungelfelder als hätten sie Straßen. Diese Felder können genutzt werden, um bei der Erforschung des Rades Stadtverbindungen herzustellen.
All units move through Forest and Jungle Tiles in friendly territory as if they have roads. These tiles can be used to establish City Connections upon researching the Wheel. = Alle Einheiten bewegen sich durch verbündete Wald- und Dschungelfelder als hätten sie Straßen. Diese Felder können genutzt werden, um nach Erforschung des Rades Stadtverbindungen herzustellen.
Greetings, noble Hiawatha, leader of the mighty Iroquois nations! Long have your people lived near the great and holy lake Ontario in the land that has come to be known as the New York state in North America. In the mists of antiquity, the five peoples of Seneca, Onondaga, Mohawks, Cayugas and Oneida united into one nation, the Haudenosaunee, the Iroquois. With no written language, the wise men of your nation created the great law of peace, the model for many constitutions including that of the United States. For many years, your people battled great enemies, such as the Huron, and the French and English invaders. Tough outnumbered and facing weapons far more advanced than the ones your warriors wielded, the Iroquois survived and prospered, until they were finally overwhelmed by the mighty armies of the new United States. = Seid gegrüßt, edler Hiawatha, Häuptling der mächtigen Irokesenvölker! Seit langem lebt euer Volk in der Nähe des großen und heiligen Sees Ontario in dem Land, das als der Staat New York in Nordamerika bekannt geworden ist. In den Nebeln des Altertums vereinigten sich die fünf Völker der Seneca, Onondaga, Mohawks, Cayugas und Oneida zu einer Nation, den Haudenosaunee, den Irokesen. Ohne Schriftsprache schufen die Weisen eures Volkes das große Friedensgesetz, das Vorbild für viele Verfassungen, darunter auch die der Vereinigten Staaten. Viele Jahre lang kämpfte euer Volk gegen große Feinde, wie die Huronen und die französischen und englischen Invasoren. Obwohl sie zahlenmäßig unterlegen und mit Waffen konfrontiert waren, die weitaus fortschrittlicher waren als die, die eure Krieger trugen, überlebten die Irokesen und gediehen, bis sie schließlich von den mächtigen Armeen der neuen Vereinigten Staaten überwältigt wurden.
Oh noble Hiawatha, listen to the cries of your people! They call out to you to lead them in peace and war, to rebuild the great longhouse and unite the tribes once again. Will you accept this challenge, great leader? Will you build a civilization that will stand the test of time? = Oh edler Hiawatha, höre auf die Schreie deines Volkes! Sie rufen nach Euch, um sie in Frieden und Krieg zu führen, um das große Langhaus wieder aufzubauen und die Stämme wieder zu vereinen. Werdet Ihr diese Herausforderung annehmen, großer Anführer? Könnt Ihr eine Zivilisation aufbauen, die dem Test der Zeit standhält?
Onondaga = Onondaga
@ -2523,7 +2530,7 @@ I, Pho Kun Ramkhamhaeng, King of Siam, consider it a great honor that you have w
Greetings. I believe this is a fair proposal for both parties. What do you think? = Ich grüße Euch. Ich glaube, dies ist ein fairer Vorschlag für beide Seiten. Was meint Ihr dazu?
Welcome. = Willkommen.
Father Governs Children = Vater und Kinder
Food and Culture from Friendly City-States are increased by 50% = Nahrung und Kultur aus freundlichen Stadtstaaten werden um 50% erhöht.
Food and Culture from Friendly City-States are increased by 50% = Nahrung und Kultur aus befreundeten Stadtstaaten werden um 50% erhöht.
Greetings to you, Great King Ramkhamhaeng, leader of the glorious Siamese people! O mighty King, your people bow down before you in awe and fear! You are the ruler of Siam, an ancient country in the heart of Southeast Asia, a beautiful and mysterious land. Surrounded by foes, beset by bloody war and grinding poverty, the clever and loyal Siamese people have endured and triumphed. King Ramkhamhaeng, your empire was once part of the Khmer Empire, until the 13th century AD, when your ancestors revolted, forming the small Sukhothai kingdom. Through successful battle and cunning diplomacy, the tiny kingdom grew into a mighty empire, an empire which would dominate South East Asia for more than a century! = Sei gegrüßt, Großkönig Ramkhamhaeng, Führer des glorreichen siamesischen Volkes! O mächtiger König, euer Volk verneigt sich in Ehrfurcht und Furcht vor Euch! Ihr seid der Herrscher von Siam, einem alten Land im Herzen Südostasiens, einem schönen und geheimnisvollen Land. Umgeben von Feinden, bedrängt von blutigen Kriegen und drückender Armut, hat das kluge und treue siamesische Volk ausgehalten und triumphiert. König Ramkhamhaeng, euer Reich war einst Teil des Khmer-Reiches, bis zum 13. Jahrhundert n. Chr., als sich eure Vorfahren auflehnten und das kleine Königreich Sukhothai gründeten. Durch erfolgreiche Kämpfe und schlaue Diplomatie wuchs das winzige Königreich zu einem mächtigen Reich heran, ein Reich, das Südostasien für mehr als ein Jahrhundert beherrschen sollte!
Oh, wise and puissant King Ramkhamhaeng, your people need you to once again lead them to greatness! Can you use your wits and strength of arms to protect your people and defeat your foes? Can you build a civilization that will stand the test of time? = Oh, weiser und mächtiger König Ramkhamhaeng, euer Volk braucht Euch, um es noch einmal zu Größe zu führen! Könnt Ihr Euren Verstand und Eure Waffenstärke nutzen, um euer Volk zu schützen und Eure Feinde zu besiegen? Könnt Ihr eine Zivilisation aufbauen, die dem Test der Zeit standhält?
Sukhothai = Sukhothai
@ -3427,7 +3434,7 @@ Telecommunications = Telekommunikation
'The more we elaborate our means of communication, the less we communicate.' - J.B. Priestly = 'Je mehr wir unsere Kommunikationsmittel ausbauen, desto weniger kommunizieren wir.' J.B. Priestly
Mobile Tactics = Mobile Taktiken
'All men can see these tactics whereby I conquer, but what none can see is the strategy out of which victory is evolved.' - Sun Tzu = 'Alle Menschen können diese Taten sehen, mit denen ich siege, aber was niemand sehen kann, ist die Strategie, aus der sich der Sieg entwickelt.' - Sun Tzu
Advanced Ballistics = Erweiterte Ballistik
Advanced Ballistics = Fortgeschrittene Ballistik
'Our scientific power has outrun our spiritual power, we have guided missiles and misguided men.' Martin Luther King Jr. = 'Unsere wissenschaftliche Macht hat unsere geistige Macht überholt, wir haben Raketen gelenkt und Menschen fehlgeleitet.' Martin Luther King Jr.
Satellites = Satelliten
Reveals the entire map = Enthüllt die gesamte Weltkarte
@ -3687,7 +3694,7 @@ Barrage III = Sperrfeuer III
Volley = Salve
Extended Range = erweiterte Reichweite
Extended Range = Erhöhte Reichweite
[amount] Range = [amount] Reichweite
Indirect Fire = Indirektes Feuer
@ -3728,7 +3735,7 @@ Medic = Sanitäter I
All adjacent units heal [amount] HP when healing = Beim Heilen werden alle benachbarten Einheiten um [amount] LP geheilt
Medic II = Sanitäter II
[amount] HP when healing in [tileFilter] tiles = [amount] LP beim Heilen auf [tileFilter] Feldern
[amount] HP when healing in [tileFilter] tiles = [amount] LP bei Heilung in [tileFilter] Feldern
Scouting I = Spähen I
[amount] Visibility Range = [amount] Sichtweite
@ -3753,12 +3760,12 @@ Boarding Party II = Enterkommando II
Boarding Party III = Enterkommando III
Coastal Raider I = KüstenräuberIn I
Coastal Raider I = Küstenräuberei I
Earn [amount]% of the damage done to [unitType] units as [stat] = Erhalte [amount]% des verursachten Schadens an [unitType] Einheiten als [stat]
Coastal Raider II = KüstenräuberIn II
Coastal Raider II = Küstenräuberei II
Coastal Raider III = KüstenräuberIn III
Coastal Raider III = Küstenräuberei III
Targeting I = Gezielter Schlag I
@ -3787,7 +3794,7 @@ Flight Deck II = Flugdeck II
Flight Deck III = Flugdeck III
Supply = Versorgung
May heal outside of friendly territory = Kann außerhalb des eigenen Territoriums heilen
May heal outside of friendly territory = Darf auch außerhalb von befreundetem Territorium heilen
Siege I = Belagerung I
@ -3810,7 +3817,7 @@ Air Targeting I = Luftangriff I
Air Targeting II = Luftangriff II
Sortie = Lufteinsatz
[amount] extra interceptions may be made per turn = [amount] zusätzliche Abfangungen können pro Runde durchgeführt werden
[amount] extra interceptions may be made per turn = Kann pro Runde [amount] mal zusätzlich Abfangen
Operational Range = Einsatzreichweite
@ -3938,7 +3945,7 @@ Knight = Ritter
Camel Archer = Kamel-Bogenschütze
Conquistador = Eroberer
Conquistador = Konquistador
Defense bonus when embarked = Verteidigungsbonus wenn Eingeschifft
Naresuan's Elephant = Naresuans Elefant
@ -4052,7 +4059,7 @@ Zero = Zero
B17 = B-17
Paratrooper = Fallschirmjäger
May Paradrop up to [amount] tiles from inside friendly territory = Kann einen Fallschirmabsprung bis zu [amount] Felder von innerhalb des befreundeten Territoriums aus durchführen
May Paradrop up to [amount] tiles from inside friendly territory = Kann aus befreundetem Territorium heraus einen Fallschirmabsprung bis zu [amount] Felder weit durchführen
Tank = Panzer

View File

@ -48,6 +48,7 @@ Required tech: [requiredTech] =
Requires [PolicyOrNationalWonder] =
Cannot be purchased =
See also =
Requires at least one of the following: =
Current construction =
Construction queue =
@ -856,6 +857,7 @@ Buildings that consume this resource =
Buildings that require this resource worked near the city =
Units that consume this resource =
Can be built on =
or [terrainType] =
Can be constructed by =
Defence bonus =
Movement cost =
@ -927,9 +929,13 @@ Gold reward for clearing barbarian camps =
# Other civilopedia things
Nations =
Available for [unitTypes] =
Available for: =
Free promotion: =
Free promotions: =
Free for [units] =
Free for: =
Granted by [param] =
Granted by: =
[bonus] with [tech] =
Difficulty levels =

View File

@ -575,7 +575,7 @@ open class TileInfo {
}
fun toMarkup(viewingCiv: CivilizationInfo?): ArrayList<FormattedLine> {
val lineList = ArrayList<FormattedLine>() // more readable than StringBuilder, with same performance for our use-case
val lineList = ArrayList<FormattedLine>()
val isViewableToPlayer = viewingCiv == null || UncivGame.Current.viewEntireMapForDebug
|| viewingCiv.viewableTiles.contains(this)

View File

@ -3,8 +3,14 @@
import com.badlogic.gdx.graphics.Color
import com.unciv.Constants
import com.unciv.logic.civilization.CityStateType
import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.models.stats.INamed
import com.unciv.models.translations.Translations
import com.unciv.models.translations.squareBraceRegex
import com.unciv.models.translations.tr
import com.unciv.ui.civilopedia.CivilopediaText
import com.unciv.ui.civilopedia.FormattedLine
import com.unciv.ui.civilopedia.ICivilopediaText
import com.unciv.ui.utils.Fonts
import com.unciv.ui.utils.colorFromRGB
@ -15,7 +21,7 @@ enum class VictoryType {
Scientific
}
class Nation : INamed {
class Nation : INamed, ICivilopediaText {
override lateinit var name: String
var leaderName = ""
@ -49,6 +55,8 @@ class Nation : INamed {
var adjective = ArrayList<String>()
*/
override var civilopediaText = listOf<FormattedLine>()
@Transient
private lateinit var outerColorObject: Color
fun getOuterColor(): Color = outerColorObject
@ -88,14 +96,10 @@ class Nation : INamed {
lateinit var cities: ArrayList<String>
fun getUniqueString(ruleset: Ruleset, forPickerScreen: Boolean = true): String {
/** Used only by NewGame Nation picker */
fun getUniqueString(ruleset: Ruleset): String {
val textList = ArrayList<String>()
if (leaderName.isNotEmpty() && !forPickerScreen) {
textList += getLeaderDisplayName().tr()
textList += ""
}
if (uniqueName != "") textList += uniqueName.tr() + ":"
if (uniqueText != "") {
textList += " " + uniqueText.tr()
@ -190,4 +194,152 @@ class Nation : INamed {
textList += " " + unique.tr()
}
}
override fun makeLink() = "Nation/$name"
override fun replacesCivilopediaDescription() = true
override fun hasCivilopediaTextLines() = true
override fun getCivilopediaTextLines(ruleset: Ruleset): List<FormattedLine> {
val textList = ArrayList<FormattedLine>()
if (leaderName.isNotEmpty()) {
textList += FormattedLine(extraImage = "LeaderIcons/$leaderName", imageSize = 200f)
textList += FormattedLine(getLeaderDisplayName(), centered = true, header = 3)
textList += FormattedLine()
}
if (uniqueName != "")
textList += FormattedLine("{$uniqueName}:", header = 4)
if (uniqueText != "") {
textList += FormattedLine(uniqueText, indent = 1)
} else {
uniqueObjects.forEach {
textList += FormattedLine(it)
}
textList += FormattedLine()
}
if (startBias.isNotEmpty()) {
startBias.withIndex().forEach {
// can be "Avoid []"
val link = if ('[' !in it.value) it.value
else squareBraceRegex.find(it.value)!!.groups[1]!!.value
textList += FormattedLine(
(if (it.index == 0) "[Start bias:] " else "") + it.value.tr(), // extra tr because tr cannot nest {[]}
link = "Terrain/$link",
indent = if (it.index == 0) 0 else 1)
}
textList += FormattedLine()
}
addUniqueBuildingsText(textList, ruleset)
addUniqueUnitsText(textList, ruleset)
addUniqueImprovementsText(textList, ruleset)
return textList
}
@JvmName("addUniqueBuildingsText1") // These overloads are too similar - but I hope to remove the other one soon
private fun addUniqueBuildingsText(textList: ArrayList<FormattedLine>, ruleset: Ruleset) {
for (building in ruleset.buildings.values) {
if (building.uniqueTo != name || "Will not be displayed in Civilopedia" in building.uniques) continue
textList += 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)
val originalBuildingStatMap = originalBuilding.toHashMap()
for (stat in building.toHashMap())
if (stat.value != originalBuildingStatMap[stat.key])
textList += FormattedLine(
stat.key.toString().tr() + " " +
"[${stat.value.toInt()}] vs [${originalBuildingStatMap[stat.key]!!.toInt()}]".tr(),
indent=1)
for (unique in building.uniques.filter { it !in originalBuilding.uniques })
textList += FormattedLine(unique, indent=1)
if (building.maintenance != originalBuilding.maintenance)
textList += 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)
if (building.cityStrength != originalBuilding.cityStrength)
textList += 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()
} else if (building.replaces != null) {
textList += FormattedLine("Replaces [${building.replaces}], which is not found in the ruleset!", indent=1)
} else {
textList += FormattedLine(building.getShortDescription(ruleset), indent=1)
}
}
}
@JvmName("addUniqueUnitsText1")
private fun addUniqueUnitsText(textList: ArrayList<FormattedLine>, ruleset: Ruleset) {
for (unit in ruleset.units.values) {
if (unit.uniqueTo != name || "Will not be displayed in Civilopedia" in unit.uniques) continue
textList += 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)
if (unit.cost != originalUnit.cost)
textList += 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)
if (unit.rangedStrength != originalUnit.rangedStrength)
textList += 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)
if (unit.movement != originalUnit.movement)
textList += 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)
}
// 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.uniques.filterNot { it in originalUnit.uniques })
textList += FormattedLine(unique, indent=1)
for (unique in originalUnit.uniques.filterNot { it in unit.uniques })
textList += FormattedLine("Lost ability".tr() + " (" + "vs [${originalUnit.name}]".tr() + "): " +
unique.tr(), indent=1)
for (promotion in unit.promotions.filter { it !in originalUnit.promotions }) {
val effect = ruleset.unitPromotions[promotion]!!.effect
// "{$promotion} ({$effect})" won't work as effect may contain [] and tr() does not support that kind of nesting
textList += FormattedLine(
if (effect.isEmpty()) promotion
else "${promotion.tr()} (${effect.tr()})",
link = "Promotion/$promotion", indent = 1 )
}
} else if (unit.replaces != null) {
textList += FormattedLine("Replaces [${unit.replaces}], which is not found in the ruleset!", indent=1)
} else {
textList += unit.getCivilopediaTextLines(ruleset).map {
FormattedLine(it.text, link=it.link, indent = it.indent + 1, color=it.color)
}
}
textList += FormattedLine()
}
}
@JvmName("addUniqueImprovementsText1")
private fun addUniqueImprovementsText(textList: ArrayList<FormattedLine>, ruleset: Ruleset) {
for (improvement in ruleset.tileImprovements.values) {
if (improvement.uniqueTo != name ) continue
textList += FormattedLine(improvement.name, link="Improvement/${improvement.name}")
textList += FormattedLine(improvement.clone().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)
}
}
for (unique in improvement.uniques)
textList += FormattedLine(unique, indent=1)
}
}
}

View File

@ -94,7 +94,7 @@ class BaseUnit : INamed, IConstruction, CivilopediaText() {
stats += "$rangedStrength${Fonts.rangedStrength}"
stats += "$range${Fonts.range}"
}
if (movement != 0) stats += "$movement${Fonts.movement}"
if (movement != 0 && !movesLikeAirUnits()) stats += "$movement${Fonts.movement}"
if (cost != 0) stats += "{Cost}: $cost"
if (stats.isNotEmpty())
textList += FormattedLine(stats.joinToString(", "))

View File

@ -4,22 +4,32 @@ import com.unciv.models.ruleset.Ruleset
import com.unciv.models.ruleset.Unique
import com.unciv.models.stats.INamed
import com.unciv.models.translations.tr
import com.unciv.ui.civilopedia.FormattedLine
import com.unciv.ui.civilopedia.ICivilopediaText
class Promotion : INamed{
class Promotion : INamed, ICivilopediaText {
override lateinit var name: String
var prerequisites = listOf<String>()
var effect = ""
var unitTypes = listOf<String>() // The json parser wouldn't agree to deserialize this as a list of UnitTypes. =(
var uniques = ArrayList<String>()
val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it) } + Unique(effect) }
private fun uniquesWithEffect() = sequence {
if (effect.isNotEmpty()) yield(effect)
yieldAll(uniques)
}
val uniqueObjects: List<Unique> by lazy { uniquesWithEffect().map { Unique(it) }.toList() }
fun getDescription(promotionsForUnitType: Collection<Promotion>, forCivilopedia:Boolean=false, ruleSet:Ruleset? = null):String {
// we translate it before it goes in to get uniques like "vs units in rough terrain" and after to get "vs city
val stringBuilder = StringBuilder()
override var civilopediaText = listOf<FormattedLine>()
for (unique in uniques + effect) {
stringBuilder.appendLine(unique.tr())
/** Used to describe a Promotion on the PromotionPickerScreen */
fun getDescription(promotionsForUnitType: Collection<Promotion>):String {
val textList = ArrayList<String>()
for (unique in uniquesWithEffect()) {
textList += unique.tr()
}
if (prerequisites.isNotEmpty()) {
@ -27,22 +37,103 @@ class Promotion : INamed{
for (i in prerequisites.filter { promotionsForUnitType.any { promotion -> promotion.name == it } }) {
prerequisitesString.add(i.tr())
}
stringBuilder.appendLine("{Requires}: ".tr() + prerequisitesString.joinToString(" OR ".tr()))
textList += "{Requires}: ".tr() + prerequisitesString.joinToString(" OR ".tr())
}
if(forCivilopedia){
if (unitTypes.isNotEmpty()) {
val unitTypesString = unitTypes.joinToString(", ") { it.tr() }
stringBuilder.appendLine("Available for [$unitTypesString]".tr())
return textList.joinToString("\n")
}
if (ruleSet!=null) {
val freeforUnits = ruleSet.units.filter { it.value.promotions.contains(name) }
if (freeforUnits.isNotEmpty()) {
val freeforString = freeforUnits.map { it.value.name }.joinToString(", ") { it.tr() }
stringBuilder.appendLine("Free for [$freeforString]".tr())
override fun makeLink() = "Promotion/$name"
override fun hasCivilopediaTextLines() = true
override fun replacesCivilopediaDescription() = true
override fun getCivilopediaTextLines(ruleset: Ruleset): List<FormattedLine> {
val textList = ArrayList<FormattedLine>()
for (unique in uniqueObjects) {
textList += FormattedLine(unique)
}
val filteredPrerequisites = prerequisites.mapNotNull {
ruleset.unitPromotions[it]
}
if (filteredPrerequisites.isNotEmpty()) {
textList += FormattedLine()
if (filteredPrerequisites.size == 1) {
filteredPrerequisites[0].let {
textList += FormattedLine("Requires [${it.name}]", link = it.makeLink())
}
} else {
textList += FormattedLine("Requires at least one of the following:")
filteredPrerequisites.forEach {
textList += FormattedLine(it.name, link = it.makeLink())
}
}
}
return stringBuilder.toString()
if (unitTypes.isNotEmpty()) {
textList += FormattedLine()
// This separates the linkable (corresponding to a BaseUnit name) unitFilter entries
// from the others - `first` collects those for which the predicate is `true`.
val types = unitTypes.partition { it in ruleset.units }
if (unitTypes.size == 1) {
if (types.first.isNotEmpty())
types.first.first().let {
textList += FormattedLine("Available for [${it.tr()}]", link = "Unit/$it")
}
else
textList += FormattedLine("Available for [${types.second.first().tr()}]")
} else {
textList += FormattedLine("Available for:")
types.first.forEach {
textList += FormattedLine(it, indent = 1, link = "Unit/$it")
}
types.second.forEach {
textList += FormattedLine(it, indent = 1)
}
}
}
val freeForUnits = ruleset.units.filter { it.value.promotions.contains(name) }.map { it.key }
if (freeForUnits.isNotEmpty()) {
textList += FormattedLine()
if (freeForUnits.size == 1) {
freeForUnits[0].let {
textList += FormattedLine("Free for [$it]", link = "Unit/$it")
}
} else {
textList += FormattedLine("Free for:")
freeForUnits.forEach {
textList += FormattedLine(it, link = "Unit/$it")
}
}
}
val grantors = ruleset.buildings.values.filter {
building -> building.uniqueObjects.any {
it.placeholderText == "All newly-trained [] units [] receive the [] promotion"
&& it.params[2] == name
}
} + ruleset.terrains.values.filter {
// once that unique is parameterized, this will be the efficient order of checks
terrain -> terrain.uniques.any {
it == "Grants Rejuvenation (all healing effects doubled) to adjacent military land units for the rest of the game"
&& name == "Rejuvenation"
}
}
if (grantors.isNotEmpty()) {
textList += FormattedLine()
if (grantors.size == 1) {
grantors[0].let {
textList += FormattedLine("Granted by [${it.name}]", link = it.makeLink())
}
} else {
textList += FormattedLine("Granted by:")
grantors.forEach {
textList += FormattedLine(it.name, link = it.makeLink(), indent = 1)
}
}
}
return textList
}
}

View File

@ -242,7 +242,7 @@ class CivilopediaScreen(
.map {
CivilopediaEntry(
it.name,
it.getUniqueString(ruleset, false),
"",
CivilopediaCategories.Nation.getImage?.invoke(it.name, imageSize),
(it as? ICivilopediaText).takeUnless { ct -> ct==null || ct.isCivilopediaTextEmpty() }
)
@ -260,7 +260,7 @@ class CivilopediaScreen(
.map {
CivilopediaEntry(
it.name,
it.getDescription(ruleset.unitPromotions.values, true, ruleset),
"",
CivilopediaCategories.Promotion.getImage?.invoke(it.name, imageSize),
(it as? ICivilopediaText).takeUnless { ct -> ct==null || ct.isCivilopediaTextEmpty() }
)

View File

@ -138,6 +138,8 @@ class FormattedLine (
const val iconPad = 5f
/** Padding distance per [indent] level */
const val indentPad = 30f
/** Where indent==1 will be, measured as icon count */
const val indentOneAtNumIcons = 3
// Helper for constructor(Unique)
private fun getUniqueLink(unique: Unique): String {
@ -259,7 +261,9 @@ class FormattedLine (
centered -> -usedWidth
indent == 0 && iconCount == 0 -> 0f
indent == 0 -> iconPad
else -> (indent-1) * indentPad + 3 * minIconSize + 4 * iconPad - usedWidth
noLinkImages -> indent * indentPad - usedWidth
else -> (indent-1) * indentPad +
indentOneAtNumIcons * (minIconSize + iconPad) + iconPad - usedWidth
}
val label = if (fontSize == defaultSize && labelColor == defaultColor) textToDisplay.toLabel()
else textToDisplay.toLabel(labelColor,fontSize)