mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-24 03:53:12 -04:00
Notifications for triggered uniques
This commit is contained in:
parent
7382da5bdf
commit
587b1f40f1
@ -907,6 +907,21 @@ A Great Person joins you! =
|
||||
An unknown civilization has liberated [civ] =
|
||||
|
||||
|
||||
## Trigger effects
|
||||
|
||||
Gained [amount] [unitName] unit(s) =
|
||||
You may choose a free Policy =
|
||||
You may choose [amount] free Policies =
|
||||
You enter a Golden Age =
|
||||
|
||||
## Trigger causes
|
||||
|
||||
due to researching [tech] =
|
||||
due to adopting [policy] =
|
||||
due to discovering [naturalWonder] =
|
||||
due to entering the [eraName] =
|
||||
due to constructing [buildingName] =
|
||||
|
||||
# World Screen UI
|
||||
|
||||
Working... =
|
||||
|
@ -201,13 +201,14 @@ class PolicyManager : IsPartOfGameInfoSerialization {
|
||||
triggerGlobalAlerts(policy, unique.params[0])
|
||||
}
|
||||
|
||||
val triggerNotificationText = "due to adopting [${policy.name}]"
|
||||
for (unique in policy.uniqueObjects)
|
||||
if (unique.conditionals.none { it.type!!.targetTypes.contains(UniqueTarget.TriggerCondition) })
|
||||
UniqueTriggerActivation.triggerCivwideUnique(unique, civInfo)
|
||||
UniqueTriggerActivation.triggerCivwideUnique(unique, civInfo, triggerNotificationText = triggerNotificationText)
|
||||
|
||||
for (unique in civInfo.getTriggeredUniques(UniqueType.TriggerUponAdoptingPolicy))
|
||||
if (unique.conditionals.any {it.type == UniqueType.TriggerUponAdoptingPolicy && it.params[0] == policy.name})
|
||||
UniqueTriggerActivation.triggerCivwideUnique(unique, civInfo)
|
||||
UniqueTriggerActivation.triggerCivwideUnique(unique, civInfo, triggerNotificationText = triggerNotificationText)
|
||||
|
||||
// This ALSO has the side-effect of updating the CivInfo statForNextTurn so we don't need to call it explicitly
|
||||
for (cityInfo in civInfo.cities) cityInfo.cityStats.update()
|
||||
|
@ -258,13 +258,15 @@ class TechManager : IsPartOfGameInfoSerialization {
|
||||
repeatingTechsResearched++
|
||||
researchedTechnologies = researchedTechnologies.withItem(newTech)
|
||||
addTechToTransients(newTech)
|
||||
|
||||
val triggerNotificationText = "due to researching [$techName]"
|
||||
for (unique in newTech.uniqueObjects)
|
||||
if (unique.conditionals.none { it.type!!.targetTypes.contains(UniqueTarget.TriggerCondition) })
|
||||
UniqueTriggerActivation.triggerCivwideUnique(unique, civInfo)
|
||||
UniqueTriggerActivation.triggerCivwideUnique(unique, civInfo, triggerNotificationText = triggerNotificationText)
|
||||
|
||||
for (unique in civInfo.getTriggeredUniques(UniqueType.TriggerUponResearch))
|
||||
if (unique.conditionals.any {it.type == UniqueType.TriggerUponResearch && it.params[0] == techName})
|
||||
UniqueTriggerActivation.triggerCivwideUnique(unique, civInfo)
|
||||
UniqueTriggerActivation.triggerCivwideUnique(unique, civInfo, triggerNotificationText = triggerNotificationText)
|
||||
|
||||
|
||||
updateTransientBooleans()
|
||||
@ -284,11 +286,29 @@ class TechManager : IsPartOfGameInfoSerialization {
|
||||
}
|
||||
}
|
||||
|
||||
val obsoleteUnits = getRuleset().units.values.filter { it.obsoleteTech == techName }.map { it.name }
|
||||
obsoleteOldUnits(techName)
|
||||
|
||||
for (unique in civInfo.getMatchingUniques(UniqueType.ReceiveFreeUnitWhenDiscoveringTech)) {
|
||||
if (unique.params[1] != techName) continue
|
||||
civInfo.units.addUnit(unique.params[0])
|
||||
}
|
||||
for (unique in civInfo.getMatchingUniques(UniqueType.MayanGainGreatPerson)) {
|
||||
if (unique.params[1] != techName) continue
|
||||
civInfo.addNotification("You have unlocked [The Long Count]!",
|
||||
MayaLongCountAction(), NotificationCategory.General, MayaCalendar.notificationIcon)
|
||||
}
|
||||
|
||||
moveToNewEra()
|
||||
}
|
||||
|
||||
private fun obsoleteOldUnits(techName: String) {
|
||||
val obsoleteUnits =
|
||||
getRuleset().units.values.filter { it.obsoleteTech == techName }.map { it.name }
|
||||
val unitUpgrades = HashMap<String, HashSet<City>>()
|
||||
for (city in civInfo.cities) {
|
||||
// Do not use replaceAll - that's a Java 8 feature and will fail on older phones!
|
||||
val oldQueue = city.cityConstructions.constructionQueue.toList() // copy, since we're changing the queue
|
||||
val oldQueue =
|
||||
city.cityConstructions.constructionQueue.toList() // copy, since we're changing the queue
|
||||
city.cityConstructions.constructionQueue.clear()
|
||||
for (constructionName in oldQueue) {
|
||||
if (constructionName in obsoleteUnits) {
|
||||
@ -310,13 +330,18 @@ class TechManager : IsPartOfGameInfoSerialization {
|
||||
if (cities.size == 1) {
|
||||
val city = cities.first()
|
||||
if (construction is BaseUnit && construction.upgradesTo != null) {
|
||||
val text = "[${city.name}] changed production from [$unit] to [${construction.upgradesTo!!}]"
|
||||
civInfo.addNotification(text, city.location,
|
||||
val text =
|
||||
"[${city.name}] changed production from [$unit] to [${construction.upgradesTo!!}]"
|
||||
civInfo.addNotification(
|
||||
text, city.location,
|
||||
NotificationCategory.Production, unit,
|
||||
NotificationIcon.Construction, construction.upgradesTo!!)
|
||||
NotificationIcon.Construction, construction.upgradesTo!!
|
||||
)
|
||||
} else {
|
||||
val text = "[$unit] has become obsolete and was removed from the queue in [${city.name}]!"
|
||||
civInfo.addNotification(text, city.location,
|
||||
val text =
|
||||
"[$unit] has become obsolete and was removed from the queue in [${city.name}]!"
|
||||
civInfo.addNotification(
|
||||
text, city.location,
|
||||
NotificationCategory.Production,
|
||||
NotificationIcon.Construction
|
||||
)
|
||||
@ -324,47 +349,49 @@ class TechManager : IsPartOfGameInfoSerialization {
|
||||
} else {
|
||||
val locationAction = LocationAction(cities.asSequence().map { it.location })
|
||||
if (construction is BaseUnit && construction.upgradesTo != null) {
|
||||
val text = "[${cities.size}] cities changed production from [$unit] to [${construction.upgradesTo!!}]"
|
||||
civInfo.addNotification(text, locationAction,
|
||||
val text =
|
||||
"[${cities.size}] cities changed production from [$unit] to [${construction.upgradesTo!!}]"
|
||||
civInfo.addNotification(
|
||||
text, locationAction,
|
||||
NotificationCategory.Production, unit,
|
||||
NotificationIcon.Construction, construction.upgradesTo!!)
|
||||
NotificationIcon.Construction, construction.upgradesTo!!
|
||||
)
|
||||
} else {
|
||||
val text = "[$unit] has become obsolete and was removed from the queue in [${cities.size}] cities!"
|
||||
civInfo.addNotification(text, locationAction,
|
||||
val text =
|
||||
"[$unit] has become obsolete and was removed from the queue in [${cities.size}] cities!"
|
||||
civInfo.addNotification(
|
||||
text, locationAction,
|
||||
NotificationCategory.Production,
|
||||
NotificationIcon.Construction
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (unique in civInfo.getMatchingUniques(UniqueType.ReceiveFreeUnitWhenDiscoveringTech)) {
|
||||
if (unique.params[1] != techName) continue
|
||||
civInfo.units.addUnit(unique.params[0])
|
||||
}
|
||||
for (unique in civInfo.getMatchingUniques(UniqueType.MayanGainGreatPerson)) {
|
||||
if (unique.params[1] != techName) continue
|
||||
civInfo.addNotification("You have unlocked [The Long Count]!",
|
||||
MayaLongCountAction(), NotificationCategory.General, MayaCalendar.notificationIcon)
|
||||
}
|
||||
|
||||
private fun moveToNewEra() {
|
||||
val previousEra = civInfo.getEra()
|
||||
updateEra()
|
||||
val currentEra = civInfo.getEra()
|
||||
if (previousEra != currentEra) {
|
||||
civInfo.addNotification("You have entered the [$currentEra]!",
|
||||
civInfo.addNotification(
|
||||
"You have entered the [$currentEra]!",
|
||||
NotificationCategory.General,
|
||||
NotificationIcon.Science
|
||||
)
|
||||
if (civInfo.isMajorCiv()) {
|
||||
for (knownCiv in civInfo.getKnownCivs()) {
|
||||
knownCiv.addNotification("[${civInfo.civName}] has entered the [$currentEra]!",
|
||||
knownCiv.addNotification(
|
||||
"[${civInfo.civName}] has entered the [$currentEra]!",
|
||||
NotificationCategory.General, civInfo.civName, NotificationIcon.Science
|
||||
)
|
||||
}
|
||||
}
|
||||
for (policyBranch in getRuleset().policyBranches.values.filter { it.era == currentEra.name && civInfo.policies.isAdoptable(it) }) {
|
||||
civInfo.addNotification("[${policyBranch.name}] policy branch unlocked!",
|
||||
for (policyBranch in getRuleset().policyBranches.values.filter {
|
||||
it.era == currentEra.name && civInfo.policies.isAdoptable(it)
|
||||
}) {
|
||||
civInfo.addNotification(
|
||||
"[${policyBranch.name}] policy branch unlocked!",
|
||||
NotificationCategory.General,
|
||||
NotificationIcon.Culture
|
||||
)
|
||||
@ -373,15 +400,26 @@ class TechManager : IsPartOfGameInfoSerialization {
|
||||
val erasPassed = getRuleset().eras.values
|
||||
.filter { it.eraNumber > previousEra.eraNumber && it.eraNumber <= currentEra.eraNumber }
|
||||
.sortedBy { it.eraNumber }
|
||||
|
||||
|
||||
for (era in erasPassed)
|
||||
for (unique in era.uniqueObjects)
|
||||
if (unique.conditionals.none { it.type!!.targetTypes.contains(UniqueTarget.TriggerCondition) })
|
||||
UniqueTriggerActivation.triggerCivwideUnique(unique, civInfo)
|
||||
UniqueTriggerActivation.triggerCivwideUnique(
|
||||
unique,
|
||||
civInfo,
|
||||
triggerNotificationText = "due to entering the [${era.name}]"
|
||||
)
|
||||
|
||||
val eraNames = erasPassed.map { it.name }.toHashSet()
|
||||
for (unique in civInfo.getTriggeredUniques(UniqueType.TriggerUponEnteringEra))
|
||||
if (unique.conditionals.any {it.type == UniqueType.TriggerUponEnteringEra && it.params[0] in eraNames})
|
||||
UniqueTriggerActivation.triggerCivwideUnique(unique, civInfo)
|
||||
for (eraName in eraNames)
|
||||
if (unique.conditionals.any { it.type == UniqueType.TriggerUponEnteringEra && it.params[0] == eraName })
|
||||
UniqueTriggerActivation.triggerCivwideUnique(
|
||||
unique,
|
||||
civInfo,
|
||||
triggerNotificationText = "due to entering the [$eraName]"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -177,6 +177,7 @@ class CivInfoTransientCache(val civInfo: Civilization) {
|
||||
goldGained += 500
|
||||
}
|
||||
|
||||
|
||||
if (civInfo.hasUnique(UniqueType.GoldWhenDiscoveringNaturalWonder)) {
|
||||
goldGained += if (discoveredNaturalWonders.contains(tile.naturalWonder!!)) 100 else 500
|
||||
}
|
||||
|
@ -74,10 +74,10 @@ class TileMap : IsPartOfGameInfoSerialization {
|
||||
val maxLongitude: Float by lazy { if (values.isEmpty()) 0f else values.maxOf { abs(it.longitude) } }
|
||||
|
||||
@delegate:Transient
|
||||
val naturalWonders: List<String> by lazy { tileList.asSequence().filter { it.isNaturalWonder() }.map { it.naturalWonder!! }.distinct().toList() }
|
||||
val naturalWonders: Set<String> by lazy { tileList.asSequence().filter { it.isNaturalWonder() }.map { it.naturalWonder!! }.toSet() }
|
||||
|
||||
@delegate:Transient
|
||||
val resources: List<String> by lazy { tileList.asSequence().filter { it.resource != null }.map { it.resource!! }.distinct().toList() }
|
||||
val resources: Set<String> by lazy { tileList.asSequence().filter { it.resource != null }.map { it.resource!! }.toSet() }
|
||||
|
||||
// Excluded from Serialization by having no own backing field
|
||||
val values: Collection<Tile>
|
||||
|
@ -1,7 +1,7 @@
|
||||
package com.unciv.models.ruleset
|
||||
|
||||
import com.unciv.logic.city.CityConstructions
|
||||
import com.unciv.logic.city.City
|
||||
import com.unciv.logic.city.CityConstructions
|
||||
import com.unciv.logic.city.INonPerpetualConstruction
|
||||
import com.unciv.logic.city.RejectionReason
|
||||
import com.unciv.logic.city.RejectionReasons
|
||||
@ -666,19 +666,22 @@ class Building : RulesetStatsObject(), INonPerpetualConstruction {
|
||||
// "Provides a free [buildingName] [cityFilter]"
|
||||
cityConstructions.addFreeBuildings()
|
||||
|
||||
val triggerNotificationText ="due to constructing [$name]"
|
||||
|
||||
for (unique in uniqueObjects)
|
||||
if (unique.conditionals.none { it.type!!.targetTypes.contains(UniqueTarget.TriggerCondition) })
|
||||
UniqueTriggerActivation.triggerCivwideUnique(unique, civInfo, cityConstructions.city)
|
||||
UniqueTriggerActivation.triggerCivwideUnique(unique, civInfo, cityConstructions.city, triggerNotificationText = triggerNotificationText)
|
||||
|
||||
|
||||
for (unique in civInfo.getTriggeredUniques(UniqueType.TriggerUponConstructingBuilding, StateForConditionals(civInfo, cityInfo)))
|
||||
if (unique.conditionals.any {it.type == UniqueType.TriggerUponConstructingBuilding && matchesFilter(it.params[0])})
|
||||
UniqueTriggerActivation.triggerCivwideUnique(unique, cityInfo.civInfo, cityInfo)
|
||||
UniqueTriggerActivation.triggerCivwideUnique(unique, cityInfo.civInfo, cityInfo, triggerNotificationText = triggerNotificationText)
|
||||
|
||||
for (unique in civInfo.getTriggeredUniques(UniqueType.TriggerUponConstructingBuildingCityFilter, StateForConditionals(cityInfo.civInfo, cityInfo)))
|
||||
if (unique.conditionals.any {it.type == UniqueType.TriggerUponConstructingBuildingCityFilter
|
||||
&& matchesFilter(it.params[0])
|
||||
&& cityInfo.matchesFilter(it.params[1])})
|
||||
UniqueTriggerActivation.triggerCivwideUnique(unique, cityInfo.civInfo, cityInfo)
|
||||
UniqueTriggerActivation.triggerCivwideUnique(unique, cityInfo.civInfo, cityInfo, triggerNotificationText = triggerNotificationText)
|
||||
|
||||
if (hasUnique(UniqueType.EnemyLandUnitsSpendExtraMovement))
|
||||
civInfo.cache.updateHasActiveEnemyMovementPenalty()
|
||||
|
@ -29,7 +29,8 @@ object UniqueTriggerActivation {
|
||||
civInfo: Civilization,
|
||||
city: City? = null,
|
||||
tile: Tile? = null,
|
||||
notification: String? = null
|
||||
notification: String? = null,
|
||||
triggerNotificationText: String? = null
|
||||
): Boolean {
|
||||
val timingConditional = unique.conditionals.firstOrNull { it.type == UniqueType.ConditionalTimedUnique }
|
||||
if (timingConditional != null) {
|
||||
@ -52,15 +53,18 @@ object UniqueTriggerActivation {
|
||||
if (chosenCity == null || unit == null || (unit.hasUnique(UniqueType.FoundCity) && civInfo.isOneCityChallenger()))
|
||||
return false
|
||||
|
||||
val placedUnit = civInfo.units.addUnit(unitName, chosenCity)
|
||||
if (notification != null && placedUnit != null) {
|
||||
civInfo.addNotification(
|
||||
notification,
|
||||
placedUnit.getTile().position,
|
||||
NotificationCategory.Units,
|
||||
placedUnit.name
|
||||
)
|
||||
}
|
||||
val placedUnit = civInfo.units.addUnit(unitName, chosenCity) ?: return false
|
||||
|
||||
val notificationText = if (notification != null) notification
|
||||
else if (triggerNotificationText != null) "{Gained [1] [$unitName] unit(s)}{ }{$triggerNotificationText}"
|
||||
else return true
|
||||
|
||||
civInfo.addNotification(
|
||||
notificationText,
|
||||
placedUnit.getTile().position,
|
||||
NotificationCategory.Units,
|
||||
placedUnit.name
|
||||
)
|
||||
return true
|
||||
}
|
||||
UniqueType.OneTimeAmountFreeUnits -> {
|
||||
@ -75,14 +79,18 @@ object UniqueTriggerActivation {
|
||||
if (placedUnit != null)
|
||||
tilesUnitsWerePlacedOn.add(placedUnit.getTile().position)
|
||||
}
|
||||
if (notification != null && tilesUnitsWerePlacedOn.isNotEmpty()) {
|
||||
civInfo.addNotification(
|
||||
notification,
|
||||
LocationAction(tilesUnitsWerePlacedOn),
|
||||
NotificationCategory.Units,
|
||||
civInfo.getEquivalentUnit(unit).name
|
||||
)
|
||||
}
|
||||
if (tilesUnitsWerePlacedOn.isEmpty()) return true
|
||||
|
||||
val notificationText = if (notification != null) notification
|
||||
else if (triggerNotificationText!=null) "{Gained [${tilesUnitsWerePlacedOn.size}] [$unitName] unit(s)}{ }{$triggerNotificationText}"
|
||||
else return true
|
||||
|
||||
civInfo.addNotification(
|
||||
notificationText,
|
||||
LocationAction(tilesUnitsWerePlacedOn),
|
||||
NotificationCategory.Units,
|
||||
civInfo.getEquivalentUnit(unit).name
|
||||
)
|
||||
return true
|
||||
}
|
||||
UniqueType.OneTimeFreeUnitRuins -> {
|
||||
@ -117,24 +125,37 @@ object UniqueTriggerActivation {
|
||||
// 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
|
||||
civInfo.policies.freePolicies++
|
||||
if (notification != null) {
|
||||
civInfo.addNotification(notification, NotificationCategory.General, NotificationIcon.Culture)
|
||||
}
|
||||
|
||||
val notificationText = if (notification != null) notification
|
||||
else if (triggerNotificationText != null) "{You may choose a free Policy}{ }{$triggerNotificationText}"
|
||||
else return true
|
||||
|
||||
civInfo.addNotification(notificationText, NotificationCategory.General, NotificationIcon.Culture)
|
||||
|
||||
return true
|
||||
}
|
||||
UniqueType.OneTimeAmountFreePolicies -> {
|
||||
if (civInfo.isSpectator()) return false
|
||||
civInfo.policies.freePolicies += unique.params[0].toInt()
|
||||
if (notification != null) {
|
||||
civInfo.addNotification(notification, NotificationCategory.General, NotificationIcon.Culture)
|
||||
}
|
||||
val newFreePolicies = unique.params[0].toInt()
|
||||
civInfo.policies.freePolicies += newFreePolicies
|
||||
|
||||
val notificationText = if (notification != null) notification
|
||||
else if (triggerNotificationText != null) "{You may choose [$newFreePolicies] free Policies}{ }{$triggerNotificationText}"
|
||||
else return true
|
||||
|
||||
civInfo.addNotification(notificationText, NotificationCategory.General, NotificationIcon.Culture)
|
||||
|
||||
return true
|
||||
}
|
||||
UniqueType.OneTimeEnterGoldenAge -> {
|
||||
civInfo.goldenAges.enterGoldenAge()
|
||||
if (notification != null) {
|
||||
civInfo.addNotification(notification, NotificationCategory.General, NotificationIcon.Happiness)
|
||||
}
|
||||
|
||||
val notificationText = if (notification != null) notification
|
||||
else if (triggerNotificationText != null) "{You enter a Golden Age}{ }{$triggerNotificationText}"
|
||||
else return true
|
||||
|
||||
civInfo.addNotification(notificationText, NotificationCategory.General, NotificationIcon.Happiness)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user