From 298dbcb3ee7e1ff65afb0b48344315831382e0a9 Mon Sep 17 00:00:00 2001 From: SomeTroglodyte <63000004+SomeTroglodyte@users.noreply.github.com> Date: Sun, 6 Jun 2021 11:40:02 +0200 Subject: [PATCH] More power to improvement uniques (resourceTerrainAllow-be-gone) (#4024) * More flexibility for modding improvements (tileFilter), deprecate resourceTerrainAllow * More tileFilter and improvement uniques - Translations * Update template.properties * More tileFilter and improvement uniques - Revert and/or inside unique parameter --- .../Civ V - Vanilla/TileImprovements.json | 3 +-- .../jsons/translations/German.properties | 8 ++++++++ .../jsons/translations/template.properties | 7 +++++++ .../logic/automation/WorkerAutomation.kt | 2 +- core/src/com/unciv/logic/map/TileInfo.kt | 18 +++++++++++++++-- .../com/unciv/models/ruleset/tile/Terrain.kt | 2 +- .../models/ruleset/tile/TileImprovement.kt | 20 +++++++++++++++++++ 7 files changed, 54 insertions(+), 6 deletions(-) diff --git a/android/assets/jsons/Civ V - Vanilla/TileImprovements.json b/android/assets/jsons/Civ V - Vanilla/TileImprovements.json index 4ebdde436b..6087ce72d6 100644 --- a/android/assets/jsons/Civ V - Vanilla/TileImprovements.json +++ b/android/assets/jsons/Civ V - Vanilla/TileImprovements.json @@ -42,10 +42,9 @@ // Resource-specific { "name": "Camp", - "resourceTerrainAllow": ["Forest"], "turnsToBuild": 7, "techRequired": "Trapping", - "uniques": ["[+1 Gold] once [Economics] is discovered"], + "uniques": ["Does not need removal of [Forest]","[+1 Gold] once [Economics] is discovered"], "shortcutKey": "C" }, { diff --git a/android/assets/jsons/translations/German.properties b/android/assets/jsons/translations/German.properties index 2e89d55a68..2d2ef5b36b 100644 --- a/android/assets/jsons/translations/German.properties +++ b/android/assets/jsons/translations/German.properties @@ -680,6 +680,10 @@ Water resource = Wasser-Ressource River = Fluss Fresh water = Frischwasser non-fresh water = nicht frisches Wasser +Coastal = Küsten +Bonus resource = Bonus-ressource +Strategic resource = Strategische Ressource +Luxury resource = Luxus-ressource Wonders = Wunder Base values = Grundwerte @@ -988,6 +992,9 @@ Must be on [terrain] = Muss sich auf [terrain] befinden +[amount]% vs [unitType] = +[amount]% vs [unitType] +[amount] Movement for all [unitType] units = +[amount] Bewegung für alle "[unitType]"-Einheiten +[amount]% Production when constructing [param] = +[amount]% Produktion, für alle Bauten vom Typ: [param] +Can only be built on [tileFilter] tiles = Kann nur auf [tileFilter]-Feldern gebaut werden +Cannot be built on [tileFilter] tiles = Kann nicht auf [tileFilter]-Feldern gebaut werden +Does not need removal of [feature] = Hierfür muß [feature] nicht entfernt werden # City filters in this city = in dieser Stadt @@ -3151,6 +3158,7 @@ Can be built just outside your borders = Kann, auch ein Feld weit, außerhalb De Citadel = Zitadelle Can only be built on Coastal tiles = Kann nur entlang der Küstenlinie gebaut werden + Moai = Moai Cannot be built on bonus resource = Darf nicht auf Bonus-Ressourcen gebaut werden diff --git a/android/assets/jsons/translations/template.properties b/android/assets/jsons/translations/template.properties index 4b3aeed928..0dc4f2f662 100644 --- a/android/assets/jsons/translations/template.properties +++ b/android/assets/jsons/translations/template.properties @@ -674,6 +674,10 @@ Water resource = River = Fresh water = non-fresh water = +Coastal = +Bonus resource = +Strategic resource = +Luxury resource = Wonders = Base values = @@ -979,6 +983,9 @@ Must be on [terrain] = +[amount]% vs [unitType] = +[amount] Movement for all [unitType] units = +[amount]% Production when constructing [param] = +Can only be built on [tileFilter] tiles = +Cannot be built on [tileFilter] tiles = +Does not need removal of [feature] = # City filters in this city = diff --git a/core/src/com/unciv/logic/automation/WorkerAutomation.kt b/core/src/com/unciv/logic/automation/WorkerAutomation.kt index 936de404dc..9369a44b44 100644 --- a/core/src/com/unciv/logic/automation/WorkerAutomation.kt +++ b/core/src/com/unciv/logic/automation/WorkerAutomation.kt @@ -227,7 +227,7 @@ class WorkerAutomation(val unit: MapUnit) { ?: return false val resourceImprovement = civInfo.gameInfo.ruleSet.tileImprovements[resourceImprovementName] ?: return false - return tile.terrainFeatures.any { resourceImprovement.resourceTerrainAllow.contains(it) } + return tile.terrainFeatures.any { resourceImprovement.isAllowedOnFeature(it) } } private fun isAcceptableTileForFort(tile: TileInfo, civInfo: CivilizationInfo): Boolean { diff --git a/core/src/com/unciv/logic/map/TileInfo.kt b/core/src/com/unciv/logic/map/TileInfo.kt index 84fccb19d9..93da2d2bcc 100644 --- a/core/src/com/unciv/logic/map/TileInfo.kt +++ b/core/src/com/unciv/logic/map/TileInfo.kt @@ -356,6 +356,9 @@ open class TileInfo { isCityCenter() -> false "Cannot be built on bonus resource" in improvement.uniques && resource != null && getTileResource().resourceType == ResourceType.Bonus -> false + improvement.uniqueObjects.filter { it.placeholderText == "Cannot be built on [] tiles" }.any { + unique -> matchesUniqueFilter(unique.params[0]) + } -> false // Road improvements can change on tiles with irremovable improvements - nothing else can, though. improvement.name != RoadStatus.Railroad.name && improvement.name != RoadStatus.Railroad.name @@ -376,22 +379,33 @@ open class TileInfo { improvement.name == "Railroad" && this.roadStatus != RoadStatus.Railroad && !isWater -> true improvement.name == "Remove Road" && this.roadStatus == RoadStatus.Road -> true improvement.name == "Remove Railroad" && this.roadStatus == RoadStatus.Railroad -> true - topTerrain.unbuildable && (topTerrain.name !in improvement.resourceTerrainAllow) -> 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. improvement.hasUnique("Can also be built on tiles adjacent to fresh water") && isAdjacentToFreshwater -> true "Can only be built on Coastal tiles" in improvement.uniques && isCoastalTile() -> true + improvement.uniqueObjects.filter { it.placeholderText == "Can only be built on [] tiles" }.any { + unique -> !matchesUniqueFilter(unique.params[0]) + } -> false else -> resourceIsVisible && getTileResource().improvement == improvement.name } } + /** + * Implementation of _`tileFilter`_ + * @see tileFilter + */ fun matchesUniqueFilter(filter: String, civInfo: CivilizationInfo? = null): Boolean { - return filter == baseTerrain + return filter == "All" + || filter == baseTerrain || filter == "River" && isAdjacentToRiver() || terrainFeatures.contains(filter) || baseTerrainObject.uniques.contains(filter) || improvement == filter + || resource == filter + || (resource != null && getTileResource().resourceType.name + " resource" == filter) || filter == "Water" && isWater || filter == "Land" && isLand + || filter == "Coastal" && isCoastalTile() || filter == naturalWonder || terrainFeatures.isNotEmpty() && getTerrainFeatures().last().uniques.contains(filter) || civInfo != null && hasViewableResource(civInfo) && resource == filter diff --git a/core/src/com/unciv/models/ruleset/tile/Terrain.kt b/core/src/com/unciv/models/ruleset/tile/Terrain.kt index 4d83370ab4..987f208c61 100644 --- a/core/src/com/unciv/models/ruleset/tile/Terrain.kt +++ b/core/src/com/unciv/models/ruleset/tile/Terrain.kt @@ -23,7 +23,7 @@ class Terrain : NamedStats() { /** Used by Natural Wonders: it is the baseTerrain on top of which the Natural Wonder is placed */ val turnsInto: String? = null - /** Uniques (currently used only for Natural Wonders) */ + /** Uniques (Properties such as Temp/humidity, Fresh water, elevation, rough, defense, Natural Wonder specials) */ val uniques = ArrayList() val uniqueObjects: List by lazy { uniques.map { Unique(it) } } diff --git a/core/src/com/unciv/models/ruleset/tile/TileImprovement.kt b/core/src/com/unciv/models/ruleset/tile/TileImprovement.kt index a6cb886b95..83d44358ac 100644 --- a/core/src/com/unciv/models/ruleset/tile/TileImprovement.kt +++ b/core/src/com/unciv/models/ruleset/tile/TileImprovement.kt @@ -14,6 +14,7 @@ class TileImprovement : NamedStats() { // Used only for Camp - but avoid hardcoded comparison and *allow modding* // Terrain Features that need not be cleared if the improvement enables a resource + @Deprecated("As of 3.14.15") var resourceTerrainAllow: Collection = ArrayList() var techRequired: String? = null @@ -68,5 +69,24 @@ class TileImprovement : NamedStats() { fun hasUnique(unique: String) = uniques.contains(unique) fun isGreatImprovement() = hasUnique("Great Improvement") + + /** + * Check: Is this improvement allowed on a [given][name] terrain feature? + * + * Uses both _legacy_ [resourceTerrainAllow] and unique "Does not need removal of []" + * + * Background: This not used for e.g. a lumbermill - it derives the right to be placed on forest + * from [terrainsCanBeBuiltOn]. Other improvements may be candidates without fulfilling the + * [terrainsCanBeBuiltOn] check - e.g. they are listed by a resource as 'their' improvement. + * I such cases, the 'unbuildable' property of the Terrain feature might prevent the improvement, + * 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. + */ + fun isAllowedOnFeature(name: String): Boolean { + if (name in resourceTerrainAllow) return true + return uniqueObjects.filter { it.placeholderText == "Does not need removal of []" + && it.params[0] == name + }.any() + } }