diff --git a/Mage.Sets/src/mage/sets/urzassaga/GildedDrake.java b/Mage.Sets/src/mage/sets/urzassaga/GildedDrake.java index e499027f153..71fe16fb54f 100644 --- a/Mage.Sets/src/mage/sets/urzassaga/GildedDrake.java +++ b/Mage.Sets/src/mage/sets/urzassaga/GildedDrake.java @@ -70,8 +70,10 @@ public class GildedDrake extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); - // When Gilded Drake enters the battlefield, exchange control of Gilded Drake and up to one target creature an opponent controls. If you don't make an exchange, sacrifice Gilded Drake. This ability can't be countered except by spells and abilities. + // When Gilded Drake enters the battlefield, exchange control of Gilded Drake and up to one target creature an opponent controls. If you don't make an exchange, sacrifice Gilded Drake. + // This ability can't be countered except by spells and abilities. Ability ability = new EntersBattlefieldTriggeredAbility(new GildedDrakeEffect()); + ability.setCanFizzle(false); ability.addTarget(new TargetCreaturePermanent(0, 1, filter, false)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/sets/vintagemasters/MarchesaTheBlackRose.java b/Mage.Sets/src/mage/sets/vintagemasters/MarchesaTheBlackRose.java index 22437add325..e6d06b8c363 100644 --- a/Mage.Sets/src/mage/sets/vintagemasters/MarchesaTheBlackRose.java +++ b/Mage.Sets/src/mage/sets/vintagemasters/MarchesaTheBlackRose.java @@ -117,13 +117,13 @@ class MarchesaTheBlackRoseTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { if (((ZoneChangeEvent) event).getToZone() == Zone.GRAVEYARD && ((ZoneChangeEvent) event).getFromZone() == Zone.BATTLEFIELD) { - Permanent permanent = (Permanent) game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD); + Permanent permanent = ((ZoneChangeEvent) event).getTarget(); if (permanent != null && permanent.getControllerId().equals(this.getControllerId()) && permanent.getCardType().contains(CardType.CREATURE) && permanent.getCounters().getCount(CounterType.P1P1) > 0) { for (Effect effect : this.getEffects()) { - effect.setTargetPointer(new FixedTarget(permanent.getId())); + effect.setTargetPointer(new FixedTarget(permanent.getId(), permanent.getZoneChangeCounter(game) + 1)); } return true; } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/control/ExchangeControlTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/control/ExchangeControlTest.java index d432d853eec..9eba9d61cb0 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/control/ExchangeControlTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/control/ExchangeControlTest.java @@ -35,7 +35,8 @@ public class ExchangeControlTest extends CardTestPlayerBase { } /** - * Tests switching control for two creature on one side (both creatures are under the same player's control) + * Tests switching control for two creature on one side (both creatures are + * under the same player's control) * * Also tests "7/1/2012: You don't have to control either target." */ @@ -61,8 +62,8 @@ public class ExchangeControlTest extends CardTestPlayerBase { } /** - * Tests: - * 7/1/2012: If one of the target creatures is an illegal target when Switcheroo resolves, the exchange won't happen. + * Tests: 7/1/2012: If one of the target creatures is an illegal target when + * Switcheroo resolves, the exchange won't happen. * * Targets opponent's creature */ @@ -90,10 +91,10 @@ public class ExchangeControlTest extends CardTestPlayerBase { } /** - * Tests: - * 7/1/2012: If one of the target creatures is an illegal target when Switcheroo resolves, the exchange won't happen. + * Tests: 7/1/2012: If one of the target creatures is an illegal target when + * Switcheroo resolves, the exchange won't happen. * - * Targets its own creature. + * Targets its own creature. */ @Test public void testOneTargetBecomesIllegal2() { @@ -119,8 +120,8 @@ public class ExchangeControlTest extends CardTestPlayerBase { } /** - * First gain control by Act of Treason. - * Then exchange control with other opponent's creature. + * First gain control by Act of Treason. Then exchange control with other + * opponent's creature. * * Finally second creature should stay under ours control permanently. */ @@ -183,9 +184,10 @@ public class ExchangeControlTest extends CardTestPlayerBase { } /** - * An control exchanged creature gets an copy effect from - * an creature with an activated ability to the by exchange controlled creature. - * Check that the activated ability is controlled by the new controller of the copy target. + * An control exchanged creature gets an copy effect from an creature with + * an activated ability to the by exchange controlled creature. Check that + * the activated ability is controlled by the new controller of the copy + * target. */ @Test public void testExchangeAnCopyEffect() { @@ -208,7 +210,7 @@ public class ExchangeControlTest extends CardTestPlayerBase { castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Gilded Drake"); addTarget(playerA, "Silvercoat Lion"); // Let your Silvercoat Lion now be a copy of the Manta Riders - castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Polymorphous Rush","Silvercoat Lion"); + castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Polymorphous Rush", "Silvercoat Lion"); addTarget(playerA, "Manta Riders"); // now use the activated ability to make the "Silvercoat Lions" (that became Mana Riders) flying @@ -229,10 +231,43 @@ public class ExchangeControlTest extends CardTestPlayerBase { assertPermanentCount(playerB, "Manta Riders", 1); assertPermanentCount(playerA, "Manta Riders", 1); - + Permanent controlledMantas = getPermanent("Manta Riders", playerA.getId()); Assert.assertTrue("Manta Riders should have flying ability", controlledMantas.getAbilities().contains(FlyingAbility.getInstance())); } + /** + * Gilded Drake doesn't get sacrificed if the creature its ability targets + * is invalid when it enters the battlefield + */ + @Test + public void testDrakeSacrificedIfNoExchangeHappens() { + addCard(Zone.BATTLEFIELD, playerA, "Island", 6); + // Gilded Drake {1}{U} Creature - Drake + // Flying + // When Gilded Drake enters the battlefield, exchange control of Gilded Drake and up to one target + // creature an opponent controls. If you don't make an exchange, sacrifice Gilded Drake. This ability + // can't be countered except by spells and abilities. (This effect lasts indefinitely.) + addCard(Zone.HAND, playerA, "Gilded Drake"); + + addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion"); + addCard(Zone.BATTLEFIELD, playerB, "Mountain"); + addCard(Zone.HAND, playerB, "Lightning Bolt"); + + // exchange control between Gilded Drake and Silvercoat Lion + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Gilded Drake"); + addTarget(playerA, "Silvercoat Lion"); + + // Destroy Silvercoat Lion before the exchange resolves so the Drake has to be sacrificed + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Lightning Bolt", "Silvercoat Lion", "When"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertGraveyardCount(playerB, "Lightning Bolt", 1); + assertGraveyardCount(playerB, "Silvercoat Lion", 1); + assertGraveyardCount(playerA, "Gilded Drake", 1); + + } } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/ReturnToBattlefieldEffectsTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/ReturnToBattlefieldEffectsTest.java index b2848c96634..9cad881a0e7 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/ReturnToBattlefieldEffectsTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/ReturnToBattlefieldEffectsTest.java @@ -59,7 +59,7 @@ public class ReturnToBattlefieldEffectsTest extends CardTestPlayerBase { } /** - * That that the creature with a +1/+1 counter returns + * Test that the creature with a +1/+1 counter returns */ @Test public void testMarchesatheBlackRose() { diff --git a/Mage/src/main/java/mage/abilities/Ability.java b/Mage/src/main/java/mage/abilities/Ability.java index fedff00e85d..c90dd52b5f4 100644 --- a/Mage/src/main/java/mage/abilities/Ability.java +++ b/Mage/src/main/java/mage/abilities/Ability.java @@ -568,4 +568,8 @@ public interface Ability extends Controllable, Serializable { MageObject getSourceObjectIfItStillExists(Game game); String getTargetDescription(Targets targets, Game game); + + void setCanFizzle(boolean canFizzle); + + boolean canFizzle(); } diff --git a/Mage/src/main/java/mage/abilities/AbilityImpl.java b/Mage/src/main/java/mage/abilities/AbilityImpl.java index 4440f5b4587..8b4f919f7b5 100644 --- a/Mage/src/main/java/mage/abilities/AbilityImpl.java +++ b/Mage/src/main/java/mage/abilities/AbilityImpl.java @@ -114,6 +114,7 @@ public abstract class AbilityImpl implements Ability { protected int sourceObjectZoneChangeCounter; protected List watchers = null; protected List subAbilities = null; + protected boolean canFizzle = true; public AbilityImpl(AbilityType abilityType, Zone zone) { this.id = UUID.randomUUID(); @@ -164,6 +165,7 @@ public abstract class AbilityImpl implements Ability { this.abilityWord = ability.abilityWord; this.sourceObject = ability.sourceObject; this.sourceObjectZoneChangeCounter = ability.sourceObjectZoneChangeCounter; + this.canFizzle = ability.canFizzle; } @Override @@ -1222,4 +1224,14 @@ public abstract class AbilityImpl implements Ability { this.sourceObjectZoneChangeCounter = game.getState().getZoneChangeCounter(sourceId); } + @Override + public boolean canFizzle() { + return canFizzle; + } + + @Override + public void setCanFizzle(boolean canFizzle) { + this.canFizzle = canFizzle; + } + } diff --git a/Mage/src/main/java/mage/game/GameImpl.java b/Mage/src/main/java/mage/game/GameImpl.java index 2b63c50aff4..6d35aad001e 100644 --- a/Mage/src/main/java/mage/game/GameImpl.java +++ b/Mage/src/main/java/mage/game/GameImpl.java @@ -1486,10 +1486,6 @@ public abstract class GameImpl implements Game, Serializable { } else { TriggeredAbility newAbility = ability.copy(); newAbility.newId(); - // Too early, because no targets set yet !!!!!!!!!!! - for (Effect effect : newAbility.getEffects()) { - effect.getTargetPointer().init(this, newAbility); - } state.addTriggeredAbility(newAbility); } } diff --git a/Mage/src/main/java/mage/game/stack/StackAbility.java b/Mage/src/main/java/mage/game/stack/StackAbility.java index 2177aaab12d..ae46ddd1de4 100644 --- a/Mage/src/main/java/mage/game/stack/StackAbility.java +++ b/Mage/src/main/java/mage/game/stack/StackAbility.java @@ -104,7 +104,7 @@ public class StackAbility extends StackObjImpl implements Ability { @Override public boolean resolve(Game game) { - if (ability.getTargets().stillLegal(ability, game)) { + if (ability.getTargets().stillLegal(ability, game) || !canFizzle()) { boolean result = ability.resolve(game); game.getStack().remove(this); return result; @@ -581,4 +581,13 @@ public class StackAbility extends StackObjImpl implements Ability { return getAbilities().get(0).getTargetDescription(targets, game); } + @Override + public boolean canFizzle() { + return ability.canFizzle(); + } + + @Override + public void setCanFizzle(boolean canFizzle) { + throw new UnsupportedOperationException("Not supported."); + } }