Farms near freshwater (#3063)
* Farms near freshwater * Farm now has unique "Can also be built on tiles adjacent to fresh water" https://civilization.fandom.com/wiki/Farm_(Civ5) Even snow: https://www.reddit.com/r/civ/comments/11qtko/farms_on_snow/ Hill+Farm, Snow+Farm, Tundra+Farm sprites by THE BUCKETEER and Ravignir from discord * fields improvingTech and improvingTechStats converted into uniques e.g.: "[+1 Production] once [Scientific Theory] is discovered" "[+1 Food] on [fresh water] tiles once [Civil Service] is discovered" "[+1 Food] on [non-fresh water] tiles once [Fertilizer] is discovered" * ai will build trading posts and farms in snow and tundra if it has no better tiles to work on * "Provides a one-time Production bonus to the closest city when cut down" unique for forest * update template.properties
BIN
android/Images/TileSets/FantasyHex/Tiles/Hill+Farm.png
Normal file
After Width: | Height: | Size: 983 B |
BIN
android/Images/TileSets/FantasyHex/Tiles/Snow+Farm.png
Normal file
After Width: | Height: | Size: 953 B |
BIN
android/Images/TileSets/FantasyHex/Tiles/Tundra+Farm.png
Normal file
After Width: | Height: | Size: 932 B |
Before Width: | Height: | Size: 881 KiB After Width: | Height: | Size: 882 KiB |
Before Width: | Height: | Size: 495 KiB After Width: | Height: | Size: 496 KiB |
|
@ -87,7 +87,8 @@
|
|||
"unbuildable": true,
|
||||
"defenceBonus": 0.25,
|
||||
"occursOn": ["Tundra","Plains","Grassland","Hill"],
|
||||
"rough": true
|
||||
"rough": true,
|
||||
"uniques": ["Provides a one-time Production bonus to the closest city when cut down"]
|
||||
},
|
||||
{
|
||||
"name": "Jungle",
|
||||
|
|
|
@ -6,8 +6,7 @@
|
|||
"food": 1,
|
||||
"turnsToBuild": 7,
|
||||
"techRequired": "Agriculture",
|
||||
"improvingTech": "Fertilizer",
|
||||
"improvingTechStats": {"food": 1}
|
||||
"uniques": ["Can also be built on tiles adjacent to fresh water", "[+1 Food] on [fresh water] tiles once [Civil Service] is discovered", "[+1 Food] on [non-fresh water] tiles once [Fertilizer] is discovered"],
|
||||
},
|
||||
{
|
||||
"name": "Lumber mill",
|
||||
|
@ -15,8 +14,7 @@
|
|||
"production": 1,
|
||||
"turnsToBuild": 7,
|
||||
"techRequired": "Construction",
|
||||
"improvingTech": "Steam Power",
|
||||
"improvingTechStats": {"production": 1}
|
||||
"uniques": ["[+1 Production] once [Scientific Theory] is discovered"]
|
||||
},
|
||||
{
|
||||
"name": "Mine",
|
||||
|
@ -24,8 +22,7 @@
|
|||
"production": 1,
|
||||
"turnsToBuild": 7,
|
||||
"techRequired": "Mining",
|
||||
"improvingTech": "Chemistry",
|
||||
"improvingTechStats": {"production": 1}
|
||||
"uniques": ["[+1 Production] once [Chemistry] is discovered"]
|
||||
},
|
||||
{
|
||||
"name": "Trading post",
|
||||
|
@ -33,8 +30,7 @@
|
|||
"gold": 1,
|
||||
"turnsToBuild": 7,
|
||||
"techRequired": "Guilds",
|
||||
"improvingTech": "Economics",
|
||||
"improvingTechStats": {"gold": 1}
|
||||
"uniques": ["[+1 Gold] once [Economics] is discovered"]
|
||||
},
|
||||
|
||||
// Resource-specific
|
||||
|
@ -43,8 +39,7 @@
|
|||
"resourceTerrainAllow": ["Forest"],
|
||||
"turnsToBuild": 7,
|
||||
"techRequired": "Trapping",
|
||||
"improvingTech": "Economics",
|
||||
"improvingTechStats": {"gold": 1}
|
||||
"uniques": ["[+1 Gold] once [Economics] is discovered"]
|
||||
},
|
||||
{
|
||||
"name": "Oil well",
|
||||
|
@ -55,31 +50,27 @@
|
|||
"name": "Pasture",
|
||||
"turnsToBuild": 8,
|
||||
"techRequired": "Animal Husbandry",
|
||||
"improvingTech": "Fertilizer",
|
||||
"improvingTechStats": {"food": 1}
|
||||
"uniques": ["[+1 Food] once [Fertilizer] is discovered"]
|
||||
},
|
||||
{
|
||||
"name": "Plantation",
|
||||
"turnsToBuild": 6,
|
||||
"gold": 1,
|
||||
"techRequired": "Calendar",
|
||||
"improvingTech": "Fertilizer",
|
||||
"improvingTechStats": {"food": 1}
|
||||
"uniques": ["[+1 Food] once [Fertilizer] is discovered"]
|
||||
},
|
||||
{
|
||||
"name": "Quarry",
|
||||
"turnsToBuild": 8,
|
||||
"techRequired": "Masonry",
|
||||
"improvingTech": "Chemistry",
|
||||
"improvingTechStats": {"production": 1}
|
||||
"uniques": ["[+1 Production] once [Chemistry] is discovered"]
|
||||
},
|
||||
{
|
||||
"name": "Fishing Boats",
|
||||
"terrainsCanBeBuiltOn": ["Coast"],
|
||||
"food": 1,
|
||||
"techRequired": "Sailing",
|
||||
"improvingTech": "Compass",
|
||||
"improvingTechStats": {"gold": 1}
|
||||
"uniques": ["[+1 Gold] once [Compass] is discovered"]
|
||||
},
|
||||
|
||||
// Military improvement
|
||||
|
@ -110,28 +101,28 @@
|
|||
"name": "Remove Forest",
|
||||
"turnsToBuild": 4,
|
||||
"terrainsCanBeBuiltOn": ["Forest"],
|
||||
"techRequired": "Mining"
|
||||
"techRequired": "Mining",
|
||||
"uniques": ["Can be built outside your borders"]
|
||||
},
|
||||
{
|
||||
"name": "Remove Jungle",
|
||||
"turnsToBuild": 7,
|
||||
"terrainsCanBeBuiltOn": ["Jungle"],
|
||||
"techRequired": "Bronze Working"
|
||||
"techRequired": "Bronze Working",
|
||||
"uniques": ["Can be built outside your borders"]
|
||||
},
|
||||
{
|
||||
"name": "Remove Fallout",
|
||||
"turnsToBuild": 8,
|
||||
"terrainsCanBeBuiltOn": ["Fallout"],
|
||||
"techRequired": "Atomic Theory"
|
||||
"techRequired": "Atomic Theory",
|
||||
"uniques": ["Can be built outside your borders"]
|
||||
},
|
||||
{
|
||||
"name": "Remove Marsh",
|
||||
"turnsToBuild": 6,
|
||||
"terrainsCanBeBuiltOn": ["Marsh"],
|
||||
"techRequired": "Bronze Working"
|
||||
"techRequired": "Bronze Working",
|
||||
"uniques": ["Can be built outside your borders"]
|
||||
},
|
||||
|
||||
|
@ -148,34 +139,30 @@
|
|||
},
|
||||
{
|
||||
"name": "Cancel improvement order",
|
||||
"uniques": ["Can be built outside your borders"]
|
||||
},
|
||||
|
||||
// Great Person improvements
|
||||
{
|
||||
"name": "Academy",
|
||||
"science": 8,
|
||||
"uniques": ["Great Improvement"],
|
||||
"improvingTech": "Scientific Theory",
|
||||
"improvingTechStats": {"science": 2}
|
||||
"uniques": ["Great Improvement", "[+2 Science] once [Scientific Theory] is discovered"]
|
||||
// in Gods & Kings academy will also have "[+2 Science] once [Atomic Theory] is discovered"
|
||||
},
|
||||
{
|
||||
"name": "Landmark",
|
||||
"culture": 6,
|
||||
"uniques": ["Great Improvement"],
|
||||
"uniques": ["Great Improvement"]
|
||||
},
|
||||
{
|
||||
"name": "Manufactory",
|
||||
"production": 4,
|
||||
"improvingTech": "Chemistry",
|
||||
"uniques": ["Great Improvement"],
|
||||
"improvingTechStats": {"production": 1}
|
||||
"uniques": ["Great Improvement", "[+1 Production] once [Chemistry] is discovered"]
|
||||
},
|
||||
{
|
||||
"name": "Customs house",
|
||||
"gold": 4,
|
||||
"improvingTech": "Economics",
|
||||
"uniques": ["Great Improvement"],
|
||||
"improvingTechStats": {"gold": 1}
|
||||
"uniques": ["Great Improvement", "[+1 Gold] once [Economics] is discovered"]
|
||||
},
|
||||
{
|
||||
"name": "Citadel",
|
||||
|
@ -190,8 +177,7 @@
|
|||
"turnsToBuild": 4,
|
||||
"uniques": ["[+1 Culture] for each adjacent [Moai]", "Can only be built on Coastal tiles"],
|
||||
"techRequired": "Construction",
|
||||
"improvingTech": "Flight",
|
||||
"improvingTechStats": {"gold": 1}
|
||||
"uniques": ["[+1 Gold] once [Flight] is discovered"]
|
||||
},
|
||||
{
|
||||
"name": "Terrace farm",
|
||||
|
@ -199,10 +185,8 @@
|
|||
"terrainsCanBeBuiltOn": ["Hill"],
|
||||
"food": 1,
|
||||
"turnsToBuild": 7,
|
||||
"uniques": ["[+1 Food] for each adjacent [Mountain]", "Cannot be built on bonus resource"],
|
||||
"techRequired": "Construction",
|
||||
"improvingTech": "Fertilizer",
|
||||
"improvingTechStats": {"food":1}
|
||||
"uniques": ["[+1 Food] for each adjacent [Mountain]", "Cannot be built on bonus resource", "[+1 Food] on [fresh water] tiles once [Civil Service] is discovered", "[+1 Food] on [non-fresh water] tiles once [Fertilizer] is discovered"],
|
||||
"techRequired": "Construction"
|
||||
},
|
||||
|
||||
{ "name": "Ancient ruins" },
|
||||
|
|
|
@ -434,6 +434,7 @@ Our proposed trade request is no longer relevant! =
|
|||
[defender] withdrew from a [attacker] =
|
||||
[building] has provided [amount] Gold! =
|
||||
[civName] has stolen your territory! =
|
||||
Clearing a [forest] has created [amount] Production for [cityName] =
|
||||
|
||||
|
||||
# World Screen UI
|
||||
|
@ -599,6 +600,8 @@ vs [unitType] =
|
|||
Terrain =
|
||||
Tile =
|
||||
Missing resource =
|
||||
[stats] on [tileType] tiles =
|
||||
from improvements: =
|
||||
|
||||
|
||||
Hurry Research =
|
||||
|
@ -630,6 +633,8 @@ Water =
|
|||
# For [stats] from [Water resource] tiles in this city
|
||||
Water resource =
|
||||
River =
|
||||
fresh water =
|
||||
non-fresh water =
|
||||
|
||||
Wonders =
|
||||
Base values =
|
||||
|
|
|
@ -208,7 +208,9 @@ class WorkerAutomation(val unit: MapUnit) {
|
|||
tile.terrainFeature == Constants.forest -> "Lumber mill"
|
||||
tile.baseTerrain == Constants.hill -> "Mine"
|
||||
tile.baseTerrain in listOf(Constants.grassland,Constants.desert,Constants.plains) -> "Farm"
|
||||
tile.baseTerrain == Constants.tundra -> Constants.tradingPost
|
||||
tile.baseTerrain in listOf(Constants.tundra, Constants.snow)
|
||||
&& tile.isAdjacentToFreshwater -> "Farm"
|
||||
tile.baseTerrain in listOf(Constants.tundra, Constants.snow) -> Constants.tradingPost
|
||||
else -> null
|
||||
}
|
||||
if (improvementString == null) return null
|
||||
|
|
|
@ -372,7 +372,7 @@ class MapUnit {
|
|||
private fun workOnImprovement() {
|
||||
val tile = getTile()
|
||||
tile.turnsToImprovement -= 1
|
||||
if (tile.turnsToImprovement != 0 && !civInfo.gameInfo.gameParameters.godMode) return
|
||||
if (tile.turnsToImprovement != 0) return
|
||||
|
||||
if (civInfo.isCurrentPlayer())
|
||||
UncivGame.Current.settings.addCompletedTutorialTask("Construct an improvement")
|
||||
|
@ -387,7 +387,12 @@ class MapUnit {
|
|||
}
|
||||
if (tile.improvementInProgress == "Remove Road" || tile.improvementInProgress == "Remove Railroad")
|
||||
tile.roadStatus = RoadStatus.None
|
||||
else tile.terrainFeature = null
|
||||
else {
|
||||
if (tile.tileMap.gameInfo.ruleSet.terrains[tile.terrainFeature]!!.uniques
|
||||
.contains("Provides a one-time Production bonus to the closest city when cut down"))
|
||||
tryProvideProductionToClosestCity()
|
||||
tile.terrainFeature = null
|
||||
}
|
||||
}
|
||||
tile.improvementInProgress == "Road" -> tile.roadStatus = RoadStatus.Road
|
||||
tile.improvementInProgress == "Railroad" -> tile.roadStatus = RoadStatus.Railroad
|
||||
|
@ -399,6 +404,21 @@ class MapUnit {
|
|||
tile.improvementInProgress = null
|
||||
}
|
||||
|
||||
private fun tryProvideProductionToClosestCity()
|
||||
{
|
||||
val tile = getTile()
|
||||
val closestCity = civInfo.cities.minBy { it.getCenterTile().aerialDistanceTo(tile) }
|
||||
if (closestCity == null) return
|
||||
val distance = closestCity.getCenterTile().aerialDistanceTo(tile)
|
||||
var productionPointsToAdd = if (distance == 1) 20 else 20 - (distance - 2) * 5
|
||||
if (tile.owningCity == null || tile.owningCity!!.civInfo != civInfo ) productionPointsToAdd = productionPointsToAdd * 2 / 3
|
||||
if (productionPointsToAdd > 0) {
|
||||
closestCity.cityConstructions.addProductionPoints(productionPointsToAdd)
|
||||
civInfo.addNotification("Clearing a [${tile.terrainFeature}] has created [$productionPointsToAdd] Production for [${closestCity.name}]", closestCity.location, Color.BROWN)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun heal() {
|
||||
if (isEmbarked()) return // embarked units can't heal
|
||||
var amountToHealBy = rankTileForHealing(getTile())
|
||||
|
|
|
@ -243,16 +243,24 @@ open class TileInfo {
|
|||
if (hasViewableResource(observingCiv) && getTileResource().improvement == improvement.name)
|
||||
stats.add(getTileResource().improvementStats!!.clone()) // resource-specific improvement
|
||||
|
||||
// As of 3.10.5 This is to be deprecated and converted to "[stats] once [tech] is discovered" - keeping it here to that mods with this can still work for now
|
||||
if (improvement.improvingTech != null && observingCiv.tech.isResearched(improvement.improvingTech!!))
|
||||
stats.add(improvement.improvingTechStats!!) // eg Chemistry for mines
|
||||
|
||||
for (unique in improvement.uniqueObjects) if (unique.placeholderText == "[] once [] is discovered"
|
||||
&& observingCiv.tech.isResearched(unique.params[1])) stats.add(Stats.parse(unique.params[0]))
|
||||
|
||||
if(city!=null) {
|
||||
val cityWideUniques = city.cityConstructions.builtBuildingUniqueMap.getUniques("[] from [] tiles in this city")
|
||||
val civWideUniques = city.civInfo.getMatchingUniques("[] from every []")
|
||||
for (unique in cityWideUniques + civWideUniques) {
|
||||
val improvementUniques = improvement.uniqueObjects.filter { it.placeholderText == "[] on [] tiles once [] is discovered"
|
||||
&& observingCiv.tech.isResearched(it.params[2]) }
|
||||
for (unique in cityWideUniques + civWideUniques + improvementUniques) {
|
||||
if (improvement.name == unique.params[1]
|
||||
|| (unique.params[1] == "Great Improvement" && improvement.isGreatImprovement()))
|
||||
|| (unique.params[1] == "Great Improvement" && improvement.isGreatImprovement())
|
||||
|| (unique.params[1] == "fresh water" && isAdjacentToFreshwater)
|
||||
|| (unique.params[1] == "non-fresh water" && !isAdjacentToFreshwater)
|
||||
)
|
||||
stats.add(Stats.parse(unique.params[0]))
|
||||
}
|
||||
}
|
||||
|
@ -293,6 +301,8 @@ open class TileInfo {
|
|||
improvement.name == "Remove Railroad" && this.roadStatus == RoadStatus.Railroad -> true
|
||||
improvement.name == Constants.cancelImprovementOrder && this.improvementInProgress != null -> true
|
||||
topTerrain.unbuildable && (topTerrain.name !in improvement.resourceTerrainAllow) -> false
|
||||
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
|
||||
else -> hasViewableResource(civInfo) && getTileResource().improvement == improvement.name
|
||||
}
|
||||
|
@ -431,7 +441,7 @@ open class TileInfo {
|
|||
|
||||
fun startWorkingOnImprovement(improvement: TileImprovement, civInfo: CivilizationInfo) {
|
||||
improvementInProgress = improvement.name
|
||||
turnsToImprovement = improvement.getTurnsToBuild(civInfo)
|
||||
turnsToImprovement = if (civInfo.gameInfo.gameParameters.godMode) 1 else improvement.getTurnsToBuild(civInfo)
|
||||
}
|
||||
|
||||
fun stopWorkingOnImprovement() {
|
||||
|
|
|
@ -24,6 +24,19 @@ class Technology {
|
|||
val lineList = ArrayList<String>() // more readable than StringBuilder, with same performance for our use-case
|
||||
for (unique in uniques) lineList += unique.tr()
|
||||
|
||||
val mapOfImprovedImprovements = HashMap<String, ArrayList<String>>()
|
||||
for (improvement in ruleset.tileImprovements.values) for ( unique in improvement.uniqueObjects
|
||||
.filter { it.placeholderText in setOf("[] once [] is discovered", "[] on [] tiles once [] is discovered")
|
||||
&& it.params.last() == name }) {
|
||||
val key = if (unique.params.size == 2 ) unique.params[0] else "[${unique.params[0]}] on [${unique.params[1]}] tiles"
|
||||
if (!mapOfImprovedImprovements.containsKey(key)) mapOfImprovedImprovements[key] = ArrayList()
|
||||
mapOfImprovedImprovements[key]!!.add(improvement.name)
|
||||
}
|
||||
for ( improvements in mapOfImprovedImprovements) {
|
||||
val impimpString = improvements.key.tr() + " from improvements: ".tr() + improvements.value.joinToString(", ") { it.tr() }
|
||||
lineList += impimpString
|
||||
}
|
||||
|
||||
val improvedImprovements = ruleset.tileImprovements.values
|
||||
.filter { it.improvingTech == name }.groupBy { it.improvingTechStats.toString() }
|
||||
for (improvement in improvedImprovements) {
|
||||
|
|
|
@ -19,7 +19,9 @@ class TileImprovement : NamedStats() {
|
|||
|
||||
var techRequired: String? = null
|
||||
|
||||
@Deprecated("Deprecated as of 3.10.5. Use [stats] once [tech] is discovered unique instead")
|
||||
var improvingTech: String? = null
|
||||
@Deprecated("Deprecated as of 3.10.5. Use [stats] once [tech] is discovered unique instead")
|
||||
var improvingTechStats: Stats? = null
|
||||
var uniqueTo:String? = null
|
||||
var uniques = ArrayList<String>()
|
||||
|
|
|
@ -539,6 +539,8 @@ class TileEditorOptionsTable(val mapEditorScreen: MapEditorScreen): Table(Camera
|
|||
-> if (topTerrain.unbuildable && improvement.isGreatImprovement())
|
||||
tileInfo.terrainFeature = null
|
||||
topTerrain.unbuildable -> tileInfo.improvement = null // forbid on unbuildable feature
|
||||
improvement.hasUnique("Can also be built on tiles adjacent to fresh water")
|
||||
&& tileInfo.isAdjacentToFreshwater -> Unit // allow farms on tiles adjacent to fresh water
|
||||
"Can only be built on Coastal tiles" in improvement.uniques && tileInfo.isCoastalTile()
|
||||
-> Unit // allow Moai where appropriate
|
||||
else -> tileInfo.improvement = null
|
||||
|
|
|
@ -54,7 +54,8 @@ class TechButton(techName:String, private val techManager: TechManager, isWorldS
|
|||
techEnabledIcons.add(ImageGetter.getConstructionImage(building.name).surroundWithCircle(techIconSize))
|
||||
|
||||
for (improvement in gameBasics.tileImprovements.values
|
||||
.filter { it.techRequired == techName || it.improvingTech == techName }
|
||||
.filter { it.techRequired == techName || it.uniqueObjects.any { u -> u.params.contains(techName) }
|
||||
|| it.improvingTech == techName }
|
||||
.filter { it.uniqueTo==null || it.uniqueTo==civName }) {
|
||||
if (improvement.name.startsWith("Remove"))
|
||||
techEnabledIcons.add(ImageGetter.getImage("OtherIcons/Stop")).size(techIconSize)
|
||||
|
|