Resolved #3501 - Added city-state toggle to diplomacy overview, clicking on civ names in overview opens diplomacy screen

This commit is contained in:
Yair Morgenstern
2021-01-07 23:38:26 +02:00
parent 0bb40d842a
commit c4f33f9373

View File

@ -17,6 +17,7 @@ import com.unciv.logic.trade.TradeOffersList
import com.unciv.models.ruleset.tile.ResourceType
import com.unciv.models.translations.tr
import com.unciv.ui.pickerscreens.PromotionPickerScreen
import com.unciv.ui.trade.DiplomacyScreen
import com.unciv.ui.utils.*
import java.text.DecimalFormat
import kotlin.math.abs
@ -103,46 +104,67 @@ class EmpireOverviewScreen(private var viewingPlayer:CivilizationInfo, defaultPa
stage.addActor(table)
}
private fun setDiplomacyTable() {
private fun setDiplomacyTable(includeCityStates:Boolean=false) {
centerTable.clear()
val relevantCivs = viewingPlayer.gameInfo.civilizations.filter { !it.isBarbarian() && !it.isCityState() }
val playerKnowsAndUndefeatedCivs = relevantCivs.filter { playerKnows(it) && !it.isDefeated() }
val playerKnowsAndDefeatedCivs = relevantCivs.filter { playerKnows(it) && it.isDefeated() }
val relevantCivs = viewingPlayer.gameInfo.civilizations.filter { !it.isBarbarian() && (includeCityStates || !it.isCityState()) }
val diplomacyGroup = DiplomacyGroup(viewingPlayer, stage.height - topTable.height, includeCityStates)
val playerKnowsAndUndefeatedCivs = relevantCivs.filter { diplomacyGroup.playerKnows(it) && !it.isDefeated() }
val playerKnowsAndDefeatedCivs = relevantCivs.filter { diplomacyGroup.playerKnows(it) && it.isDefeated() }
if (playerKnowsAndUndefeatedCivs.size > 1)
centerTable.add(getDiplomacyGroup())
val civTable = Table()
civTable.background = ImageGetter.getBackground(Color.BLACK)
civTable.add("[${relevantCivs.size}] Civilizations in the game".toLabel()).pad(5f).colspan(4).row()
centerTable.add(diplomacyGroup)
fun getCivMinitable(civInfo: CivilizationInfo):Table{
val table = Table()
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()
titleTable.add("Our Civilization:".toLabel())
titleTable.add(ImageGetter.getNationIndicator(viewingPlayer.nation, 25f)).pad(5f)
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.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) {
civTable.addSeparator()
playerKnowsAndUndefeatedCivs.filter { it != viewingPlayer }.forEach {
civTable.add(ImageGetter.getNationIndicator(it.nation, 25f)).pad(5f)
if (playerKnowsAndUndefeatedCivs.indexOf(it) % 2 == 0)
civTable.add(it.civName.toLabel()).left().row()
else civTable.add(it.civName.toLabel()).left()
civTable.add(getCivMinitable(it)).left()
if (playerKnowsAndUndefeatedCivs.indexOf(it) % 2 == 0) civTable.row()
}
}
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()) {
civTable.addSeparator()
playerKnowsAndDefeatedCivs.forEach {
civTable.add(ImageGetter.getNationIndicator(it.nation, 25f)).pad(5f)
if (playerKnowsAndDefeatedCivs.indexOf(it) % 2 != 0)
civTable.add(it.civName.toLabel()).left().row()
else civTable.add(it.civName.toLabel()).left()
civTable.add(getCivMinitable(it)).left()
if (playerKnowsAndUndefeatedCivs.indexOf(it) % 2 == 0) civTable.row()
}
}
val civTableScrollPane = ScrollPane(civTable)
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()
}
@ -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 {
@ -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()
}
}
}