mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-20 20:59:18 +07:00
Spies now show their current action and take time to move and set up (#7776)
* Spies now show their current action and take time to move and set up * Fixed tests * Reviews * More reviews
This commit is contained in:
@ -1248,8 +1248,6 @@ Capture [cityName] =
|
|||||||
Our status =
|
Our status =
|
||||||
Global status =
|
Global status =
|
||||||
Rankings =
|
Rankings =
|
||||||
# The \n here means: put a newline (enter) here. If this is omitted, the sidebox in the diplomacy overview will become _really_ wide.
|
|
||||||
# Feel free to replace it with a space and put it between other words in your translation
|
|
||||||
Demographics =
|
Demographics =
|
||||||
Demographic =
|
Demographic =
|
||||||
Rank =
|
Rank =
|
||||||
@ -1257,6 +1255,8 @@ Value =
|
|||||||
Best =
|
Best =
|
||||||
Average =
|
Average =
|
||||||
Worst =
|
Worst =
|
||||||
|
# The \n here means: put a newline (enter) here. If this is omitted, the sidebox in the diplomacy overview will become _really_ wide.
|
||||||
|
# Feel free to replace it with a space and put it between other words in your translation
|
||||||
Turns until the next\ndiplomacy victory vote: [amount] =
|
Turns until the next\ndiplomacy victory vote: [amount] =
|
||||||
Choose a civ to vote for =
|
Choose a civ to vote for =
|
||||||
Choose who should become the world leader and win a Diplomatic Victory! =
|
Choose who should become the world leader and win a Diplomatic Victory! =
|
||||||
|
@ -92,9 +92,9 @@ class CivInfoTransientUpdater(val civInfo: CivilizationInfo) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (spy in civInfo.espionageManager.spyList) {
|
for (spy in civInfo.espionageManager.spyList) {
|
||||||
val spyCity = spy.getLocation(civInfo.gameInfo) ?: continue
|
val spyCity = spy.getLocation() ?: continue
|
||||||
newViewableTiles.addAll(spyCity.getCenterTile().neighbors)
|
if (!spy.isSetUp()) continue // Can't see cities when you haven't set up yet
|
||||||
newViewableTiles.add(spyCity.getCenterTile())
|
newViewableTiles.addAll(spyCity.getCenterTile().getTilesInDistance(1))
|
||||||
}
|
}
|
||||||
|
|
||||||
civInfo.viewableTiles = newViewableTiles // to avoid concurrent modification problems
|
civInfo.viewableTiles = newViewableTiles // to avoid concurrent modification problems
|
||||||
|
@ -993,6 +993,8 @@ class CivilizationInfo : IsPartOfGameInfoSerialization {
|
|||||||
religionManager.endTurn(nextTurnStats.faith.toInt())
|
religionManager.endTurn(nextTurnStats.faith.toInt())
|
||||||
totalFaithForContests += nextTurnStats.faith.toInt()
|
totalFaithForContests += nextTurnStats.faith.toInt()
|
||||||
|
|
||||||
|
espionageManager.endTurn()
|
||||||
|
|
||||||
if (isMajorCiv()) greatPeople.addGreatPersonPoints(getGreatPersonPointsForNextTurn()) // City-states don't get great people!
|
if (isMajorCiv()) greatPeople.addGreatPersonPoints(getGreatPersonPointsForNextTurn()) // City-states don't get great people!
|
||||||
|
|
||||||
for (city in cities.toList()) { // a city can be removed while iterating (if it's being razed) so we need to iterate over a copy
|
for (city in cities.toList()) { // a city can be removed while iterating (if it's being razed) so we need to iterate over a copy
|
||||||
|
@ -5,10 +5,25 @@ import com.unciv.logic.GameInfo
|
|||||||
import com.unciv.logic.IsPartOfGameInfoSerialization
|
import com.unciv.logic.IsPartOfGameInfoSerialization
|
||||||
import com.unciv.logic.city.CityInfo
|
import com.unciv.logic.city.CityInfo
|
||||||
|
|
||||||
|
enum class SpyAction(val stringName: String) {
|
||||||
|
None("None"),
|
||||||
|
Moving("Moving"),
|
||||||
|
EstablishNetwork("Establishing Network"),
|
||||||
|
StealingTech("Stealing Tech"),
|
||||||
|
RiggingElections("Rigging Elections"),
|
||||||
|
CounterIntelligence("Conducting Counter-intelligence")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class Spy() : IsPartOfGameInfoSerialization {
|
class Spy() : IsPartOfGameInfoSerialization {
|
||||||
// `location == null` means that the spy is in its hideout
|
// `location == null` means that the spy is in its hideout
|
||||||
var location: String? = null
|
var location: String? = null
|
||||||
lateinit var name: String
|
lateinit var name: String
|
||||||
|
var timeTillActionFinish = 0
|
||||||
|
var action = SpyAction.None
|
||||||
|
|
||||||
|
@Transient
|
||||||
|
lateinit var civInfo: CivilizationInfo
|
||||||
|
|
||||||
constructor(name: String) : this() {
|
constructor(name: String) : this() {
|
||||||
this.name = name
|
this.name = name
|
||||||
@ -17,15 +32,60 @@ class Spy() : IsPartOfGameInfoSerialization {
|
|||||||
fun clone(): Spy {
|
fun clone(): Spy {
|
||||||
val toReturn = Spy(name)
|
val toReturn = Spy(name)
|
||||||
toReturn.location = location
|
toReturn.location = location
|
||||||
|
toReturn.timeTillActionFinish = timeTillActionFinish
|
||||||
|
toReturn.action = action
|
||||||
return toReturn
|
return toReturn
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getLocation(gameInfo: GameInfo): CityInfo? {
|
fun setTransients(civInfo: CivilizationInfo) {
|
||||||
return gameInfo.getCities().firstOrNull { it.id == location }
|
this.civInfo = civInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getLocationName(gameInfo: GameInfo): String {
|
fun endTurn() {
|
||||||
return getLocation(gameInfo)?.name ?: Constants.spyHideout
|
--timeTillActionFinish
|
||||||
|
if (timeTillActionFinish != 0) return
|
||||||
|
|
||||||
|
when (action) {
|
||||||
|
SpyAction.Moving -> {
|
||||||
|
action = SpyAction.EstablishNetwork
|
||||||
|
timeTillActionFinish = 3 // Dependent on cultural familiarity level if that is ever implemented
|
||||||
|
}
|
||||||
|
SpyAction.EstablishNetwork -> {
|
||||||
|
val location = getLocation()!! // This should be impossible to reach as going to the hideout sets your action to None.
|
||||||
|
action =
|
||||||
|
if (location.civInfo.isCityState()) {
|
||||||
|
SpyAction.RiggingElections
|
||||||
|
} else if (location.civInfo == civInfo) {
|
||||||
|
SpyAction.CounterIntelligence
|
||||||
|
} else {
|
||||||
|
SpyAction.StealingTech
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
++timeTillActionFinish // Not implemented yet, so don't do anything
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun moveTo(cityInfo: CityInfo?) {
|
||||||
|
location = cityInfo?.id
|
||||||
|
if (cityInfo == null) { // Moving to spy hideout
|
||||||
|
action = SpyAction.None
|
||||||
|
timeTillActionFinish = 0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
action = SpyAction.Moving
|
||||||
|
timeTillActionFinish = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isSetUp() = action !in listOf(SpyAction.Moving, SpyAction.None, SpyAction.EstablishNetwork)
|
||||||
|
|
||||||
|
fun getLocation(): CityInfo? {
|
||||||
|
return civInfo.gameInfo.getCities().firstOrNull { it.id == location }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getLocationName(): String {
|
||||||
|
return getLocation()?.name ?: Constants.spyHideout
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,6 +108,14 @@ class EspionageManager : IsPartOfGameInfoSerialization {
|
|||||||
|
|
||||||
fun setTransients(civInfo: CivilizationInfo) {
|
fun setTransients(civInfo: CivilizationInfo) {
|
||||||
this.civInfo = civInfo
|
this.civInfo = civInfo
|
||||||
|
for (spy in spyList) {
|
||||||
|
spy.setTransients(civInfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun endTurn() {
|
||||||
|
for (spy in spyList)
|
||||||
|
spy.endTurn()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getSpyName(): String {
|
private fun getSpyName(): String {
|
||||||
|
@ -60,7 +60,7 @@ class ModConstants {
|
|||||||
// RiverGenerator: river frequency and length bounds
|
// RiverGenerator: river frequency and length bounds
|
||||||
var riverCountMultiplier = 0.01f
|
var riverCountMultiplier = 0.01f
|
||||||
var minRiverLength = 5
|
var minRiverLength = 5
|
||||||
var maxRiverLength = 666 // Do not set < max map radius
|
var maxRiverLength = 666 // Do not set to less than the maximal map radius
|
||||||
|
|
||||||
fun merge(other: ModConstants) {
|
fun merge(other: ModConstants) {
|
||||||
if (other.maxXPfromBarbarians != defaults.maxXPfromBarbarians) maxXPfromBarbarians = other.maxXPfromBarbarians
|
if (other.maxXPfromBarbarians != defaults.maxXPfromBarbarians) maxXPfromBarbarians = other.maxXPfromBarbarians
|
||||||
|
@ -4,6 +4,7 @@ import com.badlogic.gdx.Gdx
|
|||||||
import com.badlogic.gdx.files.FileHandle
|
import com.badlogic.gdx.files.FileHandle
|
||||||
import com.unciv.json.fromJsonFile
|
import com.unciv.json.fromJsonFile
|
||||||
import com.unciv.json.json
|
import com.unciv.json.json
|
||||||
|
import com.unciv.logic.civilization.SpyAction
|
||||||
import com.unciv.models.metadata.BaseRuleset
|
import com.unciv.models.metadata.BaseRuleset
|
||||||
import com.unciv.models.metadata.LocaleCode
|
import com.unciv.models.metadata.LocaleCode
|
||||||
import com.unciv.models.ruleset.*
|
import com.unciv.models.ruleset.*
|
||||||
@ -124,6 +125,10 @@ object TranslationFileWriter {
|
|||||||
|
|
||||||
for (uniqueTarget in UniqueTarget.values())
|
for (uniqueTarget in UniqueTarget.values())
|
||||||
linesToTranslate.add("$uniqueTarget = ")
|
linesToTranslate.add("$uniqueTarget = ")
|
||||||
|
|
||||||
|
for (spyAction in SpyAction.values()) {
|
||||||
|
linesToTranslate.add("$spyAction = ")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var countOfTranslatableLines = 0
|
var countOfTranslatableLines = 0
|
||||||
|
@ -9,10 +9,12 @@ import com.unciv.UncivGame
|
|||||||
import com.unciv.logic.city.CityInfo
|
import com.unciv.logic.city.CityInfo
|
||||||
import com.unciv.logic.civilization.CivilizationInfo
|
import com.unciv.logic.civilization.CivilizationInfo
|
||||||
import com.unciv.logic.civilization.Spy
|
import com.unciv.logic.civilization.Spy
|
||||||
|
import com.unciv.logic.civilization.SpyAction
|
||||||
import com.unciv.models.translations.tr
|
import com.unciv.models.translations.tr
|
||||||
import com.unciv.ui.images.ImageGetter
|
import com.unciv.ui.images.ImageGetter
|
||||||
import com.unciv.ui.pickerscreens.PickerScreen
|
import com.unciv.ui.pickerscreens.PickerScreen
|
||||||
import com.unciv.ui.utils.AutoScrollPane
|
import com.unciv.ui.utils.AutoScrollPane
|
||||||
|
import com.unciv.ui.utils.Fonts
|
||||||
import com.unciv.ui.utils.KeyCharAndCode
|
import com.unciv.ui.utils.KeyCharAndCode
|
||||||
import com.unciv.ui.utils.extensions.addSeparator
|
import com.unciv.ui.utils.extensions.addSeparator
|
||||||
import com.unciv.ui.utils.extensions.addSeparatorVertical
|
import com.unciv.ui.utils.extensions.addSeparatorVertical
|
||||||
@ -31,7 +33,6 @@ class EspionageOverviewScreen(val civInfo: CivilizationInfo) : PickerScreen(true
|
|||||||
private val spyScrollPane = AutoScrollPane(spySelectionTable)
|
private val spyScrollPane = AutoScrollPane(spySelectionTable)
|
||||||
private val citySelectionTable = Table(skin)
|
private val citySelectionTable = Table(skin)
|
||||||
private val cityScrollPane = AutoScrollPane(citySelectionTable)
|
private val cityScrollPane = AutoScrollPane(citySelectionTable)
|
||||||
private val headerTable = Table(skin)
|
|
||||||
private val middlePanes = Table(skin)
|
private val middlePanes = Table(skin)
|
||||||
|
|
||||||
private var selectedSpyButton: TextButton? = null
|
private var selectedSpyButton: TextButton? = null
|
||||||
@ -41,9 +42,6 @@ class EspionageOverviewScreen(val civInfo: CivilizationInfo) : PickerScreen(true
|
|||||||
private var moveSpyHereButtons = hashMapOf<Button, CityInfo?>()
|
private var moveSpyHereButtons = hashMapOf<Button, CityInfo?>()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
topTable.add(headerTable)
|
|
||||||
topTable.addSeparator()
|
|
||||||
|
|
||||||
middlePanes.add(spyScrollPane)
|
middlePanes.add(spyScrollPane)
|
||||||
middlePanes.addSeparatorVertical()
|
middlePanes.addSeparatorVertical()
|
||||||
middlePanes.add(cityScrollPane)
|
middlePanes.add(cityScrollPane)
|
||||||
@ -67,11 +65,16 @@ class EspionageOverviewScreen(val civInfo: CivilizationInfo) : PickerScreen(true
|
|||||||
|
|
||||||
private fun updateSpyList() {
|
private fun updateSpyList() {
|
||||||
spySelectionTable.clear()
|
spySelectionTable.clear()
|
||||||
spySelectionTable.add("Spy".toLabel()).pad(5f)
|
spySelectionTable.add("Spy".toLabel()).pad(10f)
|
||||||
spySelectionTable.add("Location".toLabel()).pad(5f).row()
|
spySelectionTable.add("Location".toLabel()).pad(10f)
|
||||||
|
spySelectionTable.add("Action".toLabel()).pad(10f).row()
|
||||||
for (spy in civInfo.espionageManager.spyList) {
|
for (spy in civInfo.espionageManager.spyList) {
|
||||||
spySelectionTable.add(spy.name.toLabel()).pad(5f)
|
spySelectionTable.add(spy.name.toLabel()).pad(10f)
|
||||||
spySelectionTable.add(spy.getLocationName(civInfo.gameInfo).toLabel()).pad(5f)
|
spySelectionTable.add(spy.getLocationName().toLabel()).pad(10f)
|
||||||
|
val actionString =
|
||||||
|
if (spy.action == SpyAction.None) SpyAction.None.stringName
|
||||||
|
else "[${spy.action.stringName}] ${spy.timeTillActionFinish}${Fonts.turn}"
|
||||||
|
spySelectionTable.add(actionString.toLabel()).pad(10f)
|
||||||
|
|
||||||
val moveSpyButton = "Move".toTextButton()
|
val moveSpyButton = "Move".toTextButton()
|
||||||
moveSpyButton.onClick {
|
moveSpyButton.onClick {
|
||||||
@ -160,7 +163,7 @@ class EspionageOverviewScreen(val civInfo: CivilizationInfo) : PickerScreen(true
|
|||||||
val moveSpyHereButton = Button(skin)
|
val moveSpyHereButton = Button(skin)
|
||||||
moveSpyHereButton.add(ImageGetter.getArrowImage(Align.left).apply { color = Color.WHITE })
|
moveSpyHereButton.add(ImageGetter.getArrowImage(Align.left).apply { color = Color.WHITE })
|
||||||
moveSpyHereButton.onClick {
|
moveSpyHereButton.onClick {
|
||||||
selectedSpy!!.location = city?.id
|
selectedSpy!!.moveTo(city)
|
||||||
resetSelection()
|
resetSelection()
|
||||||
update()
|
update()
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user