* Opportunistic Dragon - Fixed that the can't attack effect was not discarded if the Opportunistic Dragon left the battlefield.

This commit is contained in:
LevelX2 2019-12-25 17:05:52 +01:00
parent 133cc7342d
commit 1977e7f986
2 changed files with 133 additions and 69 deletions

View file

@ -1,5 +1,6 @@
package mage.cards.o;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
@ -19,10 +20,9 @@ import mage.filter.predicate.mageobject.CardTypePredicate;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.filter.predicate.permanent.ControllerPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.TargetPermanent;
import java.util.UUID;
/**
* @author TheElk801
*/
@ -48,7 +48,8 @@ public final class OpportunisticDragon extends CardImpl {
// Flying
this.addAbility(FlyingAbility.getInstance());
// When Opportunistic Dragon enters the battlefield, choose target Human or artifact an opponent controls. For as long as Opportunistic Dragon remains on the battlefield, gain control of that permanent, it loses all abilities, and it can't attack or block.
// When Opportunistic Dragon enters the battlefield, choose target Human or artifact an opponent controls.
// For as long as Opportunistic Dragon remains on the battlefield, gain control of that permanent, it loses all abilities, and it can't attack or block.
Ability ability = new EntersBattlefieldTriggeredAbility(new OpportunisticDragonControlEffect());
ability.addEffect(new OpportunisticDragonLoseAbilitiesEffect());
ability.addEffect(new OpportunisticDragonAttackBlockEffect());
@ -70,8 +71,8 @@ class OpportunisticDragonControlEffect extends GainControlTargetEffect {
OpportunisticDragonControlEffect() {
super(Duration.Custom);
staticText = "choose target Human or artifact an opponent controls. " +
"For as long as {this} remains on the battlefield, gain control of that permanent,";
staticText = "choose target Human or artifact an opponent controls. "
+ "For as long as {this} remains on the battlefield, gain control of that permanent,";
}
private OpportunisticDragonControlEffect(final OpportunisticDragonControlEffect effect) {
@ -136,11 +137,11 @@ class OpportunisticDragonAttackBlockEffect extends CantAttackBlockTargetEffect {
}
@Override
public boolean apply(Game game, Ability source) {
public boolean applies(Permanent permanent, Ability source, Game game) {
if (source.getSourcePermanentIfItStillExists(game) == null) {
discard();
return false;
}
return super.apply(game, source);
return super.applies(permanent, source, game); //To change body of generated methods, choose Tools | Templates.
}
}

View file

@ -1,4 +1,3 @@
package org.mage.test.cards.restriction;
import mage.constants.PhaseStep;
@ -140,56 +139,56 @@ public class CantAttackTest extends CardTestPlayerBase {
assertTapped("Silvercoat Lion", false);
assertPowerToughness(playerB, "Silvercoat Lion", 4, 4);
}
/*
Reported bug: Medomai was able to attack on an extra turn when cheated into play.
*/
*/
@Test
public void testMedomaiShouldNotAttackOnExtraTurns() {
/*
Medomai the Ageless {4}{W}{U}
Legendary Creature Sphinx 4/4
Flying
Whenever Medomai the Ageless deals combat damage to a player, take an extra turn after this one.
Medomai the Ageless can't attack during extra turns.
*/
*/
String medomai = "Medomai the Ageless";
/*
Cauldron Dance {4}{B}{R} Instant
Cast Cauldron Dance only during combat.
Return target creature card from your graveyard to the battlefield. That creature gains haste. Return it to your hand at the beginning of the next end step.
You may put a creature card from your hand onto the battlefield. That creature gains haste. Its controller sacrifices it at the beginning of the next end step.
*/
*/
String cDance = "Cauldron Dance";
String dBlade = "Doom Blade"; // {1}{B} instant destroy target creature
String dBlade = "Doom Blade"; // {1}{B} instant destroy target creature
addCard(Zone.BATTLEFIELD, playerA, medomai);
addCard(Zone.HAND, playerA, dBlade);
addCard(Zone.HAND, playerA, cDance);
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 4);
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4);
// attack with Medomai, connect, and destroy him after combat
attack(1, playerA, medomai);
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, dBlade, medomai);
// next turn granted, return Medomai to field with Cauldron and try to attack again
castSpell(2, PhaseStep.BEGIN_COMBAT, playerA, cDance);
addTarget(playerA, medomai);
attack(2, playerA, medomai);
// medomai should not have been allowed to attack, but returned to hand at beginning of next end step still
setStopAt(2, PhaseStep.END_TURN);
execute();
assertLife(playerB, 16); // one hit from medomai
assertGraveyardCount(playerA, dBlade, 1);
assertGraveyardCount(playerA, cDance, 1);
assertGraveyardCount(playerA, medomai, 0);
assertHandCount(playerA, medomai, 1);
}
@Test
public void basicMedomaiTestForExtraTurn() {
/*
@ -198,184 +197,248 @@ public class CantAttackTest extends CardTestPlayerBase {
Flying
Whenever Medomai the Ageless deals combat damage to a player, take an extra turn after this one.
Medomai the Ageless can't attack during extra turns.
*/
*/
String medomai = "Medomai the Ageless";
/*
Exquisite Firecraft {1}{R}{R}
Sorcery
Exquisite Firecraft deals 4 damage to any target.
*/
*/
String eFirecraft = "Exquisite Firecraft";
addCard(Zone.BATTLEFIELD, playerA, medomai);
addCard(Zone.HAND, playerA, eFirecraft);
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
// attack with medomai, get extra turn, confirm cannot attack again with medomai and can cast sorcery
attack(1, playerA, medomai);
attack(2, playerA, medomai); // should not be allowed to
castSpell(2, PhaseStep.POSTCOMBAT_MAIN, playerA, eFirecraft, playerB);
setStopAt(2, PhaseStep.END_TURN);
execute();
assertLife(playerB, 12); // 1 hit from medomai and firecraft = 8 damage
assertGraveyardCount(playerA, eFirecraft, 1);
assertPermanentCount(playerA, medomai, 1);
}
@Test
public void sphereOfSafetyPaidCostAllowsAttack() {
public void sphereOfSafetyPaidCostAllowsAttack() {
/*
Sphere of Safety {4}{W}
Enchantment
Creatures can't attack you or a planeswalker you control unless their controller pays {X} for each of those creatures, where X is the number of enchantments you control.
*/
*/
String sphere = "Sphere of Safety";
String memnite = "Memnite";
addCard(Zone.BATTLEFIELD, playerA, memnite); // {0} 1/1
addCard(Zone.BATTLEFIELD, playerB, sphere);
addCard(Zone.BATTLEFIELD, playerA, "Forest");
attack(1, playerA, memnite);
setChoice(playerA, "Yes");
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertPermanentCount(playerB, sphere, 1);
assertLife(playerB, 19); // took the hit from memnite
assertTapped("Forest", true); // forest had to be tapped
}
@Test
public void sphereOfSafetyCostNotPaid_NoAttackAllowed() {
/*
Sphere of Safety {4}{W}
Enchantment
Creatures can't attack you or a planeswalker you control unless their controller pays {X} for each of those creatures, where X is the number of enchantments you control.
*/
*/
String sphere = "Sphere of Safety";
String memnite = "Memnite";
addCard(Zone.BATTLEFIELD, playerA, memnite); // {0} 1/1
addCard(Zone.BATTLEFIELD, playerB, sphere);
addCard(Zone.BATTLEFIELD, playerA, "Forest");
attack(1, playerA, memnite);
setChoice(playerA, "No");
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertPermanentCount(playerB, sphere, 1);
assertLife(playerB, 20); // no damage went through, did not elect to pay
assertTapped("Forest", false); // forest not tapped
}
@Test
public void collectiveResistanceCostPaid_AttackAllowed()
{
public void collectiveResistanceCostPaid_AttackAllowed() {
/*
Collective Restraint {3}{U}
Enchantment
Domain Creatures can't attack you unless their controller pays {X} for each creature they control that's attacking you, where X is the number of basic land types among lands you control.
*/
*/
String cRestraint = "Collective Restraint";
String memnite = "Memnite";
addCard(Zone.BATTLEFIELD, playerA, memnite); // {0} 1/1
addCard(Zone.BATTLEFIELD, playerB, cRestraint);
addCard(Zone.BATTLEFIELD, playerB, "Island"); // 1 basic land type = pay 1 to attack
addCard(Zone.BATTLEFIELD, playerA, "Forest");
attack(1, playerA, memnite);
setChoice(playerA, "Yes");
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertPermanentCount(playerB, cRestraint, 1);
assertLife(playerB, 19); // took the hit from memnite
assertTapped("Forest", true); // forest had to be tapped
}
@Test
public void collectiveResistanceCostNotPaid_NoAttackAllowed()
{
public void collectiveResistanceCostNotPaid_NoAttackAllowed() {
/*
Collective Restraint {3}{U}
Enchantment
Domain Creatures can't attack you unless their controller pays {X} for each creature they control that's attacking you, where X is the number of basic land types among lands you control.
*/
*/
String cRestraint = "Collective Restraint";
String memnite = "Memnite";
addCard(Zone.BATTLEFIELD, playerA, memnite); // {0} 1/1
addCard(Zone.BATTLEFIELD, playerB, cRestraint);
addCard(Zone.BATTLEFIELD, playerB, "Island"); // 1 basic land type = pay 1 to attack
addCard(Zone.BATTLEFIELD, playerA, "Forest");
attack(1, playerA, memnite);
setChoice(playerA, "No");
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertPermanentCount(playerB, cRestraint, 1);
assertLife(playerB, 20); // no damage went through, did not elect to pay
assertTapped("Forest", false); // forest not tapped
}
@Test
public void ghostlyPrison_PaidCost_AllowsAttack() {
public void ghostlyPrison_PaidCost_AllowsAttack() {
/*
Ghostly Prison {2}{W}
Enchantment
Creatures can't attack you unless their controller pays {2} for each creature they control that's attacking you.
*/
*/
String gPrison = "Ghostly Prison";
String memnite = "Memnite";
addCard(Zone.BATTLEFIELD, playerA, memnite); // {0} 1/1
addCard(Zone.BATTLEFIELD, playerB, gPrison);
addCard(Zone.BATTLEFIELD, playerA, "Forest", 2);
attack(1, playerA, memnite);
setChoice(playerA, "Yes");
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertPermanentCount(playerB, gPrison, 1);
assertLife(playerB, 19); // took the hit from memnite
assertTappedCount("Forest", true, 2); // forests had to be tapped
}
@Test
public void ghostlyPrison_CostNotPaid_NoAttackAllowed() {
/*
Ghostly Prison {2}{W}
Enchantment
Creatures can't attack you unless their controller pays {2} for each creature they control that's attacking you.
*/
*/
String gPrison = "Ghostly Prison";
String memnite = "Memnite";
addCard(Zone.BATTLEFIELD, playerA, memnite); // {0} 1/1
addCard(Zone.BATTLEFIELD, playerB, gPrison);
addCard(Zone.BATTLEFIELD, playerA, "Forest", 2);
attack(1, playerA, memnite);
setChoice(playerA, "No");
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertPermanentCount(playerB, gPrison, 1);
assertLife(playerB, 20); // no damage went through, did not elect to pay
assertTapped("Forest", false); // no forests tapped
}
@Test
public void OpportunisticDragon() {
// Flying
// When Opportunistic Dragon enters the battlefield, choose target Human or artifact an opponent controls. For as long as Opportunistic Dragon remains on the battlefield, gain control of that permanent, it loses all abilities, and it can't attack or block.
addCard(Zone.HAND, playerA, "Opportunistic Dragon"); // Creature {2}{R}{R}
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4);
addCard(Zone.BATTLEFIELD, playerA, "Desperate Castaways"); // Creature - Human Pirate 2/3
// Other Pirates you control get +1/+1.
// At the beginning of your end step, gain control of target nonland permanent controlled by a player who was dealt combat damage by three or more Pirates this turn.
addCard(Zone.BATTLEFIELD, playerB, "Admiral Beckett Brass"); // Creature {1}{B}{B}{R}
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Opportunistic Dragon");
addTarget(playerA, "Admiral Beckett Brass");
attack(3, playerA, "Admiral Beckett Brass"); // Can't attack
setStopAt(3, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertPermanentCount(playerA, "Opportunistic Dragon", 1);
assertPermanentCount(playerA, "Admiral Beckett Brass", 1);
assertPowerToughness(playerA, "Desperate Castaways", 2, 3);
assertLife(playerA, 20);
assertLife(playerB, 20);
}
/* Opportunistic Dragon - can't block/can't attack effect did not end when opportunistic dragon was exiled */
@Test
public void OpportunisticDragonEndEffects() {
// Flying
// When Opportunistic Dragon enters the battlefield, choose target Human or artifact an opponent controls. For as long as Opportunistic Dragon remains on the battlefield, gain control of that permanent, it loses all abilities, and it can't attack or block.
addCard(Zone.HAND, playerA, "Opportunistic Dragon"); // Creature {2}{R}{R}
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4);
addCard(Zone.BATTLEFIELD, playerA, "Desperate Castaways"); // Creature - Human Pirate 2/3
// Other Pirates you control get +1/+1.
// At the beginning of your end step, gain control of target nonland permanent controlled by a player who was dealt combat damage by three or more Pirates this turn.
addCard(Zone.BATTLEFIELD, playerB, "Admiral Beckett Brass"); // Creature {1}{B}{B}{R} 3/3
addCard(Zone.BATTLEFIELD, playerB, "Desperate Castaways"); // Creature - Human Pirate 2/3
// Destroy target nonartifact, nonblack creature. It can't be regenerated.
addCard(Zone.HAND, playerB, "Terror"); // Instant {1}{B}
addCard(Zone.BATTLEFIELD, playerB, "Swamp", 2);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Opportunistic Dragon");
addTarget(playerA, "Admiral Beckett Brass");
attack(3, playerA, "Admiral Beckett Brass"); // Can't attack
castSpell(3, PhaseStep.POSTCOMBAT_MAIN, playerB, "Terror", "Opportunistic Dragon");
attack(4, playerB, "Admiral Beckett Brass"); // Can attack again
setStopAt(4, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertGraveyardCount(playerB, "Terror", 1);
assertGraveyardCount(playerA, "Opportunistic Dragon", 1);
assertPermanentCount(playerB, "Admiral Beckett Brass", 1);
assertPowerToughness(playerB, "Desperate Castaways", 3, 4);
assertLife(playerA, 17);
assertLife(playerB, 20);
}
}