forked from External/mage
Update Laelia, the Blade Reforged to use ZONE_CHANGE_BATCH (#12010)
* Fix #11747 * Fix #12008
This commit is contained in:
parent
e465eab1bc
commit
d08b71642b
3 changed files with 153 additions and 39 deletions
|
|
@ -1,7 +1,6 @@
|
|||
package mage.cards.c;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.Mode;
|
||||
import mage.abilities.effects.common.ChooseACardNameEffect;
|
||||
import mage.abilities.effects.common.search.SearchTargetGraveyardHandLibraryForCardNameAndExileEffect;
|
||||
import mage.cards.CardImpl;
|
||||
|
|
@ -53,11 +52,12 @@ class CranialExtractionEffect extends SearchTargetGraveyardHandLibraryForCardNam
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
Player player = game.getPlayer(this.getTargetPointer().getFirst(game, source));
|
||||
if (player == null) {
|
||||
if (controller == null || player == null) {
|
||||
return true;
|
||||
}
|
||||
String cardName = ChooseACardNameEffect.TypeOfName.NON_LAND_NAME.getChoice(player, game, source, false);
|
||||
String cardName = ChooseACardNameEffect.TypeOfName.NON_LAND_NAME.getChoice(controller, game, source, false);
|
||||
if (cardName == null) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,12 +13,18 @@ import mage.constants.*;
|
|||
import mage.counters.CounterType;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.ZoneChangeGroupEvent;
|
||||
import mage.game.events.ZoneChangeBatchEvent;
|
||||
import mage.game.events.ZoneChangeEvent;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Rules update: 6/18/2021
|
||||
* Laelia, the Blade Reforged has received an update to its Oracle text.
|
||||
* Specifically, its last triggered ability doesn't care which player is exiling cards from the library or graveyard.
|
||||
* Cards put into exile from your library or graveyard for any reason, such as the delve ability, cause the ability to trigger.
|
||||
*
|
||||
* @author jmharmon
|
||||
*/
|
||||
public final class LaeliaTheBladeReforged extends CardImpl {
|
||||
|
|
@ -38,7 +44,7 @@ public final class LaeliaTheBladeReforged extends CardImpl {
|
|||
// Whenever Laelia, the Blade Reforged attacks, exile the top card of your library. You may play that card this turn.
|
||||
this.addAbility(new AttacksTriggeredAbility(new ExileTopXMayPlayUntilEffect(1, Duration.EndOfTurn), false));
|
||||
|
||||
// Whenever a spell or ability you control exiles one or more cards from your library and/or your graveyard, put a +1/+1 counter on Laelia.
|
||||
// Whenever one or more cards are put into exile from your library and/or your graveyard, put a +1/+1 counter on Laelia.
|
||||
this.addAbility(new LaeliaTheBladeReforgedAddCountersTriggeredAbility());
|
||||
}
|
||||
|
||||
|
|
@ -69,44 +75,21 @@ class LaeliaTheBladeReforgedAddCountersTriggeredAbility extends TriggeredAbility
|
|||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.ZONE_CHANGE_GROUP;
|
||||
return event.getType() == GameEvent.EventType.ZONE_CHANGE_BATCH;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
ZoneChangeGroupEvent zEvent = (ZoneChangeGroupEvent) event;
|
||||
final int numberExiled = zEvent.getCards().size();
|
||||
if (zEvent.getToZone() != Zone.EXILED
|
||||
|| numberExiled == 0) {
|
||||
return false;
|
||||
}
|
||||
switch (zEvent.getFromZone()) {
|
||||
case LIBRARY:
|
||||
if (zEvent
|
||||
.getCards()
|
||||
.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.map(Card::getOwnerId)
|
||||
.anyMatch(this::isControlledBy)
|
||||
&& numberExiled > 0) {
|
||||
this.getEffects().clear();
|
||||
this.getEffects().add(new AddCountersSourceEffect(CounterType.P1P1.createInstance()));
|
||||
return true;
|
||||
}
|
||||
case GRAVEYARD:
|
||||
if (zEvent
|
||||
.getCards()
|
||||
.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.map(Card::getOwnerId)
|
||||
.anyMatch(this::isControlledBy)
|
||||
&& numberExiled > 0) {
|
||||
this.getEffects().clear();
|
||||
this.getEffects().add(new AddCountersSourceEffect(CounterType.P1P1.createInstance()));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
ZoneChangeBatchEvent zEvent = (ZoneChangeBatchEvent) event;
|
||||
return zEvent.getEvents()
|
||||
.stream()
|
||||
.filter(e -> e.getFromZone() == Zone.LIBRARY || e.getFromZone() == Zone.GRAVEYARD)
|
||||
.filter(e -> e.getToZone() == Zone.EXILED)
|
||||
.map(ZoneChangeEvent::getTargetId)
|
||||
.map(game::getCard)
|
||||
.filter(Objects::nonNull)
|
||||
.map(Card::getOwnerId)
|
||||
.anyMatch(this::isControlledBy);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -0,0 +1,131 @@
|
|||
package org.mage.test.cards.single.c21;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import mage.counters.CounterType;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
* {@link mage.cards.l.LaeliaTheBladeReforged Laelia, the Blade Reforged}
|
||||
* {2}{R}
|
||||
* Legendary Creature - Spirit Warrior
|
||||
* Haste
|
||||
* Whenever Laelia, the Blade Reforged attacks, exile the top card of your library. You may play that card this turn.
|
||||
* Whenever one or more cards are put into exile from your library and/or your graveyard, put a +1/+1 counter on Laelia.
|
||||
*
|
||||
* @author DominionSpy
|
||||
*/
|
||||
public class LaeliaTheBladeReforgedTest extends CardTestPlayerBase {
|
||||
|
||||
private static final String laelia = "Laelia, the Blade Reforged";
|
||||
private static final String cranialExtraction = "Cranial Extraction";
|
||||
private static final String llanowarElves = "Llanowar Elves";
|
||||
|
||||
@Test
|
||||
public void controllerExilesOwnCards() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 4);
|
||||
addCard(Zone.BATTLEFIELD, playerA, laelia);
|
||||
addCard(Zone.HAND, playerA, cranialExtraction);
|
||||
addCard(Zone.HAND, playerA, llanowarElves);
|
||||
addCard(Zone.GRAVEYARD, playerA, llanowarElves);
|
||||
addCard(Zone.LIBRARY, playerA, llanowarElves);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, cranialExtraction, playerA);
|
||||
// Choose a nonland card name (Llanowar Elves)
|
||||
setChoice(playerA, llanowarElves);
|
||||
// Graveyard
|
||||
setChoice(playerA, llanowarElves);
|
||||
// Hand
|
||||
setChoice(playerA, llanowarElves);
|
||||
// Library
|
||||
setChoice(playerA, llanowarElves);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertCounterCount(playerA, laelia, CounterType.P1P1, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void opponentExilesControllersCards() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 4);
|
||||
addCard(Zone.HAND, playerA, cranialExtraction);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerB, laelia);
|
||||
addCard(Zone.HAND, playerB, llanowarElves);
|
||||
addCard(Zone.GRAVEYARD, playerB, llanowarElves);
|
||||
addCard(Zone.LIBRARY, playerB, llanowarElves);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, cranialExtraction, playerB);
|
||||
// Choose a nonland card name (Llanowar Elves)
|
||||
setChoice(playerA, llanowarElves);
|
||||
// Graveyard
|
||||
setChoice(playerA, llanowarElves);
|
||||
// Hand
|
||||
setChoice(playerA, llanowarElves);
|
||||
// Library
|
||||
setChoice(playerA, llanowarElves);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertCounterCount(playerB, laelia, CounterType.P1P1, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void controllerExilesOpponentsCards() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 4);
|
||||
addCard(Zone.BATTLEFIELD, playerA, laelia);
|
||||
addCard(Zone.HAND, playerA, cranialExtraction);
|
||||
|
||||
addCard(Zone.HAND, playerB, llanowarElves);
|
||||
addCard(Zone.GRAVEYARD, playerB, llanowarElves);
|
||||
addCard(Zone.LIBRARY, playerB, llanowarElves);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, cranialExtraction, playerB);
|
||||
// Choose a nonland card name (Llanowar Elves)
|
||||
setChoice(playerA, llanowarElves);
|
||||
// Graveyard
|
||||
setChoice(playerA, llanowarElves);
|
||||
// Hand
|
||||
setChoice(playerA, llanowarElves);
|
||||
// Library
|
||||
setChoice(playerA, llanowarElves);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertCounterCount(playerA, laelia, CounterType.P1P1, 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void opponentExilesOwnCards() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 4);
|
||||
addCard(Zone.HAND, playerA, cranialExtraction);
|
||||
addCard(Zone.HAND, playerA, llanowarElves);
|
||||
addCard(Zone.GRAVEYARD, playerA, llanowarElves);
|
||||
addCard(Zone.LIBRARY, playerA, llanowarElves);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerB, laelia);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, cranialExtraction, playerA);
|
||||
// Choose a nonland card name (Llanowar Elves)
|
||||
setChoice(playerA, llanowarElves);
|
||||
// Graveyard
|
||||
setChoice(playerA, llanowarElves);
|
||||
// Hand
|
||||
setChoice(playerA, llanowarElves);
|
||||
// Library
|
||||
setChoice(playerA, llanowarElves);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertCounterCount(playerB, laelia, CounterType.P1P1, 0);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue