This commit is contained in:
Yair Morgenstern
2020-07-04 23:33:49 +03:00
10 changed files with 59 additions and 10 deletions

View File

@ -1,4 +1,11 @@
[
//Spectator
{
"name": "Spectator",
"outerColor": [255,255,255]
// "innerColor": [255,255,255]
},
{
//nations
"name": "Babylon",
@ -1015,5 +1022,5 @@
"outerColor": [0,0,0],
"innerColor": [182,0,0]
}
]

View File

@ -77,4 +77,5 @@ object Constants {
const val informationEra = "Information era"
const val futureEra = "Future era"
const val barbarians = "Barbarians"
const val spectator = "Spectator"
}

View File

@ -112,6 +112,7 @@ class GameInfo {
currentPlayer = thisPlayer.civName
currentPlayerCiv = getCivilization(currentPlayer)
if (currentPlayerCiv.isSpectator()) currentPlayerCiv.popupAlerts.clear() // no popups for spectators
// Start our turn immediately before the player can made decisions - affects whether our units can commit automated actions and then be attacked immediately etc.

View File

@ -52,6 +52,12 @@ object GameStarter {
for (tech in gameInfo.getDifficulty().aiFreeTechs)
civInfo.tech.addTechnology(tech)
// add all techs to spectators
if (civInfo.isSpectator())
for (tech in ruleset.technologies.values)
if (!civInfo.tech.isResearched(tech.name))
civInfo.tech.addTechnology(tech.name)
for (tech in ruleset.technologies.values
.filter { ruleset.getEraNumber(it.era()) < ruleset.getEraNumber(gameSetupInfo.gameParameters.startingEra) })
if (!civInfo.tech.isResearched(tech.name))
@ -68,7 +74,8 @@ object GameStarter {
private fun addCivilizations(newGameParameters: GameParameters, gameInfo: GameInfo, ruleset: Ruleset) {
val availableCivNames = Stack<String>()
availableCivNames.addAll(ruleset.nations.filter { !it.value.isCityState() }.keys.shuffled())
// CityState or Spectator civs are not available for Random pick
availableCivNames.addAll(ruleset.nations.filter { it.value.isMajorCiv() }.keys.shuffled())
availableCivNames.removeAll(newGameParameters.players.map { it.chosenCiv })
availableCivNames.remove(Constants.barbarians)
@ -132,8 +139,8 @@ object GameStarter {
}
return availableMilitaryUnits.maxBy { max(it.strength, it.rangedStrength) }!!.name
}
for (civ in gameInfo.civilizations.filter { !it.isBarbarian() }) {
// no starting units for Barbarians and Spectators
for (civ in gameInfo.civilizations.filter { !it.isBarbarian() && !it.isSpectator() }) {
val startingLocation = startingLocations[civ]!!
for (tile in startingLocation.getTilesInDistance(3))
tile.improvement = null // Remove ancient ruins in immediate vicinity

View File

@ -52,6 +52,14 @@ class CivInfoTransientUpdater(val civInfo: CivilizationInfo) {
private fun setNewViewableTiles() {
val newViewableTiles = HashSet<TileInfo>()
// while spectating all map is visible
if (civInfo.isSpectator()) {
val allTiles = civInfo.gameInfo.tileMap.values.toSet()
civInfo.viewableTiles = allTiles
civInfo.viewableInvisibleUnitsTiles = allTiles
return
}
// There are a LOT of tiles usually.
// And making large lists of them just as intermediaries before we shove them into the hashset is very space-inefficient.
// And so, sequences to the rescue!

View File

@ -132,6 +132,7 @@ class CivilizationInfo {
gameInfo.gameParameters.oneCityChallenge)
fun isCurrentPlayer() = gameInfo.getCurrentPlayerCivilization()==this
fun isBarbarian() = nation.isBarbarian()
fun isSpectator() = nation.isSpectator()
fun isCityState(): Boolean = nation.isCityState()
fun getCityStateType(): CityStateType = nation.cityStateType!!
fun isMajorCiv() = nation.isMajorCiv()
@ -269,6 +270,7 @@ class CivilizationInfo {
fun isDefeated()= cities.isEmpty() // No cities
&& exploredTiles.isNotEmpty() // Dirty hack: exploredTiles are empty only before starting units are placed
&& !isBarbarian() // Barbarians can be never defeated
&& !isSpectator() // can't loose in Spectator mode
&& (citiesCreated > 0 || !getCivUnits().any { it.name == Constants.settler })
fun getEra(): String {

View File

@ -47,8 +47,9 @@ class Nation : INamed {
fun getInnerColor(): Color = innerColorObject
fun isCityState()= cityStateType != null
fun isMajorCiv() = !isBarbarian() && !isCityState()
fun isMajorCiv() = !isBarbarian() && !isCityState() &&!isSpectator()
fun isBarbarian() = name== Constants.barbarians
fun isSpectator() = name == Constants.spectator
// This is its own transient because we'll need to check this for every tile-to-tile movement which is harsh
@Transient var forestsAndJunglesAreRoads = false

View File

@ -5,6 +5,7 @@ import com.badlogic.gdx.Gdx
import com.badlogic.gdx.scenes.scene2d.ui.SelectBox
import com.badlogic.gdx.scenes.scene2d.ui.Skin
import com.badlogic.gdx.utils.Array
import com.unciv.Constants
import com.unciv.UncivGame
import com.unciv.logic.*
import com.unciv.logic.civilization.PlayerType
@ -60,6 +61,14 @@ class NewGameScreen(previousScreen:CameraStageBaseScreen, _gameSetupInfo: GameSe
return@onClick
}
if (gameSetupInfo.gameParameters.players.count { it.chosenCiv == Constants.spectator } > 1) {
val noMoreSpectatorsPopup = Popup(this)
noMoreSpectatorsPopup.addGoodSizedLabel("Sorry! No more than one spectator for the moment".tr()).row()
noMoreSpectatorsPopup.addCloseButton()
noMoreSpectatorsPopup.open()
return@onClick
}
if (gameSetupInfo.gameParameters.isOnlineMultiplayer) {
for (player in gameSetupInfo.gameParameters.players.filter { it.playerType == PlayerType.Human }) {
try {

View File

@ -73,12 +73,19 @@ class PlayerPickerTable(val previousScreen: IPreviousScreen, var gameParameters:
playerListTable.add("+".toLabel(Color.BLACK, 30).apply { this.setAlignment(Align.center) }
.surroundWithCircle(50f).onClick {
var player = Player()
if (noRandom) { player = Player(getAvailablePlayerCivs().first().name) }
// no random mode - add first not spectator civ if still available
if (noRandom) {
val availableCiv = getAvailablePlayerCivs().firstOrNull { !it.isSpectator() }
if (availableCiv != null) player = Player(availableCiv.name)
// Spectators only Humans
else player = Player("Spectator").apply { playerType = PlayerType.Human }
}
gameParameters.players.add(player)
update()
}).pad(10f)
}
previousScreen.setRightSideButtonEnabled(gameParameters.players.size > 1)
// can enable start game when more than 1 active player
previousScreen.setRightSideButtonEnabled(gameParameters.players.count{ it.chosenCiv != Constants.spectator } > 1)
}
/**
@ -122,7 +129,9 @@ class PlayerPickerTable(val previousScreen: IPreviousScreen, var gameParameters:
playerTypeTextbutton.onClick {
if (player.playerType == PlayerType.AI)
player.playerType = PlayerType.Human
else player.playerType = PlayerType.AI
// we cannot change Spectator player to AI type, robots not allowed to spectate :(
else if (player.chosenCiv != Constants.spectator)
player.playerType = PlayerType.AI
update()
}
playerTable.add(playerTypeTextbutton).width(100f).pad(5f).right()
@ -223,8 +232,12 @@ class PlayerPickerTable(val previousScreen: IPreviousScreen, var gameParameters:
if (!noRandom) { nationListTable.add(randomPlayerTable).pad(10f).width(nationsPopupWidth).row() }
for (nation in getAvailablePlayerCivs()) {
// don't show current player civ
if (player.chosenCiv == nation.name)
continue
// only humans can spectate, sorry robots
if (player.playerType == PlayerType.AI && nation.isSpectator())
continue
nationListTable.add(NationTable(nation, nationsPopupWidth, previousScreen.ruleset).onClick {
if (previousScreen is GameParametersScreen)
@ -261,7 +274,7 @@ class PlayerPickerTable(val previousScreen: IPreviousScreen, var gameParameters:
var nations = ArrayList<Nation>()
for (nation in previousScreen.ruleset.nations.values
.filter { it.isMajorCiv() }) {
if (gameParameters.players.any { it.chosenCiv == nation.name })
if (gameParameters.players.any { it.chosenCiv == nation.name && it.chosenCiv != Constants.spectator})
continue
nations.add(nation)
}

View File

@ -394,7 +394,7 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
private fun updateDiplomacyButton(civInfo: CivilizationInfo) {
diplomacyButtonWrapper.clear()
if(!civInfo.isDefeated() && civInfo.getKnownCivs()
if(!civInfo.isDefeated() && !civInfo.isSpectator() && civInfo.getKnownCivs()
.filterNot { it==viewingCiv || it.isBarbarian() }
.any()) {
displayTutorial(Tutorial.OtherCivEncountered)