From d980b0d9ff904ec3974dd8678b128d752eeedbba Mon Sep 17 00:00:00 2001 From: alexban011 Date: Mon, 19 Sep 2022 16:12:24 +0300 Subject: [PATCH] Global politics overview screen (#7469) * getting the data * finished getting the data * optimization + separator * vrtical separators * more functions * made it look good * reverted debug variables * cleanup * added icon * credits * translations * removed redundant equalizeColumns * removed redundant separator * column headers * reviews * removed redundant function * latest translations * latest review * checks 1 * removed space * removed vars and used DiplomacyManager instead * combined overview screens * 2 more translations * little cleanup and fix --- android/Images/OtherIcons/Politics.png | Bin 0 -> 16963 bytes .../jsons/translations/template.properties | 9 + .../logic/civilization/CivilizationInfo.kt | 1 + .../unciv/logic/civilization/WonderInfo.kt | 191 +++++++++++++++++ .../diplomacy/DiplomacyManager.kt | 1 + .../EmpireOverviewCategories.kt | 6 +- ...able.kt => GlobalPoliticsOverviewTable.kt} | 195 ++++++++++++++++-- .../ui/overviewscreen/WonderOverviewTable.kt | 175 +--------------- docs/Credits.md | 1 + 9 files changed, 385 insertions(+), 194 deletions(-) create mode 100644 android/Images/OtherIcons/Politics.png create mode 100644 core/src/com/unciv/logic/civilization/WonderInfo.kt rename core/src/com/unciv/ui/overviewscreen/{DiplomacyOverviewTable.kt => GlobalPoliticsOverviewTable.kt} (61%) diff --git a/android/Images/OtherIcons/Politics.png b/android/Images/OtherIcons/Politics.png new file mode 100644 index 0000000000000000000000000000000000000000..4d0c5ed196714080a20d113f60bd8f0f7d5cb986 GIT binary patch literal 16963 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 name + status == WonderStatus.Unknown -> status.label + else -> name + } + + fun getStatusColumn() = when { + status != WonderStatus.Known -> status.label + civ == null -> status.label + else -> civ.civName + } + + fun getLocationColumn() = when { + status <= WonderStatus.NotFound -> "" + location == null -> "" + location.isCityCenter() -> location.getCity()!!.name + location.getCity() != null -> "Near [${location.getCity()!!}]" + city != null -> "Somewhere around [$city]" + viewEntireMapForDebug -> location.position.toString() + else -> "Far away" + } + } + + private fun shouldBeDisplayed(wonder: Building, wonderEra: Int) = when { + wonder.hasUnique(UniqueType.HiddenFromCivilopedia) -> false + wonder.hasUnique(UniqueType.HiddenWithoutReligion) && hideReligionItems -> false + wonder.name in startingObsolete -> false + wonder.getMatchingUniques(UniqueType.HiddenWithoutVictoryType) + .any { unique -> + !gameInfo.gameParameters.victoryTypes.contains(unique.params[0]) + } -> false + else -> wonderEra <= viewerEra + } + + /** Do we know about a natural wonder despite not having found it yet? */ + private fun knownFromQuest(name: String): Boolean { + // No, *your* civInfo's QuestManager has no idea about your quests + for (civ in gameInfo.civilizations) { + for (quest in civ.questManager.assignedQuests) { + if (quest.assignee != viewingPlayer.civName) continue + if (quest.questName == QuestName.FindNaturalWonder.value && quest.data1 == name) + return true + } + } + return false + } + + fun collectInfo(): Array { + val collator = UncivGame.Current.settings.getCollatorFromLocale() + + // Maps all World Wonders by name to their era for grouping + val wonderEraMap: Map = + ruleSet.buildings.values.asSequence() + .filter { it.isWonder } + .associate { it.name to (ruleSet.eras[ruleSet.technologies[it.requiredTech]?.era()] ?: viewingPlayer.getEra()) } + + // Maps all World Wonders by their position in sort order to their name + val allWonderMap: Map = + ruleSet.buildings.values.asSequence() + .filter { it.isWonder } + .sortedWith(compareBy { wonderEraMap[it.name]!!.eraNumber }.thenBy(collator) { it.name.tr() }) + .withIndex() + .associate { it.index to it.value.name } + val wonderCount = allWonderMap.size + + // Inverse of the above + val wonderIndexMap: Map = allWonderMap.map { it.value to it.key }.toMap() + + // Maps all Natural Wonders on the map by name to their tile + val allNaturalsMap: Map = + gameInfo.tileMap.values.asSequence() + .filter { it.isNaturalWonder() } + .associateBy { it.naturalWonder!! } + val naturalsCount = allNaturalsMap.size + + // Natural Wonders sort order index to name + val naturalsIndexMap: Map = allNaturalsMap.keys + .sortedWith(compareBy(collator) { it.tr() }) + .withIndex() + .associate { it.index to it.value } + + // Pre-populate result with "Unknown" entries + val wonders = Array(wonderCount + naturalsCount) { index -> + if (index < wonderCount) { + val wonder = ruleSet.buildings[allWonderMap[index]!!]!! + val era = wonderEraMap[wonder.name]!! + val status = if (shouldBeDisplayed(wonder, era.eraNumber)) WonderStatus.Unbuilt else WonderStatus.Hidden + WonderInfo( + allWonderMap[index]!!, CivilopediaCategories.Wonder, + era.name, era.getColor(), status, null, null, null + ) + } else { + WonderInfo( + naturalsIndexMap[index - wonderCount]!!, + CivilopediaCategories.Terrain, + "Natural Wonders", + Color.FOREST, + WonderStatus.Unknown, + null, + null, + null + ) + } + } + + for (city in gameInfo.getCities()) { + for (wonderName in city.cityConstructions.builtBuildings.intersect(wonderIndexMap.keys)) { + val index = wonderIndexMap[wonderName]!! + val status = when { + viewingPlayer == city.civInfo -> WonderStatus.Owned + viewingPlayer.exploredTiles.contains(city.location) -> WonderStatus.Known + else -> WonderStatus.NotFound + } + wonders[index] = WonderInfo( + wonderName, CivilopediaCategories.Wonder, + wonders[index].groupName, wonders[index].groupColor, + status, city.civInfo, city, city.getCenterTile() + ) + } + } + + for ((index, name) in naturalsIndexMap) { + val tile = allNaturalsMap[name]!! + val civ = tile.getOwner() + val status = when { + civ == viewingPlayer -> WonderStatus.Owned + name in viewingPlayer.naturalWonders -> WonderStatus.Known + else -> WonderStatus.NotFound + } + if (status == WonderStatus.NotFound && !knownFromQuest(name)) continue + val city = if (status == WonderStatus.NotFound) null + else tile.getTilesInDistance(5) + .filter { it.isCityCenter() } + .filter { viewingPlayer.knows(it.getOwner()!!) } + .filter { it.position in viewingPlayer.exploredTiles } + .sortedBy { it.aerialDistanceTo(tile) } + .firstOrNull()?.getCity() + wonders[index + wonderCount] = WonderInfo( + name, CivilopediaCategories.Terrain, + "Natural Wonders", Color.FOREST, status, civ, city, tile + ) + } + + return wonders + } +} diff --git a/core/src/com/unciv/logic/civilization/diplomacy/DiplomacyManager.kt b/core/src/com/unciv/logic/civilization/diplomacy/DiplomacyManager.kt index d4c2c9c556..47ff038df4 100644 --- a/core/src/com/unciv/logic/civilization/diplomacy/DiplomacyManager.kt +++ b/core/src/com/unciv/logic/civilization/diplomacy/DiplomacyManager.kt @@ -823,6 +823,7 @@ class DiplomacyManager() : IsPartOfGameInfoSerialization { otherCivDiplomacy().setModifier(DiplomaticModifiers.DeclarationOfFriendship, 35f) setFlag(DiplomacyFlags.DeclarationOfFriendship, 30) otherCivDiplomacy().setFlag(DiplomacyFlags.DeclarationOfFriendship, 30) + if (otherCiv().playerType == PlayerType.Human) otherCiv().addNotification("[${civInfo.civName}] and [$otherCivName] have signed the Declaration of Friendship!", civInfo.civName, NotificationIcon.Diplomacy, otherCivName) diff --git a/core/src/com/unciv/ui/overviewscreen/EmpireOverviewCategories.kt b/core/src/com/unciv/ui/overviewscreen/EmpireOverviewCategories.kt index 055c853b8f..198b48ad58 100644 --- a/core/src/com/unciv/ui/overviewscreen/EmpireOverviewCategories.kt +++ b/core/src/com/unciv/ui/overviewscreen/EmpireOverviewCategories.kt @@ -40,10 +40,10 @@ enum class EmpireOverviewCategories( fun (viewingPlayer: CivilizationInfo, overviewScreen: EmpireOverviewScreen, persistedData: EmpireOverviewTabPersistableData?) = UnitOverviewTab(viewingPlayer, overviewScreen, persistedData), fun (viewingPlayer: CivilizationInfo) = viewingPlayer.getCivUnits().none().toState()), - Diplomacy("OtherIcons/DiplomacyW", 'D', Align.top, + Politics("OtherIcons/Politics", 'P', Align.top, fun (viewingPlayer: CivilizationInfo, overviewScreen: EmpireOverviewScreen, persistedData: EmpireOverviewTabPersistableData?) - = DiplomacyOverviewTab(viewingPlayer, overviewScreen, persistedData), - fun (viewingPlayer: CivilizationInfo) = viewingPlayer.diplomacy.isEmpty().toState()), + = GlobalPoliticsOverviewTable(viewingPlayer, overviewScreen, persistedData), + fun (_: CivilizationInfo) = EmpireOverviewTabState.Normal), Resources("StatIcons/Happiness", 'R', Align.topLeft, fun (viewingPlayer: CivilizationInfo, overviewScreen: EmpireOverviewScreen, persistedData: EmpireOverviewTabPersistableData?) = ResourcesOverviewTab(viewingPlayer, overviewScreen, persistedData), diff --git a/core/src/com/unciv/ui/overviewscreen/DiplomacyOverviewTable.kt b/core/src/com/unciv/ui/overviewscreen/GlobalPoliticsOverviewTable.kt similarity index 61% rename from core/src/com/unciv/ui/overviewscreen/DiplomacyOverviewTable.kt rename to core/src/com/unciv/ui/overviewscreen/GlobalPoliticsOverviewTable.kt index 561ef952d8..d6ad8f959f 100644 --- a/core/src/com/unciv/ui/overviewscreen/DiplomacyOverviewTable.kt +++ b/core/src/com/unciv/ui/overviewscreen/GlobalPoliticsOverviewTable.kt @@ -6,13 +6,15 @@ import com.badlogic.gdx.scenes.scene2d.Group import com.badlogic.gdx.scenes.scene2d.Touchable import com.badlogic.gdx.scenes.scene2d.ui.Table import com.badlogic.gdx.scenes.scene2d.ui.TextButton -import com.badlogic.gdx.scenes.scene2d.ui.TextButton.TextButtonStyle import com.badlogic.gdx.utils.Align import com.unciv.Constants import com.unciv.UncivGame import com.unciv.logic.HexMath import com.unciv.logic.civilization.CivilizationInfo +import com.unciv.logic.civilization.WonderInfo +import com.unciv.logic.civilization.diplomacy.DiplomacyFlags import com.unciv.logic.civilization.diplomacy.DiplomaticStatus +import com.unciv.logic.civilization.diplomacy.RelationshipLevel import com.unciv.ui.images.ImageGetter import com.unciv.ui.trade.DiplomacyScreen import com.unciv.ui.utils.AutoScrollPane @@ -20,17 +22,19 @@ import com.unciv.ui.utils.BaseScreen import com.unciv.ui.utils.UncivTooltip.Companion.addTooltip import com.unciv.ui.utils.extensions.addBorder import com.unciv.ui.utils.extensions.addSeparator +import com.unciv.ui.utils.extensions.addSeparatorVertical import com.unciv.ui.utils.extensions.center import com.unciv.ui.utils.extensions.onClick import com.unciv.ui.utils.extensions.toLabel import com.unciv.ui.utils.extensions.toTextButton import kotlin.math.roundToInt -class DiplomacyOverviewTab ( +class GlobalPoliticsOverviewTable ( viewingPlayer: CivilizationInfo, overviewScreen: EmpireOverviewScreen, persistedData: EmpireOverviewTabPersistableData? = null ) : EmpireOverviewTab(viewingPlayer, overviewScreen) { + class DiplomacyTabPersistableData( var includeCityStates: Boolean = false ) : EmpireOverviewTabPersistableData() { @@ -44,19 +48,6 @@ class DiplomacyOverviewTab ( defaults().pad(5f) background = ImageGetter.getBackground(Color.BLACK) } - val toggleCityStatesButton: TextButton = Constants.cityStates.toTextButton().apply { - onClick { - persistableData.includeCityStates = !persistableData.includeCityStates - update() - } - } - private val civTableScroll = AutoScrollPane(civTable).apply { - setOverscroll(false, false) - } - private val floatingTable = Table().apply { - add(toggleCityStatesButton).row() - add(civTableScroll.addBorder(2f, Color.WHITE)).pad(10f) - } // Reusable sequences for the Civilizations to display private var undefeatedCivs = sequenceOf() @@ -66,14 +57,178 @@ class DiplomacyOverviewTab ( private var showDiplomacyGroup = false private var portraitMode = false + init { - update() + updatePoliticsTable() + } + + private fun updatePoliticsTable() { + clear() + getFixedContent().clear() + + val diagramButton = TextButton("Show diagram", skin) + diagramButton.onClick { updateDiagram() } + + add() + addSeparatorVertical(Color.GRAY) + add("Civilization Info".toLabel()) + addSeparatorVertical(Color.GRAY) + add("Social policies".toLabel()) + addSeparatorVertical(Color.GRAY) + add("Wonders".toLabel()) + addSeparatorVertical(Color.GRAY) + add("Relations".toLabel()) + add(diagramButton).pad(10f) + row() + addSeparator(Color.GRAY) + + createGlobalPoliticsTable() + } + + private fun createGlobalPoliticsTable() { + val civilizations = mutableListOf() + civilizations.add(viewingPlayer) + civilizations.addAll(viewingPlayer.getKnownCivs()) + civilizations.removeAll(civilizations.filter { it.isBarbarian() || it.isCityState() || it.isSpectator() }) + for (civ in civilizations) { + // civ image + add(ImageGetter.getNationIndicator(civ.nation, 100f)).pad(20f) + + addSeparatorVertical(Color.GRAY) + + // info about civ + add(getCivInfoTable(civ)).pad(20f) + + addSeparatorVertical(Color.GRAY) + + // policies + add(getPoliciesTable(civ)).pad(20f) + + addSeparatorVertical(Color.GRAY) + + // wonders + add(getWondersOfCivTable(civ)).pad(20f) + + addSeparatorVertical(Color.GRAY) + + //politics + add(getPoliticsOfCivTable(civ)).pad(20f) + + if (civilizations.indexOf(civ) != civilizations.lastIndex) + addSeparator(Color.GRAY) + } + } + + private fun getCivInfoTable(civ: CivilizationInfo): Table { + val civInfoTable = Table(skin) + val leaderName = civ.getLeaderDisplayName().removeSuffix(" of " + civ.civName) + civInfoTable.add(leaderName.toLabel(fontSize = 30)).row() + civInfoTable.add(civ.civName.toLabel()).row() + civInfoTable.add(civ.tech.era.name.toLabel()).row() + return civInfoTable + } + + private fun getPoliciesTable(civ: CivilizationInfo): Table { + val policiesTable = Table(skin) + for (policy in civ.policies.branchCompletionMap) { + if (policy.value != 0) + policiesTable.add("${policy.key.name}: ${policy.value}".toLabel()).row() + } + return policiesTable + } + + private fun getWondersOfCivTable(civ: CivilizationInfo): Table { + val wonderTable = Table(skin) + val wonderInfo = WonderInfo() + val allWorldWonders = wonderInfo.collectInfo() + + for (wonder in allWorldWonders) { + if (wonder.civ?.civName == civ.civName) { + val wonderName = wonder.name.toLabel() + if (wonder.location != null) { + wonderName.onClick { + val worldScreen = UncivGame.Current.resetToWorldScreen() + worldScreen.mapHolder.setCenterPosition(wonder.location.position) + } + } + wonderTable.add(wonderName).row() + } + } + + return wonderTable + } + + private fun getPoliticsOfCivTable(civ: CivilizationInfo): Table { + val politicsTable = Table(skin) + + // wars + for (otherCiv in civ.getKnownCivs()) { + if(civ.diplomacy[otherCiv.civName]?.hasFlag(DiplomacyFlags.DeclaredWar) == true) { + val warText = "At war with ${otherCiv.civName}".toLabel() + warText.color = Color.RED + politicsTable.add(warText).row() + } + } + politicsTable.row() + + // declaration of friendships + for (otherCiv in civ.getKnownCivs()) { + if(civ.diplomacy[otherCiv.civName]?.hasFlag(DiplomacyFlags.DeclarationOfFriendship) == true) { + val friendtext = "Friends with ${otherCiv.civName} ".toLabel() + friendtext.color = Color.GREEN + val turnsLeftText = "({${civ.diplomacy[otherCiv.civName]?.getFlag(DiplomacyFlags.DeclarationOfFriendship)} Turns Left})".toLabel() + politicsTable.add(friendtext) + politicsTable.add(turnsLeftText).row() + } + } + politicsTable.row() + + // denounced civs + for (otherCiv in civ.getKnownCivs()) { + if(civ.diplomacy[otherCiv.civName]?.hasFlag(DiplomacyFlags.Denunciation) == true) { + val denouncedText = "Denounced ${otherCiv.civName} ".toLabel() + denouncedText.color = Color.RED + val turnsLeftText = "({${civ.diplomacy[otherCiv.civName]?.getFlag(DiplomacyFlags.Denunciation)} Turns Left})".toLabel() + politicsTable.add(denouncedText) + politicsTable.add(turnsLeftText).row() + } + } + politicsTable.row() + + //allied CS + for (cityState in gameInfo.getAliveCityStates()) { + if (cityState.diplomacy[civ.civName]?.relationshipLevel() == RelationshipLevel.Ally) { + val alliedText = "Allied with ${cityState.civName}".toLabel() + alliedText.color = Color.GREEN + politicsTable.add(alliedText).row() + } + } + + return politicsTable } override fun getFixedContent() = fixedContent // Refresh content and determine landscape/portrait layout - private fun update() { + private fun updateDiagram() { + val politicsButton = TextButton("Show global politics", skin).apply { onClick { updatePoliticsTable() } } + + val toggleCityStatesButton: TextButton = Constants.cityStates.toTextButton().apply { + onClick { + persistableData.includeCityStates = !persistableData.includeCityStates + updateDiagram() + } + } + + val civTableScroll = AutoScrollPane(civTable).apply { + setOverscroll(false, false) + } + val floatingTable = Table().apply { + add(toggleCityStatesButton).pad(10f).row() + add(politicsButton).row() + add(civTableScroll.addBorder(2f, Color.WHITE)).pad(10f) + } + relevantCivsCount = gameInfo.civilizations.count { !it.isSpectator() && !it.isBarbarian() && (persistableData.includeCityStates || !it.isCityState()) } @@ -111,9 +266,9 @@ class DiplomacyOverviewTab ( table.add(floatingTable) toggleCityStatesButton.style = if (persistableData.includeCityStates) { - BaseScreen.skin.get("negative", TextButtonStyle::class.java) + BaseScreen.skin.get("negative", TextButton.TextButtonStyle::class.java) } else { - BaseScreen.skin.get("positive", TextButtonStyle::class.java) + BaseScreen.skin.get("positive", TextButton.TextButtonStyle::class.java) } civTableScroll.setScrollingDisabled(portraitMode, portraitMode) } @@ -252,7 +407,7 @@ class DiplomacyOverviewTab ( width = 2f) statusLine.color = if (diplomacy.diplomaticStatus == DiplomaticStatus.War) Color.RED - else diplomacy.relationshipLevel().color + else diplomacy.relationshipLevel().color if (!civLines.containsKey(civ.civName)) civLines[civ.civName] = mutableSetOf() civLines[civ.civName]!!.add(statusLine) diff --git a/core/src/com/unciv/ui/overviewscreen/WonderOverviewTable.kt b/core/src/com/unciv/ui/overviewscreen/WonderOverviewTable.kt index 1eb7988c51..a4ec0cca79 100644 --- a/core/src/com/unciv/ui/overviewscreen/WonderOverviewTable.kt +++ b/core/src/com/unciv/ui/overviewscreen/WonderOverviewTable.kt @@ -1,18 +1,10 @@ package com.unciv.ui.overviewscreen -import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.scenes.scene2d.ui.Table import com.badlogic.gdx.utils.Align import com.unciv.UncivGame -import com.unciv.logic.city.CityInfo import com.unciv.logic.civilization.CivilizationInfo -import com.unciv.logic.map.TileInfo -import com.unciv.models.ruleset.Building -import com.unciv.models.ruleset.Era -import com.unciv.models.ruleset.QuestName -import com.unciv.models.ruleset.unique.UniqueType -import com.unciv.models.translations.tr -import com.unciv.ui.civilopedia.CivilopediaCategories +import com.unciv.logic.civilization.WonderInfo import com.unciv.ui.civilopedia.CivilopediaScreen import com.unciv.ui.images.ImageGetter import com.unciv.ui.utils.extensions.onClick @@ -24,58 +16,8 @@ class WonderOverviewTab( ) : EmpireOverviewTab(viewingPlayer, overviewScreen) { val ruleSet = gameInfo.ruleSet - private val hideReligionItems = !gameInfo.isReligionEnabled() - private val viewerEra = viewingPlayer.getEraNumber() - private val startingObsolete = ruleSet.eras[gameInfo.gameParameters.startingEra]!!.startingObsoleteWonders - - private enum class WonderStatus(val label: String) { - Hidden(""), - Unknown("Unknown"), - Unbuilt("Not built"), - NotFound("Not found"), - Known("Known"), - Owned("Owned") - } - - private class WonderInfo ( - val name: String, - val category: CivilopediaCategories, - val groupName: String, - val groupColor: Color, - val status: WonderStatus, - val civ: CivilizationInfo?, - val city: CityInfo?, - val location: TileInfo? - ) { - val viewEntireMapForDebug = UncivGame.Current.viewEntireMapForDebug - - fun getImage() = if (status == WonderStatus.Unknown && !viewEntireMapForDebug) null - else category.getImage?.invoke(name, if (category == CivilopediaCategories.Terrain) 50f else 45f) - - fun getNameColumn() = when { - viewEntireMapForDebug -> name - status == WonderStatus.Unknown -> status.label - else -> name - } - - fun getStatusColumn() = when { - status != WonderStatus.Known -> status.label - civ == null -> status.label - else -> civ.civName - } - - fun getLocationColumn() = when { - status <= WonderStatus.NotFound -> "" - location == null -> "" - location.isCityCenter() -> location.getCity()!!.name - location.getCity() != null -> "Near [${location.getCity()!!}]" - city != null -> "Somewhere around [$city]" - viewEntireMapForDebug -> location.position.toString() - else -> "Far away" - } - } - - private val wonders: Array = collectInfo() + val wonderInfo = WonderInfo() + private val wonders: Array = wonderInfo.collectInfo() private val fixedContent = Table() override fun getFixedContent() = fixedContent @@ -101,120 +43,11 @@ class WonderOverviewTab( equalizeColumns(fixedContent, this) } - private fun shouldBeDisplayed(wonder: Building, wonderEra: Int) = when { - wonder.hasUnique(UniqueType.HiddenFromCivilopedia) -> false - wonder.hasUnique(UniqueType.HiddenWithoutReligion) && hideReligionItems -> false - wonder.name in startingObsolete -> false - wonder.getMatchingUniques(UniqueType.HiddenWithoutVictoryType) - .any { unique -> - !gameInfo.gameParameters.victoryTypes.contains(unique.params[0]) - } -> false - else -> wonderEra <= viewerEra - } - - /** Do we know about a natural wonder despite not having found it yet? */ - private fun knownFromQuest(name: String): Boolean { - // No, *your* civInfo's QuestManager has no idea about your quests - for (civ in gameInfo.civilizations) { - for (quest in civ.questManager.assignedQuests) { - if (quest.assignee != viewingPlayer.civName) continue - if (quest.questName == QuestName.FindNaturalWonder.value && quest.data1 == name) - return true - } - } - return false - } - - private fun collectInfo(): Array { - val collator = UncivGame.Current.settings.getCollatorFromLocale() - - // Maps all World Wonders by name to their era for grouping - val wonderEraMap: Map = - ruleSet.buildings.values.asSequence() - .filter { it.isWonder } - .associate { it.name to (ruleSet.eras[ruleSet.technologies[it.requiredTech]?.era()] ?: viewingPlayer.getEra()) } - - // Maps all World Wonders by their position in sort order to their name - val allWonderMap: Map = - ruleSet.buildings.values.asSequence() - .filter { it.isWonder } - .sortedWith(compareBy { wonderEraMap[it.name]!!.eraNumber }.thenBy(collator) { it.name.tr() }) - .withIndex() - .associate { it.index to it.value.name } - val wonderCount = allWonderMap.size - - // Inverse of the above - val wonderIndexMap: Map = allWonderMap.map { it.value to it.key }.toMap() - - // Maps all Natural Wonders on the map by name to their tile - val allNaturalsMap: Map = - gameInfo.tileMap.values.asSequence() - .filter { it.isNaturalWonder() } - .associateBy { it.naturalWonder!! } - val naturalsCount = allNaturalsMap.size - - // Natural Wonders sort order index to name - val naturalsIndexMap: Map = allNaturalsMap.keys - .sortedWith(compareBy(collator) { it.tr() }) - .withIndex() - .associate { it.index to it.value } - - // Pre-populate result with "Unknown" entries - val wonders = Array(wonderCount + naturalsCount) { index -> - if (index < wonderCount) { - val wonder = ruleSet.buildings[allWonderMap[index]!!]!! - val era = wonderEraMap[wonder.name]!! - val status = if (shouldBeDisplayed(wonder, era.eraNumber)) WonderStatus.Unbuilt else WonderStatus.Hidden - WonderInfo(allWonderMap[index]!!, CivilopediaCategories.Wonder, - era.name, era.getColor(), status, null, null, null) - } else { - WonderInfo(naturalsIndexMap[index - wonderCount]!!, CivilopediaCategories.Terrain, - "Natural Wonders", Color.FOREST, WonderStatus.Unknown, null, null, null) - } - } - - for (city in gameInfo.getCities()) { - for (wonderName in city.cityConstructions.builtBuildings.intersect(wonderIndexMap.keys)) { - val index = wonderIndexMap[wonderName]!! - val status = when { - viewingPlayer == city.civInfo -> WonderStatus.Owned - viewingPlayer.exploredTiles.contains(city.location) -> WonderStatus.Known - else -> WonderStatus.NotFound - } - wonders[index] = WonderInfo(wonderName, CivilopediaCategories.Wonder, - wonders[index].groupName, wonders[index].groupColor, - status, city.civInfo, city, city.getCenterTile()) - } - } - - for ((index, name) in naturalsIndexMap) { - val tile = allNaturalsMap[name]!! - val civ = tile.getOwner() - val status = when { - civ == viewingPlayer -> WonderStatus.Owned - name in viewingPlayer.naturalWonders -> WonderStatus.Known - else -> WonderStatus.NotFound - } - if (status == WonderStatus.NotFound && !knownFromQuest(name)) continue - val city = if (status == WonderStatus.NotFound) null - else tile.getTilesInDistance(5) - .filter { it.isCityCenter() } - .filter { viewingPlayer.knows(it.getOwner()!!) } - .filter { it.position in viewingPlayer.exploredTiles } - .sortedBy { it.aerialDistanceTo(tile) } - .firstOrNull()?.getCity() - wonders[index + wonderCount] = WonderInfo(name, CivilopediaCategories.Terrain, - "Natural Wonders", Color.FOREST, status, civ, city, tile) - } - - return wonders - } - fun createGrid() { var lastGroup = "" for (wonder in wonders) { - if (wonder.status == WonderStatus.Hidden) continue + if (wonder.status == WonderInfo.WonderStatus.Hidden) continue if (wonder.groupName != lastGroup) { lastGroup = wonder.groupName val groupRow = Table().apply { diff --git a/docs/Credits.md b/docs/Credits.md index a7b91a9018..8441f8f8e5 100644 --- a/docs/Credits.md +++ b/docs/Credits.md @@ -746,6 +746,7 @@ Unless otherwise specified, all the following are from [the Noun Project](https: - [turn right](https://thenounproject.com/icon/turn-right-1920867/) by Alice Design for Resource Overview - [Tyrannosaurus Rex](https://thenounproject.com/icon/tyrannosaurus-rex-4130976/) by Amethyst Studio for Civilopedia Eras header - [Timer](https://www.flaticon.com/free-icons/timer) created by Gregor Cresnar Premium - Flaticon +- [Political Science](https://www.flaticon.com/premium-icon/political-science_5403775) created by Hilmy Abiyyu A. - Flaticon - [Question](https://thenounproject.com/icon/question-1157126/) created by Aneeque Ahmed for Question Icon ### Main menu