mirror of
https://github.com/yairm210/Unciv.git
synced 2025-03-09 04:09:35 +07:00
Espionage Uniques, Buildings and Policy (#11401)
* Added OneTimeSpiesLevelUp, OneTimeGainSpy, SpyEffectiveness, EnemySpyEffectiveness and HiddenWithoutEspionage Uniques * Spy effectiveness affects stealing tech and rigging elections * Fixed HiddenWithoutEspionage * Added Constabulary and Police Station * Added cityFilter to SpyEffectiveness * Added national Intelligence agency * Added Great Firewall * Fixed great firewall having a float value * EspionageManager addSpy now returns Spy instead of name * Added some simple espionage tests * Fixed OneTimeSpiesLevelUp still wanting parameter * Spy efficiency occurs after skill modifier * Added another test * Added Police State spy efficiency reduction unique * Fixed "Hidden when espionage is disabled" wording * Fixed "effectiveness" wording * Changed "enemy spy effectiveness" unique to use negative matters * Spy effectiveness only affect tech steal rate * Changed "Gain an extra spy" and "Promotes all spies" uniques * Removed Police State comment that is no longer accurate * Changed spy effectiveness to be multiplicative
This commit is contained in:
parent
35c3f7b191
commit
ef9965e218
@ -709,6 +709,14 @@
|
||||
"requiredBuilding": "Market",
|
||||
"requiredTech": "Banking"
|
||||
},
|
||||
{
|
||||
"name": "Constabulary",
|
||||
"cost": 160,
|
||||
"maintenance": 1,
|
||||
"hurryCostModifier": 10,
|
||||
"uniques": ["Hidden when espionage is disabled", "[-25]% enemy spy effectiveness [in this city]"],
|
||||
"requiredTech": "Banking"
|
||||
},
|
||||
// will be introduced in BNW expansion pack
|
||||
// {
|
||||
// "name": "Hanse",
|
||||
@ -934,6 +942,15 @@
|
||||
"uniques": ["Must be on [River]","[+1 Production] from [River] tiles [in this city]"],
|
||||
"requiredTech": "Electricity"
|
||||
},
|
||||
{
|
||||
"name": "Police Station",
|
||||
"cost": 300,
|
||||
"maintenance": 1,
|
||||
"hurryCostModifier": 10,
|
||||
"uniques": ["Hidden when espionage is disabled", "[-25]% enemy spy effectiveness [in this city]"],
|
||||
"requiredBuilding": "Constabulary",
|
||||
"requiredTech": "Electricity"
|
||||
},
|
||||
|
||||
// Modern Era
|
||||
|
||||
@ -964,6 +981,15 @@
|
||||
"requiredTech": "Radio",
|
||||
"quote": "'We live only to discover beauty, all else is a form of waiting' - Kahlil Gibran"
|
||||
},
|
||||
{
|
||||
"name": "National Intelligence Agency",
|
||||
"cost": 120,
|
||||
"culture": 1,
|
||||
"isNationalWonder": true,
|
||||
"uniques": ["Hidden when espionage is disabled", "Gain an extra spy", "Promotes all spies", "[-15]% enemy spy effectiveness [in this city]",
|
||||
"Only available <if [Police Station] is constructed in all [non-[Puppeted]] cities>", "Cost increases by [30] per owned city"],
|
||||
"requiredTech": "Radio"
|
||||
},
|
||||
{
|
||||
"name": "Military Base",
|
||||
"cityStrength": 12,
|
||||
@ -1083,6 +1109,13 @@
|
||||
"Hidden when [Scientific] Victory is disabled", "Cannot be hurried"],
|
||||
"requiredTech": "Rocketry"
|
||||
},
|
||||
{
|
||||
"name": "Great Firewall",
|
||||
"isWonder": true,
|
||||
"uniques": ["Hidden when espionage is disabled", "[-99]% enemy spy effectiveness [in this city]",
|
||||
"[-25]% enemy spy effectiveness [in all cities]",],
|
||||
"requiredTech": "Computers"
|
||||
},
|
||||
|
||||
// Information Era
|
||||
|
||||
|
@ -577,9 +577,9 @@
|
||||
"name": "Police State",
|
||||
"uniques": [
|
||||
"[+3 Happiness] from every [Courthouse]",
|
||||
"[+100]% Production when constructing [Courthouse] buildings [in all cities]"
|
||||
"[+100]% Production when constructing [Courthouse] buildings [in all cities]",
|
||||
"[-25]% enemy spy effectiveness [in all cities]"
|
||||
],
|
||||
// There are also some uniques regarding espoinage, which as of this writing is not yet implemented
|
||||
"requires": ["Militarism"],
|
||||
"row": 2,
|
||||
"column": 4
|
||||
|
@ -41,12 +41,12 @@ class EspionageManager : IsPartOfGameInfoSerialization {
|
||||
return validSpyNames.random()
|
||||
}
|
||||
|
||||
fun addSpy(): String {
|
||||
fun addSpy(): Spy {
|
||||
val spyName = getSpyName()
|
||||
val newSpy = Spy(spyName)
|
||||
newSpy.setTransients(civInfo)
|
||||
spyList.add(newSpy)
|
||||
return spyName
|
||||
return newSpy
|
||||
}
|
||||
|
||||
fun getTilesVisibleViaSpies(): Sequence<Tile> {
|
||||
|
@ -8,6 +8,9 @@ import com.unciv.logic.civilization.Civilization
|
||||
import com.unciv.logic.civilization.NotificationCategory
|
||||
import com.unciv.logic.civilization.NotificationIcon
|
||||
import com.unciv.logic.civilization.managers.EspionageManager
|
||||
import com.unciv.models.ruleset.unique.StateForConditionals
|
||||
import com.unciv.models.ruleset.unique.Unique
|
||||
import com.unciv.models.ruleset.unique.UniqueType
|
||||
import kotlin.random.Random
|
||||
|
||||
|
||||
@ -100,8 +103,10 @@ class Spy() : IsPartOfGameInfoSerialization {
|
||||
return
|
||||
}
|
||||
val techStealCost = stealableTechs.maxOfOrNull { civInfo.gameInfo.ruleset.technologies[it]!!.cost }!!
|
||||
var progressThisTurn = getLocation()!!.cityStats.currentCityStats.science
|
||||
// 33% spy bonus for each level
|
||||
val progressThisTurn = getLocation()!!.cityStats.currentCityStats.science * (rank + 2f) / 3f
|
||||
progressThisTurn *= (rank + 2f) / 3f
|
||||
progressThisTurn *= getEfficiencyModifier().toFloat()
|
||||
progressTowardsStealingTech += progressThisTurn.toInt()
|
||||
if (progressTowardsStealingTech > techStealCost) {
|
||||
stealTech()
|
||||
@ -120,7 +125,7 @@ class Spy() : IsPartOfGameInfoSerialization {
|
||||
val oldSpyName = name
|
||||
name = espionageManager.getSpyName()
|
||||
action = SpyAction.None
|
||||
civInfo.addNotification("We have recruited a new spy name [$name] after [$oldSpyName] was killed.",
|
||||
civInfo.addNotification("We have recruited a new spy name [$name] after [$oldSpyName] was killed.",
|
||||
NotificationCategory.Espionage, NotificationIcon.Spy)
|
||||
}
|
||||
SpyAction.CounterIntelligence -> {
|
||||
@ -129,7 +134,7 @@ class Spy() : IsPartOfGameInfoSerialization {
|
||||
// Once turnRemainingForAction is <= 0 the spy won't be considered to be doing work any more
|
||||
--turnsRemainingForAction
|
||||
return
|
||||
}
|
||||
}
|
||||
else -> return // Not implemented yet, so don't do anything
|
||||
}
|
||||
}
|
||||
@ -157,7 +162,6 @@ class Spy() : IsPartOfGameInfoSerialization {
|
||||
// Subtract the experience of the counter inteligence spies
|
||||
val defendingSpy = city.civ.espionageManager.getSpyAssignedToCity(city)
|
||||
spyResult += defendingSpy?.getSkillModifier() ?: 0
|
||||
//TODO: Add policies modifier here
|
||||
|
||||
val detectionString = when {
|
||||
spyResult < 0 -> null // Not detected
|
||||
@ -228,7 +232,7 @@ class Spy() : IsPartOfGameInfoSerialization {
|
||||
action = SpyAction.Moving
|
||||
turnsRemainingForAction = 1
|
||||
}
|
||||
|
||||
|
||||
fun canMoveTo(city: City): Boolean {
|
||||
if (getLocation() == city) return true
|
||||
if (!city.getCenterTile().isVisible(civInfo)) return false
|
||||
@ -238,7 +242,7 @@ class Spy() : IsPartOfGameInfoSerialization {
|
||||
fun isSetUp() = action !in listOf(SpyAction.Moving, SpyAction.None, SpyAction.EstablishNetwork)
|
||||
|
||||
// Only returns true if the spy is doing a helpful and implemented action
|
||||
fun isDoingWork(): Boolean {
|
||||
fun isDoingWork(): Boolean {
|
||||
if (action == SpyAction.StealingTech || action == SpyAction.EstablishNetwork || action == SpyAction.Moving) return true
|
||||
if (action == SpyAction.RiggingElections && !civInfo.isAtWarWith(getLocation()!!.civ)) return true
|
||||
if (action == SpyAction.CounterIntelligence && turnsRemainingForAction > 0) return true
|
||||
@ -260,9 +264,9 @@ class Spy() : IsPartOfGameInfoSerialization {
|
||||
|
||||
fun levelUpSpy() {
|
||||
//TODO: Make the spy level cap dependent on some unique
|
||||
if (rank >= 3) return
|
||||
if (rank >= 3) return
|
||||
if (getLocation() != null) {
|
||||
civInfo.addNotification("Your spy [$name] has leveled up!", getLocation()!!.location,
|
||||
civInfo.addNotification("Your spy [$name] has leveled up!", getLocation()!!.location,
|
||||
NotificationCategory.Espionage, NotificationIcon.Spy)
|
||||
} else {
|
||||
civInfo.addNotification("Your spy [$name] has leveled up!",
|
||||
@ -275,6 +279,32 @@ class Spy() : IsPartOfGameInfoSerialization {
|
||||
return getSpyRank() * 30
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a friendly and enemy efficiency uniques for the spy at the location
|
||||
* @return a value centered around 100 for the work efficiency of the spy, won't be negative
|
||||
*/
|
||||
fun getEfficiencyModifier(): Double {
|
||||
lateinit var friendlyUniques: Sequence<Unique>
|
||||
lateinit var enemyUniques: Sequence<Unique>
|
||||
if (getLocation() != null) {
|
||||
val city = getLocation()!!
|
||||
if (city.civ == civInfo) {
|
||||
friendlyUniques = city.getMatchingUniques(UniqueType.SpyEffectiveness, StateForConditionals(city), includeCivUniques = true)
|
||||
enemyUniques = sequenceOf()
|
||||
} else {
|
||||
friendlyUniques = civInfo.getMatchingUniques(UniqueType.SpyEffectiveness)
|
||||
enemyUniques = city.getMatchingUniques(UniqueType.EnemySpyEffectiveness, StateForConditionals(city), includeCivUniques = true)
|
||||
}
|
||||
} else {
|
||||
friendlyUniques = civInfo.getMatchingUniques(UniqueType.SpyEffectiveness)
|
||||
enemyUniques = sequenceOf()
|
||||
}
|
||||
var totalEfficiency = 1.0
|
||||
totalEfficiency *= (100.0 + friendlyUniques.sumOf { it.params[0].toInt() }) / 100
|
||||
totalEfficiency *= (100.0 + enemyUniques.sumOf { it.params[0].toInt() }) / 100
|
||||
return totalEfficiency.coerceAtLeast(0.0)
|
||||
}
|
||||
|
||||
fun killSpy() {
|
||||
// We don't actually remove this spy object, we set them as dead and let them revive
|
||||
moveTo(null)
|
||||
@ -282,6 +312,6 @@ class Spy() : IsPartOfGameInfoSerialization {
|
||||
turnsRemainingForAction = 5
|
||||
rank = 1
|
||||
}
|
||||
|
||||
|
||||
fun isAlive(): Boolean = action != SpyAction.Dead
|
||||
}
|
||||
|
@ -315,6 +315,10 @@ class Building : RulesetStatsObject(), INonPerpetualConstruction {
|
||||
if (!civ.gameInfo.isReligionEnabled())
|
||||
yield(RejectionReasonType.DisabledBySetting.toInstance())
|
||||
|
||||
UniqueType.HiddenWithoutEspionage ->
|
||||
if (!civ.gameInfo.isEspionageEnabled())
|
||||
yield(RejectionReasonType.DisabledBySetting.toInstance())
|
||||
|
||||
UniqueType.MaxNumberBuildable ->
|
||||
if (civ.civConstructions.countConstructedObjects(this@Building) >= unique.params[0].toInt())
|
||||
yield(RejectionReasonType.MaxNumberBuildable.toInstance())
|
||||
|
@ -15,6 +15,7 @@ import com.unciv.ui.objectdescriptions.BaseUnitDescriptions
|
||||
import com.unciv.ui.objectdescriptions.BuildingDescriptions
|
||||
import com.unciv.ui.objectdescriptions.ImprovementDescriptions
|
||||
import com.unciv.ui.objectdescriptions.uniquesToCivilopediaTextLines
|
||||
import com.unciv.ui.screens.civilopediascreen.CivilopediaScreen.Companion.showEspionageInCivilopedia
|
||||
import com.unciv.ui.screens.civilopediascreen.CivilopediaScreen.Companion.showReligionInCivilopedia
|
||||
import com.unciv.ui.screens.civilopediascreen.FormattedLine
|
||||
import kotlin.math.pow
|
||||
@ -193,11 +194,13 @@ class Nation : RulesetObject() {
|
||||
|
||||
private fun getUniqueBuildingsText(ruleset: Ruleset) = sequence {
|
||||
val religionEnabled = showReligionInCivilopedia(ruleset)
|
||||
val espionageEnabled = showEspionageInCivilopedia(ruleset)
|
||||
for (building in ruleset.buildings.values) {
|
||||
when {
|
||||
building.uniqueTo != name -> continue
|
||||
building.hasUnique(UniqueType.HiddenFromCivilopedia) -> continue
|
||||
!religionEnabled && building.hasUnique(UniqueType.HiddenWithoutReligion) -> continue
|
||||
!espionageEnabled && building.hasUnique(UniqueType.HiddenWithoutEspionage) -> continue
|
||||
}
|
||||
yield(FormattedLine(separator = true))
|
||||
yield(FormattedLine("{${building.name}} -", link=building.makeLink()))
|
||||
|
@ -804,7 +804,7 @@ object UniqueTriggerActivation {
|
||||
val currentEra = civInfo.getEra().name
|
||||
for (otherCiv in civInfo.gameInfo.getAliveMajorCivs()) {
|
||||
if (currentEra !in otherCiv.espionageManager.erasSpyEarnedFor) {
|
||||
val spyName = otherCiv.espionageManager.addSpy()
|
||||
val spyName = otherCiv.espionageManager.addSpy().name
|
||||
otherCiv.espionageManager.erasSpyEarnedFor.add(currentEra)
|
||||
if (otherCiv == civInfo || otherCiv.knows(civInfo))
|
||||
// We don't tell which civilization entered the new era, as that is done in the notification directly above this one
|
||||
@ -821,6 +821,26 @@ object UniqueTriggerActivation {
|
||||
}
|
||||
}
|
||||
|
||||
UniqueType.OneTimeSpiesLevelUp -> {
|
||||
if (!civInfo.isMajorCiv()) return null
|
||||
if (!civInfo.gameInfo.isEspionageEnabled()) return null
|
||||
|
||||
return {
|
||||
civInfo.espionageManager.spyList.forEach { it.levelUpSpy() }
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
UniqueType.OneTimeGainSpy -> {
|
||||
if (!civInfo.isMajorCiv()) return null
|
||||
if (!civInfo.gameInfo.isEspionageEnabled()) return null
|
||||
|
||||
return {
|
||||
civInfo.espionageManager.addSpy()
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
UniqueType.GainFreeBuildings -> {
|
||||
val freeBuilding = civInfo.getEquivalentBuilding(unique.params[0])
|
||||
val applicableCities =
|
||||
|
@ -227,6 +227,10 @@ enum class UniqueType(
|
||||
MayNotGenerateGreatProphet("May not generate great prophet equivalents naturally", UniqueTarget.Global),
|
||||
FaithCostOfGreatProphetChange("[relativeAmount]% Faith cost of generating Great Prophet equivalents", UniqueTarget.Global),
|
||||
|
||||
/// Espionage
|
||||
SpyEffectiveness("[relativeAmount]% spy effectiveness [cityFilter]", UniqueTarget.Global, UniqueTarget.Global),
|
||||
EnemySpyEffectiveness("[relativeAmount]% enemy spy effectiveness [cityFilter]", UniqueTarget.Global, UniqueTarget.Global),
|
||||
|
||||
/// Things you get at the start of the game
|
||||
StartingTech("Starting tech", UniqueTarget.Tech),
|
||||
StartsWithTech("Starts with [tech]", UniqueTarget.Nation),
|
||||
@ -787,6 +791,8 @@ enum class UniqueType(
|
||||
OneTimeRevealCrudeMap("From a randomly chosen tile [positiveAmount] tiles away from the ruins, reveal tiles up to [positiveAmount] tiles away with [positiveAmount]% chance", UniqueTarget.Ruins),
|
||||
OneTimeGlobalAlert("Triggers the following global alert: [comment]", UniqueTarget.Triggerable), // used in Policy
|
||||
OneTimeGlobalSpiesWhenEnteringEra("Every major Civilization gains a spy once a civilization enters this era", UniqueTarget.Era),
|
||||
OneTimeSpiesLevelUp("Promotes all spies", UniqueTarget.Triggerable), // used in Policies, Buildings
|
||||
OneTimeGainSpy("Gain an extra spy", UniqueTarget.Triggerable), // used in Wonders
|
||||
|
||||
OneTimeUnitHeal("Heal this unit by [positiveAmount] HP", UniqueTarget.UnitTriggerable),
|
||||
OneTimeUnitDamage("This Unit takes [positiveAmount] damage", UniqueTarget.UnitTriggerable),
|
||||
@ -853,6 +859,8 @@ enum class UniqueType(
|
||||
HiddenWithoutReligion("Hidden when religion is disabled",
|
||||
UniqueTarget.Unit, UniqueTarget.Building, UniqueTarget.Ruins, UniqueTarget.Tutorial,
|
||||
flags = UniqueFlag.setOfHiddenToUsers),
|
||||
HiddenWithoutEspionage("Hidden when espionage is disabled", UniqueTarget.Building,
|
||||
flags = UniqueFlag.setOfHiddenToUsers),
|
||||
|
||||
HiddenWithoutVictoryType("Hidden when [victoryType] Victory is disabled", UniqueTarget.Building, UniqueTarget.Unit, flags = UniqueFlag.setOfHiddenToUsers),
|
||||
HiddenFromCivilopedia("Will not be displayed in Civilopedia", *UniqueTarget.Displayable, flags = UniqueFlag.setOfHiddenToUsers),
|
||||
|
@ -309,20 +309,21 @@ object TechnologyDescriptions {
|
||||
civInfo: Civilization?,
|
||||
predicate: (Building) -> Boolean
|
||||
): Sequence<Building> {
|
||||
val (nuclearWeaponsEnabled, religionEnabled) = getNukeAndReligionSwitches(civInfo)
|
||||
val (nuclearWeaponsEnabled, religionEnabled, espionageEnabled) = getNukeAndReligionSwitches(civInfo)
|
||||
return ruleset.buildings.values.asSequence()
|
||||
.filter {
|
||||
predicate(it) // expected to be the most selective, thus tested first
|
||||
&& (it.uniqueTo == civInfo?.civName || it.uniqueTo == null && civInfo?.getEquivalentBuilding(it) == it)
|
||||
&& (nuclearWeaponsEnabled || !it.hasUnique(UniqueType.EnablesNuclearWeapons))
|
||||
&& (religionEnabled || !it.hasUnique(UniqueType.HiddenWithoutReligion))
|
||||
&& (espionageEnabled || !it.hasUnique(UniqueType.HiddenWithoutEspionage))
|
||||
&& !it.hasUnique(UniqueType.HiddenFromCivilopedia)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getNukeAndReligionSwitches(civInfo: Civilization?): Pair<Boolean, Boolean> {
|
||||
if (civInfo == null) return true to true
|
||||
return civInfo.gameInfo.run { gameParameters.nuclearWeaponsEnabled to isReligionEnabled() }
|
||||
private fun getNukeAndReligionSwitches(civInfo: Civilization?): Triple<Boolean, Boolean, Boolean> {
|
||||
if (civInfo == null) return Triple(true, true, true)
|
||||
return civInfo.gameInfo.run { Triple(gameParameters.nuclearWeaponsEnabled, isReligionEnabled(), isEspionageEnabled()) }
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -200,12 +200,14 @@ class CivilopediaScreen(
|
||||
val imageSize = 50f
|
||||
|
||||
val religionEnabled = showReligionInCivilopedia(ruleset)
|
||||
val espionageEnabled = showEspionageInCivilopedia(ruleset)
|
||||
val victoryTypes = game.gameInfo?.gameParameters?.victoryTypes ?: ruleset.victories.keys
|
||||
|
||||
fun shouldBeDisplayed(obj: IHasUniques): Boolean {
|
||||
return when {
|
||||
obj.hasUnique(UniqueType.HiddenFromCivilopedia) -> false
|
||||
(!religionEnabled && obj.hasUnique(UniqueType.HiddenWithoutReligion)) -> false
|
||||
(!espionageEnabled && obj.hasUnique(UniqueType.HiddenWithoutEspionage)) -> false
|
||||
obj.getMatchingUniques(UniqueType.HiddenWithoutVictoryType).any { !victoryTypes.contains(it.params[0]) } -> false
|
||||
else -> true
|
||||
}
|
||||
@ -326,5 +328,11 @@ class CivilopediaScreen(
|
||||
ruleset != null -> ruleset.beliefs.isNotEmpty()
|
||||
else -> true
|
||||
}
|
||||
|
||||
fun showEspionageInCivilopedia(ruleset: Ruleset? = null) = when {
|
||||
UncivGame.isCurrentInitialized() && UncivGame.Current.gameInfo != null ->
|
||||
UncivGame.Current.gameInfo!!.isEspionageEnabled()
|
||||
else -> true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -98,6 +98,7 @@ class WonderInfo {
|
||||
val gameInfo = UncivGame.Current.gameInfo!!
|
||||
val ruleSet = gameInfo.ruleset
|
||||
private val hideReligionItems = !gameInfo.isReligionEnabled()
|
||||
private val hideEspionageItems = !gameInfo.isEspionageEnabled()
|
||||
private val startingObsolete = ruleSet.eras[gameInfo.gameParameters.startingEra]!!.startingObsoleteWonders
|
||||
|
||||
enum class WonderStatus(val label: String) {
|
||||
@ -150,6 +151,7 @@ class WonderInfo {
|
||||
private fun shouldBeDisplayed(viewingPlayer: Civilization, wonder: Building, wonderEra: Int?) = when {
|
||||
wonder.hasUnique(UniqueType.HiddenFromCivilopedia) -> false
|
||||
wonder.hasUnique(UniqueType.HiddenWithoutReligion) && hideReligionItems -> false
|
||||
wonder.hasUnique(UniqueType.HiddenWithoutEspionage) && hideEspionageItems -> false
|
||||
wonder.name in startingObsolete -> false
|
||||
wonder.getMatchingUniques(UniqueType.HiddenWithoutVictoryType)
|
||||
.any { unique ->
|
||||
|
@ -144,6 +144,12 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
|
||||
|
||||
Applicable to: Triggerable
|
||||
|
||||
??? example "Promotes all spies"
|
||||
Applicable to: Triggerable
|
||||
|
||||
??? example "Gain an extra spy"
|
||||
Applicable to: Triggerable
|
||||
|
||||
??? example "Turn this tile into a [terrainName] tile"
|
||||
Example: "Turn this tile into a [Forest] tile"
|
||||
|
||||
@ -758,6 +764,16 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
|
||||
|
||||
Applicable to: Global
|
||||
|
||||
??? example "[relativeAmount]% spy effectiveness [cityFilter]"
|
||||
Example: "[+20]% spy effectiveness [in all cities]"
|
||||
|
||||
Applicable to: Global
|
||||
|
||||
??? example "[relativeAmount]% enemy spy effectiveness [cityFilter]"
|
||||
Example: "[+20]% enemy spy effectiveness [in all cities]"
|
||||
|
||||
Applicable to: Global
|
||||
|
||||
??? example "Triggers victory"
|
||||
Applicable to: Global
|
||||
|
||||
@ -1176,6 +1192,9 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
|
||||
??? example "Hidden when religion is disabled"
|
||||
Applicable to: Building, Unit, Ruins, Tutorial
|
||||
|
||||
??? example "Hidden when espionage is disabled"
|
||||
Applicable to: Building
|
||||
|
||||
??? example "Hidden when [victoryType] Victory is disabled"
|
||||
Example: "Hidden when [Domination] Victory is disabled"
|
||||
|
||||
|
57
tests/src/com/unciv/logic/civilization/EspionageTests.kt
Normal file
57
tests/src/com/unciv/logic/civilization/EspionageTests.kt
Normal file
@ -0,0 +1,57 @@
|
||||
package com.unciv.logic.civilization
|
||||
|
||||
import com.badlogic.gdx.math.Vector2
|
||||
import com.unciv.testing.GdxTestRunner
|
||||
import com.unciv.testing.TestGame
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
@RunWith(GdxTestRunner::class)
|
||||
class EspionageTests {
|
||||
private val testGame = TestGame()
|
||||
|
||||
val civA = testGame.addCiv()
|
||||
val civB = testGame.addCiv()
|
||||
@Before
|
||||
fun setup() {
|
||||
testGame.gameInfo.gameParameters.espionageEnabled = true
|
||||
civA.diplomacyFunctions.makeCivilizationsMeet(civB)
|
||||
testGame.makeHexagonalMap(3)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Espionage manager add spy`() {
|
||||
val espionageManagerA = civA.espionageManager
|
||||
assertEquals(0, espionageManagerA.spyList.size)
|
||||
espionageManagerA.addSpy()
|
||||
assertEquals(1, espionageManagerA.spyList.size)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Espionage check spy effectiveness reduction unique`() {
|
||||
val espionageManagerA = civA.espionageManager
|
||||
val spy = espionageManagerA.addSpy()
|
||||
val city = civB.addCity(Vector2(1f,1f))
|
||||
spy.moveTo(city)
|
||||
assertEquals(1.0, spy.getEfficiencyModifier(), 0.1)
|
||||
city.cityConstructions.addBuilding("Constabulary")
|
||||
assertEquals(0.75, spy.getEfficiencyModifier(), 0.1)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Spy effectiveness can't go below zero`() {
|
||||
val espionageManagerA = civA.espionageManager
|
||||
val spy = espionageManagerA.addSpy()
|
||||
val city = civB.addCity(Vector2(1f,1f))
|
||||
spy.moveTo(city)
|
||||
city.cityConstructions.addBuilding("Constabulary")
|
||||
city.cityConstructions.addBuilding("Police Station")
|
||||
city.cityConstructions.addBuilding("National Intelligence Agency")
|
||||
city.cityConstructions.addBuilding("Great Firewall")
|
||||
assertTrue(spy.getEfficiencyModifier() >= 0)
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user