* Feather, the Redeemed - fixed that it returns to hand re-casted/blinked cards;

This commit is contained in:
Oleg Agafonov 2019-05-02 23:15:43 +04:00
parent 648026ac0b
commit 735d2a16a2
2 changed files with 123 additions and 4 deletions

View file

@ -167,11 +167,9 @@ class FeatherTheRedeemedEffect extends ReplacementEffectImpl {
if (zEvent.getFromZone() == Zone.STACK
&& zEvent.getToZone() == Zone.GRAVEYARD
&& event.getSourceId() != null) {
if (event.getSourceId().equals(event.getTargetId())) {
if (event.getSourceId().equals(event.getTargetId()) && mor.getZoneChangeCounter() == game.getState().getZoneChangeCounter(event.getSourceId())) {
Spell spell = game.getStack().getSpell(mor.getSourceId());
if (spell != null && spell.isInstantOrSorcery()) {
return true;
}
return spell != null && spell.isInstantOrSorcery();
}
}
return false;

View file

@ -0,0 +1,121 @@
package org.mage.test.cards.abilities.other;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneAllEffect;
import mage.constants.Duration;
import mage.constants.PhaseStep;
import mage.constants.TargetController;
import mage.constants.Zone;
import mage.filter.StaticFilters;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
* @author JayDi85
*/
public class FeatherTheRedeemedTest extends CardTestPlayerBase {
// Feather, the Redeemed {R}{W}{W}
/*
Whenever you cast an instant or sorcery spell that targets a creature you control, exile that card
instead of putting it into your graveyard as it resolves. If you do, return it to your hand at the beginning of the next end step.
*/
@Test
public void test_ExileSpellWithReturnAtTheEnd() {
// cast bolt, put to exile, return to hand
addCard(Zone.BATTLEFIELD, playerA, "Feather, the Redeemed");
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
addCard(Zone.HAND, playerA, "Lightning Bolt", 1);
addCard(Zone.BATTLEFIELD, playerA, "Grizzly Bears", 2);
// cast and put to exile
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Grizzly Bears");
checkPermanentCount("turn 1", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Grizzly Bears", 1);
checkExileCount("turn 1", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Lightning Bolt", 1);
checkHandCardCount("turn 1", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Lightning Bolt", 0);
// return to hand at the next end step
checkExileCount("turn 1 after", 2, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", 0);
checkHandCardCount("turn 1 after", 2, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", 1);
setStrictChooseMode(true);
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertAllCommandsUsed();
}
@Test
public void test_ExileSpellAndRecastWithReturnAtTheEnd() {
// cast bolt, put to exile, cast from exile, put to exile, return to hand
addCustomCardWithAbility("cast from exile", playerA, new SimpleStaticAbility(
new PlayFromNotOwnHandZoneAllEffect(StaticFilters.FILTER_CARD, Zone.EXILED, false, TargetController.ANY, Duration.WhileOnBattlefield)
));
addCard(Zone.BATTLEFIELD, playerA, "Feather, the Redeemed");
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
addCard(Zone.HAND, playerA, "Lightning Bolt", 1);
addCard(Zone.BATTLEFIELD, playerA, "Grizzly Bears", 3);
// cast and put to exile
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Grizzly Bears");
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
checkPermanentCount("turn 1", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Grizzly Bears", 3 - 1);
checkExileCount("turn 1", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", 1);
checkHandCardCount("turn 1", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", 0);
// cast from exile and put to exile again
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Grizzly Bears");
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
checkPermanentCount("turn 1 recast", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Grizzly Bears", 3 - 2);
checkExileCount("turn 1 recast", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", 1);
checkHandCardCount("turn 1 recast", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", 0);
// return to hand at the next end step
setChoice(playerA, "At the beginning of the next end step"); // two triggeres from two cast (card's code adds two same effects on each trigger)
checkExileCount("turn 1 after", 2, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", 0);
checkHandCardCount("turn 1 after", 2, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", 1);
setStrictChooseMode(true);
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertAllCommandsUsed();
}
@Test
public void test_ExileSpellAndRecastWithoutReturn() {
// cast bolt, put to exile, cast from exile with different target, put to graveyard, not return
addCustomCardWithAbility("cast from exile", playerA, new SimpleStaticAbility(
new PlayFromNotOwnHandZoneAllEffect(StaticFilters.FILTER_CARD, Zone.EXILED, false, TargetController.ANY, Duration.WhileOnBattlefield)
));
addCard(Zone.BATTLEFIELD, playerA, "Feather, the Redeemed");
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
addCard(Zone.HAND, playerA, "Lightning Bolt", 1);
addCard(Zone.BATTLEFIELD, playerA, "Grizzly Bears", 3);
// cast and put to exile
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Grizzly Bears");
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
checkPermanentCount("turn 1", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Grizzly Bears", 3 - 1);
checkExileCount("turn 1", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", 1);
checkHandCardCount("turn 1", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", 0);
// cast from exile to target player (without trigger) and put to graveyard
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
checkPermanentCount("turn 1 recast", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Grizzly Bears", 3 - 1); // no changes
checkLife("turn 1 recast", 1, PhaseStep.PRECOMBAT_MAIN, playerB, 20 - 3);
checkExileCount("turn 1 recast", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", 0);
checkHandCardCount("turn 1 recast", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", 0);
// not return to hand at the next end step
checkExileCount("turn 1 after", 2, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", 0);
checkHandCardCount("turn 1 after", 2, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", 0);
setStrictChooseMode(true);
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertAllCommandsUsed();
}
}