Empire Overview Diplomacy (#6375)

* Empire Overview Diplomacy: Preparations

* Empire Overview Diplomacy: DiplomacyScreen linkable

* Empire Overview Diplomacy: Overhaul

* Empire Overview Diplomacy: List always begins a new row between major and minor civs
This commit is contained in:
SomeTroglodyte
2022-03-21 20:05:30 +01:00
committed by GitHub
parent 984c4d9b2d
commit f6a989f1fc
7 changed files with 258 additions and 182 deletions

View File

@ -283,15 +283,15 @@ class GameInfo {
}
)
}
private fun checkForTimeVictory() {
if (turns != gameParameters.maxTurns || !gameParameters.victoryTypes.contains(VictoryType.Time)) return
val winningCiv = civilizations
.filter { it.isMajorCiv() && !it.isSpectator() && !it.isBarbarian() }
.maxByOrNull { it.calculateScoreBreakdown().values.sum() }
.maxByOrNull { it.calculateTotalScore() }
?: return // Are there no civs left?
winningCiv.victoryManager.hasWonTimeVictory = true
}
@ -322,19 +322,18 @@ class GameInfo {
// Calling with `maxDistance = 0` removes distance limitation.
data class CityTileAndDistance(val city: CityInfo, val tile: TileInfo, val distance: Int)
var exploredRevealTiles:Sequence<TileInfo>
if (ruleSet.tileResources[resourceName]!!.hasUnique(UniqueType.CityStateOnlyResource)) {
// Look for matching mercantile CS centers
exploredRevealTiles = getAliveCityStates()
.asSequence()
.filter { it.cityStateResource == resourceName }
.map { it.getCapital().getCenterTile() }
} else {
exploredRevealTiles = tileMap.values
.asSequence()
.filter { it.resource == resourceName }
}
val exploredRevealTiles: Sequence<TileInfo> =
if (ruleSet.tileResources[resourceName]!!.hasUnique(UniqueType.CityStateOnlyResource)) {
// Look for matching mercantile CS centers
getAliveCityStates()
.asSequence()
.filter { it.cityStateResource == resourceName }
.map { it.getCapital().getCenterTile() }
} else {
tileMap.values
.asSequence()
.filter { it.resource == resourceName }
}
val exploredRevealInfo = exploredRevealTiles
.filter { it.position in civInfo.exploredTiles }

View File

@ -288,6 +288,20 @@ class CivilizationInfo {
fun knows(otherCivName: String) = diplomacy.containsKey(otherCivName)
fun knows(otherCiv: CivilizationInfo) = knows(otherCiv.civName)
/** A sorted Sequence of all other civs we know (excluding barbarians and spectators) */
fun getKnownCivsSorted(includeCityStates: Boolean = true, includeDefeated: Boolean = false) =
gameInfo.civilizations.asSequence()
.filterNot {
it == this ||
it.isBarbarian() || it.isSpectator() ||
!this.knows(it) ||
(!includeDefeated && it.isDefeated()) ||
(!includeCityStates && it.isCityState())
}
.sortedWith(
compareByDescending<CivilizationInfo> { it.isMajorCiv() }
.thenBy (UncivGame.Current.settings.getCollatorFromLocale()) { it.civName.tr() }
)
fun getCapital() = cities.first { it.isCapital() }
fun isPlayerCivilization() = playerType == PlayerType.Human
fun isOneCityChallenger() = (
@ -611,7 +625,7 @@ class CivilizationInfo {
fun getStatForRanking(category: RankingType): Int {
return when (category) {
RankingType.Score -> calculateScoreBreakdown().values.sum().toInt()
RankingType.Score -> calculateTotalScore().toInt()
RankingType.Population -> cities.sumOf { it.population.population }
RankingType.Crop_Yield -> statsForNextTurn.food.roundToInt()
RankingType.Production -> statsForNextTurn.production.roundToInt()
@ -673,7 +687,7 @@ class CivilizationInfo {
var mapSizeModifier = 1276 / gameInfo.tileMap.mapParameters.numberOfTiles().toDouble()
if (mapSizeModifier > 1)
mapSizeModifier = (mapSizeModifier - 1) / 3 + 1
scoreBreakdown["Cities"] = cities.count() * 10 * mapSizeModifier
scoreBreakdown["Population"] = cities.sumOf { it.population.population } * 3 * mapSizeModifier
scoreBreakdown["Tiles"] = cities.sumOf { city -> city.getTiles().filter { !it.isWater}.count() } * 1 * mapSizeModifier
@ -683,10 +697,12 @@ class CivilizationInfo {
}.toDouble()
scoreBreakdown["Techs"] = tech.getNumberOfTechsResearched() * 4.toDouble()
scoreBreakdown["Future Tech"] = tech.repeatingTechsResearched * 10.toDouble()
return scoreBreakdown
}
fun calculateTotalScore() = calculateScoreBreakdown().values.sum()
//endregion
//region state-changing functions

View File

@ -95,14 +95,13 @@ data class CityAction(val city: Vector2 = Vector2.Zero): NotificationAction {
/** enter diplomacy screen */
data class DiplomacyAction(val otherCivName: String = ""): NotificationAction {
override fun execute(worldScreen: WorldScreen) {
val screen = DiplomacyScreen(worldScreen.viewingCiv)
screen.updateRightSide(worldScreen.gameInfo.getCivilization(otherCivName))
worldScreen.game.setScreen(screen)
val otherCiv = worldScreen.gameInfo.getCivilization(otherCivName)
worldScreen.game.setScreen(DiplomacyScreen(worldScreen.viewingCiv, otherCiv))
}
}
/** enter Maya Long Count popup */
class MayaLongCountAction() : NotificationAction {
class MayaLongCountAction : NotificationAction {
override fun execute(worldScreen: WorldScreen) {
MayaCalendar.openPopup(worldScreen, worldScreen.selectedCiv, worldScreen.gameInfo.getYear())
}

View File

@ -5,12 +5,17 @@ import com.badlogic.gdx.scenes.scene2d.Actor
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.WidgetGroup
import com.badlogic.gdx.utils.Align
import com.unciv.UncivGame
import com.unciv.logic.HexMath
import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.logic.civilization.diplomacy.DiplomaticStatus
import com.unciv.ui.trade.DiplomacyScreen
import com.unciv.ui.utils.*
import com.unciv.ui.utils.UncivTooltip.Companion.addTooltip
import kotlin.math.roundToInt
class DiplomacyOverviewTab (
viewingPlayer: CivilizationInfo,
@ -24,41 +29,91 @@ class DiplomacyOverviewTab (
}
override val persistableData = (persistedData as? DiplomacyTabPersistableData) ?: DiplomacyTabPersistableData()
// Widgets that are kept between updates
private val fixedContent = Table()
private val civTable = Table().apply {
defaults().pad(5f)
background = ImageGetter.getBackground(Color.BLACK)
}
val toggleCityStatesButton: TextButton = "City-States".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<CivilizationInfo>()
private var defeatedCivs = sequenceOf<CivilizationInfo>()
private var relevantCivsCount = 0 // includes unknown civs
private var showDiplomacyGroup = false
private var portraitMode = false
init {
update()
}
fun update() {
clear()
val relevantCivs = gameInfo.civilizations
.filter { !it.isBarbarian() && !it.isSpectator() && (persistableData.includeCityStates || !it.isCityState()) }
val diplomacyGroup = DiplomacyGroup(viewingPlayer, overviewScreen.centerAreaHeight, persistableData.includeCityStates)
val playerKnowsAndUndefeatedCivs = relevantCivs.filter { diplomacyGroup.playerKnows(it) && !it.isDefeated() }
val playerKnowsAndDefeatedCivs = relevantCivs.filter { diplomacyGroup.playerKnows(it) && it.isDefeated() }
if (playerKnowsAndUndefeatedCivs.size > 1)
add(diplomacyGroup).top()
val titleTable = Table()
titleTable.add("Our Civilization:".toLabel()).colspan(2).row()
titleTable.add(ImageGetter.getNationIndicator(viewingPlayer.nation, 25f)).pad(5f)
titleTable.add(viewingPlayer.civName.toLabel()).left().padRight(10f)
titleTable.add(viewingPlayer.calculateScoreBreakdown().values.sum().toInt().toLabel()).row()
val civTableScrollPane = getCivTableScroll(relevantCivs, titleTable, playerKnowsAndUndefeatedCivs, playerKnowsAndDefeatedCivs)
val toggleCityStatesButton = "City-States".toTextButton()
toggleCityStatesButton.color = if (persistableData.includeCityStates) Color.RED else Color.GREEN
toggleCityStatesButton.onClick {
persistableData.includeCityStates = !persistableData.includeCityStates
update()
}
val floatingTable = Table()
floatingTable.add(toggleCityStatesButton).row()
floatingTable.add(civTableScrollPane.addBorder(2f, Color.WHITE)).pad(10f)
add(floatingTable)
override fun getFixedContent(): WidgetGroup {
return fixedContent
}
// Refresh content and determine landscape/portrait layout
private fun update() {
relevantCivsCount = gameInfo.civilizations.count {
!it.isSpectator() && !it.isBarbarian() && (persistableData.includeCityStates || !it.isCityState())
}
undefeatedCivs = sequenceOf(viewingPlayer) +
viewingPlayer.getKnownCivsSorted(persistableData.includeCityStates)
defeatedCivs = viewingPlayer.getKnownCivsSorted(persistableData.includeCityStates, true)
.filter { it.isDefeated() }
clear()
fixedContent.clear()
showDiplomacyGroup = undefeatedCivs.any { it != viewingPlayer }
updateCivTable(2)
portraitMode = !showDiplomacyGroup ||
civTable.minWidth > overviewScreen.stage.width / 2 ||
overviewScreen.isPortrait()
val table = if (portraitMode) this else fixedContent
if (showDiplomacyGroup) {
val diplomacySize = (overviewScreen.stage.width - (if (portraitMode) 0f else civTable.minWidth))
.coerceAtMost(overviewScreen.centerAreaHeight)
val diplomacyGroup = DiplomacyGroup(undefeatedCivs, diplomacySize)
table.add(diplomacyGroup).top()
}
if (portraitMode) {
if (showDiplomacyGroup) table.row()
val columns = 2 * (overviewScreen.stage.width / civTable.minWidth).roundToInt()
if (columns > 2) {
updateCivTable(columns)
if (civTable.minWidth > overviewScreen.stage.width)
updateCivTable(columns - 2)
}
}
table.add(floatingTable)
toggleCityStatesButton.color = if (persistableData.includeCityStates) Color.RED else Color.GREEN
civTableScroll.setScrollingDisabled(portraitMode, portraitMode)
}
private fun updateCivTable(columns: Int) = civTable.apply {
clear()
addTitleInfo(columns)
addCivsCategory(columns, "alive", undefeatedCivs.filter { it != viewingPlayer })
addCivsCategory(columns, "defeated", defeatedCivs)
layout()
}
private fun getCivMiniTable(civInfo: CivilizationInfo): Table {
val table = Table()
@ -67,62 +122,56 @@ class DiplomacyOverviewTab (
table.touchable = Touchable.enabled
table.onClick {
if (civInfo.isDefeated() || viewingPlayer.isSpectator() || civInfo == viewingPlayer) return@onClick
UncivGame.Current.setScreen(DiplomacyScreen(viewingPlayer).apply { updateRightSide(civInfo) })
overviewScreen.dispose()
UncivGame.Current.setScreen(DiplomacyScreen(viewingPlayer, civInfo))
}
return table
}
private fun getCivTableScroll(relevantCivs: List<CivilizationInfo>, titleTable: Table,
playerKnowsAndUndefeatedCivs: List<CivilizationInfo>,
playerKnowsAndDefeatedCivs: List<CivilizationInfo>): AutoScrollPane {
val civTable = Table()
civTable.defaults().pad(5f)
civTable.background = ImageGetter.getBackground(Color.BLACK)
civTable.add("[${relevantCivs.size}] Civilizations in the game".toLabel()).pad(5f).colspan(2).row()
civTable.add(titleTable).colspan(2).row()
val turnsTillNextDiplomaticVote = viewingPlayer.getTurnsTillNextDiplomaticVote()
if (turnsTillNextDiplomaticVote != null)
civTable.add("Turns until the next\ndiplomacy victory vote: [$turnsTillNextDiplomaticVote]".toLabel()).center().pad(5f).colspan(2).row()
civTable.addSeparator()
civTable.add("Known and alive ([${playerKnowsAndUndefeatedCivs.size - 1}])".toLabel())
.pad(5f).colspan(2).row()
if (playerKnowsAndUndefeatedCivs.size > 1) {
civTable.addSeparator()
var cityStatesParsed = 0
playerKnowsAndUndefeatedCivs.filter { it != viewingPlayer }.forEach {
civTable.add(getCivMiniTable(it)).left()
if (it.isCityState()) {
cityStatesParsed++
} else {
civTable.add(it.calculateScoreBreakdown().values.sum().toInt().toLabel()).left()
}
if (!it.isCityState() || cityStatesParsed % 2 == 0)
civTable.row()
}
}
civTable.addSeparator()
civTable.add("Known and defeated ([${playerKnowsAndDefeatedCivs.size}])".toLabel())
.pad(5f).colspan(2).row()
if (playerKnowsAndDefeatedCivs.isNotEmpty()) {
civTable.addSeparator()
var cityStatesParsed = 0
playerKnowsAndDefeatedCivs.forEach {
civTable.add(getCivMiniTable(it)).left()
if (it.isCityState()) {
cityStatesParsed++
} else {
civTable.add(it.calculateScoreBreakdown().values.sum().toInt().toLabel()).left()
}
if (!it.isCityState() || cityStatesParsed % 2 == 0)
civTable.row()
}
}
val civTableScrollPane = AutoScrollPane(civTable)
civTableScrollPane.setOverscroll(false, false)
return civTableScrollPane
private fun Table.addTitleInfo(columns: Int) {
add("[$relevantCivsCount] Civilizations in the game".toLabel()).colspan(columns).row()
add("Our Civilization:".toLabel()).colspan(columns).left().padLeft(10f).padTop(10f).row()
add(getCivMiniTable(viewingPlayer)).left()
add(viewingPlayer.calculateTotalScore().toInt().toLabel()).left().row()
val turnsTillNextDiplomaticVote = viewingPlayer.getTurnsTillNextDiplomaticVote() ?: return
add("Turns until the next\ndiplomacy victory vote: [$turnsTillNextDiplomaticVote]".toLabel()).colspan(columns).row()
}
private class DiplomacyGroup(val viewingPlayer: CivilizationInfo, freeHeight: Float, includeCityStates: Boolean): Group() {
private fun Table.addCivsCategory(columns: Int, aliveOrDefeated: String, civs: Sequence<CivilizationInfo>) {
addSeparator()
val count = civs.count()
add("Known and $aliveOrDefeated ([$count])".toLabel())
.pad(5f).colspan(columns).row()
if (count == 0) return
addSeparator()
var currentColumn = 0
var lastCivWasMajor = false
fun advanceCols(delta: Int) {
currentColumn += delta
if (currentColumn >= columns) {
row()
currentColumn = 0
}
lastCivWasMajor = delta == 2
}
for (civ in civs) {
if (lastCivWasMajor && civ.isCityState())
advanceCols(columns)
add(getCivMiniTable(civ)).left()
if (civ.isCityState()) {
advanceCols(1)
} else {
add(civ.calculateTotalScore().toInt().toLabel()).left()
advanceCols(2)
}
}
}
/** This is the 'spider net'-like polygon showing one line per civ-civ relation */
private class DiplomacyGroup(
undefeatedCivs: Sequence<CivilizationInfo>,
freeSize: Float
): Group() {
private fun onCivClicked(civLines: HashMap<String, MutableSet<Actor>>, name: String) {
// ignore the clicks on "dead" civilizations, and remember the selected one
val selectedLines = civLines[name] ?: return
@ -146,61 +195,59 @@ class DiplomacyOverviewTab (
}
}
if (selectedLines.first().isVisible)
// invert visibility of all lines except selected one
civLines.filter { it.key != name }.forEach { it.value.forEach { line -> line.isVisible = !line.isVisible } }
else
// it happens only when all are visible except selected one
// invert visibility of the selected civ's lines
if (selectedLines.first().isVisible) {
// invert visibility of all lines except selected one
civLines.filter { it.key != name }
.forEach { it.value.forEach { line -> line.isVisible = !line.isVisible } }
} else {
// it happens only when all are visible except selected one
// invert visibility of the selected civ's lines
selectedLines.forEach { it.isVisible = !it.isVisible }
}
}
fun playerKnows(civ: CivilizationInfo) = civ == viewingPlayer ||
viewingPlayer.diplomacy.containsKey(civ.civName)
init {
val relevantCivs = viewingPlayer.gameInfo.civilizations.filter { !it.isBarbarian() && (includeCityStates || !it.isCityState()) }
val playerKnowsAndUndefeatedCivs = relevantCivs.filter { playerKnows(it) && !it.isDefeated() }
setSize(freeHeight, freeHeight)
setSize(freeSize, freeSize)
val civGroups = HashMap<String, Actor>()
val civLines = HashMap<String, MutableSet<Actor>>()
for (i in 0..playerKnowsAndUndefeatedCivs.lastIndex) {
val civ = playerKnowsAndUndefeatedCivs[i]
val civCount = undefeatedCivs.count()
for ((i, civ) in undefeatedCivs.withIndex()) {
val civGroup = ImageGetter.getNationIndicator(civ.nation, 30f)
val vector = HexMath.getVectorForAngle(2 * Math.PI.toFloat() * i / playerKnowsAndUndefeatedCivs.size)
val vector = HexMath.getVectorForAngle(2 * Math.PI.toFloat() * i / civCount)
civGroup.center(this)
civGroup.moveBy(vector.x * freeHeight / 2.25f, vector.y * freeHeight / 2.25f)
civGroup.moveBy(vector.x * freeSize / 2.25f, vector.y * freeSize / 2.25f)
civGroup.touchable = Touchable.enabled
civGroup.onClick {
onCivClicked(civLines, civ.civName)
}
civGroup.addTooltip(civ.civName, tipAlign = Align.bottomLeft)
civGroups[civ.civName] = civGroup
addActor(civGroup)
}
for (civ in relevantCivs.filter { playerKnows(it) && !it.isDefeated() })
for (diplomacy in civ.diplomacy.values.filter {
(it.otherCiv().isMajorCiv() || includeCityStates) && playerKnows(it.otherCiv()) && !it.otherCiv().isDefeated()
}) {
for (civ in undefeatedCivs)
for (diplomacy in civ.diplomacy.values) {
if (diplomacy.otherCiv() !in undefeatedCivs) continue
val civGroup = civGroups[civ.civName]!!
val otherCivGroup = civGroups[diplomacy.otherCivName]!!
if (!civLines.containsKey(civ.civName))
civLines[civ.civName] = mutableSetOf()
val statusLine = ImageGetter.getLine(
startX = civGroup.x + civGroup.width / 2,
startY = civGroup.y + civGroup.height / 2,
endX = otherCivGroup.x + otherCivGroup.width / 2,
endY = otherCivGroup.y + otherCivGroup.height / 2,
width = 2f)
val statusLine = ImageGetter.getLine(civGroup.x + civGroup.width / 2, civGroup.y + civGroup.height / 2,
otherCivGroup.x + otherCivGroup.width / 2, otherCivGroup.y + otherCivGroup.height / 2, 2f)
statusLine.color = if (diplomacy.diplomaticStatus == DiplomaticStatus.War) Color.RED else Color.GREEN
statusLine.color = if (diplomacy.diplomaticStatus == DiplomaticStatus.War) Color.RED
else diplomacy.relationshipLevel().color
if (!civLines.containsKey(civ.civName)) civLines[civ.civName] = mutableSetOf()
civLines[civ.civName]!!.add(statusLine)
addActor(statusLine)
statusLine.toBack()
addActorAt(0, statusLine)
}
}
}

View File

@ -415,9 +415,7 @@ class CityButton(val city: CityInfo, private val tileGroup: WorldTileGroup): Tab
private fun foreignCityInfoPopup() {
fun openDiplomacy() {
// If city doesn't belong to you, go directly to its owner's diplomacy screen.
val screen = DiplomacyScreen(worldScreen.viewingCiv)
screen.updateRightSide(city.civInfo)
worldScreen.game.setScreen(screen)
worldScreen.game.setScreen(DiplomacyScreen(worldScreen.viewingCiv, city.civInfo))
}
// If there's nothing to display cuz no Religion - skip popup

View File

@ -10,14 +10,15 @@ import com.unciv.UncivGame
import com.unciv.logic.civilization.*
import com.unciv.logic.civilization.diplomacy.*
import com.unciv.logic.civilization.diplomacy.DiplomaticModifiers.*
import com.unciv.logic.trade.Trade
import com.unciv.logic.trade.TradeLogic
import com.unciv.logic.trade.TradeOffer
import com.unciv.logic.trade.TradeType
import com.unciv.models.ruleset.ModOptionsConstants
import com.unciv.models.ruleset.Quest
import com.unciv.models.ruleset.tile.ResourceType
import com.unciv.models.ruleset.unique.Unique
import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.models.ruleset.tile.ResourceType
import com.unciv.models.stats.Stat
import com.unciv.models.translations.fillPlaceholders
import com.unciv.models.translations.tr
@ -27,57 +28,77 @@ import com.unciv.ui.civilopedia.CivilopediaScreen
import com.unciv.ui.tilegroups.CityButton
import com.unciv.ui.utils.*
import com.unciv.ui.utils.UncivTooltip.Companion.addTooltip
import kotlin.collections.ArrayList
import kotlin.math.floor
import kotlin.math.roundToInt
import com.unciv.ui.utils.AutoScrollPane as ScrollPane
class DiplomacyScreen(val viewingCiv:CivilizationInfo): BaseScreen() {
/**
* Creates the diplomacy screen for [viewingCiv].
*
* When [selectCiv] is given and [selectTrade] is not, that Civilization is selected as if clicked on the left side.
* When [selectCiv] and [selectTrade] are supplied, that Trade for that Civilization is selected, used for the counter-offer option from `TradePopup`.
*/
@Suppress("KDocUnresolvedReference") // Mentioning non-field parameters is flagged, but they work anyway
class DiplomacyScreen(
val viewingCiv: CivilizationInfo,
selectCiv: CivilizationInfo? = null,
selectTrade: Trade? = null
): BaseScreen() {
companion object {
private const val nationIconSize = 100f
private const val nationIconPad = 10f
}
private val leftSideTable = Table().apply { defaults().pad(10f) }
private val leftSideTable = Table().apply { defaults().pad(nationIconPad) }
private val leftSideScroll = ScrollPane(leftSideTable)
private val rightSideTable = Table()
private val closeButton = Constants.close.toTextButton()
private fun isNotPlayersTurn() = !UncivGame.Current.worldScreen.canChangeState
init {
onBackButtonClicked { UncivGame.Current.setWorldScreen() }
val splitPane = SplitPane(ScrollPane(leftSideTable), rightSideTable, false, skin)
val splitPane = SplitPane(leftSideScroll, rightSideTable, false, skin)
splitPane.splitAmount = 0.2f
updateLeftSideTable()
updateLeftSideTable(selectCiv)
splitPane.setFillParent(true)
stage.addActor(splitPane)
val closeButton = Constants.close.toTextButton()
closeButton.onClick { UncivGame.Current.setWorldScreen() }
closeButton.label.setFontSize(Constants.headingFontSize)
closeButton.labelCell.pad(10f)
closeButton.pack()
closeButton.y = stage.height - closeButton.height - 10
closeButton.x =
(stage.width * 0.2f - closeButton.width) / 2 // center, leftSideTable.width not known yet
positionCloseButton()
stage.addActor(closeButton) // This must come after the split pane so it will be above, that the button will be clickable
if (selectCiv != null) {
if (selectTrade != null) {
val tradeTable = setTrade(selectCiv)
tradeTable.tradeLogic.currentTrade.set(selectTrade)
tradeTable.offerColumnsTable.update()
} else
updateRightSide(selectCiv)
}
}
private fun updateLeftSideTable() {
private fun positionCloseButton() {
closeButton.setPosition(stage.width * 0.1f, stage.height - 10f, Align.top)
}
private fun updateLeftSideTable(selectCiv: CivilizationInfo?) {
leftSideTable.clear()
leftSideTable.add().padBottom(60f).row() // room so the close button does not cover the first
val civsToDisplay = viewingCiv.gameInfo.civilizations.asSequence()
.filterNot {
it.isDefeated() || it == viewingCiv || it.isBarbarian() || it.isSpectator() ||
!viewingCiv.knows(it)
var selectCivY = 0f
for (civ in viewingCiv.getKnownCivsSorted()) {
if (civ == selectCiv) {
selectCivY = leftSideTable.prefHeight
}
.sortedWith(
compareByDescending<CivilizationInfo>{ it.isMajorCiv() }
.thenBy (UncivGame.Current.settings.getCollatorFromLocale(), { it.civName.tr() })
)
for (civ in civsToDisplay) {
val civIndicator = ImageGetter.getNationIndicator(civ.nation, 100f)
val civIndicator = ImageGetter.getNationIndicator(civ.nation, nationIconSize)
val relationLevel = civ.getDiplomacyManager(viewingCiv).relationshipLevel()
val relationshipIcon = if (civ.isCityState() && relationLevel == RelationshipLevel.Ally)
@ -114,9 +135,15 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo): BaseScreen() {
civIndicator.onClick { updateRightSide(civ) }
}
if (selectCivY != 0f) {
leftSideScroll.layout()
leftSideScroll.scrollY = selectCivY + (nationIconSize + 2 * nationIconPad - stage.height) / 2
leftSideScroll.updateVisualScroll()
}
}
fun updateRightSide(otherCiv: CivilizationInfo) {
private fun updateRightSide(otherCiv: CivilizationInfo) {
rightSideTable.clear()
if (otherCiv.isCityState()) rightSideTable.add(
ScrollPane(getCityStateDiplomacyTable(otherCiv))
@ -125,7 +152,7 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo): BaseScreen() {
.height(stage.height)
}
fun setTrade(civ: CivilizationInfo): TradeTable {
private fun setTrade(civ: CivilizationInfo): TradeTable {
rightSideTable.clear()
val tradeTable = TradeTable(civ, this)
rightSideTable.add(tradeTable)
@ -303,7 +330,7 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo): BaseScreen() {
revokeProtectionButton.onClick {
YesNoPopup("Revoke protection for [${otherCiv.civName}]?", {
otherCiv.removeProtectorCiv(viewingCiv)
updateLeftSideTable()
updateLeftSideTable(otherCiv)
updateRightSide(otherCiv)
}, this).open()
}
@ -314,7 +341,7 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo): BaseScreen() {
protectionButton.onClick {
YesNoPopup("Declare Protection of [${otherCiv.civName}]?", {
otherCiv.addProtectorCiv(viewingCiv)
updateLeftSideTable()
updateLeftSideTable(otherCiv)
updateRightSide(otherCiv)
}, this).open()
}
@ -350,7 +377,7 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo): BaseScreen() {
)
)
tradeLogic.acceptTrade()
updateLeftSideTable()
updateLeftSideTable(otherCiv)
updateRightSide(otherCiv)
}, this).open()
}
@ -443,7 +470,7 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo): BaseScreen() {
"Gift [$giftAmount] gold (+[$influenceAmount] influence)".toTextButton()
giftButton.onClick {
otherCiv.receiveGoldGift(viewingCiv, giftAmount)
updateLeftSideTable()
updateLeftSideTable(otherCiv)
updateRightSide(otherCiv)
}
diplomacyTable.add(giftButton).row()
@ -694,7 +721,7 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo): BaseScreen() {
denounceButton.onClick {
YesNoPopup("Denounce [${otherCiv.civName}]?", {
diplomacyManager.denounce()
updateLeftSideTable()
updateLeftSideTable(otherCiv)
setRightSideFlavorText(otherCiv, "We will remember this.", "Very well.")
}, this).open()
}
@ -864,7 +891,7 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo): BaseScreen() {
YesNoPopup("Declare war on [${otherCiv.civName}]?", {
diplomacyManager.declareWar()
setRightSideFlavorText(otherCiv, otherCiv.nation.attacked, "Very well.")
updateLeftSideTable()
updateLeftSideTable(otherCiv)
UncivGame.Current.musicController.chooseTrack(otherCiv.civName, MusicMood.War, MusicTrackChooserFlags.setSpecific)
}, this).open()
}
@ -897,4 +924,8 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo): BaseScreen() {
rightSideTable.add(diplomacyTable)
}
override fun resize(width: Int, height: Int) {
super.resize(width, height)
positionCloseButton()
}
}

View File

@ -2,17 +2,11 @@ package com.unciv.ui.worldscreen
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.unciv.Constants
import com.unciv.UncivGame
import com.unciv.logic.civilization.NotificationIcon
import com.unciv.logic.civilization.diplomacy.DiplomacyFlags
import com.unciv.logic.trade.TradeEvaluation
import com.unciv.logic.trade.TradeLogic
import com.unciv.logic.trade.TradeOffer
import com.unciv.logic.trade.TradeType
import com.unciv.models.translations.tr
import com.unciv.ui.audio.MusicMood
import com.unciv.ui.audio.MusicTrackChooserFlags
import com.unciv.ui.trade.DiplomacyScreen
import com.unciv.ui.trade.LeaderIntroTable
import com.unciv.ui.utils.*
@ -90,23 +84,15 @@ class TradePopup(worldScreen: WorldScreen): Popup(worldScreen){
}
addButton("Not this time.", 'n') {
tradeRequest.decline(viewingCiv)
close()
requestingCiv.addNotification("[${viewingCiv.civName}] has denied your trade request", viewingCiv.civName, NotificationIcon.Trade)
worldScreen.shouldUpdate = true
}
addButton("How about something else...", 'e') {
close()
val diplomacyScreen = DiplomacyScreen(viewingCiv)
val tradeTable = diplomacyScreen.setTrade(requestingCiv)
tradeTable.tradeLogic.currentTrade.set(trade)
tradeTable.offerColumnsTable.update()
worldScreen.game.setScreen(diplomacyScreen)
worldScreen.game.setScreen(DiplomacyScreen(viewingCiv, requestingCiv, trade))
worldScreen.shouldUpdate = true
}
}