From 64b979b0d71062d6b1e5a4ff93a8e585272c707b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20P=C5=82azie=C5=84ski?= Date: Wed, 1 Apr 2020 19:06:54 +0200 Subject: [PATCH] Satyr Firedancer triggers for each opponent Satyr Firedancer should trigger multiple times when single Instant or Sorcery deals damage to multiple opponents, once for each opponent. Cards like Price of Progress currently triggered first time for first opponent in turn order, but not for others. This commit changes how the ability handles multiple damage by single source: single spell can trigger multiple times of a single stack object, because it can represent multiple instances of damage. --- .../src/mage/cards/s/SatyrFiredancer.java | 49 +++++++-------- .../oneshot/damage/SatyrFiredancerTest.java | 60 +++++++++++++++++++ 2 files changed, 82 insertions(+), 27 deletions(-) diff --git a/Mage.Sets/src/mage/cards/s/SatyrFiredancer.java b/Mage.Sets/src/mage/cards/s/SatyrFiredancer.java index 19e16e50ca..88bfb5bdc2 100644 --- a/Mage.Sets/src/mage/cards/s/SatyrFiredancer.java +++ b/Mage.Sets/src/mage/cards/s/SatyrFiredancer.java @@ -26,7 +26,9 @@ import mage.target.targetadjustment.TargetAdjuster; import mage.target.targetpointer.FixedTarget; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.UUID; /** @@ -57,8 +59,6 @@ public final class SatyrFiredancer extends CardImpl { class SatyrFiredancerTriggeredAbility extends TriggeredAbilityImpl { - private List handledStackObjects = new ArrayList<>(); - public SatyrFiredancerTriggeredAbility() { super(Zone.BATTLEFIELD, new SatyrFiredancerDamageEffect(), false); targetAdjuster = SatyrFiredancerAdjuster.instance; @@ -73,11 +73,6 @@ class SatyrFiredancerTriggeredAbility extends TriggeredAbilityImpl { return new SatyrFiredancerTriggeredAbility(this); } - @Override - public void reset(Game game) { - handledStackObjects.clear(); - } - @Override public boolean checkEventType(GameEvent event, Game game) { return event.getType() == EventType.DAMAGED_PLAYER; @@ -85,27 +80,27 @@ class SatyrFiredancerTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - if (isControlledBy(game.getControllerId(event.getSourceId()))) { - MageObject damageSource = game.getObject(event.getSourceId()); - if (damageSource != null) { - if (game.getOpponents(getControllerId()).contains(event.getTargetId())) { - MageObject object = game.getObject(event.getSourceId()); - if (object != null && (object.isInstant() || object.isSorcery())) { - if (!(damageSource instanceof StackObject) || !handledStackObjects.contains(damageSource.getId())) { - if (damageSource instanceof StackObject) { - handledStackObjects.add(damageSource.getId()); - } - for (Effect effect : this.getEffects()) { - effect.setTargetPointer(new FixedTarget(event.getTargetId())); // used by adjust targets - effect.setValue("damage", event.getAmount()); - } - return true; - } - } - } - } + boolean controlledBy = isControlledBy(game.getControllerId(event.getSourceId())); + if (!controlledBy) { + return false; } - return false; + MageObject damageSource = game.getObject(event.getSourceId()); + if (damageSource == null) { + return false; + } + UUID damageTarget = event.getTargetId(); + if (!game.getOpponents(getControllerId()).contains(damageTarget)) { + return false; + } + MageObject sourceObject = game.getObject(event.getSourceId()); + if (sourceObject == null || !(sourceObject.isInstant() || sourceObject.isSorcery())) { + return false; + } + for (Effect effect : this.getEffects()) { + effect.setTargetPointer(new FixedTarget(damageTarget)); // used by adjust targets + effect.setValue("damage", event.getAmount()); + } + return true; } @Override diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/oneshot/damage/SatyrFiredancerTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/oneshot/damage/SatyrFiredancerTest.java index 5491a9b7bc..26091b3859 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/oneshot/damage/SatyrFiredancerTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/oneshot/damage/SatyrFiredancerTest.java @@ -3,6 +3,7 @@ package org.mage.test.cards.abilities.oneshot.damage; import mage.constants.PhaseStep; import mage.constants.Zone; +import mage.game.GameException; import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBase; @@ -75,4 +76,63 @@ public class SatyrFiredancerTest extends CardTestPlayerBase { assertLife(playerB, 19); } + + @Test + public void testPriceOfProgressMultiplayer() throws GameException { + playerC = createPlayer(currentGame, playerC, "PlayerC"); + addCard(Zone.BATTLEFIELD, playerA, "Satyr Firedancer", 1); + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2); + addCard(Zone.HAND, playerA, "Price of Progress", 1); + + addCard(Zone.BATTLEFIELD, playerB, "Taiga", 1); + addCard(Zone.BATTLEFIELD, playerB, "Swab Goblin", 1); + addCard(Zone.BATTLEFIELD, playerC, "Savannah", 1); + addCard(Zone.BATTLEFIELD, playerC, "Grizzly Bears", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Price of Progress"); + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); + + execute(); + + assertPermanentCount(playerB, "Swab Goblin", 0); + assertGraveyardCount(playerB, "Swab Goblin", 1); + + assertPermanentCount(playerC, "Grizzly Bears", 0); + assertGraveyardCount(playerC, "Grizzly Bears", 1); + } + + @Test + public void testMultipleInstanceOfDamage() { + addCard(Zone.BATTLEFIELD, playerA, "Satyr Firedancer", 1); + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4); + addCard(Zone.HAND, playerA, "Fiery Confluence", 1); + + addCard(Zone.BATTLEFIELD, playerB, "Taiga", 1); + addCard(Zone.BATTLEFIELD, playerB, "Grizzly Bears", 1); + addCard(Zone.BATTLEFIELD, playerB, "Bear Cub", 1); + addCard(Zone.BATTLEFIELD, playerB, "Forest Bear", 1); + addCard(Zone.BATTLEFIELD, playerB, "Runeclaw Bear", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Fiery Confluence"); + setModeChoice(playerA, "2"); + setModeChoice(playerA, "2"); + setModeChoice(playerA, "2"); + + addTarget(playerA, "Grizzly Bears"); + addTarget(playerA, "Bear Cub"); + addTarget(playerA, "Forest Bear"); + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); + + execute(); + + assertPermanentCount(playerB, "Grizzly Bears", 0); + assertPermanentCount(playerB, "Bear Cub", 0); + assertPermanentCount(playerB, "Forest Bear", 0); + assertPermanentCount(playerB, "Runeclaw Bear", 1); + + assertGraveyardCount(playerB, "Grizzly Bears", 1); + assertGraveyardCount(playerB, "Bear Cub", 1); + assertGraveyardCount(playerB, "Forest Bear", 1); + assertGraveyardCount(playerB, "Runeclaw Bear", 0); + } }