mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-27 05:46:43 -04:00
Allow determining *if* a unique can trigger a triggerable effect, *without* actually doing so
This commit is contained in:
parent
d51d032e18
commit
27465425b0
@ -61,6 +61,20 @@ object UniqueTriggerActivation {
|
||||
notification: String? = null,
|
||||
triggerNotificationText: String? = null
|
||||
): Boolean {
|
||||
val function = getTriggerFunction(unique, civInfo, city, unit, tile, notification, triggerNotificationText) ?: return false
|
||||
return function.invoke()
|
||||
}
|
||||
|
||||
/** @return The action to be performed if possible, else null */
|
||||
fun getTriggerFunction(
|
||||
unique: Unique,
|
||||
civInfo: Civilization,
|
||||
city: City? = null,
|
||||
unit: MapUnit? = null,
|
||||
tile: Tile? = city?.getCenterTile() ?: unit?.currentTile,
|
||||
notification: String? = null,
|
||||
triggerNotificationText: String? = null
|
||||
): (()->Boolean)? {
|
||||
|
||||
val relevantCity by lazy {
|
||||
city?: tile?.getCity()
|
||||
@ -68,11 +82,10 @@ object UniqueTriggerActivation {
|
||||
|
||||
val timingConditional = unique.conditionals.firstOrNull { it.type == UniqueType.ConditionalTimedUnique }
|
||||
if (timingConditional != null) {
|
||||
civInfo.temporaryUniques.add(TemporaryUnique(unique, timingConditional.params[0].toInt()))
|
||||
return true
|
||||
return { civInfo.temporaryUniques.add(TemporaryUnique(unique, timingConditional.params[0].toInt())) }
|
||||
}
|
||||
|
||||
if (!unique.conditionalsApply(StateForConditionals(civInfo, city, unit, tile))) return false
|
||||
if (!unique.conditionalsApply(StateForConditionals(civInfo, city, unit, tile))) return null
|
||||
|
||||
val chosenCity = relevantCity ?:
|
||||
civInfo.cities.firstOrNull { it.isCapital() }
|
||||
@ -85,16 +98,17 @@ object UniqueTriggerActivation {
|
||||
when (unique.type) {
|
||||
UniqueType.OneTimeFreeUnit -> {
|
||||
val unitName = unique.params[0]
|
||||
val baseUnit = ruleSet.units[unitName] ?: return false
|
||||
val baseUnit = ruleSet.units[unitName] ?: return null
|
||||
val civUnit = civInfo.getEquivalentUnit(baseUnit)
|
||||
if (civUnit.isCityFounder() && civInfo.isOneCityChallenger())
|
||||
return false
|
||||
return null
|
||||
|
||||
val limit = civUnit.getMatchingUniques(UniqueType.MaxNumberBuildable)
|
||||
.map { it.params[0].toInt() }.minOrNull()
|
||||
if (limit != null && limit <= civInfo.units.getCivUnits().count { it.name == civUnit.name })
|
||||
return false
|
||||
return null
|
||||
|
||||
fun placeUnit(): Boolean {
|
||||
val placedUnit = when {
|
||||
// Set unit at city if there's an explict city or if there's no tile to set at
|
||||
relevantCity != null || (tile == null && civInfo.cities.isNotEmpty()) ->
|
||||
@ -104,12 +118,14 @@ object UniqueTriggerActivation {
|
||||
// Else set unit unit near other units if we have no cities
|
||||
civInfo.units.getCivUnits().any() ->
|
||||
civInfo.units.placeUnitNearTile(civInfo.units.getCivUnits().first().currentTile.position, civUnit) ?: return false
|
||||
|
||||
else -> return false
|
||||
}
|
||||
val notificationText = getNotificationText(notification, triggerNotificationText,
|
||||
"Gained [1] [${civUnit.name}] unit(s)")
|
||||
?: return true
|
||||
|
||||
val notificationText = getNotificationText(
|
||||
notification, triggerNotificationText,
|
||||
"Gained [1] [${civUnit.name}] unit(s)"
|
||||
)
|
||||
if (notificationText != null)
|
||||
civInfo.addNotification(
|
||||
notificationText,
|
||||
MapUnitAction(placedUnit),
|
||||
@ -118,12 +134,15 @@ object UniqueTriggerActivation {
|
||||
)
|
||||
return true
|
||||
}
|
||||
return { placeUnit() }
|
||||
}
|
||||
|
||||
UniqueType.OneTimeAmountFreeUnits -> {
|
||||
val unitName = unique.params[1]
|
||||
val baseUnit = ruleSet.units[unitName] ?: return false
|
||||
val baseUnit = ruleSet.units[unitName] ?: return null
|
||||
val civUnit = civInfo.getEquivalentUnit(baseUnit)
|
||||
if (civUnit.isCityFounder() && civInfo.isOneCityChallenger())
|
||||
return false
|
||||
return null
|
||||
|
||||
val limit = civUnit.getMatchingUniques(UniqueType.MaxNumberBuildable)
|
||||
.map { it.params[0].toInt() }.minOrNull()
|
||||
@ -135,8 +154,9 @@ object UniqueTriggerActivation {
|
||||
else -> amountFromTriggerable
|
||||
}
|
||||
|
||||
if (actualAmount <= 0) return false
|
||||
if (actualAmount <= 0) return null
|
||||
|
||||
fun placeUnits():Boolean {
|
||||
val tilesUnitsWerePlacedOn: MutableList<Vector2> = mutableListOf()
|
||||
repeat(actualAmount) {
|
||||
val placedUnit = when {
|
||||
@ -148,6 +168,7 @@ object UniqueTriggerActivation {
|
||||
// Else set unit unit near other units if we have no cities
|
||||
civInfo.units.getCivUnits().any() ->
|
||||
civInfo.units.placeUnitNearTile(civInfo.units.getCivUnits().first().currentTile.position, civUnit)
|
||||
|
||||
else -> null
|
||||
}
|
||||
if (placedUnit != null)
|
||||
@ -155,10 +176,12 @@ object UniqueTriggerActivation {
|
||||
}
|
||||
if (tilesUnitsWerePlacedOn.isEmpty()) return false
|
||||
|
||||
val notificationText = getNotificationText(notification, triggerNotificationText,
|
||||
"Gained [${tilesUnitsWerePlacedOn.size}] [${civUnit.name}] unit(s)")
|
||||
?: return true
|
||||
val notificationText = getNotificationText(
|
||||
notification, triggerNotificationText,
|
||||
"Gained [${tilesUnitsWerePlacedOn.size}] [${civUnit.name}] unit(s)"
|
||||
)
|
||||
|
||||
if (notificationText != null)
|
||||
civInfo.addNotification(
|
||||
notificationText,
|
||||
MapUnitAction(tilesUnitsWerePlacedOn),
|
||||
@ -167,6 +190,8 @@ object UniqueTriggerActivation {
|
||||
)
|
||||
return true
|
||||
}
|
||||
return { placeUnits() }
|
||||
}
|
||||
UniqueType.OneTimeFreeUnitRuins -> {
|
||||
var civUnit = civInfo.getEquivalentUnit(unique.params[0])
|
||||
if ( civUnit.isCityFounder() && civInfo.isOneCityChallenger()) {
|
||||
@ -174,13 +199,14 @@ object UniqueTriggerActivation {
|
||||
.firstOrNull {
|
||||
it.getMatchingUniques(UniqueType.BuildImprovements)
|
||||
.any { unique -> unique.params[0] == "Land" }
|
||||
} ?: return false
|
||||
} ?: return null
|
||||
civUnit = civInfo.getEquivalentUnit(replacementUnit.name)
|
||||
}
|
||||
|
||||
val placingTile =
|
||||
tile ?: civInfo.cities.random().getCenterTile()
|
||||
|
||||
fun placeUnit():Boolean {
|
||||
val placedUnit = civInfo.units.placeUnitNearTile(placingTile.position, civUnit.name)
|
||||
if (notification != null && placedUnit != null) {
|
||||
val notificationText =
|
||||
@ -197,62 +223,78 @@ object UniqueTriggerActivation {
|
||||
placedUnit.name
|
||||
)
|
||||
}
|
||||
|
||||
return placedUnit != null
|
||||
}
|
||||
|
||||
return {placeUnit()}
|
||||
}
|
||||
|
||||
UniqueType.OneTimeFreePolicy -> {
|
||||
// spectators get all techs at start of game, and if (in a mod) a tech gives a free policy, the game gets stuck on the policy picker screen
|
||||
if (civInfo.isSpectator()) return false
|
||||
if (civInfo.isSpectator()) return null
|
||||
|
||||
return {
|
||||
civInfo.policies.freePolicies++
|
||||
|
||||
val notificationText = getNotificationText(notification, triggerNotificationText,
|
||||
"You may choose a free Policy")
|
||||
?: return true
|
||||
|
||||
if (notificationText != null)
|
||||
civInfo.addNotification(notificationText, NotificationCategory.General, NotificationIcon.Culture)
|
||||
return true
|
||||
true
|
||||
}
|
||||
}
|
||||
UniqueType.OneTimeAmountFreePolicies -> {
|
||||
if (civInfo.isSpectator()) return false
|
||||
if (civInfo.isSpectator()) return null
|
||||
val newFreePolicies = unique.params[0].toInt()
|
||||
|
||||
return {
|
||||
civInfo.policies.freePolicies += newFreePolicies
|
||||
|
||||
val notificationText = getNotificationText(notification, triggerNotificationText,
|
||||
"You may choose [$newFreePolicies] free Policies")
|
||||
?: return true
|
||||
|
||||
val notificationText = getNotificationText(
|
||||
notification, triggerNotificationText,
|
||||
"You may choose [$newFreePolicies] free Policies"
|
||||
)
|
||||
if (notificationText != null)
|
||||
civInfo.addNotification(notificationText, NotificationCategory.General, NotificationIcon.Culture)
|
||||
return true
|
||||
true
|
||||
}
|
||||
}
|
||||
UniqueType.OneTimeAdoptPolicy -> {
|
||||
val policyName = unique.params[0]
|
||||
if (civInfo.policies.isAdopted(policyName)) return false
|
||||
val policy = civInfo.gameInfo.ruleset.policies[policyName] ?: return false
|
||||
if (civInfo.policies.isAdopted(policyName)) return null
|
||||
val policy = civInfo.gameInfo.ruleset.policies[policyName] ?: return null
|
||||
|
||||
return {
|
||||
civInfo.policies.freePolicies++
|
||||
civInfo.policies.adopt(policy)
|
||||
|
||||
val notificationText = getNotificationText(notification, triggerNotificationText,
|
||||
"You gain the [$policyName] Policy")
|
||||
?: return true
|
||||
|
||||
val notificationText = getNotificationText(
|
||||
notification, triggerNotificationText,
|
||||
"You gain the [$policyName] Policy"
|
||||
)
|
||||
if (notificationText != null)
|
||||
civInfo.addNotification(notificationText, PolicyAction(policyName), NotificationCategory.General, NotificationIcon.Culture)
|
||||
return true
|
||||
true
|
||||
}
|
||||
}
|
||||
UniqueType.OneTimeEnterGoldenAge, UniqueType.OneTimeEnterGoldenAgeTurns -> {
|
||||
return {
|
||||
if (unique.type == UniqueType.OneTimeEnterGoldenAgeTurns) civInfo.goldenAges.enterGoldenAge(unique.params[0].toInt())
|
||||
else civInfo.goldenAges.enterGoldenAge()
|
||||
|
||||
val notificationText = getNotificationText(notification, triggerNotificationText,
|
||||
"You enter a Golden Age")
|
||||
?: return true
|
||||
|
||||
val notificationText = getNotificationText(
|
||||
notification, triggerNotificationText,
|
||||
"You enter a Golden Age"
|
||||
)
|
||||
if (notificationText != null)
|
||||
civInfo.addNotification(notificationText, NotificationCategory.General, NotificationIcon.Happiness)
|
||||
return true
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
UniqueType.OneTimeFreeGreatPerson -> {
|
||||
if (civInfo.isSpectator()) return false
|
||||
if (civInfo.isSpectator()) return null
|
||||
return {
|
||||
civInfo.greatPeople.freeGreatPeople++
|
||||
// Anyone an idea for a good icon?
|
||||
if (notification != null)
|
||||
@ -261,28 +303,32 @@ object UniqueTriggerActivation {
|
||||
if (civInfo.isAI() || UncivGame.Current.settings.autoPlay.isAutoPlayingAndFullAI()) {
|
||||
NextTurnAutomation.chooseGreatPerson(civInfo)
|
||||
}
|
||||
|
||||
return true
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
UniqueType.OneTimeGainPopulation -> {
|
||||
val applicableCities =
|
||||
if (unique.params[1] == "in this city") sequenceOf(relevantCity!!)
|
||||
else civInfo.cities.asSequence().filter { it.matchesFilter(unique.params[1]) }
|
||||
if (applicableCities.none()) return null
|
||||
return {
|
||||
for (applicableCity in applicableCities) {
|
||||
applicableCity.population.addPopulation(unique.params[0].toInt())
|
||||
}
|
||||
if (notification != null && applicableCities.any())
|
||||
if (notification != null)
|
||||
civInfo.addNotification(
|
||||
notification,
|
||||
LocationAction(applicableCities.map { it.location }),
|
||||
NotificationCategory.Cities,
|
||||
NotificationIcon.Population
|
||||
)
|
||||
return applicableCities.any()
|
||||
true
|
||||
}
|
||||
}
|
||||
UniqueType.OneTimeGainPopulationRandomCity -> {
|
||||
if (civInfo.cities.isEmpty()) return false
|
||||
if (civInfo.cities.isEmpty()) return null
|
||||
return {
|
||||
val randomCity = civInfo.cities.random(tileBasedRandom)
|
||||
randomCity.population.addPopulation(unique.params[0].toInt())
|
||||
if (notification != null) {
|
||||
@ -297,24 +343,27 @@ object UniqueTriggerActivation {
|
||||
NotificationIcon.Population
|
||||
)
|
||||
}
|
||||
return true
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
UniqueType.OneTimeFreeTech -> {
|
||||
if (civInfo.isSpectator()) return false
|
||||
if (civInfo.isSpectator()) return null
|
||||
return {
|
||||
civInfo.tech.freeTechs += 1
|
||||
if (notification != null) {
|
||||
if (notification != null)
|
||||
civInfo.addNotification(notification, NotificationCategory.General, NotificationIcon.Science)
|
||||
true
|
||||
}
|
||||
return true
|
||||
}
|
||||
UniqueType.OneTimeAmountFreeTechs -> {
|
||||
if (civInfo.isSpectator()) return false
|
||||
if (civInfo.isSpectator()) return null
|
||||
return {
|
||||
civInfo.tech.freeTechs += unique.params[0].toInt()
|
||||
if (notification != null) {
|
||||
if (notification != null)
|
||||
civInfo.addNotification(notification, NotificationCategory.General, NotificationIcon.Science)
|
||||
true
|
||||
}
|
||||
return true
|
||||
}
|
||||
UniqueType.OneTimeFreeTechRuins -> {
|
||||
val researchableTechsFromThatEra = ruleSet.technologies.values
|
||||
@ -322,8 +371,9 @@ object UniqueTriggerActivation {
|
||||
(it.column!!.era == unique.params[1] || unique.params[1] == "any era")
|
||||
&& civInfo.tech.canBeResearched(it.name)
|
||||
}
|
||||
if (researchableTechsFromThatEra.isEmpty()) return false
|
||||
if (researchableTechsFromThatEra.isEmpty()) return null
|
||||
|
||||
return {
|
||||
val techsToResearch = researchableTechsFromThatEra.shuffled(tileBasedRandom)
|
||||
.take(unique.params[0].toInt())
|
||||
for (tech in techsToResearch)
|
||||
@ -339,93 +389,110 @@ object UniqueTriggerActivation {
|
||||
// Relies on RulesetValidator catching <= 0!
|
||||
val notificationActions: Sequence<NotificationAction> =
|
||||
LocationAction(tile?.position) + TechAction(techsToResearch.first().name)
|
||||
civInfo.addNotification(notificationText, notificationActions,
|
||||
NotificationCategory.General, NotificationIcon.Science)
|
||||
civInfo.addNotification(
|
||||
notificationText, notificationActions,
|
||||
NotificationCategory.General, NotificationIcon.Science
|
||||
)
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
UniqueType.OneTimeDiscoverTech -> {
|
||||
val techName = unique.params[0]
|
||||
if (civInfo.tech.isResearched(techName)) return false
|
||||
if (civInfo.tech.isResearched(techName)) return null
|
||||
|
||||
return {
|
||||
civInfo.tech.addTechnology(techName)
|
||||
|
||||
val notificationText = getNotificationText(notification, triggerNotificationText,
|
||||
"You have discovered the secrets of [$techName]")
|
||||
?: return true
|
||||
|
||||
val notificationText = getNotificationText(
|
||||
notification, triggerNotificationText,
|
||||
"You have discovered the secrets of [$techName]"
|
||||
)
|
||||
if (notificationText != null)
|
||||
civInfo.addNotification(notificationText, TechAction(techName), NotificationCategory.General, NotificationIcon.Science)
|
||||
return true
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
UniqueType.StrategicResourcesIncrease -> {
|
||||
return {
|
||||
civInfo.cache.updateCivResources()
|
||||
if (notification != null) {
|
||||
if (notification != null)
|
||||
civInfo.addNotification(
|
||||
notification,
|
||||
NotificationCategory.General,
|
||||
NotificationIcon.Construction
|
||||
)
|
||||
true
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
UniqueType.OneTimeProvideResources -> {
|
||||
val resourceName = unique.params[1]
|
||||
val resource = ruleSet.tileResources[resourceName] ?: return false
|
||||
if (!resource.isStockpiled()) return false
|
||||
val resource = ruleSet.tileResources[resourceName] ?: return null
|
||||
if (!resource.isStockpiled()) return null
|
||||
|
||||
return {
|
||||
val amount = unique.params[0].toInt()
|
||||
civInfo.resourceStockpiles.add(resourceName, amount)
|
||||
|
||||
val notificationText = getNotificationText(notification, triggerNotificationText,
|
||||
"You have gained [$amount] [$resourceName]")
|
||||
?: return true
|
||||
|
||||
val notificationText = getNotificationText(
|
||||
notification, triggerNotificationText,
|
||||
"You have gained [$amount] [$resourceName]"
|
||||
)
|
||||
if (notificationText != null)
|
||||
civInfo.addNotification(notificationText, NotificationCategory.General, NotificationIcon.Science, "ResourceIcons/$resourceName")
|
||||
return true
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
UniqueType.OneTimeConsumeResources -> {
|
||||
val resourceName = unique.params[1]
|
||||
val resource = ruleSet.tileResources[resourceName] ?: return false
|
||||
if (!resource.isStockpiled()) return false
|
||||
val resource = ruleSet.tileResources[resourceName] ?: return null
|
||||
if (!resource.isStockpiled()) return null
|
||||
|
||||
return {
|
||||
val amount = unique.params[0].toInt()
|
||||
civInfo.resourceStockpiles.add(resourceName, -amount)
|
||||
|
||||
val notificationText = getNotificationText(notification, triggerNotificationText,
|
||||
"You have lost [$amount] [$resourceName]")
|
||||
?: return true
|
||||
|
||||
val notificationText = getNotificationText(
|
||||
notification, triggerNotificationText,
|
||||
"You have lost [$amount] [$resourceName]"
|
||||
)
|
||||
if (notificationText != null)
|
||||
civInfo.addNotification(notificationText, NotificationCategory.General, NotificationIcon.Science, "ResourceIcons/$resourceName")
|
||||
return true
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
UniqueType.OneTimeRevealEntireMap -> {
|
||||
return {
|
||||
if (notification != null) {
|
||||
civInfo.addNotification(notification, LocationAction(tile?.position), NotificationCategory.General, NotificationIcon.Scout)
|
||||
}
|
||||
civInfo.gameInfo.tileMap.values.asSequence()
|
||||
.forEach { it.setExplored(civInfo, true) }
|
||||
return true
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
UniqueType.UnitsGainPromotion -> {
|
||||
val filter = unique.params[0]
|
||||
val promotion = unique.params[1]
|
||||
|
||||
val promotedUnitLocations: MutableList<Vector2> = mutableListOf()
|
||||
for (civUnit in civInfo.units.getCivUnits()) {
|
||||
if (civUnit.matchesFilter(filter)
|
||||
&& ruleSet.unitPromotions.values.any {
|
||||
it.name == promotion && civUnit.type.name in it.unitTypes
|
||||
val unitsToPromote = civInfo.units.getCivUnits().filter { it.matchesFilter(filter) }
|
||||
.filter { unitToPromote ->
|
||||
ruleSet.unitPromotions.values.any {
|
||||
it.name == promotion && unitToPromote.type.name in it.unitTypes
|
||||
}
|
||||
) {
|
||||
}.toList()
|
||||
if (unitsToPromote.isEmpty()) return null
|
||||
|
||||
return {
|
||||
val promotedUnitLocations: MutableList<Vector2> = mutableListOf()
|
||||
for (civUnit in unitsToPromote) {
|
||||
civUnit.promotions.addPromotion(promotion, isFree = true)
|
||||
promotedUnitLocations.add(civUnit.getTile().position)
|
||||
}
|
||||
}
|
||||
|
||||
if (notification != null) {
|
||||
civInfo.addNotification(
|
||||
@ -435,7 +502,8 @@ object UniqueTriggerActivation {
|
||||
"unitPromotionIcons/${unique.params[1]}"
|
||||
)
|
||||
}
|
||||
return promotedUnitLocations.isNotEmpty()
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -454,93 +522,106 @@ object UniqueTriggerActivation {
|
||||
* I could parametrize the 'Allied' of the Unique text, but eh.
|
||||
*/
|
||||
UniqueType.CityStateCanGiftGreatPeople -> {
|
||||
return {
|
||||
civInfo.addFlag(
|
||||
CivFlags.CityStateGreatPersonGift.name,
|
||||
civInfo.cityStateFunctions.turnsForGreatPersonFromCityState() / 2
|
||||
)
|
||||
if (notification != null) {
|
||||
if (notification != null)
|
||||
civInfo.addNotification(notification, NotificationCategory.Diplomacy, NotificationIcon.CityState)
|
||||
true
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
UniqueType.OneTimeGainStat -> {
|
||||
val stat = Stat.safeValueOf(unique.params[1]) ?: return false
|
||||
val stat = Stat.safeValueOf(unique.params[1]) ?: return null
|
||||
|
||||
if (stat !in Stat.statsWithCivWideField
|
||||
|| unique.params[0].toIntOrNull() == null
|
||||
) return false
|
||||
) return null
|
||||
|
||||
return {
|
||||
val statAmount = unique.params[0].toInt()
|
||||
val stats = Stats().add(stat, statAmount.toFloat())
|
||||
civInfo.addStats(stats)
|
||||
|
||||
val filledNotification = if(notification!=null && notification.hasPlaceholderParameters())
|
||||
val filledNotification = if (notification != null && notification.hasPlaceholderParameters())
|
||||
notification.fillPlaceholders(statAmount.toString())
|
||||
else notification
|
||||
|
||||
val notificationText = getNotificationText(filledNotification, triggerNotificationText,
|
||||
"Gained [${stats.toStringForNotifications()}]")
|
||||
?: return true
|
||||
|
||||
val notificationText = getNotificationText(
|
||||
filledNotification, triggerNotificationText,
|
||||
"Gained [${stats.toStringForNotifications()}]"
|
||||
)
|
||||
if (notificationText != null)
|
||||
civInfo.addNotification(notificationText, LocationAction(tile?.position), NotificationCategory.General, stat.notificationIcon)
|
||||
return true
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
UniqueType.OneTimeGainStatSpeed -> {
|
||||
val stat = Stat.safeValueOf(unique.params[1]) ?: return false
|
||||
val stat = Stat.safeValueOf(unique.params[1]) ?: return null
|
||||
|
||||
if (stat !in Stat.statsWithCivWideField
|
||||
|| unique.params[0].toIntOrNull() == null
|
||||
) return false
|
||||
) return null
|
||||
|
||||
return {
|
||||
val statAmount = (unique.params[0].toInt() * (civInfo.gameInfo.speed.statCostModifiers[stat]!!)).roundToInt()
|
||||
val stats = Stats().add(stat, statAmount.toFloat())
|
||||
civInfo.addStats(stats)
|
||||
|
||||
val filledNotification = if(notification!=null && notification.hasPlaceholderParameters())
|
||||
val filledNotification = if (notification != null && notification.hasPlaceholderParameters())
|
||||
notification.fillPlaceholders(statAmount.toString())
|
||||
else notification
|
||||
|
||||
val notificationText = getNotificationText(filledNotification, triggerNotificationText,
|
||||
"Gained [${stats.toStringForNotifications()}]")
|
||||
?: return true
|
||||
val notificationText = getNotificationText(
|
||||
filledNotification, triggerNotificationText,
|
||||
"Gained [${stats.toStringForNotifications()}]"
|
||||
)
|
||||
|
||||
if (notificationText != null)
|
||||
civInfo.addNotification(notificationText, LocationAction(tile?.position), NotificationCategory.General, stat.notificationIcon)
|
||||
return true
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
UniqueType.OneTimeGainStatRange -> {
|
||||
val stat = Stat.safeValueOf(unique.params[2]) ?: return false
|
||||
val stat = Stat.safeValueOf(unique.params[2]) ?: return null
|
||||
|
||||
if (stat !in Stat.statsWithCivWideField
|
||||
|| unique.params[0].toIntOrNull() == null
|
||||
|| unique.params[1].toIntOrNull() == null
|
||||
) return false
|
||||
) return null
|
||||
|
||||
|
||||
val finalStatAmount = (tileBasedRandom.nextInt(unique.params[0].toInt(), unique.params[1].toInt()) *
|
||||
civInfo.gameInfo.speed.statCostModifiers[stat]!!).roundToInt()
|
||||
|
||||
return {
|
||||
val stats = Stats().add(stat, finalStatAmount.toFloat())
|
||||
civInfo.addStats(stats)
|
||||
|
||||
val filledNotification = if (notification!=null && notification.hasPlaceholderParameters())
|
||||
val filledNotification = if (notification != null && notification.hasPlaceholderParameters())
|
||||
notification.fillPlaceholders(finalStatAmount.toString())
|
||||
else notification
|
||||
|
||||
val notificationText = getNotificationText(filledNotification, triggerNotificationText,
|
||||
"Gained [${stats.toStringForNotifications()}]")
|
||||
?: return true
|
||||
val notificationText = getNotificationText(
|
||||
filledNotification, triggerNotificationText,
|
||||
"Gained [${stats.toStringForNotifications()}]"
|
||||
)
|
||||
|
||||
if (notificationText != null)
|
||||
civInfo.addNotification(notificationText, LocationAction(tile?.position), NotificationCategory.General, stat.notificationIcon)
|
||||
|
||||
return true
|
||||
true
|
||||
}
|
||||
}
|
||||
UniqueType.OneTimeGainPantheon -> {
|
||||
if (civInfo.religionManager.religionState != ReligionState.None) return false
|
||||
if (civInfo.religionManager.religionState != ReligionState.None) return null
|
||||
val gainedFaith = civInfo.religionManager.faithForPantheon(2)
|
||||
if (gainedFaith == 0) return false
|
||||
if (gainedFaith == 0) return null
|
||||
|
||||
return {
|
||||
civInfo.addStat(Stat.Faith, gainedFaith)
|
||||
|
||||
if (notification != null) {
|
||||
@ -550,15 +631,16 @@ object UniqueTriggerActivation {
|
||||
else notification
|
||||
civInfo.addNotification(notificationText, LocationAction(tile?.position), NotificationCategory.Religion, NotificationIcon.Faith)
|
||||
}
|
||||
|
||||
return true
|
||||
true
|
||||
}
|
||||
}
|
||||
UniqueType.OneTimeGainProphet -> {
|
||||
if (civInfo.religionManager.getGreatProphetEquivalent() == null) return false
|
||||
if (civInfo.religionManager.getGreatProphetEquivalent() == null) return null
|
||||
val gainedFaith =
|
||||
(civInfo.religionManager.faithForNextGreatProphet() * (unique.params[0].toFloat() / 100f)).toInt()
|
||||
if (gainedFaith == 0) return false
|
||||
if (gainedFaith == 0) return null
|
||||
|
||||
return {
|
||||
civInfo.addStat(Stat.Faith, gainedFaith)
|
||||
|
||||
if (notification != null) {
|
||||
@ -568,30 +650,30 @@ object UniqueTriggerActivation {
|
||||
else notification
|
||||
civInfo.addNotification(notificationText, LocationAction(tile?.position), NotificationCategory.Religion, NotificationIcon.Faith)
|
||||
}
|
||||
|
||||
return true
|
||||
true
|
||||
}
|
||||
}
|
||||
UniqueType.OneTimeFreeBelief -> {
|
||||
if (!civInfo.isMajorCiv()) return false
|
||||
if (!civInfo.isMajorCiv()) return null
|
||||
val beliefType = BeliefType.valueOf(unique.params[0])
|
||||
val religionManager = civInfo.religionManager
|
||||
if ((beliefType != BeliefType.Pantheon && beliefType != BeliefType.Any)
|
||||
&& religionManager.religionState <= ReligionState.Pantheon)
|
||||
return false // situation where we're trying to add a formal religion belief to a civ that hasn't founded a religion
|
||||
return null // situation where we're trying to add a formal religion belief to a civ that hasn't founded a religion
|
||||
if (religionManager.numberOfBeliefsAvailable(beliefType) == 0)
|
||||
return false // no more available beliefs of this type
|
||||
return null // no more available beliefs of this type
|
||||
|
||||
return {
|
||||
if (beliefType == BeliefType.Any && religionManager.religionState <= ReligionState.Pantheon)
|
||||
religionManager.freeBeliefs.add(BeliefType.Pantheon.name, 1) // add pantheon instead of any type
|
||||
else
|
||||
religionManager.freeBeliefs.add(beliefType.name, 1)
|
||||
return true
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
UniqueType.OneTimeRevealSpecificMapTiles -> {
|
||||
|
||||
if (tile == null)
|
||||
return false
|
||||
if (tile == null) return null
|
||||
|
||||
// "Reveal up to [amount/'all'] [tileFilter] within a [amount] tile radius"
|
||||
val amount = unique.params[0]
|
||||
@ -605,13 +687,14 @@ object UniqueTriggerActivation {
|
||||
.filter { !it.isExplored(civInfo) && it.matchesFilter(filter) }
|
||||
|
||||
if (explorableTiles.none())
|
||||
return false
|
||||
return null
|
||||
|
||||
if (!isAll) {
|
||||
explorableTiles.shuffled(tileBasedRandom)
|
||||
explorableTiles = explorableTiles.take(amount.toInt())
|
||||
}
|
||||
|
||||
return {
|
||||
for (explorableTile in explorableTiles) {
|
||||
explorableTile.setExplored(civInfo, true)
|
||||
positions += explorableTile.position
|
||||
@ -630,16 +713,14 @@ object UniqueTriggerActivation {
|
||||
NotificationIcon.Barbarians else NotificationIcon.Scout
|
||||
)
|
||||
}
|
||||
|
||||
return true
|
||||
true
|
||||
}
|
||||
}
|
||||
UniqueType.OneTimeRevealCrudeMap -> {
|
||||
if (tile == null)
|
||||
return false
|
||||
if (tile == null) return null
|
||||
|
||||
// "From a randomly chosen tile [amount] tiles away from the ruins,
|
||||
// reveal tiles up to [amount] tiles away with [amount]% chance"
|
||||
|
||||
val distance = unique.params[0].toInt()
|
||||
val radius = unique.params[1].toInt()
|
||||
val chance = unique.params[2].toFloat() / 100f
|
||||
@ -648,7 +729,9 @@ object UniqueTriggerActivation {
|
||||
.filter { !it.isExplored(civInfo) }
|
||||
.toList()
|
||||
.randomOrNull(tileBasedRandom)
|
||||
?: return false
|
||||
?: return null
|
||||
|
||||
return {
|
||||
revealCenter.getTilesInDistance(radius)
|
||||
.filter { tileBasedRandom.nextFloat() < chance }
|
||||
.forEach { it.setExplored(civInfo, true) }
|
||||
@ -660,10 +743,12 @@ object UniqueTriggerActivation {
|
||||
NotificationCategory.General,
|
||||
NotificationIcon.Ruins
|
||||
)
|
||||
return true
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
UniqueType.OneTimeTriggerVoting -> {
|
||||
return {
|
||||
for (civ in civInfo.gameInfo.civilizations)
|
||||
if (!civ.isBarbarian() && !civ.isSpectator())
|
||||
civ.addFlag(
|
||||
@ -672,12 +757,15 @@ object UniqueTriggerActivation {
|
||||
)
|
||||
if (notification != null)
|
||||
civInfo.addNotification(notification, NotificationCategory.General, NotificationIcon.Diplomacy)
|
||||
return true
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
UniqueType.OneTimeGlobalSpiesWhenEnteringEra -> {
|
||||
if (!civInfo.isMajorCiv()) return false
|
||||
if (!civInfo.gameInfo.isEspionageEnabled()) return false
|
||||
if (!civInfo.isMajorCiv()) return null
|
||||
if (!civInfo.gameInfo.isEspionageEnabled()) return null
|
||||
|
||||
return {
|
||||
val currentEra = civInfo.getEra().name
|
||||
for (otherCiv in civInfo.gameInfo.getAliveMajorCivs()) {
|
||||
if (currentEra !in otherCiv.espionageManager.erasSpyEarnedFor) {
|
||||
@ -687,10 +775,15 @@ object UniqueTriggerActivation {
|
||||
// We don't tell which civilization entered the new era, as that is done in the notification directly above this one
|
||||
otherCiv.addNotification("We have recruited [${spyName}] as a spy!", NotificationCategory.Espionage, NotificationIcon.Spy)
|
||||
else
|
||||
otherCiv.addNotification("After an unknown civilization entered the [${currentEra}], we have recruited [${spyName}] as a spy!", NotificationCategory.Espionage, NotificationIcon.Spy)
|
||||
otherCiv.addNotification(
|
||||
"After an unknown civilization entered the [${currentEra}], we have recruited [${spyName}] as a spy!",
|
||||
NotificationCategory.Espionage,
|
||||
NotificationIcon.Spy
|
||||
)
|
||||
}
|
||||
}
|
||||
return true
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
UniqueType.GainFreeBuildings -> {
|
||||
@ -698,119 +791,144 @@ object UniqueTriggerActivation {
|
||||
val applicableCities =
|
||||
if (unique.params[1] == "in this city") sequenceOf(relevantCity!!)
|
||||
else civInfo.cities.asSequence().filter { it.matchesFilter(unique.params[1]) }
|
||||
if (applicableCities.none()) return null
|
||||
|
||||
return {
|
||||
for (applicableCity in applicableCities) {
|
||||
applicableCity.cityConstructions.freeBuildingsProvidedFromThisCity.addToMapOfSets(applicableCity.id, freeBuilding.name)
|
||||
|
||||
if (applicableCity.cityConstructions.containsBuildingOrEquivalent(freeBuilding.name)) continue
|
||||
applicableCity.cityConstructions.constructionComplete(freeBuilding)
|
||||
}
|
||||
return true
|
||||
true
|
||||
}
|
||||
}
|
||||
UniqueType.FreeStatBuildings -> {
|
||||
val stat = Stat.safeValueOf(unique.params[0]) ?: return false
|
||||
val stat = Stat.safeValueOf(unique.params[0]) ?: return null
|
||||
return {
|
||||
civInfo.civConstructions.addFreeStatBuildings(stat, unique.params[1].toInt())
|
||||
return true
|
||||
true
|
||||
}
|
||||
}
|
||||
UniqueType.FreeSpecificBuildings ->{
|
||||
val building = ruleSet.buildings[unique.params[0]] ?: return false
|
||||
val building = ruleSet.buildings[unique.params[0]] ?: return null
|
||||
return {
|
||||
civInfo.civConstructions.addFreeBuildings(building, unique.params[1].toInt())
|
||||
return true
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
UniqueType.RemoveBuilding -> {
|
||||
val applicableCities =
|
||||
if (unique.params[1] == "in this city") sequenceOf(relevantCity!!)
|
||||
else civInfo.cities.asSequence().filter { it.matchesFilter(unique.params[1]) }
|
||||
if (applicableCities.none()) return null
|
||||
|
||||
return {
|
||||
for (applicableCity in applicableCities) {
|
||||
val buildingsToRemove = applicableCity.cityConstructions.getBuiltBuildings().filter {
|
||||
it.matchesFilter(unique.params[0])
|
||||
}.toSet()
|
||||
applicableCity.cityConstructions.removeBuildings(buildingsToRemove)
|
||||
}
|
||||
|
||||
return true
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
UniqueType.SellBuilding -> {
|
||||
val applicableCities =
|
||||
if (unique.params[1] == "in this city") sequenceOf(relevantCity!!)
|
||||
else civInfo.cities.asSequence().filter { it.matchesFilter(unique.params[1]) }
|
||||
if (applicableCities.none()) return null
|
||||
|
||||
return {
|
||||
for (applicableCity in applicableCities) {
|
||||
val buildingsToSell = applicableCity.cityConstructions.getBuiltBuildings().filter {
|
||||
it.matchesFilter(unique.params[0]) && it.isSellable()
|
||||
}
|
||||
|
||||
for (building in buildingsToSell) {
|
||||
applicableCity.sellBuilding(building)
|
||||
for (building in buildingsToSell) applicableCity.sellBuilding(building)
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
UniqueType.OneTimeUnitHeal -> {
|
||||
if (unit == null) return false
|
||||
if (unit == null) return null
|
||||
if (unit.health == 100)
|
||||
return {
|
||||
unit.healBy(unique.params[0].toInt())
|
||||
if (notification != null)
|
||||
unit.civ.addNotification(notification, unit.getTile().position, NotificationCategory.Units) // Do we have a heal icon?
|
||||
return true
|
||||
true
|
||||
}
|
||||
}
|
||||
UniqueType.OneTimeUnitDamage -> {
|
||||
if (unit == null) return false
|
||||
if (unit == null) return null
|
||||
return {
|
||||
MapUnitCombatant(unit).takeDamage(unique.params[0].toInt())
|
||||
if (notification != null)
|
||||
unit.civ.addNotification(notification, unit.getTile().position, NotificationCategory.Units) // Do we have a heal icon?
|
||||
return true
|
||||
true
|
||||
}
|
||||
}
|
||||
UniqueType.OneTimeUnitGainXP -> {
|
||||
if (unit == null) return false
|
||||
if (!unit.baseUnit.isMilitary()) return false
|
||||
if (unit == null) return null
|
||||
if (!unit.baseUnit.isMilitary()) return null
|
||||
return {
|
||||
unit.promotions.XP += unique.params[0].toInt()
|
||||
if (notification != null)
|
||||
unit.civ.addNotification(notification, unit.getTile().position, NotificationCategory.Units)
|
||||
return true
|
||||
true
|
||||
}
|
||||
}
|
||||
UniqueType.OneTimeUnitUpgrade -> {
|
||||
if (unit == null) return false
|
||||
if (unit == null) return null
|
||||
val upgradeAction = UnitActionsUpgrade.getFreeUpgradeAction(unit)
|
||||
if (upgradeAction.none()) return false
|
||||
if (upgradeAction.none()) return null
|
||||
return {
|
||||
(upgradeAction.minBy { (it as UpgradeUnitAction).unitToUpgradeTo.cost }).action!!()
|
||||
if (notification != null)
|
||||
unit.civ.addNotification(notification, unit.getTile().position, NotificationCategory.Units)
|
||||
return true
|
||||
true
|
||||
}
|
||||
}
|
||||
UniqueType.OneTimeUnitSpecialUpgrade -> {
|
||||
if (unit == null) return false
|
||||
if (unit == null) return null
|
||||
val upgradeAction = UnitActionsUpgrade.getAncientRuinsUpgradeAction(unit)
|
||||
if (upgradeAction.none()) return false
|
||||
if (upgradeAction.none()) return null
|
||||
return {
|
||||
(upgradeAction.minBy { (it as UpgradeUnitAction).unitToUpgradeTo.cost }).action!!()
|
||||
if (notification != null)
|
||||
unit.civ.addNotification(notification, unit.getTile().position, NotificationCategory.Units)
|
||||
return true
|
||||
true
|
||||
}
|
||||
}
|
||||
UniqueType.OneTimeUnitGainPromotion -> {
|
||||
if (unit == null) return false
|
||||
if (unit == null) return null
|
||||
val promotion = unit.civ.gameInfo.ruleset.unitPromotions.keys
|
||||
.firstOrNull { it == unique.params[0] }
|
||||
?: return false
|
||||
?: return null
|
||||
return {
|
||||
unit.promotions.addPromotion(promotion, true)
|
||||
if (notification != null)
|
||||
unit.civ.addNotification(notification, unit.getTile().position, NotificationCategory.Units, unit.name)
|
||||
return true
|
||||
true
|
||||
}
|
||||
}
|
||||
UniqueType.OneTimeUnitRemovePromotion -> {
|
||||
if (unit == null) return false
|
||||
if (unit == null) return null
|
||||
val promotion = unit.civ.gameInfo.ruleset.unitPromotions.keys
|
||||
.firstOrNull { it == unique.params[0]}
|
||||
?: return false
|
||||
?: return null
|
||||
return {
|
||||
unit.promotions.removePromotion(promotion)
|
||||
return true
|
||||
true
|
||||
}
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
return false
|
||||
return null
|
||||
}
|
||||
|
||||
private fun getNotificationText(notification: String?, triggerNotificationText: String?, effectNotificationText: String): String? {
|
||||
|
Loading…
x
Reference in New Issue
Block a user