mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-08 23:08:35 +07:00
From the indstrial era onwards, things change in religion (#5095)
* Improved redability * From the industrial era onwards, religion goes into 'second phase' * Fixed tests * Fixed formula for buying great prophets starting from the industrial era * Added `getMatchingUniques`, `hasUnique` to `IHasUniques`, cleaned up some code * Fix compilation errors
This commit is contained in:
@ -137,7 +137,11 @@
|
||||
"Mercantile": ["Provides [3] Happiness", "Provides a unique luxury"],
|
||||
"Militaristic": ["Provides military units every [17] turns"]
|
||||
},
|
||||
"iconRGB": [63, 81, 182]
|
||||
"iconRGB": [63, 81, 182],
|
||||
"uniques": ["May not generate great prophet equivalents naturally",
|
||||
"May buy [Great Prophet] units for [200] [Faith] [in all cities in which the majority religion is a major religion] at an increasing price ([100])",
|
||||
"Starting in this era disables religion"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Modern era",
|
||||
@ -168,7 +172,11 @@
|
||||
"Mercantile": ["Provides [3] Happiness", "Provides a unique luxury"],
|
||||
"Militaristic": ["Provides military units every [17] turns"]
|
||||
},
|
||||
"iconRGB": [33, 150, 243]
|
||||
"iconRGB": [33, 150, 243],
|
||||
"uniques": ["May not generate great prophet equivalents naturally",
|
||||
"May buy [Great Prophet] units for [200] [Faith] [in all cities in which the majority religion is a major religion] at an increasing price ([100])",
|
||||
"Starting in this era disables religion"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Atomic era",
|
||||
@ -200,7 +208,11 @@
|
||||
"Mercantile": ["Provides [3] Happiness", "Provides a unique luxury"],
|
||||
"Militaristic": ["Provides military units every [17] turns"]
|
||||
},
|
||||
"iconRGB": [0, 150, 136]
|
||||
"iconRGB": [0, 150, 136],
|
||||
"uniques": ["May not generate great prophet equivalents naturally",
|
||||
"May buy [Great Prophet] units for [200] [Faith] [in all cities in which the majority religion is a major religion] at an increasing price ([100])",
|
||||
"Starting in this era disables religion"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Information era",
|
||||
@ -236,7 +248,11 @@
|
||||
"Mercantile": ["Provides [3] Happiness", "Provides a unique luxury"],
|
||||
"Militaristic": ["Provides military units every [17] turns"]
|
||||
},
|
||||
"iconRGB": [76, 176, 81]
|
||||
"iconRGB": [76, 176, 81],
|
||||
"uniques": ["May not generate great prophet equivalents naturally",
|
||||
"May buy [Great Prophet] units for [200] [Faith] [in all cities in which the majority religion is a major religion] at an increasing price ([100])",
|
||||
"Starting in this era disables religion"
|
||||
]
|
||||
},
|
||||
{ // Technically, this Era doesn't exist in the original game.
|
||||
// But as it is _really_ usefull to have for testing, I'd like to keep it.
|
||||
@ -271,6 +287,10 @@
|
||||
"Mercantile": ["Provides [3] Happiness", "Provides a unique luxury"],
|
||||
"Militaristic": ["Provides military units every [17] turns"]
|
||||
},
|
||||
"iconRGB": [76, 176, 81]
|
||||
"iconRGB": [76, 176, 81],
|
||||
"uniques": ["May not generate great prophet equivalents naturally",
|
||||
"May buy [Great Prophet] units for [200] [Faith] [in all cities in which the majority religion is a major religion] at an increasing price ([100])",
|
||||
"Starting in this era disables religion"
|
||||
]
|
||||
}
|
||||
]
|
@ -433,7 +433,10 @@ class GameInfo {
|
||||
}
|
||||
|
||||
|
||||
fun hasReligionEnabled() = gameParameters.religionEnabled || ruleSet.hasReligion() // Temporary function to check whether religion should be used for this game
|
||||
fun hasReligionEnabled() =
|
||||
// Temporary function to check whether religion should be used for this game
|
||||
(gameParameters.religionEnabled || ruleSet.hasReligion())
|
||||
&& (ruleSet.eras.isEmpty() || !ruleSet.eras[gameParameters.startingEra]!!.hasUnique("Starting in this era disables religion"))
|
||||
}
|
||||
|
||||
// reduced variant only for load preview
|
||||
|
@ -43,15 +43,15 @@ class CityInfo {
|
||||
lateinit var tilesInRange: HashSet<TileInfo>
|
||||
|
||||
@Transient
|
||||
var hasJustBeenConquered =
|
||||
false // this is so that military units can enter the city, even before we decide what to do with it
|
||||
// This is so that military units can enter the city, even before we decide what to do with it
|
||||
var hasJustBeenConquered = false
|
||||
|
||||
var location: Vector2 = Vector2.Zero
|
||||
var id: String = UUID.randomUUID().toString()
|
||||
var name: String = ""
|
||||
var foundingCiv = ""
|
||||
var previousOwner =
|
||||
"" // This is so that cities in resistance that re recaptured aren't in resistance anymore
|
||||
// This is so that cities in resistance that are recaptured aren't in resistance anymore
|
||||
var previousOwner = ""
|
||||
var turnAcquired = 0
|
||||
var health = 200
|
||||
var resistanceCounter = 0
|
||||
@ -245,8 +245,10 @@ class CityInfo {
|
||||
fun isCapital(): Boolean = cityConstructions.builtBuildings.contains(capitalCityIndicator())
|
||||
fun isCoastal(): Boolean = centerTileInfo.isCoastalTile()
|
||||
fun capitalCityIndicator(): String {
|
||||
val indicatorBuildings = getRuleset().buildings.values.asSequence()
|
||||
val indicatorBuildings = getRuleset().buildings.values
|
||||
.asSequence()
|
||||
.filter { it.uniques.contains("Indicates the capital city") }
|
||||
|
||||
val civSpecificBuilding = indicatorBuildings.firstOrNull { it.uniqueTo == civInfo.civName }
|
||||
if (civSpecificBuilding != null) return civSpecificBuilding.name
|
||||
else return indicatorBuildings.first().name
|
||||
@ -294,8 +296,9 @@ class CityInfo {
|
||||
val resource = getRuleset().tileResources[unique.params[1]]
|
||||
if (resource != null) {
|
||||
cityResources.add(
|
||||
resource, unique.params[0].toInt()
|
||||
* civInfo.getResourceModifier(resource), "Tiles"
|
||||
resource,
|
||||
unique.params[0].toInt() * civInfo.getResourceModifier(resource),
|
||||
"Tiles"
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -596,11 +599,15 @@ class CityInfo {
|
||||
*/
|
||||
private fun triggerCitiesSettledNearOtherCiv() {
|
||||
val citiesWithin6Tiles =
|
||||
civInfo.gameInfo.civilizations.filter { it.isMajorCiv() && it != civInfo }
|
||||
civInfo.gameInfo.civilizations
|
||||
.filter { it.isMajorCiv() && it != civInfo }
|
||||
.flatMap { it.cities }
|
||||
.filter { it.getCenterTile().aerialDistanceTo(getCenterTile()) <= 6 }
|
||||
val civsWithCloseCities = citiesWithin6Tiles.map { it.civInfo }.distinct()
|
||||
.filter { it.knows(civInfo) && it.exploredTiles.contains(location) }
|
||||
val civsWithCloseCities =
|
||||
citiesWithin6Tiles
|
||||
.map { it.civInfo }
|
||||
.distinct()
|
||||
.filter { it.knows(civInfo) && it.exploredTiles.contains(location) }
|
||||
for (otherCiv in civsWithCloseCities)
|
||||
otherCiv.getDiplomacyManager(civInfo).setFlag(DiplomacyFlags.SettledCitiesNearUs, 30)
|
||||
}
|
||||
@ -627,13 +634,13 @@ class CityInfo {
|
||||
"in all cities with a garrison" -> getCenterTile().militaryUnit != null
|
||||
"in all cities in which the majority religion is a major religion" ->
|
||||
religion.getMajorityReligionName() != null
|
||||
&& religion.getMajorityReligion()!!.isMajorReligion()
|
||||
&& religion.getMajorityReligion()!!.isMajorReligion()
|
||||
"in all cities in which the majority religion is an enhanced religion" ->
|
||||
religion.getMajorityReligionName() != null
|
||||
&& religion.getMajorityReligion()!!.isEnhancedReligion()
|
||||
&& religion.getMajorityReligion()!!.isEnhancedReligion()
|
||||
"in non-enemy foreign cities" ->
|
||||
viewingCiv != civInfo
|
||||
&& !civInfo.isAtWarWith(viewingCiv)
|
||||
&& !civInfo.isAtWarWith(viewingCiv)
|
||||
"in foreign cities" -> viewingCiv != civInfo
|
||||
"in annexed cities" -> foundingCiv != civInfo.civName && !isPuppet
|
||||
"in holy cities" -> religion.religionThisIsTheHolyCityOf != null
|
||||
@ -715,9 +722,11 @@ class CityInfo {
|
||||
if (!tilesList.contains(tile))
|
||||
cityPositionList.add(tile)
|
||||
|
||||
return cityPositionList.asSequence()
|
||||
.map { it.getOwner()?.civName }.filterNotNull()
|
||||
.distinct().toList()
|
||||
return cityPositionList
|
||||
.asSequence()
|
||||
.mapNotNull { it.getOwner()?.civName }
|
||||
.distinct()
|
||||
.toList()
|
||||
}
|
||||
|
||||
fun getImprovableTiles(): Sequence<TileInfo> = getTiles()
|
||||
|
@ -24,13 +24,6 @@ interface INonPerpetualConstruction : IConstruction, INamed, IHasUniques {
|
||||
fun getRejectionReasons(cityConstructions: CityConstructions): RejectionReasons
|
||||
fun postBuildEvent(cityConstructions: CityConstructions, boughtWith: Stat? = null): Boolean // Yes I'm hilarious.
|
||||
|
||||
fun getMatchingUniques(uniqueTemplate: String): Sequence<Unique> {
|
||||
return uniqueObjects.asSequence().filter { it.placeholderText == uniqueTemplate }
|
||||
}
|
||||
fun hasUnique(uniqueTemplate: String): Boolean {
|
||||
return uniqueObjects.any { it.placeholderText == uniqueTemplate }
|
||||
}
|
||||
|
||||
fun canBePurchasedWithStat(cityInfo: CityInfo?, stat: Stat): Boolean {
|
||||
if (stat in listOf(Stat.Production, Stat.Happiness)) return false
|
||||
if ("Cannot be purchased" in uniques) return false
|
||||
@ -82,41 +75,46 @@ interface INonPerpetualConstruction : IConstruction, INamed, IHasUniques {
|
||||
|
||||
|
||||
class RejectionReasons(): HashSet<RejectionReason>() {
|
||||
private val techPolicyEraWonderRequirements = hashSetOf(
|
||||
RejectionReason.Obsoleted,
|
||||
RejectionReason.RequiresTech,
|
||||
RejectionReason.RequiresPolicy,
|
||||
RejectionReason.MorePolicyBranches,
|
||||
RejectionReason.RequiresBuildingInSomeCity
|
||||
)
|
||||
|
||||
fun filterTechPolicyEraWonderRequirements(): HashSet<RejectionReason> {
|
||||
return filterNot { it in techPolicyEraWonderRequirements }.toHashSet()
|
||||
}
|
||||
|
||||
private val reasonsToDefinitivelyRemoveFromQueue = hashSetOf(
|
||||
RejectionReason.Obsoleted,
|
||||
RejectionReason.WonderAlreadyBuilt,
|
||||
RejectionReason.NationalWonderAlreadyBuilt,
|
||||
RejectionReason.CannotBeBuiltWith,
|
||||
RejectionReason.ReachedBuildCap
|
||||
)
|
||||
fun hasAReasonToBeRemovedFromQueue(): Boolean {
|
||||
return any { it in reasonsToDefinitivelyRemoveFromQueue }
|
||||
}
|
||||
|
||||
private val orderOfErrorMessages = listOf(
|
||||
RejectionReason.WonderBeingBuiltElsewhere,
|
||||
RejectionReason.NationalWonderBeingBuiltElsewhere,
|
||||
RejectionReason.RequiresBuildingInAllCities,
|
||||
RejectionReason.RequiresBuildingInThisCity,
|
||||
RejectionReason.RequiresBuildingInSomeCity,
|
||||
RejectionReason.PopulationRequirement,
|
||||
RejectionReason.ConsumesResources,
|
||||
RejectionReason.CanOnlyBePurchased
|
||||
)
|
||||
fun getMostImportantRejectionReason(): String? {
|
||||
return orderOfErrorMessages.firstOrNull { it in this }?.errorMessage
|
||||
}
|
||||
|
||||
// Used for constant variables in the functions above
|
||||
companion object {
|
||||
private val techPolicyEraWonderRequirements = hashSetOf(
|
||||
RejectionReason.Obsoleted,
|
||||
RejectionReason.RequiresTech,
|
||||
RejectionReason.RequiresPolicy,
|
||||
RejectionReason.MorePolicyBranches,
|
||||
RejectionReason.RequiresBuildingInSomeCity
|
||||
)
|
||||
private val reasonsToDefinitivelyRemoveFromQueue = hashSetOf(
|
||||
RejectionReason.Obsoleted,
|
||||
RejectionReason.WonderAlreadyBuilt,
|
||||
RejectionReason.NationalWonderAlreadyBuilt,
|
||||
RejectionReason.CannotBeBuiltWith,
|
||||
RejectionReason.ReachedBuildCap
|
||||
)
|
||||
private val orderOfErrorMessages = listOf(
|
||||
RejectionReason.WonderBeingBuiltElsewhere,
|
||||
RejectionReason.NationalWonderBeingBuiltElsewhere,
|
||||
RejectionReason.RequiresBuildingInAllCities,
|
||||
RejectionReason.RequiresBuildingInThisCity,
|
||||
RejectionReason.RequiresBuildingInSomeCity,
|
||||
RejectionReason.PopulationRequirement,
|
||||
RejectionReason.ConsumesResources,
|
||||
RejectionReason.CanOnlyBePurchased
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -293,11 +293,15 @@ class CivilizationInfo {
|
||||
temporaryUniques
|
||||
.asSequence()
|
||||
.filter { it.first.placeholderText == uniqueTemplate }.map { it.first } +
|
||||
if (religionManager.religion != null)
|
||||
religionManager.religion!!.getFounderUniques()
|
||||
.asSequence()
|
||||
.filter { it.placeholderText == uniqueTemplate }
|
||||
else sequenceOf()
|
||||
getEra().getMatchingUniques(uniqueTemplate)
|
||||
.asSequence() +
|
||||
(
|
||||
if (religionManager.religion != null)
|
||||
religionManager.religion!!.getFounderUniques()
|
||||
.asSequence()
|
||||
.filter { it.placeholderText == uniqueTemplate }
|
||||
else sequenceOf()
|
||||
)
|
||||
}
|
||||
|
||||
//region Units
|
||||
|
@ -27,8 +27,11 @@ class ReligionManager {
|
||||
// But the other one should still be _somewhere_. So our only option is to have the GameInfo
|
||||
// contain the master list, and the ReligionManagers retrieve it from there every time the game loads.
|
||||
|
||||
var greatProphetsEarned = 0
|
||||
private set
|
||||
// Deprecated since 3.16.13
|
||||
@Deprecated("Replace by adding to `civInfo.boughtConstructionsWithGloballyIncreasingPrice`")
|
||||
var greatProphetsEarned = 0
|
||||
private set
|
||||
//
|
||||
|
||||
var religionState = ReligionState.None
|
||||
private set
|
||||
@ -47,7 +50,6 @@ class ReligionManager {
|
||||
clone.shouldChoosePantheonBelief = shouldChoosePantheonBelief
|
||||
clone.storedFaith = storedFaith
|
||||
clone.religionState = religionState
|
||||
clone.greatProphetsEarned = greatProphetsEarned
|
||||
return clone
|
||||
}
|
||||
|
||||
@ -62,6 +64,13 @@ class ReligionManager {
|
||||
religion = civInfo.gameInfo.religions.values.firstOrNull {
|
||||
it.foundingCivName == civInfo.civName
|
||||
}
|
||||
|
||||
// greatProphetsEarned deprecated since 3.16.13, replacement code
|
||||
if (greatProphetsEarned != 0) {
|
||||
civInfo.boughtConstructionsWithGloballyIncreasingPrice[getGreatProphetEquivalent()!!] = greatProphetsEarned
|
||||
greatProphetsEarned = 0
|
||||
}
|
||||
//
|
||||
}
|
||||
|
||||
fun startTurn() {
|
||||
@ -106,6 +115,8 @@ class ReligionManager {
|
||||
// https://www.reddit.com/r/civ/comments/2m82wu/can_anyone_detail_the_finer_points_of_great/
|
||||
// Game files (globaldefines.xml)
|
||||
fun faithForNextGreatProphet(): Int {
|
||||
val greatProphetsEarned = civInfo.boughtConstructionsWithGloballyIncreasingPrice[getGreatProphetEquivalent()!!] ?: 0
|
||||
|
||||
var faithCost =
|
||||
(200 + 100 * greatProphetsEarned * (greatProphetsEarned + 1) / 2f) *
|
||||
civInfo.gameInfo.gameParameters.gameSpeed.modifier
|
||||
@ -120,22 +131,28 @@ class ReligionManager {
|
||||
if (religion == null || religionState == ReligionState.None) return false // First get a pantheon, then we'll talk about a real religion
|
||||
if (storedFaith < faithForNextGreatProphet()) return false
|
||||
if (!civInfo.isMajorCiv()) return false
|
||||
// In the base game, great prophets shouldn't generate anymore starting from the industrial era
|
||||
// This is difficult to implement in the current codebase, probably requires an additional variable in eras.json
|
||||
if (civInfo.hasUnique("May not generate great prophet equivalents naturally")) return false
|
||||
return true
|
||||
}
|
||||
|
||||
fun getGreatProphetEquivalent(): String? {
|
||||
return civInfo.gameInfo.ruleSet.units.values.firstOrNull { it.hasUnique("May found a religion") }?.name
|
||||
}
|
||||
|
||||
private fun generateProphet() {
|
||||
val prophetUnitName = getGreatProphetEquivalent() ?: return // No prophet units in this mod
|
||||
|
||||
val prophetSpawnChange = (5f + storedFaith - faithForNextGreatProphet()) / 100f
|
||||
|
||||
if (Random(civInfo.gameInfo.turns).nextFloat() < prophetSpawnChange) {
|
||||
val birthCity =
|
||||
if (religionState <= ReligionState.Pantheon) civInfo.getCapital()
|
||||
else civInfo.cities.firstOrNull { it.religion.religionThisIsTheHolyCityOf == religion!!.name }
|
||||
val prophet = civInfo.addUnit("Great Prophet", birthCity) ?: return
|
||||
val prophet = civInfo.addUnit(prophetUnitName, birthCity) ?: return
|
||||
prophet.religion = religion!!.name
|
||||
storedFaith -= faithForNextGreatProphet()
|
||||
greatProphetsEarned += 1
|
||||
civInfo.boughtConstructionsWithGloballyIncreasingPrice[prophetUnitName] =
|
||||
(civInfo.boughtConstructionsWithGloballyIncreasingPrice[prophetUnitName] ?: 0) + 1
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,9 @@ class RuinsManager {
|
||||
for (possibleReward in possibleRewards) {
|
||||
if (civInfo.gameInfo.difficulty in possibleReward.excludedDifficulties) continue
|
||||
if (Constants.hiddenWithoutReligionUnique in possibleReward.uniques && !civInfo.gameInfo.hasReligionEnabled()) continue
|
||||
if ("Hidden after generating a Great Prophet" in possibleReward.uniques && civInfo.religionManager.greatProphetsEarned > 0) continue
|
||||
if ("Hidden after generating a Great Prophet" in possibleReward.uniques
|
||||
&& civInfo.boughtConstructionsWithGloballyIncreasingPrice[civInfo.religionManager.getGreatProphetEquivalent()] ?: 0 > 0
|
||||
) continue
|
||||
if (possibleReward.uniqueObjects.any { unique ->
|
||||
unique.placeholderText == "Only available after [] turns"
|
||||
&& unique.params[0].toInt() < civInfo.gameInfo.turns
|
||||
|
@ -5,7 +5,7 @@ import com.unciv.logic.civilization.CityStateType
|
||||
import com.unciv.models.stats.INamed
|
||||
import com.unciv.ui.utils.colorFromRGB
|
||||
|
||||
class Era : INamed {
|
||||
class Era : INamed, IHasUniques {
|
||||
override var name: String = ""
|
||||
var eraNumber: Int = -1
|
||||
var researchAgreementCost = 300
|
||||
@ -25,6 +25,8 @@ class Era : INamed {
|
||||
var friendBonus = HashMap<String, List<String>>()
|
||||
var allyBonus = HashMap<String, List<String>>()
|
||||
var iconRGB: List<Int>? = null
|
||||
override var uniques: ArrayList<String> = arrayListOf()
|
||||
override val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it) } }
|
||||
|
||||
fun getStartingUnits(): List<String> {
|
||||
val startingUnits = mutableListOf<String>()
|
||||
|
@ -6,4 +6,8 @@ package com.unciv.models.ruleset
|
||||
interface IHasUniques {
|
||||
var uniques: ArrayList<String> // Can not be a hashset as that would remove doubles
|
||||
val uniqueObjects: List<Unique>
|
||||
|
||||
fun getMatchingUniques(uniqueTemplate: String) = uniqueObjects.asSequence().filter { it.placeholderText == uniqueTemplate }
|
||||
|
||||
fun hasUnique(uniqueTemplate: String) = uniqueObjects.any { it.placeholderText == uniqueTemplate }
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ class RuinReward : INamed, ICivilopediaText, IHasUniques {
|
||||
override var uniques = ArrayList<String>()
|
||||
@delegate:Transient // Defense in depth against mad modders
|
||||
override val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it) } }
|
||||
|
||||
val excludedDifficulties: List<String> = listOf()
|
||||
val weight: Int = 1
|
||||
val color: String = "" // For Civilopedia
|
||||
|
@ -3,6 +3,7 @@ package com.unciv.models.ruleset.tile
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.unciv.Constants
|
||||
import com.unciv.models.ruleset.Belief
|
||||
import com.unciv.models.ruleset.IHasUniques
|
||||
import com.unciv.models.ruleset.Ruleset
|
||||
import com.unciv.models.ruleset.Unique
|
||||
import com.unciv.models.stats.NamedStats
|
||||
@ -10,7 +11,7 @@ import com.unciv.ui.civilopedia.FormattedLine
|
||||
import com.unciv.ui.civilopedia.ICivilopediaText
|
||||
import com.unciv.ui.utils.colorFromRGB
|
||||
|
||||
class Terrain : NamedStats(), ICivilopediaText {
|
||||
class Terrain : NamedStats(), ICivilopediaText, IHasUniques {
|
||||
|
||||
lateinit var type: TerrainType
|
||||
|
||||
@ -26,8 +27,8 @@ class Terrain : NamedStats(), ICivilopediaText {
|
||||
val turnsInto: String? = null
|
||||
|
||||
/** Uniques (Properties such as Temp/humidity, Fresh water, elevation, rough, defense, Natural Wonder specials) */
|
||||
val uniques = ArrayList<String>()
|
||||
val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it) } }
|
||||
override var uniques = ArrayList<String>()
|
||||
override val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it) } }
|
||||
|
||||
/** Natural Wonder weight: probability to be picked */
|
||||
var weight = 10
|
||||
|
@ -70,7 +70,6 @@ class TileImprovement : NamedStats(), ICivilopediaText, IHasUniques {
|
||||
return lines.joinToString("\n")
|
||||
}
|
||||
|
||||
fun hasUnique(unique: String) = uniques.contains(unique)
|
||||
fun isGreatImprovement() = hasUnique("Great Improvement")
|
||||
fun isRoad() = RoadStatus.values().any { it != RoadStatus.None && it.name == this.name }
|
||||
fun isAncientRuinsEquivalent() = hasUnique("Provides a random bonus when entered")
|
||||
|
@ -225,6 +225,15 @@ class BaseUnit : INamed, INonPerpetualConstruction, ICivilopediaText {
|
||||
}
|
||||
) return true
|
||||
|
||||
// May buy [unitFilter] units for [amount] [Stat] [cityFilter] at an increasing price ([amount])
|
||||
if (cityInfo != null && cityInfo.civInfo.getMatchingUniques("May buy [] units for [] [] [] at an increasing price ([])")
|
||||
.any {
|
||||
matchesFilter(it.params[0])
|
||||
&& cityInfo.matchesFilter(it.params[3])
|
||||
&& it.params[2] == stat.name
|
||||
}
|
||||
) return true
|
||||
|
||||
return super.canBePurchasedWithStat(cityInfo, stat)
|
||||
}
|
||||
|
||||
@ -237,12 +246,12 @@ class BaseUnit : INamed, INonPerpetualConstruction, ICivilopediaText {
|
||||
return (
|
||||
sequenceOf(super.getBaseBuyCost(cityInfo, stat)).filterNotNull()
|
||||
// May buy [unitFilter] units for [amount] [Stat] starting from the [eraName] at an increasing price ([amount])
|
||||
+ cityInfo.civInfo.getMatchingUniques("May buy [] units for [] [] [] starting from the [] at an increasing price ([])")
|
||||
+ (cityInfo.civInfo.getMatchingUniques("May buy [] units for [] [] [] starting from the [] at an increasing price ([])")
|
||||
.filter {
|
||||
matchesFilter(it.params[0])
|
||||
&& cityInfo.matchesFilter(it.params[3])
|
||||
&& cityInfo.civInfo.getEraNumber() >= ruleset.eras[it.params[4]]!!.eraNumber
|
||||
&& it.params[2] == stat.name
|
||||
&& cityInfo.matchesFilter(it.params[3])
|
||||
&& cityInfo.civInfo.getEraNumber() >= ruleset.eras[it.params[4]]!!.eraNumber
|
||||
&& it.params[2] == stat.name
|
||||
}.map {
|
||||
getCostForConstructionsIncreasingInPrice(
|
||||
it.params[1].toInt(),
|
||||
@ -250,6 +259,20 @@ class BaseUnit : INamed, INonPerpetualConstruction, ICivilopediaText {
|
||||
cityInfo.civInfo.boughtConstructionsWithGloballyIncreasingPrice[name] ?: 0
|
||||
)
|
||||
}
|
||||
)
|
||||
+ (cityInfo.civInfo.getMatchingUniques("May buy [] units for [] [] [] at an increasing price ([])")
|
||||
.filter {
|
||||
matchesFilter(it.params[0])
|
||||
&& cityInfo.matchesFilter(it.params[3])
|
||||
&& it.params[2] == stat.name
|
||||
}.map {
|
||||
getCostForConstructionsIncreasingInPrice(
|
||||
it.params[1].toInt(),
|
||||
it.params[4].toInt(),
|
||||
cityInfo.civInfo.boughtConstructionsWithGloballyIncreasingPrice[name] ?: 0
|
||||
)
|
||||
}
|
||||
)
|
||||
).minOrNull()
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.unciv.models.ruleset.unit
|
||||
|
||||
import com.unciv.models.ruleset.IHasUniques
|
||||
import com.unciv.models.ruleset.Unique
|
||||
import com.unciv.models.stats.INamed
|
||||
|
||||
@ -16,13 +17,13 @@ enum class UnitMovementType { // The types of tiles the unit can by default ente
|
||||
Air // Only city tiles and carrying units
|
||||
}
|
||||
|
||||
class UnitType() : INamed {
|
||||
class UnitType() : INamed, IHasUniques {
|
||||
override lateinit var name: String
|
||||
private var movementType: String? = null
|
||||
private val unitMovementType: UnitMovementType? by lazy { if (movementType == null) null else UnitMovementType.valueOf(movementType!!) }
|
||||
|
||||
val uniques: ArrayList<String> = ArrayList()
|
||||
val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it) } }
|
||||
override var uniques: ArrayList<String> = ArrayList()
|
||||
override val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it) } }
|
||||
|
||||
constructor(name: String, domain: String? = null) : this() {
|
||||
this.name = name
|
||||
|
@ -2,6 +2,7 @@
|
||||
package com.unciv.logic.map
|
||||
|
||||
import com.unciv.Constants
|
||||
import com.unciv.logic.GameInfo
|
||||
import com.unciv.logic.city.CityInfo
|
||||
import com.unciv.logic.civilization.CivilizationInfo
|
||||
import com.unciv.logic.civilization.diplomacy.DiplomacyManager
|
||||
@ -37,6 +38,8 @@ class UnitMovementAlgorithmsTests {
|
||||
name = "My nation"
|
||||
cities = arrayListOf("The Capital")
|
||||
}
|
||||
civInfo.gameInfo = GameInfo()
|
||||
civInfo.gameInfo.ruleSet = ruleSet
|
||||
unit.civInfo = civInfo
|
||||
|
||||
|
||||
@ -117,10 +120,13 @@ class UnitMovementAlgorithmsTests {
|
||||
unit.baseUnit = BaseUnit().apply { unitType = type.key; ruleset = ruleSet }
|
||||
unit.updateUniques()
|
||||
|
||||
Assert.assertTrue("$type cannot be in Ice", (
|
||||
type.value.uniques.contains("Can enter ice tiles"))
|
||||
|| type.value.uniques.contains("Can pass through impassable tiles"
|
||||
) == unit.movement.canPassThrough(tile))
|
||||
Assert.assertTrue(
|
||||
"$type cannot be in Ice",
|
||||
unit.movement.canPassThrough(tile) == (
|
||||
type.value.uniques.contains("Can enter ice tiles")
|
||||
|| type.value.uniques.contains("Can pass through impassable tiles")
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user