* Commander: fixed that non hand abilities are castable from command zone (example: Escape, Jumpstart, see #7632);

This commit is contained in:
Oleg Agafonov 2021-03-01 01:14:00 +04:00
parent f739eedc46
commit 098796f86e
3 changed files with 55 additions and 10 deletions

View file

@ -40,8 +40,8 @@ public final class UroTitanOfNaturesWrath extends CardImpl {
// Whenever Uro enters the battlefield or attacks, you gain 3 life and draw a card, then you may put a land card from your hand onto the battlefield. // Whenever Uro enters the battlefield or attacks, you gain 3 life and draw a card, then you may put a land card from your hand onto the battlefield.
Ability ability = new EntersBattlefieldOrAttacksSourceTriggeredAbility(new GainLifeEffect(3)); Ability ability = new EntersBattlefieldOrAttacksSourceTriggeredAbility(new GainLifeEffect(3));
ability.addEffect(new DrawCardSourceControllerEffect(1).setText("and draw a card, then")); ability.addEffect(new DrawCardSourceControllerEffect(1).concatBy("and"));
ability.addEffect(new PutCardFromHandOntoBattlefieldEffect(StaticFilters.FILTER_CARD_LAND_A)); ability.addEffect(new PutCardFromHandOntoBattlefieldEffect(StaticFilters.FILTER_CARD_LAND_A).concatBy(", then"));
this.addAbility(ability); this.addAbility(ability);
// Escape-{G}{G}{U}{U}, Exile five other cards from your graveyard. // Escape-{G}{G}{U}{U}, Exile five other cards from your graveyard.

View file

@ -578,4 +578,37 @@ public class CommandersCastTest extends CardTestCommander4Players {
execute(); execute();
assertAllCommandsUsed(); assertAllCommandsUsed();
} }
@Test
public void test_Escape_CantBeCastableFromCommandZone() {
// Player order: A -> D -> C -> B
// When Uro enters the battlefield, sacrifice it unless it escaped.
// Whenever Uro enters the battlefield or attacks, you gain 3 life and draw a card, then you may put a land card from your hand onto the battlefield.
// Escape-{G}{G}{U}{U}, Exile five other cards from your graveyard.
addCard(Zone.COMMAND, playerA, "Uro, Titan of Nature's Wrath", 1); // {1}{G}{U}
addCard(Zone.BATTLEFIELD, playerA, "Forest", 2);
addCard(Zone.BATTLEFIELD, playerA, "Island", 2);
//
addCard(Zone.GRAVEYARD, playerA, "Grizzly Bears", 5);
addCard(Zone.HAND, playerA, "Swamp", 1);
checkPlayableAbility("normal cast allowed", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Uro, Titan of Nature's Wrath", true);
checkPlayableAbility("escape cast not allowed", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Uro, Titan of Nature's Wrath with Escape", false);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Uro, Titan of Nature's Wrath");
setChoice(playerA, "Whenever {this} enters the battlefield or attacks"); // gain life trigger first, sacrifice next
setChoice(playerA, "No"); // keep in graveyard
setChoice(playerA, "Yes"); // put land to battlefield
setChoice(playerA, "Swamp"); // put a Swamp
setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertAllCommandsUsed();
assertLife(playerA, 20 + 3);
assertPermanentCount(playerA, "Swamp", 1);
assertGraveyardCount(playerA, "Uro, Titan of Nature's Wrath", 1); // sacrificed
}
} }

View file

@ -8,7 +8,6 @@ import mage.abilities.common.CastCommanderAbility;
import mage.abilities.common.PlayLandAsCommanderAbility; import mage.abilities.common.PlayLandAsCommanderAbility;
import mage.abilities.costs.mana.ManaCost; import mage.abilities.costs.mana.ManaCost;
import mage.abilities.costs.mana.ManaCosts; import mage.abilities.costs.mana.ManaCosts;
import mage.abilities.keyword.EscapeAbility;
import mage.abilities.text.TextPart; import mage.abilities.text.TextPart;
import mage.cards.Card; import mage.cards.Card;
import mage.cards.FrameStyle; import mage.cards.FrameStyle;
@ -44,10 +43,6 @@ public class Commander implements CommandObject {
switch (spellAbility.getSpellAbilityType()) { switch (spellAbility.getSpellAbilityType()) {
case BASE: case BASE:
case BASE_ALTERNATE: case BASE_ALTERNATE:
// Escape only castable from graveyard
if (ability instanceof EscapeAbility) {
break;
}
case SPLIT: case SPLIT:
case SPLIT_FUSED: case SPLIT_FUSED:
case SPLIT_LEFT: case SPLIT_LEFT:
@ -57,7 +52,9 @@ public class Commander implements CommandObject {
case MODAL_RIGHT: case MODAL_RIGHT:
case ADVENTURE_SPELL: case ADVENTURE_SPELL:
// can be used from command zone // can be used from command zone
abilities.add(new CastCommanderAbility(card, spellAbility)); if (canUseAbilityFromCommandZone(spellAbility)) {
abilities.add(new CastCommanderAbility(card, spellAbility));
}
break; break;
case FACE_DOWN_CREATURE: // dynamic added spell for alternative cost like cast as face down case FACE_DOWN_CREATURE: // dynamic added spell for alternative cost like cast as face down
case SPLICE: // only from hand case SPLICE: // only from hand
@ -73,8 +70,10 @@ public class Commander implements CommandObject {
// replace play land with commander play land (to play from command zone) // replace play land with commander play land (to play from command zone)
for (Ability ability : card.getAbilities()) { for (Ability ability : card.getAbilities()) {
if (ability instanceof PlayLandAbility) { if (ability instanceof PlayLandAbility) {
Ability newAbility = new PlayLandAsCommanderAbility((PlayLandAbility) ability); if (canUseAbilityFromCommandZone(ability)) {
abilities.add(newAbility); Ability newAbility = new PlayLandAsCommanderAbility((PlayLandAbility) ability);
abilities.add(newAbility);
}
} }
} }
@ -86,11 +85,24 @@ public class Commander implements CommandObject {
} }
// all other abilities must be added to commander (example: triggers from command zone, alternative cost, etc) // all other abilities must be added to commander (example: triggers from command zone, alternative cost, etc)
// no changes to ability zone, so can add any
Ability newAbility = ability.copy(); Ability newAbility = ability.copy();
abilities.add(newAbility); abilities.add(newAbility);
} }
} }
private boolean canUseAbilityFromCommandZone(Ability ability) {
// ability can be restricted by zone usage, so you must ignore it for commander (example: Escape or Jumpstart)
switch (ability.getZone()) {
case ALL:
case COMMAND:
case HAND:
return true;
default:
return false;
}
}
private Commander(final Commander commander) { private Commander(final Commander commander) {
this.sourceObject = commander.sourceObject; this.sourceObject = commander.sourceObject;
this.copy = commander.copy; this.copy = commander.copy;