mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-23 03:23:17 -04:00
chore(purity): CityConstructions
This commit is contained in:
parent
99fa2cd964
commit
5e0d23fb1c
@ -66,6 +66,7 @@ allprojects {
|
||||
"kotlin.collections.subtract",
|
||||
"kotlin.collections.union",
|
||||
"kotlin.collections.intersect",
|
||||
"kotlin.collections.List.indexOf",
|
||||
|
||||
)
|
||||
wellKnownPureClasses = setOf<String>(
|
||||
|
@ -15,6 +15,7 @@ import com.unciv.models.ruleset.unique.UniqueType
|
||||
import com.unciv.models.stats.Stat
|
||||
import com.unciv.ui.screens.worldscreen.unit.actions.UnitActions
|
||||
import com.unciv.ui.screens.worldscreen.unit.actions.UnitActionsFromUniques
|
||||
import yairm210.purity.annotations.Readonly
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
object SpecificUnitAutomation {
|
||||
@ -347,6 +348,7 @@ object SpecificUnitAutomation {
|
||||
return tileBeforeMoving != unit.currentTile
|
||||
}
|
||||
|
||||
@Readonly
|
||||
private fun getWonderThatWouldBenefitFromBeingSpedUp(city: City): Building? {
|
||||
return city.cityConstructions.getBuildableBuildings().filter { building ->
|
||||
building.isWonder && !building.hasUnique(UniqueType.CannotBeHurried)
|
||||
|
@ -37,6 +37,7 @@ import com.unciv.ui.screens.civilopediascreen.FormattedLine
|
||||
import com.unciv.ui.screens.pickerscreens.PromotionTree
|
||||
import com.unciv.utils.withItem
|
||||
import com.unciv.utils.withoutItem
|
||||
import yairm210.purity.annotations.LocalState
|
||||
import yairm210.purity.annotations.Readonly
|
||||
import kotlin.math.ceil
|
||||
import kotlin.math.min
|
||||
@ -101,17 +102,20 @@ class CityConstructions : IsPartOfGameInfoSerialization {
|
||||
}
|
||||
|
||||
// Why is one of these called 'buildable' and the other 'constructable'?
|
||||
@Readonly
|
||||
internal fun getBuildableBuildings(): Sequence<Building> = city.getRuleset().buildings.values
|
||||
.asSequence().filter { it.isBuildable(this) }
|
||||
|
||||
@Readonly
|
||||
fun getConstructableUnits() = city.getRuleset().units.values
|
||||
.asSequence().filter { it.isBuildable(this) }
|
||||
|
||||
/**
|
||||
* @return [Stats] provided by all built buildings in city plus the bonus from Library
|
||||
* @return [Stats] provided by all built buildings in city
|
||||
*/
|
||||
@Readonly
|
||||
fun getStats(localUniqueCache: LocalUniqueCache): StatTreeNode {
|
||||
val stats = StatTreeNode()
|
||||
@LocalState val stats = StatTreeNode()
|
||||
for (building in getBuiltBuildings())
|
||||
stats.addStats(building.getStats(city, localUniqueCache), building.name)
|
||||
return stats
|
||||
@ -120,6 +124,7 @@ class CityConstructions : IsPartOfGameInfoSerialization {
|
||||
/**
|
||||
* @return Maintenance cost of all built buildings
|
||||
*/
|
||||
@Readonly
|
||||
fun getMaintenanceCosts(): Float {
|
||||
var maintenanceCost = 0f
|
||||
val freeBuildings = city.civ.civConstructions.getFreeBuildingNames(city)
|
||||
@ -144,6 +149,7 @@ class CityConstructions : IsPartOfGameInfoSerialization {
|
||||
return maintenanceCost
|
||||
}
|
||||
|
||||
@Readonly
|
||||
fun getCityProductionTextForCityButton(): String {
|
||||
val currentConstructionSnapshot = currentConstructionFromQueue // See below
|
||||
var result = currentConstructionSnapshot.tr(true)
|
||||
@ -156,10 +162,12 @@ class CityConstructions : IsPartOfGameInfoSerialization {
|
||||
}
|
||||
|
||||
/** @param constructionName needs to be a non-perpetual construction, else an empty string is returned */
|
||||
@Readonly
|
||||
internal fun getTurnsToConstructionString(constructionName: String, useStoredProduction: Boolean = true) =
|
||||
getTurnsToConstructionString(getConstruction(constructionName), useStoredProduction)
|
||||
|
||||
/** @param construction needs to be a non-perpetual construction, else an empty string is returned */
|
||||
@Readonly
|
||||
internal fun getTurnsToConstructionString(construction: IConstruction, useStoredProduction: Boolean = true): String {
|
||||
if (construction !is INonPerpetualConstruction) return "" // shouldn't happen
|
||||
val cost = construction.getProductionCost(city.civ, city)
|
||||
@ -179,6 +187,7 @@ class CityConstructions : IsPartOfGameInfoSerialization {
|
||||
return lines.joinToString("\n", "\n")
|
||||
}
|
||||
|
||||
@Readonly
|
||||
fun getProductionMarkup(ruleset: Ruleset): FormattedLine {
|
||||
val currentConstructionSnapshot = currentConstructionFromQueue
|
||||
if (currentConstructionSnapshot.isEmpty()) return FormattedLine()
|
||||
@ -219,19 +228,22 @@ class CityConstructions : IsPartOfGameInfoSerialization {
|
||||
/** @return `true` if [constructionName] is anywhere in the construction queue - [isBeingConstructed] **or** [isEnqueuedForLater] */
|
||||
@Readonly fun isBeingConstructedOrEnqueued(constructionName: String) = constructionQueue.contains(constructionName)
|
||||
|
||||
fun isQueueFull(): Boolean = constructionQueue.size >= queueMaxSize
|
||||
@Readonly fun isQueueFull(): Boolean = constructionQueue.size >= queueMaxSize
|
||||
|
||||
@Readonly
|
||||
fun isBuildingWonder(): Boolean {
|
||||
val currentConstruction = getCurrentConstruction()
|
||||
return currentConstruction is Building && currentConstruction.isWonder
|
||||
}
|
||||
|
||||
@Readonly
|
||||
fun canBeHurried(): Boolean {
|
||||
val currentConstruction = getCurrentConstruction()
|
||||
return currentConstruction is INonPerpetualConstruction && !currentConstruction.hasUnique(UniqueType.CannotBeHurried)
|
||||
}
|
||||
|
||||
/** If the city is constructing multiple units of the same type, subsequent units will require the full cost */
|
||||
@Readonly
|
||||
fun isFirstConstructionOfItsKind(constructionQueueIndex: Int, name: String): Boolean {
|
||||
// Simply compare index of first found [name] with given index
|
||||
return constructionQueueIndex == constructionQueue.indexOf(name)
|
||||
@ -276,6 +288,7 @@ class CityConstructions : IsPartOfGameInfoSerialization {
|
||||
}
|
||||
}
|
||||
|
||||
@Readonly
|
||||
fun turnsToConstruction(constructionName: String, useStoredProduction: Boolean = true): Int {
|
||||
val workLeft = getRemainingWork(constructionName, useStoredProduction)
|
||||
if (workLeft <= 0) // This most often happens when a production is more than finished in a multiplayer game while its not your turn
|
||||
@ -287,6 +300,7 @@ class CityConstructions : IsPartOfGameInfoSerialization {
|
||||
return ceil((workLeft-productionOverflow) / productionForConstruction(constructionName).toDouble()).toInt()
|
||||
}
|
||||
|
||||
@Readonly
|
||||
fun productionForConstruction(constructionName: String): Int {
|
||||
val cityStatsForConstruction: Stats
|
||||
if (currentConstructionFromQueue == constructionName) cityStatsForConstruction = city.cityStats.currentCityStats
|
||||
@ -302,7 +316,7 @@ class CityConstructions : IsPartOfGameInfoSerialization {
|
||||
we get all sorts of fun concurrency problems when accessing various parts of the cityStats.
|
||||
SO, we create an entirely new CityStats and iterate there - problem solve!
|
||||
*/
|
||||
val cityStats = CityStats(city)
|
||||
@LocalState val cityStats = CityStats(city)
|
||||
cityStats.statsFromTiles = city.cityStats.statsFromTiles // take as-is
|
||||
val construction = city.cityConstructions.getConstruction(constructionName)
|
||||
cityStats.update(construction, false, false)
|
||||
@ -312,6 +326,7 @@ class CityConstructions : IsPartOfGameInfoSerialization {
|
||||
return cityStatsForConstruction.production.roundToInt()
|
||||
}
|
||||
|
||||
@Readonly
|
||||
fun cheapestStatBuilding(stat: Stat): Building? {
|
||||
return city.getRuleset().buildings.values.asSequence()
|
||||
.filter { !it.isAnyWonder() && it.isStatRelated(stat, city) &&
|
||||
|
@ -120,6 +120,7 @@ class CityStats(val city: City) {
|
||||
return stats
|
||||
}
|
||||
|
||||
@Readonly
|
||||
fun getStatConversionRate(stat: Stat): Float {
|
||||
var conversionRate = 1 / 4f
|
||||
val conversionUnique = city.civ.getMatchingUniques(UniqueType.ProductionToCivWideStatConversionBonus).firstOrNull { it.params[0] == stat.name }
|
||||
|
@ -293,7 +293,7 @@ open class PerpetualConstruction(override var name: String, val description: Str
|
||||
IConstruction {
|
||||
|
||||
override fun shouldBeDisplayed(cityConstructions: CityConstructions) = isBuildable(cityConstructions)
|
||||
open fun getProductionTooltip(city: City, withIcon: Boolean = false) : String = ""
|
||||
@Readonly open fun getProductionTooltip(city: City, withIcon: Boolean = false) : String = ""
|
||||
override fun getStockpiledResourceRequirements(state: GameContext) = Counter.ZERO
|
||||
|
||||
companion object {
|
||||
@ -325,7 +325,7 @@ open class PerpetualStatConversion(val stat: Stat) :
|
||||
|
||||
override fun getProductionTooltip(city: City, withIcon: Boolean) : String
|
||||
= "\r\n${(city.cityStats.currentCityStats.production / getConversionRate(city)).roundToInt()}${if (withIcon) stat.character else ""}/${Fonts.turn}"
|
||||
fun getConversionRate(city: City) : Int = (1/city.cityStats.getStatConversionRate(stat)).roundToInt()
|
||||
@Readonly fun getConversionRate(city: City) : Int = (1/city.cityStats.getStatConversionRate(stat)).roundToInt()
|
||||
|
||||
override fun isBuildable(cityConstructions: CityConstructions): Boolean {
|
||||
val city = cityConstructions.city
|
||||
|
Loading…
x
Reference in New Issue
Block a user