Replaced hardcoded Settler references with unique

Tech uniques now saved in tech object for less regex parsing per turn
This commit is contained in:
Yair Morgenstern
2020-12-22 23:31:29 +02:00
parent 12b844d917
commit c7d79ad179
6 changed files with 35 additions and 26 deletions

View File

@ -15,7 +15,7 @@
"unitType": "Civilian", "unitType": "Civilian",
"movement": 2, "movement": 2,
"cost": 106, "cost": 106,
"uniques": ["Founds a new city"], "uniques": ["Founds a new city", "Excess Food converted to Production when under construction"],
"hurryCostModifier": 20 "hurryCostModifier": 20
}, },
{ {

View File

@ -18,6 +18,7 @@ class CityStats {
@Transient @Transient
var baseStatList = LinkedHashMap<String, Stats>() var baseStatList = LinkedHashMap<String, Stats>()
@Transient @Transient
var statPercentBonusList = LinkedHashMap<String, Stats>() var statPercentBonusList = LinkedHashMap<String, Stats>()
@ -27,11 +28,13 @@ class CityStats {
@Transient @Transient
var happinessList = LinkedHashMap<String, Float>() var happinessList = LinkedHashMap<String, Float>()
@Transient @Transient
var foodEaten = 0f var foodEaten = 0f
@Transient @Transient
var currentCityStats: Stats = Stats() // This is so we won't have to calculate this multiple times - takes a lot of time, especially on phones var currentCityStats: Stats = Stats() // This is so we won't have to calculate this multiple times - takes a lot of time, especially on phones
@Transient @Transient
lateinit var cityInfo: CityInfo lateinit var cityInfo: CityInfo
@ -67,7 +70,7 @@ class CityStats {
} }
fun getScienceConversionRate(): Float { fun getScienceConversionRate(): Float {
var conversionRate = 1/4f var conversionRate = 1 / 4f
if (cityInfo.civInfo.hasUnique("Production to science conversion in cities increased by 33%")) if (cityInfo.civInfo.hasUnique("Production to science conversion in cities increased by 33%"))
conversionRate *= 1.33f conversionRate *= 1.33f
return conversionRate return conversionRate
@ -176,11 +179,11 @@ class CityStats {
if (cityInfo.civInfo.hasUnique("+15% growth in all cities")) if (cityInfo.civInfo.hasUnique("+15% growth in all cities"))
bonus += 15f bonus += 15f
for(unique in cityInfo.civInfo.getMatchingUniques("+[]% growth in all cities")) for (unique in cityInfo.civInfo.getMatchingUniques("+[]% growth in all cities"))
bonus += unique.params[0].toFloat() bonus += unique.params[0].toFloat()
if (cityInfo.isCapital()) for(unique in cityInfo.civInfo.getMatchingUniques("+[]% growth in capital")) if (cityInfo.isCapital()) for (unique in cityInfo.civInfo.getMatchingUniques("+[]% growth in capital"))
bonus += unique.params[0].toFloat() bonus += unique.params[0].toFloat()
return bonus/100 return bonus / 100
} }
// needs to be a separate function because we need to know the global happiness state // needs to be a separate function because we need to know the global happiness state
@ -207,8 +210,8 @@ class CityStats {
else if (hasExtraAnnexUnhappiness()) else if (hasExtraAnnexUnhappiness())
unhappinessFromCitizens *= 2f unhappinessFromCitizens *= 2f
for(unique in civInfo.getMatchingUniques("Unhappiness from population decreased by []%")) for (unique in civInfo.getMatchingUniques("Unhappiness from population decreased by []%"))
unhappinessFromCitizens *= (1-unique.params[0].toFloat()/100) unhappinessFromCitizens *= (1 - unique.params[0].toFloat() / 100)
newHappinessList["Population"] = -unhappinessFromCitizens * unhappinessModifier newHappinessList["Population"] = -unhappinessFromCitizens * unhappinessModifier
@ -227,7 +230,7 @@ class CityStats {
if (hasExtraAnnexUnhappiness()) newHappinessList["Occupied City"] = -2f //annexed city if (hasExtraAnnexUnhappiness()) newHappinessList["Occupied City"] = -2f //annexed city
val happinessFromSpecialists = getStatsFromSpecialists(cityInfo.population.getNewSpecialists()).happiness.toInt().toFloat() val happinessFromSpecialists = getStatsFromSpecialists(cityInfo.population.getNewSpecialists()).happiness.toInt().toFloat()
if (happinessFromSpecialists>0) newHappinessList["Specialists"] = happinessFromSpecialists if (happinessFromSpecialists > 0) newHappinessList["Specialists"] = happinessFromSpecialists
val happinessFromBuildings = cityInfo.cityConstructions.getStats().happiness.toInt().toFloat() val happinessFromBuildings = cityInfo.cityConstructions.getStats().happiness.toInt().toFloat()
newHappinessList["Buildings"] = happinessFromBuildings newHappinessList["Buildings"] = happinessFromBuildings
@ -244,7 +247,7 @@ class CityStats {
} }
private fun hasExtraAnnexUnhappiness() : Boolean { private fun hasExtraAnnexUnhappiness(): Boolean {
if (cityInfo.civInfo.civName == cityInfo.foundingCiv || cityInfo.foundingCiv == "" || cityInfo.isPuppet) return false if (cityInfo.civInfo.civName == cityInfo.foundingCiv || cityInfo.foundingCiv == "" || cityInfo.isPuppet) return false
return !cityInfo.containsBuildingUnique("Remove extra unhappiness from annexed cities") return !cityInfo.containsBuildingUnique("Remove extra unhappiness from annexed cities")
} }
@ -254,13 +257,13 @@ class CityStats {
if (stat == Stat.Culture || stat == Stat.Science) stats.add(stat, 3f) if (stat == Stat.Culture || stat == Stat.Science) stats.add(stat, 3f)
else stats.add(stat, 2f) // science and gold specialists else stats.add(stat, 2f) // science and gold specialists
for(unique in cityInfo.civInfo.getMatchingUniques("[] from every specialist")) for (unique in cityInfo.civInfo.getMatchingUniques("[] from every specialist"))
stats.add(unique.stats) stats.add(unique.stats)
return stats return stats
} }
fun getStatsOfSpecialist(specialistName:String): Stats { fun getStatsOfSpecialist(specialistName: String): Stats {
val specialist = cityInfo.getRuleset().specialists[specialistName] val specialist = cityInfo.getRuleset().specialists[specialistName]
if (specialist == null) return Stats() if (specialist == null) return Stats()
val stats = specialist.clone() val stats = specialist.clone()
@ -276,7 +279,7 @@ class CityStats {
return stats return stats
} }
private fun getStatsFromUniques(uniques: Sequence<Unique>):Stats { private fun getStatsFromUniques(uniques: Sequence<Unique>): Stats {
val stats = Stats() val stats = Stats()
for (unique in uniques) { for (unique in uniques) {
@ -308,7 +311,7 @@ class CityStats {
} }
private fun getStatPercentBonusesFromBuildings(): Stats { private fun getStatPercentBonusesFromBuildings(): Stats {
val stats = cityInfo.cityConstructions.getStatPercentBonuses() val stats = cityInfo.cityConstructions.getStatPercentBonuses()
val currentConstruction = cityInfo.cityConstructions.getCurrentConstruction() val currentConstruction = cityInfo.cityConstructions.getCurrentConstruction()
// This is to be deprecated and converted to "+[]% production when building [] in this city" - keeping it here to that mods with this can still work for now // This is to be deprecated and converted to "+[]% production when building [] in this city" - keeping it here to that mods with this can still work for now
@ -373,7 +376,7 @@ class CityStats {
return stats return stats
} }
fun constructionMatchesFilter(construction:IConstruction, filter:String): Boolean { fun constructionMatchesFilter(construction: IConstruction, filter: String): Boolean {
return construction.name == filter return construction.name == filter
// All of these are deprecated as of 3.11.20 in favor of "+[]% Production when constructing [] units" // All of these are deprecated as of 3.11.20 in favor of "+[]% Production when constructing [] units"
|| filter == "land units" && construction is BaseUnit && construction.unitType.isLandUnit() || filter == "land units" && construction is BaseUnit && construction.unitType.isLandUnit()
@ -448,7 +451,7 @@ class CityStats {
updateFinalStatList() // again, we don't edit the existing currentCityStats directly, in order to avoid concurrency exceptions updateFinalStatList() // again, we don't edit the existing currentCityStats directly, in order to avoid concurrency exceptions
val newCurrentCityStats = Stats() val newCurrentCityStats = Stats()
for(stat in finalStatList.values) newCurrentCityStats.add(stat) for (stat in finalStatList.values) newCurrentCityStats.add(stat)
currentCityStats = newCurrentCityStats currentCityStats = newCurrentCityStats
cityInfo.civInfo.updateStatsForNextTurn() cityInfo.civInfo.updateStatsForNextTurn()
@ -527,7 +530,9 @@ class CityStats {
newFinalStatList["Maintenance"] = Stats().apply { gold -= buildingsMaintenance.toInt() } newFinalStatList["Maintenance"] = Stats().apply { gold -= buildingsMaintenance.toInt() }
if (cityInfo.cityConstructions.currentConstructionFromQueue == Constants.settler && totalFood > 0) { val currentconstruction = cityInfo.cityConstructions.currentConstructionFromQueue
if (totalFood > 0 && cityInfo.getRuleset().units[currentconstruction]
.let { it != null && it.uniques.contains("Excess Food converted to Production when under construction") }) {
newFinalStatList["Excess food to production"] = newFinalStatList["Excess food to production"] =
Stats().apply { production = totalFood; food = -totalFood } Stats().apply { production = totalFood; food = -totalFood }
} }
@ -541,7 +546,7 @@ class CityStats {
} }
private fun updateFoodEaten() { private fun updateFoodEaten() {
foodEaten = (cityInfo.population.population * 2).toFloat() foodEaten = cityInfo.population.population.toFloat() * 2
if (cityInfo.civInfo.hasUnique("-50% food consumption by specialists")) if (cityInfo.civInfo.hasUnique("-50% food consumption by specialists"))
foodEaten -= cityInfo.population.getNumberOfSpecialists() foodEaten -= cityInfo.population.getNumberOfSpecialists()
} }

View File

@ -230,7 +230,7 @@ class CivilizationInfo {
return nation.uniqueObjects.asSequence().filter { it.placeholderText == uniqueTemplate } + return nation.uniqueObjects.asSequence().filter { it.placeholderText == uniqueTemplate } +
cities.asSequence().flatMap { it.cityConstructions.builtBuildingUniqueMap.getUniques(uniqueTemplate).asSequence() } + cities.asSequence().flatMap { it.cityConstructions.builtBuildingUniqueMap.getUniques(uniqueTemplate).asSequence() } +
policies.policyUniques.getUniques(uniqueTemplate) + policies.policyUniques.getUniques(uniqueTemplate) +
tech.getTechUniques() tech.getTechUniques().filter { it.placeholderText == uniqueTemplate }
} }
//region Units //region Units

View File

@ -122,7 +122,7 @@ class TechManager {
return tech.prerequisites.all { isResearched(it) } return tech.prerequisites.all { isResearched(it) }
} }
fun getTechUniques() = researchedTechUniques fun getTechUniques() = researchedTechUniques.asSequence()
//endregion //endregion
@ -231,9 +231,9 @@ class TechManager {
if (!newTech.isContinuallyResearchable()) if (!newTech.isContinuallyResearchable())
techsToResearch.remove(techName) techsToResearch.remove(techName)
researchedTechnologies = researchedTechnologies.withItem(newTech) researchedTechnologies = researchedTechnologies.withItem(newTech)
for (unique in newTech.uniques) { for (unique in newTech.uniqueObjects) {
researchedTechUniques = researchedTechUniques.withItem(Unique(unique)) researchedTechUniques = researchedTechUniques.withItem(unique)
UniqueTriggerActivation.triggerCivwideUnique(Unique(unique), civInfo) UniqueTriggerActivation.triggerCivwideUnique(unique, civInfo)
} }
updateTransientBooleans() updateTransientBooleans()
@ -296,7 +296,7 @@ class TechManager {
fun setTransients() { fun setTransients() {
researchedTechnologies.addAll(techsResearched.map { getRuleset().technologies[it]!! }) researchedTechnologies.addAll(techsResearched.map { getRuleset().technologies[it]!! })
researchedTechUniques.addAll(researchedTechnologies.asSequence().flatMap { it.uniques.asSequence() }.map { Unique(it) }) researchedTechUniques.addAll(researchedTechnologies.asSequence().flatMap { it.uniqueObjects.asSequence() })
updateTransientBooleans() updateTransientBooleans()
} }

View File

@ -4,6 +4,7 @@ import com.unciv.UncivGame
import com.unciv.logic.civilization.CivilizationInfo import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.models.ruleset.Building import com.unciv.models.ruleset.Building
import com.unciv.models.ruleset.Ruleset import com.unciv.models.ruleset.Ruleset
import com.unciv.models.ruleset.Unique
import com.unciv.models.translations.tr import com.unciv.models.translations.tr
import com.unciv.models.ruleset.unit.BaseUnit import com.unciv.models.ruleset.unit.BaseUnit
import java.util.* import java.util.*
@ -15,6 +16,7 @@ class Technology {
var cost: Int = 0 var cost: Int = 0
var prerequisites = HashSet<String>() var prerequisites = HashSet<String>()
var uniques = ArrayList<String>() var uniques = ArrayList<String>()
val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it) } }
var column: TechColumn? = null // The column that this tech is in the tech tree var column: TechColumn? = null // The column that this tech is in the tech tree
var row: Int = 0 var row: Int = 0

View File

@ -67,7 +67,9 @@ class CityStatsTable(val cityScreen: CityScreen): Table() {
when { when {
cityInfo.isGrowing() -> "[${cityInfo.getNumTurnsToNewPopulation()}] turns to new population".tr() cityInfo.isGrowing() -> "[${cityInfo.getNumTurnsToNewPopulation()}] turns to new population".tr()
cityInfo.isStarving() -> "[${cityInfo.getNumTurnsToStarvation()}] turns to lose population".tr() cityInfo.isStarving() -> "[${cityInfo.getNumTurnsToStarvation()}] turns to lose population".tr()
cityInfo.cityConstructions.currentConstructionFromQueue == Constants.settler -> "Food converts to production".tr() cityInfo.getRuleset().units[cityInfo.cityConstructions.currentConstructionFromQueue]
.let { it != null && it.uniques.contains("Excess Food converted to Production when under construction") }
-> "Food converts to production".tr()
else -> "Stopped population growth".tr() else -> "Stopped population growth".tr()
} }
turnsToPopString += " (" + cityInfo.population.foodStored + "/" + cityInfo.population.getFoodToNextPopulation() + ")" turnsToPopString += " (" + cityInfo.population.foodStored + "/" + cityInfo.population.getFoodToNextPopulation() + ")"