diff --git a/core/src/com/unciv/logic/GameStarter.kt b/core/src/com/unciv/logic/GameStarter.kt index 2818f2bed9..6c02e61228 100644 --- a/core/src/com/unciv/logic/GameStarter.kt +++ b/core/src/com/unciv/logic/GameStarter.kt @@ -18,8 +18,8 @@ import com.unciv.models.ruleset.ModOptionsConstants import com.unciv.models.ruleset.Ruleset import com.unciv.models.ruleset.RulesetCache import com.unciv.models.ruleset.unique.StateForConditionals -import com.unciv.models.ruleset.unique.UniqueType import com.unciv.models.ruleset.unique.UniqueTriggerActivation +import com.unciv.models.ruleset.unique.UniqueType import com.unciv.models.ruleset.unit.BaseUnit import com.unciv.models.stats.Stats import com.unciv.models.translations.equalsPlaceholderText @@ -416,7 +416,7 @@ object GameStarter { ruleset: Ruleset ) { val startingEra = gameInfo.gameParameters.startingEra - val settlerLikeUnits = ruleset.units.filter { it.value.hasUnique(UniqueType.FoundCity) } + val settlerLikeUnits = ruleset.units.filter { it.value.isCityFounder() } for (civ in gameInfo.civilizations.filter { !it.isBarbarian() && !it.isSpectator() }) { val startingLocation = startingLocations[civ]!! @@ -539,7 +539,7 @@ object GameStarter { ): HashMap { val civsOrderedByAvailableLocations = getCivsOrderedByAvailableLocations(civs, tileMap) - + for (minimumDistanceBetweenStartingLocations in tileMap.tileMatrix.size / 6 downTo 0) { val freeTiles = getFreeTiles(tileMap, landTilesInBigEnoughGroup, minimumDistanceBetweenStartingLocations) @@ -581,12 +581,12 @@ object GameStarter { ): HashMap? { val startingLocations = HashMap() for (civ in civsOrderedByAvailableLocations) { - + val startingLocation = getCivStartingLocation(civ, tileMap, freeTiles, startScores) startingLocation ?: break - + startingLocations[civ] = startingLocation - + val distanceToNext = minimumDistanceBetweenStartingLocations / (if (civ.isCityState()) 2 else 1) // We allow city states to squeeze in tighter freeTiles.removeAll(tileMap.getTilesInDistance(startingLocation.position, distanceToNext) diff --git a/core/src/com/unciv/logic/automation/civilization/NextTurnAutomation.kt b/core/src/com/unciv/logic/automation/civilization/NextTurnAutomation.kt index 0c67f0594d..168b835770 100644 --- a/core/src/com/unciv/logic/automation/civilization/NextTurnAutomation.kt +++ b/core/src/com/unciv/logic/automation/civilization/NextTurnAutomation.kt @@ -1026,7 +1026,7 @@ object NextTurnAutomation { val sortedUnits = civInfo.units.getCivUnits().sortedBy { unit -> getUnitPriority(unit, isAtWar) } for (unit in sortedUnits) UnitAutomation.automateUnitMoves(unit) } - + private fun getUnitPriority(unit: MapUnit, isAtWar: Boolean): Int { if (unit.isCivilian() && !unit.isGreatPersonOfType("War")) return 1 // Civilian if (unit.baseUnit.isAirUnit()) return 2 @@ -1078,13 +1078,13 @@ object NextTurnAutomation { if (civInfo.getHappiness() <= civInfo.cities.size) return val settlerUnits = civInfo.gameInfo.ruleset.units.values - .filter { it.hasUnique(UniqueType.FoundCity) && it.isBuildable(civInfo) } + .filter { it.isCityFounder() && it.isBuildable(civInfo) } if (settlerUnits.isEmpty()) return if (!civInfo.units.getCivUnits().none { it.hasUnique(UniqueType.FoundCity) }) return if (civInfo.cities.any { val currentConstruction = it.cityConstructions.getCurrentConstruction() - currentConstruction is BaseUnit && currentConstruction.hasUnique(UniqueType.FoundCity) + currentConstruction is BaseUnit && currentConstruction.isCityFounder() }) return if (civInfo.units.getCivUnits().none { it.isMilitary() }) return // We need someone to defend him first diff --git a/core/src/com/unciv/models/ruleset/tech/Era.kt b/core/src/com/unciv/models/ruleset/tech/Era.kt index 3b21ba895b..521ed2e4eb 100644 --- a/core/src/com/unciv/models/ruleset/tech/Era.kt +++ b/core/src/com/unciv/models/ruleset/tech/Era.kt @@ -8,9 +8,9 @@ import com.unciv.models.ruleset.RulesetObject import com.unciv.models.ruleset.unique.StateForConditionals import com.unciv.models.ruleset.unique.UniqueTarget import com.unciv.models.ruleset.unique.UniqueType -import com.unciv.ui.screens.civilopediascreen.FormattedLine import com.unciv.ui.components.Fonts import com.unciv.ui.components.extensions.colorFromRGB +import com.unciv.ui.screens.civilopediascreen.FormattedLine class Era : RulesetObject() { var eraNumber: Int = -1 @@ -88,7 +88,7 @@ class Era : RulesetObject() { val startingSettlerName: String = if (startingSettlerUnit in ruleset.units) startingSettlerUnit else ruleset.units.values - .firstOrNull { it.hasUnique(UniqueType.FoundCity) } + .firstOrNull { it.isCityFounder() } ?.name ?: throw UncivShowableException("No Settler unit found for era $name") val startingWorkerName: String = diff --git a/core/src/com/unciv/models/ruleset/unique/UniqueTriggerActivation.kt b/core/src/com/unciv/models/ruleset/unique/UniqueTriggerActivation.kt index c3d7c42e73..b2a1c2bcb3 100644 --- a/core/src/com/unciv/models/ruleset/unique/UniqueTriggerActivation.kt +++ b/core/src/com/unciv/models/ruleset/unique/UniqueTriggerActivation.kt @@ -56,7 +56,7 @@ object UniqueTriggerActivation { val unit = ruleSet.units[unitName] if ((chosenCity == null && tile == null) || unit == null - || unit.hasUnique(UniqueType.FoundCity) && civInfo.isOneCityChallenger()) + || unit.isCityFounder() && civInfo.isOneCityChallenger()) return false val limit = unit.getMatchingUniques(UniqueType.MaxNumberBuildable) @@ -83,7 +83,7 @@ object UniqueTriggerActivation { UniqueType.OneTimeAmountFreeUnits -> { val unitName = unique.params[1] val unit = ruleSet.units[unitName] - if ((chosenCity == null && tile == null) || unit == null || (unit.hasUnique(UniqueType.FoundCity) && civInfo.isOneCityChallenger())) + if ((chosenCity == null && tile == null) || unit == null || (unit.isCityFounder() && civInfo.isOneCityChallenger())) return false val limit = unit.getMatchingUniques(UniqueType.MaxNumberBuildable) @@ -118,7 +118,7 @@ object UniqueTriggerActivation { } UniqueType.OneTimeFreeUnitRuins -> { var unit = civInfo.getEquivalentUnit(unique.params[0]) - if ( unit.hasUnique(UniqueType.FoundCity) && civInfo.isOneCityChallenger()) { + if ( unit.isCityFounder() && civInfo.isOneCityChallenger()) { val replacementUnit = ruleSet.units.values .firstOrNull { it.getMatchingUniques(UniqueType.BuildImprovements) diff --git a/core/src/com/unciv/models/ruleset/unit/BaseUnit.kt b/core/src/com/unciv/models/ruleset/unit/BaseUnit.kt index 62b3663fce..a445af16e8 100644 --- a/core/src/com/unciv/models/ruleset/unit/BaseUnit.kt +++ b/core/src/com/unciv/models/ruleset/unit/BaseUnit.kt @@ -215,7 +215,7 @@ class BaseUnit : RulesetObject(), INonPerpetualConstruction { //movement penalty if (boughtWith != null && !civInfo.gameInfo.gameParameters.godMode && !unit.hasUnique(UniqueType.MoveImmediatelyOnceBought)) unit.currentMovement = 0f - + if (this.isCivilian()) return true // tiny optimization makes save files a few bytes smaller addConstructionBonuses(unit, cityConstructions) @@ -300,6 +300,10 @@ class BaseUnit : RulesetObject(), INonPerpetualConstruction { } } + /** Determine whether this is a City-founding unit - abstract, **without any game context**. + * Use other methods for MapUnits or when there is a better StateForConditionals available. */ + fun isCityFounder() = hasUnique(UniqueType.FoundCity, StateForConditionals.IgnoreConditionals) + fun isGreatPerson() = getMatchingUniques(UniqueType.GreatPerson).any() fun isGreatPersonOfType(type: String) = getMatchingUniques(UniqueType.GreatPerson).any { it.params[0] == type } diff --git a/core/src/com/unciv/models/ruleset/validation/RulesetValidator.kt b/core/src/com/unciv/models/ruleset/validation/RulesetValidator.kt index 7661792c40..c0ebeb8d0a 100644 --- a/core/src/com/unciv/models/ruleset/validation/RulesetValidator.kt +++ b/core/src/com/unciv/models/ruleset/validation/RulesetValidator.kt @@ -173,7 +173,7 @@ class RulesetValidator(val ruleset: Ruleset) { checkUniques(ruleset.globalUniques, lines, rulesetSpecific, tryFixUnknownUniques) - if (ruleset.units.values.none { it.hasUnique(UniqueType.FoundCity, StateForConditionals.IgnoreConditionals) }) + if (ruleset.units.values.none { it.isCityFounder() }) lines += "No city-founding units in ruleset!" for (unit in ruleset.units.values) { @@ -348,7 +348,7 @@ class RulesetValidator(val ruleset: Ruleset) { lines += "Nonexistent building $building built by settlers when starting in ${era.name}" // todo the whole 'starting unit' thing needs to be redone, there's no reason we can't have a single list containing all the starting units. if (era.startingSettlerUnit !in ruleset.units - && ruleset.units.values.none { it.hasUnique(UniqueType.FoundCity) }) + && ruleset.units.values.none { it.isCityFounder() }) lines += "Nonexistent unit ${era.startingSettlerUnit} marked as starting unit when starting in ${era.name}" if (era.startingWorkerCount != 0 && era.startingWorkerUnit !in ruleset.units && ruleset.units.values.none { it.hasUnique(UniqueType.BuildImprovements) })