mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-26 13:27:22 -04:00
Civilopedia Phase X (#5003)
* Civilopedia Phase X - Show Policies * Civilopedia Phase X - Show City States * Civilopedia - Loop-driven init and Cleanup * Civilopedia - City States * Civilopedia Phase X - Remove spurious comments
This commit is contained in:
parent
30e5ac3665
commit
bf2ee91b67
@ -161,7 +161,6 @@ Declare Protection of [cityStateName]? =
|
||||
Build [improvementName] on [resourceName] (200 Gold) =
|
||||
Gift Improvement =
|
||||
|
||||
|
||||
Cultured =
|
||||
Maritime =
|
||||
Mercantile =
|
||||
@ -175,9 +174,12 @@ Personality =
|
||||
Influence =
|
||||
Reach 30 for friendship. =
|
||||
Reach highest influence above 60 for alliance. =
|
||||
|
||||
When Friends: =
|
||||
When Allies: =
|
||||
The unique luxury is one of: =
|
||||
|
||||
# Trades
|
||||
|
||||
|
||||
Trade =
|
||||
Offer trade =
|
||||
Retract offer =
|
||||
@ -989,9 +991,10 @@ Adopt free policy =
|
||||
Unlocked at =
|
||||
Gain 2 free technologies =
|
||||
All policies adopted =
|
||||
|
||||
# Religions
|
||||
|
||||
Policy branch: [branchName] =
|
||||
|
||||
# Religions
|
||||
|
||||
Choose an Icon and name for your Religion =
|
||||
Choose a [beliefType] belief! =
|
||||
Found [religionName] =
|
||||
|
@ -1,10 +1,10 @@
|
||||
package com.unciv.logic.civilization
|
||||
|
||||
enum class CityStateType {
|
||||
Cultured,
|
||||
Maritime,
|
||||
Mercantile,
|
||||
Militaristic
|
||||
enum class CityStateType(val color: String = "") {
|
||||
Cultured("#8b60ff"),
|
||||
Maritime("#38ff70"),
|
||||
Mercantile("#ffd800"),
|
||||
Militaristic("#ff0000")
|
||||
}
|
||||
|
||||
enum class CityStatePersonality {
|
||||
|
@ -2,6 +2,7 @@ package com.unciv.logic.civilization
|
||||
|
||||
import com.unciv.logic.civilization.diplomacy.RelationshipLevel
|
||||
import com.unciv.models.metadata.BASE_GAME_DURATION_TURNS
|
||||
import com.unciv.models.ruleset.Policy
|
||||
import com.unciv.models.ruleset.tile.ResourceType
|
||||
import com.unciv.models.stats.Stat
|
||||
import com.unciv.models.stats.StatMap
|
||||
@ -221,7 +222,7 @@ class CivInfoStats(val civInfo: CivilizationInfo) {
|
||||
if (civInfo.hasUnique("Provides 1 happiness per 2 additional social policies adopted")) {
|
||||
if (!statMap.containsKey("Policies")) statMap["Policies"] = 0f
|
||||
statMap["Policies"] = statMap["Policies"]!! +
|
||||
civInfo.policies.getAdoptedPolicies().count { !it.endsWith("Complete") } / 2
|
||||
civInfo.policies.getAdoptedPolicies().count { !Policy.isBranchCompleteByName(it) } / 2
|
||||
}
|
||||
|
||||
var happinessPerNaturalWonder = 1f
|
||||
|
@ -204,7 +204,7 @@ class CivilizationInfo {
|
||||
fun isAlive(): Boolean = !isDefeated()
|
||||
fun hasEverBeenFriendWith(otherCiv: CivilizationInfo): Boolean = getDiplomacyManager(otherCiv).everBeenFriends()
|
||||
fun hasMetCivTerritory(otherCiv: CivilizationInfo): Boolean = otherCiv.getCivTerritory().any { it in exploredTiles }
|
||||
fun getCompletedPolicyBranchesCount(): Int = policies.adoptedPolicies.count { it.endsWith("Complete") }
|
||||
fun getCompletedPolicyBranchesCount(): Int = policies.adoptedPolicies.count { Policy.isBranchCompleteByName(it) }
|
||||
private fun getCivTerritory() = cities.asSequence().flatMap { it.tiles.asSequence() }
|
||||
|
||||
fun victoryType(): VictoryType {
|
||||
@ -490,7 +490,7 @@ class CivilizationInfo {
|
||||
RankingType.Force -> units.sumBy { it.baseUnit.strength }
|
||||
RankingType.Happiness -> getHappiness()
|
||||
RankingType.Technologies -> tech.researchedTechnologies.size
|
||||
RankingType.Culture -> policies.adoptedPolicies.count { !it.endsWith("Complete") }
|
||||
RankingType.Culture -> policies.adoptedPolicies.count { !Policy.isBranchCompleteByName(it) }
|
||||
}
|
||||
}
|
||||
|
||||
@ -520,7 +520,7 @@ class CivilizationInfo {
|
||||
|
||||
policies.civInfo = this
|
||||
if (policies.adoptedPolicies.size > 0 && policies.numberOfAdoptedPolicies == 0)
|
||||
policies.numberOfAdoptedPolicies = policies.adoptedPolicies.count { !it.endsWith("Complete") }
|
||||
policies.numberOfAdoptedPolicies = policies.adoptedPolicies.count { !Policy.isBranchCompleteByName(it) }
|
||||
policies.setTransients()
|
||||
|
||||
questManager.civInfo = this
|
||||
|
@ -2,6 +2,7 @@ package com.unciv.logic.civilization
|
||||
|
||||
import com.unciv.logic.map.MapSize
|
||||
import com.unciv.models.ruleset.Policy
|
||||
import com.unciv.models.ruleset.Policy.PolicyBranchType
|
||||
import com.unciv.models.ruleset.UniqueMap
|
||||
import com.unciv.models.ruleset.UniqueTriggerActivation
|
||||
import com.unciv.models.translations.equalsPlaceholderText
|
||||
@ -124,7 +125,7 @@ class PolicyManager {
|
||||
*/
|
||||
fun isAdoptable(policy: Policy, checkEra: Boolean = true): Boolean {
|
||||
if (isAdopted(policy.name)) return false
|
||||
if (policy.name.endsWith("Complete")) return false
|
||||
if (policy.policyBranchType == PolicyBranchType.BranchComplete) return false
|
||||
if (!getAdoptedPolicies().containsAll(policy.requires!!)) return false
|
||||
if (checkEra && civInfo.gameInfo.ruleSet.getEraNumber(policy.branch.era) > civInfo.getEraNumber()) return false
|
||||
if (policy.uniqueObjects.any { it.placeholderText == "Incompatible with []" && adoptedPolicies.contains(it.params[0]) }) return false
|
||||
|
@ -2,8 +2,10 @@ package com.unciv.models.ruleset
|
||||
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.models.stats.INamed
|
||||
import com.unciv.models.translations.tr
|
||||
import com.unciv.ui.civilopedia.FormattedLine
|
||||
import com.unciv.ui.civilopedia.ICivilopediaText
|
||||
import java.text.Collator
|
||||
import java.util.ArrayList
|
||||
|
||||
class Belief : INamed, ICivilopediaText, IHasUniques {
|
||||
@ -15,12 +17,16 @@ class Belief : INamed, ICivilopediaText, IHasUniques {
|
||||
override var civilopediaText = listOf<FormattedLine>()
|
||||
|
||||
override fun makeLink() = "Belief/$name"
|
||||
override fun getCivilopediaTextHeader() = FormattedLine(name, icon = makeLink(), header = 2, color = if (type == BeliefType.None) "#e34a2b" else "")
|
||||
override fun replacesCivilopediaDescription() = true
|
||||
override fun hasCivilopediaTextLines() = true
|
||||
override fun getSortGroup(ruleset: Ruleset) = type.ordinal
|
||||
override fun getIconName() = if (type == BeliefType.None) "Religion" else type.name
|
||||
|
||||
override fun getCivilopediaTextLines(ruleset: Ruleset): List<FormattedLine> {
|
||||
val textList = ArrayList<FormattedLine>()
|
||||
textList += FormattedLine("{Type}: $type", color=type.color )
|
||||
if (type != BeliefType.None)
|
||||
textList += FormattedLine("{Type}: $type", color = type.color )
|
||||
uniqueObjects.forEach {
|
||||
textList += FormattedLine(it)
|
||||
}
|
||||
@ -49,7 +55,17 @@ class Belief : INamed, ICivilopediaText, IHasUniques {
|
||||
val matchingBeliefs = getBeliefsMatching(name, ruleset)
|
||||
if (matchingBeliefs.none()) return@sequence
|
||||
if (withSeeAlso) { yield(FormattedLine()); yield(FormattedLine("{See also}:")) }
|
||||
yieldAll(matchingBeliefs.map { FormattedLine(it.name, link=it.makeLink(), indent = 1) })
|
||||
yieldAll(matchingBeliefs.map { FormattedLine(it.name, link = it.makeLink(), indent = 1) })
|
||||
}
|
||||
|
||||
fun getCivilopediaReligionEntry(ruleset: Ruleset) = Belief().apply {
|
||||
name = "Religions"
|
||||
val lines = ArrayList<FormattedLine>()
|
||||
lines += FormattedLine(separator = true)
|
||||
ruleset.religions.sortedWith(compareBy(Collator.getInstance(), { it.tr() })).forEach {
|
||||
lines += FormattedLine(it, icon = "Belief/$it")
|
||||
}
|
||||
civilopediaText = lines
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -31,9 +31,27 @@ class Era : INamed {
|
||||
repeat(startingMilitaryUnitCount) {startingUnits.add(startingMilitaryUnit)}
|
||||
return startingUnits
|
||||
}
|
||||
|
||||
|
||||
fun getColor(): Color {
|
||||
if (iconRGB == null) return Color.WHITE.cpy()
|
||||
return colorFromRGB(iconRGB!![0], iconRGB!![1], iconRGB!![2])
|
||||
}
|
||||
|
||||
fun getHexColor() = "#" + getColor().toString().substring(0,6)
|
||||
|
||||
companion object {
|
||||
// User for CS bonuses in case the Eras file is missing (legacy mods)
|
||||
fun getLegacyCityStateBonusEra(eraNumber: Int) = Era().apply {
|
||||
val cultureBonus = if(eraNumber in 0..1) 3 else if (eraNumber in 2..3) 6 else 13
|
||||
val happinessBonus = if(eraNumber in 0..1) 2 else 3
|
||||
friendBonus[CityStateType.Militaristic.name] = arrayListOf("Provides military units every [20] turns")
|
||||
friendBonus[CityStateType.Cultured.name] = arrayListOf("Provides [$cultureBonus] [Culture] per turn")
|
||||
friendBonus[CityStateType.Mercantile.name] = arrayListOf("Provides [$happinessBonus] Happiness")
|
||||
friendBonus[CityStateType.Maritime.name] = arrayListOf("Provides [2] [Food] [in capital]")
|
||||
allyBonus[CityStateType.Militaristic.name] = arrayListOf("Provides military units every [17] turns")
|
||||
allyBonus[CityStateType.Cultured.name] = arrayListOf("Provides [${cultureBonus*2}] [Culture] per turn")
|
||||
allyBonus[CityStateType.Mercantile.name] = arrayListOf("Provides [$happinessBonus] Happiness", "Provides a unique luxury")
|
||||
allyBonus[CityStateType.Maritime.name] = arrayListOf("Provides [2] [Food] [in capital]", "Provides [1] [Food] [in all cities]")
|
||||
}
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.unciv.Constants
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.logic.civilization.CityStateType
|
||||
import com.unciv.models.stats.INamed
|
||||
import com.unciv.models.translations.squareBraceRegex
|
||||
@ -195,8 +196,15 @@ class Nation : INamed, ICivilopediaText, IHasUniques {
|
||||
override fun makeLink() = "Nation/$name"
|
||||
override fun replacesCivilopediaDescription() = true
|
||||
override fun hasCivilopediaTextLines() = true
|
||||
override fun getSortGroup(ruleset: Ruleset) = when {
|
||||
isCityState() -> 1
|
||||
isBarbarian() -> 9
|
||||
else -> 0
|
||||
}
|
||||
|
||||
override fun getCivilopediaTextLines(ruleset: Ruleset): List<FormattedLine> {
|
||||
if (isCityState()) return getCityStateInfo(ruleset)
|
||||
|
||||
val textList = ArrayList<FormattedLine>()
|
||||
|
||||
if (leaderName.isNotEmpty()) {
|
||||
@ -235,6 +243,50 @@ class Nation : INamed, ICivilopediaText, IHasUniques {
|
||||
return textList
|
||||
}
|
||||
|
||||
private fun getCityStateInfo(ruleset: Ruleset): List<FormattedLine> {
|
||||
val textList = ArrayList<FormattedLine>()
|
||||
|
||||
textList += FormattedLine("Type: [$cityStateType]", header = 4, color = cityStateType!!.color)
|
||||
val viewingCiv = UncivGame.Current.gameInfo.currentPlayerCiv
|
||||
val era = viewingCiv.getEraObject() ?: Era.getLegacyCityStateBonusEra(viewingCiv.getEraNumber())
|
||||
var showResources = false
|
||||
|
||||
val friendBonus = era.friendBonus[cityStateType!!.name]
|
||||
if (friendBonus != null && friendBonus.isNotEmpty()) {
|
||||
textList += FormattedLine()
|
||||
textList += FormattedLine("When Friends: ")
|
||||
friendBonus.forEach {
|
||||
textList += FormattedLine(Unique(it), indent = 1)
|
||||
if (it == "Provides a unique luxury") showResources = true
|
||||
}
|
||||
}
|
||||
|
||||
val allyBonus = era.allyBonus[cityStateType!!.name]
|
||||
if (allyBonus != null && allyBonus.isNotEmpty()) {
|
||||
textList += FormattedLine()
|
||||
textList += FormattedLine("When Allies: ")
|
||||
allyBonus.forEach {
|
||||
textList += FormattedLine(Unique(it), indent = 1)
|
||||
if (it == "Provides a unique luxury") showResources = true
|
||||
}
|
||||
}
|
||||
|
||||
if (showResources) {
|
||||
val allMercantileResources = ruleset.tileResources.values
|
||||
.filter { it.unique == "Can only be created by Mercantile City-States" }
|
||||
if (allMercantileResources.isNotEmpty()) {
|
||||
textList += FormattedLine()
|
||||
textList += FormattedLine("The unique luxury is one of:")
|
||||
allMercantileResources.forEach {
|
||||
textList += FormattedLine(it.name, it.makeLink(), indent = 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// personality is not a nation property, it gets assigned to the civ randomly
|
||||
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) {
|
||||
@ -305,10 +357,10 @@ class Nation : INamed, ICivilopediaText, IHasUniques {
|
||||
link = "Promotion/$promotion", indent = 1 )
|
||||
}
|
||||
} else if (unit.replaces != null) {
|
||||
textList += FormattedLine("Replaces [${unit.replaces}], which is not found in the ruleset!", indent=1)
|
||||
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)
|
||||
FormattedLine(it.text, link = it.link, indent = it.indent + 1, color = it.color)
|
||||
}
|
||||
}
|
||||
|
||||
@ -321,16 +373,16 @@ class Nation : INamed, ICivilopediaText, IHasUniques {
|
||||
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
|
||||
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)
|
||||
link = "Terrain/${it.value}", indent = if (it.index == 0) 1 else 2)
|
||||
}
|
||||
}
|
||||
for (unique in improvement.uniques)
|
||||
textList += FormattedLine(unique, indent=1)
|
||||
textList += FormattedLine(unique, indent = 1)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,11 @@
|
||||
package com.unciv.models.ruleset
|
||||
|
||||
import com.unciv.models.stats.INamed
|
||||
import com.unciv.models.translations.tr
|
||||
import com.unciv.ui.civilopedia.FormattedLine
|
||||
import com.unciv.ui.civilopedia.ICivilopediaText
|
||||
|
||||
open class Policy : INamed, IHasUniques {
|
||||
open class Policy : INamed, IHasUniques, ICivilopediaText {
|
||||
lateinit var branch: PolicyBranch // not in json - added in gameBasics
|
||||
|
||||
override lateinit var name: String
|
||||
@ -12,6 +15,94 @@ open class Policy : INamed, IHasUniques {
|
||||
var column: Int = 0
|
||||
var requires: ArrayList<String>? = null
|
||||
|
||||
override var civilopediaText = listOf<FormattedLine>()
|
||||
|
||||
/** Indicates whether a [Policy] is a [PolicyBranch] starting policy, a normal one, or the branch completion */
|
||||
enum class PolicyBranchType {BranchStart, Member, BranchComplete}
|
||||
/** Indicates whether this [Policy] is a [PolicyBranch] starting policy, a normal one, or the branch completion */
|
||||
val policyBranchType: PolicyBranchType by lazy { when {
|
||||
this is PolicyBranch -> PolicyBranchType.BranchStart
|
||||
isBranchCompleteByName(name) -> PolicyBranchType.BranchComplete
|
||||
else -> PolicyBranchType.Member
|
||||
} }
|
||||
companion object {
|
||||
const val branchCompleteSuffix = " Complete"
|
||||
/** Some tests to count policies by completion or not use only the String collection without instantiating them.
|
||||
* To keep the hardcoding in one place, this is public and should be used instead of duplicating it.
|
||||
*/
|
||||
fun isBranchCompleteByName(name: String) = name.endsWith(branchCompleteSuffix)
|
||||
}
|
||||
|
||||
override fun toString() = name
|
||||
|
||||
/** Used in PolicyPickerScreen to display Policy properties */
|
||||
fun getDescription(): String {
|
||||
val policyText = ArrayList<String>()
|
||||
policyText += name
|
||||
policyText += uniques
|
||||
|
||||
if (policyBranchType != PolicyBranchType.BranchComplete) {
|
||||
policyText += if (requires!!.isNotEmpty())
|
||||
"Requires [" + requires!!.joinToString { it.tr() } + "]"
|
||||
else
|
||||
"{Unlocked at} {${branch.era}}"
|
||||
}
|
||||
return policyText.joinToString("\n") { it.tr() }
|
||||
}
|
||||
|
||||
override fun makeLink() = "Policy/$name"
|
||||
override fun replacesCivilopediaDescription() = true
|
||||
override fun hasCivilopediaTextLines() = true
|
||||
override fun getSortGroup(ruleset: Ruleset) =
|
||||
ruleset.getEraNumber(branch.era) * 10000 +
|
||||
ruleset.policyBranches.keys.indexOf(branch.name) * 100 +
|
||||
policyBranchType.ordinal
|
||||
|
||||
override fun getCivilopediaTextLines(ruleset: Ruleset): List<FormattedLine> {
|
||||
val lineList = ArrayList<FormattedLine>()
|
||||
|
||||
lineList += if (this is PolicyBranch) {
|
||||
val eraColor = ruleset.eras[era]?.getHexColor() ?: ""
|
||||
FormattedLine("{Unlocked at} {${branch.era}}", header = 4, color = eraColor)
|
||||
} else {
|
||||
FormattedLine("Policy branch: [${branch.name}]", link = branch.makeLink())
|
||||
}
|
||||
|
||||
if (policyBranchType != PolicyBranchType.BranchComplete && requires != null && requires!!.isNotEmpty()) {
|
||||
lineList += FormattedLine()
|
||||
if (requires!!.size == 1)
|
||||
requires!!.first().let { lineList += FormattedLine("Requires: [$it]", link = "Policy/$it") }
|
||||
else {
|
||||
lineList += FormattedLine("Requires all of the following:")
|
||||
requires!!.forEach {
|
||||
lineList += FormattedLine(it, link = "Policy/$it")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val leadsTo = ruleset.policies.values.filter {
|
||||
it.requires != null && name in it.requires!!
|
||||
&& it.policyBranchType != PolicyBranchType.BranchComplete
|
||||
}
|
||||
if (leadsTo.isNotEmpty()) {
|
||||
lineList += FormattedLine()
|
||||
if (leadsTo.size == 1)
|
||||
leadsTo.first().let { lineList += FormattedLine("Leads to [${it.name}]", link = it.makeLink()) }
|
||||
else {
|
||||
lineList += FormattedLine("Leads to:")
|
||||
leadsTo.forEach {
|
||||
lineList += FormattedLine(it.name, link = it.makeLink(), indent = 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (uniques.isNotEmpty()) {
|
||||
lineList += FormattedLine()
|
||||
for (unique in uniqueObjects) lineList += FormattedLine(unique)
|
||||
}
|
||||
|
||||
return lineList
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -4,12 +4,12 @@ import com.unciv.models.stats.INamed
|
||||
import com.unciv.ui.civilopedia.FormattedLine
|
||||
import com.unciv.ui.civilopedia.ICivilopediaText
|
||||
|
||||
class RuinReward : INamed, ICivilopediaText {
|
||||
class RuinReward : INamed, ICivilopediaText, IHasUniques {
|
||||
override lateinit var name: String // Displayed in Civilopedia!
|
||||
val notification: String = ""
|
||||
val uniques: List<String> = listOf()
|
||||
override var uniques = ArrayList<String>()
|
||||
@delegate:Transient // Defense in depth against mad modders
|
||||
val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it) } }
|
||||
override val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it) } }
|
||||
val excludedDifficulties: List<String> = listOf()
|
||||
val weight: Int = 1
|
||||
val color: String = "" // For Civilopedia
|
||||
|
@ -206,7 +206,7 @@ class Ruleset {
|
||||
if (policy.requires == null) policy.requires = arrayListOf(branch.name)
|
||||
policies[policy.name] = policy
|
||||
}
|
||||
branch.policies.last().name = branch.name + " Complete"
|
||||
branch.policies.last().name = branch.name + Policy.branchCompleteSuffix
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -150,7 +150,8 @@ class Technology: INamed, ICivilopediaText, IHasUniques {
|
||||
override fun getCivilopediaTextLines(ruleset: Ruleset): List<FormattedLine> {
|
||||
val lineList = ArrayList<FormattedLine>()
|
||||
|
||||
lineList += FormattedLine(era(), header = 3, color = "#8080ff")
|
||||
val eraColor = ruleset.eras[era()]?.getHexColor() ?: ""
|
||||
lineList += FormattedLine(era(), header = 3, color = eraColor)
|
||||
lineList += FormattedLine()
|
||||
lineList += FormattedLine("{Cost}: $cost${Fonts.science}")
|
||||
|
||||
|
@ -127,21 +127,12 @@ class Terrain : NamedStats(), ICivilopediaText {
|
||||
if (defenceBonus != 0f)
|
||||
textList += FormattedLine("{Defence bonus}: ${(defenceBonus * 100).toInt()}%")
|
||||
|
||||
val seeAlso = (
|
||||
//todo: Could vastly be simplified using upcoming INonPerpetualConstruction
|
||||
ruleset.buildings.values.asSequence()
|
||||
.filter {
|
||||
building -> building.uniqueObjects.any {
|
||||
unique -> unique.params.any { it == name }
|
||||
}
|
||||
} +
|
||||
ruleset.units.values.asSequence()
|
||||
.filter {
|
||||
unit -> unit.uniqueObjects.any {
|
||||
unique -> unique.params.any { it == name }
|
||||
}
|
||||
val seeAlso = (ruleset.buildings.values.asSequence() + ruleset.units.values.asSequence())
|
||||
.filter {
|
||||
construction -> construction.uniqueObjects.any {
|
||||
unique -> unique.params.any { it == name }
|
||||
}
|
||||
).map { FormattedLine(it.name, it.makeLink(), indent=1) } +
|
||||
}.map { FormattedLine(it.name, it.makeLink(), indent=1) } +
|
||||
Belief.getCivilopediaTextMatching(name, ruleset, false)
|
||||
if (seeAlso.any()) {
|
||||
textList += FormattedLine()
|
||||
|
@ -3,7 +3,6 @@ package com.unciv.models.ruleset.tile
|
||||
import com.unciv.Constants
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.logic.civilization.CivilizationInfo
|
||||
import com.unciv.logic.civilization.RuinsManager.RuinsManager
|
||||
import com.unciv.models.ruleset.Belief
|
||||
import com.unciv.logic.map.RoadStatus
|
||||
import com.unciv.models.ruleset.IHasUniques
|
||||
|
@ -200,10 +200,10 @@ class BaseUnit : INamed, INonPerpetualConstruction, ICivilopediaText {
|
||||
var productionCost = cost.toFloat()
|
||||
if (civInfo.isCityState())
|
||||
productionCost *= 1.5f
|
||||
if (civInfo.isPlayerCivilization())
|
||||
productionCost *= civInfo.getDifficulty().unitCostModifier
|
||||
else
|
||||
productionCost *= civInfo.gameInfo.getDifficulty().aiUnitCostModifier
|
||||
productionCost *= if (civInfo.isPlayerCivilization())
|
||||
civInfo.getDifficulty().unitCostModifier
|
||||
else
|
||||
civInfo.gameInfo.getDifficulty().aiUnitCostModifier
|
||||
productionCost *= civInfo.gameInfo.gameParameters.gameSpeed.modifier
|
||||
return productionCost.toInt()
|
||||
}
|
||||
@ -298,8 +298,8 @@ class BaseUnit : INamed, INonPerpetualConstruction, 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 (uniques.contains(Constants.settlerUnique) && civInfo.isCityState()) return "No settler for city-states"
|
||||
@ -322,7 +322,7 @@ class BaseUnit : INamed, INonPerpetualConstruction, ICivilopediaText {
|
||||
override fun postBuildEvent(cityConstructions: CityConstructions, wasBought: Boolean): Boolean {
|
||||
val civInfo = cityConstructions.cityInfo.civInfo
|
||||
val unit = civInfo.placeUnitNearTile(cityConstructions.cityInfo.location, name)
|
||||
if (unit == null) return false // couldn't place the unit, so there's actually no unit =(
|
||||
?: return false // couldn't place the unit, so there's actually no unit =(
|
||||
|
||||
//movement penalty
|
||||
if (wasBought && !civInfo.gameInfo.gameParameters.godMode && !unit.hasUnique("Can move immediately once bought"))
|
||||
|
@ -16,7 +16,7 @@ enum class Stat(
|
||||
Culture(NotificationIcon.Culture, UncivSound.Paper, Fonts.culture),
|
||||
Happiness(NotificationIcon.Happiness, UncivSound.Click, Fonts.happiness),
|
||||
Faith(NotificationIcon.Faith, UncivSound.Choir, Fonts.faith);
|
||||
|
||||
|
||||
companion object {
|
||||
val statsUsableToBuy = listOf(Gold, Food, Science, Culture, Faith)
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ import java.io.File
|
||||
/** Encapsulates the knowledge on how to get an icon for each of the Civilopedia categories */
|
||||
object CivilopediaImageGetters {
|
||||
private const val policyIconFolder = "PolicyIcons"
|
||||
private const val policyInnerSize = 0.25f
|
||||
|
||||
// Todo: potential synergy with map editor
|
||||
fun terrainImage(terrain: Terrain, ruleset: Ruleset, imageSize: Float): Actor {
|
||||
@ -48,7 +49,7 @@ object CivilopediaImageGetters {
|
||||
|
||||
val construction = { name: String, size: Float ->
|
||||
ImageGetter.getConstructionImage(name)
|
||||
.surroundWithCircle(size, color = Color.WHITE)
|
||||
.surroundWithCircle(size)
|
||||
}
|
||||
val improvement = { name: String, size: Float ->
|
||||
ImageGetter.getImprovementIcon(name, size)
|
||||
@ -59,8 +60,16 @@ object CivilopediaImageGetters {
|
||||
else ImageGetter.getNationIndicator(nation, size)
|
||||
}
|
||||
val policy = { name: String, size: Float ->
|
||||
ImageGetter.getImage(policyIconFolder + File.separator + name)
|
||||
.apply { setSize(size,size) }
|
||||
// policy branch start and complete have no icons but are linked -> nonexistence must be passed down
|
||||
val fileName = policyIconFolder + File.separator + name
|
||||
if (ImageGetter.imageExists(fileName))
|
||||
ImageGetter.getImage(fileName)
|
||||
.apply {
|
||||
setSize(size * policyInnerSize,size * policyInnerSize)
|
||||
color = Color.BROWN
|
||||
}
|
||||
.surroundWithCircle(size)
|
||||
else null
|
||||
}
|
||||
val resource = { name: String, size: Float ->
|
||||
ImageGetter.getResourceImage(name, size)
|
||||
@ -97,6 +106,7 @@ object CivilopediaImageGetters {
|
||||
/** Enum used as keys for Civilopedia "pages" (categories).
|
||||
*
|
||||
* Note names are singular on purpose - a "link" allows both key and label
|
||||
* Order of values determines ordering of the categories in the Civilopedia top bar
|
||||
*
|
||||
* @param label Translatable caption for the Civilopedia button
|
||||
*/
|
||||
@ -114,10 +124,10 @@ enum class CivilopediaCategories (
|
||||
Nation ("Nations", false, CivilopediaImageGetters.nation ),
|
||||
Technology ("Technologies", false, CivilopediaImageGetters.technology ),
|
||||
Promotion ("Promotions", false, CivilopediaImageGetters.promotion ),
|
||||
Policy ("Policies", true, CivilopediaImageGetters.policy ),
|
||||
Policy ("Policies", false, CivilopediaImageGetters.policy ),
|
||||
Belief("Religions and Beliefs", false, CivilopediaImageGetters.belief ),
|
||||
Tutorial ("Tutorials", false, null ),
|
||||
Difficulty ("Difficulty levels", false, null ),
|
||||
Belief("Religions and Beliefs", false, CivilopediaImageGetters.belief)
|
||||
;
|
||||
|
||||
companion object {
|
||||
|
@ -6,6 +6,7 @@ import com.badlogic.gdx.scenes.scene2d.Touchable
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.*
|
||||
import com.unciv.Constants
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.models.ruleset.Belief
|
||||
import com.unciv.models.ruleset.Ruleset
|
||||
import com.unciv.models.ruleset.Unique
|
||||
import com.unciv.models.ruleset.VictoryType
|
||||
@ -77,7 +78,7 @@ class CivilopediaScreen(
|
||||
/** Select a specified category
|
||||
* @param name Category name or label
|
||||
*/
|
||||
fun selectCategory(name: String) {
|
||||
private fun selectCategory(name: String) {
|
||||
val category = CivilopediaCategories.fromLink(name)
|
||||
?: return // silently ignore unknown category names in links
|
||||
selectCategory(category)
|
||||
@ -86,7 +87,7 @@ class CivilopediaScreen(
|
||||
/** Select a specified category - unselects entry, rebuilds left side buttons.
|
||||
* @param category Category key
|
||||
*/
|
||||
fun selectCategory(category: CivilopediaCategories) {
|
||||
private fun selectCategory(category: CivilopediaCategories) {
|
||||
currentCategory = category
|
||||
entrySelectTable.clear()
|
||||
entryIndex.clear()
|
||||
@ -173,139 +174,53 @@ class CivilopediaScreen(
|
||||
onBackButtonClicked { UncivGame.Current.setWorldScreen() }
|
||||
|
||||
val hideReligionItems = !game.gameInfo.hasReligionEnabled()
|
||||
val noCulturalVictory = VictoryType.Cultural !in game.gameInfo.gameParameters.victoryTypes
|
||||
|
||||
categoryToEntries[CivilopediaCategories.Building] = ruleset.buildings.values
|
||||
.filter { shouldBeDisplayed(it.uniqueObjects)
|
||||
&& !it.isAnyWonder() }
|
||||
.map {
|
||||
CivilopediaEntry(
|
||||
it.name,
|
||||
"",
|
||||
CivilopediaCategories.Building.getImage?.invoke(it.name, imageSize),
|
||||
(it as? ICivilopediaText).takeUnless { ct -> ct==null || ct.isCivilopediaTextEmpty() }
|
||||
)
|
||||
}
|
||||
categoryToEntries[CivilopediaCategories.Wonder] = ruleset.buildings.values
|
||||
.filter { shouldBeDisplayed(it.uniqueObjects)
|
||||
&& it.isAnyWonder() }
|
||||
.map {
|
||||
CivilopediaEntry(
|
||||
it.name,
|
||||
"",
|
||||
CivilopediaCategories.Wonder.getImage?.invoke(it.name, imageSize),
|
||||
(it as? ICivilopediaText).takeUnless { ct -> ct==null || ct.isCivilopediaTextEmpty() }
|
||||
)
|
||||
}
|
||||
categoryToEntries[CivilopediaCategories.Resource] = ruleset.tileResources.values
|
||||
.map {
|
||||
CivilopediaEntry(
|
||||
it.name,
|
||||
"",
|
||||
CivilopediaCategories.Resource.getImage?.invoke(it.name, imageSize),
|
||||
(it as? ICivilopediaText).takeUnless { ct -> ct==null || ct.isCivilopediaTextEmpty() }
|
||||
)
|
||||
}
|
||||
categoryToEntries[CivilopediaCategories.Terrain] = ruleset.terrains.values
|
||||
.filter { shouldBeDisplayed(it.uniqueObjects) }
|
||||
.map {
|
||||
CivilopediaEntry(
|
||||
it.name,
|
||||
"",
|
||||
CivilopediaCategories.Terrain.getImage?.invoke(it.name, imageSize),
|
||||
(it as? ICivilopediaText).takeUnless { ct -> ct==null || ct.isCivilopediaTextEmpty() }
|
||||
)
|
||||
}
|
||||
categoryToEntries[CivilopediaCategories.Improvement] = ruleset.tileImprovements.values
|
||||
.filter { shouldBeDisplayed(it.uniqueObjects) }
|
||||
.map {
|
||||
CivilopediaEntry(
|
||||
it.name,
|
||||
"",
|
||||
CivilopediaCategories.Improvement.getImage?.invoke(it.name, imageSize),
|
||||
(it as? ICivilopediaText).takeUnless { ct -> ct==null || ct.isCivilopediaTextEmpty() }
|
||||
)
|
||||
}
|
||||
categoryToEntries[CivilopediaCategories.Unit] = ruleset.units.values
|
||||
.filter { shouldBeDisplayed(it.uniqueObjects) }
|
||||
.map {
|
||||
CivilopediaEntry(
|
||||
it.name,
|
||||
"",
|
||||
CivilopediaCategories.Unit.getImage?.invoke(it.name, imageSize),
|
||||
(it as? ICivilopediaText).takeUnless { ct -> ct==null || ct.isCivilopediaTextEmpty() }
|
||||
)
|
||||
}
|
||||
categoryToEntries[CivilopediaCategories.Nation] = ruleset.nations.values
|
||||
.filter { shouldBeDisplayed(it.uniqueObjects) && it.isMajorCiv() }
|
||||
.map {
|
||||
CivilopediaEntry(
|
||||
it.name,
|
||||
"",
|
||||
CivilopediaCategories.Nation.getImage?.invoke(it.name, imageSize),
|
||||
(it as? ICivilopediaText).takeUnless { ct -> ct==null || ct.isCivilopediaTextEmpty() }
|
||||
)
|
||||
}
|
||||
categoryToEntries[CivilopediaCategories.Technology] = ruleset.technologies.values
|
||||
.filter { shouldBeDisplayed(it.uniqueObjects) }
|
||||
.map {
|
||||
CivilopediaEntry(
|
||||
it.name,
|
||||
"",
|
||||
CivilopediaCategories.Technology.getImage?.invoke(it.name, imageSize),
|
||||
(it as? ICivilopediaText).takeUnless { ct -> ct==null || ct.isCivilopediaTextEmpty() }
|
||||
)
|
||||
}
|
||||
categoryToEntries[CivilopediaCategories.Promotion] = ruleset.unitPromotions.values
|
||||
.filter { shouldBeDisplayed(it.uniqueObjects) }
|
||||
.map {
|
||||
CivilopediaEntry(
|
||||
it.name,
|
||||
"",
|
||||
CivilopediaCategories.Promotion.getImage?.invoke(it.name, imageSize),
|
||||
(it as? ICivilopediaText).takeUnless { ct -> ct==null || ct.isCivilopediaTextEmpty() }
|
||||
)
|
||||
}
|
||||
fun shouldBeDisplayed(uniqueObjects: List<Unique>): Boolean {
|
||||
val uniques = uniqueObjects.map { it.placeholderText }
|
||||
|
||||
categoryToEntries[CivilopediaCategories.Tutorial] = tutorialController.getCivilopediaTutorials()
|
||||
.map {
|
||||
CivilopediaEntry(
|
||||
it.name,
|
||||
"",
|
||||
// CivilopediaCategories.Tutorial.getImage?.invoke(it.name, imageSize)
|
||||
flavour = it
|
||||
)
|
||||
}
|
||||
return Constants.hideFromCivilopediaUnique !in uniques
|
||||
&& !(hideReligionItems && Constants.hiddenWithoutReligionUnique in uniques)
|
||||
&& !(uniqueObjects.filter { unique -> unique.placeholderText == "Hidden when [] Victory is disabled"}.any {
|
||||
unique -> !game.gameInfo.gameParameters.victoryTypes.contains(VictoryType.valueOf(unique.params[0] ))
|
||||
})
|
||||
// Deprecated since 3.15.14
|
||||
&& !(noCulturalVictory && "Hidden when cultural victory is disabled" in uniques)
|
||||
//
|
||||
}
|
||||
|
||||
categoryToEntries[CivilopediaCategories.Difficulty] = ruleset.difficulties.values
|
||||
.map {
|
||||
CivilopediaEntry(
|
||||
it.name,
|
||||
"",
|
||||
// CivilopediaCategories.Difficulty.getImage?.invoke(it.name, imageSize)
|
||||
flavour = (it as? ICivilopediaText)
|
||||
)
|
||||
}
|
||||
fun getCategoryIterator(category: CivilopediaCategories): Collection<ICivilopediaText> =
|
||||
when (category) {
|
||||
CivilopediaCategories.Building -> ruleset.buildings.values.filter { !it.isAnyWonder() }
|
||||
CivilopediaCategories.Wonder -> ruleset.buildings.values.filter { it.isAnyWonder() }
|
||||
CivilopediaCategories.Resource -> ruleset.tileResources.values
|
||||
CivilopediaCategories.Terrain -> ruleset.terrains.values
|
||||
CivilopediaCategories.Improvement -> ruleset.tileImprovements.values
|
||||
CivilopediaCategories.Unit -> ruleset.units.values
|
||||
CivilopediaCategories.Nation -> ruleset.nations.values.filter { !it.isSpectator() }
|
||||
CivilopediaCategories.Technology -> ruleset.technologies.values
|
||||
CivilopediaCategories.Promotion -> ruleset.unitPromotions.values
|
||||
CivilopediaCategories.Policy -> ruleset.policies.values
|
||||
CivilopediaCategories.Tutorial -> tutorialController.getCivilopediaTutorials()
|
||||
CivilopediaCategories.Difficulty -> ruleset.difficulties.values
|
||||
CivilopediaCategories.Belief -> (ruleset.beliefs.values.asSequence() +
|
||||
Belief.getCivilopediaReligionEntry(ruleset)).toList()
|
||||
}
|
||||
|
||||
for (loopCategory in CivilopediaCategories.values()) {
|
||||
if (loopCategory.hide) continue
|
||||
if (hideReligionItems && loopCategory == CivilopediaCategories.Belief) continue
|
||||
categoryToEntries[loopCategory] =
|
||||
getCategoryIterator(loopCategory)
|
||||
.filter { it.getUniquesAsObjects()?.let { uniques -> shouldBeDisplayed(uniques) } ?: true }
|
||||
.map { CivilopediaEntry(
|
||||
(it as INamed).name, "",
|
||||
loopCategory.getImage?.invoke(it.getIconName(), imageSize),
|
||||
it.takeUnless { ct -> ct.isCivilopediaTextEmpty() },
|
||||
sortBy = it.getSortGroup(ruleset)
|
||||
) }
|
||||
}
|
||||
|
||||
if (!hideReligionItems)
|
||||
categoryToEntries[CivilopediaCategories.Belief] = (
|
||||
ruleset.beliefs.values.asSequence()
|
||||
.map {
|
||||
CivilopediaEntry(
|
||||
it.name,
|
||||
"",
|
||||
CivilopediaCategories.Belief.getImage?.invoke(it.type.name, imageSize),
|
||||
(it as? ICivilopediaText).takeUnless { ct -> ct==null || ct.isCivilopediaTextEmpty() },
|
||||
sortBy = it.type.ordinal
|
||||
)
|
||||
} + CivilopediaEntry(
|
||||
"Religions",
|
||||
"",
|
||||
CivilopediaCategories.Belief.getImage?.invoke("Religion", imageSize),
|
||||
getReligionText(),
|
||||
sortBy = -1
|
||||
)
|
||||
).toList()
|
||||
|
||||
val buttonTable = Table()
|
||||
buttonTable.pad(15f)
|
||||
buttonTable.defaults().pad(10f)
|
||||
@ -364,31 +279,6 @@ class CivilopediaScreen(
|
||||
selectEntry(link, noScrollAnimation = true)
|
||||
}
|
||||
|
||||
private fun getReligionText(): ICivilopediaText {
|
||||
val lines = ArrayList<FormattedLine>()
|
||||
lines += FormattedLine("Religions", header=2, color="#e34a2b")
|
||||
lines += FormattedLine(separator=true)
|
||||
ruleset.religions.sortedWith(compareBy(Collator.getInstance(), { it.tr() })).forEach {
|
||||
lines += FormattedLine(it, icon="Belief/$it")
|
||||
}
|
||||
return SimpleCivilopediaText(lines, true)
|
||||
}
|
||||
|
||||
private fun shouldBeDisplayed(uniqueObjects: List<Unique>): Boolean {
|
||||
val uniques = uniqueObjects.map { it.placeholderText }
|
||||
val hideReligionItems = !game.gameInfo.hasReligionEnabled()
|
||||
val noCulturalVictory = VictoryType.Cultural !in game.gameInfo.gameParameters.victoryTypes
|
||||
|
||||
return Constants.hideFromCivilopediaUnique !in uniques
|
||||
&& !(hideReligionItems && Constants.hiddenWithoutReligionUnique in uniques)
|
||||
&& !(uniqueObjects.filter { unique -> unique.placeholderText == "Hidden when [] Victory is disabled"}.any {
|
||||
unique -> !game.gameInfo.gameParameters.victoryTypes.contains(VictoryType.valueOf(unique.params[0] ))
|
||||
})
|
||||
// Deprecated since 3.15.14
|
||||
&& !(noCulturalVictory && "Hidden when cultural victory is disabled" in uniques)
|
||||
//
|
||||
}
|
||||
|
||||
override fun resize(width: Int, height: Int) {
|
||||
if (stage.viewport.screenWidth != width || stage.viewport.screenHeight != height) {
|
||||
game.setScreen(CivilopediaScreen(game.worldScreen.gameInfo.ruleSet, currentCategory, currentEntry))
|
||||
|
@ -7,6 +7,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||
import com.badlogic.gdx.utils.Align
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.models.metadata.BaseRuleset
|
||||
import com.unciv.models.ruleset.IHasUniques
|
||||
import com.unciv.models.ruleset.Ruleset
|
||||
import com.unciv.models.ruleset.RulesetCache
|
||||
import com.unciv.models.ruleset.Unique
|
||||
@ -141,7 +142,7 @@ class FormattedLine (
|
||||
/** Padding distance per [indent] level */
|
||||
const val indentPad = 30f
|
||||
/** Where indent==1 will be, measured as icon count */
|
||||
const val indentOneAtNumIcons = 3
|
||||
const val indentOneAtNumIcons = 2
|
||||
|
||||
private var rulesetCachedInNameMap: Ruleset? = null
|
||||
// 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.
|
||||
@ -378,11 +379,6 @@ object MarkupRenderer {
|
||||
}
|
||||
}
|
||||
|
||||
/** Storage class for interface [ICivilopediaText] for use as base class */
|
||||
@Deprecated("As of 3.16.1, use ICivilopediaText directly please")
|
||||
abstract class CivilopediaText : ICivilopediaText {
|
||||
override var civilopediaText = listOf<FormattedLine>()
|
||||
}
|
||||
/** Storage class for instantiation of the simplest form containing only the lines collection */
|
||||
open class SimpleCivilopediaText(
|
||||
override var civilopediaText: List<FormattedLine>,
|
||||
@ -401,7 +397,7 @@ open class SimpleCivilopediaText(
|
||||
/** Addon common to most ruleset game objects managing civilopedia display
|
||||
*
|
||||
* ### Usage:
|
||||
* 1. Let [Ruleset] object implement this (e.g. by inheriting class [CivilopediaText] or adding var [civilopediaText] itself)
|
||||
* 1. Let [Ruleset] object implement this (by inheriting and implementing class [ICivilopediaText])
|
||||
* 2. Add `"civilopediaText": ["",…],` in the json for these objects
|
||||
* 3. Optionally override [getCivilopediaTextHeader] to supply a different header line
|
||||
* 4. Optionally override [getCivilopediaTextLines] to supply automatic stuff like tech prerequisites, uniques, etc.
|
||||
@ -484,4 +480,20 @@ interface ICivilopediaText {
|
||||
|
||||
/** Create the correct string for a Civilopedia link */
|
||||
fun makeLink(): String
|
||||
|
||||
/** This just marshals access to the uniques so they can be queried as part of the ICivilopediaText interface.
|
||||
* Used exclusively by CivilopediaScreen, named to avoid JVM signature confusion
|
||||
* (a getUniqueObjects exists in IHasUniques and most civilopedia objects will implement that interface)
|
||||
*/
|
||||
fun getUniquesAsObjects() = (this as? IHasUniques)?.uniqueObjects
|
||||
|
||||
/** Overrides alphabetical sorting in Civilopedia
|
||||
* @param ruleset The current ruleset in case the function needs to do lookups
|
||||
*/
|
||||
fun getSortGroup(ruleset: Ruleset): Int = 0
|
||||
|
||||
/** Overrides Icon used for Civilopedia entry list (where you select the instance)
|
||||
* This will still be passed to the category-specific image getter.
|
||||
*/
|
||||
fun getIconName() = if (this is INamed) name else ""
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import com.unciv.models.Tutorial
|
||||
import com.unciv.models.UncivSound
|
||||
import com.unciv.models.ruleset.Policy
|
||||
import com.unciv.models.ruleset.PolicyBranch
|
||||
import com.unciv.models.ruleset.Policy.PolicyBranchType
|
||||
import com.unciv.models.translations.tr
|
||||
import com.unciv.ui.utils.*
|
||||
import com.unciv.ui.worldscreen.WorldScreen
|
||||
@ -110,7 +111,7 @@ class PolicyPickerScreen(val worldScreen: WorldScreen, civInfo: CivilizationInfo
|
||||
|| worldScreen.viewingCiv.isSpectator() // viewingCiv var points to selectedCiv in case of spectator
|
||||
|| viewingCiv.isDefeated()
|
||||
|| viewingCiv.policies.isAdopted(policy.name)
|
||||
|| policy.name.endsWith("Complete")
|
||||
|| policy.policyBranchType == PolicyBranchType.BranchComplete
|
||||
|| !viewingCiv.policies.isAdoptable(policy)
|
||||
|| !viewingCiv.policies.canAdoptPolicy()) {
|
||||
rightSideButton.disable()
|
||||
@ -123,17 +124,8 @@ class PolicyPickerScreen(val worldScreen: WorldScreen, civInfo: CivilizationInfo
|
||||
game.setScreen(PolicyPickerScreen(worldScreen))
|
||||
}
|
||||
pickedPolicy = policy
|
||||
val policyText = mutableListOf<String>()
|
||||
policyText += policy.name
|
||||
policyText += policy.uniques
|
||||
|
||||
if (!policy.name.endsWith("Complete")) {
|
||||
if (policy.requires!!.isNotEmpty())
|
||||
policyText += "Requires [" + policy.requires!!.joinToString { it.tr() } + "]"
|
||||
else
|
||||
policyText += "{Unlocked at} {" + policy.branch.era + "}"
|
||||
}
|
||||
descriptionLabel.setText(policyText.joinToString("\n") { it.tr() })
|
||||
|
||||
descriptionLabel.setText(policy.getDescription())
|
||||
}
|
||||
|
||||
/**
|
||||
@ -151,7 +143,7 @@ class PolicyPickerScreen(val worldScreen: WorldScreen, civInfo: CivilizationInfo
|
||||
var currentColumn = 1
|
||||
val branchTable = Table()
|
||||
for (policy in branch.policies) {
|
||||
if (policy.name.endsWith("Complete")) continue
|
||||
if (policy.policyBranchType == PolicyBranchType.BranchComplete) continue
|
||||
if (policy.row > currentRow) {
|
||||
branchTable.row().pad(2.5f)
|
||||
currentRow++
|
||||
|
@ -16,6 +16,7 @@ import com.unciv.logic.civilization.diplomacy.RelationshipLevel
|
||||
import com.unciv.logic.trade.TradeLogic
|
||||
import com.unciv.logic.trade.TradeOffer
|
||||
import com.unciv.logic.trade.TradeType
|
||||
import com.unciv.models.ruleset.Era
|
||||
import com.unciv.models.ruleset.ModOptionsConstants
|
||||
import com.unciv.models.ruleset.Quest
|
||||
import com.unciv.models.ruleset.tile.ResourceType
|
||||
@ -158,67 +159,38 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() {
|
||||
else -> "Reach highest influence above 60 for alliance."
|
||||
}
|
||||
diplomacyTable.add(getRelationshipTable(otherCivDiplomacyManager)).row()
|
||||
if (nextLevelString != "") {
|
||||
if (nextLevelString.isNotEmpty()) {
|
||||
diplomacyTable.add(nextLevelString.toLabel()).row()
|
||||
}
|
||||
|
||||
var friendBonusText = "When Friends: ".tr()
|
||||
val eraInfo = viewingCiv.getEraObject()
|
||||
val friendBonuses =
|
||||
if (eraInfo == null) null
|
||||
else eraInfo.friendBonus[otherCiv.cityStateType.name]
|
||||
friendBonusText +=
|
||||
if (friendBonuses != null) {
|
||||
friendBonuses.joinToString(separator = ", ") { it.tr() }
|
||||
} else {
|
||||
// Deprecated, assume Civ V values for compatibility
|
||||
val cultureBonus = if(viewingCiv.getEraNumber() in 0..1) "3" else if (viewingCiv.getEraNumber() in 2..3) "6" else "13"
|
||||
val happinessBonus = if(viewingCiv.getEraNumber() in 0..1) "2" else "3"
|
||||
when (otherCiv.cityStateType) {
|
||||
CityStateType.Militaristic -> "Provides military units every [20] turns".tr()
|
||||
CityStateType.Cultured -> ("Provides [" + cultureBonus + "] [Culture] per turn").tr()
|
||||
CityStateType.Mercantile -> ("Provides [" + happinessBonus + "] Happiness").tr()
|
||||
CityStateType.Maritime -> "Provides [2] [Food] [in capital]".tr()
|
||||
}
|
||||
}
|
||||
val eraInfo = viewingCiv.getEraObject() ?: Era.getLegacyCityStateBonusEra(viewingCiv.getEraNumber())
|
||||
|
||||
var friendBonusText = "{When Friends:} ".tr()
|
||||
val friendBonuses = eraInfo.friendBonus[otherCiv.cityStateType.name]
|
||||
friendBonusText += friendBonuses?.joinToString(separator = ", ") { it.tr() } ?: ""
|
||||
|
||||
var allyBonusText = "When Allies: "
|
||||
val allyBonuses =
|
||||
if (eraInfo == null) null
|
||||
else eraInfo.allyBonus[otherCiv.cityStateType.name]
|
||||
if (allyBonuses != null) {
|
||||
allyBonusText += allyBonuses.joinToString(separator = ", ") { it.tr() }
|
||||
} else {
|
||||
// Deprecated, assume Civ V values for compatibility
|
||||
val cultureBonus = if(viewingCiv.getEraNumber() in 0..1) "6" else if (viewingCiv.getEraNumber() in 2..3) "12" else "26"
|
||||
val happinessBonus = if(viewingCiv.getEraNumber() in 0..1) "2" else "3"
|
||||
allyBonusText += when (otherCiv.cityStateType) {
|
||||
CityStateType.Militaristic -> "Provides military units every [20] turns".tr()
|
||||
CityStateType.Cultured -> ("Provides [" + cultureBonus + "] [Culture] per turn").tr()
|
||||
CityStateType.Mercantile -> ("Provides [" + happinessBonus + "] Happiness").tr() + ", " + "Provides a unique luxury".tr()
|
||||
CityStateType.Maritime -> "Provides [2] [Food] [in capital]".tr() + ", " + "Provides [1] [Food] [in all cities]".tr()
|
||||
}
|
||||
}
|
||||
var allyBonusText = "{When Allies:} ".tr()
|
||||
val allyBonuses = eraInfo.allyBonus[otherCiv.cityStateType.name]
|
||||
allyBonusText += allyBonuses?.joinToString(separator = ", ") { it.tr() } ?: ""
|
||||
|
||||
val friendBonusLabelColor: Color
|
||||
if (otherCivDiplomacyManager.relationshipLevel() >= RelationshipLevel.Friend) {
|
||||
friendBonusLabelColor = Color.GREEN
|
||||
val relationLevel = otherCivDiplomacyManager.relationshipLevel()
|
||||
if (relationLevel >= RelationshipLevel.Friend) {
|
||||
// RelationshipChange = Ally -> Friend or Friend -> Favorable
|
||||
val turnsToRelationshipChange = otherCivDiplomacyManager.getTurnsToRelationshipChange()
|
||||
diplomacyTable.add("Relationship changes in another [$turnsToRelationshipChange] turns".toLabel())
|
||||
.row()
|
||||
} else
|
||||
friendBonusLabelColor = Color.GRAY
|
||||
}
|
||||
|
||||
val friendBonusLabelColor = if (relationLevel >= RelationshipLevel.Friend) Color.GREEN else Color.GRAY
|
||||
val friendBonusLabel = friendBonusText.toLabel(friendBonusLabelColor)
|
||||
.apply { setAlignment(Align.center) }
|
||||
diplomacyTable.add(friendBonusLabel).row()
|
||||
val allyBonusLabelColor = if (otherCivDiplomacyManager.relationshipLevel() == RelationshipLevel.Ally) Color.GREEN else Color.GRAY
|
||||
|
||||
val allyBonusLabelColor = if (relationLevel == RelationshipLevel.Ally) Color.GREEN else Color.GRAY
|
||||
val allyBonusLabel = allyBonusText.toLabel(allyBonusLabelColor)
|
||||
.apply { setAlignment(Align.center) }
|
||||
diplomacyTable.add(allyBonusLabel).row()
|
||||
|
||||
|
||||
return diplomacyTable
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.TextButton
|
||||
import com.badlogic.gdx.utils.Align
|
||||
import com.unciv.logic.civilization.CivilizationInfo
|
||||
import com.unciv.models.ruleset.Policy
|
||||
import com.unciv.models.ruleset.VictoryType
|
||||
import com.unciv.models.translations.getPlaceholderParameters
|
||||
import com.unciv.models.translations.tr
|
||||
@ -202,11 +203,11 @@ class VictoryScreen(val worldScreen: WorldScreen) : PickerScreen() {
|
||||
policyVictoryColumn.add("Branches completed".toLabel()).row()
|
||||
policyVictoryColumn.addSeparator()
|
||||
|
||||
data class civToBranchesCompleted(val civ: CivilizationInfo, val branchesCompleted: Int)
|
||||
data class CivToBranchesCompleted(val civ: CivilizationInfo, val branchesCompleted: Int)
|
||||
|
||||
val civsToBranchesCompleted =
|
||||
majorCivs.map { civToBranchesCompleted(it, it.policies.adoptedPolicies.count { pol -> pol.endsWith("Complete") }) }
|
||||
.sortedByDescending { it.branchesCompleted }
|
||||
val civsToBranchesCompleted = majorCivs.map {
|
||||
CivToBranchesCompleted(it, it.policies.adoptedPolicies.count { pol -> Policy.isBranchCompleteByName(pol) })
|
||||
}.sortedByDescending { it.branchesCompleted }
|
||||
|
||||
for (entry in civsToBranchesCompleted) {
|
||||
val civToBranchesHaveCompleted = EmpireOverviewScreen.getCivGroup(entry.civ, " - " + entry.branchesCompleted, playerCivInfo)
|
||||
|
Loading…
x
Reference in New Issue
Block a user