Fix buildings/units not triggering and golden age stat updates (#9731)

* Fix buildings not triggering, golden age stat updates, and units not triggering

* Forgot import, whoops

* uodate resources and city connection when removing a building

* Move building triggers to function, added unit notification to translations

* Quick edits without android studio sucks

* Add unitActionModifier check back to hasTriggerConditional

---------

Co-authored-by: Yair Morgenstern <yairm210@hotmail.com>
This commit is contained in:
SeventhM 2023-07-05 14:36:43 -07:00 committed by GitHub
parent d2dac66f40
commit 5ea1d5722b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 74 additions and 69 deletions

View File

@ -1027,6 +1027,7 @@ due to adopting [policy] =
due to discovering [naturalWonder] =
due to entering the [eraName] =
due to constructing [buildingName] =
due to gaining a [unitName] =
due to founding a city =
due to discovering a Natural Wonder =
due to our [unitName] defeating a [otherUnitName] =

View File

@ -22,6 +22,7 @@ import com.unciv.models.ruleset.unique.LocalUniqueCache
import com.unciv.models.ruleset.unique.StateForConditionals
import com.unciv.models.ruleset.unique.UniqueMap
import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.models.ruleset.unique.UniqueTriggerActivation
import com.unciv.models.ruleset.unit.BaseUnit
import com.unciv.models.stats.Stat
import com.unciv.models.stats.Stats
@ -479,16 +480,75 @@ class CityConstructions : IsPartOfGameInfoSerialization {
}
fun addBuilding(buildingName: String) {
val buildingObject = city.getRuleset().buildings[buildingName]!!
builtBuildingObjects = builtBuildingObjects.withItem(buildingObject)
val building = city.getRuleset().buildings[buildingName]!!
val civ = city.civ
if (building.cityHealth > 0) {
// city built a building that increases health so add a portion of this added health that is
// proportional to the city's current health
city.health += (building.cityHealth.toFloat() * city.health.toFloat() / city.getMaxHealth().toFloat()).toInt()
}
builtBuildingObjects = builtBuildingObjects.withItem(building)
builtBuildings.add(buildingName)
/** Support for [UniqueType.CreatesOneImprovement] */
applyCreateOneImprovement(building)
addFreeBuildings()
triggerNewBuildingUniques(building)
if (building.hasUnique(UniqueType.EnemyUnitsSpendExtraMovement))
civ.cache.updateHasActiveEnemyMovementPenalty()
// Korean unique - apparently gives the same as the research agreement
if (building.isStatRelated(Stat.Science) && civ.hasUnique(UniqueType.TechBoostWhenScientificBuildingsBuiltInCapital))
civ.tech.addScience(civ.tech.scienceOfLast8Turns.sum() / 8)
val uniqueTypesModifyingYields = listOf(
UniqueType.StatsFromTiles, UniqueType.StatsFromTilesWithout, UniqueType.StatsFromObject,
UniqueType.StatPercentFromObject, UniqueType.AllStatsPercentFromObject
)
// Happiness is global, so it could affect all cities
if(building.isStatRelated(Stat.Happiness)) {
for (city in civ.cities) {
city.reassignPopulationDeferred()
}
}
else if(uniqueTypesModifyingYields.any { building.hasUnique(it) })
city.reassignPopulationDeferred()
updateUniques()
civ.cache.updateCivResources() // this building could be a resource-requiring one
civ.cache.updateCitiesConnectedToCapital(false) // could be a connecting building, like a harbor
}
fun triggerNewBuildingUniques(building: Building) {
val triggerNotificationText ="due to constructing [${building.name}]"
for (unique in building.uniqueObjects)
if (!unique.hasTriggerConditional())
UniqueTriggerActivation.triggerCivwideUnique(unique, city.civ, city, triggerNotificationText = triggerNotificationText)
for (unique in city.civ.getTriggeredUniques(UniqueType.TriggerUponConstructingBuilding, StateForConditionals(city.civ, city)))
if (unique.conditionals.any {it.type == UniqueType.TriggerUponConstructingBuilding && building.matchesFilter(it.params[0])})
UniqueTriggerActivation.triggerCivwideUnique(unique, city.civ, city, triggerNotificationText = triggerNotificationText)
for (unique in city.civ.getTriggeredUniques(UniqueType.TriggerUponConstructingBuildingCityFilter, StateForConditionals(city.civ, city)))
if (unique.conditionals.any {it.type == UniqueType.TriggerUponConstructingBuildingCityFilter
&& building.matchesFilter(it.params[0])
&& city.matchesFilter(it.params[1])})
UniqueTriggerActivation.triggerCivwideUnique(unique, city.civ, city, triggerNotificationText = triggerNotificationText)
}
fun removeBuilding(buildingName: String) {
val buildingObject = city.getRuleset().buildings[buildingName]!!
builtBuildingObjects = builtBuildingObjects.withoutItem(buildingObject)
builtBuildings.remove(buildingName)
city.civ.cache.updateCivResources() // this building could be a resource-requiring one
city.civ.cache.updateCitiesConnectedToCapital(false) // could be a connecting building, like a harbor
updateUniques()
}

View File

@ -209,7 +209,6 @@ class CityFounder {
}
civInfo.civConstructions.tryAddFreeBuildings()
city.cityConstructions.addFreeBuildings()
}

View File

@ -49,7 +49,9 @@ class GoldenAgeManager : IsPartOfGameInfoSerialization {
for (unique in civInfo.getTriggeredUniques(UniqueType.TriggerUponEnteringGoldenAge))
UniqueTriggerActivation.triggerCivwideUnique(unique, civInfo)
civInfo.updateStatsForNextTurn()
//Golden Age can happen mid turn with Great Artist effects
for (city in civInfo.cities)
city.cityStats.update()
}
fun endTurn(happiness: Int) {

View File

@ -71,9 +71,13 @@ class UnitManager(val civInfo:Civilization) {
val unit = civInfo.gameInfo.tileMap.placeUnitNearTile(location, unitName, civInfo)
if (unit != null) {
val triggerNotificationText = "due to gaining a [${unit.name}]"
for (unique in unit.getUniques())
if (!unique.hasTriggerConditional())
UniqueTriggerActivation.triggerUnitwideUnique(unique, unit, triggerNotificationText = triggerNotificationText)
for (unique in civInfo.getTriggeredUniques(UniqueType.TriggerUponGainingUnit))
if (unit.matchesFilter(unique.params[0]))
UniqueTriggerActivation.triggerCivwideUnique(unique, civInfo)
UniqueTriggerActivation.triggerCivwideUnique(unique, civInfo, triggerNotificationText = triggerNotificationText)
if (unit.baseUnit.getResourceRequirementsPerTurn().isNotEmpty())
civInfo.cache.updateCivResources()
}

View File

@ -643,75 +643,14 @@ class Building : RulesetStatsObject(), INonPerpetualConstruction {
getRejectionReasons(cityConstructions).none()
override fun postBuildEvent(cityConstructions: CityConstructions, boughtWith: Stat?): Boolean {
val city = cityConstructions.city
val civInfo = city.civ
val civInfo = cityConstructions.city.civ
if (civInfo.gameInfo.spaceResources.contains(name)) {
civInfo.victoryManager.currentsSpaceshipParts.add(name, 1)
return true
}
if (cityHealth > 0) {
// city built a building that increases health so add a portion of this added health that is
// proportional to the city's current health
cityConstructions.city.health += (cityHealth.toFloat() * cityConstructions.city.health.toFloat() / cityConstructions.city.getMaxHealth().toFloat()).toInt()
}
cityConstructions.addBuilding(name)
/** Support for [UniqueType.CreatesOneImprovement] */
cityConstructions.applyCreateOneImprovement(this)
// "Provides a free [buildingName] [cityFilter]"
cityConstructions.addFreeBuildings()
val triggerNotificationText ="due to constructing [$name]"
for (unique in uniqueObjects)
if (!unique.hasTriggerConditional())
UniqueTriggerActivation.triggerCivwideUnique(unique, civInfo, cityConstructions.city, triggerNotificationText = triggerNotificationText)
for (unique in civInfo.getTriggeredUniques(UniqueType.TriggerUponConstructingBuilding, StateForConditionals(civInfo, city)))
if (unique.conditionals.any {it.type == UniqueType.TriggerUponConstructingBuilding && matchesFilter(it.params[0])})
UniqueTriggerActivation.triggerCivwideUnique(unique, city.civ, city, triggerNotificationText = triggerNotificationText)
for (unique in civInfo.getTriggeredUniques(UniqueType.TriggerUponConstructingBuildingCityFilter, StateForConditionals(city.civ, city)))
if (unique.conditionals.any {it.type == UniqueType.TriggerUponConstructingBuildingCityFilter
&& matchesFilter(it.params[0])
&& city.matchesFilter(it.params[1])})
UniqueTriggerActivation.triggerCivwideUnique(unique, city.civ, city, triggerNotificationText = triggerNotificationText)
if (hasUnique(UniqueType.EnemyUnitsSpendExtraMovement))
civInfo.cache.updateHasActiveEnemyMovementPenalty()
// Korean unique - apparently gives the same as the research agreement
if (isStatRelated(Stat.Science) && civInfo.hasUnique(UniqueType.TechBoostWhenScientificBuildingsBuiltInCapital))
civInfo.tech.addScience(civInfo.tech.scienceOfLast8Turns.sum() / 8)
// Happiness change _may_ invalidate best worked tiles (#9238), but if the building
// isn't bought (or the AI bought it) then reassignPopulation will run later in startTurn anyway
if (boughtWith != null && isStatRelated(Stat.Happiness)) {
// Happiness is global, so it could affect all cities
Concurrency.runOnNonDaemonThreadPool("reassignPopulationAllCities") {
for (city in civInfo.cities)
city.reassignPopulationDeferred()
}
}
// Buying a building influencing tile yield may change CityFocus decisions
val uniqueTypesModifyingYields = listOf(
UniqueType.StatsFromTiles, UniqueType.StatsFromTilesWithout, UniqueType.StatsFromObject,
UniqueType.StatPercentFromObject, UniqueType.AllStatsPercentFromObject
)
if (boughtWith != null && uniqueTypesModifyingYields.any { hasUnique(it) }) {
cityConstructions.city.reassignPopulationDeferred()
}
cityConstructions.city.cityStats.update() // new building, new stats
civInfo.cache.updateCivResources() // this building/unit could be a resource-requiring one
civInfo.cache.updateCitiesConnectedToCapital(false) // could be a connecting building, like a harbor
return true
}

View File

@ -45,7 +45,7 @@ class Unique(val text: String, val sourceObjectType: UniqueTarget? = null, val s
fun hasTriggerConditional(): Boolean {
if(conditionals.none()) return false
return conditionals.any{ conditional -> conditional.type?.targetTypes
?.any{ it.canAcceptUniqueTarget(UniqueTarget.TriggerCondition) }
?.any{ it.canAcceptUniqueTarget(UniqueTarget.TriggerCondition) || it.canAcceptUniqueTarget(UniqueTarget.UnitActionModifier) }
?: false
}
}