Spectators can enter and view other player cities (#2856)

* Spectators can enter and view other player cities

* Spectators not shown on diplomacy screen

* master merge fix

* Spectators can enter and view other player cities

* Spectators not shown on diplomacy screen

* Fix barbarians spawn in spectator mode

* small post fixes

* remove excessive spectator check

* Remove spectators from diplomacy screen

* Spectators cannot reallocate specialists in cities

* Refactor using canChangeState value for CityScreen and WorldScreen.

* Continue refactor using canChangeState value
This commit is contained in:
Alexander Korolyov 2020-07-19 12:35:38 +02:00 committed by GitHub
parent bd422fdb16
commit 00983dd00e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 32 additions and 22 deletions

View file

@ -182,7 +182,7 @@ class GameInfo {
fun placeBarbarianEncampment(existingEncampments: List<TileInfo>): TileInfo? {
// Barbarians will only spawn in places that no one can see
val allViewableTiles = civilizations.filterNot { it.isBarbarian() }
val allViewableTiles = civilizations.filterNot { it.isBarbarian() || it.isSpectator() }
.flatMap { it.viewableTiles }.toHashSet()
val tilesWithin3ofExistingEncampment = existingEncampments.asSequence()
.flatMap { it.getTilesInDistance(3) }.toSet()

View file

@ -22,6 +22,9 @@ class CityScreen(internal val city: CityInfo): CameraStageBaseScreen() {
var selectedConstruction: IConstruction? = null
var keyListener: InputListener? = null
/** Toggles or adds/removes all state changing buttons */
val canChangeState = UncivGame.Current.worldScreen.canChangeState
/** Toggle between Constructions and cityInfo (buildings, specialists etc. */
var showConstructionsTable = true
@ -134,12 +137,13 @@ class CityScreen(internal val city: CityInfo): CameraStageBaseScreen() {
city.annexCity()
update()
}
if (!canChangeState) annexCityButton.disable()
razeCityButtonHolder.add(annexCityButton).colspan(cityPickerTable.columns)
} else if(!city.isBeingRazed) {
val razeCityButton = "Raze city".toTextButton()
razeCityButton.labelCell.pad(10f)
razeCityButton.onClick { city.isBeingRazed=true; update() }
if(!UncivGame.Current.worldScreen.isPlayersTurn || city.isOriginalCapital)
if(!canChangeState || city.isOriginalCapital)
razeCityButton.disable()
razeCityButtonHolder.add(razeCityButton).colspan(cityPickerTable.columns)
@ -147,7 +151,7 @@ class CityScreen(internal val city: CityInfo): CameraStageBaseScreen() {
val stopRazingCityButton = "Stop razing city".toTextButton()
stopRazingCityButton.labelCell.pad(10f)
stopRazingCityButton.onClick { city.isBeingRazed=false; update() }
if(!UncivGame.Current.worldScreen.isPlayersTurn) stopRazingCityButton.disable()
if(!canChangeState) stopRazingCityButton.disable()
razeCityButtonHolder.add(stopRazingCityButton).colspan(cityPickerTable.columns)
}
razeCityButtonHolder.pack()
@ -173,7 +177,7 @@ class CityScreen(internal val city: CityInfo): CameraStageBaseScreen() {
selectedTile = tileInfo
selectedConstruction = null
if (tileGroup.isWorkable && UncivGame.Current.worldScreen.isPlayersTurn) {
if (tileGroup.isWorkable && canChangeState) {
if (!tileInfo.isWorked() && city.population.getFreePopulation() > 0) {
city.workedTiles.add(tileInfo.position)
game.settings.addCompletedTutorialTask("Reassign worked tiles")

View file

@ -34,7 +34,6 @@ class CityScreenTileTable(val cityScreen: CityScreen): Table(){
innerTable.row()
innerTable.add(getTileStatsTable(stats)).row()
if(selectedTile.getOwner()==null && selectedTile.neighbors.any {it.getCity()==city}
&& selectedTile in city.tilesInRange){
val goldCostOfTile = city.expansion.getGoldCostOfTile(selectedTile)
@ -44,7 +43,9 @@ class CityScreenTileTable(val cityScreen: CityScreen): Table(){
city.expansion.buyTile(selectedTile)
UncivGame.Current.setScreen(CityScreen(city))
}
if(goldCostOfTile>city.civInfo.gold || city.isPuppet || !UncivGame.Current.worldScreen.isPlayersTurn)
if(goldCostOfTile>city.civInfo.gold
|| city.isPuppet
|| !cityScreen.canChangeState)
buyTileButton.disable()
innerTable.add(buyTileButton).row()
@ -64,6 +65,7 @@ class CityScreenTileTable(val cityScreen: CityScreen): Table(){
update(selectedTile)
cityScreen.update()
}
if (!cityScreen.canChangeState) unlockButton.disable()
innerTable.add(unlockButton).row()
}
else {
@ -73,6 +75,7 @@ class CityScreenTileTable(val cityScreen: CityScreen): Table(){
update(selectedTile)
cityScreen.update()
}
if (!cityScreen.canChangeState) lockButton.disable()
innerTable.add(lockButton).row()
}
}

View file

@ -270,7 +270,8 @@ class ConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBaseScre
if (isSelectedQueueEntry()) {
button = "Remove from queue".toTextButton()
if (!UncivGame.Current.worldScreen.isPlayersTurn || city.isPuppet) button.disable()
if (!cityScreen.canChangeState || city.isPuppet)
button.disable()
else {
button.onClick {
cityConstructions.removeFromQueue(selectedQueueEntry,false)
@ -284,7 +285,7 @@ class ConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBaseScre
if (construction == null
|| cityConstructions.isQueueFull()
|| !cityConstructions.getConstruction(construction.name).isBuildable(cityConstructions)
|| !UncivGame.Current.worldScreen.isPlayersTurn
|| !cityScreen.canChangeState
|| construction is PerpetualConstruction && cityConstructions.isBeingConstructedOrEnqueued(construction.name)
|| city.isPuppet) {
button.disable()
@ -347,7 +348,7 @@ class ConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBaseScre
}
if ( !construction.isBuildable(cityConstructions)
|| !UncivGame.Current.worldScreen.isPlayersTurn
|| !cityScreen.canChangeState
|| city.isPuppet || city.isInResistance()
|| !city.canPurchase(construction)
|| constructionGoldCost > city.civInfo.gold )
@ -362,7 +363,7 @@ class ConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBaseScre
private fun getRaisePriorityButton(constructionQueueIndex: Int, name: String, city: CityInfo): Table {
val tab = Table()
tab.add(ImageGetter.getImage("OtherIcons/Up").surroundWithCircle(40f))
if (UncivGame.Current.worldScreen.isPlayersTurn && !city.isPuppet) {
if (cityScreen.canChangeState && !city.isPuppet) {
tab.touchable = Touchable.enabled
tab.onClick {
tab.touchable = Touchable.disabled
@ -379,7 +380,7 @@ class ConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBaseScre
private fun getLowerPriorityButton(constructionQueueIndex: Int, name: String, city: CityInfo): Table {
val tab = Table()
tab.add(ImageGetter.getImage("OtherIcons/Down").surroundWithCircle(40f))
if (UncivGame.Current.worldScreen.isPlayersTurn && !city.isPuppet) {
if (cityScreen.canChangeState && !city.isPuppet) {
tab.touchable = Touchable.enabled
tab.onClick {
tab.touchable = Touchable.disabled
@ -396,7 +397,7 @@ class ConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBaseScre
private fun getRemoveFromQueueButton(constructionQueueIndex: Int, city: CityInfo): Table {
val tab = Table()
tab.add(ImageGetter.getImage("OtherIcons/Stop").surroundWithCircle(40f))
if (UncivGame.Current.worldScreen.isPlayersTurn && !city.isPuppet) {
if (cityScreen.canChangeState && !city.isPuppet) {
tab.touchable = Touchable.enabled
tab.onClick {
tab.touchable = Touchable.disabled

View file

@ -22,9 +22,9 @@ class SpecialistAllocationTable(val cityScreen: CityScreen): Table(CameraStageBa
val assignedSpecialists = cityInfo.population.specialists.get(stat).toInt()
val maxSpecialists = cityInfo.population.getMaxSpecialists().get(stat).toInt()
add(getUnassignButton(assignedSpecialists,stat))
if (cityScreen.canChangeState) add(getUnassignButton(assignedSpecialists,stat))
add(getAllocationTable(assignedSpecialists, maxSpecialists, stat)).pad(10f)
add(getAssignButton(assignedSpecialists,maxSpecialists,stat))
if (cityScreen.canChangeState) add(getAssignButton(assignedSpecialists,maxSpecialists,stat))
addSeparatorVertical().pad(10f)
add(getSpecialistStatsTable(stat)).row()
}

View file

@ -308,7 +308,7 @@ class EmpireOverviewScreen(private val viewingPlayer:CivilizationInfo, defaultPa
viewingPlayer.diplomacy.containsKey(civ.civName)
private fun getDiplomacyGroup(): Group {
val relevantCivs = viewingPlayer.gameInfo.civilizations.filter { !it.isBarbarian() && !it.isCityState() }
val relevantCivs = viewingPlayer.gameInfo.civilizations.filter { it.isMajorCiv() }
val freeWidth = stage.width
val freeHeight = stage.height - topTable.height
val group = Group()
@ -334,8 +334,8 @@ class EmpireOverviewScreen(private val viewingPlayer:CivilizationInfo, defaultPa
for(civ in relevantCivs.filter { playerKnows(it) && !it.isDefeated() })
for(diplomacy in civ.diplomacy.values.
filter { !it.otherCiv().isBarbarian() && !it.otherCiv().isCityState()
&& playerKnows(it.otherCiv()) && !it.otherCiv().isDefeated()}){
filter { it.otherCiv().isMajorCiv()
&& playerKnows(it.otherCiv()) && !it.otherCiv().isDefeated() }){
val civGroup = civGroups[civ.civName]!!
val otherCivGroup = civGroups[diplomacy.otherCivName]!!

View file

@ -142,7 +142,7 @@ class CityButton(val city: CityInfo, private val tileGroup: WorldTileGroup): Tab
val viewingCiv = worldScreen.viewingCiv
// second tap on the button will go to the city screen
// if this city belongs to you
if (uncivGame.viewEntireMapForDebug || belongsToViewingCiv()) {
if (uncivGame.viewEntireMapForDebug || belongsToViewingCiv() || viewingCiv.isSpectator()) {
uncivGame.setScreen(CityScreen(city))
} else if (viewingCiv.knows(city.civInfo)) {
// If city doesn't belong to you, go directly to its owner's diplomacy screen.
@ -203,15 +203,16 @@ class CityButton(val city: CityInfo, private val tileGroup: WorldTileGroup): Tab
iconTable.add(connectionImage).size(20f).pad(2f).padLeft(5f)
}
iconTable.add(getPopulationGroup(uncivGame.viewEntireMapForDebug || belongsToViewingCiv()))
.padLeft(10f)
iconTable.add(getPopulationGroup(uncivGame.viewEntireMapForDebug
|| belongsToViewingCiv()
|| worldScreen.viewingCiv.isSpectator())).padLeft(10f)
val cityButtonText = city.name
val label = cityButtonText.toLabel(secondaryColor)
iconTable.add(label).pad(10f) // sufficient horizontal padding
.fillY() // provide full-height clicking area
if (uncivGame.viewEntireMapForDebug || belongsToViewingCiv())
if (uncivGame.viewEntireMapForDebug || belongsToViewingCiv() || worldScreen.viewingCiv.isSpectator())
iconTable.add(getConstructionGroup(city.cityConstructions)).padRight(10f).padLeft(10f)
else if (city.civInfo.isMajorCiv()) {
val nationIcon = ImageGetter.getNationIcon(city.civInfo.nation.name)

View file

@ -53,7 +53,7 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() {
private fun updateLeftSideTable() {
leftSideTable.clear()
for (civ in UncivGame.Current.gameInfo.civilizations
.filterNot { it.isDefeated() || it == viewingCiv || it.isBarbarian() }) {
.filterNot { it.isDefeated() || it == viewingCiv || it.isBarbarian() || it.isSpectator() }) {
if (!viewingCiv.knows(civ)) continue
val civIndicator = ImageGetter.getNationIndicator(civ.nation,100f)

View file

@ -41,6 +41,7 @@ import kotlin.concurrent.thread
class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
val gameInfo = game.gameInfo
var isPlayersTurn = viewingCiv == gameInfo.currentPlayerCiv // todo this should be updated when passing turns
val canChangeState = isPlayersTurn && !viewingCiv.isSpectator()
private var waitingForAutosave = false
val mapHolder = WorldMapHolder(this, gameInfo.tileMap)