From a6ac9aa24d1ca86cab440b7156f80126802600b6 Mon Sep 17 00:00:00 2001 From: SeventhM <127357473+SeventhM@users.noreply.github.com> Date: Wed, 22 Nov 2023 13:59:53 -0800 Subject: [PATCH] Fix free buildings triggering from conditionals in incorrect places (#10532) * ignore trigger condtional uniques * Have UniqueTriggerActivation only add the buildings of its unique * (minor optimization) move where we find the free building * Once again I forget about imports --- .../logic/civilization/CivConstructions.kt | 9 ++++--- .../ruleset/unique/UniqueTriggerActivation.kt | 25 ++++++++++++++++--- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/core/src/com/unciv/logic/civilization/CivConstructions.kt b/core/src/com/unciv/logic/civilization/CivConstructions.kt index 3ec7c6ada8..6168c45b52 100644 --- a/core/src/com/unciv/logic/civilization/CivConstructions.kt +++ b/core/src/com/unciv/logic/civilization/CivConstructions.kt @@ -97,6 +97,7 @@ class CivConstructions : IsPartOfGameInfoSerialization { private fun addFreeStatsBuildings() { val statUniquesData = civInfo.getMatchingUniques(UniqueType.FreeStatBuildings) + .filter { !it.hasTriggerConditional() } .groupBy { it.params[0] } .mapKeys { Stat.valueOf(it.key) } .mapValues { unique -> unique.value.sumOf { it.params[1].toInt() } } @@ -106,7 +107,7 @@ class CivConstructions : IsPartOfGameInfoSerialization { } } - private fun addFreeStatBuildings(stat: Stat, amount: Int) { + fun addFreeStatBuildings(stat: Stat, amount: Int) { for (city in civInfo.cities.take(amount)) { if (freeStatBuildingsProvided.contains(stat.name, city.id)) continue val building = city.cityConstructions.cheapestStatBuilding(stat) @@ -120,6 +121,7 @@ class CivConstructions : IsPartOfGameInfoSerialization { private fun addFreeSpecificBuildings() { val buildingsUniquesData = civInfo.getMatchingUniques(UniqueType.FreeSpecificBuildings) + .filter { !it.hasTriggerConditional() } .groupBy { it.params[0] } .mapValues { unique -> unique.value.sumOf { it.params[1].toInt() } } @@ -129,7 +131,7 @@ class CivConstructions : IsPartOfGameInfoSerialization { } } - private fun addFreeBuildings(building: Building, amount: Int) { + fun addFreeBuildings(building: Building, amount: Int) { for (city in civInfo.cities.take(amount)) { if (freeSpecificBuildingsProvided.contains(building.name, city.id) || city.cityConstructions.containsBuildingOrEquivalent(building.name)) continue @@ -149,7 +151,8 @@ class CivConstructions : IsPartOfGameInfoSerialization { for (city in civInfo.cities) { val freeBuildingsFromCity = city.getMatchingLocalOnlyUniques(UniqueType.GainFreeBuildings, StateForConditionals.IgnoreConditionals) val freeBuildingUniques = (freeBuildingsFromCiv + freeBuildingsFromCity) - .filter { city.matchesFilter(it.params[1]) && it.conditionalsApply(StateForConditionals(city.civ, city)) } + .filter { city.matchesFilter(it.params[1]) && it.conditionalsApply(StateForConditionals(city.civ, city)) + && !it.hasTriggerConditional() } for (unique in freeBuildingUniques) { val freeBuilding = city.civ.getEquivalentBuilding(unique.params[0]) city.cityConstructions.freeBuildingsProvidedFromThisCity.addToMapOfSets(city.id, freeBuilding.name) diff --git a/core/src/com/unciv/models/ruleset/unique/UniqueTriggerActivation.kt b/core/src/com/unciv/models/ruleset/unique/UniqueTriggerActivation.kt index 2cf09b7ede..101c4c0aaa 100644 --- a/core/src/com/unciv/models/ruleset/unique/UniqueTriggerActivation.kt +++ b/core/src/com/unciv/models/ruleset/unique/UniqueTriggerActivation.kt @@ -20,6 +20,7 @@ import com.unciv.models.stats.Stat import com.unciv.models.stats.Stats import com.unciv.models.translations.fillPlaceholders import com.unciv.models.translations.hasPlaceholderParameters +import com.unciv.ui.components.extensions.addToMapOfSets import com.unciv.ui.components.MayaCalendar import com.unciv.ui.screens.worldscreen.unit.actions.UnitActionsUpgrade import kotlin.math.roundToInt @@ -664,10 +665,28 @@ object UniqueTriggerActivation { return true } - UniqueType.FreeStatBuildings, UniqueType.FreeSpecificBuildings, UniqueType.GainFreeBuildings -> { - civInfo.civConstructions.tryAddFreeBuildings() - return true // not fully correct + val freeBuilding = civInfo.getEquivalentBuilding(unique.params[0]) + val applicableCities = + if (unique.params[1] == "in this city") sequenceOf(city!!) + else civInfo.cities.asSequence().filter { it.matchesFilter(unique.params[1]) } + 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 + } + UniqueType.FreeStatBuildings -> { + val stat = Stat.safeValueOf(unique.params[0]) ?: return false + civInfo.civConstructions.addFreeStatBuildings(stat, unique.params[1].toInt()) + return true + } + UniqueType.FreeSpecificBuildings ->{ + val building = ruleSet.buildings[unique.params[0]] ?: return false + civInfo.civConstructions.addFreeBuildings(building, unique.params[1].toInt()) + return true } UniqueType.RemoveBuilding -> {