mirror of
https://github.com/correl/mage.git
synced 2024-12-25 03:00:15 +00:00
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.
This commit is contained in:
parent
0fb80bfc15
commit
64b979b0d7
2 changed files with 82 additions and 27 deletions
|
@ -26,7 +26,9 @@ import mage.target.targetadjustment.TargetAdjuster;
|
||||||
import mage.target.targetpointer.FixedTarget;
|
import mage.target.targetpointer.FixedTarget;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -57,8 +59,6 @@ public final class SatyrFiredancer extends CardImpl {
|
||||||
|
|
||||||
class SatyrFiredancerTriggeredAbility extends TriggeredAbilityImpl {
|
class SatyrFiredancerTriggeredAbility extends TriggeredAbilityImpl {
|
||||||
|
|
||||||
private List<UUID> handledStackObjects = new ArrayList<>();
|
|
||||||
|
|
||||||
public SatyrFiredancerTriggeredAbility() {
|
public SatyrFiredancerTriggeredAbility() {
|
||||||
super(Zone.BATTLEFIELD, new SatyrFiredancerDamageEffect(), false);
|
super(Zone.BATTLEFIELD, new SatyrFiredancerDamageEffect(), false);
|
||||||
targetAdjuster = SatyrFiredancerAdjuster.instance;
|
targetAdjuster = SatyrFiredancerAdjuster.instance;
|
||||||
|
@ -73,11 +73,6 @@ class SatyrFiredancerTriggeredAbility extends TriggeredAbilityImpl {
|
||||||
return new SatyrFiredancerTriggeredAbility(this);
|
return new SatyrFiredancerTriggeredAbility(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void reset(Game game) {
|
|
||||||
handledStackObjects.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean checkEventType(GameEvent event, Game game) {
|
public boolean checkEventType(GameEvent event, Game game) {
|
||||||
return event.getType() == EventType.DAMAGED_PLAYER;
|
return event.getType() == EventType.DAMAGED_PLAYER;
|
||||||
|
@ -85,28 +80,28 @@ class SatyrFiredancerTriggeredAbility extends TriggeredAbilityImpl {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean checkTrigger(GameEvent event, Game game) {
|
public boolean checkTrigger(GameEvent event, Game game) {
|
||||||
if (isControlledBy(game.getControllerId(event.getSourceId()))) {
|
boolean controlledBy = isControlledBy(game.getControllerId(event.getSourceId()));
|
||||||
|
if (!controlledBy) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
MageObject damageSource = game.getObject(event.getSourceId());
|
MageObject damageSource = game.getObject(event.getSourceId());
|
||||||
if (damageSource != null) {
|
if (damageSource == null) {
|
||||||
if (game.getOpponents(getControllerId()).contains(event.getTargetId())) {
|
return false;
|
||||||
MageObject object = game.getObject(event.getSourceId());
|
}
|
||||||
if (object != null && (object.isInstant() || object.isSorcery())) {
|
UUID damageTarget = event.getTargetId();
|
||||||
if (!(damageSource instanceof StackObject) || !handledStackObjects.contains(damageSource.getId())) {
|
if (!game.getOpponents(getControllerId()).contains(damageTarget)) {
|
||||||
if (damageSource instanceof StackObject) {
|
return false;
|
||||||
handledStackObjects.add(damageSource.getId());
|
}
|
||||||
|
MageObject sourceObject = game.getObject(event.getSourceId());
|
||||||
|
if (sourceObject == null || !(sourceObject.isInstant() || sourceObject.isSorcery())) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
for (Effect effect : this.getEffects()) {
|
for (Effect effect : this.getEffects()) {
|
||||||
effect.setTargetPointer(new FixedTarget(event.getTargetId())); // used by adjust targets
|
effect.setTargetPointer(new FixedTarget(damageTarget)); // used by adjust targets
|
||||||
effect.setValue("damage", event.getAmount());
|
effect.setValue("damage", event.getAmount());
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getRule() {
|
public String getRule() {
|
||||||
|
|
|
@ -3,6 +3,7 @@ package org.mage.test.cards.abilities.oneshot.damage;
|
||||||
|
|
||||||
import mage.constants.PhaseStep;
|
import mage.constants.PhaseStep;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
|
import mage.game.GameException;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||||
|
|
||||||
|
@ -75,4 +76,63 @@ public class SatyrFiredancerTest extends CardTestPlayerBase {
|
||||||
assertLife(playerB, 19);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue