From 090c421f9bc97134538300da3f5bf3080841a234 Mon Sep 17 00:00:00 2001 From: Yair Morgenstern Date: Sun, 26 Feb 2023 20:31:08 +0200 Subject: [PATCH] Introduced "upon defeating [unitFilter] unit" trigger --- core/src/com/unciv/logic/battle/Battle.kt | 14 +++++++++++ .../com/unciv/logic/map/mapunit/MapUnit.kt | 5 ++++ .../unciv/logic/map/mapunit/UnitPromotions.kt | 8 ++++--- .../ruleset/unique/StateForConditionals.kt | 2 +- .../unciv/models/ruleset/unique/UniqueType.kt | 14 +++++++---- docs/Modders/uniques.md | 23 +++++++++++-------- 6 files changed, 49 insertions(+), 17 deletions(-) diff --git a/core/src/com/unciv/logic/battle/Battle.kt b/core/src/com/unciv/logic/battle/Battle.kt index b46bdf0573..5acf75fc4b 100644 --- a/core/src/com/unciv/logic/battle/Battle.kt +++ b/core/src/com/unciv/logic/battle/Battle.kt @@ -149,14 +149,28 @@ object Battle { if (!defender.isDefeated() && defender is MapUnitCombatant && defender.unit.isExploring()) defender.unit.action = null + fun triggerUniques(ourUnit:MapUnitCombatant, enemy:MapUnitCombatant){ + val stateForConditionals = StateForConditionals(civInfo = ourUnit.getCivInfo(), + ourCombatant = ourUnit, theirCombatant=enemy, tile = attackedTile) + for (unique in ourUnit.unit.getTriggeredUniques(UniqueType.TriggerUponDefeatingUnit, stateForConditionals)) + if (unique.conditionals.any { it.type == UniqueType.TriggerUponDefeatingUnit + && enemy.unit.matchesFilter(it.params[0]) }) + UniqueTriggerActivation.triggerUnitwideUnique(unique, ourUnit.unit) + } + // Add culture when defeating a barbarian when Honor policy is adopted, gold from enemy killed when honor is complete // or any enemy military unit with Sacrificial captives unique (can be either attacker or defender!) if (defender.isDefeated() && defender is MapUnitCombatant && !defender.unit.isCivilian()) { tryEarnFromKilling(attacker, defender) tryHealAfterKilling(attacker) + + if (attacker is MapUnitCombatant) triggerUniques(attacker, defender) + } else if (attacker.isDefeated() && attacker is MapUnitCombatant && !attacker.unit.isCivilian()) { tryEarnFromKilling(defender, attacker) tryHealAfterKilling(defender) + + if (defender is MapUnitCombatant) triggerUniques(defender, attacker) } if (attacker is MapUnitCombatant) { diff --git a/core/src/com/unciv/logic/map/mapunit/MapUnit.kt b/core/src/com/unciv/logic/map/mapunit/MapUnit.kt index 9c5165c392..d387eb85b6 100644 --- a/core/src/com/unciv/logic/map/mapunit/MapUnit.kt +++ b/core/src/com/unciv/logic/map/mapunit/MapUnit.kt @@ -425,6 +425,11 @@ class MapUnit : IsPartOfGameInfoSerialization { updateUniques() } + fun getTriggeredUniques(trigger: UniqueType, + stateForConditionals: StateForConditionals = StateForConditionals(civInfo = civ, unit = this)): Sequence { + return getUniques().filter { it.conditionals.any { it.type == trigger } && it.conditionalsApply(stateForConditionals) } + } + fun useMovementPoints(amount: Float) { turnsFortified = 0 currentMovement -= amount diff --git a/core/src/com/unciv/logic/map/mapunit/UnitPromotions.kt b/core/src/com/unciv/logic/map/mapunit/UnitPromotions.kt index 14e9814434..6dc2c87777 100644 --- a/core/src/com/unciv/logic/map/mapunit/UnitPromotions.kt +++ b/core/src/com/unciv/logic/map/mapunit/UnitPromotions.kt @@ -2,6 +2,7 @@ package com.unciv.logic.map.mapunit import com.unciv.logic.IsPartOfGameInfoSerialization import com.unciv.models.ruleset.unique.StateForConditionals +import com.unciv.models.ruleset.unique.UniqueTarget import com.unciv.models.ruleset.unique.UniqueTriggerActivation import com.unciv.models.ruleset.unique.UniqueType import com.unciv.models.ruleset.unit.Promotion @@ -84,9 +85,10 @@ class UnitPromotions : IsPartOfGameInfoSerialization { } private fun doDirectPromotionEffects(promotion: Promotion) { - for (unique in promotion.uniqueObjects) { - UniqueTriggerActivation.triggerUnitwideUnique(unique, unit) - } + for (unique in promotion.uniqueObjects) + if (unique.conditionalsApply(StateForConditionals(civInfo = unit.civ, unit = unit)) + && unique.conditionals.none { it.type?.targetTypes?.contains(UniqueTarget.TriggerCondition) == true }) + UniqueTriggerActivation.triggerUnitwideUnique(unique, unit) } /** Gets all promotions this unit could currently "buy" with enough [XP] diff --git a/core/src/com/unciv/models/ruleset/unique/StateForConditionals.kt b/core/src/com/unciv/models/ruleset/unique/StateForConditionals.kt index d78ad19795..6704982c38 100644 --- a/core/src/com/unciv/models/ruleset/unique/StateForConditionals.kt +++ b/core/src/com/unciv/models/ruleset/unique/StateForConditionals.kt @@ -4,9 +4,9 @@ import com.unciv.logic.battle.CombatAction import com.unciv.logic.battle.ICombatant import com.unciv.logic.city.City import com.unciv.logic.civilization.Civilization +import com.unciv.logic.map.mapgenerator.Region import com.unciv.logic.map.mapunit.MapUnit import com.unciv.logic.map.tile.Tile -import com.unciv.logic.map.mapgenerator.Region data class StateForConditionals( val civInfo: Civilization? = null, diff --git a/core/src/com/unciv/models/ruleset/unique/UniqueType.kt b/core/src/com/unciv/models/ruleset/unique/UniqueType.kt index 81add22b5b..7cabea0ac5 100644 --- a/core/src/com/unciv/models/ruleset/unique/UniqueType.kt +++ b/core/src/com/unciv/models/ruleset/unique/UniqueType.kt @@ -689,11 +689,11 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags: OneTimeGlobalAlert("Triggers the following global alert: [comment]", UniqueTarget.Policy), // used in Policy OneTimeGlobalSpiesWhenEnteringEra("Every major Civilization gains a spy once a civilization enters this era", UniqueTarget.Era), - OneTimeUnitHeal("Heal this unit by [amount] HP", UniqueTarget.Promotion), - OneTimeUnitGainXP("This Unit gains [amount] XP", UniqueTarget.Ruins), - OneTimeUnitUpgrade("This Unit upgrades for free", UniqueTarget.Global), // Not used in Vanilla + OneTimeUnitHeal("Heal this unit by [amount] HP", UniqueTarget.Unit), + OneTimeUnitGainXP("This Unit gains [amount] XP", UniqueTarget.Ruins, UniqueTarget.Unit), + OneTimeUnitUpgrade("This Unit upgrades for free", UniqueTarget.Global, UniqueTarget.Unit), // Not used in Vanilla OneTimeUnitSpecialUpgrade("This Unit upgrades for free including special upgrades", UniqueTarget.Ruins), - OneTimeUnitGainPromotion("This Unit gains the [promotion] promotion", UniqueTarget.Triggerable), // Not used in Vanilla + OneTimeUnitGainPromotion("This Unit gains the [promotion] promotion", UniqueTarget.Triggerable, UniqueTarget.Unit), // Not used in Vanilla SkipPromotion("Doing so will consume this opportunity to choose a Promotion", UniqueTarget.Promotion), UnitsGainPromotion("[mapUnitFilter] units gain the [promotion] promotion", UniqueTarget.Triggerable), // Not used in Vanilla @@ -723,6 +723,12 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags: TriggerUponFoundingReligion("upon founding a Religion", UniqueTarget.TriggerCondition), TriggerUponEnhancingReligion("upon enhancing a Religion", UniqueTarget.TriggerCondition), + //endregion + + + ///////////////////////////////////////// region UNIT TRIGGERS ///////////////////////////////////////// + + TriggerUponDefeatingUnit("upon defeating a [mapUnitFilter] unit", UniqueTarget.TriggerCondition), //endregion diff --git a/docs/Modders/uniques.md b/docs/Modders/uniques.md index 7eed5c262a..1eec919c4b 100644 --- a/docs/Modders/uniques.md +++ b/docs/Modders/uniques.md @@ -80,7 +80,7 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl ??? example "This Unit gains the [promotion] promotion" Example: "This Unit gains the [Shock I] promotion" - Applicable to: Triggerable + Applicable to: Triggerable, Unit ??? example "[mapUnitFilter] units gain the [promotion] promotion" Example: "[Wounded] units gain the [Shock I] promotion" @@ -814,7 +814,7 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl Applicable to: Global, Unit ??? example "This Unit upgrades for free" - Applicable to: Global + Applicable to: Global, Unit ## Nation uniques ??? example "Will not be chosen for new games" @@ -1300,12 +1300,17 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl Applicable to: Unit -## Promotion uniques ??? example "Heal this unit by [amount] HP" Example: "Heal this unit by [3] HP" - Applicable to: Promotion + Applicable to: Unit +??? example "This Unit gains [amount] XP" + Example: "This Unit gains [3] XP" + + Applicable to: Unit, Ruins + +## Promotion uniques ??? example "Doing so will consume this opportunity to choose a Promotion" Applicable to: Promotion @@ -1612,11 +1617,6 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl Applicable to: Ruins -??? example "This Unit gains [amount] XP" - Example: "This Unit gains [3] XP" - - Applicable to: Ruins - ??? example "This Unit upgrades for free including special upgrades" Applicable to: Ruins @@ -1944,6 +1944,11 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl ??? example "<upon enhancing a Religion>" Applicable to: TriggerCondition +??? example "<upon defeating a [unitFilter] unit>" + Example: "<upon defeating a [Unknown] unit>" + + Applicable to: TriggerCondition + *[action]: An action that a unit can perform. Currently, there are only two actions part of this: 'Spread Religion' and 'Remove Foreign religions from your own cities' *[amount]: This indicates a whole number, possibly with a + or - sign, such as `2`, `+13`, or `-3`.