mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-13 09:18:43 +07:00
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
This commit is contained in:
BIN
android/Images/OtherIcons/Politics.png
Normal file
BIN
android/Images/OtherIcons/Politics.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
@ -1219,6 +1219,15 @@ Number of your cities celebrating\n'We Love The King Day' thanks\nto access to t
|
|||||||
WLTK demand =
|
WLTK demand =
|
||||||
WLTK- =
|
WLTK- =
|
||||||
Number of your cities\ndemanding this resource for\n'We Love The King Day' =
|
Number of your cities\ndemanding this resource for\n'We Love The King Day' =
|
||||||
|
Show global politics =
|
||||||
|
Show diagram =
|
||||||
|
At war with [enemy] =
|
||||||
|
Friends with [civName] =
|
||||||
|
[numberOfTurns] Turns Left =
|
||||||
|
Denounced [otherCiv] =
|
||||||
|
Allied with [civName] =
|
||||||
|
Civilization Info =
|
||||||
|
Relations =
|
||||||
Trade request =
|
Trade request =
|
||||||
|
|
||||||
# Victory
|
# Victory
|
||||||
|
@ -44,6 +44,7 @@ import com.unciv.ui.utils.extensions.toPercent
|
|||||||
import com.unciv.ui.utils.extensions.withItem
|
import com.unciv.ui.utils.extensions.withItem
|
||||||
import com.unciv.ui.victoryscreen.RankingType
|
import com.unciv.ui.victoryscreen.RankingType
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import kotlin.collections.HashMap
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
191
core/src/com/unciv/logic/civilization/WonderInfo.kt
Normal file
191
core/src/com/unciv/logic/civilization/WonderInfo.kt
Normal file
@ -0,0 +1,191 @@
|
|||||||
|
package com.unciv.logic.civilization
|
||||||
|
|
||||||
|
import com.badlogic.gdx.graphics.Color
|
||||||
|
import com.unciv.UncivGame
|
||||||
|
import com.unciv.logic.city.CityInfo
|
||||||
|
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
|
||||||
|
|
||||||
|
class WonderInfo {
|
||||||
|
val gameInfo = UncivGame.Current.gameInfo!!
|
||||||
|
val viewingPlayer = gameInfo.getCurrentPlayerCivilization()
|
||||||
|
val ruleSet = gameInfo.ruleSet
|
||||||
|
private val hideReligionItems = !gameInfo.isReligionEnabled()
|
||||||
|
private val viewerEra = viewingPlayer.getEraNumber()
|
||||||
|
private val startingObsolete = ruleSet.eras[gameInfo.gameParameters.startingEra]!!.startingObsoleteWonders
|
||||||
|
|
||||||
|
enum class WonderStatus(val label: String) {
|
||||||
|
Hidden(""),
|
||||||
|
Unknown("Unknown"),
|
||||||
|
Unbuilt("Not built"),
|
||||||
|
NotFound("Not found"),
|
||||||
|
Known("Known"),
|
||||||
|
Owned("Owned")
|
||||||
|
}
|
||||||
|
|
||||||
|
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 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<WonderInfo> {
|
||||||
|
val collator = UncivGame.Current.settings.getCollatorFromLocale()
|
||||||
|
|
||||||
|
// Maps all World Wonders by name to their era for grouping
|
||||||
|
val wonderEraMap: Map<String, Era> =
|
||||||
|
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<Int, String> =
|
||||||
|
ruleSet.buildings.values.asSequence()
|
||||||
|
.filter { it.isWonder }
|
||||||
|
.sortedWith(compareBy<Building> { 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<String, Int> = allWonderMap.map { it.value to it.key }.toMap()
|
||||||
|
|
||||||
|
// Maps all Natural Wonders on the map by name to their tile
|
||||||
|
val allNaturalsMap: Map<String, TileInfo> =
|
||||||
|
gameInfo.tileMap.values.asSequence()
|
||||||
|
.filter { it.isNaturalWonder() }
|
||||||
|
.associateBy { it.naturalWonder!! }
|
||||||
|
val naturalsCount = allNaturalsMap.size
|
||||||
|
|
||||||
|
// Natural Wonders sort order index to name
|
||||||
|
val naturalsIndexMap: Map<Int, String> = 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
|
||||||
|
}
|
||||||
|
}
|
@ -823,6 +823,7 @@ class DiplomacyManager() : IsPartOfGameInfoSerialization {
|
|||||||
otherCivDiplomacy().setModifier(DiplomaticModifiers.DeclarationOfFriendship, 35f)
|
otherCivDiplomacy().setModifier(DiplomaticModifiers.DeclarationOfFriendship, 35f)
|
||||||
setFlag(DiplomacyFlags.DeclarationOfFriendship, 30)
|
setFlag(DiplomacyFlags.DeclarationOfFriendship, 30)
|
||||||
otherCivDiplomacy().setFlag(DiplomacyFlags.DeclarationOfFriendship, 30)
|
otherCivDiplomacy().setFlag(DiplomacyFlags.DeclarationOfFriendship, 30)
|
||||||
|
|
||||||
if (otherCiv().playerType == PlayerType.Human)
|
if (otherCiv().playerType == PlayerType.Human)
|
||||||
otherCiv().addNotification("[${civInfo.civName}] and [$otherCivName] have signed the Declaration of Friendship!",
|
otherCiv().addNotification("[${civInfo.civName}] and [$otherCivName] have signed the Declaration of Friendship!",
|
||||||
civInfo.civName, NotificationIcon.Diplomacy, otherCivName)
|
civInfo.civName, NotificationIcon.Diplomacy, otherCivName)
|
||||||
|
@ -40,10 +40,10 @@ enum class EmpireOverviewCategories(
|
|||||||
fun (viewingPlayer: CivilizationInfo, overviewScreen: EmpireOverviewScreen, persistedData: EmpireOverviewTabPersistableData?)
|
fun (viewingPlayer: CivilizationInfo, overviewScreen: EmpireOverviewScreen, persistedData: EmpireOverviewTabPersistableData?)
|
||||||
= UnitOverviewTab(viewingPlayer, overviewScreen, persistedData),
|
= UnitOverviewTab(viewingPlayer, overviewScreen, persistedData),
|
||||||
fun (viewingPlayer: CivilizationInfo) = viewingPlayer.getCivUnits().none().toState()),
|
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?)
|
fun (viewingPlayer: CivilizationInfo, overviewScreen: EmpireOverviewScreen, persistedData: EmpireOverviewTabPersistableData?)
|
||||||
= DiplomacyOverviewTab(viewingPlayer, overviewScreen, persistedData),
|
= GlobalPoliticsOverviewTable(viewingPlayer, overviewScreen, persistedData),
|
||||||
fun (viewingPlayer: CivilizationInfo) = viewingPlayer.diplomacy.isEmpty().toState()),
|
fun (_: CivilizationInfo) = EmpireOverviewTabState.Normal),
|
||||||
Resources("StatIcons/Happiness", 'R', Align.topLeft,
|
Resources("StatIcons/Happiness", 'R', Align.topLeft,
|
||||||
fun (viewingPlayer: CivilizationInfo, overviewScreen: EmpireOverviewScreen, persistedData: EmpireOverviewTabPersistableData?)
|
fun (viewingPlayer: CivilizationInfo, overviewScreen: EmpireOverviewScreen, persistedData: EmpireOverviewTabPersistableData?)
|
||||||
= ResourcesOverviewTab(viewingPlayer, overviewScreen, persistedData),
|
= ResourcesOverviewTab(viewingPlayer, overviewScreen, persistedData),
|
||||||
|
@ -6,13 +6,15 @@ import com.badlogic.gdx.scenes.scene2d.Group
|
|||||||
import com.badlogic.gdx.scenes.scene2d.Touchable
|
import com.badlogic.gdx.scenes.scene2d.Touchable
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.TextButton
|
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.badlogic.gdx.utils.Align
|
||||||
import com.unciv.Constants
|
import com.unciv.Constants
|
||||||
import com.unciv.UncivGame
|
import com.unciv.UncivGame
|
||||||
import com.unciv.logic.HexMath
|
import com.unciv.logic.HexMath
|
||||||
import com.unciv.logic.civilization.CivilizationInfo
|
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.DiplomaticStatus
|
||||||
|
import com.unciv.logic.civilization.diplomacy.RelationshipLevel
|
||||||
import com.unciv.ui.images.ImageGetter
|
import com.unciv.ui.images.ImageGetter
|
||||||
import com.unciv.ui.trade.DiplomacyScreen
|
import com.unciv.ui.trade.DiplomacyScreen
|
||||||
import com.unciv.ui.utils.AutoScrollPane
|
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.UncivTooltip.Companion.addTooltip
|
||||||
import com.unciv.ui.utils.extensions.addBorder
|
import com.unciv.ui.utils.extensions.addBorder
|
||||||
import com.unciv.ui.utils.extensions.addSeparator
|
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.center
|
||||||
import com.unciv.ui.utils.extensions.onClick
|
import com.unciv.ui.utils.extensions.onClick
|
||||||
import com.unciv.ui.utils.extensions.toLabel
|
import com.unciv.ui.utils.extensions.toLabel
|
||||||
import com.unciv.ui.utils.extensions.toTextButton
|
import com.unciv.ui.utils.extensions.toTextButton
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
class DiplomacyOverviewTab (
|
class GlobalPoliticsOverviewTable (
|
||||||
viewingPlayer: CivilizationInfo,
|
viewingPlayer: CivilizationInfo,
|
||||||
overviewScreen: EmpireOverviewScreen,
|
overviewScreen: EmpireOverviewScreen,
|
||||||
persistedData: EmpireOverviewTabPersistableData? = null
|
persistedData: EmpireOverviewTabPersistableData? = null
|
||||||
) : EmpireOverviewTab(viewingPlayer, overviewScreen) {
|
) : EmpireOverviewTab(viewingPlayer, overviewScreen) {
|
||||||
|
|
||||||
class DiplomacyTabPersistableData(
|
class DiplomacyTabPersistableData(
|
||||||
var includeCityStates: Boolean = false
|
var includeCityStates: Boolean = false
|
||||||
) : EmpireOverviewTabPersistableData() {
|
) : EmpireOverviewTabPersistableData() {
|
||||||
@ -44,19 +48,6 @@ class DiplomacyOverviewTab (
|
|||||||
defaults().pad(5f)
|
defaults().pad(5f)
|
||||||
background = ImageGetter.getBackground(Color.BLACK)
|
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
|
// Reusable sequences for the Civilizations to display
|
||||||
private var undefeatedCivs = sequenceOf<CivilizationInfo>()
|
private var undefeatedCivs = sequenceOf<CivilizationInfo>()
|
||||||
@ -66,14 +57,178 @@ class DiplomacyOverviewTab (
|
|||||||
private var showDiplomacyGroup = false
|
private var showDiplomacyGroup = false
|
||||||
private var portraitMode = false
|
private var portraitMode = false
|
||||||
|
|
||||||
|
|
||||||
init {
|
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<CivilizationInfo>()
|
||||||
|
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
|
override fun getFixedContent() = fixedContent
|
||||||
|
|
||||||
// Refresh content and determine landscape/portrait layout
|
// 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 {
|
relevantCivsCount = gameInfo.civilizations.count {
|
||||||
!it.isSpectator() && !it.isBarbarian() && (persistableData.includeCityStates || !it.isCityState())
|
!it.isSpectator() && !it.isBarbarian() && (persistableData.includeCityStates || !it.isCityState())
|
||||||
}
|
}
|
||||||
@ -111,9 +266,9 @@ class DiplomacyOverviewTab (
|
|||||||
|
|
||||||
table.add(floatingTable)
|
table.add(floatingTable)
|
||||||
toggleCityStatesButton.style = if (persistableData.includeCityStates) {
|
toggleCityStatesButton.style = if (persistableData.includeCityStates) {
|
||||||
BaseScreen.skin.get("negative", TextButtonStyle::class.java)
|
BaseScreen.skin.get("negative", TextButton.TextButtonStyle::class.java)
|
||||||
} else {
|
} else {
|
||||||
BaseScreen.skin.get("positive", TextButtonStyle::class.java)
|
BaseScreen.skin.get("positive", TextButton.TextButtonStyle::class.java)
|
||||||
}
|
}
|
||||||
civTableScroll.setScrollingDisabled(portraitMode, portraitMode)
|
civTableScroll.setScrollingDisabled(portraitMode, portraitMode)
|
||||||
}
|
}
|
||||||
@ -252,7 +407,7 @@ class DiplomacyOverviewTab (
|
|||||||
width = 2f)
|
width = 2f)
|
||||||
|
|
||||||
statusLine.color = if (diplomacy.diplomaticStatus == DiplomaticStatus.War) Color.RED
|
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()
|
if (!civLines.containsKey(civ.civName)) civLines[civ.civName] = mutableSetOf()
|
||||||
civLines[civ.civName]!!.add(statusLine)
|
civLines[civ.civName]!!.add(statusLine)
|
@ -1,18 +1,10 @@
|
|||||||
package com.unciv.ui.overviewscreen
|
package com.unciv.ui.overviewscreen
|
||||||
|
|
||||||
import com.badlogic.gdx.graphics.Color
|
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||||
import com.badlogic.gdx.utils.Align
|
import com.badlogic.gdx.utils.Align
|
||||||
import com.unciv.UncivGame
|
import com.unciv.UncivGame
|
||||||
import com.unciv.logic.city.CityInfo
|
|
||||||
import com.unciv.logic.civilization.CivilizationInfo
|
import com.unciv.logic.civilization.CivilizationInfo
|
||||||
import com.unciv.logic.map.TileInfo
|
import com.unciv.logic.civilization.WonderInfo
|
||||||
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.ui.civilopedia.CivilopediaScreen
|
import com.unciv.ui.civilopedia.CivilopediaScreen
|
||||||
import com.unciv.ui.images.ImageGetter
|
import com.unciv.ui.images.ImageGetter
|
||||||
import com.unciv.ui.utils.extensions.onClick
|
import com.unciv.ui.utils.extensions.onClick
|
||||||
@ -24,58 +16,8 @@ class WonderOverviewTab(
|
|||||||
) : EmpireOverviewTab(viewingPlayer, overviewScreen) {
|
) : EmpireOverviewTab(viewingPlayer, overviewScreen) {
|
||||||
val ruleSet = gameInfo.ruleSet
|
val ruleSet = gameInfo.ruleSet
|
||||||
|
|
||||||
private val hideReligionItems = !gameInfo.isReligionEnabled()
|
val wonderInfo = WonderInfo()
|
||||||
private val viewerEra = viewingPlayer.getEraNumber()
|
private val wonders: Array<WonderInfo.WonderInfo> = wonderInfo.collectInfo()
|
||||||
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<WonderInfo> = collectInfo()
|
|
||||||
|
|
||||||
private val fixedContent = Table()
|
private val fixedContent = Table()
|
||||||
override fun getFixedContent() = fixedContent
|
override fun getFixedContent() = fixedContent
|
||||||
@ -101,120 +43,11 @@ class WonderOverviewTab(
|
|||||||
equalizeColumns(fixedContent, this)
|
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<WonderInfo> {
|
|
||||||
val collator = UncivGame.Current.settings.getCollatorFromLocale()
|
|
||||||
|
|
||||||
// Maps all World Wonders by name to their era for grouping
|
|
||||||
val wonderEraMap: Map<String, Era> =
|
|
||||||
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<Int, String> =
|
|
||||||
ruleSet.buildings.values.asSequence()
|
|
||||||
.filter { it.isWonder }
|
|
||||||
.sortedWith(compareBy<Building> { 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<String, Int> = allWonderMap.map { it.value to it.key }.toMap()
|
|
||||||
|
|
||||||
// Maps all Natural Wonders on the map by name to their tile
|
|
||||||
val allNaturalsMap: Map<String, TileInfo> =
|
|
||||||
gameInfo.tileMap.values.asSequence()
|
|
||||||
.filter { it.isNaturalWonder() }
|
|
||||||
.associateBy { it.naturalWonder!! }
|
|
||||||
val naturalsCount = allNaturalsMap.size
|
|
||||||
|
|
||||||
// Natural Wonders sort order index to name
|
|
||||||
val naturalsIndexMap: Map<Int, String> = 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() {
|
fun createGrid() {
|
||||||
var lastGroup = ""
|
var lastGroup = ""
|
||||||
|
|
||||||
for (wonder in wonders) {
|
for (wonder in wonders) {
|
||||||
if (wonder.status == WonderStatus.Hidden) continue
|
if (wonder.status == WonderInfo.WonderStatus.Hidden) continue
|
||||||
if (wonder.groupName != lastGroup) {
|
if (wonder.groupName != lastGroup) {
|
||||||
lastGroup = wonder.groupName
|
lastGroup = wonder.groupName
|
||||||
val groupRow = Table().apply {
|
val groupRow = Table().apply {
|
||||||
|
@ -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
|
- [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
|
- [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
|
- [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
|
- [Question](https://thenounproject.com/icon/question-1157126/) created by Aneeque Ahmed for Question Icon
|
||||||
|
|
||||||
### Main menu
|
### Main menu
|
||||||
|
Reference in New Issue
Block a user