mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-13 01:08:25 +07:00
Precursor to mod target check - (#5303)
* Precursor to mod target check - Define acceptable targets for each unique holder * Warn for bad unique targets, and divide between different types of beliefs * Moved the belief type logic into the class, rather than being external * Added comment that getUniqueTarget is currently unneeded, but planned for future use
This commit is contained in:
@ -7,13 +7,18 @@ import com.unciv.models.stats.INamed
|
|||||||
import com.unciv.models.translations.tr
|
import com.unciv.models.translations.tr
|
||||||
import com.unciv.ui.civilopedia.FormattedLine
|
import com.unciv.ui.civilopedia.FormattedLine
|
||||||
import com.unciv.ui.civilopedia.ICivilopediaText
|
import com.unciv.ui.civilopedia.ICivilopediaText
|
||||||
import java.util.ArrayList
|
import kotlin.collections.ArrayList
|
||||||
|
|
||||||
class Belief : INamed, ICivilopediaText, IHasUniques {
|
class Belief : INamed, ICivilopediaText, IHasUniques {
|
||||||
override var name: String = ""
|
override var name: String = ""
|
||||||
var type: BeliefType = BeliefType.None
|
var type: BeliefType = BeliefType.None
|
||||||
override var uniques = ArrayList<String>()
|
override var uniques = ArrayList<String>()
|
||||||
override val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it, UniqueTarget.Belief, name) } }
|
|
||||||
|
override fun getUniqueTarget() =
|
||||||
|
if (type == BeliefType.Founder || type == BeliefType.Enhancer) UniqueTarget.FounderBelief
|
||||||
|
else UniqueTarget.FollowerBelief
|
||||||
|
override val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it,
|
||||||
|
getUniqueTarget(), name) } }
|
||||||
|
|
||||||
override var civilopediaText = listOf<FormattedLine>()
|
override var civilopediaText = listOf<FormattedLine>()
|
||||||
|
|
||||||
|
@ -67,6 +67,7 @@ class Building : NamedStats(), INonPerpetualConstruction, ICivilopediaText {
|
|||||||
var uniqueTo: String? = null
|
var uniqueTo: String? = null
|
||||||
var quote: String = ""
|
var quote: String = ""
|
||||||
override var uniques = ArrayList<String>()
|
override var uniques = ArrayList<String>()
|
||||||
|
override fun getUniqueTarget() = UniqueTarget.Building
|
||||||
override val uniqueObjects: List<Unique> by lazy {
|
override val uniqueObjects: List<Unique> by lazy {
|
||||||
uniques.map {
|
uniques.map {
|
||||||
Unique(it, if (isAnyWonder()) UniqueTarget.Wonder else UniqueTarget.Building, name)
|
Unique(it, if (isAnyWonder()) UniqueTarget.Wonder else UniqueTarget.Building, name)
|
||||||
|
@ -33,7 +33,9 @@ class Era : INamed, IHasUniques {
|
|||||||
|
|
||||||
var iconRGB: List<Int>? = null
|
var iconRGB: List<Int>? = null
|
||||||
override var uniques: ArrayList<String> = arrayListOf()
|
override var uniques: ArrayList<String> = arrayListOf()
|
||||||
override val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it, UniqueTarget.Era, name) } }
|
override fun getUniqueTarget() = UniqueTarget.Era
|
||||||
|
override val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it,
|
||||||
|
getUniqueTarget(), name) } }
|
||||||
|
|
||||||
private fun initBonuses(bonusMap: Map<String, List<String>>): Map<CityStateType, List<Unique>> {
|
private fun initBonuses(bonusMap: Map<String, List<String>>): Map<CityStateType, List<Unique>> {
|
||||||
val objectMap = HashMap<CityStateType, List<Unique>>()
|
val objectMap = HashMap<CityStateType, List<Unique>>()
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package com.unciv.models.ruleset
|
package com.unciv.models.ruleset
|
||||||
|
|
||||||
import com.unciv.models.ruleset.unique.Unique
|
import com.unciv.models.ruleset.unique.Unique
|
||||||
|
import com.unciv.models.ruleset.unique.UniqueTarget
|
||||||
import com.unciv.models.ruleset.unique.UniqueType
|
import com.unciv.models.ruleset.unique.UniqueType
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -8,7 +9,12 @@ import com.unciv.models.ruleset.unique.UniqueType
|
|||||||
*/
|
*/
|
||||||
interface IHasUniques {
|
interface IHasUniques {
|
||||||
var uniques: ArrayList<String> // Can not be a hashset as that would remove doubles
|
var uniques: ArrayList<String> // Can not be a hashset as that would remove doubles
|
||||||
|
// I bet there's a way of initializing these without having to override it everywhere...
|
||||||
val uniqueObjects: List<Unique>
|
val uniqueObjects: List<Unique>
|
||||||
|
/** Technically not currently needed, since the unique target can be retrieved from every unique in the uniqueObjects,
|
||||||
|
* But making this a function is relevant for future "unify Unciv object" plans ;)
|
||||||
|
* */
|
||||||
|
fun getUniqueTarget(): UniqueTarget
|
||||||
|
|
||||||
fun getMatchingUniques(uniqueTemplate: String) = uniqueObjects.asSequence().filter { it.placeholderText == uniqueTemplate }
|
fun getMatchingUniques(uniqueTemplate: String) = uniqueObjects.asSequence().filter { it.placeholderText == uniqueTemplate }
|
||||||
fun getMatchingUniques(uniqueType: UniqueType) = uniqueObjects.asSequence().filter { it.isOfType(uniqueType) }
|
fun getMatchingUniques(uniqueType: UniqueType) = uniqueObjects.asSequence().filter { it.isOfType(uniqueType) }
|
||||||
|
@ -44,7 +44,9 @@ class Nation : INamed, ICivilopediaText, IHasUniques {
|
|||||||
lateinit var outerColor: List<Int>
|
lateinit var outerColor: List<Int>
|
||||||
var uniqueName = ""
|
var uniqueName = ""
|
||||||
override var uniques = ArrayList<String>()
|
override var uniques = ArrayList<String>()
|
||||||
override val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it, UniqueTarget.Nation, name) } }
|
override fun getUniqueTarget() = UniqueTarget.Nation
|
||||||
|
override val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it,
|
||||||
|
getUniqueTarget(), name) } }
|
||||||
var uniqueText = ""
|
var uniqueText = ""
|
||||||
var innerColor: List<Int>? = null
|
var innerColor: List<Int>? = null
|
||||||
var startBias = ArrayList<String>()
|
var startBias = ArrayList<String>()
|
||||||
|
@ -12,7 +12,9 @@ open class Policy : INamed, IHasUniques, ICivilopediaText {
|
|||||||
|
|
||||||
override lateinit var name: String
|
override lateinit var name: String
|
||||||
override var uniques: ArrayList<String> = ArrayList()
|
override var uniques: ArrayList<String> = ArrayList()
|
||||||
override val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it, UniqueTarget.Policy, name) } }
|
override fun getUniqueTarget() = UniqueTarget.Policy
|
||||||
|
override val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it,
|
||||||
|
getUniqueTarget(), name) } }
|
||||||
var row: Int = 0
|
var row: Int = 0
|
||||||
var column: Int = 0
|
var column: Int = 0
|
||||||
var requires: ArrayList<String>? = null
|
var requires: ArrayList<String>? = null
|
||||||
|
@ -10,6 +10,8 @@ class RuinReward : INamed, ICivilopediaText, IHasUniques {
|
|||||||
override lateinit var name: String // Displayed in Civilopedia!
|
override lateinit var name: String // Displayed in Civilopedia!
|
||||||
val notification: String = ""
|
val notification: String = ""
|
||||||
override var uniques = ArrayList<String>()
|
override var uniques = ArrayList<String>()
|
||||||
|
|
||||||
|
override fun getUniqueTarget() = UniqueTarget.Ruins
|
||||||
@delegate:Transient // Defense in depth against mad modders
|
@delegate:Transient // Defense in depth against mad modders
|
||||||
override val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it, UniqueTarget.Ruins, name) } }
|
override val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it, UniqueTarget.Ruins, name) } }
|
||||||
|
|
||||||
|
@ -51,6 +51,8 @@ class ModOptions : IHasUniques {
|
|||||||
override var uniques = ArrayList<String>()
|
override var uniques = ArrayList<String>()
|
||||||
// If this is delegated with "by lazy", the mod download process crashes and burns
|
// If this is delegated with "by lazy", the mod download process crashes and burns
|
||||||
override var uniqueObjects: List<Unique> = listOf()
|
override var uniqueObjects: List<Unique> = listOf()
|
||||||
|
override fun getUniqueTarget() = UniqueTarget.ModOptions
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class Ruleset {
|
class Ruleset {
|
||||||
@ -296,14 +298,23 @@ class Ruleset {
|
|||||||
val deprecationAnnotation = unique.type.declaringClass.getField(unique.type.name)
|
val deprecationAnnotation = unique.type.declaringClass.getField(unique.type.name)
|
||||||
.getAnnotation(Deprecated::class.java)
|
.getAnnotation(Deprecated::class.java)
|
||||||
if (deprecationAnnotation != null) {
|
if (deprecationAnnotation != null) {
|
||||||
val deprecationText = "$name's unique \"${unique.text}\" is deprecated ${deprecationAnnotation.message}," +
|
val deprecationText =
|
||||||
|
"$name's unique \"${unique.text}\" is deprecated ${deprecationAnnotation.message}," +
|
||||||
" replace with \"${deprecationAnnotation.replaceWith.expression}\""
|
" replace with \"${deprecationAnnotation.replaceWith.expression}\""
|
||||||
val severity = if(deprecationAnnotation.level == DeprecationLevel.WARNING)
|
val severity = if (deprecationAnnotation.level == DeprecationLevel.WARNING)
|
||||||
RulesetErrorSeverity.WarningOptionsOnly // Not user-visible
|
RulesetErrorSeverity.WarningOptionsOnly // Not user-visible
|
||||||
else RulesetErrorSeverity.Warning // User visible
|
else RulesetErrorSeverity.Warning // User visible
|
||||||
|
|
||||||
lines.add(deprecationText, severity)
|
lines.add(deprecationText, severity)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val acceptableUniqueType = uniqueContainer.getUniqueTarget()
|
||||||
|
if (unique.type.targetTypes.none { acceptableUniqueType.canAcceptUniqueTarget(it) })
|
||||||
|
lines.add(
|
||||||
|
"$name's unique \"${unique.text}\" cannot be put on this type of object!",
|
||||||
|
RulesetErrorSeverity.Warning
|
||||||
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,9 @@ class Technology: INamed, ICivilopediaText, IHasUniques {
|
|||||||
var cost: Int = 0
|
var cost: Int = 0
|
||||||
var prerequisites = HashSet<String>()
|
var prerequisites = HashSet<String>()
|
||||||
override var uniques = ArrayList<String>()
|
override var uniques = ArrayList<String>()
|
||||||
override val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it, UniqueTarget.Tech, name) } }
|
override fun getUniqueTarget() = UniqueTarget.Tech
|
||||||
|
override val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it,
|
||||||
|
getUniqueTarget(), name) } }
|
||||||
|
|
||||||
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
|
||||||
|
@ -29,7 +29,9 @@ class Terrain : NamedStats(), ICivilopediaText, IHasUniques {
|
|||||||
|
|
||||||
/** Uniques (Properties such as Temp/humidity, Fresh water, elevation, rough, defense, Natural Wonder specials) */
|
/** Uniques (Properties such as Temp/humidity, Fresh water, elevation, rough, defense, Natural Wonder specials) */
|
||||||
override var uniques = ArrayList<String>()
|
override var uniques = ArrayList<String>()
|
||||||
override val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it, UniqueTarget.Terrain, name) } }
|
override fun getUniqueTarget() = UniqueTarget.Terrain
|
||||||
|
override val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it,
|
||||||
|
getUniqueTarget(), name) } }
|
||||||
|
|
||||||
/** Natural Wonder weight: probability to be picked */
|
/** Natural Wonder weight: probability to be picked */
|
||||||
var weight = 10
|
var weight = 10
|
||||||
|
@ -23,7 +23,9 @@ class TileImprovement : NamedStats(), ICivilopediaText, IHasUniques {
|
|||||||
var techRequired: String? = null
|
var techRequired: String? = null
|
||||||
var uniqueTo:String? = null
|
var uniqueTo:String? = null
|
||||||
override var uniques = ArrayList<String>()
|
override var uniques = ArrayList<String>()
|
||||||
override val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it, UniqueTarget.Improvement, name) } }
|
override fun getUniqueTarget() = UniqueTarget.Improvement
|
||||||
|
override val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it,
|
||||||
|
getUniqueTarget(), name) } }
|
||||||
val shortcutKey: Char? = null
|
val shortcutKey: Char? = null
|
||||||
val turnsToBuild: Int = 0 // This is the base cost.
|
val turnsToBuild: Int = 0 // This is the base cost.
|
||||||
|
|
||||||
|
@ -20,7 +20,9 @@ class TileResource : NamedStats(), ICivilopediaText, IHasUniques {
|
|||||||
@Deprecated("As of 3.16.16 - replaced by uniques")
|
@Deprecated("As of 3.16.16 - replaced by uniques")
|
||||||
var unique: String? = null
|
var unique: String? = null
|
||||||
override var uniques: ArrayList<String> = arrayListOf()
|
override var uniques: ArrayList<String> = arrayListOf()
|
||||||
override val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it, UniqueTarget.Resource, name) } }
|
override fun getUniqueTarget() = UniqueTarget.Resource
|
||||||
|
override val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it,
|
||||||
|
getUniqueTarget(), name) } }
|
||||||
|
|
||||||
override var civilopediaText = listOf<FormattedLine>()
|
override var civilopediaText = listOf<FormattedLine>()
|
||||||
|
|
||||||
|
@ -3,27 +3,38 @@ package com.unciv.models.ruleset.unique
|
|||||||
import com.unciv.models.ruleset.Ruleset
|
import com.unciv.models.ruleset.Ruleset
|
||||||
import com.unciv.models.translations.getPlaceholderParameters
|
import com.unciv.models.translations.getPlaceholderParameters
|
||||||
import com.unciv.models.translations.getPlaceholderText
|
import com.unciv.models.translations.getPlaceholderText
|
||||||
|
import kotlin.collections.ArrayList
|
||||||
|
import kotlin.collections.HashSet
|
||||||
|
|
||||||
/** Buildings, units, nations, policies, religions, techs etc.
|
/** inheritsFrom means that all such uniques are acceptable as well.
|
||||||
|
* For example, all Global uniques are acceptable for Nations, Eras, etc. */
|
||||||
|
enum class UniqueTarget(val inheritsFrom:UniqueTarget?=null) {
|
||||||
|
|
||||||
|
/** Buildings, units, nations, policies, religions, techs etc.
|
||||||
* Basically anything caught by CivInfo.getMatchingUniques. */
|
* Basically anything caught by CivInfo.getMatchingUniques. */
|
||||||
enum class UniqueTarget {
|
|
||||||
Global,
|
Global,
|
||||||
|
|
||||||
// Civilization-specific
|
// Civilization-specific
|
||||||
Nation,
|
Nation(Global),
|
||||||
Era,
|
Era(Global),
|
||||||
Tech,
|
Tech(Global),
|
||||||
Policy,
|
Policy(Global),
|
||||||
Belief,
|
FounderBelief(Global),
|
||||||
|
/** These apply only to cities where the religion is the majority religion */
|
||||||
|
FollowerBelief,
|
||||||
|
|
||||||
// City-specific
|
// City-specific
|
||||||
Building,
|
/** This is used as the base when checking buildings */
|
||||||
Wonder,
|
Building(Global),
|
||||||
|
Wonder(Building),
|
||||||
|
|
||||||
// Unit-specific
|
// Unit-specific
|
||||||
|
// These are a bit of a lie. There's no "Promotion only" or "UnitType only" uniques,
|
||||||
|
// they're all just Unit uniques in different places.
|
||||||
|
// So there should be no uniqueType that has a Promotion or UnitType target.
|
||||||
Unit,
|
Unit,
|
||||||
UnitType,
|
UnitType(Unit),
|
||||||
Promotion,
|
Promotion(Unit),
|
||||||
|
|
||||||
// Tile-specific
|
// Tile-specific
|
||||||
Terrain,
|
Terrain,
|
||||||
@ -35,9 +46,16 @@ enum class UniqueTarget {
|
|||||||
CityState,
|
CityState,
|
||||||
ModOptions,
|
ModOptions,
|
||||||
Conditional,
|
Conditional,
|
||||||
|
;
|
||||||
|
|
||||||
|
fun canAcceptUniqueTarget(uniqueTarget: UniqueTarget): Boolean {
|
||||||
|
if (this == uniqueTarget) return true
|
||||||
|
if (inheritsFrom != null) return inheritsFrom.canAcceptUniqueTarget(uniqueTarget)
|
||||||
|
return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class UniqueType(val text:String, vararg target: UniqueTarget) {
|
enum class UniqueType(val text:String, vararg targets: UniqueTarget) {
|
||||||
|
|
||||||
Stats("[stats]", UniqueTarget.Global),
|
Stats("[stats]", UniqueTarget.Global),
|
||||||
StatsPerCity("[stats] [cityFilter]", UniqueTarget.Global),
|
StatsPerCity("[stats] [cityFilter]", UniqueTarget.Global),
|
||||||
@ -91,7 +109,7 @@ enum class UniqueType(val text:String, vararg target: UniqueTarget) {
|
|||||||
/** For uniques that have "special" parameters that can accept multiple types, we can override them manually
|
/** For uniques that have "special" parameters that can accept multiple types, we can override them manually
|
||||||
* For 95% of cases, auto-matching is fine. */
|
* For 95% of cases, auto-matching is fine. */
|
||||||
val parameterTypeMap = ArrayList<List<UniqueParameterType>>()
|
val parameterTypeMap = ArrayList<List<UniqueParameterType>>()
|
||||||
val replacedBy: UniqueType? = null
|
val targetTypes = HashSet<UniqueTarget>()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
for (placeholder in text.getPlaceholderParameters()) {
|
for (placeholder in text.getPlaceholderParameters()) {
|
||||||
@ -100,6 +118,7 @@ enum class UniqueType(val text:String, vararg target: UniqueTarget) {
|
|||||||
?: UniqueParameterType.Unknown
|
?: UniqueParameterType.Unknown
|
||||||
parameterTypeMap.add(listOf(matchingParameterType))
|
parameterTypeMap.add(listOf(matchingParameterType))
|
||||||
}
|
}
|
||||||
|
targetTypes.addAll(targets)
|
||||||
}
|
}
|
||||||
|
|
||||||
val placeholderText = text.getPlaceholderText()
|
val placeholderText = text.getPlaceholderText()
|
||||||
|
@ -40,8 +40,12 @@ class BaseUnit : INamed, INonPerpetualConstruction, ICivilopediaText {
|
|||||||
fun getType() = ruleset.unitTypes[unitType]!!
|
fun getType() = ruleset.unitTypes[unitType]!!
|
||||||
var requiredTech: String? = null
|
var requiredTech: String? = null
|
||||||
private var requiredResource: String? = null
|
private var requiredResource: String? = null
|
||||||
|
|
||||||
override var uniques = ArrayList<String>() // Can not be a hashset as that would remove doubles
|
override var uniques = ArrayList<String>() // Can not be a hashset as that would remove doubles
|
||||||
override val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it, UniqueTarget.Unit, name) } }
|
override fun getUniqueTarget() = UniqueTarget.Unit
|
||||||
|
override val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it,
|
||||||
|
getUniqueTarget(), name) } }
|
||||||
|
|
||||||
private var replacementTextForUniques = ""
|
private var replacementTextForUniques = ""
|
||||||
var promotions = HashSet<String>()
|
var promotions = HashSet<String>()
|
||||||
var obsoleteTech: String? = null
|
var obsoleteTech: String? = null
|
||||||
|
@ -23,7 +23,10 @@ class Promotion : INamed, ICivilopediaText, IHasUniques {
|
|||||||
if (effect.isNotEmpty()) yield(effect)
|
if (effect.isNotEmpty()) yield(effect)
|
||||||
yieldAll(uniques)
|
yieldAll(uniques)
|
||||||
}
|
}
|
||||||
override val uniqueObjects: List<Unique> by lazy { uniquesWithEffect().map { Unique(it, UniqueTarget.Promotion, name) }.toList() }
|
|
||||||
|
override fun getUniqueTarget() = UniqueTarget.Promotion
|
||||||
|
override val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it,
|
||||||
|
getUniqueTarget(), name) } }
|
||||||
|
|
||||||
override var civilopediaText = listOf<FormattedLine>()
|
override var civilopediaText = listOf<FormattedLine>()
|
||||||
|
|
||||||
|
@ -24,7 +24,9 @@ class UnitType() : INamed, IHasUniques {
|
|||||||
private val unitMovementType: UnitMovementType? by lazy { if (movementType == null) null else UnitMovementType.valueOf(movementType!!) }
|
private val unitMovementType: UnitMovementType? by lazy { if (movementType == null) null else UnitMovementType.valueOf(movementType!!) }
|
||||||
|
|
||||||
override var uniques: ArrayList<String> = ArrayList()
|
override var uniques: ArrayList<String> = ArrayList()
|
||||||
override val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it, UniqueTarget.Unit, name) } }
|
override fun getUniqueTarget() = UniqueTarget.UnitType
|
||||||
|
override val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it,
|
||||||
|
getUniqueTarget(), name) } }
|
||||||
|
|
||||||
constructor(name: String, domain: String? = null) : this() {
|
constructor(name: String, domain: String? = null) : this() {
|
||||||
this.name = name
|
this.name = name
|
||||||
|
Reference in New Issue
Block a user