mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-28 14:24:43 -04:00
UniqueType-i-fying UniqueTriggerActivation (#5397)
* UniqueType-i-fying UniqueTriggerActivation * UniqueType-i-fying UniqueTriggerActivation - fix missing param types * UniqueType-i-fying UniqueTriggerActivation - alternate and all params
This commit is contained in:
parent
088e35ff13
commit
2884cbb469
@ -189,7 +189,7 @@ object BattleDamage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unique in attacker.getCivInfo().getMatchingUniques("+[]% attack strength to all [] units for [] turns")) {
|
for (unique in attacker.getCivInfo().getMatchingUniques(UniqueType.TimedAttackStrength)) {
|
||||||
if (attacker.matchesCategory(unique.params[1])) {
|
if (attacker.matchesCategory(unique.params[1])) {
|
||||||
modifiers.add("Temporary Bonus", unique.params[0].toInt())
|
modifiers.add("Temporary Bonus", unique.params[0].toInt())
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,12 @@ package com.unciv.logic.civilization
|
|||||||
|
|
||||||
import com.unciv.logic.city.INonPerpetualConstruction
|
import com.unciv.logic.city.INonPerpetualConstruction
|
||||||
import com.unciv.models.Counter
|
import com.unciv.models.Counter
|
||||||
|
import com.unciv.models.ruleset.unique.UniqueType
|
||||||
import com.unciv.models.stats.Stat
|
import com.unciv.models.stats.Stat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.collections.HashMap
|
import kotlin.collections.HashMap
|
||||||
|
|
||||||
class CivConstructions() {
|
class CivConstructions {
|
||||||
|
|
||||||
@Transient
|
@Transient
|
||||||
lateinit var civInfo: CivilizationInfo
|
lateinit var civInfo: CivilizationInfo
|
||||||
@ -22,16 +23,16 @@ class CivConstructions() {
|
|||||||
// to function properly and forcing this to be an `HashMap<String, HashSet<String>>`
|
// to function properly and forcing this to be an `HashMap<String, HashSet<String>>`
|
||||||
// when loading, even if this wasn't the original type, leading to run-time errors.
|
// when loading, even if this wasn't the original type, leading to run-time errors.
|
||||||
private val freeStatBuildingsProvided: HashMap<String, HashSet<String>> = hashMapOf()
|
private val freeStatBuildingsProvided: HashMap<String, HashSet<String>> = hashMapOf()
|
||||||
|
|
||||||
// Maps buildings to the cities that have received that building
|
// Maps buildings to the cities that have received that building
|
||||||
private val freeSpecificBuildingsProvided: HashMap<String, HashSet<String>> = hashMapOf()
|
private val freeSpecificBuildingsProvided: HashMap<String, HashSet<String>> = hashMapOf()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
for (stat in Stat.values()) {
|
for (stat in Stat.values()) {
|
||||||
freeStatBuildingsProvided[stat.name] = hashSetOf()
|
freeStatBuildingsProvided[stat.name] = hashSetOf()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun clone(): CivConstructions {
|
fun clone(): CivConstructions {
|
||||||
val toReturn = CivConstructions()
|
val toReturn = CivConstructions()
|
||||||
toReturn.civInfo = civInfo
|
toReturn.civInfo = civInfo
|
||||||
@ -41,7 +42,7 @@ class CivConstructions() {
|
|||||||
toReturn.boughtItemsWithIncreasingPrice.add(boughtItemsWithIncreasingPrice.clone())
|
toReturn.boughtItemsWithIncreasingPrice.add(boughtItemsWithIncreasingPrice.clone())
|
||||||
return toReturn
|
return toReturn
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setTransients(civInfo: CivilizationInfo) {
|
fun setTransients(civInfo: CivilizationInfo) {
|
||||||
this.civInfo = civInfo
|
this.civInfo = civInfo
|
||||||
|
|
||||||
@ -53,7 +54,7 @@ class CivConstructions() {
|
|||||||
civInfo.boughtConstructionsWithGloballyIncreasingPrice.clear()
|
civInfo.boughtConstructionsWithGloballyIncreasingPrice.clear()
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
|
|
||||||
// Deprecated variables in civ.policies since 3.16.15, this is replacement code
|
// Deprecated variables in civ.policies since 3.16.15, this is replacement code
|
||||||
if (civInfo.policies.specificBuildingsAdded.isNotEmpty()) {
|
if (civInfo.policies.specificBuildingsAdded.isNotEmpty()) {
|
||||||
for ((building, cities) in civInfo.policies.specificBuildingsAdded) {
|
for ((building, cities) in civInfo.policies.specificBuildingsAdded) {
|
||||||
@ -69,11 +70,11 @@ class CivConstructions() {
|
|||||||
}
|
}
|
||||||
civInfo.policies.specificBuildingsAdded.clear()
|
civInfo.policies.specificBuildingsAdded.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (civInfo.policies.cultureBuildingsAdded.isNotEmpty()) {
|
if (civInfo.policies.cultureBuildingsAdded.isNotEmpty()) {
|
||||||
for ((cityId, building) in civInfo.policies.cultureBuildingsAdded) {
|
for ((cityId, building) in civInfo.policies.cultureBuildingsAdded) {
|
||||||
freeStatBuildingsProvided[Stat.Culture.name]!!.add(cityId)
|
freeStatBuildingsProvided[Stat.Culture.name]!!.add(cityId)
|
||||||
|
|
||||||
if (cityId !in freeBuildings)
|
if (cityId !in freeBuildings)
|
||||||
freeBuildings[cityId] = hashSetOf()
|
freeBuildings[cityId] = hashSetOf()
|
||||||
freeBuildings[cityId]!!.add(building)
|
freeBuildings[cityId]!!.add(building)
|
||||||
@ -82,16 +83,16 @@ class CivConstructions() {
|
|||||||
}
|
}
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
fun startTurn() {
|
fun startTurn() {
|
||||||
tryAddFreeBuildings()
|
tryAddFreeBuildings()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun tryAddFreeBuildings() {
|
fun tryAddFreeBuildings() {
|
||||||
addFreeStatsBuildings()
|
addFreeStatsBuildings()
|
||||||
addFreeSpecificBuildings()
|
addFreeSpecificBuildings()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getFreeBuildings(cityId: String): HashSet<String> {
|
fun getFreeBuildings(cityId: String): HashSet<String> {
|
||||||
val toReturn = freeBuildings[cityId] ?: hashSetOf()
|
val toReturn = freeBuildings[cityId] ?: hashSetOf()
|
||||||
for (city in civInfo.cities) {
|
for (city in civInfo.cities) {
|
||||||
@ -99,36 +100,36 @@ class CivConstructions() {
|
|||||||
}
|
}
|
||||||
return toReturn
|
return toReturn
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addFreeBuilding(cityId: String, building: String) {
|
private fun addFreeBuilding(cityId: String, building: String) {
|
||||||
if (!freeBuildings.containsKey(cityId))
|
if (!freeBuildings.containsKey(cityId))
|
||||||
freeBuildings[cityId] = hashSetOf()
|
freeBuildings[cityId] = hashSetOf()
|
||||||
freeBuildings[cityId]!!.add(building)
|
freeBuildings[cityId]!!.add(building)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addFreeStatsBuildings() {
|
private fun addFreeStatsBuildings() {
|
||||||
val statUniquesData = civInfo.getMatchingUniques("Provides the cheapest [] building in your first [] cities for free")
|
val statUniquesData = civInfo.getMatchingUniques(UniqueType.FreeStatBuildings)
|
||||||
.groupBy { it.params[0] }
|
.groupBy { it.params[0] }
|
||||||
.mapKeys { Stat.valueOf(it.key) }
|
.mapKeys { Stat.valueOf(it.key) }
|
||||||
.mapValues { unique -> unique.value.sumOf { it.params[1].toInt() } }
|
.mapValues { unique -> unique.value.sumOf { it.params[1].toInt() } }
|
||||||
.toMutableMap()
|
.toMutableMap()
|
||||||
|
|
||||||
// Deprecated since 3.16.15
|
// Deprecated since 3.16.15
|
||||||
statUniquesData[Stat.Culture] = (statUniquesData[Stat.Culture] ?: 0) +
|
statUniquesData[Stat.Culture] = (statUniquesData[Stat.Culture] ?: 0) +
|
||||||
civInfo.getMatchingUniques("Immediately creates the cheapest available cultural building in each of your first [] cities for free")
|
civInfo.getMatchingUniques("Immediately creates the cheapest available cultural building in each of your first [] cities for free")
|
||||||
.sumOf { it.params[0].toInt() }
|
.sumOf { it.params[0].toInt() }
|
||||||
//
|
//
|
||||||
|
|
||||||
|
|
||||||
for ((stat, amount) in statUniquesData) {
|
for ((stat, amount) in statUniquesData) {
|
||||||
addFreeStatBuildings(stat, amount)
|
addFreeStatBuildings(stat, amount)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addFreeStatBuildings(stat: Stat, amount: Int) {
|
private fun addFreeStatBuildings(stat: Stat, amount: Int) {
|
||||||
for (city in civInfo.cities.take(amount)) {
|
for (city in civInfo.cities.take(amount)) {
|
||||||
if (freeStatBuildingsProvided[stat.name]!!.contains(city.id) || !city.cityConstructions.hasBuildableStatBuildings(stat)) continue
|
if (freeStatBuildingsProvided[stat.name]!!.contains(city.id) || !city.cityConstructions.hasBuildableStatBuildings(stat)) continue
|
||||||
|
|
||||||
val builtBuilding = city.cityConstructions.addCheapestBuildableStatBuilding(stat)
|
val builtBuilding = city.cityConstructions.addCheapestBuildableStatBuilding(stat)
|
||||||
if (builtBuilding != null) {
|
if (builtBuilding != null) {
|
||||||
freeStatBuildingsProvided[stat.name]!!.add(city.id)
|
freeStatBuildingsProvided[stat.name]!!.add(city.id)
|
||||||
@ -136,9 +137,9 @@ class CivConstructions() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addFreeSpecificBuildings() {
|
private fun addFreeSpecificBuildings() {
|
||||||
val buildingsUniquesData = (civInfo.getMatchingUniques("Provides a [] in your first [] cities for free")
|
val buildingsUniquesData = (civInfo.getMatchingUniques(UniqueType.FreeSpecificBuildings)
|
||||||
// Deprecated since 3.16.15
|
// Deprecated since 3.16.15
|
||||||
+ civInfo.getMatchingUniques("Immediately creates a [] in each of your first [] cities for free")
|
+ civInfo.getMatchingUniques("Immediately creates a [] in each of your first [] cities for free")
|
||||||
//
|
//
|
||||||
@ -149,13 +150,13 @@ class CivConstructions() {
|
|||||||
addFreeBuildings(building, amount)
|
addFreeBuildings(building, amount)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addFreeBuildings(building: String, amount: Int) {
|
private fun addFreeBuildings(building: String, amount: Int) {
|
||||||
for (city in civInfo.cities.take(amount)) {
|
for (city in civInfo.cities.take(amount)) {
|
||||||
if (freeSpecificBuildingsProvided[building]?.contains(city.id) == true || city.cityConstructions.containsBuildingOrEquivalent(building)) continue
|
if (freeSpecificBuildingsProvided[building]?.contains(city.id) == true || city.cityConstructions.containsBuildingOrEquivalent(building)) continue
|
||||||
|
|
||||||
(city.cityConstructions.getConstruction(building) as INonPerpetualConstruction).postBuildEvent(city.cityConstructions)
|
(city.cityConstructions.getConstruction(building) as INonPerpetualConstruction).postBuildEvent(city.cityConstructions)
|
||||||
|
|
||||||
if (!freeSpecificBuildingsProvided.containsKey(building))
|
if (!freeSpecificBuildingsProvided.containsKey(building))
|
||||||
freeSpecificBuildingsProvided[building] = hashSetOf()
|
freeSpecificBuildingsProvided[building] = hashSetOf()
|
||||||
freeSpecificBuildingsProvided[building]!!.add(city.id)
|
freeSpecificBuildingsProvided[building]!!.add(city.id)
|
||||||
@ -163,4 +164,4 @@ class CivConstructions() {
|
|||||||
addFreeBuilding(city.id, building)
|
addFreeBuilding(city.id, building)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -319,7 +319,7 @@ class CivilizationInfo {
|
|||||||
if (unique.params[0] == resource.name)
|
if (unique.params[0] == resource.name)
|
||||||
resourceModifier *= 2f
|
resourceModifier *= 2f
|
||||||
if (resource.resourceType == ResourceType.Strategic) {
|
if (resource.resourceType == ResourceType.Strategic) {
|
||||||
resourceModifier *= 1f + getMatchingUniques("Quantity of strategic resources produced by the empire +[]%")
|
resourceModifier *= 1f + getMatchingUniques(UniqueType.StrategicResourcesIncrease)
|
||||||
.map { it.params[0].toFloat() / 100f }.sum()
|
.map { it.params[0].toFloat() / 100f }.sum()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import com.unciv.logic.civilization.CivilizationInfo
|
|||||||
import com.unciv.models.metadata.Player
|
import com.unciv.models.metadata.Player
|
||||||
import com.unciv.models.ruleset.Nation
|
import com.unciv.models.ruleset.Nation
|
||||||
import com.unciv.models.ruleset.Ruleset
|
import com.unciv.models.ruleset.Ruleset
|
||||||
|
import com.unciv.models.ruleset.unique.UniqueType
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
|
|
||||||
/** An Unciv map with all properties as produced by the [map editor][com.unciv.ui.mapeditor.MapEditorScreen]
|
/** An Unciv map with all properties as produced by the [map editor][com.unciv.ui.mapeditor.MapEditorScreen]
|
||||||
@ -442,12 +443,12 @@ class TileMap {
|
|||||||
for (promotion in unit.baseUnit.promotions)
|
for (promotion in unit.baseUnit.promotions)
|
||||||
unit.promotions.addPromotion(promotion, true)
|
unit.promotions.addPromotion(promotion, true)
|
||||||
|
|
||||||
for (unique in civInfo.getMatchingUniques("[] units gain the [] promotion")) {
|
for (unique in civInfo.getMatchingUniques(UniqueType.UnitsGainPromotion)) {
|
||||||
if (unit.matchesFilter(unique.params[0])) {
|
if (unit.matchesFilter(unique.params[0])) {
|
||||||
unit.promotions.addPromotion(unique.params[1], true)
|
unit.promotions.addPromotion(unique.params[1], true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// And update civ stats, since the new unit changes both unit upkeep and resource consumption
|
// And update civ stats, since the new unit changes both unit upkeep and resource consumption
|
||||||
civInfo.updateStatsForNextTurn()
|
civInfo.updateStatsForNextTurn()
|
||||||
civInfo.updateDetailedCivResources()
|
civInfo.updateDetailedCivResources()
|
||||||
|
@ -15,6 +15,11 @@ enum class UniqueParameterType(val parameterName:String) {
|
|||||||
else null
|
else null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// todo potentially remove if OneTimeRevealSpecificMapTiles changes
|
||||||
|
KeywordAll("'all'") {
|
||||||
|
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset) =
|
||||||
|
if (parameterText == "All") null else UniqueType.UniqueComplianceErrorSeverity.RulesetInvariant
|
||||||
|
},
|
||||||
MapUnitFilter("mapUnitFilter"){
|
MapUnitFilter("mapUnitFilter"){
|
||||||
private val knownValues = setOf("Wounded", "Barbarians", "City-State", "Embarked", "Non-City")
|
private val knownValues = setOf("Wounded", "Barbarians", "City-State", "Embarked", "Non-City")
|
||||||
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
|
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
|
||||||
@ -116,6 +121,13 @@ enum class UniqueParameterType(val parameterName:String) {
|
|||||||
else -> UniqueType.UniqueComplianceErrorSeverity.RulesetSpecific
|
else -> UniqueType.UniqueComplianceErrorSeverity.RulesetSpecific
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Era("era") {
|
||||||
|
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
|
||||||
|
UniqueType.UniqueComplianceErrorSeverity? = when (parameterText) {
|
||||||
|
in ruleset.eras -> null
|
||||||
|
else -> UniqueType.UniqueComplianceErrorSeverity.RulesetSpecific
|
||||||
|
}
|
||||||
|
},
|
||||||
/** Behaves like [Unknown], but states explicitly the parameter is OK and its contents are ignored */
|
/** Behaves like [Unknown], but states explicitly the parameter is OK and its contents are ignored */
|
||||||
Comment("comment") {
|
Comment("comment") {
|
||||||
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
|
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
|
||||||
@ -166,6 +178,8 @@ enum class UniqueParameterType(val parameterName:String) {
|
|||||||
"in City-State cities",
|
"in City-State cities",
|
||||||
"in cities following this religion",
|
"in cities following this religion",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
fun safeValueOf(param: String) = values().firstOrNull { it.parameterName == param } ?: Unknown
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ import com.unciv.logic.city.CityInfo
|
|||||||
import com.unciv.logic.civilization.*
|
import com.unciv.logic.civilization.*
|
||||||
import com.unciv.logic.map.MapUnit
|
import com.unciv.logic.map.MapUnit
|
||||||
import com.unciv.logic.map.TileInfo
|
import com.unciv.logic.map.TileInfo
|
||||||
|
import com.unciv.models.ruleset.unique.UniqueType.*
|
||||||
import com.unciv.models.ruleset.VictoryType
|
import com.unciv.models.ruleset.VictoryType
|
||||||
import com.unciv.models.stats.Stat
|
import com.unciv.models.stats.Stat
|
||||||
import com.unciv.models.translations.fillPlaceholders
|
import com.unciv.models.translations.fillPlaceholders
|
||||||
@ -22,14 +23,14 @@ object UniqueTriggerActivation {
|
|||||||
tile: TileInfo? = null,
|
tile: TileInfo? = null,
|
||||||
notification: String? = null
|
notification: String? = null
|
||||||
): Boolean {
|
): Boolean {
|
||||||
val chosenCity =
|
val chosenCity = cityInfo ?: civInfo.cities.firstOrNull { it.isCapital() }
|
||||||
if (cityInfo != null) cityInfo
|
|
||||||
else civInfo.cities.firstOrNull { it.isCapital() }
|
|
||||||
val tileBasedRandom =
|
val tileBasedRandom =
|
||||||
if (tile != null) Random(tile.position.toString().hashCode())
|
if (tile != null) Random(tile.position.toString().hashCode())
|
||||||
else Random(-550) // Very random indeed
|
else Random(-550) // Very random indeed
|
||||||
when (unique.placeholderText) {
|
|
||||||
"Free [] appears" -> {
|
@Suppress("NON_EXHAUSTIVE_WHEN") // Yes we're not treating all types here
|
||||||
|
when (unique.type) {
|
||||||
|
OneTimeFreeUnit -> {
|
||||||
val unitName = unique.params[0]
|
val unitName = unique.params[0]
|
||||||
val unit = civInfo.gameInfo.ruleSet.units[unitName]
|
val unit = civInfo.gameInfo.ruleSet.units[unitName]
|
||||||
if (chosenCity == null || unit == null || (unit.uniques.contains("Founds a new city") && civInfo.isOneCityChallenger()))
|
if (chosenCity == null || unit == null || (unit.uniques.contains("Founds a new city") && civInfo.isOneCityChallenger()))
|
||||||
@ -45,7 +46,7 @@ object UniqueTriggerActivation {
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
"[] free [] units appear" -> {
|
OneTimeAmountFreeUnits -> {
|
||||||
val unitName = unique.params[1]
|
val unitName = unique.params[1]
|
||||||
val unit = civInfo.gameInfo.ruleSet.units[unitName]
|
val unit = civInfo.gameInfo.ruleSet.units[unitName]
|
||||||
if (chosenCity == null || unit == null || (unit.uniques.contains("Founds a new city") && civInfo.isOneCityChallenger()))
|
if (chosenCity == null || unit == null || (unit.uniques.contains("Founds a new city") && civInfo.isOneCityChallenger()))
|
||||||
@ -66,8 +67,7 @@ object UniqueTriggerActivation {
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// Differs from "Free [] appears" in that it spawns near the ruins instead of in a city
|
OneTimeFreeUnitRuins -> {
|
||||||
"Free [] found in the ruins" -> {
|
|
||||||
val unit = civInfo.getEquivalentUnit(unique.params[0])
|
val unit = civInfo.getEquivalentUnit(unique.params[0])
|
||||||
val placingTile =
|
val placingTile =
|
||||||
tile ?: civInfo.cities.random().getCenterTile()
|
tile ?: civInfo.cities.random().getCenterTile()
|
||||||
@ -88,8 +88,8 @@ object UniqueTriggerActivation {
|
|||||||
return placedUnit != null
|
return placedUnit != null
|
||||||
}
|
}
|
||||||
|
|
||||||
// spectators get all techs at start of game, and if (in a mod) a tech gives a free policy, the game gets stuck on the policy picker screen
|
OneTimeFreePolicy -> {
|
||||||
"Free Social Policy" -> {
|
// spectators get all techs at start of game, and if (in a mod) a tech gives a free policy, the game gets stuck on the policy picker screen
|
||||||
if (civInfo.isSpectator()) return false
|
if (civInfo.isSpectator()) return false
|
||||||
civInfo.policies.freePolicies++
|
civInfo.policies.freePolicies++
|
||||||
if (notification != null) {
|
if (notification != null) {
|
||||||
@ -97,7 +97,7 @@ object UniqueTriggerActivation {
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
"[] Free Social Policies" -> {
|
OneTimeAmountFreePolicies -> {
|
||||||
if (civInfo.isSpectator()) return false
|
if (civInfo.isSpectator()) return false
|
||||||
civInfo.policies.freePolicies += unique.params[0].toInt()
|
civInfo.policies.freePolicies += unique.params[0].toInt()
|
||||||
if (notification != null) {
|
if (notification != null) {
|
||||||
@ -105,14 +105,14 @@ object UniqueTriggerActivation {
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
"Empire enters golden age" -> {
|
OneTimeEnterGoldenAge -> {
|
||||||
civInfo.goldenAges.enterGoldenAge()
|
civInfo.goldenAges.enterGoldenAge()
|
||||||
if (notification != null) {
|
if (notification != null) {
|
||||||
civInfo.addNotification(notification, NotificationIcon.Happiness)
|
civInfo.addNotification(notification, NotificationIcon.Happiness)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
"Free Great Person" -> {
|
OneTimeFreeGreatPerson -> {
|
||||||
if (civInfo.isSpectator()) return false
|
if (civInfo.isSpectator()) return false
|
||||||
if (civInfo.isPlayerCivilization()) {
|
if (civInfo.isPlayerCivilization()) {
|
||||||
civInfo.greatPeople.freeGreatPeople++
|
civInfo.greatPeople.freeGreatPeople++
|
||||||
@ -139,7 +139,7 @@ object UniqueTriggerActivation {
|
|||||||
return civInfo.addUnit(greatPerson.name, chosenCity) != null
|
return civInfo.addUnit(greatPerson.name, chosenCity) != null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"[] population []" -> {
|
OneTimeGainPopulation -> {
|
||||||
val citiesWithPopulationChanged: MutableList<Vector2> = mutableListOf()
|
val citiesWithPopulationChanged: MutableList<Vector2> = mutableListOf()
|
||||||
for (city in civInfo.cities) {
|
for (city in civInfo.cities) {
|
||||||
if (city.matchesFilter(unique.params[1])) {
|
if (city.matchesFilter(unique.params[1])) {
|
||||||
@ -155,7 +155,7 @@ object UniqueTriggerActivation {
|
|||||||
)
|
)
|
||||||
return citiesWithPopulationChanged.isNotEmpty()
|
return citiesWithPopulationChanged.isNotEmpty()
|
||||||
}
|
}
|
||||||
"[] population in a random city" -> {
|
OneTimeGainPopulationRandomCity -> {
|
||||||
if (civInfo.cities.isEmpty()) return false
|
if (civInfo.cities.isEmpty()) return false
|
||||||
val randomCity = civInfo.cities.random(tileBasedRandom)
|
val randomCity = civInfo.cities.random(tileBasedRandom)
|
||||||
randomCity.population.addPopulation(unique.params[0].toInt())
|
randomCity.population.addPopulation(unique.params[0].toInt())
|
||||||
@ -173,7 +173,7 @@ object UniqueTriggerActivation {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
"Free Technology" -> {
|
OneTimeFreeTech -> {
|
||||||
if (civInfo.isSpectator()) return false
|
if (civInfo.isSpectator()) return false
|
||||||
civInfo.tech.freeTechs += 1
|
civInfo.tech.freeTechs += 1
|
||||||
if (notification != null) {
|
if (notification != null) {
|
||||||
@ -181,7 +181,7 @@ object UniqueTriggerActivation {
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
"[] Free Technologies" -> {
|
OneTimeAmountFreeTechs -> {
|
||||||
if (civInfo.isSpectator()) return false
|
if (civInfo.isSpectator()) return false
|
||||||
civInfo.tech.freeTechs += unique.params[0].toInt()
|
civInfo.tech.freeTechs += unique.params[0].toInt()
|
||||||
if (notification != null) {
|
if (notification != null) {
|
||||||
@ -189,7 +189,7 @@ object UniqueTriggerActivation {
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
"[] free random researchable Tech(s) from the []" -> {
|
OneTimeFreeTechRuins -> {
|
||||||
val researchableTechsFromThatEra = civInfo.gameInfo.ruleSet.technologies.values
|
val researchableTechsFromThatEra = civInfo.gameInfo.ruleSet.technologies.values
|
||||||
.filter {
|
.filter {
|
||||||
(it.column!!.era == unique.params[1] || unique.params[1] == "any era")
|
(it.column!!.era == unique.params[1] || unique.params[1] == "any era")
|
||||||
@ -214,7 +214,7 @@ object UniqueTriggerActivation {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
"Quantity of strategic resources produced by the empire increased by 100%" -> {
|
StrategicResourcesIncrease -> {
|
||||||
civInfo.updateDetailedCivResources()
|
civInfo.updateDetailedCivResources()
|
||||||
if (notification != null) {
|
if (notification != null) {
|
||||||
civInfo.addNotification(
|
civInfo.addNotification(
|
||||||
@ -224,7 +224,8 @@ object UniqueTriggerActivation {
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
"+[]% attack strength to all [] Units for [] turns" -> {
|
|
||||||
|
TimedAttackStrength -> {
|
||||||
civInfo.temporaryUniques.add(Pair(unique, unique.params[2].toInt()))
|
civInfo.temporaryUniques.add(Pair(unique, unique.params[2].toInt()))
|
||||||
if (notification != null) {
|
if (notification != null) {
|
||||||
civInfo.addNotification(notification, NotificationIcon.War)
|
civInfo.addNotification(notification, NotificationIcon.War)
|
||||||
@ -232,7 +233,7 @@ object UniqueTriggerActivation {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
"Reveals the entire map" -> {
|
OneTimeRevealEntireMap -> {
|
||||||
if (notification != null) {
|
if (notification != null) {
|
||||||
civInfo.addNotification(notification, "UnitIcons/Scout")
|
civInfo.addNotification(notification, "UnitIcons/Scout")
|
||||||
}
|
}
|
||||||
@ -240,7 +241,7 @@ object UniqueTriggerActivation {
|
|||||||
civInfo.gameInfo.tileMap.values.asSequence().map { it.position })
|
civInfo.gameInfo.tileMap.values.asSequence().map { it.position })
|
||||||
}
|
}
|
||||||
|
|
||||||
"[] units gain the [] promotion" -> {
|
UnitsGainPromotion -> {
|
||||||
val filter = unique.params[0]
|
val filter = unique.params[0]
|
||||||
val promotion = unique.params[1]
|
val promotion = unique.params[1]
|
||||||
|
|
||||||
@ -266,7 +267,7 @@ object UniqueTriggerActivation {
|
|||||||
return promotedUnitLocations.isNotEmpty()
|
return promotedUnitLocations.isNotEmpty()
|
||||||
}
|
}
|
||||||
|
|
||||||
"Allied City-States will occasionally gift Great People" -> {
|
CityStateCanGiftGreatPeople -> {
|
||||||
civInfo.addFlag(
|
civInfo.addFlag(
|
||||||
CivFlags.CityStateGreatPersonGift.name,
|
CivFlags.CityStateGreatPersonGift.name,
|
||||||
civInfo.turnsForGreatPersonFromCityState() / 2
|
civInfo.turnsForGreatPersonFromCityState() / 2
|
||||||
@ -292,7 +293,7 @@ object UniqueTriggerActivation {
|
|||||||
// Note that the way this is implemented now, this unique does NOT stack
|
// Note that the way this is implemented now, this unique does NOT stack
|
||||||
// I could parametrize the [Allied], but eh.
|
// I could parametrize the [Allied], but eh.
|
||||||
|
|
||||||
"Gain [] []" -> {
|
OneTimeGainStat -> {
|
||||||
if (Stat.values().none { it.name == unique.params[1] }) return false
|
if (Stat.values().none { it.name == unique.params[1] }) return false
|
||||||
val stat = Stat.valueOf(unique.params[1])
|
val stat = Stat.valueOf(unique.params[1])
|
||||||
|
|
||||||
@ -305,7 +306,7 @@ object UniqueTriggerActivation {
|
|||||||
civInfo.addNotification(notification, stat.notificationIcon)
|
civInfo.addNotification(notification, stat.notificationIcon)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
"Gain []-[] []" -> {
|
OneTimeGainStatRange -> {
|
||||||
if (Stat.values().none { it.name == unique.params[2] }) return false
|
if (Stat.values().none { it.name == unique.params[2] }) return false
|
||||||
val stat = Stat.valueOf(unique.params[2])
|
val stat = Stat.valueOf(unique.params[2])
|
||||||
|
|
||||||
@ -334,7 +335,7 @@ object UniqueTriggerActivation {
|
|||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
"Gain enough Faith for a Pantheon" -> {
|
OneTimeGainPantheon -> {
|
||||||
if (civInfo.religionManager.religionState != ReligionState.None) return false
|
if (civInfo.religionManager.religionState != ReligionState.None) return false
|
||||||
val gainedFaith = civInfo.religionManager.faithForPantheon(2)
|
val gainedFaith = civInfo.religionManager.faithForPantheon(2)
|
||||||
if (gainedFaith == 0) return false
|
if (gainedFaith == 0) return false
|
||||||
@ -351,7 +352,7 @@ object UniqueTriggerActivation {
|
|||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
"Gain enough Faith for []% of a Great Prophet" -> {
|
OneTimeGainProphet -> {
|
||||||
if (civInfo.religionManager.getGreatProphetEquivalent() == null) return false
|
if (civInfo.religionManager.getGreatProphetEquivalent() == null) return false
|
||||||
val gainedFaith =
|
val gainedFaith =
|
||||||
(civInfo.religionManager.faithForNextGreatProphet() * (unique.params[0].toFloat() / 100f)).toInt()
|
(civInfo.religionManager.faithForNextGreatProphet() * (unique.params[0].toFloat() / 100f)).toInt()
|
||||||
@ -370,14 +371,13 @@ object UniqueTriggerActivation {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
"Reveal up to [] [] within a [] tile radius" -> {
|
OneTimeRevealSpecificMapTiles -> {
|
||||||
if (tile == null) return false
|
if (tile == null) return false
|
||||||
val nearbyRevealableTiles = tile
|
val nearbyRevealableTiles = tile
|
||||||
.getTilesInDistance(unique.params[2].toInt())
|
.getTilesInDistance(unique.params[2].toInt())
|
||||||
.filter {
|
.filter {
|
||||||
!civInfo.exploredTiles.contains(it.position) && it.matchesFilter(
|
!civInfo.exploredTiles.contains(it.position) &&
|
||||||
unique.params[1]
|
it.matchesFilter(unique.params[1])
|
||||||
)
|
|
||||||
}
|
}
|
||||||
.map { it.position }
|
.map { it.position }
|
||||||
if (nearbyRevealableTiles.none()) return false
|
if (nearbyRevealableTiles.none()) return false
|
||||||
@ -397,13 +397,13 @@ object UniqueTriggerActivation {
|
|||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
"From a randomly chosen tile [] tiles away from the ruins, reveal tiles up to [] tiles away with []% chance" -> {
|
OneTimeRevealCrudeMap -> {
|
||||||
if (tile == null) return false
|
if (tile == null) return false
|
||||||
val revealCenter = tile.getTilesAtDistance(unique.params[0].toInt())
|
val revealCenter = tile.getTilesAtDistance(unique.params[0].toInt())
|
||||||
.filter { it.position !in civInfo.exploredTiles }
|
.filter { it.position !in civInfo.exploredTiles }
|
||||||
.toList()
|
.toList()
|
||||||
.randomOrNull(tileBasedRandom)
|
.randomOrNull(tileBasedRandom)
|
||||||
if (revealCenter == null) return false
|
?: return false
|
||||||
val tilesToReveal = revealCenter
|
val tilesToReveal = revealCenter
|
||||||
.getTilesInDistance(unique.params[1].toInt())
|
.getTilesInDistance(unique.params[1].toInt())
|
||||||
.map { it.position }
|
.map { it.position }
|
||||||
@ -417,7 +417,8 @@ object UniqueTriggerActivation {
|
|||||||
"ImprovementIcons/Ancient ruins"
|
"ImprovementIcons/Ancient ruins"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
"Triggers voting for the Diplomatic Victory" -> {
|
|
||||||
|
OneTimeTriggerVoting -> {
|
||||||
for (civ in civInfo.gameInfo.civilizations)
|
for (civ in civInfo.gameInfo.civilizations)
|
||||||
if (!civ.isBarbarian() && !civ.isSpectator())
|
if (!civ.isBarbarian() && !civ.isSpectator())
|
||||||
civ.addFlag(
|
civ.addFlag(
|
||||||
@ -429,8 +430,7 @@ object UniqueTriggerActivation {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
"Provides the cheapest [] building in your first [] cities for free",
|
FreeStatBuildings, FreeSpecificBuildings ->
|
||||||
"Provides a [] in your first [] cities for free" ->
|
|
||||||
civInfo.civConstructions.tryAddFreeBuildings()
|
civInfo.civConstructions.tryAddFreeBuildings()
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
@ -442,21 +442,22 @@ object UniqueTriggerActivation {
|
|||||||
unit: MapUnit,
|
unit: MapUnit,
|
||||||
notification: String? = null
|
notification: String? = null
|
||||||
): Boolean {
|
): Boolean {
|
||||||
when (unique.placeholderText) {
|
@Suppress("NON_EXHAUSTIVE_WHEN") // Yes we're not treating all types here
|
||||||
"Heal this unit by [] HP" -> {
|
when (unique.type) {
|
||||||
|
OneTimeUnitHeal -> {
|
||||||
unit.healBy(unique.params[0].toInt())
|
unit.healBy(unique.params[0].toInt())
|
||||||
if (notification != null)
|
if (notification != null)
|
||||||
unit.civInfo.addNotification(notification, unit.getTile().position) // Do we have a heal icon?
|
unit.civInfo.addNotification(notification, unit.getTile().position) // Do we have a heal icon?
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
"This Unit gains [] XP" -> {
|
OneTimeUnitGainXP -> {
|
||||||
if (!unit.baseUnit.isMilitary()) return false
|
if (!unit.baseUnit.isMilitary()) return false
|
||||||
unit.promotions.XP += unique.params[0].toInt()
|
unit.promotions.XP += unique.params[0].toInt()
|
||||||
if (notification != null)
|
if (notification != null)
|
||||||
unit.civInfo.addNotification(notification, unit.getTile().position)
|
unit.civInfo.addNotification(notification, unit.getTile().position)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
"This Unit upgrades for free" -> {
|
OneTimeUnitUpgrade -> {
|
||||||
val upgradeAction = UnitActions.getUpgradeAction(unit, true)
|
val upgradeAction = UnitActions.getUpgradeAction(unit, true)
|
||||||
?: return false
|
?: return false
|
||||||
upgradeAction.action!!()
|
upgradeAction.action!!()
|
||||||
@ -464,7 +465,7 @@ object UniqueTriggerActivation {
|
|||||||
unit.civInfo.addNotification(notification, unit.getTile().position)
|
unit.civInfo.addNotification(notification, unit.getTile().position)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
"This Unit upgrades for free including special upgrades" -> {
|
OneTimeUnitSpecialUpgrade -> {
|
||||||
val upgradeAction = UnitActions.getAncientRuinsUpgradeAction(unit)
|
val upgradeAction = UnitActions.getAncientRuinsUpgradeAction(unit)
|
||||||
?: return false
|
?: return false
|
||||||
upgradeAction.action!!()
|
upgradeAction.action!!()
|
||||||
@ -472,9 +473,10 @@ object UniqueTriggerActivation {
|
|||||||
unit.civInfo.addNotification(notification, unit.getTile().position)
|
unit.civInfo.addNotification(notification, unit.getTile().position)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
"This Unit gains the [] promotion" -> {
|
OneTimeUnitGainPromotion -> {
|
||||||
val promotion = unit.civInfo.gameInfo.ruleSet.unitPromotions.keys.firstOrNull { it == unique.params[0] }
|
val promotion = unit.civInfo.gameInfo.ruleSet.unitPromotions.keys
|
||||||
if (promotion == null) return false
|
.firstOrNull { it == unique.params[0] }
|
||||||
|
?: return false
|
||||||
unit.promotions.addPromotion(promotion, true)
|
unit.promotions.addPromotion(promotion, true)
|
||||||
if (notification != null)
|
if (notification != null)
|
||||||
unit.civInfo.addNotification(notification, unit.name)
|
unit.civInfo.addNotification(notification, unit.name)
|
||||||
@ -483,4 +485,4 @@ object UniqueTriggerActivation {
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -80,12 +80,12 @@ enum class UniqueType(val text:String, vararg targets: UniqueTarget) {
|
|||||||
CityStateHappiness("Provides [amount] Happiness", UniqueTarget.CityState),
|
CityStateHappiness("Provides [amount] Happiness", UniqueTarget.CityState),
|
||||||
CityStateMilitaryUnits("Provides military units every ≈[amount] turns", UniqueTarget.CityState), // No conditional support as of yet
|
CityStateMilitaryUnits("Provides military units every ≈[amount] turns", UniqueTarget.CityState), // No conditional support as of yet
|
||||||
CityStateUniqueLuxury("Provides a unique luxury", UniqueTarget.CityState), // No conditional support as of yet
|
CityStateUniqueLuxury("Provides a unique luxury", UniqueTarget.CityState), // No conditional support as of yet
|
||||||
|
|
||||||
CityStateGiftedUnitsStartWithXp("Military Units gifted from City-States start with [amount] XP", UniqueTarget.Global),
|
CityStateGiftedUnitsStartWithXp("Military Units gifted from City-States start with [amount] XP", UniqueTarget.Global),
|
||||||
CityStateGoldGiftsProvideMoreInfluence("Gifts of Gold to City-States generate [amount]% more Influence", UniqueTarget.Global),
|
CityStateGoldGiftsProvideMoreInfluence("Gifts of Gold to City-States generate [amount]% more Influence", UniqueTarget.Global),
|
||||||
CityStateCanBeBoughtForGold("Can spend Gold to annex or puppet a City-State that has been your ally for [amount] turns.", UniqueTarget.Global),
|
CityStateCanBeBoughtForGold("Can spend Gold to annex or puppet a City-State that has been your ally for [amount] turns.", UniqueTarget.Global),
|
||||||
CityStateTerritoryAlwaysFriendly("City-State territory always counts as friendly territory", UniqueTarget.Global),
|
CityStateTerritoryAlwaysFriendly("City-State territory always counts as friendly territory", UniqueTarget.Global),
|
||||||
|
|
||||||
|
CityStateCanGiftGreatPeople("Allied City-States will occasionally gift Great People", UniqueTarget.Global), // used in Policy
|
||||||
CityStateDeprecated("Will not be chosen for new games", UniqueTarget.Nation), // implemented for CS only for now
|
CityStateDeprecated("Will not be chosen for new games", UniqueTarget.Nation), // implemented for CS only for now
|
||||||
|
|
||||||
/////// Other global uniques
|
/////// Other global uniques
|
||||||
@ -115,7 +115,7 @@ enum class UniqueType(val text:String, vararg targets: UniqueTarget) {
|
|||||||
FreeExtraBeliefs("May choose [amount] additional [beliefType] beliefs when [foundingOrEnhancing] a religion", UniqueTarget.Global),
|
FreeExtraBeliefs("May choose [amount] additional [beliefType] beliefs when [foundingOrEnhancing] a religion", UniqueTarget.Global),
|
||||||
FreeExtraAnyBeliefs("May choose [amount] additional of any type when [foundingOrEnhancing] a religion", UniqueTarget.Global),
|
FreeExtraAnyBeliefs("May choose [amount] additional of any type when [foundingOrEnhancing] a religion", UniqueTarget.Global),
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////// UNIT UNIQUES /////////////////////////////////////////
|
///////////////////////////////////////// UNIT UNIQUES /////////////////////////////////////////
|
||||||
|
|
||||||
Strength("[amount]% Strength", UniqueTarget.Unit, UniqueTarget.Global),
|
Strength("[amount]% Strength", UniqueTarget.Unit, UniqueTarget.Global),
|
||||||
@ -141,25 +141,25 @@ enum class UniqueType(val text:String, vararg targets: UniqueTarget) {
|
|||||||
DamageForUnits("[mapUnitFilter] units deal +[amount]% damage", UniqueTarget.Global),
|
DamageForUnits("[mapUnitFilter] units deal +[amount]% damage", UniqueTarget.Global),
|
||||||
@Deprecated("As of 3.17.5", ReplaceWith("[+10]% Strength <for [All] units> <during a Golden Age>"), DeprecationLevel.WARNING)
|
@Deprecated("As of 3.17.5", ReplaceWith("[+10]% Strength <for [All] units> <during a Golden Age>"), DeprecationLevel.WARNING)
|
||||||
StrengthGoldenAge("+10% Strength for all units during Golden Age", UniqueTarget.Global),
|
StrengthGoldenAge("+10% Strength for all units during Golden Age", UniqueTarget.Global),
|
||||||
|
|
||||||
Movement("[amount] Movement", UniqueTarget.Unit, UniqueTarget.Global),
|
Movement("[amount] Movement", UniqueTarget.Unit, UniqueTarget.Global),
|
||||||
Sight("[amount] Sight", UniqueTarget.Unit, UniqueTarget.Global),
|
Sight("[amount] Sight", UniqueTarget.Unit, UniqueTarget.Global),
|
||||||
SpreadReligionStrength("[amount]% Spread Religion Strength", UniqueTarget.Unit, UniqueTarget.Global),
|
SpreadReligionStrength("[amount]% Spread Religion Strength", UniqueTarget.Unit, UniqueTarget.Global),
|
||||||
|
|
||||||
@Deprecated("As of 3.17.5", ReplaceWith("[amount] Movement <for [mapUnitFilter] units>"), DeprecationLevel.WARNING)
|
@Deprecated("As of 3.17.5", ReplaceWith("[amount] Movement <for [mapUnitFilter] units>"), DeprecationLevel.WARNING)
|
||||||
MovementUnits("+[amount] Movement for all [mapUnitFilter] units", UniqueTarget.Global),
|
MovementUnits("+[amount] Movement for all [mapUnitFilter] units", UniqueTarget.Global),
|
||||||
@Deprecated("As of 3.17.5", ReplaceWith("[amount] Movement <for [All] units> <during a Golden Age>"), DeprecationLevel.WARNING)
|
@Deprecated("As of 3.17.5", ReplaceWith("[amount] Movement <for [All] units> <during a Golden Age>"), DeprecationLevel.WARNING)
|
||||||
MovementGoldenAge("+1 Movement for all units during Golden Age", UniqueTarget.Global),
|
MovementGoldenAge("+1 Movement for all units during Golden Age", UniqueTarget.Global),
|
||||||
|
|
||||||
@Deprecated("As of 3.17.5", ReplaceWith("[amount] Sight <for [mapUnitFilter] units>"), DeprecationLevel.WARNING)
|
@Deprecated("As of 3.17.5", ReplaceWith("[amount] Sight <for [mapUnitFilter] units>"), DeprecationLevel.WARNING)
|
||||||
SightUnits("[amount] Sight for all [mapUnitFilter] units", UniqueTarget.Global),
|
SightUnits("[amount] Sight for all [mapUnitFilter] units", UniqueTarget.Global),
|
||||||
@Deprecated("As of 3.17.5", ReplaceWith("[amount] Sight"), DeprecationLevel.WARNING)
|
@Deprecated("As of 3.17.5", ReplaceWith("[amount] Sight"), DeprecationLevel.WARNING)
|
||||||
VisibilityRange("[amount] Visibility Range", UniqueTarget.Unit),
|
VisibilityRange("[amount] Visibility Range", UniqueTarget.Unit),
|
||||||
|
|
||||||
@Deprecated("As of 3.17.5", ReplaceWith("[amount]% Spread Religion Strength <for [mapUnitFilter] units>"), DeprecationLevel.WARNING)
|
@Deprecated("As of 3.17.5", ReplaceWith("[amount]% Spread Religion Strength <for [mapUnitFilter] units>"), DeprecationLevel.WARNING)
|
||||||
SpreadReligionStrengthUnits("[amount]% Spread Religion Strength for [mapUnitFilter] units", UniqueTarget.Global),
|
SpreadReligionStrengthUnits("[amount]% Spread Religion Strength for [mapUnitFilter] units", UniqueTarget.Global),
|
||||||
|
|
||||||
|
|
||||||
// The following block gets cached in MapUnit for faster getMovementCostBetweenAdjacentTiles
|
// The following block gets cached in MapUnit for faster getMovementCostBetweenAdjacentTiles
|
||||||
DoubleMovementOnTerrain("Double movement in [terrainFilter]", UniqueTarget.Unit),
|
DoubleMovementOnTerrain("Double movement in [terrainFilter]", UniqueTarget.Unit),
|
||||||
@Deprecated("As of 3.17.1", ReplaceWith("Double movement in [terrainFilter]"), DeprecationLevel.WARNING)
|
@Deprecated("As of 3.17.1", ReplaceWith("Double movement in [terrainFilter]"), DeprecationLevel.WARNING)
|
||||||
@ -177,7 +177,7 @@ enum class UniqueType(val text:String, vararg targets: UniqueTarget) {
|
|||||||
CannotEnterOcean("Cannot enter ocean tiles", UniqueTarget.Unit),
|
CannotEnterOcean("Cannot enter ocean tiles", UniqueTarget.Unit),
|
||||||
CannotEnterOceanUntilAstronomy("Cannot enter ocean tiles until Astronomy", UniqueTarget.Unit),
|
CannotEnterOceanUntilAstronomy("Cannot enter ocean tiles until Astronomy", UniqueTarget.Unit),
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////// TERRAIN UNIQUES ////////////////////////////////////////
|
//////////////////////////////////////// TERRAIN UNIQUES ////////////////////////////////////////
|
||||||
|
|
||||||
NaturalWonderNeighborCount("Must be adjacent to [amount] [simpleTerrain] tiles", UniqueTarget.Terrain),
|
NaturalWonderNeighborCount("Must be adjacent to [amount] [simpleTerrain] tiles", UniqueTarget.Terrain),
|
||||||
@ -205,10 +205,10 @@ enum class UniqueType(val text:String, vararg targets: UniqueTarget) {
|
|||||||
ConditionalNotWar("when not at war", UniqueTarget.Conditional),
|
ConditionalNotWar("when not at war", UniqueTarget.Conditional),
|
||||||
ConditionalHappy("while the empire is happy", UniqueTarget.Conditional),
|
ConditionalHappy("while the empire is happy", UniqueTarget.Conditional),
|
||||||
ConditionalGoldenAge("during a Golden Age", UniqueTarget.Conditional),
|
ConditionalGoldenAge("during a Golden Age", UniqueTarget.Conditional),
|
||||||
|
|
||||||
// city conditionals
|
// city conditionals
|
||||||
ConditionalSpecialistCount("if this city has at least [amount] specialists", UniqueTarget.Conditional),
|
ConditionalSpecialistCount("if this city has at least [amount] specialists", UniqueTarget.Conditional),
|
||||||
|
|
||||||
// unit conditionals
|
// unit conditionals
|
||||||
ConditionalOurUnit("for [mapUnitFilter] units", UniqueTarget.Conditional),
|
ConditionalOurUnit("for [mapUnitFilter] units", UniqueTarget.Conditional),
|
||||||
ConditionalVsCity("vs cities", UniqueTarget.Conditional),
|
ConditionalVsCity("vs cities", UniqueTarget.Conditional),
|
||||||
@ -222,6 +222,44 @@ enum class UniqueType(val text:String, vararg targets: UniqueTarget) {
|
|||||||
// tile conditionals
|
// tile conditionals
|
||||||
ConditionalNeighborTiles("with [amount] to [amount] neighboring [tileFilter] tiles", UniqueTarget.Conditional),
|
ConditionalNeighborTiles("with [amount] to [amount] neighboring [tileFilter] tiles", UniqueTarget.Conditional),
|
||||||
ConditionalNeighborTilesAnd("with [amount] to [amount] neighboring [tileFilter] [tileFilter] tiles", UniqueTarget.Conditional),
|
ConditionalNeighborTilesAnd("with [amount] to [amount] neighboring [tileFilter] [tileFilter] tiles", UniqueTarget.Conditional),
|
||||||
|
|
||||||
|
///////////////////////////////////////// TRIGGERED ONE-TIME /////////////////////////////////////////
|
||||||
|
|
||||||
|
OneTimeFreeUnit("Free [baseUnitFilter] appears", UniqueTarget.Global), // used in Policies, Buildings
|
||||||
|
OneTimeAmountFreeUnits("[amount] free [baseUnitFilter] units appear", UniqueTarget.Global), // used in Buildings
|
||||||
|
OneTimeFreeUnitRuins("Free [baseUnitFilter] found in the ruins", UniqueTarget.Ruins), // Differs from "Free [] appears" in that it spawns near the ruins instead of in a city
|
||||||
|
OneTimeFreePolicy("Free Social Policy", UniqueTarget.Global), // used in Buildings
|
||||||
|
OneTimeAmountFreePolicies("[amount] Free Social Policies", UniqueTarget.Global), // Not used in Vanilla
|
||||||
|
OneTimeEnterGoldenAge("Empire enters golden age", UniqueTarget.Global), // used in Policies, Buildings
|
||||||
|
OneTimeFreeGreatPerson("Free Great Person", UniqueTarget.Global), // used in Policies, Buildings
|
||||||
|
OneTimeGainPopulation("[amount] population [cityFilter]", UniqueTarget.Global), // used in CN tower
|
||||||
|
OneTimeGainPopulationRandomCity("[amount] population in a random city", UniqueTarget.Ruins),
|
||||||
|
OneTimeFreeTech("Free Technology", UniqueTarget.Global), // used in Buildings
|
||||||
|
OneTimeAmountFreeTechs("[amount] Free Technologies", UniqueTarget.Global), // used in Policy
|
||||||
|
OneTimeFreeTechRuins("[amount] free random researchable Tech(s) from the [era]", UniqueTarget.Ruins), // todo: Not picked up by TranslationFileWriter?
|
||||||
|
OneTimeRevealEntireMap("Reveals the entire map", UniqueTarget.Global), // used in tech
|
||||||
|
OneTimeGainStat("Gain [amount] [stat]", UniqueTarget.Ruins),
|
||||||
|
OneTimeGainStatRange("Gain [amount]-[amount] [stat]", UniqueTarget.Ruins),
|
||||||
|
OneTimeGainPantheon("Gain enough Faith for a Pantheon", UniqueTarget.Ruins),
|
||||||
|
OneTimeGainProphet("Gain enough Faith for [amount]% of a Great Prophet", UniqueTarget.Ruins),
|
||||||
|
// todo: The "up to [All]" used in vanilla json is not nice to read. Split?
|
||||||
|
OneTimeRevealSpecificMapTiles("Reveal up to [amount/'all'] [tileFilter] within a [amount] tile radius", UniqueTarget.Ruins),
|
||||||
|
OneTimeRevealCrudeMap("From a randomly chosen tile [amount] tiles away from the ruins, reveal tiles up to [amount] tiles away with [amount]% chance", UniqueTarget.Ruins),
|
||||||
|
OneTimeTriggerVoting("Triggers voting for the Diplomatic Victory", UniqueTarget.Global), // used in Building
|
||||||
|
|
||||||
|
OneTimeUnitHeal("Heal this unit by [amount] HP", UniqueTarget.Promotion),
|
||||||
|
OneTimeUnitGainXP("This Unit gains [amount] XP", UniqueTarget.Ruins),
|
||||||
|
OneTimeUnitUpgrade("This Unit upgrades for free", UniqueTarget.Global), // Not used in Vanilla
|
||||||
|
OneTimeUnitSpecialUpgrade("This Unit upgrades for free including special upgrades", UniqueTarget.Ruins),
|
||||||
|
OneTimeUnitGainPromotion("This Unit gains the [promotion] promotion", UniqueTarget.Global), // Not used in Vanilla
|
||||||
|
|
||||||
|
UnitsGainPromotion("[mapUnitFilter] units gain the [promotion] promotion", UniqueTarget.Global), // Not used in Vanilla
|
||||||
|
// todo: remove forced sign
|
||||||
|
StrategicResourcesIncrease("Quantity of strategic resources produced by the empire +[amount]%", UniqueTarget.Global), // used in Policy
|
||||||
|
// todo: remove forced sign
|
||||||
|
TimedAttackStrength("+[amount]% attack strength to all [mapUnitFilter] Units for [amount] turns", UniqueTarget.Global), // used in Policy
|
||||||
|
FreeStatBuildings("Provides the cheapest [stat] building in your first [amount] cities for free", UniqueTarget.Global), // used in Policy
|
||||||
|
FreeSpecificBuildings("Provides a [building] in your first [amount] cities for free", UniqueTarget.Global), // used in Policy
|
||||||
;
|
;
|
||||||
|
|
||||||
/** For uniques that have "special" parameters that can accept multiple types, we can override them manually
|
/** For uniques that have "special" parameters that can accept multiple types, we can override them manually
|
||||||
@ -231,10 +269,10 @@ enum class UniqueType(val text:String, vararg targets: UniqueTarget) {
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
for (placeholder in text.getPlaceholderParameters()) {
|
for (placeholder in text.getPlaceholderParameters()) {
|
||||||
val matchingParameterType =
|
val matchingParameterTypes = placeholder
|
||||||
UniqueParameterType.values().firstOrNull { it.parameterName == placeholder }
|
.split('/')
|
||||||
?: UniqueParameterType.Unknown
|
.map { UniqueParameterType.safeValueOf(it) }
|
||||||
parameterTypeMap.add(listOf(matchingParameterType))
|
parameterTypeMap.add(matchingParameterTypes)
|
||||||
}
|
}
|
||||||
targetTypes.addAll(targets)
|
targetTypes.addAll(targets)
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import com.unciv.UncivGame
|
|||||||
import com.unciv.logic.map.MapUnit
|
import com.unciv.logic.map.MapUnit
|
||||||
import com.unciv.models.Tutorial
|
import com.unciv.models.Tutorial
|
||||||
import com.unciv.models.UncivSound
|
import com.unciv.models.UncivSound
|
||||||
|
import com.unciv.models.ruleset.unique.UniqueType
|
||||||
import com.unciv.models.ruleset.unit.Promotion
|
import com.unciv.models.ruleset.unit.Promotion
|
||||||
import com.unciv.models.translations.tr
|
import com.unciv.models.translations.tr
|
||||||
import com.unciv.ui.utils.*
|
import com.unciv.ui.utils.*
|
||||||
@ -71,7 +72,7 @@ class PromotionPickerScreen(val unit: MapUnit) : PickerScreen() {
|
|||||||
availablePromotionsGroup.row()
|
availablePromotionsGroup.row()
|
||||||
}
|
}
|
||||||
for (promotion in promotionsForUnitType) {
|
for (promotion in promotionsForUnitType) {
|
||||||
if (promotion.uniqueObjects.any { it.placeholderText == "Heal this unit by [] HP" } && unit.health == 100) continue
|
if (promotion.hasUnique(UniqueType.OneTimeUnitHeal) && unit.health == 100) continue
|
||||||
val isPromotionAvailable = promotion in unitAvailablePromotions
|
val isPromotionAvailable = promotion in unitAvailablePromotions
|
||||||
val unitHasPromotion = unit.promotions.promotions.contains(promotion.name)
|
val unitHasPromotion = unit.promotions.promotions.contains(promotion.name)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user