From 9cce7b21bdeb81706ad86361094a939a64cb5c24 Mon Sep 17 00:00:00 2001 From: Rob Loach Date: Mon, 23 Jun 2025 16:18:06 -0400 Subject: [PATCH] Add `Gain control over [positiveAmount] tiles [cityFilter]` Triggerable (#13489) * Add 'Expand the border [cityFilter]' Unique * Update OneTimeExpandBorder * Add quantifier * Clean up the code * Rename and add a test * Update docs --- .../ruleset/unique/UniqueTriggerActivation.kt | 17 +++++++++++++++++ .../unciv/models/ruleset/unique/UniqueType.kt | 2 +- docs/Modders/uniques.md | 5 +++++ .../src/com/unciv/uniques/GlobalUniquesTests.kt | 16 ++++++++++++++++ 4 files changed, 39 insertions(+), 1 deletion(-) diff --git a/core/src/com/unciv/models/ruleset/unique/UniqueTriggerActivation.kt b/core/src/com/unciv/models/ruleset/unique/UniqueTriggerActivation.kt index f98d3711cc..c7ff455010 100644 --- a/core/src/com/unciv/models/ruleset/unique/UniqueTriggerActivation.kt +++ b/core/src/com/unciv/models/ruleset/unique/UniqueTriggerActivation.kt @@ -913,6 +913,23 @@ object UniqueTriggerActivation { } } + UniqueType.OneTimeTakeOverTilesInCity -> { + val applicableCities = getApplicableCities(unique.params[1]) + if (applicableCities.none()) return null + if (applicableCities.none { it.expansion.chooseNewTileToOwn() != null }) return null + + return { + val positiveAmount = unique.params[0].toInt() + for (applicableCity in applicableCities) { + for (i in 1..positiveAmount) { + val tileToOwn = applicableCity.expansion.chooseNewTileToOwn() ?: break + applicableCity.expansion.takeOwnership(tileToOwn) + } + } + true + } + } + UniqueType.GainFreeBuildings -> { val freeBuilding = civInfo.getEquivalentBuilding(unique.params[0]) val applicableCities = getApplicableCities(unique.params[1]) diff --git a/core/src/com/unciv/models/ruleset/unique/UniqueType.kt b/core/src/com/unciv/models/ruleset/unique/UniqueType.kt index 8bac6552b4..b6971eb2e2 100644 --- a/core/src/com/unciv/models/ruleset/unique/UniqueType.kt +++ b/core/src/com/unciv/models/ruleset/unique/UniqueType.kt @@ -857,6 +857,7 @@ enum class UniqueType( OneTimeGainTechPercent("Research [relativeAmount]% of [tech]", UniqueTarget.Triggerable), OneTimeTakeOverTilesInRadius("Gain control over [tileFilter] tiles in a [nonNegativeAmount]-tile radius", UniqueTarget.Triggerable), + OneTimeTakeOverTilesInCity("Gain control over [positiveAmount] tiles [cityFilter]", UniqueTarget.Triggerable), // todo: The "up to [All]" used in vanilla json is not nice to read. Split? // Or just reword it without the 'up to', so it reads "Reveal [amount/'all'] [tileFilter] tiles within [amount] tiles" @@ -867,7 +868,6 @@ enum class UniqueType( OneTimeSpiesLevelUp("Promotes all spies [positiveAmount] time(s)", UniqueTarget.Triggerable), // used in Policies, Buildings OneTimeGainSpy("Gain an extra spy", UniqueTarget.Triggerable), // used in Wonders - SkipPromotion("Doing so will consume this opportunity to choose a Promotion", UniqueTarget.Promotion), FreePromotion("This Promotion is free", UniqueTarget.Promotion), diff --git a/docs/Modders/uniques.md b/docs/Modders/uniques.md index e2e1665401..8b2180549a 100644 --- a/docs/Modders/uniques.md +++ b/docs/Modders/uniques.md @@ -153,6 +153,11 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl Applicable to: Triggerable +??? example "Gain control over [positiveAmount] tiles [cityFilter]" + Example: "Gain control over [3] tiles [in all cities]" + + Applicable to: Triggerable + ??? example "Reveal up to [positiveAmount/'all'] [tileFilter] within a [positiveAmount] tile radius" Example: "Reveal up to [3] [Farm] within a [3] tile radius" diff --git a/tests/src/com/unciv/uniques/GlobalUniquesTests.kt b/tests/src/com/unciv/uniques/GlobalUniquesTests.kt index 6cfdb6a431..754f09ee54 100644 --- a/tests/src/com/unciv/uniques/GlobalUniquesTests.kt +++ b/tests/src/com/unciv/uniques/GlobalUniquesTests.kt @@ -626,6 +626,22 @@ class GlobalUniquesTests { } // endregion + // region Gain control over tiles + + @Test + fun takeOverTilesInCity() { + game.makeHexagonalMap(5) + val civInfo = game.addCiv() + val tile = game.getTile(Vector2.Zero) + val city = game.addCity(civInfo, tile, true) + Assert.assertEquals(7, city.getTiles().count()) + val building = game.createBuilding("Gain control over [8] tiles [in this city]") + city.cityConstructions.addBuilding(building) + Assert.assertEquals(15, city.getTiles().count()) + } + + // endregion + // endregion }