mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-21 21:30:20 +07:00
Resolved #3501 - Added city-state toggle to diplomacy overview, clicking on civ names in overview opens diplomacy screen
This commit is contained in:
@ -17,6 +17,7 @@ import com.unciv.logic.trade.TradeOffersList
|
|||||||
import com.unciv.models.ruleset.tile.ResourceType
|
import com.unciv.models.ruleset.tile.ResourceType
|
||||||
import com.unciv.models.translations.tr
|
import com.unciv.models.translations.tr
|
||||||
import com.unciv.ui.pickerscreens.PromotionPickerScreen
|
import com.unciv.ui.pickerscreens.PromotionPickerScreen
|
||||||
|
import com.unciv.ui.trade.DiplomacyScreen
|
||||||
import com.unciv.ui.utils.*
|
import com.unciv.ui.utils.*
|
||||||
import java.text.DecimalFormat
|
import java.text.DecimalFormat
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
@ -103,46 +104,67 @@ class EmpireOverviewScreen(private var viewingPlayer:CivilizationInfo, defaultPa
|
|||||||
stage.addActor(table)
|
stage.addActor(table)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setDiplomacyTable() {
|
private fun setDiplomacyTable(includeCityStates:Boolean=false) {
|
||||||
centerTable.clear()
|
centerTable.clear()
|
||||||
val relevantCivs = viewingPlayer.gameInfo.civilizations.filter { !it.isBarbarian() && !it.isCityState() }
|
val relevantCivs = viewingPlayer.gameInfo.civilizations.filter { !it.isBarbarian() && (includeCityStates || !it.isCityState()) }
|
||||||
val playerKnowsAndUndefeatedCivs = relevantCivs.filter { playerKnows(it) && !it.isDefeated() }
|
val diplomacyGroup = DiplomacyGroup(viewingPlayer, stage.height - topTable.height, includeCityStates)
|
||||||
val playerKnowsAndDefeatedCivs = relevantCivs.filter { playerKnows(it) && it.isDefeated() }
|
val playerKnowsAndUndefeatedCivs = relevantCivs.filter { diplomacyGroup.playerKnows(it) && !it.isDefeated() }
|
||||||
|
val playerKnowsAndDefeatedCivs = relevantCivs.filter { diplomacyGroup.playerKnows(it) && it.isDefeated() }
|
||||||
if (playerKnowsAndUndefeatedCivs.size > 1)
|
if (playerKnowsAndUndefeatedCivs.size > 1)
|
||||||
centerTable.add(getDiplomacyGroup())
|
centerTable.add(diplomacyGroup)
|
||||||
val civTable = Table()
|
fun getCivMinitable(civInfo: CivilizationInfo):Table{
|
||||||
civTable.background = ImageGetter.getBackground(Color.BLACK)
|
val table = Table()
|
||||||
civTable.add("[${relevantCivs.size}] Civilizations in the game".toLabel()).pad(5f).colspan(4).row()
|
table.add(ImageGetter.getNationIndicator(civInfo.nation, 25f)).pad(5f)
|
||||||
|
table.add(civInfo.civName.toLabel()).left()
|
||||||
|
table.touchable = Touchable.enabled
|
||||||
|
table.onClick {
|
||||||
|
game.setScreen(DiplomacyScreen(viewingPlayer).apply { updateRightSide(civInfo) })
|
||||||
|
}
|
||||||
|
return table
|
||||||
|
}
|
||||||
|
|
||||||
val titleTable = Table()
|
val titleTable = Table()
|
||||||
titleTable.add("Our Civilization:".toLabel())
|
titleTable.add("Our Civilization:".toLabel())
|
||||||
titleTable.add(ImageGetter.getNationIndicator(viewingPlayer.nation, 25f)).pad(5f)
|
titleTable.add(ImageGetter.getNationIndicator(viewingPlayer.nation, 25f)).pad(5f)
|
||||||
titleTable.add(viewingPlayer.civName.toLabel()).left().row()
|
titleTable.add(viewingPlayer.civName.toLabel()).left().row()
|
||||||
civTable.add(titleTable).colspan(4).row()
|
|
||||||
|
|
||||||
|
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()
|
||||||
civTable.addSeparator()
|
civTable.addSeparator()
|
||||||
civTable.add("Known and alive ([${playerKnowsAndUndefeatedCivs.size - 1}])".toLabel()).pad(5f).colspan(4).row()
|
civTable.add("Known and alive ([${playerKnowsAndUndefeatedCivs.size - 1}])".toLabel()).pad(5f).colspan(2).row()
|
||||||
if (playerKnowsAndUndefeatedCivs.size > 1) {
|
if (playerKnowsAndUndefeatedCivs.size > 1) {
|
||||||
civTable.addSeparator()
|
civTable.addSeparator()
|
||||||
playerKnowsAndUndefeatedCivs.filter { it != viewingPlayer }.forEach {
|
playerKnowsAndUndefeatedCivs.filter { it != viewingPlayer }.forEach {
|
||||||
civTable.add(ImageGetter.getNationIndicator(it.nation, 25f)).pad(5f)
|
civTable.add(getCivMinitable(it)).left()
|
||||||
if (playerKnowsAndUndefeatedCivs.indexOf(it) % 2 == 0)
|
if (playerKnowsAndUndefeatedCivs.indexOf(it) % 2 == 0) civTable.row()
|
||||||
civTable.add(it.civName.toLabel()).left().row()
|
|
||||||
else civTable.add(it.civName.toLabel()).left()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
civTable.addSeparator()
|
civTable.addSeparator()
|
||||||
civTable.add("Known and defeated ([${playerKnowsAndDefeatedCivs.size}])".toLabel()).pad(5f).colspan(4).row()
|
civTable.add("Known and defeated ([${playerKnowsAndDefeatedCivs.size}])".toLabel()).pad(5f).colspan(2).row()
|
||||||
if (playerKnowsAndDefeatedCivs.isNotEmpty()) {
|
if (playerKnowsAndDefeatedCivs.isNotEmpty()) {
|
||||||
civTable.addSeparator()
|
civTable.addSeparator()
|
||||||
playerKnowsAndDefeatedCivs.forEach {
|
playerKnowsAndDefeatedCivs.forEach {
|
||||||
civTable.add(ImageGetter.getNationIndicator(it.nation, 25f)).pad(5f)
|
civTable.add(getCivMinitable(it)).left()
|
||||||
if (playerKnowsAndDefeatedCivs.indexOf(it) % 2 != 0)
|
if (playerKnowsAndUndefeatedCivs.indexOf(it) % 2 == 0) civTable.row()
|
||||||
civTable.add(it.civName.toLabel()).left().row()
|
|
||||||
else civTable.add(it.civName.toLabel()).left()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val civTableScrollPane = ScrollPane(civTable)
|
val civTableScrollPane = ScrollPane(civTable)
|
||||||
civTableScrollPane.setOverscroll(false, false)
|
civTableScrollPane.setOverscroll(false, false)
|
||||||
centerTable.add(civTableScrollPane.addBorder(2f, Color.WHITE)).pad(10f)
|
|
||||||
|
val toggleCityStatesButton = "City-States".toTextButton()
|
||||||
|
toggleCityStatesButton.color = if(includeCityStates)Color.RED else Color.GREEN
|
||||||
|
toggleCityStatesButton.onClick { setDiplomacyTable(!includeCityStates) }
|
||||||
|
civTable.add(toggleCityStatesButton).row()
|
||||||
|
|
||||||
|
val floatingTable = Table()
|
||||||
|
floatingTable.add(toggleCityStatesButton).row()
|
||||||
|
floatingTable.add(civTableScrollPane.addBorder(2f, Color.WHITE)).pad(10f)
|
||||||
|
|
||||||
|
centerTable.add(floatingTable)
|
||||||
centerTable.pack()
|
centerTable.pack()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -370,89 +392,6 @@ class EmpireOverviewScreen(private var viewingPlayer:CivilizationInfo, defaultPa
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun playerKnows(civ:CivilizationInfo) = civ==viewingPlayer ||
|
|
||||||
viewingPlayer.diplomacy.containsKey(civ.civName)
|
|
||||||
|
|
||||||
private fun getDiplomacyGroup(): Group {
|
|
||||||
val relevantCivs = viewingPlayer.gameInfo.civilizations.filter { !it.isBarbarian() && !it.isCityState() }
|
|
||||||
val playerKnowsAndUndefeatedCivs = relevantCivs.filter { playerKnows(it) && !it.isDefeated() }
|
|
||||||
val freeHeight = stage.height - topTable.height
|
|
||||||
val group = Group()
|
|
||||||
group.setSize(freeHeight, freeHeight)
|
|
||||||
val civGroups = HashMap<String, Actor>()
|
|
||||||
val civLines = HashMap<String, MutableSet<Actor>>()
|
|
||||||
for (i in 0..playerKnowsAndUndefeatedCivs.lastIndex) {
|
|
||||||
val civ = playerKnowsAndUndefeatedCivs[i]
|
|
||||||
|
|
||||||
val civGroup = ImageGetter.getNationIndicator(civ.nation, 30f)
|
|
||||||
|
|
||||||
val vector = HexMath.getVectorForAngle(2 * Math.PI.toFloat() * i / playerKnowsAndUndefeatedCivs.size)
|
|
||||||
civGroup.center(group)
|
|
||||||
civGroup.moveBy(vector.x * freeHeight / 2.25f, vector.y * freeHeight / 2.25f)
|
|
||||||
civGroup.touchable = Touchable.enabled
|
|
||||||
civGroup.onClick {
|
|
||||||
onCivClicked(civLines, civ.civName)
|
|
||||||
}
|
|
||||||
|
|
||||||
civGroups[civ.civName] = civGroup
|
|
||||||
group.addActor(civGroup)
|
|
||||||
}
|
|
||||||
|
|
||||||
for (civ in relevantCivs.filter { playerKnows(it) && !it.isDefeated() })
|
|
||||||
for (diplomacy in civ.diplomacy.values.filter {
|
|
||||||
it.otherCiv().isMajorCiv() && playerKnows(it.otherCiv()) && !it.otherCiv().isDefeated()
|
|
||||||
}) {
|
|
||||||
val civGroup = civGroups[civ.civName]!!
|
|
||||||
val otherCivGroup = civGroups[diplomacy.otherCivName]!!
|
|
||||||
|
|
||||||
if (!civLines.containsKey(civ.civName))
|
|
||||||
civLines[civ.civName] = mutableSetOf()
|
|
||||||
|
|
||||||
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.Peace) Color.GREEN else Color.RED
|
|
||||||
|
|
||||||
civLines[civ.civName]!!.add(statusLine)
|
|
||||||
|
|
||||||
group.addActor(statusLine)
|
|
||||||
statusLine.toBack()
|
|
||||||
}
|
|
||||||
|
|
||||||
return 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
|
|
||||||
|
|
||||||
// let's check whether lines of all civs are visible (except selected one)
|
|
||||||
var atLeastOneLineVisible = false
|
|
||||||
var allAreLinesInvisible = true
|
|
||||||
for (lines in civLines.values) {
|
|
||||||
// skip the civilization selected by user, and civilizations with no lines
|
|
||||||
if (lines == selectedLines || lines.isEmpty()) continue
|
|
||||||
|
|
||||||
val visibility = lines.first().isVisible
|
|
||||||
atLeastOneLineVisible = atLeastOneLineVisible || visibility
|
|
||||||
allAreLinesInvisible = allAreLinesInvisible && visibility
|
|
||||||
|
|
||||||
// check whether both visible and invisible lines are present
|
|
||||||
if (atLeastOneLineVisible && !allAreLinesInvisible) {
|
|
||||||
// invert visibility of the selected civ's lines
|
|
||||||
selectedLines.forEach { it.isVisible = !it.isVisible }
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private fun getResourcesTable(): Table {
|
private fun getResourcesTable(): Table {
|
||||||
@ -560,3 +499,87 @@ class EmpireOverviewScreen(private var viewingPlayer:CivilizationInfo, defaultPa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class DiplomacyGroup(val viewingPlayer: CivilizationInfo, freeHeight: Float, includeCityStates: Boolean): 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
|
||||||
|
|
||||||
|
// let's check whether lines of all civs are visible (except selected one)
|
||||||
|
var atLeastOneLineVisible = false
|
||||||
|
var allAreLinesInvisible = true
|
||||||
|
for (lines in civLines.values) {
|
||||||
|
// skip the civilization selected by user, and civilizations with no lines
|
||||||
|
if (lines == selectedLines || lines.isEmpty()) continue
|
||||||
|
|
||||||
|
val visibility = lines.first().isVisible
|
||||||
|
atLeastOneLineVisible = atLeastOneLineVisible || visibility
|
||||||
|
allAreLinesInvisible = allAreLinesInvisible && visibility
|
||||||
|
|
||||||
|
// check whether both visible and invisible lines are present
|
||||||
|
if (atLeastOneLineVisible && !allAreLinesInvisible) {
|
||||||
|
// invert visibility of the selected civ's lines
|
||||||
|
selectedLines.forEach { it.isVisible = !it.isVisible }
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
val civGroups = HashMap<String, Actor>()
|
||||||
|
val civLines = HashMap<String, MutableSet<Actor>>()
|
||||||
|
for (i in 0..playerKnowsAndUndefeatedCivs.lastIndex) {
|
||||||
|
val civ = playerKnowsAndUndefeatedCivs[i]
|
||||||
|
|
||||||
|
val civGroup = ImageGetter.getNationIndicator(civ.nation, 30f)
|
||||||
|
|
||||||
|
val vector = HexMath.getVectorForAngle(2 * Math.PI.toFloat() * i / playerKnowsAndUndefeatedCivs.size)
|
||||||
|
civGroup.center(this)
|
||||||
|
civGroup.moveBy(vector.x * freeHeight / 2.25f, vector.y * freeHeight / 2.25f)
|
||||||
|
civGroup.touchable = Touchable.enabled
|
||||||
|
civGroup.onClick {
|
||||||
|
onCivClicked(civLines, civ.civName)
|
||||||
|
}
|
||||||
|
|
||||||
|
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()
|
||||||
|
}) {
|
||||||
|
val civGroup = civGroups[civ.civName]!!
|
||||||
|
val otherCivGroup = civGroups[diplomacy.otherCivName]!!
|
||||||
|
|
||||||
|
if (!civLines.containsKey(civ.civName))
|
||||||
|
civLines[civ.civName] = mutableSetOf()
|
||||||
|
|
||||||
|
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.Peace) Color.GREEN else Color.RED
|
||||||
|
|
||||||
|
civLines[civ.civName]!!.add(statusLine)
|
||||||
|
|
||||||
|
addActor(statusLine)
|
||||||
|
statusLine.toBack()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user