mirror of
https://github.com/magefree/mage.git
synced 2026-01-26 21:29:17 -08:00
* Guilded Drake - Fixed that the sacrifice did not happen if the target creature for exchange is no longer a valid target during resolution (fixes #1546).
This commit is contained in:
parent
ea5c825897
commit
cf3488d5e5
8 changed files with 80 additions and 22 deletions
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -114,6 +114,7 @@ public abstract class AbilityImpl implements Ability {
|
|||
protected int sourceObjectZoneChangeCounter;
|
||||
protected List<Watcher> watchers = null;
|
||||
protected List<Ability> 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue