Resolves #12057 - Can go to war with no warmongering penalties if allied or protected city-states have been attacked

This commit is contained in:
yairm210
2024-08-04 14:06:11 +03:00
parent 3401eb6fda
commit 97e4695ba6
47 changed files with 335 additions and 60 deletions

View File

@ -19,6 +19,7 @@ enum class AlertType : IsPartOfGameInfoSerialization {
DiplomaticMarriage,
BulliedProtectedMinor,
AttackedProtectedMinor,
AttackedAllyMinor,
RecapturedCivilian,
GameHasBeenWon,
Event

View File

@ -44,7 +44,7 @@ class CityStateFunctions(val civInfo: Civilization) {
uniqueTypes.addAll(cityStateType.allyBonusUniqueMap.getAllUniques().mapNotNull { it.type })
// CS Personality
civInfo.cityStatePersonality = CityStatePersonality.entries.toTypedArray().random()
civInfo.cityStatePersonality = CityStatePersonality.entries.random()
// Mercantile bonus resources
@ -674,6 +674,25 @@ class CityStateFunctions(val civInfo: Civilization) {
) // we need to pass both civs as argument, hence the horrible chimera
}
// Even if we aren't *technically* protectors, we *can* still be pissed you attacked our allies*
val allyCivName = civInfo.getAllyCiv()
val allyCiv = if (allyCivName != null) civInfo.gameInfo.getCivilization(allyCivName) else null
if (allyCiv != null && allyCiv !in civInfo.cityStateFunctions.getProtectorCivs()){
val allyDiplomacy = allyCiv.getDiplomacyManager(attacker)!!
// Less than if we were protectors
allyDiplomacy.addModifier(DiplomaticModifiers.AttackedAlliedMinor, -10f)
if (allyCiv.playerType != PlayerType.Human) // Humans can have their own emotions
attacker.addNotification("[${allyCiv.civName}] is upset that you attacked [${civInfo.civName}], whom they are allied with!",
NotificationCategory.Diplomacy, NotificationIcon.Diplomacy, allyCiv.civName)
else // Let humans choose who to side with
allyCiv.popupAlerts.add(
PopupAlert(
AlertType.AttackedAllyMinor,
attacker.civName + "@" + civInfo.civName)
)
}
// Set up war with major pseudo-quest
civInfo.questManager.wasAttackedBy(attacker)
civInfo.getDiplomacyManager(attacker)!!.setFlag(DiplomacyFlags.RecentlyAttacked, 2) // Reminder to ask for unit gifts in 2 turns

View File

@ -80,25 +80,26 @@ object DeclareWar {
NotificationCategory.Diplomacy, otherCiv.civName, NotificationIcon.War, civInfo.civName)
}
}
WarType.DefensivePactWar, WarType.CityStateAllianceWar, WarType.JoinWar -> {
WarType.DefensivePactWar, WarType.CityStateAllianceWar, WarType.JoinWar,
WarType.ProtectedCityStateWar, WarType.AlliedCityStateWar -> {
val allyCiv = declareWarReason.allyCiv!!
otherCiv.popupAlerts.add(PopupAlert(AlertType.WarDeclaration, civInfo.civName))
val agressor = if (declareWarReason.warType == WarType.DefensivePactWar) otherCiv else civInfo
val aggressor = if (declareWarReason.warType == WarType.DefensivePactWar) otherCiv else civInfo
val defender = if (declareWarReason.warType == WarType.DefensivePactWar) civInfo else otherCiv
defender.addNotification("[${agressor.civName}] has joined [${allyCiv.civName}] in the war against us!",
NotificationCategory.Diplomacy, defender.civName, NotificationIcon.War, allyCiv.civName, agressor.civName)
defender.addNotification("[${aggressor.civName}] has joined [${allyCiv.civName}] in the war against us!",
NotificationCategory.Diplomacy, defender.civName, NotificationIcon.War, allyCiv.civName, aggressor.civName)
agressor.addNotification("We have joined [${allyCiv.civName}] in the war against [${defender.civName}]!",
NotificationCategory.Diplomacy, defender.civName, NotificationIcon.War, allyCiv.civName, agressor.civName)
aggressor.addNotification("We have joined [${allyCiv.civName}] in the war against [${defender.civName}]!",
NotificationCategory.Diplomacy, defender.civName, NotificationIcon.War, allyCiv.civName, aggressor.civName)
diplomacyManager.getCommonKnownCivsWithSpectators().filterNot { it == allyCiv }.forEach {
it.addNotification("[${agressor.civName}] has joined [${allyCiv.civName}] in the war against [${defender.civName}]!",
NotificationCategory.Diplomacy, defender.civName, NotificationIcon.War, allyCiv.civName, agressor.civName)
it.addNotification("[${aggressor.civName}] has joined [${allyCiv.civName}] in the war against [${defender.civName}]!",
NotificationCategory.Diplomacy, defender.civName, NotificationIcon.War, allyCiv.civName, aggressor.civName)
}
allyCiv.addNotification("[${agressor.civName}] has joined us in the war against [${defender.civName}]!",
NotificationCategory.Diplomacy, defender.civName, NotificationIcon.War, allyCiv.civName, agressor.civName)
allyCiv.addNotification("[${aggressor.civName}] has joined us in the war against [${defender.civName}]!",
NotificationCategory.Diplomacy, defender.civName, NotificationIcon.War, allyCiv.civName, aggressor.civName)
}
WarType.TeamWar -> {
val allyCiv = declareWarReason.allyCiv!!
@ -335,6 +336,10 @@ enum class WarType {
JoinWar,
/** Two civilizations are starting a war through a trade. */
TeamWar,
/** Someone attacked our protected city-state */
ProtectedCityStateWar,
/** Someone attacked our allied city-state */
AlliedCityStateWar
}
/**

View File

@ -90,6 +90,7 @@ enum class DiplomaticModifiers(val text: String) {
StealingTerritory("You have stolen our lands!"),
DestroyedProtectedMinor("You destroyed City-States that were under our protection!"),
AttackedProtectedMinor("You attacked City-States that were under our protection!"),
AttackedAlliedMinor("You attacked our allied City-States!"),
BulliedProtectedMinor("You demanded tribute from City-States that were under our protection!"),
SidedWithProtectedMinor("You sided with a City-State over us"),
SpiedOnUs("You spied on us!"),
@ -395,7 +396,8 @@ class DiplomacyManager() : IsPartOfGameInfoSerialization {
fun canDeclareWar() = !civInfo.isDefeated() && !otherCiv().isDefeated()
&& turnsToPeaceTreaty() == 0 && diplomaticStatus != DiplomaticStatus.War
fun declareWar(declareWarReason: DeclareWarReason = DeclareWarReason(WarType.DirectWar)) = DeclareWar.declareWar(this, declareWarReason)
fun declareWar(declareWarReason: DeclareWarReason = DeclareWarReason(WarType.DirectWar)) =
DeclareWar.declareWar(this, declareWarReason)
//Used for nuke
fun canAttack() = turnsToPeaceTreaty() == 0

View File

@ -15,9 +15,7 @@ import com.unciv.logic.civilization.LocationAction
import com.unciv.logic.civilization.NotificationCategory
import com.unciv.logic.civilization.NotificationIcon
import com.unciv.logic.civilization.PopupAlert
import com.unciv.logic.civilization.diplomacy.DiplomacyFlags
import com.unciv.logic.civilization.diplomacy.DiplomaticModifiers
import com.unciv.logic.civilization.diplomacy.RelationshipLevel
import com.unciv.logic.civilization.diplomacy.*
import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.models.translations.fillPlaceholders
import com.unciv.models.translations.tr
@ -100,7 +98,7 @@ class AlertPopup(
AlertType.DeclarationOfFriendship -> addDeclarationOfFriendship()
AlertType.StartIntro -> addStartIntro()
AlertType.DiplomaticMarriage -> addDiplomaticMarriage()
AlertType.BulliedProtectedMinor, AlertType.AttackedProtectedMinor -> addBulliedOrAttackedProtectedMinor()
AlertType.BulliedProtectedMinor, AlertType.AttackedProtectedMinor, AlertType.AttackedAllyMinor -> addBulliedOrAttackedProtectedOrAlliedMinor()
AlertType.RecapturedCivilian -> skipThisAlert = addRecapturedCivilian()
AlertType.GameHasBeenWon -> addGameHasBeenWon()
AlertType.Event -> skipThisAlert = !addEvent()
@ -118,7 +116,7 @@ class AlertPopup(
addCloseButton("Never!", KeyboardBinding.Cancel)
}
private fun addBulliedOrAttackedProtectedMinor() {
private fun addBulliedOrAttackedProtectedOrAlliedMinor() {
val involvedCivs = popupAlert.value.split('@')
val bullyOrAttacker = getCiv(involvedCivs[0])
val cityState = getCiv(involvedCivs[1])
@ -132,15 +130,23 @@ class AlertPopup(
popupAlert.type == AlertType.BulliedProtectedMinor -> // Nasty message
"We asked [${cityState.civName}] for a tribute recently and they gave in.\nYou promised to protect them from such things, but we both know you cannot back that up."
isAtLeastNeutral -> // Nice message
"It's come to my attention that I may have attacked [${cityState.civName}], a city-state under your protection.\nWhile it was not my goal to be at odds with your empire, this was deemed a necessary course of action."
"It's come to my attention that I may have attacked [${cityState.civName}].\nWhile it was not my goal to be at odds with your empire, this was deemed a necessary course of action."
else -> // Nasty message
"I thought you might like to know that I've launched an invasion of one of your little pet states.\nThe lands of [${cityState.civName}] will make a fine addition to my own."
}
addGoodSizedLabel(text).row()
addCloseButton("THIS MEANS WAR!", KeyboardBinding.Confirm) {
player.getDiplomacyManager(bullyOrAttacker)!!.sideWithCityState()
val warReason = if (popupAlert.type == AlertType.AttackedAllyMinor) WarType.AlliedCityStateWar else WarType.ProtectedCityStateWar
player.getDiplomacyManager(bullyOrAttacker)!!.declareWar(DeclareWarReason(warReason, cityState))
cityState.getDiplomacyManager(player)!!.influence += 20f // You went to war for us!!
}.row()
addCloseButton("You'll pay for this!", KeyboardBinding.Confirm) {
player.getDiplomacyManager(bullyOrAttacker)!!.sideWithCityState()
}.row()
addCloseButton("Very well.", KeyboardBinding.Cancel) {
player.addNotification("You have broken your Pledge to Protect [${cityState.civName}]!",
cityState.cityStateFunctions.getNotificationActions(), NotificationCategory.Diplomacy, cityState.civName)