Settler 'by name' recognition changed to 'by unique' recognition, allowing for modded settler-like units

This commit is contained in:
Yair Morgenstern 2020-08-23 00:28:55 +03:00
parent a930ad6360
commit 002d0cc7f6
10 changed files with 38 additions and 34 deletions

View file

@ -133,7 +133,7 @@
"movement": 4,
"cost": 30,
"requiredTech": "Sailing",
"uniques": ["Cannot enter ocean tiles until Astronomy","May create improvements on water resources"],
"uniques": ["Cannot enter ocean tiles until Astronomy", "May create improvements on water resources"],
"hurryCostModifier": 20
},
{
@ -175,7 +175,7 @@
"requiredResource": "Horses",
"upgradesTo": "Knight",
"obsoleteTech": "Chivalry",
"uniques": ["No defensive terrain bonus","Rough terrain penalty"],
"uniques": ["No defensive terrain bonus", "Rough terrain penalty"],
"hurryCostModifier": 20,
"attackSound": "arrow"
},
@ -191,7 +191,7 @@
"requiredTech": "The Wheel",
"upgradesTo": "Knight",
"obsoleteTech": "Chivalry",
"uniques": ["No defensive terrain bonus","Rough terrain penalty"],
"uniques": ["No defensive terrain bonus", "Rough terrain penalty"],
"hurryCostModifier": 20,
"attackSound": "arrow"
},

View file

@ -4,6 +4,7 @@ object Constants {
const val worker = "Worker"
const val workerUnique = "Can build improvements on tiles"
const val settler = "Settler"
const val settlerUnique = "Founds a new city"
const val greatGeneral = "Great General"
const val impassable = "Impassable"

View file

@ -107,7 +107,8 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){
else if (isAtWar) modifier *= unitsToCitiesRatio * 2
if (!cityIsOverAverageProduction) modifier /= 5 // higher production cities will deal with this
if (cityInfo.getCenterTile().civilianUnit?.name == Constants.settler
val civilianUnit = cityInfo.getCenterTile().civilianUnit
if (civilianUnit != null && civilianUnit.hasUnique(Constants.settlerUnique)
&& cityInfo.getCenterTile().getTilesInDistance(5).none { it.militaryUnit?.civInfo == civInfo })
modifier = 5f // there's a settler just sitting here, doing nothing - BAD

View file

@ -15,6 +15,7 @@ import com.unciv.models.ruleset.ModOptions
import com.unciv.models.ruleset.ModOptionsConstants
import com.unciv.models.ruleset.VictoryType
import com.unciv.models.ruleset.tech.Technology
import com.unciv.models.ruleset.unit.BaseUnit
import com.unciv.models.translations.tr
import kotlin.math.min
@ -480,14 +481,20 @@ object NextTurnAutomation{
if (civInfo.isCityState()) return
if (civInfo.isAtWar()) return // don't train settlers when you could be training troops.
if (civInfo.victoryType() == VictoryType.Cultural && civInfo.cities.size > 3) return
if (civInfo.cities.any()
&& civInfo.getHappiness() > civInfo.cities.size + 5
&& civInfo.getCivUnits().none { it.name == Constants.settler }
&& civInfo.cities.none { it.cityConstructions.currentConstructionFromQueue == Constants.settler }) {
if (civInfo.cities.none() || civInfo.getHappiness() <= civInfo.cities.size + 5) return
val settlerUnits = civInfo.gameInfo.ruleSet.units.values
.filter { it.uniques.contains(Constants.settlerUnique) && it.isBuildable(civInfo) }
if (settlerUnits.isEmpty()) return
if (civInfo.getCivUnits().none { it.hasUnique(Constants.settlerUnique) }
&& civInfo.cities.none {
val currentConstruction = it.cityConstructions.getCurrentConstruction()
currentConstruction is BaseUnit && currentConstruction.uniques.contains(Constants.settlerUnique)
}) {
val bestCity = civInfo.cities.maxBy { it.cityStats.currentCityStats.production }!!
if (bestCity.cityConstructions.builtBuildings.size > 1) // 2 buildings or more, otherwise focus on self first
bestCity.cityConstructions.currentConstructionFromQueue = Constants.settler
bestCity.cityConstructions.currentConstructionFromQueue = settlerUnits.minBy { it.cost }!!.name
}
}

View file

@ -91,7 +91,7 @@ object UnitAutomation {
throw IllegalStateException("Barbarians is not allowed here.")
if(unit.type.isCivilian()) {
if (unit.name == Constants.settler)
if (unit.hasUnique(Constants.settlerUnique))
return SpecificUnitAutomation.automateSettlerActions(unit)
if (unit.hasUnique(Constants.workerUnique))
@ -261,7 +261,8 @@ object UnitAutomation {
val settlerOrGreatPersonToAccompany = unit.civInfo.getCivUnits()
.firstOrNull {
val tile = it.currentTile
(it.name == Constants.settler || it.name in GreatPersonManager().statToGreatPersonMapping.values)
it.type==UnitType.Civilian &&
(it.hasUnique(Constants.settlerUnique) || unit.name in GreatPersonManager().statToGreatPersonMapping.values)
&& tile.militaryUnit == null && unit.movement.canMoveTo(tile) && unit.movement.canReach(tile)
}
if (settlerOrGreatPersonToAccompany == null) return false

View file

@ -15,6 +15,7 @@ import com.unciv.ui.utils.withItem
import com.unciv.ui.utils.withoutItem
import java.util.*
import kotlin.collections.ArrayList
import kotlin.math.ceil
import kotlin.math.roundToInt
/**
@ -194,7 +195,7 @@ class CityConstructions {
// Since this is only ever used for UI purposes, I feel fine with having it be a bit inefficient
// and recalculating the entire city stats
// We don't want to change our current construction queue - what if we have an empty queue, too many changes to check for -
// So we ust clone it and see what would happen f that was our construction
// So we must clone it and see what would happen if that was our construction
val cityConstructionsClone = clone()
cityConstructionsClone.currentConstructionFromQueue = constructionName
cityConstructionsClone.cityInfo = cityInfo
@ -210,7 +211,7 @@ class CityConstructions {
var production = cityStatsForConstruction.production.roundToInt()
if (constructionName == Constants.settler) production += cityStatsForConstruction.food.toInt()
return Math.ceil((workLeft / production.toDouble())).toInt()
return ceil(workLeft / production.toDouble()).toInt()
}
//endregion

View file

@ -219,34 +219,26 @@ class CityInfo {
return 0
}
fun isGrowing(): Boolean {
return foodForNextTurn() > 0 && cityConstructions.currentConstructionFromQueue != Constants.settler
}
fun isGrowing() = foodForNextTurn() > 0
fun isStarving(): Boolean = foodForNextTurn() < 0
fun isStarving() = foodForNextTurn() < 0
private fun foodForNextTurn() = cityStats.currentCityStats.food.roundToInt()
/** Take null to mean infinity. */
fun getNumTurnsToNewPopulation(): Int? {
if (isGrowing()) {
val roundedFoodPerTurn = foodForNextTurn().toFloat()
val remainingFood = population.getFoodToNextPopulation() - population.foodStored
var turnsToGrowth = ceil( remainingFood / roundedFoodPerTurn).toInt()
if (turnsToGrowth < 1) turnsToGrowth = 1
return turnsToGrowth
}
return null
if (!isGrowing()) return null
val roundedFoodPerTurn = foodForNextTurn().toFloat()
val remainingFood = population.getFoodToNextPopulation() - population.foodStored
var turnsToGrowth = ceil( remainingFood / roundedFoodPerTurn).toInt()
if (turnsToGrowth < 1) turnsToGrowth = 1
return turnsToGrowth
}
/** Take null to mean infinity. */
fun getNumTurnsToStarvation(): Int? {
if (isStarving()) {
return population.foodStored / -foodForNextTurn() + 1
}
return null
if (!isStarving()) return null
return population.foodStored / -foodForNextTurn() + 1
}
fun containsBuildingUnique(unique:String) = cityConstructions.getBuiltBuildings().any { it.uniques.contains(unique) }

View file

@ -277,7 +277,7 @@ class CivilizationInfo {
if (gameInfo.gameParameters.victoryTypes.contains(VictoryType.Scenario))
return cities.isEmpty() && getCivUnits().none()
else return cities.isEmpty() // No cities
&& (citiesCreated > 0 || !getCivUnits().any { it.name == Constants.settler })
&& (citiesCreated > 0 || !getCivUnits().any { it.hasUnique(Constants.settlerUnique) })
}
fun getEra(): String {

View file

@ -137,8 +137,8 @@ class BaseUnit : INamed, IConstruction {
if (uniques.contains("Requires Manhattan Project") && !civInfo.hasUnique("Enables nuclear weapon"))
return "Requires Manhattan Project"
if (requiredResource!=null && !civInfo.hasResource(requiredResource!!) && !civInfo.gameInfo.gameParameters.godMode) return "Consumes 1 [$requiredResource]"
if (name == Constants.settler && civInfo.isCityState()) return "No settler for city-states"
if (name == Constants.settler && civInfo.isOneCityChallenger()) return "No settler for players in One City Challenge"
if (uniques.contains(Constants.settlerUnique) && civInfo.isCityState()) return "No settler for city-states"
if (uniques.contains(Constants.settlerUnique) && civInfo.isOneCityChallenger()) return "No settler for players in One City Challenge"
return ""
}

View file

@ -209,6 +209,7 @@ object TranslationFileWriter {
RulesetCache.getBaseRuleset().tileImprovements.containsKey(parameter) -> "tileImprovement"
RulesetCache.getBaseRuleset().tileResources.containsKey(parameter) -> "resource"
RulesetCache.getBaseRuleset().technologies.containsKey(parameter) -> "tech"
RulesetCache.getBaseRuleset().unitPromotions.containsKey(parameter) -> "promotion"
RulesetCache.getBaseRuleset().buildings.containsKey(parameter)
|| parameter == "Wonders" -> "building"