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
This commit is contained in:
SomeTroglodyte
2021-06-06 11:40:02 +02:00
committed by GitHub
parent dc8657dc02
commit 298dbcb3ee
7 changed files with 54 additions and 6 deletions

View File

@ -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 {

View File

@ -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 <a href="https://github.com/yairm210/Unciv/wiki/uniques#user-content-tilefilter">tileFilter</a>
*/
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

View File

@ -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<String>()
val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it) } }

View File

@ -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<String> = 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()
}
}