mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-16 18:59:15 +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:
@ -92,9 +92,9 @@ class CivInfoTransientUpdater(val civInfo: CivilizationInfo) {
|
||||
}
|
||||
|
||||
for (spy in civInfo.espionageManager.spyList) {
|
||||
val spyCity = spy.getLocation(civInfo.gameInfo) ?: continue
|
||||
newViewableTiles.addAll(spyCity.getCenterTile().neighbors)
|
||||
newViewableTiles.add(spyCity.getCenterTile())
|
||||
val spyCity = spy.getLocation() ?: continue
|
||||
if (!spy.isSetUp()) continue // Can't see cities when you haven't set up yet
|
||||
newViewableTiles.addAll(spyCity.getCenterTile().getTilesInDistance(1))
|
||||
}
|
||||
|
||||
civInfo.viewableTiles = newViewableTiles // to avoid concurrent modification problems
|
||||
|
@ -993,6 +993,8 @@ class CivilizationInfo : IsPartOfGameInfoSerialization {
|
||||
religionManager.endTurn(nextTurnStats.faith.toInt())
|
||||
totalFaithForContests += nextTurnStats.faith.toInt()
|
||||
|
||||
espionageManager.endTurn()
|
||||
|
||||
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
|
||||
|
@ -5,10 +5,25 @@ import com.unciv.logic.GameInfo
|
||||
import com.unciv.logic.IsPartOfGameInfoSerialization
|
||||
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 {
|
||||
// `location == null` means that the spy is in its hideout
|
||||
var location: String? = null
|
||||
lateinit var name: String
|
||||
var timeTillActionFinish = 0
|
||||
var action = SpyAction.None
|
||||
|
||||
@Transient
|
||||
lateinit var civInfo: CivilizationInfo
|
||||
|
||||
constructor(name: String) : this() {
|
||||
this.name = name
|
||||
@ -17,15 +32,60 @@ class Spy() : IsPartOfGameInfoSerialization {
|
||||
fun clone(): Spy {
|
||||
val toReturn = Spy(name)
|
||||
toReturn.location = location
|
||||
toReturn.timeTillActionFinish = timeTillActionFinish
|
||||
toReturn.action = action
|
||||
return toReturn
|
||||
}
|
||||
|
||||
fun getLocation(gameInfo: GameInfo): CityInfo? {
|
||||
return gameInfo.getCities().firstOrNull { it.id == location }
|
||||
fun setTransients(civInfo: CivilizationInfo) {
|
||||
this.civInfo = civInfo
|
||||
}
|
||||
|
||||
fun getLocationName(gameInfo: GameInfo): String {
|
||||
return getLocation(gameInfo)?.name ?: Constants.spyHideout
|
||||
fun endTurn() {
|
||||
--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) {
|
||||
this.civInfo = civInfo
|
||||
for (spy in spyList) {
|
||||
spy.setTransients(civInfo)
|
||||
}
|
||||
}
|
||||
|
||||
fun endTurn() {
|
||||
for (spy in spyList)
|
||||
spy.endTurn()
|
||||
}
|
||||
|
||||
private fun getSpyName(): String {
|
||||
|
@ -60,7 +60,7 @@ class ModConstants {
|
||||
// RiverGenerator: river frequency and length bounds
|
||||
var riverCountMultiplier = 0.01f
|
||||
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) {
|
||||
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.unciv.json.fromJsonFile
|
||||
import com.unciv.json.json
|
||||
import com.unciv.logic.civilization.SpyAction
|
||||
import com.unciv.models.metadata.BaseRuleset
|
||||
import com.unciv.models.metadata.LocaleCode
|
||||
import com.unciv.models.ruleset.*
|
||||
@ -124,6 +125,10 @@ object TranslationFileWriter {
|
||||
|
||||
for (uniqueTarget in UniqueTarget.values())
|
||||
linesToTranslate.add("$uniqueTarget = ")
|
||||
|
||||
for (spyAction in SpyAction.values()) {
|
||||
linesToTranslate.add("$spyAction = ")
|
||||
}
|
||||
}
|
||||
|
||||
var countOfTranslatableLines = 0
|
||||
|
@ -9,10 +9,12 @@ import com.unciv.UncivGame
|
||||
import com.unciv.logic.city.CityInfo
|
||||
import com.unciv.logic.civilization.CivilizationInfo
|
||||
import com.unciv.logic.civilization.Spy
|
||||
import com.unciv.logic.civilization.SpyAction
|
||||
import com.unciv.models.translations.tr
|
||||
import com.unciv.ui.images.ImageGetter
|
||||
import com.unciv.ui.pickerscreens.PickerScreen
|
||||
import com.unciv.ui.utils.AutoScrollPane
|
||||
import com.unciv.ui.utils.Fonts
|
||||
import com.unciv.ui.utils.KeyCharAndCode
|
||||
import com.unciv.ui.utils.extensions.addSeparator
|
||||
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 citySelectionTable = Table(skin)
|
||||
private val cityScrollPane = AutoScrollPane(citySelectionTable)
|
||||
private val headerTable = Table(skin)
|
||||
private val middlePanes = Table(skin)
|
||||
|
||||
private var selectedSpyButton: TextButton? = null
|
||||
@ -41,9 +42,6 @@ class EspionageOverviewScreen(val civInfo: CivilizationInfo) : PickerScreen(true
|
||||
private var moveSpyHereButtons = hashMapOf<Button, CityInfo?>()
|
||||
|
||||
init {
|
||||
topTable.add(headerTable)
|
||||
topTable.addSeparator()
|
||||
|
||||
middlePanes.add(spyScrollPane)
|
||||
middlePanes.addSeparatorVertical()
|
||||
middlePanes.add(cityScrollPane)
|
||||
@ -67,11 +65,16 @@ class EspionageOverviewScreen(val civInfo: CivilizationInfo) : PickerScreen(true
|
||||
|
||||
private fun updateSpyList() {
|
||||
spySelectionTable.clear()
|
||||
spySelectionTable.add("Spy".toLabel()).pad(5f)
|
||||
spySelectionTable.add("Location".toLabel()).pad(5f).row()
|
||||
spySelectionTable.add("Spy".toLabel()).pad(10f)
|
||||
spySelectionTable.add("Location".toLabel()).pad(10f)
|
||||
spySelectionTable.add("Action".toLabel()).pad(10f).row()
|
||||
for (spy in civInfo.espionageManager.spyList) {
|
||||
spySelectionTable.add(spy.name.toLabel()).pad(5f)
|
||||
spySelectionTable.add(spy.getLocationName(civInfo.gameInfo).toLabel()).pad(5f)
|
||||
spySelectionTable.add(spy.name.toLabel()).pad(10f)
|
||||
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()
|
||||
moveSpyButton.onClick {
|
||||
@ -160,7 +163,7 @@ class EspionageOverviewScreen(val civInfo: CivilizationInfo) : PickerScreen(true
|
||||
val moveSpyHereButton = Button(skin)
|
||||
moveSpyHereButton.add(ImageGetter.getArrowImage(Align.left).apply { color = Color.WHITE })
|
||||
moveSpyHereButton.onClick {
|
||||
selectedSpy!!.location = city?.id
|
||||
selectedSpy!!.moveTo(city)
|
||||
resetSelection()
|
||||
update()
|
||||
}
|
||||
|
Reference in New Issue
Block a user