mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-27 05:46:43 -04:00
Merge branch 'yairm210:master' into updated-so-you-can-build-naval-unit-on-water-tile
This commit is contained in:
commit
8b37ba8182
@ -4,8 +4,8 @@ package com.unciv.build
|
|||||||
object BuildConfig {
|
object BuildConfig {
|
||||||
const val kotlinVersion = "2.1.20"
|
const val kotlinVersion = "2.1.20"
|
||||||
const val appName = "Unciv"
|
const val appName = "Unciv"
|
||||||
const val appCodeNumber = 1151
|
const val appCodeNumber = 1152
|
||||||
const val appVersion = "4.17.11"
|
const val appVersion = "4.17.11-patch1"
|
||||||
|
|
||||||
const val gdxVersion = "1.13.1"
|
const val gdxVersion = "1.13.1"
|
||||||
const val ktorVersion = "2.3.13"
|
const val ktorVersion = "2.3.13"
|
||||||
|
@ -487,7 +487,7 @@ open class UncivGame(val isConsoleMode: Boolean = false) : Game(), PlatformSpeci
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
//region AUTOMATICALLY GENERATED VERSION DATA - DO NOT CHANGE THIS REGION, INCLUDING THIS COMMENT
|
//region AUTOMATICALLY GENERATED VERSION DATA - DO NOT CHANGE THIS REGION, INCLUDING THIS COMMENT
|
||||||
val VERSION = Version("4.17.11", 1151)
|
val VERSION = Version("4.17.11-patch1", 1152)
|
||||||
//endregion
|
//endregion
|
||||||
|
|
||||||
/** Global reference to the one Gdx.Game instance created by the platform launchers - do not use without checking [isCurrentInitialized] first. */
|
/** Global reference to the one Gdx.Game instance created by the platform launchers - do not use without checking [isCurrentInitialized] first. */
|
||||||
|
@ -559,7 +559,7 @@ class CityStateFunctions(val civInfo: Civilization) {
|
|||||||
.filter { !it.hasUnique(UniqueType.ResearchableMultipleTimes) && civInfo.tech.canBeResearched(it.name) }
|
.filter { !it.hasUnique(UniqueType.ResearchableMultipleTimes) && civInfo.tech.canBeResearched(it.name) }
|
||||||
for (tech in researchableTechs) {
|
for (tech in researchableTechs) {
|
||||||
val aliveMajorCivs = civInfo.gameInfo.getAliveMajorCivs()
|
val aliveMajorCivs = civInfo.gameInfo.getAliveMajorCivs()
|
||||||
if (aliveMajorCivs.count { it.tech.isResearched(tech.name) } >= aliveMajorCivs.size / 2)
|
if (aliveMajorCivs.count { it.tech.isResearched(tech.name) } > aliveMajorCivs.size / 2)
|
||||||
civInfo.tech.addTechnology(tech.name)
|
civInfo.tech.addTechnology(tech.name)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
@ -19,7 +19,6 @@ import com.unciv.logic.map.mapgenerator.MapResourceSetting
|
|||||||
import com.unciv.logic.map.mapunit.MapUnit
|
import com.unciv.logic.map.mapunit.MapUnit
|
||||||
import com.unciv.logic.map.mapunit.UnitTurnManager
|
import com.unciv.logic.map.mapunit.UnitTurnManager
|
||||||
import com.unciv.logic.map.mapunit.movement.UnitMovement
|
import com.unciv.logic.map.mapunit.movement.UnitMovement
|
||||||
import com.unciv.models.UnitAction
|
|
||||||
import com.unciv.models.ruleset.Ruleset
|
import com.unciv.models.ruleset.Ruleset
|
||||||
import com.unciv.models.ruleset.tile.ResourceType
|
import com.unciv.models.ruleset.tile.ResourceType
|
||||||
import com.unciv.models.ruleset.tile.Terrain
|
import com.unciv.models.ruleset.tile.Terrain
|
||||||
@ -632,27 +631,12 @@ class Tile : IsPartOfGameInfoSerialization, Json.Serializable {
|
|||||||
return min(distance, wrappedDistance).toInt()
|
return min(distance, wrappedDistance).toInt()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun canBeSettled(unitCanFoundUnique: Unique?=null): Boolean {
|
@Readonly
|
||||||
|
fun canBeSettled(): Boolean {
|
||||||
val modConstants = tileMap.gameInfo.ruleset.modOptions.constants
|
val modConstants = tileMap.gameInfo.ruleset.modOptions.constants
|
||||||
var addedDistanceBeweenContinents: Int
|
|
||||||
var canSettleInTileWithUnique = false
|
|
||||||
if (unitCanFoundUnique != null) {
|
|
||||||
canSettleInTileWithUnique = (isWater || isImpassible()) &&
|
|
||||||
unitCanFoundUnique.getModifiers(UniqueType.ConditionalInTiles).none{
|
|
||||||
matchesFilter(it.params[0])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
Putting the ! to make sure the player/Ai doesn't place cities too near each other.
|
|
||||||
Because when .none return False when one element has a match.
|
|
||||||
*/
|
|
||||||
|
|
||||||
addedDistanceBeweenContinents = if (!canSettleInTileWithUnique) 1 else 0
|
|
||||||
|
|
||||||
return when {
|
return when {
|
||||||
canSettleInTileWithUnique -> false
|
isWater || isImpassible() -> false
|
||||||
getTilesInDistance(modConstants.minimalCityDistanceOnDifferentContinents+
|
getTilesInDistance(modConstants.minimalCityDistanceOnDifferentContinents)
|
||||||
addedDistanceBeweenContinents)
|
|
||||||
.any { it.isCityCenter() && it.getContinent() != getContinent() } -> false
|
.any { it.isCityCenter() && it.getContinent() != getContinent() } -> false
|
||||||
getTilesInDistance(modConstants.minimalCityDistance)
|
getTilesInDistance(modConstants.minimalCityDistance)
|
||||||
.any { it.isCityCenter() && it.getContinent() == getContinent() } -> false
|
.any { it.isCityCenter() && it.getContinent() == getContinent() } -> false
|
||||||
|
@ -296,7 +296,6 @@ class Ruleset {
|
|||||||
@Readonly fun allUniques(): Sequence<Unique> = RulesetFile.entries.asSequence().flatMap { it.getUniques(this) }
|
@Readonly fun allUniques(): Sequence<Unique> = RulesetFile.entries.asSequence().flatMap { it.getUniques(this) }
|
||||||
@Readonly fun allICivilopediaText(): Sequence<ICivilopediaText> = allRulesetObjects() + events.values.flatMap { it.choices }
|
@Readonly fun allICivilopediaText(): Sequence<ICivilopediaText> = allRulesetObjects() + events.values.flatMap { it.choices }
|
||||||
|
|
||||||
|
|
||||||
fun load(folderHandle: FileHandle) {
|
fun load(folderHandle: FileHandle) {
|
||||||
// Note: Most files are loaded using createHashmap, which sets originRuleset automatically.
|
// Note: Most files are loaded using createHashmap, which sets originRuleset automatically.
|
||||||
// For other files containing IRulesetObject's we'll have to remember to do so manually - e.g. Tech.
|
// For other files containing IRulesetObject's we'll have to remember to do so manually - e.g. Tech.
|
||||||
|
@ -187,7 +187,6 @@ class Terrain : RulesetStatsObject() {
|
|||||||
type.name -> true
|
type.name -> true
|
||||||
"Natural Wonder" -> type == TerrainType.NaturalWonder
|
"Natural Wonder" -> type == TerrainType.NaturalWonder
|
||||||
"Terrain Feature" -> type == TerrainType.TerrainFeature
|
"Terrain Feature" -> type == TerrainType.TerrainFeature
|
||||||
"Impassable" -> impassable
|
|
||||||
|
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
|
@ -805,8 +805,7 @@ enum class UniqueType(
|
|||||||
|
|
||||||
/////// tile conditionals
|
/////// tile conditionals
|
||||||
ConditionalNeighborTiles("with [nonNegativeAmount] to [nonNegativeAmount] neighboring [tileFilter] tiles", UniqueTarget.Conditional),
|
ConditionalNeighborTiles("with [nonNegativeAmount] to [nonNegativeAmount] neighboring [tileFilter] tiles", UniqueTarget.Conditional),
|
||||||
ConditionalInTiles("in [tileFilter] tiles", UniqueTarget.Conditional,
|
ConditionalInTiles("in [tileFilter] tiles", UniqueTarget.Conditional),
|
||||||
docDescription = "Can be used with FoundCity and FoundPuppetCity to only found cities in Water/Impassible tiles."),
|
|
||||||
ConditionalInTilesNot("in tiles without [tileFilter]", UniqueTarget.Conditional),
|
ConditionalInTilesNot("in tiles without [tileFilter]", UniqueTarget.Conditional),
|
||||||
ConditionalNearTiles("within [positiveAmount] tiles of a [tileFilter]", UniqueTarget.Conditional),
|
ConditionalNearTiles("within [positiveAmount] tiles of a [tileFilter]", UniqueTarget.Conditional),
|
||||||
|
|
||||||
|
@ -15,8 +15,6 @@ import com.unciv.models.ruleset.unique.UniqueParameterType
|
|||||||
import com.unciv.models.ruleset.unique.UniqueTarget
|
import com.unciv.models.ruleset.unique.UniqueTarget
|
||||||
import com.unciv.models.ruleset.unique.UniqueType
|
import com.unciv.models.ruleset.unique.UniqueType
|
||||||
import com.unciv.models.ruleset.unique.expressions.Expressions
|
import com.unciv.models.ruleset.unique.expressions.Expressions
|
||||||
import yairm210.purity.annotations.Cache
|
|
||||||
import yairm210.purity.annotations.LocalState
|
|
||||||
import yairm210.purity.annotations.Readonly
|
import yairm210.purity.annotations.Readonly
|
||||||
|
|
||||||
class UniqueValidator(val ruleset: Ruleset) {
|
class UniqueValidator(val ruleset: Ruleset) {
|
||||||
@ -66,7 +64,7 @@ class UniqueValidator(val ruleset: Ruleset) {
|
|||||||
UniqueType.ConditionalNotAdjacentTo
|
UniqueType.ConditionalNotAdjacentTo
|
||||||
)
|
)
|
||||||
|
|
||||||
@Readonly
|
@Readonly @Suppress("purity")
|
||||||
fun checkUnique(
|
fun checkUnique(
|
||||||
unique: Unique,
|
unique: Unique,
|
||||||
tryFixUnknownUniques: Boolean,
|
tryFixUnknownUniques: Boolean,
|
||||||
@ -76,7 +74,7 @@ class UniqueValidator(val ruleset: Ruleset) {
|
|||||||
val prefix by lazy { getUniqueContainerPrefix(uniqueContainer) + "\"${unique.text}\"" }
|
val prefix by lazy { getUniqueContainerPrefix(uniqueContainer) + "\"${unique.text}\"" }
|
||||||
if (unique.type == null) return checkUntypedUnique(unique, tryFixUnknownUniques, uniqueContainer, prefix, reportRulesetSpecificErrors)
|
if (unique.type == null) return checkUntypedUnique(unique, tryFixUnknownUniques, uniqueContainer, prefix, reportRulesetSpecificErrors)
|
||||||
|
|
||||||
@LocalState val rulesetErrors = RulesetErrorList(ruleset)
|
val rulesetErrors = RulesetErrorList(ruleset)
|
||||||
|
|
||||||
if (uniqueContainer != null &&
|
if (uniqueContainer != null &&
|
||||||
!(unique.type.canAcceptUniqueTarget(uniqueContainer.getUniqueTarget()) ||
|
!(unique.type.canAcceptUniqueTarget(uniqueContainer.getUniqueTarget()) ||
|
||||||
@ -109,14 +107,14 @@ class UniqueValidator(val ruleset: Ruleset) {
|
|||||||
complianceError.errorSeverity.getRulesetErrorSeverity(), uniqueContainer, unique
|
complianceError.errorSeverity.getRulesetErrorSeverity(), uniqueContainer, unique
|
||||||
)
|
)
|
||||||
|
|
||||||
rulesetErrors += getExpressionParseErrors(complianceError, uniqueContainer, unique)
|
addExpressionParseErrors(complianceError, rulesetErrors, uniqueContainer, unique)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (conditional in unique.modifiers) {
|
for (conditional in unique.modifiers) {
|
||||||
rulesetErrors += getConditionalErrors(conditional, prefix, unique, uniqueContainer, reportRulesetSpecificErrors)
|
addConditionalErrors(conditional, rulesetErrors, prefix, unique, uniqueContainer, reportRulesetSpecificErrors)
|
||||||
}
|
}
|
||||||
|
|
||||||
rulesetErrors += getUniqueTypeSpecificErrors(prefix, unique, uniqueContainer, reportRulesetSpecificErrors)
|
addUniqueTypeSpecificErrors(rulesetErrors, prefix, unique, uniqueContainer, reportRulesetSpecificErrors)
|
||||||
|
|
||||||
val conditionals = unique.modifiers.filter { it.type?.canAcceptUniqueTarget(UniqueTarget.Conditional) == true }
|
val conditionals = unique.modifiers.filter { it.type?.canAcceptUniqueTarget(UniqueTarget.Conditional) == true }
|
||||||
if (conditionals.size > 1){
|
if (conditionals.size > 1){
|
||||||
@ -146,19 +144,18 @@ class UniqueValidator(val ruleset: Ruleset) {
|
|||||||
if (reportRulesetSpecificErrors)
|
if (reportRulesetSpecificErrors)
|
||||||
// If we don't filter these messages will be listed twice as this function is called twice on most objects
|
// If we don't filter these messages will be listed twice as this function is called twice on most objects
|
||||||
// The tests are RulesetInvariant in nature, but RulesetSpecific is called for _all_ objects, invariant is not.
|
// The tests are RulesetInvariant in nature, but RulesetSpecific is called for _all_ objects, invariant is not.
|
||||||
rulesetErrors += addDeprecationAnnotationErrors(unique, prefix, uniqueContainer)
|
addDeprecationAnnotationErrors(unique, prefix, rulesetErrors, uniqueContainer)
|
||||||
|
|
||||||
return rulesetErrors
|
return rulesetErrors
|
||||||
}
|
}
|
||||||
|
|
||||||
@Readonly
|
private fun addExpressionParseErrors(
|
||||||
private fun getExpressionParseErrors(
|
|
||||||
complianceError: UniqueComplianceError,
|
complianceError: UniqueComplianceError,
|
||||||
|
rulesetErrors: RulesetErrorList,
|
||||||
uniqueContainer: IHasUniques?,
|
uniqueContainer: IHasUniques?,
|
||||||
unique: Unique
|
unique: Unique
|
||||||
): RulesetErrorList {
|
) {
|
||||||
@LocalState val rulesetErrors = RulesetErrorList(ruleset)
|
if (!complianceError.acceptableParameterTypes.contains(UniqueParameterType.Countable)) return
|
||||||
if (!complianceError.acceptableParameterTypes.contains(UniqueParameterType.Countable)) return rulesetErrors
|
|
||||||
|
|
||||||
val parseError = Expressions.getParsingError(complianceError.parameterName)
|
val parseError = Expressions.getParsingError(complianceError.parameterName)
|
||||||
if (parseError != null) {
|
if (parseError != null) {
|
||||||
@ -170,7 +167,7 @@ class UniqueValidator(val ruleset: Ruleset) {
|
|||||||
val text = "\"${complianceError.parameterName}\" could not be parsed as an expression due to:" +
|
val text = "\"${complianceError.parameterName}\" could not be parsed as an expression due to:" +
|
||||||
" ${parseError.message}. \n$parameterWithErrorLocationMarked"
|
" ${parseError.message}. \n$parameterWithErrorLocationMarked"
|
||||||
rulesetErrors.add(text, RulesetErrorSeverity.WarningOptionsOnly, uniqueContainer, unique)
|
rulesetErrors.add(text, RulesetErrorSeverity.WarningOptionsOnly, uniqueContainer, unique)
|
||||||
return rulesetErrors
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val countableErrors = Expressions.getCountableErrors(complianceError.parameterName, ruleset)
|
val countableErrors = Expressions.getCountableErrors(complianceError.parameterName, ruleset)
|
||||||
@ -179,7 +176,6 @@ class UniqueValidator(val ruleset: Ruleset) {
|
|||||||
" ${countableErrors.joinToString(", ")}"
|
" ${countableErrors.joinToString(", ")}"
|
||||||
rulesetErrors.add(text, RulesetErrorSeverity.WarningOptionsOnly, uniqueContainer, unique)
|
rulesetErrors.add(text, RulesetErrorSeverity.WarningOptionsOnly, uniqueContainer, unique)
|
||||||
}
|
}
|
||||||
return rulesetErrors
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val resourceUniques = setOf(UniqueType.ProvidesResources, UniqueType.ConsumesResources,
|
private val resourceUniques = setOf(UniqueType.ProvidesResources, UniqueType.ConsumesResources,
|
||||||
@ -192,37 +188,21 @@ class UniqueValidator(val ruleset: Ruleset) {
|
|||||||
UniqueType.ConditionalWhenBelowAmountStatResource,
|
UniqueType.ConditionalWhenBelowAmountStatResource,
|
||||||
)
|
)
|
||||||
|
|
||||||
@Readonly
|
private fun addConditionalErrors(
|
||||||
private fun getUniqueTypeSpecificErrors(
|
|
||||||
prefix: String, unique: Unique, uniqueContainer: IHasUniques?, reportRulesetSpecificErrors: Boolean
|
|
||||||
): RulesetErrorList {
|
|
||||||
@LocalState val rulesetErrors = RulesetErrorList(ruleset)
|
|
||||||
when (unique.type) {
|
|
||||||
UniqueType.RuinsUpgrade -> {
|
|
||||||
if (reportRulesetSpecificErrors && !anyAncientRuins)
|
|
||||||
rulesetErrors.add("$prefix is pointless - there are no ancient ruins", RulesetErrorSeverity.Warning, uniqueContainer, unique)
|
|
||||||
}
|
|
||||||
else -> {}
|
|
||||||
}
|
|
||||||
return rulesetErrors
|
|
||||||
}
|
|
||||||
|
|
||||||
@Readonly
|
|
||||||
private fun getConditionalErrors(
|
|
||||||
conditional: Unique,
|
conditional: Unique,
|
||||||
|
rulesetErrors: RulesetErrorList,
|
||||||
prefix: String,
|
prefix: String,
|
||||||
unique: Unique,
|
unique: Unique,
|
||||||
uniqueContainer: IHasUniques?,
|
uniqueContainer: IHasUniques?,
|
||||||
reportRulesetSpecificErrors: Boolean
|
reportRulesetSpecificErrors: Boolean
|
||||||
): RulesetErrorList {
|
) {
|
||||||
@LocalState val rulesetErrors = RulesetErrorList(ruleset)
|
|
||||||
if (unique.hasFlag(UniqueFlag.NoConditionals)) {
|
if (unique.hasFlag(UniqueFlag.NoConditionals)) {
|
||||||
rulesetErrors.add(
|
rulesetErrors.add(
|
||||||
"$prefix contains the conditional \"${conditional.text}\"," +
|
"$prefix contains the conditional \"${conditional.text}\"," +
|
||||||
" but the unique does not accept conditionals!",
|
" but the unique does not accept conditionals!",
|
||||||
RulesetErrorSeverity.Error, uniqueContainer, unique
|
RulesetErrorSeverity.Error, uniqueContainer, unique
|
||||||
)
|
)
|
||||||
return rulesetErrors
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conditional.type == null) {
|
if (conditional.type == null) {
|
||||||
@ -241,7 +221,7 @@ class UniqueValidator(val ruleset: Ruleset) {
|
|||||||
text,
|
text,
|
||||||
RulesetErrorSeverity.Warning, uniqueContainer, unique
|
RulesetErrorSeverity.Warning, uniqueContainer, unique
|
||||||
)
|
)
|
||||||
return rulesetErrors
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conditional.type.targetTypes.none { it.modifierType != UniqueTarget.ModifierType.None })
|
if (conditional.type.targetTypes.none { it.modifierType != UniqueTarget.ModifierType.None })
|
||||||
@ -296,21 +276,30 @@ class UniqueValidator(val ruleset: Ruleset) {
|
|||||||
complianceError.errorSeverity.getRulesetErrorSeverity(), uniqueContainer, unique
|
complianceError.errorSeverity.getRulesetErrorSeverity(), uniqueContainer, unique
|
||||||
)
|
)
|
||||||
|
|
||||||
rulesetErrors += getExpressionParseErrors(complianceError, uniqueContainer, unique)
|
addExpressionParseErrors(complianceError, rulesetErrors, uniqueContainer, unique)
|
||||||
}
|
}
|
||||||
|
|
||||||
addDeprecationAnnotationErrors(conditional, "$prefix contains modifier \"${conditional.text}\" which", uniqueContainer)
|
addDeprecationAnnotationErrors(conditional, "$prefix contains modifier \"${conditional.text}\" which", rulesetErrors, uniqueContainer)
|
||||||
|
}
|
||||||
return rulesetErrors
|
|
||||||
|
private fun addUniqueTypeSpecificErrors(
|
||||||
|
rulesetErrors: RulesetErrorList, prefix: String, unique: Unique, uniqueContainer: IHasUniques?, reportRulesetSpecificErrors: Boolean
|
||||||
|
) {
|
||||||
|
when(unique.type) {
|
||||||
|
UniqueType.RuinsUpgrade -> {
|
||||||
|
if (reportRulesetSpecificErrors && !anyAncientRuins)
|
||||||
|
rulesetErrors.add("$prefix is pointless - there are no ancient ruins", RulesetErrorSeverity.Warning, uniqueContainer, unique)
|
||||||
|
}
|
||||||
|
else -> return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Readonly
|
|
||||||
private fun addDeprecationAnnotationErrors(
|
private fun addDeprecationAnnotationErrors(
|
||||||
unique: Unique,
|
unique: Unique,
|
||||||
prefix: String,
|
prefix: String,
|
||||||
|
rulesetErrors: RulesetErrorList,
|
||||||
uniqueContainer: IHasUniques?
|
uniqueContainer: IHasUniques?
|
||||||
): RulesetErrorList {
|
) {
|
||||||
@LocalState val rulesetErrors = RulesetErrorList(ruleset)
|
|
||||||
val deprecationAnnotation = unique.getDeprecationAnnotation()
|
val deprecationAnnotation = unique.getDeprecationAnnotation()
|
||||||
if (deprecationAnnotation != null) {
|
if (deprecationAnnotation != null) {
|
||||||
val replacementUniqueText = unique.getReplacementText(ruleset)
|
val replacementUniqueText = unique.getReplacementText(ruleset)
|
||||||
@ -325,13 +314,12 @@ class UniqueValidator(val ruleset: Ruleset) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check for deprecated Countables
|
// Check for deprecated Countables
|
||||||
if (unique.type == null) return rulesetErrors
|
if (unique.type == null) return
|
||||||
val countables =
|
val countables =
|
||||||
unique.type.parameterTypeMap.withIndex()
|
unique.type.parameterTypeMap.withIndex()
|
||||||
.filter { UniqueParameterType.Countable in it.value }
|
.filter { UniqueParameterType.Countable in it.value }
|
||||||
.map { unique.params[it.index] }
|
.map { unique.params[it.index] }
|
||||||
.mapNotNull { Countables.getMatching(it, ruleset) }
|
.mapNotNull { Countables.getMatching(it, ruleset) }
|
||||||
|
|
||||||
for (countable in countables) {
|
for (countable in countables) {
|
||||||
val deprecation = countable.getDeprecationAnnotation() ?: continue
|
val deprecation = countable.getDeprecationAnnotation() ?: continue
|
||||||
// This is less flexible than unique.getReplacementText(ruleset)
|
// This is less flexible than unique.getReplacementText(ruleset)
|
||||||
@ -343,18 +331,14 @@ class UniqueValidator(val ruleset: Ruleset) {
|
|||||||
else RulesetErrorSeverity.ErrorOptionsOnly // User visible in new game and red in options
|
else RulesetErrorSeverity.ErrorOptionsOnly // User visible in new game and red in options
|
||||||
rulesetErrors.add(text, severity, uniqueContainer, unique)
|
rulesetErrors.add(text, severity, uniqueContainer, unique)
|
||||||
}
|
}
|
||||||
|
|
||||||
return rulesetErrors
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Maps uncompliant parameters to their required types */
|
/** Maps uncompliant parameters to their required types */
|
||||||
@Readonly
|
|
||||||
private fun getComplianceErrors(
|
private fun getComplianceErrors(
|
||||||
unique: Unique,
|
unique: Unique,
|
||||||
): List<UniqueComplianceError> {
|
): List<UniqueComplianceError> {
|
||||||
if (unique.type == null) return emptyList()
|
if (unique.type == null) return emptyList()
|
||||||
@LocalState val errorList = ArrayList<UniqueComplianceError>()
|
val errorList = ArrayList<UniqueComplianceError>()
|
||||||
|
|
||||||
for ((index, param) in unique.params.withIndex()) {
|
for ((index, param) in unique.params.withIndex()) {
|
||||||
// Trying to catch the error at #11404
|
// Trying to catch the error at #11404
|
||||||
if (unique.type.parameterTypeMap.size != unique.params.size) {
|
if (unique.type.parameterTypeMap.size != unique.params.size) {
|
||||||
@ -379,13 +363,11 @@ class UniqueValidator(val ruleset: Ruleset) {
|
|||||||
return errorList
|
return errorList
|
||||||
}
|
}
|
||||||
|
|
||||||
@Cache private val paramTypeErrorSeverityCache = HashMap<UniqueParameterType, HashMap<String, UniqueType.UniqueParameterErrorSeverity?>>()
|
private val paramTypeErrorSeverityCache = HashMap<UniqueParameterType, HashMap<String, UniqueType.UniqueParameterErrorSeverity?>>()
|
||||||
@Readonly
|
|
||||||
private fun getParamTypeErrorSeverityCached(uniqueParameterType: UniqueParameterType, param: String): UniqueType.UniqueParameterErrorSeverity? {
|
private fun getParamTypeErrorSeverityCached(uniqueParameterType: UniqueParameterType, param: String): UniqueType.UniqueParameterErrorSeverity? {
|
||||||
if (!paramTypeErrorSeverityCache.containsKey(uniqueParameterType))
|
if (!paramTypeErrorSeverityCache.containsKey(uniqueParameterType))
|
||||||
paramTypeErrorSeverityCache[uniqueParameterType] = hashMapOf()
|
paramTypeErrorSeverityCache[uniqueParameterType] = hashMapOf()
|
||||||
|
val uniqueParamCache = paramTypeErrorSeverityCache[uniqueParameterType]!!
|
||||||
@LocalState val uniqueParamCache = paramTypeErrorSeverityCache[uniqueParameterType]!!
|
|
||||||
|
|
||||||
if (uniqueParamCache.containsKey(param)) return uniqueParamCache[param]
|
if (uniqueParamCache.containsKey(param)) return uniqueParamCache[param]
|
||||||
|
|
||||||
@ -394,7 +376,6 @@ class UniqueValidator(val ruleset: Ruleset) {
|
|||||||
return severity
|
return severity
|
||||||
}
|
}
|
||||||
|
|
||||||
@Readonly
|
|
||||||
private fun checkUntypedUnique(
|
private fun checkUntypedUnique(
|
||||||
unique: Unique,
|
unique: Unique,
|
||||||
tryFixUnknownUniques: Boolean,
|
tryFixUnknownUniques: Boolean,
|
||||||
@ -410,7 +391,7 @@ class UniqueValidator(val ruleset: Ruleset) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Support purely filtering Uniques without actual implementation
|
// Support purely filtering Uniques without actual implementation
|
||||||
if (isFilteringUniqueAllowed(unique, reportRulesetSpecificErrors)) return RulesetErrorList(ruleset)
|
if (isFilteringUniqueAllowed(unique, reportRulesetSpecificErrors)) return RulesetErrorList()
|
||||||
|
|
||||||
if (tryFixUnknownUniques) {
|
if (tryFixUnknownUniques) {
|
||||||
val fixes = tryFixUnknownUnique(unique, uniqueContainer, prefix)
|
val fixes = tryFixUnknownUnique(unique, uniqueContainer, prefix)
|
||||||
@ -424,7 +405,6 @@ class UniqueValidator(val ruleset: Ruleset) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Readonly
|
|
||||||
private fun isFilteringUniqueAllowed(unique: Unique, reportRulesetSpecificErrors: Boolean): Boolean {
|
private fun isFilteringUniqueAllowed(unique: Unique, reportRulesetSpecificErrors: Boolean): Boolean {
|
||||||
// Isolate this decision, to allow easy change of approach
|
// Isolate this decision, to allow easy change of approach
|
||||||
// This says: Must have no conditionals or parameters, and is used in any "filtering" parameter of another Unique
|
// This says: Must have no conditionals or parameters, and is used in any "filtering" parameter of another Unique
|
||||||
@ -433,7 +413,6 @@ class UniqueValidator(val ruleset: Ruleset) {
|
|||||||
return unique.text in allUniqueParameters // referenced at least once from elsewhere
|
return unique.text in allUniqueParameters // referenced at least once from elsewhere
|
||||||
}
|
}
|
||||||
|
|
||||||
@Readonly
|
|
||||||
private fun tryFixUnknownUnique(unique: Unique, uniqueContainer: IHasUniques?, prefix: String): RulesetErrorList {
|
private fun tryFixUnknownUnique(unique: Unique, uniqueContainer: IHasUniques?, prefix: String): RulesetErrorList {
|
||||||
val similarUniques = UniqueType.entries.filter {
|
val similarUniques = UniqueType.entries.filter {
|
||||||
getRelativeTextDistance(
|
getRelativeTextDistance(
|
||||||
@ -464,14 +443,13 @@ class UniqueValidator(val ruleset: Ruleset) {
|
|||||||
}.prependIndent("\t")
|
}.prependIndent("\t")
|
||||||
RulesetErrorList.of(text, RulesetErrorSeverity.OK, ruleset, uniqueContainer, unique)
|
RulesetErrorList.of(text, RulesetErrorSeverity.OK, ruleset, uniqueContainer, unique)
|
||||||
}
|
}
|
||||||
else -> RulesetErrorList(ruleset)
|
else -> RulesetErrorList()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val whichDoesNotFitParameterType = "which does not fit parameter type"
|
const val whichDoesNotFitParameterType = "which does not fit parameter type"
|
||||||
|
|
||||||
@Readonly
|
|
||||||
internal fun getUniqueContainerPrefix(uniqueContainer: IHasUniques?) =
|
internal fun getUniqueContainerPrefix(uniqueContainer: IHasUniques?) =
|
||||||
(if (uniqueContainer is IRulesetObject) "${uniqueContainer.originRuleset}: " else "") +
|
(if (uniqueContainer is IRulesetObject) "${uniqueContainer.originRuleset}: " else "") +
|
||||||
(if (uniqueContainer == null) "The" else "(${uniqueContainer.getUniqueTarget().name}) ${uniqueContainer.name}'s") +
|
(if (uniqueContainer == null) "The" else "(${uniqueContainer.getUniqueTarget().name}) ${uniqueContainer.name}'s") +
|
||||||
|
@ -45,11 +45,11 @@ object UnitActionsFromUniques {
|
|||||||
UnitActionModifiers.getUsableUnitActionUniques(unit,
|
UnitActionModifiers.getUsableUnitActionUniques(unit,
|
||||||
UniqueType.FoundPuppetCity).firstOrNull() ?: return null
|
UniqueType.FoundPuppetCity).firstOrNull() ?: return null
|
||||||
|
|
||||||
|
if (tile.isWater || tile.isImpassible()) return null
|
||||||
// Spain should still be able to build Conquistadors in a one city challenge - but can't settle them
|
// Spain should still be able to build Conquistadors in a one city challenge - but can't settle them
|
||||||
if (unit.civ.isOneCityChallenger() && unit.civ.hasEverOwnedOriginalCapital) return null
|
if (unit.civ.isOneCityChallenger() && unit.civ.hasEverOwnedOriginalCapital) return null
|
||||||
|
|
||||||
if (!unit.hasMovement() || !tile.canBeSettled(unique))
|
if (!unit.hasMovement() || !tile.canBeSettled())
|
||||||
return UnitAction(UnitActionType.FoundCity, 80f, action = null)
|
return UnitAction(UnitActionType.FoundCity, 80f, action = null)
|
||||||
|
|
||||||
val hasActionModifiers = unique.modifiers.any { it.type?.targetTypes?.contains(
|
val hasActionModifiers = unique.modifiers.any { it.type?.targetTypes?.contains(
|
||||||
|
@ -3535,8 +3535,6 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
|
|||||||
Applicable to: Conditional
|
Applicable to: Conditional
|
||||||
|
|
||||||
??? example "<in [tileFilter] tiles>"
|
??? example "<in [tileFilter] tiles>"
|
||||||
Can be used with FoundCity and FoundPuppetCity to only found cities in Water/Impassible tiles.
|
|
||||||
|
|
||||||
Example: "<in [Farm] tiles>"
|
Example: "<in [Farm] tiles>"
|
||||||
|
|
||||||
Applicable to: Conditional
|
Applicable to: Conditional
|
||||||
|
@ -23,6 +23,7 @@ theme:
|
|||||||
|
|
||||||
repo_name: yairm210/unciv
|
repo_name: yairm210/unciv
|
||||||
repo_url: https://github.com/yairm210/unciv
|
repo_url: https://github.com/yairm210/unciv
|
||||||
|
site_url: https://yairm210.github.io/Unciv
|
||||||
|
|
||||||
markdown_extensions:
|
markdown_extensions:
|
||||||
# For adminitions
|
# For adminitions
|
||||||
|
Loading…
x
Reference in New Issue
Block a user