From cd1f3985fdafd2c5825541f2a8083c194a5b3fbf Mon Sep 17 00:00:00 2001
From: xenohedron <12538125+xenohedron@users.noreply.github.com>
Date: Sun, 9 Nov 2025 23:13:29 -0500
Subject: [PATCH 01/14] add test cases (not depending on lifelink)
---
.../damage/DamageMultiTriggerTest.java | 188 ++++++++++++++++++
1 file changed, 188 insertions(+)
create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/triggers/damage/DamageMultiTriggerTest.java
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/damage/DamageMultiTriggerTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/damage/DamageMultiTriggerTest.java
new file mode 100644
index 00000000000..ced360b10bf
--- /dev/null
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/damage/DamageMultiTriggerTest.java
@@ -0,0 +1,188 @@
+package org.mage.test.cards.triggers.damage;
+
+import mage.constants.PhaseStep;
+import mage.constants.Zone;
+import mage.counters.CounterType;
+import org.junit.Test;
+import org.mage.test.serverside.base.CardTestPlayerBase;
+
+/**
+ * @author xenohedron
+ */
+public class DamageMultiTriggerTest extends CardTestPlayerBase {
+
+ private static final String hatchling = "Kraken Hatchling"; // 0/4
+ private static final String wishcoin = "Wishcoin Crab"; // 2/5
+
+ private static final String brothers = "Brothers of Fire"; // 2/2
+ // 1RR: 1 dmg to any target and 1 dmg to you
+ private static final String embermage = "Reckless Embermage"; // 2/2
+ // 1R: 1 dmg to any target and 1 dmg to itself
+
+ private static final String arc = "Arc Trail";
+ // Arc Trail deals 2 damage to any target and 1 damage to another target.
+ private static final String cone = "Cone of Flame";
+ // Cone of Flame deals 1 damage to any target, 2 damage to another target, and 3 damage to a third target.
+ private static final String chaar = "Char";
+ // Char deals 4 damage to any target and 2 damage to you.
+ private static final String outrage = "Chandra's Outrage";
+ // Chandra's Outrage deals 4 damage to target creature and 2 damage to that creature's controller.
+ private static final String fury = "Chandra's Fury";
+ // Chandra's Fury deals 4 damage to target player or planeswalker
+ // and 1 damage to each creature that player or that planeswalker's controller controls.
+
+ private static final String tamanoa = "Tamanoa"; // 2/4
+ // Whenever a noncreature source you control deals damage, you gain that much life.
+ private static final String spiritLink = "Spirit Link"; // 2/2
+ // Whenever enchanted creature deals damage, you gain that much life.
+ private static final String pridemate = "Ajani's Pridemate"; // 2/2
+ // Whenever you gain life, put a +1/+1 counter on this creature.
+
+ private void setupBattlefield() {
+ addCard(Zone.BATTLEFIELD, playerA, "Plateau", 5);
+ addCard(Zone.BATTLEFIELD, playerA, tamanoa);
+ addCard(Zone.HAND, playerA, spiritLink);
+ addCard(Zone.BATTLEFIELD, playerA, pridemate);
+ addCard(Zone.BATTLEFIELD, playerA, hatchling);
+ addCard(Zone.BATTLEFIELD, playerB, wishcoin);
+ }
+
+ @Test
+ public void testCreatureDamageTargetAndYou() {
+ setupBattlefield();
+ addCard(Zone.BATTLEFIELD, playerA, brothers);
+
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, spiritLink, brothers);
+ waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
+ activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}{R}{R}: ");
+ addTarget(playerA, wishcoin);
+
+ setStrictChooseMode(true);
+ setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
+ execute();
+
+ assertLife(playerA, 20 - 1 + 2);
+ assertLife(playerB, 20);
+ assertDamageReceived(playerB, wishcoin, 1);
+ assertCounterCount(pridemate, CounterType.P1P1, 1);
+ }
+
+ @Test
+ public void testCreatureDamageTargetAndSelf() {
+ setupBattlefield();
+ addCard(Zone.BATTLEFIELD, playerA, embermage);
+
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, spiritLink, embermage);
+ waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
+ activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}{R}: ");
+ addTarget(playerA, wishcoin);
+
+ setStrictChooseMode(true);
+ setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
+ execute();
+
+ assertLife(playerA, 20 + 2);
+ assertLife(playerB, 20);
+ assertDamageReceived(playerB, wishcoin, 1);
+ assertDamageReceived(playerA, embermage, 1);
+ assertCounterCount(pridemate, CounterType.P1P1, 1);
+ }
+
+ @Test
+ public void testSpellDamageTargetAndTarget() {
+ setupBattlefield();
+ addCard(Zone.HAND, playerA, arc);
+
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, arc);
+ addTarget(playerA, wishcoin);
+ addTarget(playerA, hatchling);
+
+ setStrictChooseMode(true);
+ setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
+ execute();
+
+ assertLife(playerA, 20 + 3);
+ assertLife(playerB, 20);
+ assertDamageReceived(playerB, wishcoin, 2);
+ assertDamageReceived(playerA, hatchling, 1);
+ assertCounterCount(pridemate, CounterType.P1P1, 1);
+ }
+
+ @Test
+ public void testSpellDamageThreeTargets() {
+ setupBattlefield();
+ addCard(Zone.HAND, playerA, cone);
+
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, cone);
+ addTarget(playerA, wishcoin);
+ addTarget(playerA, hatchling);
+ addTarget(playerA, tamanoa);
+
+ setStrictChooseMode(true);
+ setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
+ execute();
+
+ assertLife(playerA, 20 + 6);
+ assertLife(playerB, 20);
+ assertDamageReceived(playerB, wishcoin, 1);
+ assertDamageReceived(playerA, hatchling, 2);
+ assertDamageReceived(playerA, tamanoa, 3);
+ assertCounterCount(pridemate, CounterType.P1P1, 1);
+ }
+
+ @Test
+ public void testSpellDamageTargetAndYou() {
+ setupBattlefield();
+ addCard(Zone.HAND, playerA, chaar);
+
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, chaar);
+ addTarget(playerA, wishcoin);
+
+ setStrictChooseMode(true);
+ setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
+ execute();
+
+ assertLife(playerA, 20 - 2 + 6);
+ assertLife(playerB, 20);
+ assertDamageReceived(playerB, wishcoin, 4);
+ assertCounterCount(pridemate, CounterType.P1P1, 1);
+ }
+
+ @Test
+ public void testSpellDamageTargetAndController() {
+ setupBattlefield();
+ addCard(Zone.HAND, playerA, outrage);
+
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, outrage);
+ addTarget(playerA, wishcoin);
+
+ setStrictChooseMode(true);
+ setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
+ execute();
+
+ assertLife(playerA, 20 + 6);
+ assertLife(playerB, 20 - 2);
+ assertDamageReceived(playerB, wishcoin, 4);
+ assertCounterCount(pridemate, CounterType.P1P1, 1);
+ }
+
+
+ @Test
+ public void testSpellDamagePlayerAndControlled() {
+ setupBattlefield();
+ addCard(Zone.HAND, playerA, fury);
+
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, fury);
+ addTarget(playerA, playerB);
+
+ setStrictChooseMode(true);
+ setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
+ execute();
+
+ assertLife(playerA, 20 + 5);
+ assertLife(playerB, 20 - 4);
+ assertDamageReceived(playerB, wishcoin, 1);
+ assertCounterCount(pridemate, CounterType.P1P1, 1);
+ }
+
+}
From 06c51bd829252a568036d7a612128cd981b21892 Mon Sep 17 00:00:00 2001
From: xenohedron <12538125+xenohedron@users.noreply.github.com>
Date: Sun, 9 Nov 2025 23:18:23 -0500
Subject: [PATCH 02/14] update to check damage batch by source
---
Mage.Sets/src/mage/cards/s/Spiritualize.java | 3 +--
.../abilities/common/DealsDamageAttachedTriggeredAbility.java | 3 +--
2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/Mage.Sets/src/mage/cards/s/Spiritualize.java b/Mage.Sets/src/mage/cards/s/Spiritualize.java
index 143b0e2ac33..01b32b45836 100644
--- a/Mage.Sets/src/mage/cards/s/Spiritualize.java
+++ b/Mage.Sets/src/mage/cards/s/Spiritualize.java
@@ -62,8 +62,7 @@ class SpiritualizeTriggeredAbility extends DelayedTriggeredAbility {
@Override
public boolean checkEventType(GameEvent event, Game game) {
- return event.getType() == GameEvent.EventType.DAMAGED_PLAYER
- || event.getType() == GameEvent.EventType.DAMAGED_PERMANENT;
+ return event.getType() == GameEvent.EventType.DAMAGED_BATCH_BY_SOURCE;
}
@Override
diff --git a/Mage/src/main/java/mage/abilities/common/DealsDamageAttachedTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/DealsDamageAttachedTriggeredAbility.java
index a1f6f9c286f..532c2ea65e1 100644
--- a/Mage/src/main/java/mage/abilities/common/DealsDamageAttachedTriggeredAbility.java
+++ b/Mage/src/main/java/mage/abilities/common/DealsDamageAttachedTriggeredAbility.java
@@ -29,8 +29,7 @@ public class DealsDamageAttachedTriggeredAbility extends TriggeredAbilityImpl {
@Override
public boolean checkEventType(GameEvent event, Game game) {
- return event.getType() == GameEvent.EventType.DAMAGED_PERMANENT
- || event.getType() == GameEvent.EventType.DAMAGED_PLAYER;
+ return event.getType() == GameEvent.EventType.DAMAGED_BATCH_BY_SOURCE;
}
@Override
From 7a6dfb7a2f6c698ececea5096d1382089c11d0ff Mon Sep 17 00:00:00 2001
From: xenohedron <12538125+xenohedron@users.noreply.github.com>
Date: Sun, 9 Nov 2025 23:25:37 -0500
Subject: [PATCH 03/14] new DamageTargetAndTargetEffect
---
Mage.Sets/src/mage/cards/a/ArcTrail.java | 64 +----------------
.../common/DamageTargetAndTargetEffect.java | 68 +++++++++++++++++++
2 files changed, 71 insertions(+), 61 deletions(-)
create mode 100644 Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndTargetEffect.java
diff --git a/Mage.Sets/src/mage/cards/a/ArcTrail.java b/Mage.Sets/src/mage/cards/a/ArcTrail.java
index a85ec5afa8e..2a7a57ede4f 100644
--- a/Mage.Sets/src/mage/cards/a/ArcTrail.java
+++ b/Mage.Sets/src/mage/cards/a/ArcTrail.java
@@ -1,21 +1,14 @@
package mage.cards.a;
-import mage.abilities.Ability;
-import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.DamageTargetAndTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.Outcome;
import mage.filter.common.FilterAnyTarget;
import mage.filter.common.FilterPermanentOrPlayer;
import mage.filter.predicate.other.AnotherTargetPredicate;
-import mage.game.Game;
-import mage.game.permanent.Permanent;
-import mage.players.Player;
-import mage.target.Target;
import mage.target.common.TargetPermanentOrPlayer;
-import java.io.ObjectStreamException;
import java.util.UUID;
/**
@@ -34,8 +27,8 @@ public final class ArcTrail extends CardImpl {
public ArcTrail(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{R}");
- // Arc Trail deals 2 damage to any target and 1 damage to another any target
- this.getSpellAbility().addEffect(ArcTrailEffect.getInstance());
+ // Arc Trail deals 2 damage to any target and 1 damage to another target
+ this.getSpellAbility().addEffect(new DamageTargetAndTargetEffect(2, 1));
this.getSpellAbility().addTarget(new TargetPermanentOrPlayer(filter1).setTargetTag(1));
this.getSpellAbility().addTarget(new TargetPermanentOrPlayer(filter2).setTargetTag(2));
}
@@ -50,54 +43,3 @@ public final class ArcTrail extends CardImpl {
}
}
-
-class ArcTrailEffect extends OneShotEffect {
-
- private static final ArcTrailEffect instance = new ArcTrailEffect();
-
- private Object readResolve() throws ObjectStreamException {
- return instance;
- }
-
- public static ArcTrailEffect getInstance() {
- return instance;
- }
-
- private ArcTrailEffect() {
- super(Outcome.Damage);
- staticText = "{this} deals 2 damage to any target and 1 damage to another target";
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
-
- boolean applied = false;
- boolean twoDamageDone = false;
- int damage = 2;
-
- for (Target target : source.getTargets()) {
- Permanent permanent = game.getPermanent(target.getFirstTarget());
-
- if (twoDamageDone) {
- damage = 1;
- }
-
- if (permanent != null) {
- applied |= (permanent.damage(damage, source.getSourceId(), source, game, false, true) > 0);
- }
- Player player = game.getPlayer(target.getFirstTarget());
- if (player != null) {
- applied |= (player.damage(damage, source.getSourceId(), source, game) > 0);
- }
-
- twoDamageDone = true;
- }
- return applied;
- }
-
- @Override
- public ArcTrailEffect copy() {
- return instance;
- }
-
-}
diff --git a/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndTargetEffect.java
new file mode 100644
index 00000000000..2b9acbebcf2
--- /dev/null
+++ b/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndTargetEffect.java
@@ -0,0 +1,68 @@
+package mage.abilities.effects.common;
+
+import mage.abilities.Ability;
+import mage.abilities.Mode;
+import mage.abilities.effects.OneShotEffect;
+import mage.constants.Outcome;
+import mage.game.Game;
+import mage.game.permanent.Permanent;
+import mage.players.Player;
+
+import java.util.UUID;
+
+/**
+ * @author xenohedron
+ */
+public class DamageTargetAndTargetEffect extends OneShotEffect {
+
+ private final int firstAmount;
+ private final int secondAmount;
+
+ /**
+ * Deals simultaneous damage to two targets. Must set target tag 1 and 2
+ */
+ public DamageTargetAndTargetEffect(int firstAmount, int secondAmount) {
+ super(Outcome.Damage);
+ this.firstAmount = firstAmount;
+ this.secondAmount = secondAmount;
+ }
+
+ protected DamageTargetAndTargetEffect(final DamageTargetAndTargetEffect effect) {
+ super(effect);
+ this.firstAmount = effect.firstAmount;
+ this.secondAmount = effect.secondAmount;
+ }
+
+ @Override
+ public DamageTargetAndTargetEffect copy() {
+ return new DamageTargetAndTargetEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ source.getTargets().getByTag(1).getTargets().forEach(uuid -> damageTarget(uuid, firstAmount, source, game));
+ source.getTargets().getByTag(2).getTargets().forEach(uuid -> damageTarget(uuid, secondAmount, source, game));
+ return true;
+ }
+
+ private void damageTarget(UUID targetId, int amount, Ability source, Game game) {
+ Permanent permanent = game.getPermanent(targetId);
+ if (permanent != null) {
+ permanent.damage(amount, source.getSourceId(), source, game) ;
+ } else {
+ Player player = game.getPlayer(targetId);
+ if (player != null) {
+ player.damage(amount, source.getSourceId(), source, game);
+ }
+ }
+ }
+
+ @Override
+ public String getText(Mode mode) {
+ if (staticText != null && !staticText.isEmpty()) {
+ return staticText;
+ }
+ return "{this} deals " + firstAmount + "damage to " + mode.getTargets().getByTag(1).getDescription() +
+ " and " + secondAmount + "damage to " + mode.getTargets().getByTag(2).getDescription();
+ }
+}
From 9f663f2a23e0686321c0ce764acb4a90c3318a18 Mon Sep 17 00:00:00 2001
From: xenohedron <12538125+xenohedron@users.noreply.github.com>
Date: Sun, 9 Nov 2025 23:33:18 -0500
Subject: [PATCH 04/14] new DamageTargetAndYouEffect
---
.../src/mage/cards/b/BrothersOfFire.java | 14 +---
Mage.Sets/src/mage/cards/c/Char.java | 14 +---
.../common/DamageTargetAndYouEffect.java | 77 +++++++++++++++++++
3 files changed, 85 insertions(+), 20 deletions(-)
create mode 100644 Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndYouEffect.java
diff --git a/Mage.Sets/src/mage/cards/b/BrothersOfFire.java b/Mage.Sets/src/mage/cards/b/BrothersOfFire.java
index ba5e830dd35..98098bfe433 100644
--- a/Mage.Sets/src/mage/cards/b/BrothersOfFire.java
+++ b/Mage.Sets/src/mage/cards/b/BrothersOfFire.java
@@ -1,21 +1,18 @@
-
package mage.cards.b;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
-import mage.abilities.effects.Effect;
-import mage.abilities.effects.common.DamageControllerEffect;
-import mage.abilities.effects.common.DamageTargetEffect;
+import mage.abilities.effects.common.DamageTargetAndYouEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
-import mage.constants.Zone;
import mage.target.common.TargetAnyTarget;
+import java.util.UUID;
+
/**
*
* @author LoneFox
@@ -29,10 +26,7 @@ public final class BrothersOfFire extends CardImpl {
this.toughness = new MageInt(2);
// {1}{R}{R}: Brothers of Fire deals 1 damage to any target and 1 damage to you.
- Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(1), new ManaCostsImpl<>("{1}{R}{R}"));
- Effect effect = new DamageControllerEffect(1);
- effect.setText("and 1 damage to you");
- ability.addEffect(effect);
+ Ability ability = new SimpleActivatedAbility(new DamageTargetAndYouEffect(1), new ManaCostsImpl<>("{1}{R}{R}"));
ability.addTarget(new TargetAnyTarget());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/c/Char.java b/Mage.Sets/src/mage/cards/c/Char.java
index d3fb54b2f59..96fbde8965a 100644
--- a/Mage.Sets/src/mage/cards/c/Char.java
+++ b/Mage.Sets/src/mage/cards/c/Char.java
@@ -1,15 +1,13 @@
-
package mage.cards.c;
-import java.util.UUID;
-import mage.abilities.effects.Effect;
-import mage.abilities.effects.common.DamageControllerEffect;
-import mage.abilities.effects.common.DamageTargetEffect;
+import mage.abilities.effects.common.DamageTargetAndYouEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.target.common.TargetAnyTarget;
+import java.util.UUID;
+
/**
*
* @author LevelX2
@@ -19,13 +17,9 @@ public final class Char extends CardImpl {
public Char(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{R}");
-
// Char deals 4 damage to any target and 2 damage to you.
- this.getSpellAbility().addEffect(new DamageTargetEffect(4));
+ this.getSpellAbility().addEffect(new DamageTargetAndYouEffect(4, 2));
this.getSpellAbility().addTarget(new TargetAnyTarget());
- Effect effect = new DamageControllerEffect(2);
- effect.setText("and 2 damage to you");
- this.getSpellAbility().addEffect(effect);
}
private Char(final Char card) {
diff --git a/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndYouEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndYouEffect.java
new file mode 100644
index 00000000000..b1e874e845e
--- /dev/null
+++ b/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndYouEffect.java
@@ -0,0 +1,77 @@
+package mage.abilities.effects.common;
+
+import mage.abilities.Ability;
+import mage.abilities.Mode;
+import mage.abilities.effects.OneShotEffect;
+import mage.constants.Outcome;
+import mage.game.Game;
+import mage.game.permanent.Permanent;
+import mage.players.Player;
+
+import java.util.UUID;
+
+/**
+ * @author xenohedron
+ */
+public class DamageTargetAndYouEffect extends OneShotEffect {
+
+ private final int firstAmount;
+ private final int secondAmount;
+
+ /**
+ * Deals simultaneous damage to the target and the controller of the source
+ */
+ public DamageTargetAndYouEffect(int amount) {
+ this(amount, amount);
+ }
+
+ /**
+ * Deals simultaneous damage to the target and the controller of the source
+ */
+ public DamageTargetAndYouEffect(int firstAmount, int secondAmount) {
+ super(Outcome.Damage);
+ this.firstAmount = firstAmount;
+ this.secondAmount = secondAmount;
+ }
+
+ protected DamageTargetAndYouEffect(final DamageTargetAndYouEffect effect) {
+ super(effect);
+ this.firstAmount = effect.firstAmount;
+ this.secondAmount = effect.secondAmount;
+ }
+
+ @Override
+ public DamageTargetAndYouEffect copy() {
+ return new DamageTargetAndYouEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ for (UUID targetId : this.getTargetPointer().getTargets(game, source)) {
+ Permanent permanent = game.getPermanent(targetId);
+ if (permanent != null) {
+ permanent.damage(firstAmount, source.getSourceId(), source, game);
+ } else {
+ Player player = game.getPlayer(targetId);
+ if (player != null) {
+ player.damage(firstAmount, source.getSourceId(), source, game);
+ }
+ }
+ }
+ Player controller = game.getPlayer(source.getControllerId());
+ if (controller != null) {
+ controller.damage(secondAmount, source.getSourceId(), source, game);
+ }
+ return true;
+ }
+
+ @Override
+ public String getText(Mode mode) {
+ if (staticText != null && !staticText.isEmpty()) {
+ return staticText;
+ }
+ return "{this} deals " + firstAmount + "damage to " +
+ getTargetPointer().describeTargets(mode.getTargets(), "that creature") +
+ " and " + secondAmount + "damage to you";
+ }
+}
From 24785b6d81b84c3d5a8b020e53b41e77d657bc68 Mon Sep 17 00:00:00 2001
From: xenohedron <12538125+xenohedron@users.noreply.github.com>
Date: Sun, 9 Nov 2025 23:36:12 -0500
Subject: [PATCH 05/14] new DamageTargetAndSelfEffect
---
.../src/mage/cards/r/RecklessEmbermage.java | 11 +--
.../common/DamageTargetAndSelfEffect.java | 77 +++++++++++++++++++
2 files changed, 81 insertions(+), 7 deletions(-)
create mode 100644 Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndSelfEffect.java
diff --git a/Mage.Sets/src/mage/cards/r/RecklessEmbermage.java b/Mage.Sets/src/mage/cards/r/RecklessEmbermage.java
index 9446db91015..4605538e0c5 100644
--- a/Mage.Sets/src/mage/cards/r/RecklessEmbermage.java
+++ b/Mage.Sets/src/mage/cards/r/RecklessEmbermage.java
@@ -1,20 +1,18 @@
-
package mage.cards.r;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
-import mage.abilities.effects.common.DamageSelfEffect;
-import mage.abilities.effects.common.DamageTargetEffect;
+import mage.abilities.effects.common.DamageTargetAndSelfEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
-import mage.constants.Zone;
import mage.target.common.TargetAnyTarget;
+import java.util.UUID;
+
/**
*
* @author Quercitron
@@ -30,8 +28,7 @@ public final class RecklessEmbermage extends CardImpl {
this.toughness = new MageInt(2);
// {1}{R}: Reckless Embermage deals 1 damage to any target and 1 damage to itself.
- Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(1), new ManaCostsImpl<>("{1}{R}"));
- ability.addEffect(new DamageSelfEffect(1).setText("and 1 damage to itself"));
+ Ability ability = new SimpleActivatedAbility(new DamageTargetAndSelfEffect(1), new ManaCostsImpl<>("{1}{R}"));
ability.addTarget(new TargetAnyTarget());
this.addAbility(ability);
}
diff --git a/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndSelfEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndSelfEffect.java
new file mode 100644
index 00000000000..ea7bc7c38ea
--- /dev/null
+++ b/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndSelfEffect.java
@@ -0,0 +1,77 @@
+package mage.abilities.effects.common;
+
+import mage.abilities.Ability;
+import mage.abilities.Mode;
+import mage.abilities.effects.OneShotEffect;
+import mage.constants.Outcome;
+import mage.game.Game;
+import mage.game.permanent.Permanent;
+import mage.players.Player;
+
+import java.util.UUID;
+
+/**
+ * @author xenohedron
+ */
+public class DamageTargetAndSelfEffect extends OneShotEffect {
+
+ private final int firstAmount;
+ private final int secondAmount;
+
+ /**
+ * Deals simultaneous damage to the target and to itself
+ */
+ public DamageTargetAndSelfEffect(int amount) {
+ this(amount, amount);
+ }
+
+ /**
+ * Deals simultaneous damage to the target and to itself
+ */
+ public DamageTargetAndSelfEffect(int firstAmount, int secondAmount) {
+ super(Outcome.Damage);
+ this.firstAmount = firstAmount;
+ this.secondAmount = secondAmount;
+ }
+
+ protected DamageTargetAndSelfEffect(final DamageTargetAndSelfEffect effect) {
+ super(effect);
+ this.firstAmount = effect.firstAmount;
+ this.secondAmount = effect.secondAmount;
+ }
+
+ @Override
+ public DamageTargetAndSelfEffect copy() {
+ return new DamageTargetAndSelfEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ for (UUID targetId : this.getTargetPointer().getTargets(game, source)) {
+ Permanent permanent = game.getPermanent(targetId);
+ if (permanent != null) {
+ permanent.damage(firstAmount, source.getSourceId(), source, game);
+ } else {
+ Player player = game.getPlayer(targetId);
+ if (player != null) {
+ player.damage(firstAmount, source.getSourceId(), source, game);
+ }
+ }
+ }
+ Permanent itself = source.getSourcePermanentIfItStillExists(game);
+ if (itself != null) {
+ itself.damage(secondAmount, source.getSourceId(), source, game);
+ }
+ return true;
+ }
+
+ @Override
+ public String getText(Mode mode) {
+ if (staticText != null && !staticText.isEmpty()) {
+ return staticText;
+ }
+ return "{this} deals " + firstAmount + "damage to " +
+ getTargetPointer().describeTargets(mode.getTargets(), "that creature") +
+ " and " + secondAmount + "damage to itself";
+ }
+}
From 03100a932ea1e5023dfaa64f83f5dc57f2367624 Mon Sep 17 00:00:00 2001
From: xenohedron <12538125+xenohedron@users.noreply.github.com>
Date: Sun, 9 Nov 2025 23:47:44 -0500
Subject: [PATCH 06/14] new DamageTargetAndTargetControllerEffect
---
.../src/mage/cards/c/ChandrasOutrage.java | 14 ++--
...DamageTargetAndTargetControllerEffect.java | 65 +++++++++++++++++++
2 files changed, 69 insertions(+), 10 deletions(-)
create mode 100644 Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndTargetControllerEffect.java
diff --git a/Mage.Sets/src/mage/cards/c/ChandrasOutrage.java b/Mage.Sets/src/mage/cards/c/ChandrasOutrage.java
index ddaaed5fe15..e3517234cdf 100644
--- a/Mage.Sets/src/mage/cards/c/ChandrasOutrage.java
+++ b/Mage.Sets/src/mage/cards/c/ChandrasOutrage.java
@@ -1,16 +1,13 @@
-
-
package mage.cards.c;
-import java.util.UUID;
-import mage.abilities.effects.Effect;
-import mage.abilities.effects.common.DamageTargetControllerEffect;
-import mage.abilities.effects.common.DamageTargetEffect;
+import mage.abilities.effects.common.DamageTargetAndTargetControllerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.target.common.TargetCreaturePermanent;
+import java.util.UUID;
+
/**
*
* @author BetaSteward_at_googlemail.com
@@ -21,10 +18,7 @@ public final class ChandrasOutrage extends CardImpl {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{R}{R}");
// Chandra's Outrage deals 4 damage to target creature and 2 damage to that creature's controller.
- this.getSpellAbility().addEffect(new DamageTargetEffect(4));
- Effect effect = new DamageTargetControllerEffect(2);
- effect.setText("and 2 damage to that creature's controller");
- this.getSpellAbility().addEffect(effect);
+ this.getSpellAbility().addEffect(new DamageTargetAndTargetControllerEffect(4, 2));
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
}
diff --git a/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndTargetControllerEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndTargetControllerEffect.java
new file mode 100644
index 00000000000..de20b0cb6aa
--- /dev/null
+++ b/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndTargetControllerEffect.java
@@ -0,0 +1,65 @@
+package mage.abilities.effects.common;
+
+import mage.abilities.Ability;
+import mage.abilities.Mode;
+import mage.abilities.effects.OneShotEffect;
+import mage.constants.Outcome;
+import mage.game.Game;
+import mage.game.permanent.Permanent;
+import mage.players.Player;
+
+import java.util.UUID;
+
+/**
+ * @author xenohedron
+ */
+public class DamageTargetAndTargetControllerEffect extends OneShotEffect {
+
+ private final int firstAmount;
+ private final int secondAmount;
+
+ /**
+ * Deals simultaneous damage to the target and to the controller of the target
+ */
+ public DamageTargetAndTargetControllerEffect(int firstAmount, int secondAmount) {
+ super(Outcome.Damage);
+ this.firstAmount = firstAmount;
+ this.secondAmount = secondAmount;
+ }
+
+ protected DamageTargetAndTargetControllerEffect(final DamageTargetAndTargetControllerEffect effect) {
+ super(effect);
+ this.firstAmount = effect.firstAmount;
+ this.secondAmount = effect.secondAmount;
+ }
+
+ @Override
+ public DamageTargetAndTargetControllerEffect copy() {
+ return new DamageTargetAndTargetControllerEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ for (UUID targetId : this.getTargetPointer().getTargets(game, source)) {
+ Permanent permanent = game.getPermanent(targetId);
+ if (permanent != null) {
+ permanent.damage(firstAmount, source.getSourceId(), source, game);
+ Player player = game.getPlayer(permanent.getControllerId());
+ if (player != null) {
+ player.damage(secondAmount, source.getSourceId(), source, game);
+ }
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public String getText(Mode mode) {
+ if (staticText != null && !staticText.isEmpty()) {
+ return staticText;
+ }
+ return "{this} deals " + firstAmount + "damage to " +
+ getTargetPointer().describeTargets(mode.getTargets(), "that creature") +
+ " and " + secondAmount + "damage to that creature's controller";
+ }
+}
From b8394f99e22d402374fea1368aeeac71e77641d1 Mon Sep 17 00:00:00 2001
From: xenohedron <12538125+xenohedron@users.noreply.github.com>
Date: Sun, 9 Nov 2025 23:58:45 -0500
Subject: [PATCH 07/14] new DamageTargetAndAllControlledEffect
---
Mage.Sets/src/mage/cards/c/ChandrasFury.java | 14 ++--
.../DamageTargetAndAllControlledEffect.java | 73 +++++++++++++++++++
2 files changed, 79 insertions(+), 8 deletions(-)
create mode 100644 Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndAllControlledEffect.java
diff --git a/Mage.Sets/src/mage/cards/c/ChandrasFury.java b/Mage.Sets/src/mage/cards/c/ChandrasFury.java
index 98e752ca138..87f167a107f 100644
--- a/Mage.Sets/src/mage/cards/c/ChandrasFury.java
+++ b/Mage.Sets/src/mage/cards/c/ChandrasFury.java
@@ -1,14 +1,14 @@
-
package mage.cards.c;
-import java.util.UUID;
-import mage.abilities.effects.common.DamageAllControlledTargetEffect;
-import mage.abilities.effects.common.DamageTargetEffect;
+import mage.abilities.effects.common.DamageTargetAndAllControlledEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
+import mage.filter.StaticFilters;
import mage.target.common.TargetPlayerOrPlaneswalker;
+import java.util.UUID;
+
/**
*
* @author North
@@ -19,10 +19,8 @@ public final class ChandrasFury extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{4}{R}");
// Chandra's Fury deals 4 damage to target player and 1 damage to each creature that player controls.
- this.getSpellAbility().addEffect(new DamageTargetEffect(4));
- this.getSpellAbility().addEffect(new DamageAllControlledTargetEffect(1)
- .setText("and 1 damage to each creature that player or that planeswalker's controller controls")
- );
+ this.getSpellAbility().addEffect(new DamageTargetAndAllControlledEffect(4, 1,
+ StaticFilters.FILTER_PERMANENT_CREATURE));
this.getSpellAbility().addTarget(new TargetPlayerOrPlaneswalker());
}
diff --git a/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndAllControlledEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndAllControlledEffect.java
new file mode 100644
index 00000000000..843bd5609ce
--- /dev/null
+++ b/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndAllControlledEffect.java
@@ -0,0 +1,73 @@
+package mage.abilities.effects.common;
+
+import mage.abilities.Ability;
+import mage.abilities.Mode;
+import mage.abilities.effects.OneShotEffect;
+import mage.constants.Outcome;
+import mage.filter.FilterPermanent;
+import mage.game.Game;
+import mage.game.permanent.Permanent;
+import mage.players.Player;
+
+/**
+ * @author xenohedron
+ */
+public class DamageTargetAndAllControlledEffect extends OneShotEffect {
+
+ private final int firstAmount;
+ private final int secondAmount;
+ private final FilterPermanent filter;
+
+ /**
+ * Deals simultaneous damage to the target and to each creature the target controls
+ */
+ public DamageTargetAndAllControlledEffect(int firstAmount, int secondAmount, FilterPermanent filter) {
+ super(Outcome.Damage);
+ this.firstAmount = firstAmount;
+ this.secondAmount = secondAmount;
+ this.filter = filter;
+ }
+
+ protected DamageTargetAndAllControlledEffect(final DamageTargetAndAllControlledEffect effect) {
+ super(effect);
+ this.firstAmount = effect.firstAmount;
+ this.secondAmount = effect.secondAmount;
+ this.filter = effect.filter.copy();
+ }
+
+ @Override
+ public DamageTargetAndAllControlledEffect copy() {
+ return new DamageTargetAndAllControlledEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
+ if (permanent != null) {
+ permanent.damage(firstAmount, source.getSourceId(), source, game);
+ } else {
+ Player player = game.getPlayer(getTargetPointer().getFirst(game, source));
+ if (player != null) {
+ player.damage(firstAmount, source.getSourceId(), source, game);
+ }
+ }
+ Player controller = game.getPlayerOrPlaneswalkerController(getTargetPointer().getFirst(game, source));
+ if (controller != null) {
+ for (Permanent perm : game.getBattlefield().getAllActivePermanents(filter, controller.getId(), game)) {
+ perm.damage(secondAmount, source.getSourceId(), source, game, false, true);
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public String getText(Mode mode) {
+ if (staticText != null && !staticText.isEmpty()) {
+ return staticText;
+ }
+ return "{this} deals " + firstAmount + "damage to " +
+ getTargetPointer().describeTargets(mode.getTargets(), "that creature") +
+ " and " + secondAmount + " damage to each " + filter.getMessage() +
+ " that player or that planeswalker's controller controls";
+ }
+}
From 1a1f7ec588252412d9a9414554c2fb3bdb63e8ab Mon Sep 17 00:00:00 2001
From: xenohedron <12538125+xenohedron@users.noreply.github.com>
Date: Mon, 10 Nov 2025 01:37:28 -0500
Subject: [PATCH 08/14] update all cards that deal damage to two or more
specific things simultaneously
---
Mage.Sets/src/mage/cards/a/ArcTrail.java | 6 ++-
.../src/mage/cards/a/AssembledAlphas.java | 13 ++---
.../src/mage/cards/b/BellowingFiend.java | 20 ++++---
.../src/mage/cards/b/BurningSunsAvatar.java | 15 +++---
.../src/mage/cards/c/CarnivalCarnage.java | 5 +-
.../src/mage/cards/c/ChandraFlamesFury.java | 48 ++---------------
.../src/mage/cards/c/ChandraPyromaster.java | 9 ++--
.../src/mage/cards/c/ConductElectricity.java | 14 ++---
Mage.Sets/src/mage/cards/c/CunningStrike.java | 22 +++-----
.../src/mage/cards/c/CuombajjWitches.java | 5 +-
Mage.Sets/src/mage/cards/d/DaggerCaster.java | 38 ++++++++++---
.../src/mage/cards/d/DragonsparkReactor.java | 3 +-
.../mage/cards/d/DrakusethMawOfFlames.java | 50 ++---------------
.../src/mage/cards/e/ExplosiveWelcome.java | 22 +++-----
Mage.Sets/src/mage/cards/f/FearFireFoes.java | 5 +-
.../src/mage/cards/f/FireAndBrimstone.java | 6 +--
Mage.Sets/src/mage/cards/f/Fireslinger.java | 6 +--
Mage.Sets/src/mage/cards/f/Firespout.java | 47 +++++++++++++---
Mage.Sets/src/mage/cards/f/FirstVolley.java | 10 +---
Mage.Sets/src/mage/cards/f/ForgeDevil.java | 17 ++----
.../src/mage/cards/g/GoblinArtillery.java | 8 +--
.../src/mage/cards/g/GrangerGuildmage.java | 13 ++---
Mage.Sets/src/mage/cards/h/HailStorm.java | 41 ++++++++++++--
Mage.Sets/src/mage/cards/h/HungryFlames.java | 48 ++---------------
Mage.Sets/src/mage/cards/i/InsultInjury.java | 40 ++------------
.../src/mage/cards/i/InvasionOfRegatha.java | 19 ++-----
Mage.Sets/src/mage/cards/j/JudgmentBolt.java | 38 ++++++++++---
Mage.Sets/src/mage/cards/k/KamahlsSledge.java | 15 +++---
Mage.Sets/src/mage/cards/l/Lunge.java | 18 +++----
Mage.Sets/src/mage/cards/n/NeonatesRush.java | 41 ++------------
.../src/mage/cards/o/OrcishArtillery.java | 11 ++--
.../src/mage/cards/o/OrcishCannonade.java | 14 ++---
.../src/mage/cards/o/OrcishCannoneers.java | 15 ++----
Mage.Sets/src/mage/cards/p/PsionicBlast.java | 6 +--
Mage.Sets/src/mage/cards/p/PsionicEntity.java | 13 ++---
Mage.Sets/src/mage/cards/p/PsionicSliver.java | 18 ++-----
.../src/mage/cards/p/PunishTheEnemy.java | 15 +++---
.../src/mage/cards/r/RadiatingLightning.java | 11 ++--
.../src/mage/cards/r/RakdosFirewheeler.java | 11 ++--
Mage.Sets/src/mage/cards/r/RecklessRage.java | 15 ++----
Mage.Sets/src/mage/cards/s/SeismicWave.java | 6 +--
Mage.Sets/src/mage/cards/s/SelfDestruct.java | 2 +-
.../src/mage/cards/s/ShadowGuildmage.java | 12 ++---
.../src/mage/cards/s/ShockerUnshakable.java | 6 +--
.../src/mage/cards/s/ShowerOfSparks.java | 13 ++---
.../src/mage/cards/s/SoulOfShandalar.java | 3 +-
Mage.Sets/src/mage/cards/s/Sparksmith.java | 54 +++++++++++++------
.../src/mage/cards/s/SunflareShaman.java | 15 +++---
.../mage/cards/s/SynchronizedSpellcraft.java | 23 ++------
.../src/mage/cards/t/TheFallOfKroog.java | 12 ++---
Mage.Sets/src/mage/cards/t/TrickShot.java | 10 +---
Mage.Sets/src/mage/cards/u/UnleashShell.java | 10 ++--
Mage.Sets/src/mage/cards/w/WildfireHowl.java | 2 +
.../DamageTargetAndAllControlledEffect.java | 18 +++++--
...DamageTargetAndTargetControllerEffect.java | 12 +++--
55 files changed, 397 insertions(+), 572 deletions(-)
diff --git a/Mage.Sets/src/mage/cards/a/ArcTrail.java b/Mage.Sets/src/mage/cards/a/ArcTrail.java
index 2a7a57ede4f..703e3c7ecf8 100644
--- a/Mage.Sets/src/mage/cards/a/ArcTrail.java
+++ b/Mage.Sets/src/mage/cards/a/ArcTrail.java
@@ -29,8 +29,10 @@ public final class ArcTrail extends CardImpl {
// Arc Trail deals 2 damage to any target and 1 damage to another target
this.getSpellAbility().addEffect(new DamageTargetAndTargetEffect(2, 1));
- this.getSpellAbility().addTarget(new TargetPermanentOrPlayer(filter1).setTargetTag(1));
- this.getSpellAbility().addTarget(new TargetPermanentOrPlayer(filter2).setTargetTag(2));
+ this.getSpellAbility().addTarget(new TargetPermanentOrPlayer(filter1)
+ .withChooseHint("to deal 2 damage").setTargetTag(1));
+ this.getSpellAbility().addTarget(new TargetPermanentOrPlayer(filter2)
+ .withChooseHint("to deal 1 damage").setTargetTag(2));
}
private ArcTrail(final ArcTrail card) {
diff --git a/Mage.Sets/src/mage/cards/a/AssembledAlphas.java b/Mage.Sets/src/mage/cards/a/AssembledAlphas.java
index dd5ca0e07cf..fbb15e6b892 100644
--- a/Mage.Sets/src/mage/cards/a/AssembledAlphas.java
+++ b/Mage.Sets/src/mage/cards/a/AssembledAlphas.java
@@ -1,16 +1,14 @@
package mage.cards.a;
-import java.util.UUID;
import mage.MageInt;
-import mage.abilities.Ability;
import mage.abilities.common.BlocksOrBlockedByCreatureSourceTriggeredAbility;
-import mage.abilities.effects.common.DamageTargetControllerEffect;
-import mage.abilities.effects.common.DamageTargetEffect;
+import mage.abilities.effects.common.DamageTargetAndTargetControllerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
-import mage.filter.StaticFilters;
+
+import java.util.UUID;
/**
*
@@ -25,9 +23,8 @@ public final class AssembledAlphas extends CardImpl {
this.toughness = new MageInt(5);
// Whenever Assembled Alphas blocks or becomes blocked by a creature, Assembled Alphas deals 3 damage to that creature and 3 damage to that creature's controller.
- Ability ability = new BlocksOrBlockedByCreatureSourceTriggeredAbility(new DamageTargetEffect(3, true, "that creature"));
- ability.addEffect(new DamageTargetControllerEffect(3).setText("and 3 damage to that creature's controller"));
- this.addAbility(ability);
+ this.addAbility(new BlocksOrBlockedByCreatureSourceTriggeredAbility(
+ new DamageTargetAndTargetControllerEffect(3, 3)));
}
private AssembledAlphas(final AssembledAlphas card) {
diff --git a/Mage.Sets/src/mage/cards/b/BellowingFiend.java b/Mage.Sets/src/mage/cards/b/BellowingFiend.java
index 7638ae26eb9..b38acec47c7 100644
--- a/Mage.Sets/src/mage/cards/b/BellowingFiend.java
+++ b/Mage.Sets/src/mage/cards/b/BellowingFiend.java
@@ -3,9 +3,7 @@ package mage.cards.b;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.DealsDamageToACreatureTriggeredAbility;
-import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
-import mage.abilities.effects.common.DamageControllerEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -31,12 +29,10 @@ public final class BellowingFiend extends CardImpl {
// Flying
this.addAbility(FlyingAbility.getInstance());
+
// Whenever Bellowing Fiend deals damage to a creature, Bellowing Fiend deals 3 damage to that creature's controller and 3 damage to you.
- Ability ability = new DealsDamageToACreatureTriggeredAbility(new BellowingFiendEffect(), false, false, true);
- Effect effect = new DamageControllerEffect(3);
- effect.setText("and 3 damage to you");
- ability.addEffect(effect);
- this.addAbility(ability);
+ this.addAbility(new DealsDamageToACreatureTriggeredAbility(
+ new BellowingFiendEffect(), false, false, true));
}
private BellowingFiend(final BellowingFiend card) {
@@ -53,7 +49,7 @@ class BellowingFiendEffect extends OneShotEffect {
BellowingFiendEffect() {
super(Outcome.Detriment);
- this.staticText = "{this} deals 3 damage to that creature's controller";
+ this.staticText = "{this} deals 3 damage to that creature's controller and 3 damage to you";
}
private BellowingFiendEffect(final BellowingFiendEffect effect) {
@@ -67,15 +63,17 @@ class BellowingFiendEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
- boolean applied = false;
Permanent damagedCreature = getTargetPointer().getFirstTargetPermanentOrLKI(game, source);
if (damagedCreature != null) {
Player controller = game.getPlayer(damagedCreature.getControllerId());
if (controller != null) {
controller.damage(3, source.getSourceId(), source, game);
- applied = true;
}
}
- return applied;
+ Player you = game.getPlayer(source.getControllerId());
+ if (you != null) {
+ you.damage(3, source.getSourceId(), source, game);
+ }
+ return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/b/BurningSunsAvatar.java b/Mage.Sets/src/mage/cards/b/BurningSunsAvatar.java
index 0aca1c22fc8..4394b57717d 100644
--- a/Mage.Sets/src/mage/cards/b/BurningSunsAvatar.java
+++ b/Mage.Sets/src/mage/cards/b/BurningSunsAvatar.java
@@ -1,12 +1,9 @@
-
package mage.cards.b;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
-import mage.abilities.effects.Effect;
-import mage.abilities.effects.common.DamageTargetEffect;
+import mage.abilities.effects.common.DamageTargetAndTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
@@ -14,6 +11,8 @@ import mage.constants.SubType;
import mage.target.common.TargetCreaturePermanent;
import mage.target.common.TargetOpponentOrPlaneswalker;
+import java.util.UUID;
+
/**
*
* @author TheElk801
@@ -29,11 +28,9 @@ public final class BurningSunsAvatar extends CardImpl {
this.toughness = new MageInt(6);
// When Burning Sun's Avatar enters the battlefield, it deals 3 damage to target opponent and 3 damage to up to one target creature.
- Effect effect = new DamageTargetEffect(3);
- effect.setText("it deals 3 damage to target opponent or planeswalker and 3 damage to up to one target creature");
- Ability ability = new EntersBattlefieldTriggeredAbility(effect, false);
- ability.addTarget(new TargetOpponentOrPlaneswalker());
- ability.addTarget(new TargetCreaturePermanent(0, 1));
+ Ability ability = new EntersBattlefieldTriggeredAbility(new DamageTargetAndTargetEffect(3, 3));
+ ability.addTarget(new TargetOpponentOrPlaneswalker().setTargetTag(1));
+ ability.addTarget(new TargetCreaturePermanent(0, 1).setTargetTag(2));
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/c/CarnivalCarnage.java b/Mage.Sets/src/mage/cards/c/CarnivalCarnage.java
index 8ff9875068c..33452f3972e 100644
--- a/Mage.Sets/src/mage/cards/c/CarnivalCarnage.java
+++ b/Mage.Sets/src/mage/cards/c/CarnivalCarnage.java
@@ -1,6 +1,6 @@
package mage.cards.c;
-import mage.abilities.effects.common.DamageTargetControllerEffect;
+import mage.abilities.effects.common.DamageTargetAndTargetControllerEffect;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.effects.common.discard.DiscardTargetEffect;
import mage.cards.CardSetInfo;
@@ -22,8 +22,7 @@ public final class CarnivalCarnage extends SplitCard {
// Carnival
// Carnival deals 1 damage to target creature or planeswalker and 1 damage to that permanent's controller.
- this.getLeftHalfCard().getSpellAbility().addEffect(new DamageTargetEffect(1));
- this.getLeftHalfCard().getSpellAbility().addEffect(new DamageTargetControllerEffect(1).setText("and 1 damage to that permanent's controller"));
+ this.getLeftHalfCard().getSpellAbility().addEffect(new DamageTargetAndTargetControllerEffect(1, 1));
this.getLeftHalfCard().getSpellAbility().addTarget(new TargetCreatureOrPlaneswalker());
// Carnage
diff --git a/Mage.Sets/src/mage/cards/c/ChandraFlamesFury.java b/Mage.Sets/src/mage/cards/c/ChandraFlamesFury.java
index a3303380cae..16beae1a99b 100644
--- a/Mage.Sets/src/mage/cards/c/ChandraFlamesFury.java
+++ b/Mage.Sets/src/mage/cards/c/ChandraFlamesFury.java
@@ -2,19 +2,14 @@ package mage.cards.c;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
-import mage.abilities.effects.OneShotEffect;
-import mage.abilities.effects.common.DamageAllControlledTargetEffect;
+import mage.abilities.effects.common.DamageTargetAndAllControlledEffect;
+import mage.abilities.effects.common.DamageTargetAndTargetControllerEffect;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.SuperType;
-import mage.filter.StaticFilters;
-import mage.game.Game;
-import mage.game.permanent.Permanent;
-import mage.players.Player;
import mage.target.TargetPlayer;
import mage.target.common.TargetAnyTarget;
import mage.target.common.TargetCreaturePermanent;
@@ -39,15 +34,12 @@ public final class ChandraFlamesFury extends CardImpl {
this.addAbility(ability);
// −2: Chandra, Flame's Fury deals 4 damage to target creature and 2 damage to that creature's controller.
- ability = new LoyaltyAbility(new ChandraFlamesFuryEffect(), -2);
+ ability = new LoyaltyAbility(new DamageTargetAndTargetControllerEffect(4, 2), -2);
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability);
// −8: Chandra, Flame's Fury deals 10 damage to target player and each creature that player controls.
- ability = new LoyaltyAbility(new DamageTargetEffect(10), -8);
- ability.addEffect(new DamageAllControlledTargetEffect(
- 10, StaticFilters.FILTER_PERMANENT_CREATURE
- ).setText("and each creature that player controls"));
+ ability = new LoyaltyAbility(new DamageTargetAndAllControlledEffect(10), -8);
ability.addTarget(new TargetPlayer());
this.addAbility(ability);
}
@@ -61,35 +53,3 @@ public final class ChandraFlamesFury extends CardImpl {
return new ChandraFlamesFury(this);
}
}
-
-class ChandraFlamesFuryEffect extends OneShotEffect {
-
- ChandraFlamesFuryEffect() {
- super(Outcome.Benefit);
- staticText = "{this} deals 4 damage to target creature and 2 damage to that creature's controller.";
- }
-
- private ChandraFlamesFuryEffect(final ChandraFlamesFuryEffect effect) {
- super(effect);
- }
-
- @Override
- public ChandraFlamesFuryEffect copy() {
- return new ChandraFlamesFuryEffect(this);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- Permanent permanent = game.getPermanent(source.getFirstTarget());
- if (permanent == null) {
- return false;
- }
- Player player = game.getPlayer(permanent.getControllerId());
- if (player == null) {
- return false;
- }
- permanent.damage(4, source.getSourceId(), source, game);
- player.damage(2, source.getSourceId(), source, game);
- return true;
- }
-}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/c/ChandraPyromaster.java b/Mage.Sets/src/mage/cards/c/ChandraPyromaster.java
index 035f31d6a6d..8a8b4880a1b 100644
--- a/Mage.Sets/src/mage/cards/c/ChandraPyromaster.java
+++ b/Mage.Sets/src/mage/cards/c/ChandraPyromaster.java
@@ -36,8 +36,7 @@ public final class ChandraPyromaster extends CardImpl {
this.setStartingLoyalty(4);
- // +1: Chandra, Pyromaster deals 1 damage to target player and 1 damage to
- // up to one target creature that player controls. That creature can't block this turn.
+ // +1: Chandra, Pyromaster deals 1 damage to target player and 1 damage to up to one target creature that player controls. That creature can't block this turn.
LoyaltyAbility ability1 = new LoyaltyAbility(new ChandraPyromasterEffect1(), 1);
Target target1 = new TargetPlayerOrPlaneswalker();
ability1.addTarget(target1);
@@ -68,7 +67,7 @@ public final class ChandraPyromaster extends CardImpl {
class ChandraPyromasterEffect1 extends OneShotEffect {
- public ChandraPyromasterEffect1() {
+ ChandraPyromasterEffect1() {
super(Outcome.Damage);
staticText = "{this} deals 1 damage to target player or planeswalker "
+ "and 1 damage to up to one target creature that player or that "
@@ -101,7 +100,7 @@ class ChandraPyromasterEffect1 extends OneShotEffect {
class ChandraPyromasterTarget extends TargetPermanent {
- public ChandraPyromasterTarget() {
+ ChandraPyromasterTarget() {
super(0, 1, new FilterCreaturePermanent("creature that the targeted player "
+ "or planeswalker's controller controls"), false);
}
@@ -138,7 +137,7 @@ class ChandraPyromasterTarget extends TargetPermanent {
class ChandraPyromasterEffect2 extends OneShotEffect {
- public ChandraPyromasterEffect2() {
+ ChandraPyromasterEffect2() {
super(Outcome.Detriment);
this.staticText = "Exile the top card of your library. You may play it this turn";
}
diff --git a/Mage.Sets/src/mage/cards/c/ConductElectricity.java b/Mage.Sets/src/mage/cards/c/ConductElectricity.java
index 335dae1cb40..339fddbc851 100644
--- a/Mage.Sets/src/mage/cards/c/ConductElectricity.java
+++ b/Mage.Sets/src/mage/cards/c/ConductElectricity.java
@@ -1,13 +1,12 @@
package mage.cards.c;
-import mage.abilities.effects.common.DamageTargetEffect;
+import mage.abilities.effects.common.DamageTargetAndTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.filter.StaticFilters;
import mage.target.TargetPermanent;
import mage.target.common.TargetCreaturePermanent;
-import mage.target.targetpointer.SecondTargetPointer;
import java.util.UUID;
@@ -20,16 +19,11 @@ public final class ConductElectricity extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{4}{R}");
// Conduct Electricity deals 6 damage to target creature and 2 damage to up to one target creature token.
- this.getSpellAbility().addEffect(new DamageTargetEffect(
- 6, true, "", true
- ));
- this.getSpellAbility().addEffect(new DamageTargetEffect(
- 2, true, "", true
- ).setTargetPointer(new SecondTargetPointer()).setText("and 2 damage to up to one target creature token"));
- this.getSpellAbility().addTarget(new TargetCreaturePermanent());
+ this.getSpellAbility().addEffect(new DamageTargetAndTargetEffect(6, 2));
+ this.getSpellAbility().addTarget(new TargetCreaturePermanent().setTargetTag(1));
this.getSpellAbility().addTarget(new TargetPermanent(
0, 1, StaticFilters.FILTER_CREATURE_TOKEN
- ));
+ ).setTargetTag(2));
}
private ConductElectricity(final ConductElectricity card) {
diff --git a/Mage.Sets/src/mage/cards/c/CunningStrike.java b/Mage.Sets/src/mage/cards/c/CunningStrike.java
index e3bdf684b9d..0b1d21da301 100644
--- a/Mage.Sets/src/mage/cards/c/CunningStrike.java
+++ b/Mage.Sets/src/mage/cards/c/CunningStrike.java
@@ -1,17 +1,14 @@
-
package mage.cards.c;
-import java.util.UUID;
-import mage.abilities.dynamicvalue.common.StaticValue;
-import mage.abilities.effects.Effect;
-import mage.abilities.effects.common.DamageTargetEffect;
+import mage.abilities.effects.common.DamageTargetAndTargetEffect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.target.common.TargetCreaturePermanent;
import mage.target.common.TargetPlayerOrPlaneswalker;
-import mage.target.targetpointer.SecondTargetPointer;
+
+import java.util.UUID;
/**
*
@@ -22,14 +19,11 @@ public final class CunningStrike extends CardImpl {
public CunningStrike(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{U}{R}");
- // Cunning Strike deals 2 damage to target creature and 2 damage to target player.
- this.getSpellAbility().addEffect(new DamageTargetEffect(StaticValue.get(2), true, "", true));
- this.getSpellAbility().addTarget(new TargetCreaturePermanent());
- Effect effect = new DamageTargetEffect(StaticValue.get(2), true, "", true);
- effect.setTargetPointer(new SecondTargetPointer());
- effect.setText("and 2 damage to target player or planeswalker");
- this.getSpellAbility().addEffect(effect);
- this.getSpellAbility().addTarget(new TargetPlayerOrPlaneswalker());
+ // Cunning Strike deals 2 damage to target creature and 2 damage to target player or planeswalker.
+ this.getSpellAbility().addEffect(new DamageTargetAndTargetEffect(2, 2));
+ this.getSpellAbility().addTarget(new TargetCreaturePermanent().setTargetTag(1));
+ this.getSpellAbility().addTarget(new TargetPlayerOrPlaneswalker().setTargetTag(2));
+
// Draw a card.
this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1).concatBy("
"));
}
diff --git a/Mage.Sets/src/mage/cards/c/CuombajjWitches.java b/Mage.Sets/src/mage/cards/c/CuombajjWitches.java
index 2389a6b11b8..79029a89b03 100644
--- a/Mage.Sets/src/mage/cards/c/CuombajjWitches.java
+++ b/Mage.Sets/src/mage/cards/c/CuombajjWitches.java
@@ -1,4 +1,3 @@
-
package mage.cards.c;
import mage.MageInt;
@@ -12,13 +11,13 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
-import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
import mage.target.Target;
import mage.target.common.TargetAnyTarget;
import mage.target.common.TargetOpponent;
import mage.target.targetadjustment.TargetAdjuster;
+import mage.target.targetpointer.EachTargetPointer;
import java.util.UUID;
@@ -35,7 +34,7 @@ public final class CuombajjWitches extends CardImpl {
this.toughness = new MageInt(3);
// {T}: Cuombajj Witches deals 1 damage to any target and 1 damage to any target of an opponent's choice.
- Effect effect = new DamageTargetEffect(1);
+ Effect effect = new DamageTargetEffect(1).setTargetPointer(new EachTargetPointer());
effect.setText("{this} deals 1 damage to any target and 1 damage to any target of an opponent's choice");
Ability ability = new SimpleActivatedAbility(effect, new TapSourceCost());
ability.addTarget(new TargetAnyTarget());
diff --git a/Mage.Sets/src/mage/cards/d/DaggerCaster.java b/Mage.Sets/src/mage/cards/d/DaggerCaster.java
index aed8e187569..18a7388ae79 100644
--- a/Mage.Sets/src/mage/cards/d/DaggerCaster.java
+++ b/Mage.Sets/src/mage/cards/d/DaggerCaster.java
@@ -3,14 +3,17 @@ package mage.cards.d;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
+import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DamageAllEffect;
import mage.abilities.effects.common.DamagePlayersEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
+import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.TargetController;
import mage.filter.StaticFilters;
+import mage.game.Game;
import java.util.UUID;
@@ -28,14 +31,7 @@ public final class DaggerCaster extends CardImpl {
this.toughness = new MageInt(3);
// When Dagger Caster enters the battlefield, it deals 1 damage to each opponent and 1 damage to each creature your opponents control.
- Ability ability = new EntersBattlefieldTriggeredAbility(new DamagePlayersEffect(
- 1, TargetController.OPPONENT, "it"
- ));
- ability.addEffect(
- new DamageAllEffect(1, StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)
- .setText("and 1 damage to each creature your opponents control")
- );
- this.addAbility(ability);
+ this.addAbility(new EntersBattlefieldTriggeredAbility(new DaggerCasterEffect()));
}
private DaggerCaster(final DaggerCaster card) {
@@ -47,3 +43,29 @@ public final class DaggerCaster extends CardImpl {
return new DaggerCaster(this);
}
}
+
+// needed for simultaneous damage
+class DaggerCasterEffect extends OneShotEffect {
+
+ DaggerCasterEffect() {
+ super(Outcome.Damage);
+ staticText = "it deals 1 damage to each opponent and 1 damage to each creature your opponents control";
+ }
+
+ private DaggerCasterEffect(final DaggerCasterEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public DaggerCasterEffect copy() {
+ return new DaggerCasterEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ new DamagePlayersEffect(1, TargetController.OPPONENT, "it").apply(game, source);
+ new DamageAllEffect(1, StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE).apply(game, source);
+ return true;
+ }
+
+}
diff --git a/Mage.Sets/src/mage/cards/d/DragonsparkReactor.java b/Mage.Sets/src/mage/cards/d/DragonsparkReactor.java
index 45469a4de18..0f9d6fcbdd3 100644
--- a/Mage.Sets/src/mage/cards/d/DragonsparkReactor.java
+++ b/Mage.Sets/src/mage/cards/d/DragonsparkReactor.java
@@ -16,6 +16,7 @@ import mage.counters.CounterType;
import mage.filter.StaticFilters;
import mage.target.TargetPlayer;
import mage.target.common.TargetCreaturePermanent;
+import mage.target.targetpointer.EachTargetPointer;
import java.util.UUID;
@@ -40,7 +41,7 @@ public final class DragonsparkReactor extends CardImpl {
new DamageTargetEffect(xValue).setText(
"it deals damage equal to the number of charge counters on it to target player " +
"and that much damage to up to one target creature"
- ), new GenericManaCost(4)
+ ).setTargetPointer(new EachTargetPointer()), new GenericManaCost(4)
);
ability.addCost(new SacrificeSourceCost());
ability.addTarget(new TargetPlayer());
diff --git a/Mage.Sets/src/mage/cards/d/DrakusethMawOfFlames.java b/Mage.Sets/src/mage/cards/d/DrakusethMawOfFlames.java
index 5b05e77d8d3..be989545f08 100644
--- a/Mage.Sets/src/mage/cards/d/DrakusethMawOfFlames.java
+++ b/Mage.Sets/src/mage/cards/d/DrakusethMawOfFlames.java
@@ -3,20 +3,16 @@ package mage.cards.d;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.AttacksTriggeredAbility;
-import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.DamageTargetAndTargetEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.filter.common.FilterAnyTarget;
import mage.filter.common.FilterPermanentOrPlayer;
import mage.filter.predicate.other.AnotherTargetPredicate;
-import mage.game.Game;
-import mage.game.permanent.Permanent;
-import mage.players.Player;
import mage.target.common.TargetAnyTarget;
import mage.target.common.TargetPermanentOrPlayer;
@@ -26,6 +22,7 @@ import java.util.UUID;
* @author TheElk801
*/
public final class DrakusethMawOfFlames extends CardImpl {
+
private static final FilterPermanentOrPlayer filter = new FilterAnyTarget("any target");
static {
@@ -45,7 +42,8 @@ public final class DrakusethMawOfFlames extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// Whenever Drakuseth, Maw of Flames attacks, it deals 4 damage to any target and 3 damage to each of up to two other targets.
- Ability ability = new AttacksTriggeredAbility(new DrakusethMawOfFlamesEffect(), false);
+ Ability ability = new AttacksTriggeredAbility(new DamageTargetAndTargetEffect(4, 3)
+ .setText("it deals 4 damage to any target and 3 damage to each of up to two other targets"));
ability.addTarget(new TargetAnyTarget().withChooseHint("to deal 4 damage").setTargetTag(1));
ability.addTarget(new TargetPermanentOrPlayer(
0, 2, filter, false
@@ -62,43 +60,3 @@ public final class DrakusethMawOfFlames extends CardImpl {
return new DrakusethMawOfFlames(this);
}
}
-
-class DrakusethMawOfFlamesEffect extends OneShotEffect {
-
- DrakusethMawOfFlamesEffect() {
- super(Outcome.Damage);
- staticText = "it deals 4 damage to any target and 3 damage to each of "
- + "up to two other targets.";
- }
-
- private DrakusethMawOfFlamesEffect(final DrakusethMawOfFlamesEffect effect) {
- super(effect);
- }
-
- @Override
- public DrakusethMawOfFlamesEffect copy() {
- return new DrakusethMawOfFlamesEffect(this);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- damage(4, source.getTargets().get(0).getFirstTarget(), game, source);
- source.getTargets()
- .get(1)
- .getTargets()
- .stream()
- .forEach(targetId -> damage(3, targetId, game, source));
- return true;
- }
-
- private static void damage(int damage, UUID targetId, Game game, Ability source) {
- Permanent permanent = game.getPermanent(targetId);
- if (permanent != null) {
- permanent.damage(damage, source.getSourceId(), source, game, false, true);
- }
- Player player = game.getPlayer(targetId);
- if (player != null) {
- player.damage(damage, source.getSourceId(), source, game);
- }
- }
-}
diff --git a/Mage.Sets/src/mage/cards/e/ExplosiveWelcome.java b/Mage.Sets/src/mage/cards/e/ExplosiveWelcome.java
index a38deebd541..34d261a336d 100644
--- a/Mage.Sets/src/mage/cards/e/ExplosiveWelcome.java
+++ b/Mage.Sets/src/mage/cards/e/ExplosiveWelcome.java
@@ -1,8 +1,7 @@
package mage.cards.e;
import mage.Mana;
-import mage.abilities.dynamicvalue.common.StaticValue;
-import mage.abilities.effects.common.DamageTargetEffect;
+import mage.abilities.effects.common.DamageTargetAndTargetEffect;
import mage.abilities.effects.mana.BasicManaEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -11,10 +10,8 @@ import mage.constants.ManaType;
import mage.filter.common.FilterAnyTarget;
import mage.filter.common.FilterPermanentOrPlayer;
import mage.filter.predicate.other.AnotherTargetPredicate;
-import mage.target.Target;
import mage.target.common.TargetAnyTarget;
import mage.target.common.TargetPermanentOrPlayer;
-import mage.target.targetpointer.SecondTargetPointer;
import java.util.UUID;
@@ -34,19 +31,12 @@ public final class ExplosiveWelcome extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{7}{R}");
// Explosive Welcome deals 5 damage to any target and 3 damage to any other target. Add {R}{R}{R}.
- this.getSpellAbility().addEffect(new DamageTargetEffect(StaticValue.get(5), true, "", true));
- this.getSpellAbility().addEffect(
- new DamageTargetEffect(StaticValue.get(3), true, "", true)
- .setTargetPointer(new SecondTargetPointer())
- .setText("and 3 damage to any other target.")
- );
+ this.getSpellAbility().addEffect(new DamageTargetAndTargetEffect(5, 3));
this.getSpellAbility().addEffect(new BasicManaEffect(new Mana(ManaType.RED, 3)));
- Target target = new TargetAnyTarget();
- target.setTargetTag(1);
- this.getSpellAbility().addTarget(target);
- target = new TargetPermanentOrPlayer(filter);
- target.setTargetTag(2);
- this.getSpellAbility().addTarget(target);
+ this.getSpellAbility().addTarget(new TargetAnyTarget()
+ .withChooseHint("to deal 5 damage").setTargetTag(1));
+ this.getSpellAbility().addTarget(new TargetPermanentOrPlayer(filter)
+ .withChooseHint("to deal 3 damage").setTargetTag(2));
}
private ExplosiveWelcome(final ExplosiveWelcome card) {
diff --git a/Mage.Sets/src/mage/cards/f/FearFireFoes.java b/Mage.Sets/src/mage/cards/f/FearFireFoes.java
index 230a0c21a29..0e598e70321 100644
--- a/Mage.Sets/src/mage/cards/f/FearFireFoes.java
+++ b/Mage.Sets/src/mage/cards/f/FearFireFoes.java
@@ -34,7 +34,6 @@ public final class FearFireFoes extends CardImpl {
this.getSpellAbility().addEffect(new DamageCantBePreventedEffect(
Duration.EndOfTurn
));
- this.getSpellAbility().addEffect(new DamageTargetEffect(GetXValue.instance));
this.getSpellAbility().addEffect(new FearFireFoesEffect());
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
}
@@ -53,7 +52,8 @@ class FearFireFoesEffect extends OneShotEffect {
FearFireFoesEffect() {
super(Outcome.Benefit);
- staticText = "and 1 damage to each other creature with the same controller";
+ staticText = "{this} deals X damage to target creature " +
+ "and 1 damage to each other creature with the same controller";
}
private FearFireFoesEffect(final FearFireFoesEffect effect) {
@@ -67,6 +67,7 @@ class FearFireFoesEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
+ new DamageTargetEffect(GetXValue.instance).apply(game, source);
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
if (permanent == null) {
return false;
diff --git a/Mage.Sets/src/mage/cards/f/FireAndBrimstone.java b/Mage.Sets/src/mage/cards/f/FireAndBrimstone.java
index f7258a53ac3..701183efdd5 100644
--- a/Mage.Sets/src/mage/cards/f/FireAndBrimstone.java
+++ b/Mage.Sets/src/mage/cards/f/FireAndBrimstone.java
@@ -1,7 +1,6 @@
package mage.cards.f;
-import mage.abilities.effects.common.DamageControllerEffect;
-import mage.abilities.effects.common.DamageTargetEffect;
+import mage.abilities.effects.common.DamageTargetAndYouEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
@@ -30,8 +29,7 @@ public final class FireAndBrimstone extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{W}{W}");
// Fire and Brimstone deals 4 damage to target player who attacked this turn and 4 damage to you.
- this.getSpellAbility().addEffect(new DamageTargetEffect(4));
- this.getSpellAbility().addEffect(new DamageControllerEffect(4).setText("and 4 damage to you"));
+ this.getSpellAbility().addEffect(new DamageTargetAndYouEffect(4));
this.getSpellAbility().addTarget(new TargetPlayer(1, 1, false, filter));
}
diff --git a/Mage.Sets/src/mage/cards/f/Fireslinger.java b/Mage.Sets/src/mage/cards/f/Fireslinger.java
index d0312a29d12..92e78e6cb22 100644
--- a/Mage.Sets/src/mage/cards/f/Fireslinger.java
+++ b/Mage.Sets/src/mage/cards/f/Fireslinger.java
@@ -4,8 +4,7 @@ import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
-import mage.abilities.effects.common.DamageControllerEffect;
-import mage.abilities.effects.common.DamageTargetEffect;
+import mage.abilities.effects.common.DamageTargetAndYouEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
@@ -26,8 +25,7 @@ public final class Fireslinger extends CardImpl {
this.power = new MageInt(1);
this.toughness = new MageInt(1);
- Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(1), new TapSourceCost());
- ability.addEffect(new DamageControllerEffect(1).setText("and 1 damage to you"));
+ Ability ability = new SimpleActivatedAbility(new DamageTargetAndYouEffect(1), new TapSourceCost());
ability.addTarget(new TargetAnyTarget());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/f/Firespout.java b/Mage.Sets/src/mage/cards/f/Firespout.java
index c8ed77f2799..a992ca121da 100644
--- a/Mage.Sets/src/mage/cards/f/Firespout.java
+++ b/Mage.Sets/src/mage/cards/f/Firespout.java
@@ -1,17 +1,20 @@
-
package mage.cards.f;
+import mage.abilities.Ability;
import mage.abilities.condition.common.ManaWasSpentCondition;
import mage.abilities.decorator.ConditionalOneShotEffect;
+import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DamageAllEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
+import mage.constants.Outcome;
import mage.filter.StaticFilters;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.AbilityPredicate;
+import mage.game.Game;
import java.util.UUID;
@@ -30,12 +33,8 @@ public final class Firespout extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{R/G}");
// Firespout deals 3 damage to each creature without flying if {R} was spent to cast Firespout and 3 damage to each creature with flying if {G} was spent to cast it.
- this.getSpellAbility().addEffect(new ConditionalOneShotEffect(
- new DamageAllEffect(3, filter1),
- ManaWasSpentCondition.RED, "{this} deals 3 damage to each creature without flying if {R} was spent to cast this spell"));
- this.getSpellAbility().addEffect(new ConditionalOneShotEffect(
- new DamageAllEffect(3, StaticFilters.FILTER_CREATURE_FLYING),
- ManaWasSpentCondition.GREEN, "and 3 damage to each creature with flying if {G} was spent to cast this spell. (Do both if {R}{G} was spent.)"));
+ this.getSpellAbility().addEffect(new FirespoutEffect());
+
}
private Firespout(final Firespout card) {
@@ -47,3 +46,37 @@ public final class Firespout extends CardImpl {
return new Firespout(this);
}
}
+
+// needed for simultaneous damage
+class FirespoutEffect extends OneShotEffect {
+
+ private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature without flying");
+ static {
+ filter.add(Predicates.not(new AbilityPredicate(FlyingAbility.class)));
+ }
+
+ FirespoutEffect() {
+ super(Outcome.Benefit);
+ staticText = "{this} deals 3 damage to each creature without flying if {R} was spent to cast this spell " +
+ "and 3 damage to each creature with flying if {G} was spent to cast this spell. " +
+ "(Do both if {R}{G} was spent.)";
+ }
+
+ private FirespoutEffect(final FirespoutEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public FirespoutEffect copy() {
+ return new FirespoutEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ new ConditionalOneShotEffect(new DamageAllEffect(3, filter),
+ ManaWasSpentCondition.RED).apply(game, source);
+ new ConditionalOneShotEffect(new DamageAllEffect(3, StaticFilters.FILTER_CREATURE_FLYING),
+ ManaWasSpentCondition.GREEN).apply(game, source);
+ return true;
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/f/FirstVolley.java b/Mage.Sets/src/mage/cards/f/FirstVolley.java
index 8186188eeae..da125cec8a0 100644
--- a/Mage.Sets/src/mage/cards/f/FirstVolley.java
+++ b/Mage.Sets/src/mage/cards/f/FirstVolley.java
@@ -1,9 +1,6 @@
-
package mage.cards.f;
-import mage.abilities.effects.Effect;
-import mage.abilities.effects.common.DamageTargetControllerEffect;
-import mage.abilities.effects.common.DamageTargetEffect;
+import mage.abilities.effects.common.DamageTargetAndTargetControllerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
@@ -23,10 +20,7 @@ public final class FirstVolley extends CardImpl {
this.subtype.add(SubType.ARCANE);
// First Volley deals 1 damage to target creature and 1 damage to that creature's controller.
- this.getSpellAbility().addEffect(new DamageTargetEffect(1));
- Effect effect = new DamageTargetControllerEffect(1);
- effect.setText("and 1 damage to that creature's controller");
- this.getSpellAbility().addEffect(effect);
+ this.getSpellAbility().addEffect(new DamageTargetAndTargetControllerEffect(1, 1));
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
}
diff --git a/Mage.Sets/src/mage/cards/f/ForgeDevil.java b/Mage.Sets/src/mage/cards/f/ForgeDevil.java
index 6229e8bbba7..a5ce17b7fa7 100644
--- a/Mage.Sets/src/mage/cards/f/ForgeDevil.java
+++ b/Mage.Sets/src/mage/cards/f/ForgeDevil.java
@@ -1,22 +1,20 @@
-
package mage.cards.f;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
-import mage.abilities.effects.Effect;
-import mage.abilities.effects.common.DamageControllerEffect;
-import mage.abilities.effects.common.DamageTargetEffect;
+import mage.abilities.effects.common.DamageTargetAndYouEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.target.common.TargetCreaturePermanent;
+import java.util.UUID;
+
/**
*
- * @author anonymous
+ * @author xenohedron
*/
public final class ForgeDevil extends CardImpl {
@@ -28,13 +26,8 @@ public final class ForgeDevil extends CardImpl {
this.toughness = new MageInt(1);
// When Forge Devil enters the battlefield, it deals 1 damage to target creature and 1 damage to you.
- Effect effect = new DamageTargetEffect(1);
- effect.setText("it deals 1 damage to target creature");
- Ability ability = new EntersBattlefieldTriggeredAbility(effect);
+ Ability ability = new EntersBattlefieldTriggeredAbility(new DamageTargetAndYouEffect(1));
ability.addTarget(new TargetCreaturePermanent());
- effect = new DamageControllerEffect(1);
- effect.setText("and 1 damage to you");
- ability.addEffect(effect);
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/g/GoblinArtillery.java b/Mage.Sets/src/mage/cards/g/GoblinArtillery.java
index 77b0946d7be..c5c19053734 100644
--- a/Mage.Sets/src/mage/cards/g/GoblinArtillery.java
+++ b/Mage.Sets/src/mage/cards/g/GoblinArtillery.java
@@ -4,8 +4,7 @@ import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
-import mage.abilities.effects.common.DamageControllerEffect;
-import mage.abilities.effects.common.DamageTargetEffect;
+import mage.abilities.effects.common.DamageTargetAndYouEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
@@ -26,8 +25,9 @@ public final class GoblinArtillery extends CardImpl {
this.power = new MageInt(1);
this.toughness = new MageInt(3);
- Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(2), new TapSourceCost());
- ability.addEffect(new DamageControllerEffect(3).setText("and 3 damage to you"));
+
+ // {T}: This creature deals 2 damage to any target and 3 damage to you.
+ Ability ability = new SimpleActivatedAbility(new DamageTargetAndYouEffect(2, 3), new TapSourceCost());
ability.addTarget(new TargetAnyTarget());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/g/GrangerGuildmage.java b/Mage.Sets/src/mage/cards/g/GrangerGuildmage.java
index aa45d3eb1c8..c7dbd57ec8f 100644
--- a/Mage.Sets/src/mage/cards/g/GrangerGuildmage.java
+++ b/Mage.Sets/src/mage/cards/g/GrangerGuildmage.java
@@ -1,25 +1,23 @@
-
package mage.cards.g;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl;
-import mage.abilities.effects.common.DamageControllerEffect;
-import mage.abilities.effects.common.DamageTargetEffect;
+import mage.abilities.effects.common.DamageTargetAndYouEffect;
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
import mage.abilities.keyword.FirstStrikeAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.SubType;
import mage.constants.Duration;
-import mage.constants.Zone;
+import mage.constants.SubType;
import mage.target.common.TargetAnyTarget;
import mage.target.common.TargetCreaturePermanent;
+import java.util.UUID;
+
/**
*
* @author fireshoes
@@ -34,9 +32,8 @@ public final class GrangerGuildmage extends CardImpl {
this.toughness = new MageInt(1);
// {R}, {tap}: Granger Guildmage deals 1 damage to any target and 1 damage to you.
- Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(1), new ManaCostsImpl<>("{R}"));
+ Ability ability = new SimpleActivatedAbility(new DamageTargetAndYouEffect(1, 1), new ManaCostsImpl<>("{R}"));
ability.addCost(new TapSourceCost());
- ability.addEffect(new DamageControllerEffect(1).setText("and 1 damage to you"));
ability.addTarget(new TargetAnyTarget());
this.addAbility(ability);
diff --git a/Mage.Sets/src/mage/cards/h/HailStorm.java b/Mage.Sets/src/mage/cards/h/HailStorm.java
index 8668f420724..71c0938b515 100644
--- a/Mage.Sets/src/mage/cards/h/HailStorm.java
+++ b/Mage.Sets/src/mage/cards/h/HailStorm.java
@@ -1,14 +1,18 @@
-
package mage.cards.h;
-import java.util.UUID;
+import mage.abilities.Ability;
+import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DamageAllEffect;
import mage.abilities.effects.common.DamageControllerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
+import mage.constants.Outcome;
import mage.filter.StaticFilters;
import mage.filter.common.FilterAttackingCreature;
+import mage.game.Game;
+
+import java.util.UUID;
/**
*
@@ -20,9 +24,7 @@ public final class HailStorm extends CardImpl {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{G}{G}");
// Hail Storm deals 2 damage to each attacking creature and 1 damage to you and each creature you control.
- this.getSpellAbility().addEffect(new DamageAllEffect(2, new FilterAttackingCreature()));
- this.getSpellAbility().addEffect(new DamageControllerEffect(1).setText("and 1 damage to you"));
- this.getSpellAbility().addEffect(new DamageAllEffect(1, StaticFilters.FILTER_PERMANENT_CREATURE_CONTROLLED).setText("and each creature you control."));
+ this.getSpellAbility().addEffect(new HailStormEffect());
}
private HailStorm(final HailStorm card) {
@@ -34,3 +36,32 @@ public final class HailStorm extends CardImpl {
return new HailStorm(this);
}
}
+
+// needed for simultaneous damage
+class HailStormEffect extends OneShotEffect {
+
+ private static final FilterAttackingCreature filter = new FilterAttackingCreature();
+
+ HailStormEffect() {
+ super(Outcome.Benefit);
+ staticText = "{this} deals 2 damage to each attacking creature " +
+ "and 1 damage to you and each creature you control";
+ }
+
+ private HailStormEffect(final HailStormEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public HailStormEffect copy() {
+ return new HailStormEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ new DamageAllEffect(2, filter).apply(game, source);
+ new DamageControllerEffect(1).apply(game, source);
+ new DamageAllEffect(1, StaticFilters.FILTER_PERMANENT_CREATURE_CONTROLLED).apply(game, source);
+ return true;
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/h/HungryFlames.java b/Mage.Sets/src/mage/cards/h/HungryFlames.java
index bd704cb8b14..d458bb6b8d2 100644
--- a/Mage.Sets/src/mage/cards/h/HungryFlames.java
+++ b/Mage.Sets/src/mage/cards/h/HungryFlames.java
@@ -1,14 +1,9 @@
package mage.cards.h;
-import mage.abilities.Ability;
-import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.DamageTargetAndTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.Outcome;
-import mage.game.Game;
-import mage.game.permanent.Permanent;
-import mage.players.Player;
import mage.target.common.TargetCreaturePermanent;
import mage.target.common.TargetPlayerOrPlaneswalker;
@@ -22,10 +17,10 @@ public final class HungryFlames extends CardImpl {
public HungryFlames(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{R}");
- // Hungry Flames deals 3 damage to target creature and 2 damage to target player.
- this.getSpellAbility().addTarget(new TargetCreaturePermanent());
- this.getSpellAbility().addTarget(new TargetPlayerOrPlaneswalker());
- this.getSpellAbility().addEffect(new HungryFlamesEffect());
+ // Hungry Flames deals 3 damage to target creature and 2 damage to target player or planeswalker.
+ this.getSpellAbility().addTarget(new TargetCreaturePermanent().setTargetTag(1));
+ this.getSpellAbility().addTarget(new TargetPlayerOrPlaneswalker().setTargetTag(2));
+ this.getSpellAbility().addEffect(new DamageTargetAndTargetEffect(3, 2));
}
private HungryFlames(final HungryFlames card) {
@@ -37,37 +32,4 @@ public final class HungryFlames extends CardImpl {
return new HungryFlames(this);
}
- private static class HungryFlamesEffect extends OneShotEffect {
-
- HungryFlamesEffect() {
- super(Outcome.Damage);
- this.staticText = "{this} deals 3 damage to target creature and 2 damage to target player or planeswalker";
- }
-
- private HungryFlamesEffect(final HungryFlamesEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- Permanent permanent = game.getPermanent(source.getTargets().get(0).getFirstTarget());
- Player player = game.getPlayer(source.getTargets().get(1).getFirstTarget());
-
- if (permanent != null) {
- permanent.damage(3, source.getSourceId(), source, game, false, true);
- }
-
- if (player != null) {
- player.damage(2, source.getSourceId(), source, game);
- }
-
- return true;
- }
-
- @Override
- public HungryFlamesEffect copy() {
- return new HungryFlamesEffect(this);
- }
- }
-
}
diff --git a/Mage.Sets/src/mage/cards/i/InsultInjury.java b/Mage.Sets/src/mage/cards/i/InsultInjury.java
index 9a9caea0e0c..a55864cd52c 100644
--- a/Mage.Sets/src/mage/cards/i/InsultInjury.java
+++ b/Mage.Sets/src/mage/cards/i/InsultInjury.java
@@ -1,8 +1,8 @@
package mage.cards.i;
import mage.abilities.Ability;
-import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.ReplacementEffectImpl;
+import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.effects.common.continuous.DamageCantBePreventedEffect;
import mage.abilities.keyword.AftermathAbility;
import mage.cards.CardSetInfo;
@@ -13,10 +13,9 @@ import mage.constants.Outcome;
import mage.constants.SpellAbilityType;
import mage.game.Game;
import mage.game.events.GameEvent;
-import mage.game.permanent.Permanent;
-import mage.players.Player;
import mage.target.common.TargetCreaturePermanent;
import mage.target.common.TargetPlayerOrPlaneswalker;
+import mage.target.targetpointer.EachTargetPointer;
import mage.util.CardUtil;
import java.util.UUID;
@@ -41,7 +40,7 @@ public final class InsultInjury extends SplitCard {
getRightHalfCard().addAbility(new AftermathAbility().setRuleAtTheTop(true));
getRightHalfCard().getSpellAbility().addTarget(new TargetCreaturePermanent());
getRightHalfCard().getSpellAbility().addTarget(new TargetPlayerOrPlaneswalker());
- getRightHalfCard().getSpellAbility().addEffect(new InjuryEffect());
+ getRightHalfCard().getSpellAbility().addEffect(new DamageTargetEffect(2).setTargetPointer(new EachTargetPointer()));
}
private InsultInjury(final InsultInjury card) {
@@ -87,36 +86,3 @@ class InsultDoubleDamageEffect extends ReplacementEffectImpl {
return false;
}
}
-
-class InjuryEffect extends OneShotEffect {
-
- InjuryEffect() {
- super(Outcome.Damage);
- this.staticText = "{this} deals 2 damage to target creature and 2 damage to target player or planeswalker";
- }
-
- private InjuryEffect(final InjuryEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- Permanent permanent = game.getPermanent(source.getTargets().get(0).getFirstTarget());
- Player player = game.getPlayer(source.getTargets().get(1).getFirstTarget());
-
- if (permanent != null) {
- permanent.damage(2, source.getSourceId(), source, game, false, true);
- }
-
- if (player != null) {
- player.damage(2, source.getSourceId(), source, game);
- }
-
- return true;
- }
-
- @Override
- public InjuryEffect copy() {
- return new InjuryEffect(this);
- }
-}
diff --git a/Mage.Sets/src/mage/cards/i/InvasionOfRegatha.java b/Mage.Sets/src/mage/cards/i/InvasionOfRegatha.java
index 6096e876853..f6068787a4b 100644
--- a/Mage.Sets/src/mage/cards/i/InvasionOfRegatha.java
+++ b/Mage.Sets/src/mage/cards/i/InvasionOfRegatha.java
@@ -3,7 +3,7 @@ package mage.cards.i;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SiegeAbility;
-import mage.abilities.effects.common.DamageTargetEffect;
+import mage.abilities.effects.common.DamageTargetAndTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
@@ -14,7 +14,6 @@ import mage.filter.common.FilterPermanentOrPlayer;
import mage.filter.predicate.mageobject.AnotherPredicate;
import mage.target.common.TargetCreaturePermanent;
import mage.target.common.TargetPermanentOrPlayer;
-import mage.target.targetpointer.SecondTargetPointer;
import java.util.UUID;
@@ -43,19 +42,9 @@ public final class InvasionOfRegatha extends CardImpl {
this.addAbility(new SiegeAbility());
// When Invasion of Regatha enters the battlefield, it deals 4 damage to another target battle or opponent and 1 damage to up to one target creature.
- Ability ability = new EntersBattlefieldTriggeredAbility(
- new DamageTargetEffect(
- 4, true,
- "another target battle or opponent", "it"
-
- ).setUseOnlyTargetPointer(true)
- );
- ability.addTarget(new TargetPermanentOrPlayer(filter));
- ability.addEffect(new DamageTargetEffect(1)
- .setUseOnlyTargetPointer(true)
- .setTargetPointer(new SecondTargetPointer())
- .setText("and 1 damage to up to one target creature"));
- ability.addTarget(new TargetCreaturePermanent(0, 1));
+ Ability ability = new EntersBattlefieldTriggeredAbility(new DamageTargetAndTargetEffect(4, 1));
+ ability.addTarget(new TargetPermanentOrPlayer(filter).setTargetTag(1));
+ ability.addTarget(new TargetCreaturePermanent(0, 1).setTargetTag(2));
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/j/JudgmentBolt.java b/Mage.Sets/src/mage/cards/j/JudgmentBolt.java
index d0581aa5d85..164fc2740aa 100644
--- a/Mage.Sets/src/mage/cards/j/JudgmentBolt.java
+++ b/Mage.Sets/src/mage/cards/j/JudgmentBolt.java
@@ -1,16 +1,19 @@
package mage.cards.j;
+import mage.abilities.Ability;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
-import mage.abilities.effects.common.DamageTargetControllerEffect;
-import mage.abilities.effects.common.DamageTargetEffect;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.DamageTargetAndTargetControllerEffect;
import mage.abilities.hint.Hint;
import mage.abilities.hint.ValueHint;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
+import mage.constants.Outcome;
import mage.constants.SubType;
import mage.filter.common.FilterControlledPermanent;
+import mage.game.Game;
import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
@@ -20,16 +23,14 @@ import java.util.UUID;
*/
public final class JudgmentBolt extends CardImpl {
- private static final DynamicValue xValue = new PermanentsOnBattlefieldCount(new FilterControlledPermanent(SubType.EQUIPMENT));
+ static final DynamicValue xValue = new PermanentsOnBattlefieldCount(new FilterControlledPermanent(SubType.EQUIPMENT));
private static final Hint hint = new ValueHint("Equipment you control", xValue);
public JudgmentBolt(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{R}");
// Judgment Bolt deals 5 damage to target creature and X damage to that creature's controller, where X is the number of Equipment you control.
- this.getSpellAbility().addEffect(new DamageTargetEffect(5));
- this.getSpellAbility().addEffect(new DamageTargetControllerEffect(xValue)
- .setText("and X damage to that creature's controller, where X is the number of Equipment you control"));
+ this.getSpellAbility().addEffect(new JudgmentBoltEffect());
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
this.getSpellAbility().addHint(hint);
}
@@ -43,3 +44,28 @@ public final class JudgmentBolt extends CardImpl {
return new JudgmentBolt(this);
}
}
+
+// too lazy to handle dynamic value properly in the common class
+class JudgmentBoltEffect extends OneShotEffect {
+
+ JudgmentBoltEffect() {
+ super(Outcome.Benefit);
+ staticText = "{this} deals 5 damage to target creature and X damage to that creature's controller," +
+ " where X is the number of Equipment you control";
+ }
+
+ private JudgmentBoltEffect(final JudgmentBoltEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public JudgmentBoltEffect copy() {
+ return new JudgmentBoltEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ return new DamageTargetAndTargetControllerEffect(5, JudgmentBolt.xValue.calculate(game, source, this))
+ .apply(game, source);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/k/KamahlsSledge.java b/Mage.Sets/src/mage/cards/k/KamahlsSledge.java
index 2349adb94c2..38f2f014855 100644
--- a/Mage.Sets/src/mage/cards/k/KamahlsSledge.java
+++ b/Mage.Sets/src/mage/cards/k/KamahlsSledge.java
@@ -2,7 +2,7 @@ package mage.cards.k;
import mage.abilities.condition.common.ThresholdCondition;
import mage.abilities.decorator.ConditionalOneShotEffect;
-import mage.abilities.effects.common.DamageTargetControllerEffect;
+import mage.abilities.effects.common.DamageTargetAndTargetControllerEffect;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -21,15 +21,16 @@ public final class KamahlsSledge extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{5}{R}{R}");
// Kamahl's Sledge deals 4 damage to target creature.
- this.getSpellAbility().addEffect(new DamageTargetEffect(4));
- this.getSpellAbility().addTarget(new TargetCreaturePermanent());
-
// Threshold - If seven or more cards are in your graveyard, instead Kamahl's Sledge deals 4 damage to that creature and 4 damage to that creature's controller.
this.getSpellAbility().addEffect(new ConditionalOneShotEffect(
- new DamageTargetControllerEffect(4), ThresholdCondition.instance, "
" +
- AbilityWord.THRESHOLD.formatWord() + "If seven or more cards are in your graveyard, " +
- "instead {this} deals 4 damage to that creature and 4 damage to that creature's controller."
+ new DamageTargetAndTargetControllerEffect(4, 4),
+ new DamageTargetEffect(4),
+ ThresholdCondition.instance,
+ "{this} deals 4 damage to target creature.
" +
+ AbilityWord.THRESHOLD.formatWord() + "If seven or more cards are in your graveyard, " +
+ "instead {this} deals 4 damage to that creature and 4 damage to that creature's controller."
));
+ this.getSpellAbility().addTarget(new TargetCreaturePermanent());
}
private KamahlsSledge(final KamahlsSledge card) {
diff --git a/Mage.Sets/src/mage/cards/l/Lunge.java b/Mage.Sets/src/mage/cards/l/Lunge.java
index b3bb6efb96f..feb397b976c 100644
--- a/Mage.Sets/src/mage/cards/l/Lunge.java
+++ b/Mage.Sets/src/mage/cards/l/Lunge.java
@@ -1,15 +1,13 @@
-
package mage.cards.l;
-import java.util.UUID;
-import mage.abilities.effects.Effect;
-import mage.abilities.effects.common.DamageTargetEffect;
+import mage.abilities.effects.common.DamageTargetAndTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.target.common.TargetCreaturePermanent;
import mage.target.common.TargetPlayerOrPlaneswalker;
-import mage.target.targetpointer.SecondTargetPointer;
+
+import java.util.UUID;
/**
*
@@ -21,14 +19,10 @@ public final class Lunge extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{R}");
// Lunge deals 2 damage to target creature and 2 damage to target player.
- this.getSpellAbility().addEffect(new DamageTargetEffect(2).setUseOnlyTargetPointer(true));
- this.getSpellAbility().addTarget(new TargetCreaturePermanent());
+ this.getSpellAbility().addEffect(new DamageTargetAndTargetEffect(2, 2));
+ this.getSpellAbility().addTarget(new TargetCreaturePermanent().setTargetTag(1));
+ this.getSpellAbility().addTarget(new TargetPlayerOrPlaneswalker().setTargetTag(2));
- Effect effect = new DamageTargetEffect(2).setUseOnlyTargetPointer(true);
- effect.setTargetPointer(new SecondTargetPointer());
- effect.setText("and 2 damage to target player or planeswalker");
- this.getSpellAbility().addEffect(effect);
- this.getSpellAbility().addTarget(new TargetPlayerOrPlaneswalker());
}
private Lunge(final Lunge card) {
diff --git a/Mage.Sets/src/mage/cards/n/NeonatesRush.java b/Mage.Sets/src/mage/cards/n/NeonatesRush.java
index 148c3eeb053..b907fd0b0b3 100644
--- a/Mage.Sets/src/mage/cards/n/NeonatesRush.java
+++ b/Mage.Sets/src/mage/cards/n/NeonatesRush.java
@@ -1,10 +1,9 @@
package mage.cards.n;
-import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.Condition;
import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition;
-import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.DamageTargetAndTargetControllerEffect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.cost.SpellCostReductionSourceEffect;
import mage.abilities.hint.ConditionHint;
@@ -12,13 +11,9 @@ import mage.abilities.hint.Hint;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.FilterPermanent;
-import mage.game.Game;
-import mage.game.permanent.Permanent;
-import mage.players.Player;
import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
@@ -42,7 +37,8 @@ public final class NeonatesRush extends CardImpl {
).addHint(hint).setRuleAtTheTop(true));
// Neonate's Rush deals 1 damage to target creature and 1 damage to its controller. Draw a card.
- this.getSpellAbility().addEffect(new NeonatesRushEffect());
+ this.getSpellAbility().addEffect(new DamageTargetAndTargetControllerEffect(1, 1)
+ .setText("{this} deals 1 damage to target creature and 1 damage to its controller"));
this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1));
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
}
@@ -56,34 +52,3 @@ public final class NeonatesRush extends CardImpl {
return new NeonatesRush(this);
}
}
-
-class NeonatesRushEffect extends OneShotEffect {
-
- NeonatesRushEffect() {
- super(Outcome.Benefit);
- staticText = "{this} deals 1 damage to target creature and 1 damage to its controller.";
- }
-
- private NeonatesRushEffect(final NeonatesRushEffect effect) {
- super(effect);
- }
-
- @Override
- public NeonatesRushEffect copy() {
- return new NeonatesRushEffect(this);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- Permanent permanent = game.getPermanent(source.getFirstTarget());
- if (permanent == null) {
- return false;
- }
- permanent.damage(1, source.getSourceId(), source, game);
- Player player = game.getPlayer(permanent.getControllerId());
- if (player != null) {
- player.damage(1, source.getSourceId(), source, game);
- }
- return true;
- }
-}
diff --git a/Mage.Sets/src/mage/cards/o/OrcishArtillery.java b/Mage.Sets/src/mage/cards/o/OrcishArtillery.java
index c4589153f12..52f7b05ec24 100644
--- a/Mage.Sets/src/mage/cards/o/OrcishArtillery.java
+++ b/Mage.Sets/src/mage/cards/o/OrcishArtillery.java
@@ -1,20 +1,18 @@
-
package mage.cards.o;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
-import mage.abilities.effects.common.DamageControllerEffect;
-import mage.abilities.effects.common.DamageTargetEffect;
+import mage.abilities.effects.common.DamageTargetAndYouEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
-import mage.constants.Zone;
import mage.target.common.TargetAnyTarget;
+import java.util.UUID;
+
/**
*
* @author Plopman
@@ -30,9 +28,8 @@ public final class OrcishArtillery extends CardImpl {
this.toughness = new MageInt(3);
// {tap}: Orcish Artillery deals 2 damage to any target and 3 damage to you.
- Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(2), new TapSourceCost());
+ Ability ability = new SimpleActivatedAbility(new DamageTargetAndYouEffect(2, 3), new TapSourceCost());
ability.addTarget(new TargetAnyTarget());
- ability.addEffect(new DamageControllerEffect(3).setText("and 3 damage to you"));
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/o/OrcishCannonade.java b/Mage.Sets/src/mage/cards/o/OrcishCannonade.java
index fe965ea9193..c33c70f1ae6 100644
--- a/Mage.Sets/src/mage/cards/o/OrcishCannonade.java
+++ b/Mage.Sets/src/mage/cards/o/OrcishCannonade.java
@@ -1,16 +1,14 @@
-
package mage.cards.o;
-import java.util.UUID;
-import mage.abilities.effects.Effect;
-import mage.abilities.effects.common.DamageControllerEffect;
-import mage.abilities.effects.common.DamageTargetEffect;
+import mage.abilities.effects.common.DamageTargetAndYouEffect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.target.common.TargetAnyTarget;
+import java.util.UUID;
+
/**
*
* @author LevelX2
@@ -21,11 +19,9 @@ public final class OrcishCannonade extends CardImpl {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{R}{R}");
// Orcish Cannonade deals 2 damage to any target and 3 damage to you.
- this.getSpellAbility().addEffect(new DamageTargetEffect(2));
+ this.getSpellAbility().addEffect(new DamageTargetAndYouEffect(2, 3));
this.getSpellAbility().addTarget(new TargetAnyTarget());
- Effect effect = new DamageControllerEffect(3);
- effect.setText("and 3 damage to you");
- this.getSpellAbility().addEffect(effect);
+
// Draw a card.
this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1).concatBy("
"));
}
diff --git a/Mage.Sets/src/mage/cards/o/OrcishCannoneers.java b/Mage.Sets/src/mage/cards/o/OrcishCannoneers.java
index bf873ae3736..a2ad2abab8a 100644
--- a/Mage.Sets/src/mage/cards/o/OrcishCannoneers.java
+++ b/Mage.Sets/src/mage/cards/o/OrcishCannoneers.java
@@ -1,21 +1,18 @@
-
package mage.cards.o;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
-import mage.abilities.effects.Effect;
-import mage.abilities.effects.common.DamageControllerEffect;
-import mage.abilities.effects.common.DamageTargetEffect;
+import mage.abilities.effects.common.DamageTargetAndYouEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
-import mage.constants.Zone;
import mage.target.common.TargetAnyTarget;
+import java.util.UUID;
+
/**
*
* @author LoneFox
@@ -31,10 +28,8 @@ public final class OrcishCannoneers extends CardImpl {
this.toughness = new MageInt(3);
// {tap}: Orcish Cannoneers deals 2 damage to any target and 3 damage to you.
- Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(2), new TapSourceCost()); ability.addTarget(new TargetAnyTarget());
- Effect effect = new DamageControllerEffect(3);
- effect.setText("and 3 damage to you");
- ability.addEffect(effect);
+ Ability ability = new SimpleActivatedAbility(new DamageTargetAndYouEffect(2, 3), new TapSourceCost());
+ ability.addTarget(new TargetAnyTarget());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/p/PsionicBlast.java b/Mage.Sets/src/mage/cards/p/PsionicBlast.java
index 254ff05fe3d..47ca09ad239 100644
--- a/Mage.Sets/src/mage/cards/p/PsionicBlast.java
+++ b/Mage.Sets/src/mage/cards/p/PsionicBlast.java
@@ -1,7 +1,6 @@
package mage.cards.p;
-import mage.abilities.effects.common.DamageControllerEffect;
-import mage.abilities.effects.common.DamageTargetEffect;
+import mage.abilities.effects.common.DamageTargetAndYouEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
@@ -18,8 +17,7 @@ public final class PsionicBlast extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{U}");
// Psionic Blast deals 4 damage to any target and 2 damage to you.
- this.getSpellAbility().addEffect(new DamageTargetEffect(4));
- this.getSpellAbility().addEffect(new DamageControllerEffect(2).setText("and 2 damage to you"));
+ this.getSpellAbility().addEffect(new DamageTargetAndYouEffect(4, 2));
this.getSpellAbility().addTarget(new TargetAnyTarget());
}
diff --git a/Mage.Sets/src/mage/cards/p/PsionicEntity.java b/Mage.Sets/src/mage/cards/p/PsionicEntity.java
index 02b0b3a1e10..3c7121bef86 100644
--- a/Mage.Sets/src/mage/cards/p/PsionicEntity.java
+++ b/Mage.Sets/src/mage/cards/p/PsionicEntity.java
@@ -1,20 +1,18 @@
-
package mage.cards.p;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
-import mage.abilities.effects.common.DamageSelfEffect;
-import mage.abilities.effects.common.DamageTargetEffect;
-import mage.constants.SubType;
+import mage.abilities.effects.common.DamageTargetAndSelfEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.Zone;
+import mage.constants.SubType;
import mage.target.common.TargetAnyTarget;
+import java.util.UUID;
+
/**
*
* @author TheElk801
@@ -29,8 +27,7 @@ public final class PsionicEntity extends CardImpl {
this.toughness = new MageInt(2);
// {tap}: Psionic Entity deals 2 damage to any target and 3 damage to itself.
- Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(2), new TapSourceCost());
- ability.addEffect(new DamageSelfEffect(3).setText("and 3 damage to itself"));
+ Ability ability = new SimpleActivatedAbility(new DamageTargetAndSelfEffect(2, 3), new TapSourceCost());
ability.addTarget(new TargetAnyTarget());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/p/PsionicSliver.java b/Mage.Sets/src/mage/cards/p/PsionicSliver.java
index beb44bdeed6..08eb41473cb 100644
--- a/Mage.Sets/src/mage/cards/p/PsionicSliver.java
+++ b/Mage.Sets/src/mage/cards/p/PsionicSliver.java
@@ -1,28 +1,24 @@
-
package mage.cards.p;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.common.TapSourceCost;
-import mage.abilities.effects.common.DamageSelfEffect;
-import mage.abilities.effects.common.DamageTargetEffect;
+import mage.abilities.effects.common.DamageTargetAndSelfEffect;
import mage.abilities.effects.common.continuous.GainAbilityAllEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
-import mage.constants.Zone;
import mage.filter.common.FilterCreaturePermanent;
import mage.target.common.TargetAnyTarget;
+import java.util.UUID;
+
/**
- *
- * @author anonymous
- * @see mage.sets.seventhedition.RecklessEmbermage
+ * @author xenohedron
*/
public final class PsionicSliver extends CardImpl {
@@ -35,11 +31,7 @@ public final class PsionicSliver extends CardImpl {
this.toughness = new MageInt(2);
// All Sliver creatures have "{T}: This creature deals 2 damage to any target and 3 damage to itself."
- Ability ability = new SimpleActivatedAbility(
- new DamageTargetEffect(2).setText("This creature deals 2 damage to any target"),
- new TapSourceCost()
- );
- ability.addEffect(new DamageSelfEffect(3).setText("3 damage to itself."));
+ Ability ability = new SimpleActivatedAbility(new DamageTargetAndSelfEffect(2, 3), new TapSourceCost());
ability.addTarget(new TargetAnyTarget());
this.addAbility(
new SimpleStaticAbility(new GainAbilityAllEffect(ability, Duration.WhileOnBattlefield, filter,
diff --git a/Mage.Sets/src/mage/cards/p/PunishTheEnemy.java b/Mage.Sets/src/mage/cards/p/PunishTheEnemy.java
index aa474c088ee..a56e57185f6 100644
--- a/Mage.Sets/src/mage/cards/p/PunishTheEnemy.java
+++ b/Mage.Sets/src/mage/cards/p/PunishTheEnemy.java
@@ -1,15 +1,14 @@
-
package mage.cards.p;
-import java.util.UUID;
-import mage.abilities.effects.common.DamageTargetEffect;
+import mage.abilities.effects.common.DamageTargetAndTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.target.Target;
import mage.target.common.TargetCreaturePermanent;
import mage.target.common.TargetPlayerOrPlaneswalker;
+import java.util.UUID;
+
/**
*
* @author LevelX2
@@ -20,11 +19,9 @@ public final class PunishTheEnemy extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{4}{R}");
// Punish the Enemy deals 3 damage to target player and 3 damage to target creature.
- this.getSpellAbility().addEffect(new DamageTargetEffect(3, true, "target player or planeswalker and 3 damage to target creature"));
- Target target = new TargetPlayerOrPlaneswalker();
- this.getSpellAbility().addTarget(target);
- target = new TargetCreaturePermanent();
- this.getSpellAbility().addTarget(target);
+ this.getSpellAbility().addEffect(new DamageTargetAndTargetEffect(3, 3));
+ this.getSpellAbility().addTarget(new TargetPlayerOrPlaneswalker().setTargetTag(1));
+ this.getSpellAbility().addTarget(new TargetCreaturePermanent().setTargetTag(2));
}
private PunishTheEnemy(final PunishTheEnemy card) {
diff --git a/Mage.Sets/src/mage/cards/r/RadiatingLightning.java b/Mage.Sets/src/mage/cards/r/RadiatingLightning.java
index 106f3759b40..afd1b213b5d 100644
--- a/Mage.Sets/src/mage/cards/r/RadiatingLightning.java
+++ b/Mage.Sets/src/mage/cards/r/RadiatingLightning.java
@@ -1,12 +1,10 @@
-
package mage.cards.r;
-import mage.abilities.effects.common.DamageAllControlledTargetEffect;
-import mage.abilities.effects.common.DamageTargetEffect;
+import mage.abilities.effects.common.DamageTargetAndAllControlledEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.filter.common.FilterCreaturePermanent;
+import mage.filter.StaticFilters;
import mage.target.TargetPlayer;
import java.util.UUID;
@@ -20,10 +18,9 @@ public final class RadiatingLightning extends CardImpl {
public RadiatingLightning(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{3}{R}");
-
// Radiating Lightning deals 3 damage to target player and 1 damage to each creature that player controls.
- this.getSpellAbility().addEffect(new DamageTargetEffect(3));
- this.getSpellAbility().addEffect(new DamageAllControlledTargetEffect(1, new FilterCreaturePermanent()).setText("and 1 damage to each creature that player controls"));
+ this.getSpellAbility().addEffect(new DamageTargetAndAllControlledEffect(
+ 3, 1, StaticFilters.FILTER_PERMANENT_CREATURE));
this.getSpellAbility().addTarget(new TargetPlayer());
}
diff --git a/Mage.Sets/src/mage/cards/r/RakdosFirewheeler.java b/Mage.Sets/src/mage/cards/r/RakdosFirewheeler.java
index e9db64acfe7..aa004843f01 100644
--- a/Mage.Sets/src/mage/cards/r/RakdosFirewheeler.java
+++ b/Mage.Sets/src/mage/cards/r/RakdosFirewheeler.java
@@ -3,8 +3,7 @@ package mage.cards.r;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
-import mage.abilities.effects.Effect;
-import mage.abilities.effects.common.DamageTargetEffect;
+import mage.abilities.effects.common.DamageTargetAndTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
@@ -29,11 +28,9 @@ public final class RakdosFirewheeler extends CardImpl {
this.toughness = new MageInt(3);
// When Rakdos Firewheeler enters the battlefield, it deals 2 damage to target opponent and 2 damage to up to one target creature or planeswalker.
- Effect effect = new DamageTargetEffect(2);
- effect.setText("it deals 2 damage to target opponent and 2 damage to up to one target creature or planeswalker");
- Ability ability = new EntersBattlefieldTriggeredAbility(effect, false);
- ability.addTarget(new TargetOpponent());
- ability.addTarget(new TargetCreatureOrPlaneswalker(0, 1));
+ Ability ability = new EntersBattlefieldTriggeredAbility(new DamageTargetAndTargetEffect(2, 2));
+ ability.addTarget(new TargetOpponent().setTargetTag(1));
+ ability.addTarget(new TargetCreatureOrPlaneswalker(0, 1).setTargetTag(2));
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/r/RecklessRage.java b/Mage.Sets/src/mage/cards/r/RecklessRage.java
index 79b30f0ec35..c052f4c0c8a 100644
--- a/Mage.Sets/src/mage/cards/r/RecklessRage.java
+++ b/Mage.Sets/src/mage/cards/r/RecklessRage.java
@@ -1,19 +1,15 @@
package mage.cards.r;
-import mage.abilities.effects.common.DamageTargetEffect;
+import mage.abilities.effects.common.DamageTargetAndTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.filter.StaticFilters;
import mage.target.TargetPermanent;
import mage.target.common.TargetControlledCreaturePermanent;
-import mage.target.common.TargetCreaturePermanent;
-import mage.target.targetpointer.SecondTargetPointer;
import java.util.UUID;
-import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL;
-
/**
* @author JayDi85
*/
@@ -23,12 +19,9 @@ public final class RecklessRage extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{R}");
// Reckless Rage deals 4 damage to target creature you don't control and 2 damage to target creature you control.
- this.getSpellAbility().addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL));
- this.getSpellAbility().addEffect(new DamageTargetEffect(4).setUseOnlyTargetPointer(true));
- this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent());
- this.getSpellAbility().addEffect(new DamageTargetEffect(2).setUseOnlyTargetPointer(true)
- .setText("and 2 damage to target creature you control")
- .setTargetPointer(new SecondTargetPointer()));
+ this.getSpellAbility().addEffect(new DamageTargetAndTargetEffect(4, 2));
+ this.getSpellAbility().addTarget(new TargetPermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL).setTargetTag(1));
+ this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent().setTargetTag(2));
}
private RecklessRage(final RecklessRage card) {
diff --git a/Mage.Sets/src/mage/cards/s/SeismicWave.java b/Mage.Sets/src/mage/cards/s/SeismicWave.java
index ebc6f6a8e18..e3cf4e810a4 100644
--- a/Mage.Sets/src/mage/cards/s/SeismicWave.java
+++ b/Mage.Sets/src/mage/cards/s/SeismicWave.java
@@ -28,8 +28,8 @@ public final class SeismicWave extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{R}");
// Seismic Wave deals 2 damage to any target and 1 damage to each nonartifact creature target opponent controls.
- this.getSpellAbility().addTarget(new TargetAnyTarget().withChooseHint("2 damage"));
- this.getSpellAbility().addTarget(new TargetOpponent().withChooseHint("1 damage to each nonartifact creature target opponent controls"));
+ this.getSpellAbility().addTarget(new TargetAnyTarget().withChooseHint("to deal 2 damage"));
+ this.getSpellAbility().addTarget(new TargetOpponent().withChooseHint("1 damage to each nonartifact creature they control"));
this.getSpellAbility().addEffect(new SeismicWaveEffect());
}
@@ -51,7 +51,7 @@ class SeismicWaveEffect extends OneShotEffect {
filter.add(Predicates.not(CardType.ARTIFACT.getPredicate()));
}
- public SeismicWaveEffect() {
+ SeismicWaveEffect() {
super(Outcome.Damage);
this.staticText = "{this} deals 2 damage to any target and 1 damage to each nonartifact creature target opponent controls";
}
diff --git a/Mage.Sets/src/mage/cards/s/SelfDestruct.java b/Mage.Sets/src/mage/cards/s/SelfDestruct.java
index 8e57a76ef4c..4d4fbb70754 100644
--- a/Mage.Sets/src/mage/cards/s/SelfDestruct.java
+++ b/Mage.Sets/src/mage/cards/s/SelfDestruct.java
@@ -89,7 +89,7 @@ class SelfDestructEffect extends OneShotEffect {
if (player != null) {
player.damage(power, creature.getId(), source, game);
}
- permanent.damage(power, permanent.getId(), source, game);
+ creature.damage(power, creature.getId(), source, game);
return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/s/ShadowGuildmage.java b/Mage.Sets/src/mage/cards/s/ShadowGuildmage.java
index af5c2d262a4..eafc596a173 100644
--- a/Mage.Sets/src/mage/cards/s/ShadowGuildmage.java
+++ b/Mage.Sets/src/mage/cards/s/ShadowGuildmage.java
@@ -1,21 +1,20 @@
package mage.cards.s;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl;
-import mage.abilities.effects.common.DamageControllerEffect;
-import mage.abilities.effects.common.DamageTargetEffect;
+import mage.abilities.effects.common.DamageTargetAndYouEffect;
import mage.abilities.effects.common.PutOnLibraryTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
-import mage.constants.Zone;
-import mage.target.common.TargetControlledCreaturePermanent;
import mage.target.common.TargetAnyTarget;
+import mage.target.common.TargetControlledCreaturePermanent;
+
+import java.util.UUID;
/**
*
@@ -37,9 +36,8 @@ public final class ShadowGuildmage extends CardImpl {
this.addAbility(ability);
// {R}, {tap}: Shadow Guildmage deals 1 damage to any target and 1 damage to you.
- ability = new SimpleActivatedAbility(new DamageTargetEffect(1), new ManaCostsImpl<>("{R}"));
+ ability = new SimpleActivatedAbility(new DamageTargetAndYouEffect(1, 1), new ManaCostsImpl<>("{R}"));
ability.addCost(new TapSourceCost());
- ability.addEffect(new DamageControllerEffect(1).setText("and 1 damage to you"));
ability.addTarget(new TargetAnyTarget());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/s/ShockerUnshakable.java b/Mage.Sets/src/mage/cards/s/ShockerUnshakable.java
index 661ecfe7032..d4a1b2c57d1 100644
--- a/Mage.Sets/src/mage/cards/s/ShockerUnshakable.java
+++ b/Mage.Sets/src/mage/cards/s/ShockerUnshakable.java
@@ -6,8 +6,7 @@ import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.common.MyTurnCondition;
import mage.abilities.decorator.ConditionalContinuousEffect;
-import mage.abilities.effects.common.DamageTargetControllerEffect;
-import mage.abilities.effects.common.DamageTargetEffect;
+import mage.abilities.effects.common.DamageTargetAndTargetControllerEffect;
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
import mage.abilities.keyword.FirstStrikeAbility;
import mage.cards.CardImpl;
@@ -42,8 +41,7 @@ public final class ShockerUnshakable extends CardImpl {
)));
// Vibro-Shock Gauntlets -- When Shocker enters, he deals 2 damage to target creature and 2 damage to that creature's controller.
- Ability ability = new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(2, "he"));
- ability.addEffect(new DamageTargetControllerEffect(2).setText("and 2 damage to that creature's controller"));
+ Ability ability = new EntersBattlefieldTriggeredAbility(new DamageTargetAndTargetControllerEffect(2, 2));
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability.withFlavorWord("Vibro-Shock Gauntlets"));
}
diff --git a/Mage.Sets/src/mage/cards/s/ShowerOfSparks.java b/Mage.Sets/src/mage/cards/s/ShowerOfSparks.java
index db144515b38..8d13d17e372 100644
--- a/Mage.Sets/src/mage/cards/s/ShowerOfSparks.java
+++ b/Mage.Sets/src/mage/cards/s/ShowerOfSparks.java
@@ -1,13 +1,14 @@
package mage.cards.s;
-import java.util.UUID;
-import mage.abilities.effects.common.DamageTargetEffect;
+import mage.abilities.effects.common.DamageTargetAndTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.target.common.TargetCreaturePermanent;
import mage.target.common.TargetPlayerOrPlaneswalker;
+import java.util.UUID;
+
/**
*
* @author LevelX2
@@ -17,10 +18,10 @@ public final class ShowerOfSparks extends CardImpl {
public ShowerOfSparks(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{R}");
- // Shower of sparks deals 1 damage to target creature and 1 damage to target player.
- this.getSpellAbility().addEffect(new DamageTargetEffect(1, true, "target creature and 1 damage to target player or planeswalker"));
- this.getSpellAbility().addTarget(new TargetCreaturePermanent());
- this.getSpellAbility().addTarget(new TargetPlayerOrPlaneswalker());
+ // Shower of Sparks deals 1 damage to target creature and 1 damage to target player or planeswalker.
+ this.getSpellAbility().addEffect(new DamageTargetAndTargetEffect(1, 1));
+ this.getSpellAbility().addTarget(new TargetCreaturePermanent().setTargetTag(1));
+ this.getSpellAbility().addTarget(new TargetPlayerOrPlaneswalker().setTargetTag(2));
}
private ShowerOfSparks(final ShowerOfSparks card) {
diff --git a/Mage.Sets/src/mage/cards/s/SoulOfShandalar.java b/Mage.Sets/src/mage/cards/s/SoulOfShandalar.java
index f18b7cf1613..5b4fe81e8b6 100644
--- a/Mage.Sets/src/mage/cards/s/SoulOfShandalar.java
+++ b/Mage.Sets/src/mage/cards/s/SoulOfShandalar.java
@@ -1,4 +1,3 @@
-
package mage.cards.s;
import mage.MageInt;
@@ -93,7 +92,7 @@ class SoulOfShandalarEffect extends OneShotEffect {
class SoulOfShandalarTarget extends TargetPermanent {
- public SoulOfShandalarTarget() {
+ SoulOfShandalarTarget() {
super(0, 1, new FilterCreaturePermanent("creature that the targeted player or planeswalker's controller controls"));
}
diff --git a/Mage.Sets/src/mage/cards/s/Sparksmith.java b/Mage.Sets/src/mage/cards/s/Sparksmith.java
index 7a11696bfc3..158c416bd05 100644
--- a/Mage.Sets/src/mage/cards/s/Sparksmith.java
+++ b/Mage.Sets/src/mage/cards/s/Sparksmith.java
@@ -1,35 +1,30 @@
-
package mage.cards.s;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
-import mage.abilities.effects.common.DamageControllerEffect;
-import mage.abilities.effects.common.DamageTargetEffect;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.DamageTargetAndYouEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
+import mage.constants.Outcome;
import mage.constants.SubType;
-import mage.constants.Zone;
import mage.filter.FilterPermanent;
+import mage.game.Game;
import mage.target.common.TargetCreaturePermanent;
+import java.util.UUID;
+
/**
*
* @author Plopman
*/
public final class Sparksmith extends CardImpl {
- private static final FilterPermanent filter = new FilterPermanent("Goblins on the battlefield");
- static {
- filter.add(SubType.GOBLIN.getPredicate());
- }
- private static final DynamicValue xValue = new PermanentsOnBattlefieldCount(filter);
-
public Sparksmith(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{R}");
this.subtype.add(SubType.GOBLIN);
@@ -38,11 +33,8 @@ public final class Sparksmith extends CardImpl {
this.toughness = new MageInt(1);
// {tap}: Sparksmith deals X damage to target creature and X damage to you, where X is the number of Goblins on the battlefield.
- Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(xValue)
- .setText("{this} deals X damage to target creature"), new TapSourceCost());
+ Ability ability = new SimpleActivatedAbility(new SparksmithEffect(), new TapSourceCost());
ability.addTarget(new TargetCreaturePermanent());
- ability.addEffect(new DamageControllerEffect(xValue)
- .setText("and X damage to you, where X is the number of Goblins on the battlefield"));
this.addAbility(ability);
}
@@ -55,3 +47,35 @@ public final class Sparksmith extends CardImpl {
return new Sparksmith(this);
}
}
+
+// too lazy to handle dynamic value properly in the common class
+class SparksmithEffect extends OneShotEffect {
+
+
+ private static final FilterPermanent filter = new FilterPermanent("Goblins on the battlefield");
+ static {
+ filter.add(SubType.GOBLIN.getPredicate());
+ }
+ private static final DynamicValue xValue = new PermanentsOnBattlefieldCount(filter);
+
+ SparksmithEffect() {
+ super(Outcome.Benefit);
+ staticText = "{this} deals X damage to target creature and X damage to you, " +
+ "where X is the number of Goblins on the battlefield";
+ }
+
+ private SparksmithEffect(final SparksmithEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public SparksmithEffect copy() {
+ return new SparksmithEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ int amount = xValue.calculate(game, source, this);
+ return new DamageTargetAndYouEffect(amount, amount).apply(game, source);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/s/SunflareShaman.java b/Mage.Sets/src/mage/cards/s/SunflareShaman.java
index 70e6d1ada1a..31a468e6fa8 100644
--- a/Mage.Sets/src/mage/cards/s/SunflareShaman.java
+++ b/Mage.Sets/src/mage/cards/s/SunflareShaman.java
@@ -1,26 +1,24 @@
-
package mage.cards.s;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
-import mage.abilities.effects.common.DamageSelfEffect;
-import mage.abilities.effects.common.DamageTargetEffect;
+import mage.abilities.effects.common.DamageTargetAndSelfEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
-import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetAnyTarget;
+import java.util.UUID;
+
/**
*
* @author jeffwadsworth
@@ -60,7 +58,7 @@ class SunflareShamanEffect extends OneShotEffect {
filter.add(SubType.ELEMENTAL.getPredicate());
}
- public SunflareShamanEffect() {
+ SunflareShamanEffect() {
super(Outcome.Damage);
this.staticText = "{this} deals X damage to any target and X damage to itself, where X is the number of Elemental cards in your graveyard";
}
@@ -78,9 +76,8 @@ class SunflareShamanEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
- int ElementalsInYourGraveyard = controller.getGraveyard().count(filter, game);
- new DamageTargetEffect(ElementalsInYourGraveyard).apply(game, source);
- new DamageSelfEffect(ElementalsInYourGraveyard).apply(game, source);
+ int amount = controller.getGraveyard().count(filter, game);
+ new DamageTargetAndSelfEffect(amount, amount).apply(game, source);
return true;
}
return false;
diff --git a/Mage.Sets/src/mage/cards/s/SynchronizedSpellcraft.java b/Mage.Sets/src/mage/cards/s/SynchronizedSpellcraft.java
index 1a4e756ff70..699427c2482 100644
--- a/Mage.Sets/src/mage/cards/s/SynchronizedSpellcraft.java
+++ b/Mage.Sets/src/mage/cards/s/SynchronizedSpellcraft.java
@@ -3,15 +3,13 @@ package mage.cards.s;
import mage.abilities.Ability;
import mage.abilities.dynamicvalue.common.PartyCount;
import mage.abilities.effects.OneShotEffect;
-import mage.abilities.effects.common.DamageTargetEffect;
+import mage.abilities.effects.common.DamageTargetAndTargetControllerEffect;
import mage.abilities.hint.common.PartyCountHint;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.game.Game;
-import mage.game.permanent.Permanent;
-import mage.players.Player;
import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
@@ -25,7 +23,6 @@ public final class SynchronizedSpellcraft extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{4}{R}");
// Synchronized Spellcraft deals 4 damage to target creature and X damage to that creature's controller, where X is the number of creatures in your party.
- this.getSpellAbility().addEffect(new DamageTargetEffect(4));
this.getSpellAbility().addEffect(new SynchronizedSpellcraftEffect());
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
this.getSpellAbility().addHint(PartyCountHint.instance);
@@ -45,7 +42,8 @@ class SynchronizedSpellcraftEffect extends OneShotEffect {
SynchronizedSpellcraftEffect() {
super(Outcome.Benefit);
- staticText = "and X damage to that creature's controller, " +
+ staticText = "{this} deals 4 damage to target creature " +
+ "and X damage to that creature's controller, " +
"where X is the number of creatures in your party. " + PartyCount.getReminder();
}
@@ -60,18 +58,7 @@ class SynchronizedSpellcraftEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
- int partyCount = PartyCount.instance.calculate(game, source, this);
- if (partyCount < 1) {
- return false;
- }
- Permanent permanent = game.getPermanentOrLKIBattlefield(source.getFirstTarget());
- if (permanent == null) {
- return false;
- }
- Player player = game.getPlayer(permanent.getControllerId());
- if (player == null) {
- return false;
- }
- return player.damage(partyCount, source.getSourceId(), source, game) > 0;
+ int amount = PartyCount.instance.calculate(game, source, this);
+ return new DamageTargetAndTargetControllerEffect(4, amount).apply(game, source);
}
}
diff --git a/Mage.Sets/src/mage/cards/t/TheFallOfKroog.java b/Mage.Sets/src/mage/cards/t/TheFallOfKroog.java
index 2d16a039f9d..c52ca2da726 100644
--- a/Mage.Sets/src/mage/cards/t/TheFallOfKroog.java
+++ b/Mage.Sets/src/mage/cards/t/TheFallOfKroog.java
@@ -2,8 +2,7 @@ package mage.cards.t;
import mage.MageItem;
import mage.abilities.Ability;
-import mage.abilities.effects.common.DamageAllControlledTargetEffect;
-import mage.abilities.effects.common.DamageTargetEffect;
+import mage.abilities.effects.common.DamageTargetAndAllControlledEffect;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -32,12 +31,9 @@ public final class TheFallOfKroog extends CardImpl {
this.getSpellAbility().addEffect(new DestroyTargetEffect()
.setText("choose target opponent. Destroy target land that player controls")
.setTargetPointer(new SecondTargetPointer()));
- this.getSpellAbility().addEffect(new DamageTargetEffect(
- 3, true, "that player"
- ));
- this.getSpellAbility().addEffect(new DamageAllControlledTargetEffect(
- 1, StaticFilters.FILTER_PERMANENT_CREATURE
- ).setText("and 1 damage to each creature they control"));
+ this.getSpellAbility().addEffect(new DamageTargetAndAllControlledEffect(
+ 3, 1, StaticFilters.FILTER_PERMANENT_CREATURE
+ ).setText("{this} deals 3 damage to that player and 1 damage to each creature they control"));
this.getSpellAbility().addTarget(new TargetOpponent());
this.getSpellAbility().addTarget(new TheFallOfKroogTarget());
}
diff --git a/Mage.Sets/src/mage/cards/t/TrickShot.java b/Mage.Sets/src/mage/cards/t/TrickShot.java
index 9eeb2b6385f..e233fc090af 100644
--- a/Mage.Sets/src/mage/cards/t/TrickShot.java
+++ b/Mage.Sets/src/mage/cards/t/TrickShot.java
@@ -1,6 +1,6 @@
package mage.cards.t;
-import mage.abilities.effects.common.DamageTargetEffect;
+import mage.abilities.effects.common.DamageTargetAndTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
@@ -9,7 +9,6 @@ import mage.filter.predicate.other.AnotherTargetPredicate;
import mage.filter.predicate.permanent.TokenPredicate;
import mage.target.TargetPermanent;
import mage.target.common.TargetCreaturePermanent;
-import mage.target.targetpointer.SecondTargetPointer;
import java.util.UUID;
@@ -31,12 +30,7 @@ public final class TrickShot extends CardImpl {
// Trick Shot deals 6 damage to target creature and 2 damage to up to one other target creature token.
this.getSpellAbility().addTarget(new TargetCreaturePermanent().setTargetTag(1));
this.getSpellAbility().addTarget(new TargetPermanent(0, 1, filter).setTargetTag(2));
- this.getSpellAbility().addEffect(new DamageTargetEffect(6, true, "", true));
- this.getSpellAbility().addEffect(
- new DamageTargetEffect(2, true, "", true)
- .setTargetPointer(new SecondTargetPointer())
- .setText("and 2 damage to up to one other target creature token")
- );
+ this.getSpellAbility().addEffect(new DamageTargetAndTargetEffect(6, 2));
}
private TrickShot(final TrickShot card) {
diff --git a/Mage.Sets/src/mage/cards/u/UnleashShell.java b/Mage.Sets/src/mage/cards/u/UnleashShell.java
index a52d7e657df..ffd4fd4c34d 100644
--- a/Mage.Sets/src/mage/cards/u/UnleashShell.java
+++ b/Mage.Sets/src/mage/cards/u/UnleashShell.java
@@ -1,14 +1,13 @@
package mage.cards.u;
-import java.util.UUID;
-
-import mage.abilities.effects.common.DamageTargetControllerEffect;
-import mage.abilities.effects.common.DamageTargetEffect;
+import mage.abilities.effects.common.DamageTargetAndTargetControllerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.target.common.TargetCreatureOrPlaneswalker;
+import java.util.UUID;
+
/**
*
* @author weirddan455
@@ -19,9 +18,8 @@ public final class UnleashShell extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{R}{R}");
// Unleash Shell deals 5 damage to target creature or planeswalker and 2 damage to that permanent's controller.
- this.getSpellAbility().addEffect(new DamageTargetEffect(5));
- this.getSpellAbility().addEffect(new DamageTargetControllerEffect(2).setText("and 2 damage to that permanent's controller"));
this.getSpellAbility().addTarget(new TargetCreatureOrPlaneswalker());
+ this.getSpellAbility().addEffect(new DamageTargetAndTargetControllerEffect(5, 2));
}
private UnleashShell(final UnleashShell card) {
diff --git a/Mage.Sets/src/mage/cards/w/WildfireHowl.java b/Mage.Sets/src/mage/cards/w/WildfireHowl.java
index c61f9d097a4..e897682c8de 100644
--- a/Mage.Sets/src/mage/cards/w/WildfireHowl.java
+++ b/Mage.Sets/src/mage/cards/w/WildfireHowl.java
@@ -33,6 +33,8 @@ public final class WildfireHowl extends CardImpl {
GiftWasPromisedCondition.TRUE, "{this} deals 2 damage to each creature. " +
"If the gift was promised, instead {this} deals 1 damage to any target and 2 damage to each creature"
).addEffect(new DamageAllEffect(2, StaticFilters.FILTER_PERMANENT_CREATURE)));
+ // ConditionalOneShotEffect doesn't call processAction between effects, so currently works
+ // if that gets changed (which it perhaps should?) then need to make this a single effect
this.getSpellAbility().setTargetAdjuster(new ConditionalTargetAdjuster(
GiftWasPromisedCondition.TRUE, new TargetAnyTarget()
));
diff --git a/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndAllControlledEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndAllControlledEffect.java
index 843bd5609ce..b62896f7e90 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndAllControlledEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndAllControlledEffect.java
@@ -5,6 +5,7 @@ import mage.abilities.Mode;
import mage.abilities.effects.OneShotEffect;
import mage.constants.Outcome;
import mage.filter.FilterPermanent;
+import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
@@ -18,6 +19,13 @@ public class DamageTargetAndAllControlledEffect extends OneShotEffect {
private final int secondAmount;
private final FilterPermanent filter;
+ /**
+ * Deals simultaneous damage to the target and to each creature the target controls
+ */
+ public DamageTargetAndAllControlledEffect(int amount) {
+ this(amount, amount, StaticFilters.FILTER_PERMANENT_CREATURE);
+ }
+
/**
* Deals simultaneous damage to the target and to each creature the target controls
*/
@@ -54,7 +62,7 @@ public class DamageTargetAndAllControlledEffect extends OneShotEffect {
Player controller = game.getPlayerOrPlaneswalkerController(getTargetPointer().getFirst(game, source));
if (controller != null) {
for (Permanent perm : game.getBattlefield().getAllActivePermanents(filter, controller.getId(), game)) {
- perm.damage(secondAmount, source.getSourceId(), source, game, false, true);
+ perm.damage(secondAmount, source.getSourceId(), source, game);
}
}
return true;
@@ -65,9 +73,11 @@ public class DamageTargetAndAllControlledEffect extends OneShotEffect {
if (staticText != null && !staticText.isEmpty()) {
return staticText;
}
- return "{this} deals " + firstAmount + "damage to " +
- getTargetPointer().describeTargets(mode.getTargets(), "that creature") +
+ String description = getTargetPointer().describeTargets(mode.getTargets(), "that player");
+ return "{this} deals " + firstAmount + "damage to " + description +
" and " + secondAmount + " damage to each " + filter.getMessage() +
- " that player or that planeswalker's controller controls";
+ " that player" +
+ (description.contains("planeswalker") ? " or that planeswalker's controller" : "") +
+ " controls";
}
}
diff --git a/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndTargetControllerEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndTargetControllerEffect.java
index de20b0cb6aa..50f4bbda6ec 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndTargetControllerEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndTargetControllerEffect.java
@@ -44,7 +44,10 @@ public class DamageTargetAndTargetControllerEffect extends OneShotEffect {
Permanent permanent = game.getPermanent(targetId);
if (permanent != null) {
permanent.damage(firstAmount, source.getSourceId(), source, game);
- Player player = game.getPlayer(permanent.getControllerId());
+ }
+ Permanent lki = game.getPermanentOrLKIBattlefield(targetId);
+ if (lki != null) {
+ Player player = game.getPlayer(lki.getControllerId());
if (player != null) {
player.damage(secondAmount, source.getSourceId(), source, game);
}
@@ -58,8 +61,9 @@ public class DamageTargetAndTargetControllerEffect extends OneShotEffect {
if (staticText != null && !staticText.isEmpty()) {
return staticText;
}
- return "{this} deals " + firstAmount + "damage to " +
- getTargetPointer().describeTargets(mode.getTargets(), "that creature") +
- " and " + secondAmount + "damage to that creature's controller";
+ String description = getTargetPointer().describeTargets(mode.getTargets(), "that creature");
+ return "{this} deals " + firstAmount + "damage to " + description +
+ " and " + secondAmount + "damage to that " +
+ (description.contains(" or ") ? "permanent's" : "creature's") + " controller";
}
}
From 0ae2c2b86e6dd6b32e2123cc990aa4611200a329 Mon Sep 17 00:00:00 2001
From: xenohedron <12538125+xenohedron@users.noreply.github.com>
Date: Mon, 10 Nov 2025 01:52:30 -0500
Subject: [PATCH 09/14] remove custom multitarget handling from
DamageTargetEffect
---
.../src/mage/cards/a/AvalancheOfSector7.java | 2 +-
Mage.Sets/src/mage/cards/b/BarretWallace.java | 2 +-
.../src/mage/cards/b/BedeckBedazzle.java | 5 ++-
.../src/mage/cards/b/BurningTreeShaman.java | 2 +-
Mage.Sets/src/mage/cards/c/CutIn.java | 6 +---
.../src/mage/cards/e/ExpansionExplosion.java | 3 +-
.../src/mage/cards/f/FieryAnnihilation.java | 2 +-
.../mage/cards/f/FlamescrollCelebrant.java | 2 +-
Mage.Sets/src/mage/cards/h/HarshMentor.java | 2 +-
.../src/mage/cards/i/IchneumonDruid.java | 7 ++--
.../src/mage/cards/i/ImmolationShaman.java | 2 +-
.../src/mage/cards/j/JeskaiRevelation.java | 2 +-
.../mage/cards/m/ManticoreOfTheGauntlet.java | 4 +--
.../src/mage/cards/n/NivMizzetGuildpact.java | 1 -
Mage.Sets/src/mage/cards/s/Simulacrum.java | 3 +-
.../effects/common/DamageTargetEffect.java | 36 ++-----------------
16 files changed, 19 insertions(+), 62 deletions(-)
diff --git a/Mage.Sets/src/mage/cards/a/AvalancheOfSector7.java b/Mage.Sets/src/mage/cards/a/AvalancheOfSector7.java
index 6ef053cc5c2..863b8b6def2 100644
--- a/Mage.Sets/src/mage/cards/a/AvalancheOfSector7.java
+++ b/Mage.Sets/src/mage/cards/a/AvalancheOfSector7.java
@@ -65,7 +65,7 @@ public final class AvalancheOfSector7 extends CardImpl {
class AvalancheOfSector7TriggeredAbility extends TriggeredAbilityImpl {
AvalancheOfSector7TriggeredAbility() {
- super(Zone.BATTLEFIELD, new DamageTargetEffect(1, true, "that player", true));
+ super(Zone.BATTLEFIELD, new DamageTargetEffect(1, true, "that player"));
setTriggerPhrase("Whenever an opponent activates an ability of an artifact they control, ");
}
diff --git a/Mage.Sets/src/mage/cards/b/BarretWallace.java b/Mage.Sets/src/mage/cards/b/BarretWallace.java
index e040ec94df4..d7e9c48f3ad 100644
--- a/Mage.Sets/src/mage/cards/b/BarretWallace.java
+++ b/Mage.Sets/src/mage/cards/b/BarretWallace.java
@@ -49,7 +49,7 @@ public final class BarretWallace extends CardImpl {
// Whenever Barret Wallace attacks, it deals damage equal to the number of equipped creatures you control to defending player.
this.addAbility(new AttacksTriggeredAbility(
- new DamageTargetEffect(xValue, true, "it", true)
+ new DamageTargetEffect(xValue, true, "it")
.setText("it deals damage equal to the number of equipped creatures you control to defending player"),
false, null, SetTargetPointer.PLAYER
).withRuleTextReplacement(true).addHint(hint));
diff --git a/Mage.Sets/src/mage/cards/b/BedeckBedazzle.java b/Mage.Sets/src/mage/cards/b/BedeckBedazzle.java
index b0b65e3af98..2b76d6a4d8c 100644
--- a/Mage.Sets/src/mage/cards/b/BedeckBedazzle.java
+++ b/Mage.Sets/src/mage/cards/b/BedeckBedazzle.java
@@ -1,7 +1,6 @@
package mage.cards.b;
import mage.abilities.Ability;
-import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DamageTargetEffect;
@@ -75,9 +74,9 @@ class BedazzleEffect extends OneShotEffect {
if (permanent != null) {
permanent.destroy(source, game, false);
}
- Effect effect = new DamageTargetEffect(StaticValue.get(2), true, "", true);
+ Effect effect = new DamageTargetEffect(2);
effect.setTargetPointer(new FixedTarget(source.getTargets().get(1).getFirstTarget(), game));
effect.apply(game, source);
return true;
}
-}
\ No newline at end of file
+}
diff --git a/Mage.Sets/src/mage/cards/b/BurningTreeShaman.java b/Mage.Sets/src/mage/cards/b/BurningTreeShaman.java
index 4b0fd3eac54..9295e4ec8b0 100644
--- a/Mage.Sets/src/mage/cards/b/BurningTreeShaman.java
+++ b/Mage.Sets/src/mage/cards/b/BurningTreeShaman.java
@@ -46,7 +46,7 @@ public final class BurningTreeShaman extends CardImpl {
class BurningTreeShamanTriggeredAbility extends TriggeredAbilityImpl {
BurningTreeShamanTriggeredAbility() {
- super(Zone.BATTLEFIELD, new DamageTargetEffect(StaticValue.get(1), true, "that player", true));
+ super(Zone.BATTLEFIELD, new DamageTargetEffect(StaticValue.get(1), true, "that player"));
}
private BurningTreeShamanTriggeredAbility(final BurningTreeShamanTriggeredAbility ability) {
diff --git a/Mage.Sets/src/mage/cards/c/CutIn.java b/Mage.Sets/src/mage/cards/c/CutIn.java
index 9d23e5e6a82..a0d73d9e607 100644
--- a/Mage.Sets/src/mage/cards/c/CutIn.java
+++ b/Mage.Sets/src/mage/cards/c/CutIn.java
@@ -22,11 +22,7 @@ public final class CutIn extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{R}");
// Cut In deals 4 damage to target creature.
- this.getSpellAbility().addEffect(
- new DamageTargetEffect(4)
- .setUseOnlyTargetPointer(true)
- .setTargetPointer(new FirstTargetPointer())
- );
+ this.getSpellAbility().addEffect(new DamageTargetEffect(4));
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
// Create a Young Hero Role token attached to up to one target creature you control.
diff --git a/Mage.Sets/src/mage/cards/e/ExpansionExplosion.java b/Mage.Sets/src/mage/cards/e/ExpansionExplosion.java
index 4c6fb4651f6..3115b588596 100644
--- a/Mage.Sets/src/mage/cards/e/ExpansionExplosion.java
+++ b/Mage.Sets/src/mage/cards/e/ExpansionExplosion.java
@@ -1,7 +1,6 @@
package mage.cards.e;
import mage.abilities.Ability;
-import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CopyTargetStackObjectEffect;
@@ -82,7 +81,7 @@ class ExplosionEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
int xValue = CardUtil.getSourceCostsTag(game, source, "X", 0);
- Effect effect = new DamageTargetEffect(StaticValue.get(xValue), true, "", true);
+ Effect effect = new DamageTargetEffect(xValue);
effect.setTargetPointer(new FixedTarget(source.getFirstTarget(), game));
effect.apply(game, source);
Player player = game.getPlayer(source.getTargets().get(1).getFirstTarget());
diff --git a/Mage.Sets/src/mage/cards/f/FieryAnnihilation.java b/Mage.Sets/src/mage/cards/f/FieryAnnihilation.java
index ad81f8376c0..2196e4d6699 100644
--- a/Mage.Sets/src/mage/cards/f/FieryAnnihilation.java
+++ b/Mage.Sets/src/mage/cards/f/FieryAnnihilation.java
@@ -37,7 +37,7 @@ public final class FieryAnnihilation extends CardImpl {
// Fiery Annihilation deals 5 damage to target creature. Exile up to one target Equipment attached to that creature. If that creature would die this turn, exile it instead.
this.getSpellAbility().addEffect(new DamageTargetEffect(
- 5, true, "target creature", true
+ 5, true, "target creature"
));
this.getSpellAbility().addEffect(new ExileTargetEffect()
.setTargetPointer(new SecondTargetPointer())
diff --git a/Mage.Sets/src/mage/cards/f/FlamescrollCelebrant.java b/Mage.Sets/src/mage/cards/f/FlamescrollCelebrant.java
index de0e113027a..ee7cedd0b5a 100644
--- a/Mage.Sets/src/mage/cards/f/FlamescrollCelebrant.java
+++ b/Mage.Sets/src/mage/cards/f/FlamescrollCelebrant.java
@@ -73,7 +73,7 @@ public final class FlamescrollCelebrant extends ModalDoubleFacedCard {
class FlamescrollCelebrantTriggeredAbility extends TriggeredAbilityImpl {
FlamescrollCelebrantTriggeredAbility() {
- super(Zone.BATTLEFIELD, new DamageTargetEffect(StaticValue.get(1), true, "that player", true));
+ super(Zone.BATTLEFIELD, new DamageTargetEffect(StaticValue.get(1), true, "that player"));
}
private FlamescrollCelebrantTriggeredAbility(final FlamescrollCelebrantTriggeredAbility ability) {
diff --git a/Mage.Sets/src/mage/cards/h/HarshMentor.java b/Mage.Sets/src/mage/cards/h/HarshMentor.java
index d317abe73b2..281c340514d 100644
--- a/Mage.Sets/src/mage/cards/h/HarshMentor.java
+++ b/Mage.Sets/src/mage/cards/h/HarshMentor.java
@@ -48,7 +48,7 @@ public final class HarshMentor extends CardImpl {
class HarshMentorTriggeredAbility extends TriggeredAbilityImpl {
HarshMentorTriggeredAbility() {
- super(Zone.BATTLEFIELD, new DamageTargetEffect(StaticValue.get(2), true, "that player", true));
+ super(Zone.BATTLEFIELD, new DamageTargetEffect(StaticValue.get(2), true, "that player"));
}
private HarshMentorTriggeredAbility(final HarshMentorTriggeredAbility ability) {
diff --git a/Mage.Sets/src/mage/cards/i/IchneumonDruid.java b/Mage.Sets/src/mage/cards/i/IchneumonDruid.java
index 8ab18e4d7ab..174558742a7 100644
--- a/Mage.Sets/src/mage/cards/i/IchneumonDruid.java
+++ b/Mage.Sets/src/mage/cards/i/IchneumonDruid.java
@@ -1,4 +1,3 @@
-
package mage.cards.i;
import java.util.HashMap;
@@ -50,8 +49,8 @@ public final class IchneumonDruid extends CardImpl {
class IchneumonDruidAbility extends TriggeredAbilityImpl {
- public IchneumonDruidAbility() {
- super(Zone.BATTLEFIELD, new DamageTargetEffect(StaticValue.get(4), false, "that player", true));
+ IchneumonDruidAbility() {
+ super(Zone.BATTLEFIELD, new DamageTargetEffect(StaticValue.get(4), false, "that player"));
}
private IchneumonDruidAbility(final IchneumonDruidAbility ability) {
@@ -95,7 +94,7 @@ class IchneumonDruidWatcher extends Watcher {
private final Map playerInstantCount = new HashMap<>();
- public IchneumonDruidWatcher() {
+ IchneumonDruidWatcher() {
super(WatcherScope.GAME);
}
diff --git a/Mage.Sets/src/mage/cards/i/ImmolationShaman.java b/Mage.Sets/src/mage/cards/i/ImmolationShaman.java
index 79fad9b9bdf..785653ee816 100644
--- a/Mage.Sets/src/mage/cards/i/ImmolationShaman.java
+++ b/Mage.Sets/src/mage/cards/i/ImmolationShaman.java
@@ -67,7 +67,7 @@ public final class ImmolationShaman extends CardImpl {
class ImmolationShamanTriggeredAbility extends TriggeredAbilityImpl {
ImmolationShamanTriggeredAbility() {
- super(Zone.BATTLEFIELD, new DamageTargetEffect(StaticValue.get(1), true, "that player", true));
+ super(Zone.BATTLEFIELD, new DamageTargetEffect(StaticValue.get(1), true, "that player"));
setTriggerPhrase("Whenever an opponent activates an ability of an artifact, creature, or land that isn't a mana ability, ");
}
diff --git a/Mage.Sets/src/mage/cards/j/JeskaiRevelation.java b/Mage.Sets/src/mage/cards/j/JeskaiRevelation.java
index 5a4a488cc07..4a0b4d6f52b 100644
--- a/Mage.Sets/src/mage/cards/j/JeskaiRevelation.java
+++ b/Mage.Sets/src/mage/cards/j/JeskaiRevelation.java
@@ -23,7 +23,7 @@ public final class JeskaiRevelation extends CardImpl {
this.getSpellAbility().addEffect(new ReturnToHandTargetEffect());
this.getSpellAbility().addTarget(new TargetSpellOrPermanent());
this.getSpellAbility().addEffect(new DamageTargetEffect(
- 4, true, "any target", true
+ 4, true, "any target"
).setTargetPointer(new SecondTargetPointer()));
this.getSpellAbility().addTarget(new TargetAnyTarget());
this.getSpellAbility().addEffect(new CreateTokenEffect(new MonasteryMentorToken(), 2));
diff --git a/Mage.Sets/src/mage/cards/m/ManticoreOfTheGauntlet.java b/Mage.Sets/src/mage/cards/m/ManticoreOfTheGauntlet.java
index 53ecb2e7186..60611147a48 100644
--- a/Mage.Sets/src/mage/cards/m/ManticoreOfTheGauntlet.java
+++ b/Mage.Sets/src/mage/cards/m/ManticoreOfTheGauntlet.java
@@ -1,11 +1,9 @@
-
package mage.cards.m;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
-import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
@@ -37,7 +35,7 @@ public final class ManticoreOfTheGauntlet extends CardImpl {
counters.setText("put a -1/-1 counter on target creature you control");
counters.setTargetPointer(new FirstTargetPointer());
- Effect damage = new DamageTargetEffect(StaticValue.get(3), true, "", true);
+ Effect damage = new DamageTargetEffect(3);
damage.setText("{this} deals 3 damage to target opponent or planeswalker.");
damage.setTargetPointer(new SecondTargetPointer());
diff --git a/Mage.Sets/src/mage/cards/n/NivMizzetGuildpact.java b/Mage.Sets/src/mage/cards/n/NivMizzetGuildpact.java
index 2c12aaf71c7..e6336262de4 100644
--- a/Mage.Sets/src/mage/cards/n/NivMizzetGuildpact.java
+++ b/Mage.Sets/src/mage/cards/n/NivMizzetGuildpact.java
@@ -52,7 +52,6 @@ public final class NivMizzetGuildpact extends CardImpl {
// Whenever Niv-Mizzet, Guildpact deals combat damage to a player, it deals X damage to any target, target player draws X cards, and you gain X life, where X is the number of different color pairs among permanents you control that are exactly two colors.
Ability ability = new DealsCombatDamageToAPlayerTriggeredAbility(
new DamageTargetEffect(NivMizzetGuildpactCount.instance)
- .setUseOnlyTargetPointer(true)
.setText("it deals X damage to any target"), false);
ability.addTarget(new TargetAnyTarget());
ability.addEffect(new DrawCardTargetEffect(NivMizzetGuildpactCount.instance)
diff --git a/Mage.Sets/src/mage/cards/s/Simulacrum.java b/Mage.Sets/src/mage/cards/s/Simulacrum.java
index 282bbf88232..ac2fcc450ce 100644
--- a/Mage.Sets/src/mage/cards/s/Simulacrum.java
+++ b/Mage.Sets/src/mage/cards/s/Simulacrum.java
@@ -1,4 +1,3 @@
-
package mage.cards.s;
import java.util.UUID;
@@ -27,7 +26,7 @@ public final class Simulacrum extends CardImpl {
// You gain life equal to the damage dealt to you this turn. Simulacrum deals damage to target creature you control equal to the damage dealt to you this turn.
this.getSpellAbility().addEffect(new GainLifeEffect(new SimulacrumAmount(), "You gain life equal to the damage dealt to you this turn."));
this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent());
- Effect effect = new DamageTargetEffect(new SimulacrumAmount(), true, "target creature you control", true);
+ Effect effect = new DamageTargetEffect(new SimulacrumAmount(), true, "target creature you control");
effect.setText(" {this} deals damage to target creature you control equal to the damage dealt to you this turn.");
this.getSpellAbility().addEffect(effect);
this.getSpellAbility().addWatcher(new AmountOfDamageAPlayerReceivedThisTurnWatcher());
diff --git a/Mage/src/main/java/mage/abilities/effects/common/DamageTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DamageTargetEffect.java
index ae23687ce8a..217f6dd4bdf 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/DamageTargetEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/DamageTargetEffect.java
@@ -4,7 +4,6 @@ import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.StaticValue;
-import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.constants.Outcome;
import mage.game.Game;
@@ -24,7 +23,6 @@ public class DamageTargetEffect extends OneShotEffect {
protected DynamicValue amount;
protected boolean preventable;
protected String targetDescription;
- protected boolean useOnlyTargetPointer; // TODO: investigate why do we ignore targetPointer by default??
protected String sourceName = "{this}";
public DamageTargetEffect(int amount) {
@@ -44,10 +42,6 @@ public class DamageTargetEffect extends OneShotEffect {
this(StaticValue.get(amount), preventable, targetDescription);
}
- public DamageTargetEffect(int amount, boolean preventable, String targetDescription, boolean useOnlyTargetPointer) {
- this(StaticValue.get(amount), preventable, targetDescription, useOnlyTargetPointer);
- }
-
public DamageTargetEffect(int amount, boolean preventable, String targetDescription, String whoDealDamageName) {
this(StaticValue.get(amount), preventable, targetDescription);
this.sourceName = whoDealDamageName;
@@ -67,15 +61,10 @@ public class DamageTargetEffect extends OneShotEffect {
}
public DamageTargetEffect(DynamicValue amount, boolean preventable, String targetDescription) {
- this(amount, preventable, targetDescription, false);
- }
-
- public DamageTargetEffect(DynamicValue amount, boolean preventable, String targetDescription, boolean useOnlyTargetPointer) {
super(Outcome.Damage);
this.amount = amount;
this.preventable = preventable;
this.targetDescription = targetDescription;
- this.useOnlyTargetPointer = useOnlyTargetPointer;
}
public int getAmount() {
@@ -95,21 +84,15 @@ public class DamageTargetEffect extends OneShotEffect {
this.amount = effect.amount.copy();
this.preventable = effect.preventable;
this.targetDescription = effect.targetDescription;
- this.useOnlyTargetPointer = effect.useOnlyTargetPointer;
this.sourceName = effect.sourceName;
}
+ @Override
public DamageTargetEffect withTargetDescription(String targetDescription) {
this.targetDescription = targetDescription;
return this;
}
- // TODO: this should most likely be refactored to not be needed and always use target pointer.
- public Effect setUseOnlyTargetPointer(boolean useOnlyTargetPointer) {
- this.useOnlyTargetPointer = useOnlyTargetPointer;
- return this;
- }
-
@Override
public DamageTargetEffect copy() {
return new DamageTargetEffect(this);
@@ -117,21 +100,6 @@ public class DamageTargetEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
- if (!useOnlyTargetPointer && source.getTargets().size() > 1) {
- for (Target target : source.getTargets()) {
- for (UUID targetId : target.getTargets()) {
- Permanent permanent = game.getPermanent(targetId);
- if (permanent != null) {
- permanent.damage(amount.calculate(game, source, this), source.getSourceId(), source, game, false, preventable);
- }
- Player player = game.getPlayer(targetId);
- if (player != null) {
- player.damage(amount.calculate(game, source, this), source.getSourceId(), source, game, false, preventable);
- }
- }
- }
- return true;
- }
for (UUID targetId : this.getTargetPointer().getTargets(game, source)) {
Permanent permanent = game.getPermanent(targetId);
if (permanent != null) {
@@ -154,7 +122,7 @@ public class DamageTargetEffect extends OneShotEffect {
StringBuilder sb = new StringBuilder();
String message = amount.getMessage();
sb.append(this.sourceName).append(" deals ");
- if (message.isEmpty() || !message.equals("1")) {
+ if (!message.equals("1")) {
sb.append(amount);
}
if (!sb.toString().endsWith(" ")) {
From 1fb0d26db97ee7af769df3e86a9088e942713f74 Mon Sep 17 00:00:00 2001
From: xenohedron <12538125+xenohedron@users.noreply.github.com>
Date: Mon, 10 Nov 2025 02:01:58 -0500
Subject: [PATCH 10/14] cleanup to common class
---
.../src/mage/cards/f/FlashConscription.java | 58 +++----------------
.../token/VrondissRageOfAncientsToken.java | 39 +------------
2 files changed, 10 insertions(+), 87 deletions(-)
diff --git a/Mage.Sets/src/mage/cards/f/FlashConscription.java b/Mage.Sets/src/mage/cards/f/FlashConscription.java
index 189881c60b1..b4fba0da72f 100644
--- a/Mage.Sets/src/mage/cards/f/FlashConscription.java
+++ b/Mage.Sets/src/mage/cards/f/FlashConscription.java
@@ -1,10 +1,9 @@
-
package mage.cards.f;
-import java.util.UUID;
-import mage.abilities.TriggeredAbilityImpl;
+import mage.abilities.common.DealsCombatDamageTriggeredAbility;
import mage.abilities.condition.common.ManaWasSpentCondition;
import mage.abilities.decorator.ConditionalContinuousEffect;
+import mage.abilities.dynamicvalue.common.SavedDamageValue;
import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.effects.common.UntapTargetEffect;
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
@@ -13,15 +12,11 @@ import mage.abilities.keyword.HasteAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.ColoredManaSymbol;
import mage.constants.Duration;
-import mage.constants.Zone;
-import mage.game.Game;
-import mage.game.events.DamagedEvent;
-import mage.game.events.GameEvent;
-import mage.game.events.GameEvent.EventType;
import mage.target.common.TargetCreaturePermanent;
+import java.util.UUID;
+
/**
*
* @author LevelX2
@@ -36,7 +31,10 @@ public final class FlashConscription extends CardImpl {
this.getSpellAbility().addEffect(new GainControlTargetEffect(Duration.EndOfTurn).setText("and gain control of it until end of turn"));
this.getSpellAbility().addEffect(new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn).setText("That creature gains haste until end of turn"));
this.getSpellAbility().addEffect(new ConditionalContinuousEffect(
- new GainAbilityTargetEffect(new FlashConscriptionTriggeredAbility(), Duration.EndOfTurn),
+ new GainAbilityTargetEffect(
+ new DealsCombatDamageTriggeredAbility(new GainLifeEffect(SavedDamageValue.MUCH), false),
+ Duration.EndOfTurn
+ ),
ManaWasSpentCondition.WHITE,
"If {W} was spent to cast this spell, the creature gains "
+ "\"Whenever this creature deals combat damage, you gain that much life\" until end of turn"
@@ -54,43 +52,3 @@ public final class FlashConscription extends CardImpl {
return new FlashConscription(this);
}
}
-
-class FlashConscriptionTriggeredAbility extends TriggeredAbilityImpl {
-
- public FlashConscriptionTriggeredAbility() {
- super(Zone.BATTLEFIELD, null);
- }
-
- private FlashConscriptionTriggeredAbility(final FlashConscriptionTriggeredAbility ability) {
- super(ability);
- }
-
- @Override
- public FlashConscriptionTriggeredAbility copy() {
- return new FlashConscriptionTriggeredAbility(this);
- }
-
- @Override
- public boolean checkEventType(GameEvent event, Game game) {
- return event.getType() == GameEvent.EventType.DAMAGED_PERMANENT
- || event.getType() == GameEvent.EventType.DAMAGED_PLAYER;
- }
-
- @Override
- public boolean checkTrigger(GameEvent event, Game game) {
- DamagedEvent damageEvent = (DamagedEvent) event;
- if (damageEvent.isCombatDamage()) {
- if (event.getSourceId().equals(this.sourceId)) {
- this.getEffects().clear();
- this.getEffects().add(new GainLifeEffect(damageEvent.getAmount()));
- return true;
- }
- }
- return false;
- }
-
- @Override
- public String getRule() {
- return "Whenever {this} deals combat damage, you gain that much life.";
- }
-}
diff --git a/Mage/src/main/java/mage/game/permanent/token/VrondissRageOfAncientsToken.java b/Mage/src/main/java/mage/game/permanent/token/VrondissRageOfAncientsToken.java
index f5b0d1c0bf9..de93c7ee3de 100644
--- a/Mage/src/main/java/mage/game/permanent/token/VrondissRageOfAncientsToken.java
+++ b/Mage/src/main/java/mage/game/permanent/token/VrondissRageOfAncientsToken.java
@@ -1,13 +1,10 @@
package mage.game.permanent.token;
import mage.MageInt;
-import mage.abilities.TriggeredAbilityImpl;
+import mage.abilities.common.DealsCombatDamageTriggeredAbility;
import mage.abilities.effects.common.SacrificeSourceEffect;
import mage.constants.CardType;
import mage.constants.SubType;
-import mage.constants.Zone;
-import mage.game.Game;
-import mage.game.events.GameEvent;
public final class VrondissRageOfAncientsToken extends TokenImpl {
@@ -21,7 +18,7 @@ public final class VrondissRageOfAncientsToken extends TokenImpl {
power = new MageInt(5);
toughness = new MageInt(4);
- this.addAbility(new VrondissRageOfAncientsTokenTriggeredAbility());
+ this.addAbility(new DealsCombatDamageTriggeredAbility(new SacrificeSourceEffect(), false));
}
private VrondissRageOfAncientsToken(final VrondissRageOfAncientsToken token) {
@@ -32,35 +29,3 @@ public final class VrondissRageOfAncientsToken extends TokenImpl {
return new VrondissRageOfAncientsToken(this);
}
}
-
-class VrondissRageOfAncientsTokenTriggeredAbility extends TriggeredAbilityImpl {
-
- public VrondissRageOfAncientsTokenTriggeredAbility() {
- super(Zone.BATTLEFIELD, new SacrificeSourceEffect(), false);
- }
-
- protected VrondissRageOfAncientsTokenTriggeredAbility(final VrondissRageOfAncientsTokenTriggeredAbility ability) {
- super(ability);
- }
-
- @Override
- public VrondissRageOfAncientsTokenTriggeredAbility copy() {
- return new VrondissRageOfAncientsTokenTriggeredAbility(this);
- }
-
- @Override
- public boolean checkEventType(GameEvent event, Game game) {
- return event.getType() == GameEvent.EventType.DAMAGED_PLAYER
- || event.getType() == GameEvent.EventType.DAMAGED_PERMANENT;
- }
-
- @Override
- public boolean checkTrigger(GameEvent event, Game game) {
- return event.getSourceId().equals(this.getSourceId());
- }
-
- @Override
- public String getRule() {
- return "When this creature deals damage, sacrifice it.";
- }
-}
From 71269f972ef9752880e5e2c135d2bb9d0c29bc57 Mon Sep 17 00:00:00 2001
From: xenohedron <12538125+xenohedron@users.noreply.github.com>
Date: Mon, 10 Nov 2025 02:02:59 -0500
Subject: [PATCH 11/14] add failing tests using lifelink
---
.../DamageMultiLifelinkTriggerTest.java | 191 ++++++++++++++++++
1 file changed, 191 insertions(+)
create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/triggers/damage/DamageMultiLifelinkTriggerTest.java
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/damage/DamageMultiLifelinkTriggerTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/damage/DamageMultiLifelinkTriggerTest.java
new file mode 100644
index 00000000000..35b642b209c
--- /dev/null
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/damage/DamageMultiLifelinkTriggerTest.java
@@ -0,0 +1,191 @@
+package org.mage.test.cards.triggers.damage;
+
+import mage.constants.PhaseStep;
+import mage.constants.Zone;
+import mage.counters.CounterType;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.mage.test.serverside.base.CardTestPlayerBase;
+
+/**
+ * @author xenohedron
+ */
+public class DamageMultiLifelinkTriggerTest extends CardTestPlayerBase {
+
+ private static final String hatchling = "Kraken Hatchling"; // 0/4
+ private static final String wishcoin = "Wishcoin Crab"; // 2/5
+
+ private static final String devil = "Forge Devil"; // 1/1
+ // ETB 1 dmg to any target and 1 dmg to you
+ private static final String embermage = "Reckless Embermage"; // 2/2
+ // 1R: 1 dmg to any target and 1 dmg to itself
+
+ private static final String arc = "Arc Trail";
+ // Arc Trail deals 2 damage to any target and 1 damage to another target.
+ private static final String cone = "Cone of Flame";
+ // Cone of Flame deals 1 damage to any target, 2 damage to another target, and 3 damage to a third target.
+ private static final String chaar = "Char";
+ // Char deals 4 damage to any target and 2 damage to you.
+ private static final String outrage = "Chandra's Outrage";
+ // Chandra's Outrage deals 4 damage to target creature and 2 damage to that creature's controller.
+ private static final String fury = "Chandra's Fury";
+ // Chandra's Fury deals 4 damage to target player or planeswalker
+ // and 1 damage to each creature that player or that planeswalker's controller controls.
+
+ private static final String whip = "Whip of Erebos";
+ // Creatures you control have lifelink.
+ private static final String firesong = "Firesong and Sunspeaker";
+ // Red instant and sorcery spells you control have lifelink.
+ private static final String pridemate = "Ajani's Pridemate"; // 2/2
+ // Whenever you gain life, put a +1/+1 counter on this creature.
+
+ private void setupBattlefield() {
+ addCard(Zone.BATTLEFIELD, playerA, "Mountain", 5);
+ addCard(Zone.BATTLEFIELD, playerA, whip);
+ addCard(Zone.BATTLEFIELD, playerA, firesong);
+ addCard(Zone.BATTLEFIELD, playerA, pridemate);
+ addCard(Zone.BATTLEFIELD, playerA, hatchling);
+ addCard(Zone.BATTLEFIELD, playerB, wishcoin);
+ }
+
+ @Test
+ @Ignore
+ public void testCreatureDamageTargetAndYou() {
+ setupBattlefield();
+ addCard(Zone.HAND, playerA, devil);
+
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, devil);
+ addTarget(playerA, wishcoin);
+
+ setStrictChooseMode(true);
+ setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
+ execute();
+
+ assertLife(playerA, 20 - 1 + 2);
+ assertLife(playerB, 20);
+ assertDamageReceived(playerB, wishcoin, 1);
+ assertCounterCount(pridemate, CounterType.P1P1, 1);
+ }
+
+ @Test
+ @Ignore
+ public void testCreatureDamageTargetAndSelf() {
+ setupBattlefield();
+ addCard(Zone.BATTLEFIELD, playerA, embermage);
+
+ activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}{R}: ");
+ addTarget(playerA, wishcoin);
+
+ setStrictChooseMode(true);
+ setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
+ execute();
+
+ assertLife(playerA, 20 + 2);
+ assertLife(playerB, 20);
+ assertDamageReceived(playerB, wishcoin, 1);
+ assertDamageReceived(playerB, embermage, 1);
+ assertCounterCount(pridemate, CounterType.P1P1, 1);
+ }
+
+ @Test
+ @Ignore
+ public void testSpellDamageTargetAndTarget() {
+ setupBattlefield();
+ addCard(Zone.HAND, playerA, arc);
+
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, arc);
+ addTarget(playerA, wishcoin);
+ addTarget(playerA, hatchling);
+
+ setStrictChooseMode(true);
+ setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
+ execute();
+
+ assertLife(playerA, 20 + 3);
+ assertLife(playerB, 20);
+ assertDamageReceived(playerB, wishcoin, 2);
+ assertDamageReceived(playerA, hatchling, 1);
+ assertCounterCount(pridemate, CounterType.P1P1, 1);
+ }
+
+ @Test
+ @Ignore
+ public void testSpellDamageThreeTargets() {
+ setupBattlefield();
+ addCard(Zone.HAND, playerA, cone);
+
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, cone);
+ addTarget(playerA, wishcoin);
+ addTarget(playerA, hatchling);
+ addTarget(playerA, firesong);
+
+ setStrictChooseMode(true);
+ setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
+ execute();
+
+ assertLife(playerA, 20 + 6);
+ assertLife(playerB, 20);
+ assertDamageReceived(playerB, wishcoin, 3);
+ assertDamageReceived(playerA, hatchling, 2);
+ assertDamageReceived(playerA, firesong, 1);
+ assertCounterCount(pridemate, CounterType.P1P1, 1);
+ }
+
+ @Test
+ @Ignore
+ public void testSpellDamageTargetAndYou() {
+ setupBattlefield();
+ addCard(Zone.HAND, playerA, chaar);
+
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, chaar);
+ addTarget(playerA, wishcoin);
+
+ setStrictChooseMode(true);
+ setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
+ execute();
+
+ assertLife(playerA, 20 - 2 + 6);
+ assertLife(playerB, 20);
+ assertDamageReceived(playerB, wishcoin, 4);
+ assertCounterCount(pridemate, CounterType.P1P1, 1);
+ }
+
+ @Test
+ @Ignore
+ public void testSpellDamageTargetAndController() {
+ setupBattlefield();
+ addCard(Zone.HAND, playerA, outrage);
+
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, outrage);
+ addTarget(playerA, wishcoin);
+
+ setStrictChooseMode(true);
+ setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
+ execute();
+
+ assertLife(playerA, 20 + 6);
+ assertLife(playerB, 20 - 2);
+ assertDamageReceived(playerB, wishcoin, 4);
+ assertCounterCount(pridemate, CounterType.P1P1, 1);
+ }
+
+ @Test
+ @Ignore
+ public void testSpellDamagePlayerAndControlled() {
+ setupBattlefield();
+ addCard(Zone.HAND, playerA, fury);
+
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, fury);
+ addTarget(playerA, playerB);
+
+ setStrictChooseMode(true);
+ setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
+ execute();
+
+ assertLife(playerA, 20 + 5);
+ assertLife(playerB, 20 - 4);
+ assertDamageReceived(playerB, wishcoin, 1);
+ assertCounterCount(pridemate, CounterType.P1P1, 1);
+ }
+
+}
From 97fd15d7a63f97cdafac16f31829e70a7d7fa5c9 Mon Sep 17 00:00:00 2001
From: xenohedron <12538125+xenohedron@users.noreply.github.com>
Date: Mon, 10 Nov 2025 22:06:41 -0500
Subject: [PATCH 12/14] fix oversight
---
Mage.Sets/src/mage/cards/i/InsultInjury.java | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/Mage.Sets/src/mage/cards/i/InsultInjury.java b/Mage.Sets/src/mage/cards/i/InsultInjury.java
index a55864cd52c..196069f5d48 100644
--- a/Mage.Sets/src/mage/cards/i/InsultInjury.java
+++ b/Mage.Sets/src/mage/cards/i/InsultInjury.java
@@ -2,7 +2,7 @@ package mage.cards.i;
import mage.abilities.Ability;
import mage.abilities.effects.ReplacementEffectImpl;
-import mage.abilities.effects.common.DamageTargetEffect;
+import mage.abilities.effects.common.DamageTargetAndTargetEffect;
import mage.abilities.effects.common.continuous.DamageCantBePreventedEffect;
import mage.abilities.keyword.AftermathAbility;
import mage.cards.CardSetInfo;
@@ -15,7 +15,6 @@ import mage.game.Game;
import mage.game.events.GameEvent;
import mage.target.common.TargetCreaturePermanent;
import mage.target.common.TargetPlayerOrPlaneswalker;
-import mage.target.targetpointer.EachTargetPointer;
import mage.util.CardUtil;
import java.util.UUID;
@@ -40,7 +39,7 @@ public final class InsultInjury extends SplitCard {
getRightHalfCard().addAbility(new AftermathAbility().setRuleAtTheTop(true));
getRightHalfCard().getSpellAbility().addTarget(new TargetCreaturePermanent());
getRightHalfCard().getSpellAbility().addTarget(new TargetPlayerOrPlaneswalker());
- getRightHalfCard().getSpellAbility().addEffect(new DamageTargetEffect(2).setTargetPointer(new EachTargetPointer()));
+ getRightHalfCard().getSpellAbility().addEffect(new DamageTargetAndTargetEffect(2, 2));
}
private InsultInjury(final InsultInjury card) {
From 646d34a90eb9f04ce458ed22cfa4a68f5642500c Mon Sep 17 00:00:00 2001
From: xenohedron <12538125+xenohedron@users.noreply.github.com>
Date: Mon, 10 Nov 2025 22:35:55 -0500
Subject: [PATCH 13/14] fix oversight for real this time
---
Mage.Sets/src/mage/cards/i/InsultInjury.java | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Mage.Sets/src/mage/cards/i/InsultInjury.java b/Mage.Sets/src/mage/cards/i/InsultInjury.java
index 196069f5d48..a7cc880c8f6 100644
--- a/Mage.Sets/src/mage/cards/i/InsultInjury.java
+++ b/Mage.Sets/src/mage/cards/i/InsultInjury.java
@@ -37,8 +37,8 @@ public final class InsultInjury extends SplitCard {
// Injury
// Injury deals 2 damage to target creature and 2 damage to target player.
getRightHalfCard().addAbility(new AftermathAbility().setRuleAtTheTop(true));
- getRightHalfCard().getSpellAbility().addTarget(new TargetCreaturePermanent());
- getRightHalfCard().getSpellAbility().addTarget(new TargetPlayerOrPlaneswalker());
+ getRightHalfCard().getSpellAbility().addTarget(new TargetCreaturePermanent().setTargetTag(1));
+ getRightHalfCard().getSpellAbility().addTarget(new TargetPlayerOrPlaneswalker().setTargetTag(2));
getRightHalfCard().getSpellAbility().addEffect(new DamageTargetAndTargetEffect(2, 2));
}
From f2bf831e6169190ba412c9e1c44d3b04c8a909e9 Mon Sep 17 00:00:00 2001
From: xenohedron <12538125+xenohedron@users.noreply.github.com>
Date: Tue, 11 Nov 2025 00:20:32 -0500
Subject: [PATCH 14/14] improve verify checks for target tag usage
---
.../common/DamageTargetAndTargetEffect.java | 8 +++--
.../common/TargetsDamageTargetsEffect.java | 30 +++++++------------
2 files changed, 17 insertions(+), 21 deletions(-)
diff --git a/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndTargetEffect.java
index 2b9acbebcf2..55a951b8085 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndTargetEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndTargetEffect.java
@@ -40,8 +40,8 @@ public class DamageTargetAndTargetEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
- source.getTargets().getByTag(1).getTargets().forEach(uuid -> damageTarget(uuid, firstAmount, source, game));
- source.getTargets().getByTag(2).getTargets().forEach(uuid -> damageTarget(uuid, secondAmount, source, game));
+ source.getTargets().getTargetsByTag(1).forEach(uuid -> damageTarget(uuid, firstAmount, source, game));
+ source.getTargets().getTargetsByTag(2).forEach(uuid -> damageTarget(uuid, secondAmount, source, game));
return true;
}
@@ -59,6 +59,10 @@ public class DamageTargetAndTargetEffect extends OneShotEffect {
@Override
public String getText(Mode mode) {
+ // verify check that target tags are properly setup
+ if (mode.getTargets().getByTag(1) == null || mode.getTargets().getByTag(2) == null) {
+ throw new IllegalArgumentException("Wrong code usage: need to add tags to targets");
+ }
if (staticText != null && !staticText.isEmpty()) {
return staticText;
}
diff --git a/Mage/src/main/java/mage/abilities/effects/common/TargetsDamageTargetsEffect.java b/Mage/src/main/java/mage/abilities/effects/common/TargetsDamageTargetsEffect.java
index cad1c21c75b..577b5b508dc 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/TargetsDamageTargetsEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/TargetsDamageTargetsEffect.java
@@ -6,7 +6,6 @@ import mage.abilities.effects.OneShotEffect;
import mage.constants.Outcome;
import mage.game.Game;
import mage.game.permanent.Permanent;
-import mage.target.Target;
import java.util.ArrayList;
import java.util.List;
@@ -42,37 +41,26 @@ public class TargetsDamageTargetsEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
- if (source.getTargets().size() < 2) {
- return false;
- }
-
- Target damageTarget = source.getTargets().getByTag(1);
- Target additionalDamageTarget = source.getTargets().getByTag(2);
- Target destTarget = source.getTargets().getByTag(3);
-
List damagingPermanents = new ArrayList<>();
List receivingPermanents = new ArrayList<>();
- for (UUID id : damageTarget.getTargets()) {
+ for (UUID id : source.getTargets().getTargetsByTag(1)) { // dealing damage
Permanent permanent = game.getPermanent(id);
if (permanent != null) {
damagingPermanents.add(permanent);
}
}
- if (additionalDamageTarget != null) {
- for (UUID id : additionalDamageTarget.getTargets()) {
- Permanent permanent = game.getPermanent(id);
- if (permanent != null) {
- damagingPermanents.add(permanent);
- }
+ for (UUID id : source.getTargets().getTargetsByTag(2)) { // additional dealing damage, if applicable
+ Permanent permanent = game.getPermanent(id);
+ if (permanent != null) {
+ damagingPermanents.add(permanent);
}
}
- for (UUID id : destTarget.getTargets()) {
+ for (UUID id : source.getTargets().getTargetsByTag(3)) { // receiving damage
Permanent permanent = game.getPermanent(id);
if (permanent != null) {
receivingPermanents.add(permanent);
}
}
-
if (receivingPermanents.isEmpty() || damagingPermanents.isEmpty()) {
return false;
}
@@ -86,6 +74,10 @@ public class TargetsDamageTargetsEffect extends OneShotEffect {
@Override
public String getText(Mode mode) {
+ // verify check that target tags are properly setup
+ if (mode.getTargets().getByTag(1) == null || mode.getTargets().getByTag(3) == null) {
+ throw new IllegalArgumentException("Wrong code usage: need to add tags to targets");
+ }
if (staticText != null && !staticText.isEmpty()) {
return staticText;
}
@@ -102,4 +94,4 @@ public class TargetsDamageTargetsEffect extends OneShotEffect {
sb.append(mode.getTargets().getByTag(3).getDescription());
return sb.toString();
}
-}
\ No newline at end of file
+}