diff --git a/core/src/com/unciv/logic/battle/Battle.kt b/core/src/com/unciv/logic/battle/Battle.kt index d6f0627bc9..da63b5cccd 100644 --- a/core/src/com/unciv/logic/battle/Battle.kt +++ b/core/src/com/unciv/logic/battle/Battle.kt @@ -580,11 +580,11 @@ object Battle { return null } - fun destroyIfDefeated(attackedCiv: Civilization, attacker: Civilization) { + fun destroyIfDefeated(attackedCiv: Civilization, attacker: Civilization, notificationLocation: Vector2? = null) { if (attackedCiv.isDefeated()) { if (attackedCiv.isCityState()) attackedCiv.cityStateFunctions.cityStateDestroyed(attacker) - attackedCiv.destroy() + attackedCiv.destroy(notificationLocation) attacker.popupAlerts.add(PopupAlert(AlertType.Defeated, attackedCiv.civName)) } } diff --git a/core/src/com/unciv/logic/battle/Nuke.kt b/core/src/com/unciv/logic/battle/Nuke.kt index 80bac816c7..e7288f4b48 100644 --- a/core/src/com/unciv/logic/battle/Nuke.kt +++ b/core/src/com/unciv/logic/battle/Nuke.kt @@ -218,7 +218,7 @@ object Nuke { buildingModifier = city.getAggregateModifier(UniqueType.GarrisonDamageFromNukes) doNukeExplosionDamageToCity(city, nukeStrength, damageModifierFromMissingResource) Battle.postBattleNotifications(attacker, CityCombatant(city), city.getCenterTile()) - Battle.destroyIfDefeated(city.civ, attacker.getCivInfo()) + Battle.destroyIfDefeated(city.civ, attacker.getCivInfo(), city.location) } // Damage and/or destroy units on the tile diff --git a/core/src/com/unciv/logic/city/managers/CityConquestFunctions.kt b/core/src/com/unciv/logic/city/managers/CityConquestFunctions.kt index c65ef7e834..9ae3d8ce9d 100644 --- a/core/src/com/unciv/logic/city/managers/CityConquestFunctions.kt +++ b/core/src/com/unciv/logic/city/managers/CityConquestFunctions.kt @@ -90,7 +90,7 @@ class CityConquestFunctions(val city: City) { city.moveToCiv(receivingCiv) - Battle.destroyIfDefeated(conqueredCiv, conqueringCiv) + Battle.destroyIfDefeated(conqueredCiv, conqueringCiv, city.location) city.health = city.getMaxHealth() / 2 // I think that cities recover to half health when conquered? if (city.population.population > 1) diff --git a/core/src/com/unciv/logic/civilization/Civilization.kt b/core/src/com/unciv/logic/civilization/Civilization.kt index c61e9df89d..2dff2717f3 100644 --- a/core/src/com/unciv/logic/civilization/Civilization.kt +++ b/core/src/com/unciv/logic/civilization/Civilization.kt @@ -801,11 +801,24 @@ class Civilization : IsPartOfGameInfoSerialization { newCity.cityConstructions.chooseNextConstruction() } - fun destroy() { + /** Destroy what's left of a Civilization + * + * - function expects cities.isEmpty() + * - remaining units are destroyed and diplomacy cleaned up + * @param notificationLocation if given *and* the civ receiving the notification can see the tile or knows there was a city there, then the notification can show this location on click + */ + // At the moment, the "last unit down" callers do not pass a location, the city ones do - because the former isn't interesting + fun destroy(notificationLocation: Vector2? = null) { val destructionText = if (isMajorCiv()) "The civilization of [$civName] has been destroyed!" - else "The City-State of [$civName] has been destroyed!" - for (civ in gameInfo.civilizations) - civ.addNotification(destructionText, NotificationCategory.General, civName, NotificationIcon.Death) + else "The City-State of [$civName] has been destroyed!" + for (civ in gameInfo.civilizations) { + if (civ.isDefeated()) continue // addNotification will ignore barbarians and other AI + val location = notificationLocation?.takeIf { + val tile = gameInfo.tileMap[notificationLocation] + tile.isVisible(civ) || tile.isExplored(civ) && tile.getShownImprovement(civ) == Constants.cityCenter + } + civ.addNotification(destructionText, LocationAction(location), NotificationCategory.General, civName, NotificationIcon.Death) + } units.getCivUnits().forEach { it.destroy() } tradeRequests.clear() // if we don't do this then there could be resources taken by "pending" trades forever for (diplomacyManager in diplomacy.values) { diff --git a/core/src/com/unciv/logic/civilization/diplomacy/CityStateFunctions.kt b/core/src/com/unciv/logic/civilization/diplomacy/CityStateFunctions.kt index edd0a9e817..4085bc8a80 100644 --- a/core/src/com/unciv/logic/civilization/diplomacy/CityStateFunctions.kt +++ b/core/src/com/unciv/logic/civilization/diplomacy/CityStateFunctions.kt @@ -312,13 +312,14 @@ class CityStateFunctions(val civInfo: Civilization) { return otherCiv.addGold(-getDiplomaticMarriageCost()) + val notificationLocation = civInfo.getCapital()!!.location otherCiv.addNotification("We have married into the ruling family of [${civInfo.civName}], bringing them under our control.", - civInfo.getCapital()!!.location, + notificationLocation, NotificationCategory.Diplomacy, civInfo.civName, NotificationIcon.Diplomacy, otherCiv.civName) for (civ in civInfo.gameInfo.civilizations.filter { it != otherCiv }) civ.addNotification("[${otherCiv.civName}] has married into the ruling family of [${civInfo.civName}], bringing them under their control.", - civInfo.getCapital()!!.location, + notificationLocation, NotificationCategory.Diplomacy, civInfo.civName, NotificationIcon.Diplomacy, otherCiv.civName) for (unit in civInfo.units.getCivUnits()) @@ -336,7 +337,7 @@ class CityStateFunctions(val civInfo: Civilization) { city.moveToCiv(otherCiv) city.isPuppet = true // Human players get a popup that allows them to annex instead } - civInfo.destroy() + civInfo.destroy(notificationLocation) } fun getTributeWillingness(demandingCiv: Civilization, demandingWorker: Boolean = false): Int {