mirror of
https://github.com/yairm210/Unciv.git
synced 2025-10-01 07:51:53 -04:00
Enumified all remaining resource & improvement uniques (#5523)
* Added conditionals & enumified improvement stat uniques * Enumified all the other uniques * Fixed bug where improvemen stat icons didn't show up in tech tree & reviews
This commit is contained in:
parent
e9d36ea0ce
commit
b66443574e
@ -390,7 +390,7 @@
|
|||||||
"culture": 1,
|
"culture": 1,
|
||||||
"isWonder": true,
|
"isWonder": true,
|
||||||
"greatPersonPoints": {"Great Engineer": 1},
|
"greatPersonPoints": {"Great Engineer": 1},
|
||||||
"uniques": ["Must be next to [Desert]", "[+1 Food, +1 Production, +1 Gold] from [Desert] tiles without [Flood plains] [in this city]", "Gain a free [Amphitheater] [in this city]", "[+6 Culture] once [Archaeology] is discovered"],
|
"uniques": ["Must be next to [Desert]", "[+1 Food, +1 Production, +1 Gold] from [Desert] tiles without [Flood plains] [in this city]", "Gain a free [Amphitheater] [in this city]", "[+6 Culture] <after discovering [Archaeology]>"],
|
||||||
"requiredTech": "Currency",
|
"requiredTech": "Currency",
|
||||||
"quote": "'...who drinks the water I shall give him, says the Lord, will have a spring inside him welling up for eternal life. Let them bring me to your holy mountain in the place where you dwell. Across the desert and through the mountain to the Canyon of the Crescent Moon...' - Indiana Jones"
|
"quote": "'...who drinks the water I shall give him, says the Lord, will have a spring inside him welling up for eternal life. Let them bring me to your holy mountain in the place where you dwell. Across the desert and through the mountain to the Canyon of the Crescent Moon...' - Indiana Jones"
|
||||||
},
|
},
|
||||||
@ -603,7 +603,7 @@
|
|||||||
"culture": 2,
|
"culture": 2,
|
||||||
"hurryCostModifier": 25,
|
"hurryCostModifier": 25,
|
||||||
"requiredBuilding": "Walls",
|
"requiredBuilding": "Walls",
|
||||||
"uniques": ["[+1 Gold] once [Flight] is discovered", "Destroyed when the city is captured"],
|
"uniques": ["[+1 Gold] <after discovering [Flight]>", "Destroyed when the city is captured"],
|
||||||
"requiredTech": "Chivalry"
|
"requiredTech": "Chivalry"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -7,8 +7,8 @@
|
|||||||
"turnsToBuild": 7,
|
"turnsToBuild": 7,
|
||||||
"techRequired": "Agriculture",
|
"techRequired": "Agriculture",
|
||||||
"uniques": ["Can also be built on tiles adjacent to fresh water",
|
"uniques": ["Can also be built on tiles adjacent to fresh water",
|
||||||
"[+1 Food] on [Fresh water] tiles once [Civil Service] is discovered",
|
"[+1 Food] from [Fresh water] tiles <after discovering [Civil Service]>",
|
||||||
"[+1 Food] on [non-fresh water] tiles once [Fertilizer] is discovered"],
|
"[+1 Food] from [non-fresh water] tiles <after discovering [Fertilizer]>"],
|
||||||
"shortcutKey": "F"
|
"shortcutKey": "F"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -17,7 +17,7 @@
|
|||||||
"production": 1,
|
"production": 1,
|
||||||
"turnsToBuild": 7,
|
"turnsToBuild": 7,
|
||||||
"techRequired": "Construction",
|
"techRequired": "Construction",
|
||||||
"uniques": ["[+1 Production] once [Scientific Theory] is discovered"],
|
"uniques": ["[+1 Production] <after discovering [Scientific Theory]>"],
|
||||||
"shortcutKey": "L"
|
"shortcutKey": "L"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -26,7 +26,7 @@
|
|||||||
"production": 1,
|
"production": 1,
|
||||||
"turnsToBuild": 7,
|
"turnsToBuild": 7,
|
||||||
"techRequired": "Mining",
|
"techRequired": "Mining",
|
||||||
"uniques": ["[+1 Production] once [Chemistry] is discovered"],
|
"uniques": ["[+1 Production] <after discovering [Chemistry]>"],
|
||||||
"shortcutKey": "M"
|
"shortcutKey": "M"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -35,7 +35,7 @@
|
|||||||
"gold": 1,
|
"gold": 1,
|
||||||
"turnsToBuild": 7,
|
"turnsToBuild": 7,
|
||||||
"techRequired": "Guilds",
|
"techRequired": "Guilds",
|
||||||
"uniques": ["[+1 Gold] once [Economics] is discovered"],
|
"uniques": ["[+1 Gold] <after discovering [Economics]>"],
|
||||||
"shortcutKey": "T"
|
"shortcutKey": "T"
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -44,7 +44,7 @@
|
|||||||
"name": "Camp",
|
"name": "Camp",
|
||||||
"turnsToBuild": 7,
|
"turnsToBuild": 7,
|
||||||
"techRequired": "Trapping",
|
"techRequired": "Trapping",
|
||||||
"uniques": ["Does not need removal of [Forest]","Does not need removal of [Jungle]","[+1 Gold] once [Economics] is discovered"],
|
"uniques": ["Does not need removal of [Forest]","Does not need removal of [Jungle]","[+1 Gold] <after discovering [Economics]>"],
|
||||||
"shortcutKey": "C"
|
"shortcutKey": "C"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -59,7 +59,7 @@
|
|||||||
"name": "Pasture",
|
"name": "Pasture",
|
||||||
"turnsToBuild": 8,
|
"turnsToBuild": 8,
|
||||||
"techRequired": "Animal Husbandry",
|
"techRequired": "Animal Husbandry",
|
||||||
"uniques": ["[+1 Food] once [Fertilizer] is discovered"],
|
"uniques": ["[+1 Food] <after discovering [Fertilizer]>"],
|
||||||
"shortcutKey": "P"
|
"shortcutKey": "P"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -67,14 +67,14 @@
|
|||||||
"turnsToBuild": 6,
|
"turnsToBuild": 6,
|
||||||
"gold": 1,
|
"gold": 1,
|
||||||
"techRequired": "Calendar",
|
"techRequired": "Calendar",
|
||||||
"uniques": ["[+1 Food] once [Fertilizer] is discovered"],
|
"uniques": ["[+1 Food] <after discovering [Fertilizer]>"],
|
||||||
"shortcutKey": "P"
|
"shortcutKey": "P"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Quarry",
|
"name": "Quarry",
|
||||||
"turnsToBuild": 8,
|
"turnsToBuild": 8,
|
||||||
"techRequired": "Masonry",
|
"techRequired": "Masonry",
|
||||||
"uniques": ["[+1 Production] once [Chemistry] is discovered"],
|
"uniques": ["[+1 Production] <after discovering [Chemistry]>"],
|
||||||
"shortcutKey": "Q"
|
"shortcutKey": "Q"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -82,7 +82,7 @@
|
|||||||
"terrainsCanBeBuiltOn": ["Coast"],
|
"terrainsCanBeBuiltOn": ["Coast"],
|
||||||
"food": 1,
|
"food": 1,
|
||||||
"techRequired": "Sailing",
|
"techRequired": "Sailing",
|
||||||
"uniques": ["[+1 Gold] once [Compass] is discovered"]
|
"uniques": ["[+1 Gold] <after discovering [Compass]>"]
|
||||||
},
|
},
|
||||||
|
|
||||||
// Military improvement
|
// Military improvement
|
||||||
@ -100,6 +100,7 @@
|
|||||||
"name": "Road",
|
"name": "Road",
|
||||||
"turnsToBuild": 4,
|
"turnsToBuild": 4,
|
||||||
"techRequired": "The Wheel",
|
"techRequired": "The Wheel",
|
||||||
|
// "Costs [1] gold per turn when in your territory" does nothing and is only to inform the user
|
||||||
"uniques": ["Can be built outside your borders", "Costs [1] gold per turn when in your territory"],
|
"uniques": ["Can be built outside your borders", "Costs [1] gold per turn when in your territory"],
|
||||||
"shortcutKey": "R",
|
"shortcutKey": "R",
|
||||||
"civilopediaText": [
|
"civilopediaText": [
|
||||||
@ -173,7 +174,7 @@
|
|||||||
{
|
{
|
||||||
"name": "Academy",
|
"name": "Academy",
|
||||||
"science": 8,
|
"science": 8,
|
||||||
"uniques": ["Great Improvement", "[+2 Science] once [Scientific Theory] is discovered", "[+2 Science] once [Atomic Theory] is discovered"]
|
"uniques": ["Great Improvement", "[+2 Science] <after discovering [Scientific Theory]>", "[+2 Science] <after discovering [Atomic Theory]>"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Landmark",
|
"name": "Landmark",
|
||||||
@ -183,12 +184,12 @@
|
|||||||
{
|
{
|
||||||
"name": "Manufactory",
|
"name": "Manufactory",
|
||||||
"production": 4,
|
"production": 4,
|
||||||
"uniques": ["Great Improvement", "[+1 Production] once [Chemistry] is discovered"]
|
"uniques": ["Great Improvement", "[+1 Production] <after discovering [Chemistry]>"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Customs house",
|
"name": "Customs house",
|
||||||
"gold": 4,
|
"gold": 4,
|
||||||
"uniques": ["Great Improvement", "[+1 Gold] once [Economics] is discovered"]
|
"uniques": ["Great Improvement", "[+1 Gold] <after discovering [Economics]>"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Holy site",
|
"name": "Holy site",
|
||||||
@ -197,7 +198,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Citadel",
|
"name": "Citadel",
|
||||||
"uniques": ["Great Improvement", "Gives a defensive bonus of [100]%", "Deal 30 damage to adjacent enemy units", "Can be built just outside your borders"],
|
"uniques": ["Great Improvement", "Gives a defensive bonus of [100]%", "Adjacent enemy units ending their turn take [30] damage", "Can be built just outside your borders"],
|
||||||
"civilopediaText": [{"text":"Constructing it will take over the tiles around it and assign them to your closest city"}]
|
"civilopediaText": [{"text":"Constructing it will take over the tiles around it and assign them to your closest city"}]
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -207,7 +208,7 @@
|
|||||||
"uniqueTo": "Polynesia",
|
"uniqueTo": "Polynesia",
|
||||||
"culture": 1,
|
"culture": 1,
|
||||||
"turnsToBuild": 4,
|
"turnsToBuild": 4,
|
||||||
"uniques": ["Can only be built on [Coastal] tiles", "[+1 Culture] for each adjacent [Moai]", "[+1 Gold] once [Flight] is discovered"],
|
"uniques": ["Can only be built on [Coastal] tiles", "[+1 Culture] for each adjacent [Moai]", "[+1 Gold] <after discovering [Flight]>"],
|
||||||
"techRequired": "Construction",
|
"techRequired": "Construction",
|
||||||
"shortcutKey": "M"
|
"shortcutKey": "M"
|
||||||
},
|
},
|
||||||
@ -219,8 +220,8 @@
|
|||||||
"turnsToBuild": 7,
|
"turnsToBuild": 7,
|
||||||
"uniques": ["Cannot be built on [Bonus resource] tiles",
|
"uniques": ["Cannot be built on [Bonus resource] tiles",
|
||||||
"[+1 Food] for each adjacent [Mountain]",
|
"[+1 Food] for each adjacent [Mountain]",
|
||||||
"[+1 Food] on [Fresh water] tiles once [Civil Service] is discovered",
|
"[+1 Food] on [Fresh water] tiles <after discovering [Civil Service]>",
|
||||||
"[+1 Food] on [non-fresh water] tiles once [Fertilizer] is discovered"],
|
"[+1 Food] on [non-fresh water] tiles <after discovering[Fertilizer]>"],
|
||||||
"techRequired": "Construction",
|
"techRequired": "Construction",
|
||||||
"shortcutKey": "F"
|
"shortcutKey": "F"
|
||||||
},
|
},
|
||||||
@ -230,7 +231,7 @@
|
|||||||
"food": 3,
|
"food": 3,
|
||||||
"terrainsCanBeBuiltOn": ["Marsh", "Flood plains"],
|
"terrainsCanBeBuiltOn": ["Marsh", "Flood plains"],
|
||||||
"turnsToBuild": 7,
|
"turnsToBuild": 7,
|
||||||
"uniques": ["[+1 Production, +2 Gold] once [Economics] is discovered"],
|
"uniques": ["[+1 Production, +2 Gold] <after discovering [Economics]>"],
|
||||||
"techRequired": "Guilds",
|
"techRequired": "Guilds",
|
||||||
"shortcutKey": "F"
|
"shortcutKey": "F"
|
||||||
},
|
},
|
||||||
|
@ -324,5 +324,5 @@
|
|||||||
"gold": 2,
|
"gold": 2,
|
||||||
"improvement": "Camp",
|
"improvement": "Camp",
|
||||||
"improvementStats": {"gold": 1}
|
"improvementStats": {"gold": 1}
|
||||||
},
|
}
|
||||||
]
|
]
|
||||||
|
@ -212,7 +212,7 @@ object GameStarter {
|
|||||||
|
|
||||||
val allMercantileResources = ruleset.tileResources.values.filter {
|
val allMercantileResources = ruleset.tileResources.values.filter {
|
||||||
it.unique == "Can only be created by Mercantile City-States" // Deprecated as of 3.16.16
|
it.unique == "Can only be created by Mercantile City-States" // Deprecated as of 3.16.16
|
||||||
|| it.uniques.contains("Can only be created by Mercantile City-States") }.map { it.name }
|
|| it.hasUnique(UniqueType.CityStateOnlyResource) }.map { it.name }
|
||||||
|
|
||||||
|
|
||||||
val unusedMercantileResources = Stack<String>()
|
val unusedMercantileResources = Stack<String>()
|
||||||
|
@ -695,7 +695,7 @@ object Battle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Remove improvements, add fallout
|
// Remove improvements, add fallout
|
||||||
if (tile.improvement != null && !tile.getTileImprovement()!!.hasUnique("Indestructible")) {
|
if (tile.improvement != null && !tile.getTileImprovement()!!.hasUnique(UniqueType.Indestructible)) {
|
||||||
tile.improvement = null
|
tile.improvement = null
|
||||||
}
|
}
|
||||||
tile.improvementInProgress = null
|
tile.improvementInProgress = null
|
||||||
@ -758,7 +758,7 @@ object Battle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Remove improvements
|
// Remove improvements
|
||||||
if (tile.improvement != null && !tile.getTileImprovement()!!.hasUnique("Indestructible")) {
|
if (tile.improvement != null && !tile.getTileImprovement()!!.hasUnique(UniqueType.Indestructible)) {
|
||||||
tile.improvement = null
|
tile.improvement = null
|
||||||
}
|
}
|
||||||
tile.improvementInProgress = null
|
tile.improvementInProgress = null
|
||||||
|
@ -116,10 +116,12 @@ class CityConstructions {
|
|||||||
stats.add(unique.stats.times(cityInfo.population.population / unique.params[1].toFloat()))
|
stats.add(unique.stats.times(cityInfo.population.population / unique.params[1].toFloat()))
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unique in cityInfo.getLocalMatchingUniques("[] once [] is discovered")) {
|
// Deprecated since 3.17.11
|
||||||
if (cityInfo.civInfo.tech.isResearched(unique.params[1]))
|
for (unique in cityInfo.getLocalMatchingUniques(UniqueType.StatsWithTech)) {
|
||||||
stats.add(unique.stats)
|
if (cityInfo.civInfo.tech.isResearched(unique.params[1]))
|
||||||
}
|
stats.add(unique.stats)
|
||||||
|
}
|
||||||
|
//
|
||||||
|
|
||||||
return stats
|
return stats
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ class CityStateFunctions(val civInfo: CivilizationInfo) {
|
|||||||
for (tech in startingTechs)
|
for (tech in startingTechs)
|
||||||
civInfo.tech.techsResearched.add(tech.name) // can't be .addTechnology because the civInfo isn't assigned yet
|
civInfo.tech.techsResearched.add(tech.name) // can't be .addTechnology because the civInfo isn't assigned yet
|
||||||
|
|
||||||
val allMercantileResources = ruleset.tileResources.values.filter { it.hasUnique("Can only be created by Mercantile City-States") }.map { it.name }
|
val allMercantileResources = ruleset.tileResources.values.filter { it.hasUnique(UniqueType.CityStateOnlyResource) }.map { it.name }
|
||||||
val allPossibleBonuses = HashSet<Unique>() // We look through these to determine what kind of city state we are
|
val allPossibleBonuses = HashSet<Unique>() // We look through these to determine what kind of city state we are
|
||||||
var fallback = false
|
var fallback = false
|
||||||
for (era in ruleset.eras.values) {
|
for (era in ruleset.eras.values) {
|
||||||
|
@ -1014,15 +1014,16 @@ class MapUnit {
|
|||||||
private fun doCitadelDamage() {
|
private fun doCitadelDamage() {
|
||||||
// Check for Citadel damage - note: 'Damage does not stack with other Citadels'
|
// Check for Citadel damage - note: 'Damage does not stack with other Citadels'
|
||||||
val citadelTile = currentTile.neighbors
|
val citadelTile = currentTile.neighbors
|
||||||
.firstOrNull {
|
.filter {
|
||||||
it.getOwner() != null && civInfo.isAtWarWith(it.getOwner()!!) &&
|
it.getOwner() != null && civInfo.isAtWarWith(it.getOwner()!!) && it.improvement != null
|
||||||
with(it.getTileImprovement()) {
|
}.maxByOrNull { tile ->
|
||||||
this != null && this.hasUnique("Deal 30 damage to adjacent enemy units")
|
tile.getTileImprovement()!!
|
||||||
}
|
.getMatchingUniques(UniqueType.DamagesAdjacentEnemyUnits)
|
||||||
|
.sumOf { it.params[0].toInt() }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (citadelTile != null) {
|
if (citadelTile != null) {
|
||||||
health -= 30
|
health -= citadelTile.getTileImprovement()!!.getMatchingUniques(UniqueType.DamagesAdjacentEnemyUnits).sumOf { it.params[0].toInt() }
|
||||||
val locations = LocationAction(listOf(citadelTile.position, currentTile.position))
|
val locations = LocationAction(listOf(citadelTile.position, currentTile.position))
|
||||||
if (health <= 0) {
|
if (health <= 0) {
|
||||||
civInfo.addNotification(
|
civInfo.addNotification(
|
||||||
|
@ -10,6 +10,7 @@ import com.unciv.logic.civilization.PlayerType
|
|||||||
import com.unciv.models.ruleset.Ruleset
|
import com.unciv.models.ruleset.Ruleset
|
||||||
import com.unciv.models.ruleset.unique.UniqueType
|
import com.unciv.models.ruleset.unique.UniqueType
|
||||||
import com.unciv.models.ruleset.tile.*
|
import com.unciv.models.ruleset.tile.*
|
||||||
|
import com.unciv.models.ruleset.unique.StateForConditionals
|
||||||
import com.unciv.models.stats.Stats
|
import com.unciv.models.stats.Stats
|
||||||
import com.unciv.models.translations.tr
|
import com.unciv.models.translations.tr
|
||||||
import com.unciv.ui.civilopedia.FormattedLine
|
import com.unciv.ui.civilopedia.FormattedLine
|
||||||
@ -354,21 +355,31 @@ open class TileInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun getImprovementStats(improvement: TileImprovement, observingCiv: CivilizationInfo, city: CityInfo?): Stats {
|
fun getImprovementStats(improvement: TileImprovement, observingCiv: CivilizationInfo, city: CityInfo?): Stats {
|
||||||
val stats = improvement.clone() // clones the stats of the improvement, not the improvement itself
|
val stats = improvement.cloneStats()
|
||||||
if (hasViewableResource(observingCiv) && tileResource.improvement == improvement.name)
|
if (hasViewableResource(observingCiv) && tileResource.improvement == improvement.name)
|
||||||
stats.add(tileResource.improvementStats!!.clone()) // resource-specific improvement
|
stats.add(tileResource.improvementStats!!.clone()) // resource-specific improvement
|
||||||
|
|
||||||
for (unique in improvement.uniqueObjects)
|
// Deprecated since 3.17.10
|
||||||
if (unique.placeholderText == "[] once [] is discovered" && observingCiv.tech.isResearched(unique.params[1]))
|
for (unique in improvement.getMatchingUniques(UniqueType.StatsWithTech)) {
|
||||||
stats.add(unique.stats)
|
if (observingCiv.tech.isResearched(unique.params[1]))
|
||||||
|
stats.add(unique.stats)
|
||||||
|
}
|
||||||
|
//
|
||||||
|
|
||||||
|
for (unique in improvement.getMatchingUniques(UniqueType.Stats, StateForConditionals(civInfo = observingCiv, cityInfo = city))) {
|
||||||
|
stats.add(unique.stats)
|
||||||
|
}
|
||||||
|
|
||||||
if (city != null) {
|
if (city != null) {
|
||||||
val tileUniques = city.getMatchingUniques(UniqueType.StatsFromTiles)
|
val tileUniques = city.getMatchingUniques(UniqueType.StatsFromTiles, StateForConditionals(civInfo = observingCiv, cityInfo = city))
|
||||||
.filter { city.matchesFilter(it.params[2]) }
|
.filter { city.matchesFilter(it.params[2]) }
|
||||||
val improvementUniques = improvement.uniqueObjects.filter {
|
val improvementUniques =
|
||||||
it.placeholderText == "[] on [] tiles once [] is discovered"
|
// Deprecated since 3.17.10
|
||||||
&& observingCiv.tech.isResearched(it.params[2])
|
improvement.getMatchingUniques(UniqueType.StatsOnTileWithTech)
|
||||||
}
|
.filter { observingCiv.tech.isResearched(it.params[2]) } +
|
||||||
|
//
|
||||||
|
improvement.getMatchingUniques(UniqueType.ImprovementStatsOnTile, StateForConditionals(civInfo = observingCiv, cityInfo = city))
|
||||||
|
|
||||||
for (unique in tileUniques + improvementUniques) {
|
for (unique in tileUniques + improvementUniques) {
|
||||||
if (improvement.matchesFilter(unique.params[1])
|
if (improvement.matchesFilter(unique.params[1])
|
||||||
// Freshwater and non-freshwater cannot be moved to matchesUniqueFilter since that creates an endless feedback.
|
// Freshwater and non-freshwater cannot be moved to matchesUniqueFilter since that creates an endless feedback.
|
||||||
@ -385,15 +396,14 @@ open class TileInfo {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unique in improvement.uniqueObjects)
|
for (unique in improvement.getMatchingUniques(UniqueType.ImprovementStatsForAdjacencies)) {
|
||||||
if (unique.placeholderText == "[] for each adjacent []") {
|
val adjacent = unique.params[1]
|
||||||
val adjacent = unique.params[1]
|
val numberOfBonuses = neighbors.count {
|
||||||
val numberOfBonuses = neighbors.count {
|
it.matchesFilter(adjacent, observingCiv)
|
||||||
it.matchesFilter(adjacent, observingCiv)
|
|| it.roadStatus.name == adjacent
|
||||||
|| it.roadStatus.name == adjacent
|
|
||||||
}
|
|
||||||
stats.add(unique.stats.times(numberOfBonuses.toFloat()))
|
|
||||||
}
|
}
|
||||||
|
stats.add(unique.stats.times(numberOfBonuses.toFloat()))
|
||||||
|
}
|
||||||
|
|
||||||
for (unique in observingCiv.getMatchingUniques("+[]% yield from every []"))
|
for (unique in observingCiv.getMatchingUniques("+[]% yield from every []"))
|
||||||
if (improvement.matchesFilter(unique.params[1]))
|
if (improvement.matchesFilter(unique.params[1]))
|
||||||
@ -408,16 +418,16 @@ open class TileInfo {
|
|||||||
improvement.uniqueTo != null && improvement.uniqueTo != civInfo.civName -> false
|
improvement.uniqueTo != null && improvement.uniqueTo != civInfo.civName -> false
|
||||||
improvement.techRequired != null && !civInfo.tech.isResearched(improvement.techRequired!!) -> false
|
improvement.techRequired != null && !civInfo.tech.isResearched(improvement.techRequired!!) -> false
|
||||||
getOwner() != civInfo && !(
|
getOwner() != civInfo && !(
|
||||||
improvement.hasUnique("Can be built outside your borders")
|
improvement.hasUnique(UniqueType.CanBuildOutsideBorders)
|
||||||
// citadel can be built only next to or within own borders
|
|| ( // citadel can be built only next to or within own borders
|
||||||
|| improvement.hasUnique("Can be built just outside your borders")
|
improvement.hasUnique(UniqueType.CanBuildJustOutsideBorders)
|
||||||
&& neighbors.any { it.getOwner() == civInfo } && civInfo.cities.isNotEmpty()
|
&& neighbors.any { it.getOwner() == civInfo } && civInfo.cities.isNotEmpty()
|
||||||
) -> false
|
)
|
||||||
|
) -> false
|
||||||
improvement.uniqueObjects.any {
|
improvement.uniqueObjects.any {
|
||||||
it.placeholderText == "Obsolete with []" && civInfo.tech.isResearched(it.params[0])
|
it.placeholderText == "Obsolete with []" && civInfo.tech.isResearched(it.params[0])
|
||||||
} -> return false
|
} -> return false
|
||||||
improvement.uniqueObjects.any {
|
improvement.getMatchingUniques(UniqueType.RequiresTechToBuildOnTile).any {
|
||||||
it.placeholderText == "Cannot be built on [] tiles until [] is discovered" &&
|
|
||||||
matchesTerrainFilter(it.params[0]) && !civInfo.tech.isResearched(it.params[1])
|
matchesTerrainFilter(it.params[0]) && !civInfo.tech.isResearched(it.params[1])
|
||||||
} -> false
|
} -> false
|
||||||
improvement.uniqueObjects.any {
|
improvement.uniqueObjects.any {
|
||||||
@ -437,8 +447,8 @@ open class TileInfo {
|
|||||||
return when {
|
return when {
|
||||||
improvement.name == this.improvement -> false
|
improvement.name == this.improvement -> false
|
||||||
isCityCenter() -> false
|
isCityCenter() -> false
|
||||||
improvement.uniqueObjects.filter { it.placeholderText == "Cannot be built on [] tiles" }.any {
|
improvement.getMatchingUniques(UniqueType.CannotBuildOnTile).any {
|
||||||
unique -> matchesTerrainFilter(unique.params[0])
|
unique -> matchesTerrainFilter(unique.params[0])
|
||||||
} -> false
|
} -> false
|
||||||
|
|
||||||
// Road improvements can change on tiles with irremovable improvements - nothing else can, though.
|
// Road improvements can change on tiles with irremovable improvements - nothing else can, though.
|
||||||
@ -463,7 +473,7 @@ open class TileInfo {
|
|||||||
improvement.name == roadStatus.removeAction -> true
|
improvement.name == roadStatus.removeAction -> true
|
||||||
topTerrain.unbuildable && !improvement.isAllowedOnFeature(topTerrain.name) -> false
|
topTerrain.unbuildable && !improvement.isAllowedOnFeature(topTerrain.name) -> false
|
||||||
// DO NOT reverse this &&. isAdjacentToFreshwater() is a lazy which calls a function, and reversing it breaks the tests.
|
// DO NOT reverse this &&. isAdjacentToFreshwater() is a lazy which calls a function, and reversing it breaks the tests.
|
||||||
improvement.hasUnique("Can also be built on tiles adjacent to fresh water") && isAdjacentToFreshwater -> true
|
improvement.hasUnique(UniqueType.ImprovementBuildableByFreshWater) && isAdjacentToFreshwater -> true
|
||||||
|
|
||||||
// If an unique of this type exists, we want all to match (e.g. Hill _and_ Forest would be meaningful).
|
// If an unique of this type exists, we want all to match (e.g. Hill _and_ Forest would be meaningful).
|
||||||
improvement.uniqueObjects.filter { it.placeholderText == "Can only be built on [] tiles" }.let {
|
improvement.uniqueObjects.filter { it.placeholderText == "Can only be built on [] tiles" }.let {
|
||||||
@ -544,9 +554,8 @@ open class TileInfo {
|
|||||||
var bonus = getLastTerrain().defenceBonus
|
var bonus = getLastTerrain().defenceBonus
|
||||||
val tileImprovement = getTileImprovement()
|
val tileImprovement = getTileImprovement()
|
||||||
if (tileImprovement != null) {
|
if (tileImprovement != null) {
|
||||||
for (unique in tileImprovement.uniqueObjects)
|
for (unique in tileImprovement.getMatchingUniques(UniqueType.DefensiveBonus))
|
||||||
if (unique.placeholderText == "Gives a defensive bonus of []%")
|
bonus += unique.params[0].toFloat() / 100
|
||||||
bonus += unique.params[0].toFloat() / 100
|
|
||||||
}
|
}
|
||||||
return bonus
|
return bonus
|
||||||
}
|
}
|
||||||
@ -761,7 +770,7 @@ open class TileInfo {
|
|||||||
|
|
||||||
if (newResource.resourceType != ResourceType.Strategic) return
|
if (newResource.resourceType != ResourceType.Strategic) return
|
||||||
|
|
||||||
for (unique in newResource.getMatchingUniques(UniqueType.OverrideDepositAmountOnTileFilter)) {
|
for (unique in newResource.getMatchingUniques(UniqueType.ResourceAmountOnTiles)) {
|
||||||
if (matchesTerrainFilter(unique.params[0])) {
|
if (matchesTerrainFilter(unique.params[0])) {
|
||||||
resourceAmount = unique.params[1].toInt()
|
resourceAmount = unique.params[1].toInt()
|
||||||
return
|
return
|
||||||
|
@ -6,11 +6,10 @@ import com.unciv.UncivGame
|
|||||||
import com.unciv.logic.civilization.CityStateType
|
import com.unciv.logic.civilization.CityStateType
|
||||||
import com.unciv.models.ruleset.unique.Unique
|
import com.unciv.models.ruleset.unique.Unique
|
||||||
import com.unciv.models.ruleset.unique.UniqueTarget
|
import com.unciv.models.ruleset.unique.UniqueTarget
|
||||||
import com.unciv.models.stats.INamed
|
import com.unciv.models.ruleset.unique.UniqueType
|
||||||
import com.unciv.models.translations.squareBraceRegex
|
import com.unciv.models.translations.squareBraceRegex
|
||||||
import com.unciv.models.translations.tr
|
import com.unciv.models.translations.tr
|
||||||
import com.unciv.ui.civilopedia.FormattedLine
|
import com.unciv.ui.civilopedia.FormattedLine
|
||||||
import com.unciv.ui.civilopedia.ICivilopediaText
|
|
||||||
import com.unciv.ui.utils.Fonts
|
import com.unciv.ui.utils.Fonts
|
||||||
import com.unciv.ui.utils.colorFromRGB
|
import com.unciv.ui.utils.colorFromRGB
|
||||||
|
|
||||||
@ -177,7 +176,7 @@ class Nation : RulesetObject() {
|
|||||||
if (showResources) {
|
if (showResources) {
|
||||||
val allMercantileResources = ruleset.tileResources.values
|
val allMercantileResources = ruleset.tileResources.values
|
||||||
.filter { it.unique == "Can only be created by Mercantile City-States" // Deprecated 3.16.16
|
.filter { it.unique == "Can only be created by Mercantile City-States" // Deprecated 3.16.16
|
||||||
|| it.uniques.contains("Can only be created by Mercantile City-States") }
|
|| it.hasUnique(UniqueType.CityStateOnlyResource) }
|
||||||
|
|
||||||
if (allMercantileResources.isNotEmpty()) {
|
if (allMercantileResources.isNotEmpty()) {
|
||||||
textList += FormattedLine()
|
textList += FormattedLine()
|
||||||
|
@ -36,13 +36,26 @@ class Technology: RulesetObject() {
|
|||||||
val lineList = ArrayList<String>() // more readable than StringBuilder, with same performance for our use-case
|
val lineList = ArrayList<String>() // more readable than StringBuilder, with same performance for our use-case
|
||||||
for (unique in uniques) lineList += unique.tr()
|
for (unique in uniques) lineList += unique.tr()
|
||||||
|
|
||||||
for (improvement in ruleset.tileImprovements.values)
|
for (improvement in ruleset.tileImprovements.values) {
|
||||||
for (unique in improvement.uniqueObjects) {
|
for (unique in improvement.uniqueObjects) {
|
||||||
if (unique.placeholderText == "[] once [] is discovered" && unique.params.last() == name)
|
// Deprecated since 3.17.10
|
||||||
|
if (unique.isOfType(UniqueType.StatsWithTech) && unique.params.last() == name)
|
||||||
|
lineList += "[${unique.params[0]}] from every [${improvement.name}]"
|
||||||
|
else if (unique.isOfType(UniqueType.StatsOnTileWithTech) && unique.params.last() == name)
|
||||||
|
lineList += "[${unique.params[0]}] from every [${improvement.name}] on [${unique.params[1]}] tiles"
|
||||||
|
else
|
||||||
|
//
|
||||||
|
if (unique.isOfType(UniqueType.Stats)) {
|
||||||
|
val requiredTech = unique.conditionals.firstOrNull { it.isOfType(UniqueType.ConditionalTech) }?.params?.get(0)
|
||||||
|
if (requiredTech != name) continue
|
||||||
lineList += "[${unique.params[0]}] from every [${improvement.name}]"
|
lineList += "[${unique.params[0]}] from every [${improvement.name}]"
|
||||||
else if (unique.placeholderText == "[] on [] tiles once [] is discovered" && unique.params.last() == name)
|
} else if (unique.isOfType(UniqueType.ImprovementStatsOnTile)) {
|
||||||
|
val requiredTech = unique.conditionals.firstOrNull { it.isOfType(UniqueType.ConditionalTech) }?.params?.get(0)
|
||||||
|
if (requiredTech != name) continue
|
||||||
lineList += "[${unique.params[0]}] from every [${improvement.name}] on [${unique.params[1]}] tiles"
|
lineList += "[${unique.params[0]}] from every [${improvement.name}] on [${unique.params[1]}] tiles"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val viewingCiv = UncivGame.Current.worldScreen.viewingCiv
|
val viewingCiv = UncivGame.Current.worldScreen.viewingCiv
|
||||||
val enabledUnits = getEnabledUnits(viewingCiv)
|
val enabledUnits = getEnabledUnits(viewingCiv)
|
||||||
@ -176,12 +189,26 @@ class Technology: RulesetObject() {
|
|||||||
var wantEmpty = true
|
var wantEmpty = true
|
||||||
for (improvement in ruleset.tileImprovements.values)
|
for (improvement in ruleset.tileImprovements.values)
|
||||||
for (unique in improvement.uniqueObjects) {
|
for (unique in improvement.uniqueObjects) {
|
||||||
if (unique.placeholderText == "[] once [] is discovered" && unique.params.last() == name) {
|
// Deprecated since 3.17.10
|
||||||
if (wantEmpty) { lineList += FormattedLine(); wantEmpty = false }
|
if (unique.isOfType(UniqueType.StatsWithTech) && unique.params.last() == name) {
|
||||||
|
if (wantEmpty) { lineList += FormattedLine(); wantEmpty = false }
|
||||||
|
lineList += FormattedLine("[${unique.params[0]}] from every [${improvement.name}]",
|
||||||
|
link = improvement.makeLink())
|
||||||
|
} else if (unique.isOfType(UniqueType.StatsOnTileWithTech) && unique.params.last() == name) {
|
||||||
|
if (wantEmpty) { lineList += FormattedLine(); wantEmpty = false }
|
||||||
|
lineList += FormattedLine("[${unique.params[0]}] from every [${improvement.name}] on [${unique.params[1]}] tiles",
|
||||||
|
link = improvement.makeLink())
|
||||||
|
}
|
||||||
|
else
|
||||||
|
//
|
||||||
|
if (unique.isOfType(UniqueType.Stats)) {
|
||||||
|
val requiredTech = unique.conditionals.firstOrNull { it.isOfType(UniqueType.ConditionalTech) }?.params?.get(0)
|
||||||
|
if (requiredTech != name) continue
|
||||||
lineList += FormattedLine("[${unique.params[0]}] from every [${improvement.name}]",
|
lineList += FormattedLine("[${unique.params[0]}] from every [${improvement.name}]",
|
||||||
link = improvement.makeLink())
|
link = improvement.makeLink())
|
||||||
} else if (unique.placeholderText == "[] on [] tiles once [] is discovered" && unique.params.last() == name) {
|
} else if (unique.placeholderText == "[] on [] tiles") {
|
||||||
if (wantEmpty) { lineList += FormattedLine(); wantEmpty = false }
|
val requiredTech = unique.conditionals.firstOrNull { it.isOfType(UniqueType.ConditionalTech) }?.params?.get(0)
|
||||||
|
if (requiredTech != name) continue
|
||||||
lineList += FormattedLine("[${unique.params[0]}] from every [${improvement.name}] on [${unique.params[1]}] tiles",
|
lineList += FormattedLine("[${unique.params[0]}] from every [${improvement.name}] on [${unique.params[1]}] tiles",
|
||||||
link = improvement.makeLink())
|
link = improvement.makeLink())
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,11 @@
|
|||||||
package com.unciv.models.ruleset.tile
|
package com.unciv.models.ruleset.tile
|
||||||
|
|
||||||
import com.unciv.Constants
|
|
||||||
import com.unciv.UncivGame
|
import com.unciv.UncivGame
|
||||||
import com.unciv.logic.civilization.CivilizationInfo
|
import com.unciv.logic.civilization.CivilizationInfo
|
||||||
import com.unciv.logic.map.RoadStatus
|
import com.unciv.logic.map.RoadStatus
|
||||||
import com.unciv.models.ruleset.Belief
|
import com.unciv.models.ruleset.Belief
|
||||||
import com.unciv.models.ruleset.Ruleset
|
import com.unciv.models.ruleset.Ruleset
|
||||||
import com.unciv.models.ruleset.RulesetStatsObject
|
import com.unciv.models.ruleset.RulesetStatsObject
|
||||||
import com.unciv.models.ruleset.unique.Unique
|
|
||||||
import com.unciv.models.ruleset.unique.UniqueTarget
|
import com.unciv.models.ruleset.unique.UniqueTarget
|
||||||
import com.unciv.models.ruleset.unique.UniqueType
|
import com.unciv.models.ruleset.unique.UniqueType
|
||||||
import com.unciv.models.translations.tr
|
import com.unciv.models.translations.tr
|
||||||
@ -67,9 +65,9 @@ class TileImprovement : RulesetStatsObject() {
|
|||||||
return lines.joinToString("\n")
|
return lines.joinToString("\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isGreatImprovement() = hasUnique("Great Improvement")
|
fun isGreatImprovement() = hasUnique(UniqueType.GreatImprovement)
|
||||||
fun isRoad() = RoadStatus.values().any { it != RoadStatus.None && it.name == this.name }
|
fun isRoad() = RoadStatus.values().any { it != RoadStatus.None && it.name == this.name }
|
||||||
fun isAncientRuinsEquivalent() = hasUnique("Provides a random bonus when entered")
|
fun isAncientRuinsEquivalent() = hasUnique(UniqueType.IsAncientRuinsEquivalent)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check: Is this improvement allowed on a [given][name] terrain feature?
|
* Check: Is this improvement allowed on a [given][name] terrain feature?
|
||||||
@ -81,11 +79,7 @@ class TileImprovement : RulesetStatsObject() {
|
|||||||
* so this check is done in conjunction - for the user, success means he does not need to remove
|
* so this check is done in conjunction - for the user, success means he does not need to remove
|
||||||
* a terrain feature, thus the unique name.
|
* a terrain feature, thus the unique name.
|
||||||
*/
|
*/
|
||||||
fun isAllowedOnFeature(name: String): Boolean {
|
fun isAllowedOnFeature(name: String) = getMatchingUniques(UniqueType.NoFeatureRemovalNeeded).any { it.params[0] == name }
|
||||||
return uniqueObjects.filter { it.placeholderText == "Does not need removal of []"
|
|
||||||
&& it.params[0] == name
|
|
||||||
}.any()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun matchesFilter(filter: String): Boolean {
|
fun matchesFilter(filter: String): Boolean {
|
||||||
return when (filter) {
|
return when (filter) {
|
||||||
|
@ -5,7 +5,6 @@ import com.unciv.logic.city.CityInfo
|
|||||||
import com.unciv.models.stats.Stats
|
import com.unciv.models.stats.Stats
|
||||||
import com.unciv.models.translations.*
|
import com.unciv.models.translations.*
|
||||||
import com.unciv.logic.civilization.CivilizationInfo
|
import com.unciv.logic.civilization.CivilizationInfo
|
||||||
import com.unciv.models.ruleset.Ruleset
|
|
||||||
|
|
||||||
|
|
||||||
class Unique(val text: String, val sourceObjectType: UniqueTarget? = null, val sourceObjectName: String? = null) {
|
class Unique(val text: String, val sourceObjectType: UniqueTarget? = null, val sourceObjectName: String? = null) {
|
||||||
@ -22,6 +21,8 @@ class Unique(val text: String, val sourceObjectType: UniqueTarget? = null, val s
|
|||||||
}
|
}
|
||||||
val conditionals: List<Unique> = text.getConditionals()
|
val conditionals: List<Unique> = text.getConditionals()
|
||||||
|
|
||||||
|
val allParams = params + conditionals.flatMap { it.params }
|
||||||
|
|
||||||
fun isOfType(uniqueType: UniqueType) = uniqueType == type
|
fun isOfType(uniqueType: UniqueType) = uniqueType == type
|
||||||
|
|
||||||
fun conditionalsApply(civInfo: CivilizationInfo? = null, city: CityInfo? = null): Boolean {
|
fun conditionalsApply(civInfo: CivilizationInfo? = null, city: CityInfo? = null): Boolean {
|
||||||
@ -53,7 +54,15 @@ class Unique(val text: String, val sourceObjectType: UniqueTarget? = null, val s
|
|||||||
state.civInfo != null && state.civInfo.getEraNumber() >= state.civInfo.gameInfo.ruleSet.eras[condition.params[0]]!!.eraNumber
|
state.civInfo != null && state.civInfo.getEraNumber() >= state.civInfo.gameInfo.ruleSet.eras[condition.params[0]]!!.eraNumber
|
||||||
UniqueType.ConditionalDuringEra ->
|
UniqueType.ConditionalDuringEra ->
|
||||||
state.civInfo != null && state.civInfo.getEraNumber() == state.civInfo.gameInfo.ruleSet.eras[condition.params[0]]!!.eraNumber
|
state.civInfo != null && state.civInfo.getEraNumber() == state.civInfo.gameInfo.ruleSet.eras[condition.params[0]]!!.eraNumber
|
||||||
|
UniqueType.ConditionalTech ->
|
||||||
|
state.civInfo != null && state.civInfo.tech.isResearched(condition.params[0])
|
||||||
|
UniqueType.ConditionalNoTech ->
|
||||||
|
state.civInfo != null && !state.civInfo.tech.isResearched(condition.params[0])
|
||||||
|
UniqueType.ConditionalPolicy ->
|
||||||
|
state.civInfo != null && state.civInfo.policies.isAdopted(condition.params[0])
|
||||||
|
UniqueType.ConditionalNoPolicy ->
|
||||||
|
state.civInfo != null && !state.civInfo.policies.isAdopted(condition.params[0])
|
||||||
|
|
||||||
UniqueType.ConditionalSpecialistCount ->
|
UniqueType.ConditionalSpecialistCount ->
|
||||||
state.cityInfo != null && state.cityInfo.population.getNumberOfSpecialists() >= condition.params[0].toInt()
|
state.cityInfo != null && state.cityInfo.population.getNumberOfSpecialists() >= condition.params[0].toInt()
|
||||||
|
|
||||||
|
@ -222,6 +222,17 @@ enum class UniqueParameterType(val parameterName:String) {
|
|||||||
else -> UniqueType.UniqueComplianceErrorSeverity.RulesetSpecific
|
else -> UniqueType.UniqueComplianceErrorSeverity.RulesetSpecific
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Policy("policy") {
|
||||||
|
override fun getErrorSeverity(
|
||||||
|
parameterText: String,
|
||||||
|
ruleset: Ruleset
|
||||||
|
): UniqueType.UniqueComplianceErrorSeverity? {
|
||||||
|
return when (parameterText) {
|
||||||
|
in ruleset.policies -> 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):
|
||||||
|
@ -62,7 +62,7 @@ enum class UniqueType(val text:String, vararg targets: UniqueTarget) {
|
|||||||
|
|
||||||
/////// Stat providing uniques
|
/////// Stat providing uniques
|
||||||
|
|
||||||
Stats("[stats]", UniqueTarget.Global, UniqueTarget.FollowerBelief),
|
Stats("[stats]", UniqueTarget.Global, UniqueTarget.FollowerBelief, UniqueTarget.Improvement),
|
||||||
StatsPerCity("[stats] [cityFilter]", UniqueTarget.Global),
|
StatsPerCity("[stats] [cityFilter]", UniqueTarget.Global),
|
||||||
@Deprecated("As of 3.16.16 - removed as of 3.17.11", ReplaceWith("[stats] <if this city has at least [amount] specialists>"), DeprecationLevel.ERROR)
|
@Deprecated("As of 3.16.16 - removed as of 3.17.11", ReplaceWith("[stats] <if this city has at least [amount] specialists>"), DeprecationLevel.ERROR)
|
||||||
StatBonusForNumberOfSpecialists("[stats] if this city has at least [amount] specialists", UniqueTarget.Global),
|
StatBonusForNumberOfSpecialists("[stats] if this city has at least [amount] specialists", UniqueTarget.Global),
|
||||||
@ -175,7 +175,6 @@ enum class UniqueType(val text:String, vararg targets: UniqueTarget) {
|
|||||||
RequiresAnotherBuilding("Requires a [buildingName] in this city", UniqueTarget.Building),
|
RequiresAnotherBuilding("Requires a [buildingName] in this city", UniqueTarget.Building),
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////// UNIT UNIQUES /////////////////////////////////////////
|
///////////////////////////////////////// UNIT UNIQUES /////////////////////////////////////////
|
||||||
|
|
||||||
FoundCity("Founds a new city", UniqueTarget.Unit),
|
FoundCity("Founds a new city", UniqueTarget.Unit),
|
||||||
@ -306,13 +305,41 @@ enum class UniqueType(val text:String, vararg targets: UniqueTarget) {
|
|||||||
FreshWater("Fresh water", UniqueTarget.Terrain),
|
FreshWater("Fresh water", UniqueTarget.Terrain),
|
||||||
RoughTerrain("Rough terrain", UniqueTarget.Terrain),
|
RoughTerrain("Rough terrain", UniqueTarget.Terrain),
|
||||||
|
|
||||||
// Resource uniques
|
/////// Resource uniques
|
||||||
OverrideDepositAmountOnTileFilter("Deposits in [tileFilter] tiles always provide [amount] resources", UniqueTarget.Resource),
|
ResourceAmountOnTiles("Deposits in [tileFilter] tiles always provide [amount] resources", UniqueTarget.Resource),
|
||||||
|
CityStateOnlyResource("Can only be created by Mercantile City-States", UniqueTarget.Resource),
|
||||||
|
|
||||||
|
////// Improvement uniques
|
||||||
|
ImprovementBuildableByFreshWater("Can also be built on tiles adjacent to fresh water", UniqueTarget.Improvement),
|
||||||
|
ImprovementStatsOnTile("[stats] from [tileFilter] tiles", UniqueTarget.Improvement),
|
||||||
|
@Deprecated("As of 3.17.10", ReplaceWith("[stats] from [tileFilter] tiles <after discovering [tech]>"), DeprecationLevel.WARNING)
|
||||||
|
StatsOnTileWithTech("[stats] on [tileFilter] tiles once [tech] is discovered", UniqueTarget.Improvement),
|
||||||
|
@Deprecated("As of 3.17.10", ReplaceWith("[stats] <after discovering [tech]>"), DeprecationLevel.WARNING)
|
||||||
|
StatsWithTech("[stats] once [tech] is discovered", UniqueTarget.Improvement, UniqueTarget.Building),
|
||||||
|
ImprovementStatsForAdjacencies("[stats] for each adjacent [tileFilter]", UniqueTarget.Improvement),
|
||||||
|
|
||||||
|
CanBuildOutsideBorders("Can be built outside your borders", UniqueTarget.Improvement),
|
||||||
|
CanBuildJustOutsideBorders("Can be built just outside your borders", UniqueTarget.Improvement),
|
||||||
|
RequiresTechToBuildOnTile("Cannot be built on [tileFilter] tiles until [tech] is discovered", UniqueTarget.Improvement),
|
||||||
|
CannotBuildOnTile("Cannot be built on [tileFilter] tiles", UniqueTarget.Improvement),
|
||||||
|
NoFeatureRemovalNeeded("Does not need removal of [tileFilter]", UniqueTarget.Improvement),
|
||||||
|
|
||||||
|
DefensiveBonus("Gives a defensive bonus of [amount]%", UniqueTarget.Improvement),
|
||||||
|
ImprovementMaintenance("Costs [amount] gold per turn when in your territory", UniqueTarget.Improvement), // Unused
|
||||||
|
DamagesAdjacentEnemyUnits("Deal [amount] damage to adjacent enemy units", UniqueTarget.Improvement),
|
||||||
|
@Deprecated("As of 3.17.10", ReplaceWith("Adjacent enemy units ending their turn take [30] damage"), DeprecationLevel.WARNING)
|
||||||
|
DamagesAdjacentEnemyUnitsForExactlyThirtyDamage("Deal 30 damage to adjacent enemy units", UniqueTarget.Improvement),
|
||||||
|
|
||||||
|
GreatImprovement("Great Improvement", UniqueTarget.Improvement),
|
||||||
|
IsAncientRuinsEquivalent("Provides a random bonus when entered", UniqueTarget.Improvement),
|
||||||
|
|
||||||
|
Unpillagable("Unpillagable", UniqueTarget.Improvement),
|
||||||
|
Indestructible("Indestructible", UniqueTarget.Improvement),
|
||||||
|
|
||||||
///////////////////////////////////////// CONDITIONALS /////////////////////////////////////////
|
///////////////////////////////////////// CONDITIONALS /////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
// civ conditionals
|
/////// civ conditionals
|
||||||
ConditionalWar("when at war", UniqueTarget.Conditional),
|
ConditionalWar("when at war", UniqueTarget.Conditional),
|
||||||
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),
|
||||||
@ -321,11 +348,16 @@ enum class UniqueType(val text:String, vararg targets: UniqueTarget) {
|
|||||||
ConditionalDuringEra("during the [era]", UniqueTarget.Conditional),
|
ConditionalDuringEra("during the [era]", UniqueTarget.Conditional),
|
||||||
ConditionalBeforeEra("before the [era]", UniqueTarget.Conditional),
|
ConditionalBeforeEra("before the [era]", UniqueTarget.Conditional),
|
||||||
ConditionalStartingFromEra("starting from the [era]", UniqueTarget.Conditional),
|
ConditionalStartingFromEra("starting from the [era]", UniqueTarget.Conditional),
|
||||||
|
|
||||||
|
ConditionalTech("after discovering [tech]", UniqueTarget.Conditional),
|
||||||
|
ConditionalNoTech("before discovering [tech]", UniqueTarget.Conditional),
|
||||||
|
ConditionalPolicy("after adopting [policy]", UniqueTarget.Conditional),
|
||||||
|
ConditionalNoPolicy("before adopting [policy]", 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),
|
||||||
ConditionalVsUnits("vs [mapUnitFilter] units", UniqueTarget.Conditional),
|
ConditionalVsUnits("vs [mapUnitFilter] units", UniqueTarget.Conditional),
|
||||||
@ -333,9 +365,8 @@ enum class UniqueType(val text:String, vararg targets: UniqueTarget) {
|
|||||||
ConditionalAttacking("when attacking", UniqueTarget.Conditional),
|
ConditionalAttacking("when attacking", UniqueTarget.Conditional),
|
||||||
ConditionalDefending("when defending", UniqueTarget.Conditional),
|
ConditionalDefending("when defending", UniqueTarget.Conditional),
|
||||||
ConditionalInTiles("when fighting in [tileFilter] tiles", UniqueTarget.Conditional),
|
ConditionalInTiles("when fighting in [tileFilter] tiles", UniqueTarget.Conditional),
|
||||||
// ConditionalIntercepting("when intercepting", UniqueTarget.Conditional),
|
|
||||||
|
|
||||||
// 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),
|
||||||
|
|
||||||
|
@ -7,4 +7,8 @@ open class NamedStats : Stats(), INamed {
|
|||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun cloneStats(): Stats {
|
||||||
|
return clone()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -213,7 +213,7 @@ class Translations : LinkedHashMap<String, TranslationEntry>(){
|
|||||||
// Whenever this string is changed, it should also be changed in the translation files!
|
// Whenever this string is changed, it should also be changed in the translation files!
|
||||||
// It is mostly used as the template for translating the order of conditionals
|
// It is mostly used as the template for translating the order of conditionals
|
||||||
const val englishConditionalOrderingString =
|
const val englishConditionalOrderingString =
|
||||||
"<for [mapUnitFilter] units> <vs cities> <vs [mapUnitFilter] units> <when fighting in [tileFilter] tiles> <when attacking> <when defending> <if this city has at least [amount] specialists> <when at war> <when not at war> <while the empire is happy> <during a Golden Age> <during the [era]> <before the [era]> <starting from the [era]>"
|
"<for [mapUnitFilter] units> <vs cities> <vs [mapUnitFilter] units> <when fighting in [tileFilter] tiles> <when attacking> <when defending> <if this city has at least [amount] specialists> <when at war> <when not at war> <while the empire is happy> <during a Golden Age> <during the [era]> <before the [era]> <starting from the [era]> <with [techOrPolicy]> <without [techOrPolicy]>"
|
||||||
const val conditionalUniqueOrderString = "ConditionalsPlacement"
|
const val conditionalUniqueOrderString = "ConditionalsPlacement"
|
||||||
const val shouldCapitalizeString = "StartWithCapitalLetter"
|
const val shouldCapitalizeString = "StartWithCapitalLetter"
|
||||||
}
|
}
|
||||||
|
@ -154,7 +154,7 @@ class FormattedLine (
|
|||||||
val ruleSet = getCurrentRuleset()
|
val ruleSet = getCurrentRuleset()
|
||||||
if (allObjectNamesCategoryMap == null || rulesetCachedInNameMap !== ruleSet)
|
if (allObjectNamesCategoryMap == null || rulesetCachedInNameMap !== ruleSet)
|
||||||
allObjectNamesCategoryMap = initNamesCategoryMap(ruleSet)
|
allObjectNamesCategoryMap = initNamesCategoryMap(ruleSet)
|
||||||
for (parameter in unique.params) {
|
for (parameter in unique.params + unique.conditionals.flatMap { it.params }) {
|
||||||
val category = allObjectNamesCategoryMap!![parameter] ?: continue
|
val category = allObjectNamesCategoryMap!![parameter] ?: continue
|
||||||
return category.name + "/" + parameter
|
return category.name + "/" + parameter
|
||||||
}
|
}
|
||||||
|
@ -65,12 +65,14 @@ class TechButton(techName:String, private val techManager: TechManager, isWorldS
|
|||||||
})
|
})
|
||||||
|
|
||||||
for (improvement in ruleset.tileImprovements.values
|
for (improvement in ruleset.tileImprovements.values
|
||||||
.filter {
|
.filter {
|
||||||
it.techRequired == techName || it.uniqueObjects.any { u -> u.params.contains(techName) }
|
it.techRequired == techName
|
||||||
|| it.uniqueObjects.any { it.placeholderText == "[] once [] is discovered" && it.params[1] == techName }
|
|| it.uniqueObjects.any { u -> u.allParams.contains(techName) }
|
||||||
}
|
}
|
||||||
.filter { it.uniqueTo == null || it.uniqueTo == civName })
|
.filter { it.uniqueTo == null || it.uniqueTo == civName }
|
||||||
|
) {
|
||||||
techEnabledIcons.add(ImageGetter.getImprovementIcon(improvement.name, techIconSize))
|
techEnabledIcons.add(ImageGetter.getImprovementIcon(improvement.name, techIconSize))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
for (resource in ruleset.tileResources.values.filter { it.revealedBy == techName })
|
for (resource in ruleset.tileResources.values.filter { it.revealedBy == techName })
|
||||||
@ -78,7 +80,7 @@ class TechButton(techName:String, private val techManager: TechManager, isWorldS
|
|||||||
|
|
||||||
for (unique in tech.uniques)
|
for (unique in tech.uniques)
|
||||||
techEnabledIcons.add(ImageGetter.getImage("OtherIcons/Star")
|
techEnabledIcons.add(ImageGetter.getImage("OtherIcons/Star")
|
||||||
.apply { color = Color.BLACK }.surroundWithCircle(techIconSize))
|
.apply { color = Color.BLACK }.surroundWithCircle(techIconSize))
|
||||||
|
|
||||||
if (isWorldScreen) rightSide.add(techEnabledIcons)
|
if (isWorldScreen) rightSide.add(techEnabledIcons)
|
||||||
else rightSide.add(techEnabledIcons)
|
else rightSide.add(techEnabledIcons)
|
||||||
|
@ -748,7 +748,7 @@ object UnitActions {
|
|||||||
fun canPillage(unit: MapUnit, tile: TileInfo): Boolean {
|
fun canPillage(unit: MapUnit, tile: TileInfo): Boolean {
|
||||||
val tileImprovement = tile.getTileImprovement()
|
val tileImprovement = tile.getTileImprovement()
|
||||||
// City ruins, Ancient Ruins, Barbarian Camp, City Center marked in json
|
// City ruins, Ancient Ruins, Barbarian Camp, City Center marked in json
|
||||||
if (tileImprovement == null || tileImprovement.hasUnique("Unpillagable")) return false
|
if (tileImprovement == null || tileImprovement.hasUnique(UniqueType.Unpillagable)) return false
|
||||||
val tileOwner = tile.getOwner()
|
val tileOwner = tile.getOwner()
|
||||||
// Can't pillage friendly tiles, just like you can't attack them - it's an 'act of war' thing
|
// Can't pillage friendly tiles, just like you can't attack them - it's an 'act of war' thing
|
||||||
return tileOwner == null || unit.civInfo.isAtWarWith(tileOwner)
|
return tileOwner == null || unit.civInfo.isAtWarWith(tileOwner)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user