diff --git a/android/assets/jsons/translations/template.properties b/android/assets/jsons/translations/template.properties index 2fff76b401..b19bd948a0 100644 --- a/android/assets/jsons/translations/template.properties +++ b/android/assets/jsons/translations/template.properties @@ -1411,6 +1411,7 @@ What would you like to do with the city of [cityName]? = Annex = Annexed cities become part of your regular empire. = Their citizens generate 2x the unhappiness, unless you build a courthouse. = +Your civilization may not annex this city. = Puppet = Puppeted cities do not increase your tech or policy cost. = You have no control over the the production of puppeted cities. = @@ -1420,6 +1421,7 @@ Liberate (city returns to [originalOwner]) = Liberating a city returns it to its original owner, giving you a massive relationship boost with them! = Raze = Razing the city annexes it, and starts burning the city to the ground. = +Razing the city puppets it, and starts burning the city to the ground. = The population will gradually dwindle until the city is destroyed. = Original capitals and holy cities cannot be razed. = Destroy = diff --git a/core/src/com/unciv/logic/automation/civilization/NextTurnAutomation.kt b/core/src/com/unciv/logic/automation/civilization/NextTurnAutomation.kt index 18abc8e122..d7bcba3aa9 100644 --- a/core/src/com/unciv/logic/automation/civilization/NextTurnAutomation.kt +++ b/core/src/com/unciv/logic/automation/civilization/NextTurnAutomation.kt @@ -1016,7 +1016,7 @@ object NextTurnAutomation { ownMilitaryStrength < sumOfEnemiesMilitaryStrength * 0.66f for (city in civInfo.cities) { if (city.isPuppet && city.population.population > 9 - && !city.isInResistance() + && !city.isInResistance() && !civInfo.hasUnique(UniqueType.MayNotAnnexCities) ) { city.annexCity() } @@ -1124,7 +1124,7 @@ object NextTurnAutomation { if ((city.population.population < 4 || civInfo.isCityState()) && city.foundingCiv != civInfo.civName && city.canBeDestroyed(justCaptured = true)) { // raze if attacker is a city state - city.annexCity() + if (!civInfo.hasUnique(UniqueType.MayNotAnnexCities)) { city.annexCity() } city.isBeingRazed = true } } diff --git a/core/src/com/unciv/logic/battle/Battle.kt b/core/src/com/unciv/logic/battle/Battle.kt index 8369ff54e8..dd47ff9624 100644 --- a/core/src/com/unciv/logic/battle/Battle.kt +++ b/core/src/com/unciv/logic/battle/Battle.kt @@ -595,6 +595,7 @@ object Battle { if (city.isOriginalCapital && city.foundingCiv == attackerCiv.civName) { // retaking old capital city.puppetCity(attackerCiv) + //Although in Civ5 Venice is unable to re-annex their capital, that seems a bit silly. No check for May not annex cities here. city.annexCity() } else if (attackerCiv.isHuman()) { // we're not taking our former capital diff --git a/core/src/com/unciv/logic/city/managers/CityInfoConquestFunctions.kt b/core/src/com/unciv/logic/city/managers/CityInfoConquestFunctions.kt index a0079a8026..ab8ce4d33c 100644 --- a/core/src/com/unciv/logic/city/managers/CityInfoConquestFunctions.kt +++ b/core/src/com/unciv/logic/city/managers/CityInfoConquestFunctions.kt @@ -315,6 +315,13 @@ class CityInfoConquestFunctions(val city: City){ if (civ.gameInfo.isReligionEnabled()) religion.removeUnknownPantheons() + if (newCiv.hasUnique(UniqueType.MayNotAnnexCities)) { + isPuppet = true + cityConstructions.currentConstructionIsUserSet = false + cityConstructions.constructionQueue.clear() + cityConstructions.chooseNextConstruction() + } + tryUpdateRoadStatus() cityStats.update() diff --git a/core/src/com/unciv/models/ruleset/unique/UniqueType.kt b/core/src/com/unciv/models/ruleset/unique/UniqueType.kt index f3aa184783..bd8e987e1b 100644 --- a/core/src/com/unciv/models/ruleset/unique/UniqueType.kt +++ b/core/src/com/unciv/models/ruleset/unique/UniqueType.kt @@ -239,6 +239,7 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags: GainInfluenceWithUnitGiftToCityState("Gain [amount] Influence with a [baseUnitFilter] gift to a City-State", UniqueTarget.Global), FaithCostOfGreatProphetChange("[relativeAmount]% Faith cost of generating Great Prophet equivalents", UniqueTarget.Global), RestingPointOfCityStatesFollowingReligionChange("Resting point for Influence with City-States following this religion [amount]", UniqueTarget.Global), + MayNotAnnexCities("May not annex cities", UniqueTarget.Nation), ProvidesGoldWheneverGreatPersonExpended("Provides a sum of gold each time you spend a Great Person", UniqueTarget.Global), ProvidesStatsWheneverGreatPersonExpended("[stats] whenever a Great Person is expended", UniqueTarget.Global), diff --git a/core/src/com/unciv/ui/screens/cityscreen/CityScreen.kt b/core/src/com/unciv/ui/screens/cityscreen/CityScreen.kt index aad9db3f53..d29cbe25e1 100644 --- a/core/src/com/unciv/ui/screens/cityscreen/CityScreen.kt +++ b/core/src/com/unciv/ui/screens/cityscreen/CityScreen.kt @@ -259,7 +259,8 @@ class CityScreen( addWltkIcon("OtherIcons/WLTK 1") { color = Color.FIREBRICK }.padRight(10f) } - if (city.isPuppet) { + val canAnnex = !city.civ.hasUnique(UniqueType.MayNotAnnexCities) + if (city.isPuppet && canAnnex) { val annexCityButton = "Annex city".toTextButton() annexCityButton.labelCell.pad(10f) annexCityButton.onClick { @@ -272,8 +273,9 @@ class CityScreen( val razeCityButton = "Raze city".toTextButton() razeCityButton.labelCell.pad(10f) razeCityButton.onClick { city.isBeingRazed = true; update() } - if (!canChangeState || !city.canBeDestroyed()) + if (!canChangeState || !city.canBeDestroyed() || !canAnnex) { razeCityButton.disable() + } razeCityButtonHolder.add(razeCityButton) //.colspan(cityPickerTable.columns) } else { diff --git a/core/src/com/unciv/ui/screens/worldscreen/AlertPopup.kt b/core/src/com/unciv/ui/screens/worldscreen/AlertPopup.kt index 80e385877f..46a5d5f4cb 100644 --- a/core/src/com/unciv/ui/screens/worldscreen/AlertPopup.kt +++ b/core/src/com/unciv/ui/screens/worldscreen/AlertPopup.kt @@ -14,6 +14,7 @@ import com.unciv.logic.civilization.NotificationCategory import com.unciv.logic.civilization.PopupAlert import com.unciv.logic.civilization.diplomacy.DiplomaticModifiers import com.unciv.logic.civilization.diplomacy.RelationshipLevel +import com.unciv.models.ruleset.unique.UniqueType import com.unciv.models.translations.fillPlaceholders import com.unciv.models.translations.tr import com.unciv.ui.audio.MusicMood @@ -146,7 +147,8 @@ class AlertPopup( close() } } else { - addAnnexOption { + val mayAnnex = !conqueringCiv.hasUnique(UniqueType.MayNotAnnexCities) + addAnnexOption(mayAnnex = mayAnnex) { city.puppetCity(conqueringCiv) city.annexCity() worldScreen.shouldUpdate = true @@ -154,16 +156,16 @@ class AlertPopup( } addSeparator() - addPuppetOption { + addPuppetOption(mayAnnex = mayAnnex) { city.puppetCity(conqueringCiv) worldScreen.shouldUpdate = true close() } addSeparator() - addRazeOption(canRaze = { city.canBeDestroyed(justCaptured = true) } ) { + addRazeOption(canRaze = city.canBeDestroyed(justCaptured = true), mayAnnex = mayAnnex) { city.puppetCity(conqueringCiv) - city.annexCity() + if (mayAnnex) { city.annexCity() } city.isBeingRazed = true worldScreen.shouldUpdate = true close() @@ -239,13 +241,14 @@ class AlertPopup( close() } } else { - addAnnexOption { + val mayAnnex = !marryingCiv.hasUnique(UniqueType.MayNotAnnexCities) + addAnnexOption(mayAnnex) { city.annexCity() close() } addSeparator() - addPuppetOption { + addPuppetOption(mayAnnex) { city.isPuppet = true city.cityStats.update() worldScreen.shouldUpdate = true @@ -428,16 +431,25 @@ class AlertPopup( addGoodSizedLabel("Destroying the city instantly razes the city to the ground.").row() } - private fun addAnnexOption(annexAction: () -> Unit) { + private fun addAnnexOption(mayAnnex: Boolean, annexAction: () -> Unit) { val button = "Annex".toTextButton() - button.onActivation { annexAction() } - button.keyShortcuts.add('a') + button.apply { + if (!mayAnnex) disable() else { + button.onActivation { annexAction() } + button.keyShortcuts.add('a') + } + } add(button).row() - addGoodSizedLabel("Annexed cities become part of your regular empire.").row() - addGoodSizedLabel("Their citizens generate 2x the unhappiness, unless you build a courthouse.").row() + if (mayAnnex) { + addGoodSizedLabel("Annexed cities become part of your regular empire.").row() + addGoodSizedLabel("Their citizens generate 2x the unhappiness, unless you build a courthouse.").row() + } else { + addGoodSizedLabel("Your civilization may not annex this city.").row() + } + } - private fun addPuppetOption(puppetAction: () -> Unit) { + private fun addPuppetOption(mayAnnex: Boolean, puppetAction: () -> Unit) { val button = "Puppet".toTextButton() button.onActivation { puppetAction() } button.keyShortcuts.add('p') @@ -445,7 +457,7 @@ class AlertPopup( addGoodSizedLabel("Puppeted cities do not increase your tech or policy cost.").row() addGoodSizedLabel("You have no control over the the production of puppeted cities.").row() addGoodSizedLabel("Puppeted cities also generate 25% less Gold and Science.").row() - addGoodSizedLabel("A puppeted city can be annexed at any time.").row() + if (mayAnnex) addGoodSizedLabel("A puppeted city can be annexed at any time.").row() } private fun addLiberateOption(foundingCiv: String, liberateAction: () -> Unit) { @@ -456,18 +468,22 @@ class AlertPopup( addGoodSizedLabel("Liberating a city returns it to its original owner, giving you a massive relationship boost with them!") } - private fun addRazeOption(canRaze: () -> Boolean, razeAction: () -> Unit) { + private fun addRazeOption(canRaze: Boolean, mayAnnex: Boolean, razeAction: () -> Unit) { val button = "Raze".toTextButton() button.apply { - if (!canRaze()) disable() + if (!canRaze) disable() else { onActivation { razeAction() } keyShortcuts.add('r') } } add(button).row() - if (canRaze()) { - addGoodSizedLabel("Razing the city annexes it, and starts burning the city to the ground.").row() + if (canRaze) { + if (mayAnnex) { + addGoodSizedLabel("Razing the city annexes it, and starts burning the city to the ground.").row() + } else { + addGoodSizedLabel("Razing the city puppets it, and starts burning the city to the ground.").row() + } addGoodSizedLabel("The population will gradually dwindle until the city is destroyed.").row() } else { addGoodSizedLabel("Original capitals and holy cities cannot be razed.").row() diff --git a/docs/Modders/uniques.md b/docs/Modders/uniques.md index 5673736744..4d3a14f5bc 100644 --- a/docs/Modders/uniques.md +++ b/docs/Modders/uniques.md @@ -863,6 +863,9 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl ??? example "Will not be chosen for new games" Applicable to: Nation +??? example "May not annex cities" + Applicable to: Nation + ??? example "Starts with [tech]" Example: "Starts with [Agriculture]"