mirror of
https://github.com/correl/mage.git
synced 2024-11-14 19:19:32 +00:00
Refactoring + Fix of several cards (#8699)
* Simplified Azorius Aethermage * - Flattened the if statements - Renamed the custom effects and abilities to be more readable - Changed certain functiosn to be private * Flatten Thieves Auction * Flatten Possibility Storm * Flatten Aminatous Augury * Minor refactoring * Flattening and adjusting access modifiers * Aetherspouts should have been using getPlayersInRange. Current implementation was affecting all players * Simplified Akoum Hellkite * Simplified Ali From Cairo * Flattened An-Havva Constable * Flattened Aura Finesse and Autum Willow * Fixed All Hallow's Eve since it didn't work. * Several small simplifications * Flattening/Simplification of several classes * Added test for Azorius Aethermage * Added test for Abandoned Sarcophagus * Updated test with docstring instead of comment * Update AzoriusAethermageTest.java * Update BattlegateMimic.java * Update AetherworksMarvel.java * Update AetherworksMarvel.java * Update AzoriusAethermageTest.java * Update AzoriusAethermageTest.java Co-authored-by: Jeff Wadsworth <jeffwadsworth@users.noreply.github.com>
This commit is contained in:
parent
8dc99256d5
commit
6a7b2e80ac
65 changed files with 1471 additions and 1258 deletions
|
@ -34,7 +34,7 @@ public final class AbandonReason extends CardImpl {
|
||||||
this.getSpellAbility().addTarget(new TargetCreaturePermanent(0, 2));
|
this.getSpellAbility().addTarget(new TargetCreaturePermanent(0, 2));
|
||||||
|
|
||||||
// Madness {1}{R}
|
// Madness {1}{R}
|
||||||
this.addAbility(new MadnessAbility(this, new ManaCostsImpl("{1}{R}")));
|
this.addAbility(new MadnessAbility(this, new ManaCostsImpl<>("{1}{R}")));
|
||||||
}
|
}
|
||||||
|
|
||||||
private AbandonReason(final AbandonReason card) {
|
private AbandonReason(final AbandonReason card) {
|
||||||
|
|
|
@ -3,6 +3,7 @@ package mage.cards.a;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.SimpleStaticAbility;
|
import mage.abilities.common.SimpleStaticAbility;
|
||||||
import mage.abilities.effects.ReplacementEffectImpl;
|
import mage.abilities.effects.ReplacementEffectImpl;
|
||||||
|
@ -25,13 +26,17 @@ import mage.watchers.Watcher;
|
||||||
*/
|
*/
|
||||||
public final class AbandonedSarcophagus extends CardImpl {
|
public final class AbandonedSarcophagus extends CardImpl {
|
||||||
|
|
||||||
|
private static final FilterCard filter = new FilterCard("nonland cards with cycling");
|
||||||
|
|
||||||
|
static {
|
||||||
|
filter.add(Predicates.not(CardType.LAND.getPredicate()));
|
||||||
|
filter.add(new AbilityPredicate(CyclingAbility.class));
|
||||||
|
}
|
||||||
|
|
||||||
public AbandonedSarcophagus(UUID ownerId, CardSetInfo setInfo) {
|
public AbandonedSarcophagus(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}");
|
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}");
|
||||||
|
|
||||||
// You may cast nonland cards with cycling from your graveyard.
|
// You may cast nonland cards with cycling from your graveyard.
|
||||||
FilterCard filter = new FilterCard("nonland cards with cycling");
|
|
||||||
filter.add(Predicates.not(CardType.LAND.getPredicate()));
|
|
||||||
filter.add(new AbilityPredicate(CyclingAbility.class));
|
|
||||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
|
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
|
||||||
new PlayFromNotOwnHandZoneAllEffect(filter,
|
new PlayFromNotOwnHandZoneAllEffect(filter,
|
||||||
Zone.GRAVEYARD, true, TargetController.YOU, Duration.WhileOnBattlefield)
|
Zone.GRAVEYARD, true, TargetController.YOU, Duration.WhileOnBattlefield)
|
||||||
|
@ -77,16 +82,20 @@ class AbandonedSarcophagusReplacementEffect extends ReplacementEffectImpl {
|
||||||
@Override
|
@Override
|
||||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
if (controller != null) {
|
if (controller == null) {
|
||||||
Permanent permanent = game.getPermanent(event.getTargetId());
|
return false;
|
||||||
if (permanent != null) {
|
|
||||||
return controller.moveCards(permanent, Zone.EXILED, source, game);
|
|
||||||
}
|
|
||||||
Card card = game.getCard(event.getTargetId());
|
|
||||||
if (card != null) {
|
|
||||||
return controller.moveCards(card, Zone.EXILED, source, game);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Permanent permanent = game.getPermanent(event.getTargetId());
|
||||||
|
if (permanent != null) {
|
||||||
|
return controller.moveCards(permanent, Zone.EXILED, source, game);
|
||||||
|
}
|
||||||
|
|
||||||
|
Card card = game.getCard(event.getTargetId());
|
||||||
|
if (card != null) {
|
||||||
|
return controller.moveCards(card, Zone.EXILED, source, game);
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,32 +106,46 @@ class AbandonedSarcophagusReplacementEffect extends ReplacementEffectImpl {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||||
boolean cardWasCycledThisTurn = false;
|
|
||||||
boolean cardHasCycling = false;
|
|
||||||
if (!(((ZoneChangeEvent) event).getToZone() == Zone.GRAVEYARD)) {
|
if (!(((ZoneChangeEvent) event).getToZone() == Zone.GRAVEYARD)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
AbandonedSarcophagusWatcher watcher = game.getState().getWatcher(AbandonedSarcophagusWatcher.class);
|
if (controller == null) {
|
||||||
Card card = game.getCard(event.getTargetId());
|
|
||||||
if (card == null
|
|
||||||
|| controller == null
|
|
||||||
|| watcher == null
|
|
||||||
|| !card.isOwnedBy(controller.getId())) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Card card = game.getCard(event.getTargetId());
|
||||||
|
if (card == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!card.isOwnedBy(controller.getId())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
AbandonedSarcophagusWatcher watcher = game.getState().getWatcher(AbandonedSarcophagusWatcher.class);
|
||||||
|
if (watcher == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean cardHasCycling = false;
|
||||||
for (Ability ability : card.getAbilities(game)) {
|
for (Ability ability : card.getAbilities(game)) {
|
||||||
if (ability instanceof CyclingAbility) {
|
if (ability instanceof CyclingAbility) {
|
||||||
cardHasCycling = true;
|
cardHasCycling = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Cards cards = watcher.getCardsCycledThisTurn(controller.getId());
|
Cards cards = watcher.getCardsCycledThisTurn(controller.getId());
|
||||||
for (Card c : cards.getCards(game)) {
|
boolean cardWasCycledThisTurn = false;
|
||||||
if (c == card) {
|
|
||||||
|
for (Card cardCycledThisTurn : cards.getCards(game)) {
|
||||||
|
if (cardCycledThisTurn == card) {
|
||||||
cardWasCycledThisTurn = true;
|
cardWasCycledThisTurn = true;
|
||||||
watcher.getCardsCycledThisTurn(controller.getId()).remove(card); //remove reference to the card as it is no longer needed
|
watcher.getCardsCycledThisTurn(controller.getId()).remove(card); //remove reference to the card as it is no longer needed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return !cardWasCycledThisTurn && cardHasCycling;
|
return !cardWasCycledThisTurn && cardHasCycling;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -137,17 +160,26 @@ class AbandonedSarcophagusWatcher extends Watcher {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void watch(GameEvent event, Game game) {
|
public void watch(GameEvent event, Game game) {
|
||||||
if (event.getType() == GameEvent.EventType.CYCLE_CARD) {
|
if (event.getType() != GameEvent.EventType.CYCLE_CARD) {
|
||||||
Card card = game.getCard(event.getSourceId());
|
return;
|
||||||
Player controller = game.getPlayer(event.getPlayerId());
|
|
||||||
if (card != null
|
|
||||||
&& controller != null
|
|
||||||
&& card.isOwnedBy(controller.getId())) {
|
|
||||||
Cards c = getCardsCycledThisTurn(event.getPlayerId());
|
|
||||||
c.add(card);
|
|
||||||
cycledCardsThisTurn.put(event.getPlayerId(), c);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Card card = game.getCard(event.getSourceId());
|
||||||
|
if (card == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Player controller = game.getPlayer(event.getPlayerId());
|
||||||
|
if (controller == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!card.isOwnedBy(controller.getId())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Cards c = getCardsCycledThisTurn(event.getPlayerId());
|
||||||
|
c.add(card);
|
||||||
|
cycledCardsThisTurn.put(event.getPlayerId(), c);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Cards getCardsCycledThisTurn(UUID playerId) {
|
public Cards getCardsCycledThisTurn(UUID playerId) {
|
||||||
|
|
|
@ -54,7 +54,7 @@ class ActOfAuthorityEffect extends OneShotEffect {
|
||||||
this.staticText = "you may exile target artifact or enchantment. If you do, its controller gains control of {this}";
|
this.staticText = "you may exile target artifact or enchantment. If you do, its controller gains control of {this}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public ActOfAuthorityEffect(final ActOfAuthorityEffect effect) {
|
private ActOfAuthorityEffect(final ActOfAuthorityEffect effect) {
|
||||||
super(effect);
|
super(effect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,29 +66,32 @@ class ActOfAuthorityEffect extends OneShotEffect {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Permanent targetPermanent = game.getPermanent(getTargetPointer().getFirst(game, source));
|
Permanent targetPermanent = game.getPermanent(getTargetPointer().getFirst(game, source));
|
||||||
if (targetPermanent != null && new ExileTargetEffect().apply(game, source)) {
|
if (targetPermanent == null) { return false; }
|
||||||
Permanent sourcePermanent = source.getSourcePermanentIfItStillExists(game);
|
|
||||||
if (sourcePermanent != null) {
|
ExileTargetEffect exileTargetEffect = new ExileTargetEffect();
|
||||||
ContinuousEffect effect = new ActOfAuthorityGainControlEffect(Duration.Custom, targetPermanent.getControllerId());
|
if (!exileTargetEffect.apply(game, source)) { return false; }
|
||||||
effect.setTargetPointer(new FixedTarget(sourcePermanent, game));
|
|
||||||
game.addEffect(effect, source);
|
Permanent sourcePermanent = source.getSourcePermanentIfItStillExists(game);
|
||||||
}
|
if (sourcePermanent == null) { return true; }
|
||||||
return true;
|
|
||||||
}
|
ContinuousEffect effect = new ActOfAuthorityGainControlEffect(Duration.Custom, targetPermanent.getControllerId());
|
||||||
return false;
|
effect.setTargetPointer(new FixedTarget(sourcePermanent, game));
|
||||||
|
game.addEffect(effect, source);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: These and it's duplicates can probably be replaced by a gain control of effect
|
||||||
class ActOfAuthorityGainControlEffect extends ContinuousEffectImpl {
|
class ActOfAuthorityGainControlEffect extends ContinuousEffectImpl {
|
||||||
|
|
||||||
UUID controller;
|
private final UUID controller;
|
||||||
|
|
||||||
public ActOfAuthorityGainControlEffect(Duration duration, UUID controller) {
|
public ActOfAuthorityGainControlEffect(Duration duration, UUID controller) {
|
||||||
super(duration, Layer.ControlChangingEffects_2, SubLayer.NA, Outcome.GainControl);
|
super(duration, Layer.ControlChangingEffects_2, SubLayer.NA, Outcome.GainControl);
|
||||||
this.controller = controller;
|
this.controller = controller;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ActOfAuthorityGainControlEffect(final ActOfAuthorityGainControlEffect effect) {
|
private ActOfAuthorityGainControlEffect(final ActOfAuthorityGainControlEffect effect) {
|
||||||
super(effect);
|
super(effect);
|
||||||
this.controller = effect.controller;
|
this.controller = effect.controller;
|
||||||
}
|
}
|
||||||
|
@ -100,14 +103,16 @@ class ActOfAuthorityGainControlEffect extends ContinuousEffectImpl {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Permanent permanent = game.getPermanent(source.getFirstTarget());
|
Permanent permanent;
|
||||||
if (targetPointer != null) {
|
if (targetPointer == null) {
|
||||||
|
permanent = game.getPermanent(source.getFirstTarget());
|
||||||
|
} else {
|
||||||
permanent = game.getPermanent(targetPointer.getFirst(game, source));
|
permanent = game.getPermanent(targetPointer.getFirst(game, source));
|
||||||
}
|
}
|
||||||
if (permanent != null) {
|
|
||||||
return permanent.changeControllerId(controller, game, source);
|
if (permanent == null) { return false; }
|
||||||
}
|
|
||||||
return false;
|
return permanent.changeControllerId(controller, game, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -84,18 +84,17 @@ class AdarkarValkyrieEffect extends OneShotEffect {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
|
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
|
||||||
if (permanent != null) {
|
if (permanent == null) { return false; }
|
||||||
DelayedTriggeredAbility delayedAbility = new AdarkarValkyrieDelayedTriggeredAbility(new MageObjectReference(permanent, game));
|
|
||||||
game.addDelayedTriggeredAbility(delayedAbility, source);
|
DelayedTriggeredAbility delayedAbility = new AdarkarValkyrieDelayedTriggeredAbility(new MageObjectReference(permanent, game));
|
||||||
return true;
|
game.addDelayedTriggeredAbility(delayedAbility, source);
|
||||||
}
|
return true;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AdarkarValkyrieDelayedTriggeredAbility extends DelayedTriggeredAbility {
|
class AdarkarValkyrieDelayedTriggeredAbility extends DelayedTriggeredAbility {
|
||||||
|
|
||||||
protected MageObjectReference mor;
|
private final MageObjectReference mor;
|
||||||
|
|
||||||
public AdarkarValkyrieDelayedTriggeredAbility(MageObjectReference mor) {
|
public AdarkarValkyrieDelayedTriggeredAbility(MageObjectReference mor) {
|
||||||
super(new ReturnToBattlefieldUnderYourControlTargetEffect(), Duration.EndOfTurn);
|
super(new ReturnToBattlefieldUnderYourControlTargetEffect(), Duration.EndOfTurn);
|
||||||
|
@ -119,14 +118,17 @@ class AdarkarValkyrieDelayedTriggeredAbility extends DelayedTriggeredAbility {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean checkTrigger(GameEvent event, Game game) {
|
public boolean checkTrigger(GameEvent event, Game game) {
|
||||||
if (((ZoneChangeEvent) event).isDiesEvent()
|
if (!((ZoneChangeEvent) event).isDiesEvent()) { return false; }
|
||||||
&& mor.refersTo(((ZoneChangeEvent) event).getTarget(), game)
|
|
||||||
&& game.getState().getZone(event.getTargetId()) == Zone.GRAVEYARD) { // must be in the graveyard
|
|
||||||
getEffects().setTargetPointer(new FixedTarget(event.getTargetId(), game));
|
|
||||||
return true;
|
|
||||||
|
|
||||||
}
|
if (!mor.refersTo(((ZoneChangeEvent) event).getTarget(), game)) { return false; }
|
||||||
return false;
|
|
||||||
|
// TODO: Must it? Why?
|
||||||
|
// Must be in the graveyard
|
||||||
|
if (game.getState().getZone(event.getTargetId()) != Zone.GRAVEYARD) { return false; }
|
||||||
|
|
||||||
|
getEffects().setTargetPointer(new FixedTarget(event.getTargetId(), game));
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -91,7 +91,7 @@ class DamagedByPiratesWatcher extends Watcher {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean damagedByEnoughPirates(UUID sourceId) {
|
public boolean damagedByEnoughPirates(UUID sourceId) {
|
||||||
return damageSourceIds.keySet().contains(sourceId) && damageSourceIds.get(sourceId).size() > 2;
|
return damageSourceIds.containsKey(sourceId) && damageSourceIds.get(sourceId).size() > 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -110,6 +110,6 @@ enum AerialSurveyorHint implements Hint {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AerialSurveyorHint copy() {
|
public AerialSurveyorHint copy() {
|
||||||
return this;
|
return instance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,11 +44,13 @@ public final class Aetherspouts extends CardImpl {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
7/18/2014 The owner of each attacking creature chooses whether to put it on the top or bottom
|
7/18/2014 The owner of each attacking creature chooses whether to put it on the top or bottom
|
||||||
of their library. The active player (the player whose turn it is) makes all of
|
of their library.
|
||||||
their choices first, followed by each other player in turn order.
|
The active player (the player whose turn it is) makes all of their choices first,
|
||||||
|
followed by each other player in turn order.
|
||||||
|
|
||||||
7/18/2014 If an effect puts two or more cards on the top or bottom of a library at the same time,
|
7/18/2014 If an effect puts two or more cards on the top or bottom of a library at the same time,
|
||||||
the owner of those cards may arrange them in any order. That library's owner doesn't reveal
|
the owner of those cards may arrange them in any order.
|
||||||
the order in which the cards go into their library.
|
That library's owner doesn't reveal the order in which the cards go into their library.
|
||||||
*/
|
*/
|
||||||
class AetherspoutsEffect extends OneShotEffect {
|
class AetherspoutsEffect extends OneShotEffect {
|
||||||
|
|
||||||
|
@ -57,7 +59,7 @@ class AetherspoutsEffect extends OneShotEffect {
|
||||||
this.staticText = "For each attacking creature, its owner puts it on the top or bottom of their library";
|
this.staticText = "For each attacking creature, its owner puts it on the top or bottom of their library";
|
||||||
}
|
}
|
||||||
|
|
||||||
public AetherspoutsEffect(final AetherspoutsEffect effect) {
|
private AetherspoutsEffect(final AetherspoutsEffect effect) {
|
||||||
super(effect);
|
super(effect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,107 +72,107 @@ class AetherspoutsEffect extends OneShotEffect {
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
game.getPlayerList();
|
game.getPlayerList();
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
if (controller != null) {
|
if (controller == null) { return false; }
|
||||||
PlayerList playerList = game.getPlayerList().copy();
|
|
||||||
playerList.setCurrent(game.getActivePlayerId());
|
|
||||||
Player player = game.getPlayer(game.getActivePlayerId());
|
|
||||||
Player activePlayer = player;
|
|
||||||
do {
|
|
||||||
List<Permanent> permanentsToTop = new ArrayList<>();
|
|
||||||
List<Permanent> permanentsToBottom = new ArrayList<>();
|
|
||||||
for (Permanent permanent : game.getState().getBattlefield().getActivePermanents(new FilterAttackingCreature(), player.getId(), source.getSourceId(), game)) {
|
|
||||||
if (permanent.isOwnedBy(player.getId())) {
|
|
||||||
if (player.chooseUse(outcome, "Put " + permanent.getLogName() + " to the top? (else it goes to bottom)", source, game)) {
|
|
||||||
permanentsToTop.add(permanent);
|
|
||||||
game.informPlayers(permanent.getLogName() + " goes to the top of " + player.getLogName() + "'s library");
|
|
||||||
} else {
|
|
||||||
permanentsToBottom.add(permanent);
|
|
||||||
game.informPlayers(permanent.getLogName() + " goes to the bottom of " + player.getLogName() + "'s library");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// cards to top
|
|
||||||
Cards cards = new CardsImpl();
|
|
||||||
List<Permanent> toLibrary = new ArrayList<>();
|
|
||||||
for (Permanent permanent : permanentsToTop) {
|
|
||||||
if (permanent instanceof PermanentToken) {
|
|
||||||
toLibrary.add(permanent);
|
|
||||||
} else {
|
|
||||||
Card card = game.getCard(permanent.getId());
|
|
||||||
if (card != null) {
|
|
||||||
cards.add(card);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
TargetCard target = new TargetCard(Zone.BATTLEFIELD, new FilterCard("order to put on the top of library (last choosen will be the top most)"));
|
|
||||||
while (cards.size() > 1) {
|
|
||||||
if (!player.canRespond()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
player.choose(Outcome.Neutral, cards, target, game);
|
|
||||||
Card card = cards.get(target.getFirstTarget(), game);
|
|
||||||
if (card != null) {
|
|
||||||
cards.remove(card);
|
|
||||||
Permanent permanent = game.getPermanent(card.getId());
|
|
||||||
if (permanent != null) {
|
|
||||||
toLibrary.add(permanent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
target.clearChosen();
|
|
||||||
}
|
|
||||||
if (cards.size() == 1) {
|
|
||||||
Card card = cards.get(cards.iterator().next(), game);
|
|
||||||
Permanent permanent = game.getPermanent(card.getId());
|
|
||||||
if (permanent != null) {
|
|
||||||
toLibrary.add(permanent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// move all permanents to lib at the same time
|
|
||||||
for (Permanent permanent : toLibrary) {
|
|
||||||
player.moveCardToLibraryWithInfo(permanent, source, game, Zone.BATTLEFIELD, true, false);
|
|
||||||
}
|
|
||||||
// cards to bottom
|
|
||||||
cards.clear();
|
|
||||||
toLibrary.clear();
|
|
||||||
for (Permanent permanent : permanentsToBottom) {
|
|
||||||
if (permanent instanceof PermanentToken) {
|
|
||||||
toLibrary.add(permanent);
|
|
||||||
} else {
|
|
||||||
Card card = game.getCard(permanent.getId());
|
|
||||||
if (card != null) {
|
|
||||||
cards.add(card);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
target = new TargetCard(Zone.BATTLEFIELD, new FilterCard("order to put on bottom of library (last choosen will be bottommost card)"));
|
|
||||||
while (player.canRespond() && cards.size() > 1) {
|
|
||||||
player.choose(Outcome.Neutral, cards, target, game);
|
|
||||||
|
|
||||||
Card card = cards.get(target.getFirstTarget(), game);
|
PlayerList playerList = game.getState().getPlayersInRange(controller.getId(), game);
|
||||||
if (card != null) {
|
playerList.setCurrent(game.getActivePlayerId());
|
||||||
cards.remove(card);
|
Player player = game.getPlayer(game.getActivePlayerId());
|
||||||
Permanent permanent = game.getPermanent(card.getId());
|
Player activePlayer = player;
|
||||||
if (permanent != null) {
|
do {
|
||||||
toLibrary.add(permanent);
|
List<Permanent> permanentsToTop = new ArrayList<>();
|
||||||
}
|
List<Permanent> permanentsToBottom = new ArrayList<>();
|
||||||
|
for (Permanent permanent : game.getState().getBattlefield().getActivePermanents(new FilterAttackingCreature(), player.getId(), source.getSourceId(), game)) {
|
||||||
|
if (permanent.isOwnedBy(player.getId())) {
|
||||||
|
if (player.chooseUse(outcome, "Put " + permanent.getLogName() + " to the top? (else it goes to bottom)", source, game)) {
|
||||||
|
permanentsToTop.add(permanent);
|
||||||
|
game.informPlayers(permanent.getLogName() + " goes to the top of " + player.getLogName() + "'s library");
|
||||||
|
} else {
|
||||||
|
permanentsToBottom.add(permanent);
|
||||||
|
game.informPlayers(permanent.getLogName() + " goes to the bottom of " + player.getLogName() + "'s library");
|
||||||
}
|
}
|
||||||
target.clearChosen();
|
|
||||||
}
|
}
|
||||||
if (cards.size() == 1) {
|
}
|
||||||
Card card = cards.get(cards.iterator().next(), game);
|
// cards to top
|
||||||
|
Cards cards = new CardsImpl();
|
||||||
|
List<Permanent> toLibrary = new ArrayList<>();
|
||||||
|
for (Permanent permanent : permanentsToTop) {
|
||||||
|
if (permanent instanceof PermanentToken) {
|
||||||
|
toLibrary.add(permanent);
|
||||||
|
} else {
|
||||||
|
Card card = game.getCard(permanent.getId());
|
||||||
|
if (card != null) {
|
||||||
|
cards.add(card);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TargetCard target = new TargetCard(Zone.BATTLEFIELD, new FilterCard("order to put on the top of library (last choosen will be the top most)"));
|
||||||
|
while (cards.size() > 1) {
|
||||||
|
if (!player.canRespond()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
player.choose(Outcome.Neutral, cards, target, game);
|
||||||
|
Card card = cards.get(target.getFirstTarget(), game);
|
||||||
|
if (card != null) {
|
||||||
|
cards.remove(card);
|
||||||
Permanent permanent = game.getPermanent(card.getId());
|
Permanent permanent = game.getPermanent(card.getId());
|
||||||
if (permanent != null) {
|
if (permanent != null) {
|
||||||
toLibrary.add(permanent);
|
toLibrary.add(permanent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// move all permanents to lib at the same time
|
target.clearChosen();
|
||||||
for (Permanent permanent : toLibrary) {
|
}
|
||||||
player.moveCardToLibraryWithInfo(permanent, source, game, Zone.BATTLEFIELD, false, false);
|
if (cards.size() == 1) {
|
||||||
|
Card card = cards.get(cards.iterator().next(), game);
|
||||||
|
Permanent permanent = game.getPermanent(card.getId());
|
||||||
|
if (permanent != null) {
|
||||||
|
toLibrary.add(permanent);
|
||||||
}
|
}
|
||||||
player = playerList.getNext(game, false);
|
}
|
||||||
} while (player != null && !player.getId().equals(game.getActivePlayerId()) && activePlayer.canRespond());
|
// move all permanents to lib at the same time
|
||||||
return true;
|
for (Permanent permanent : toLibrary) {
|
||||||
}
|
player.moveCardToLibraryWithInfo(permanent, source, game, Zone.BATTLEFIELD, true, false);
|
||||||
return false;
|
}
|
||||||
|
// cards to bottom
|
||||||
|
cards.clear();
|
||||||
|
toLibrary.clear();
|
||||||
|
for (Permanent permanent : permanentsToBottom) {
|
||||||
|
if (permanent instanceof PermanentToken) {
|
||||||
|
toLibrary.add(permanent);
|
||||||
|
} else {
|
||||||
|
Card card = game.getCard(permanent.getId());
|
||||||
|
if (card != null) {
|
||||||
|
cards.add(card);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
target = new TargetCard(Zone.BATTLEFIELD, new FilterCard("order to put on bottom of library (last choosen will be bottommost card)"));
|
||||||
|
while (player.canRespond() && cards.size() > 1) {
|
||||||
|
player.choose(Outcome.Neutral, cards, target, game);
|
||||||
|
|
||||||
|
Card card = cards.get(target.getFirstTarget(), game);
|
||||||
|
if (card != null) {
|
||||||
|
cards.remove(card);
|
||||||
|
Permanent permanent = game.getPermanent(card.getId());
|
||||||
|
if (permanent != null) {
|
||||||
|
toLibrary.add(permanent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
target.clearChosen();
|
||||||
|
}
|
||||||
|
if (cards.size() == 1) {
|
||||||
|
Card card = cards.get(cards.iterator().next(), game);
|
||||||
|
Permanent permanent = game.getPermanent(card.getId());
|
||||||
|
if (permanent != null) {
|
||||||
|
toLibrary.add(permanent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// move all permanents to lib at the same time
|
||||||
|
for (Permanent permanent : toLibrary) {
|
||||||
|
player.moveCardToLibraryWithInfo(permanent, source, game, Zone.BATTLEFIELD, false, false);
|
||||||
|
}
|
||||||
|
player = playerList.getNext(game, false);
|
||||||
|
} while (player != null && !player.getId().equals(game.getActivePlayerId()) && activePlayer.canRespond());
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,37 +50,37 @@ public final class AgelessSentinels extends CardImpl {
|
||||||
public AgelessSentinels copy() {
|
public AgelessSentinels copy() {
|
||||||
return new AgelessSentinels(this);
|
return new AgelessSentinels(this);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class AgelessSentinelsEffect extends ContinuousEffectImpl {
|
class AgelessSentinelsEffect extends ContinuousEffectImpl {
|
||||||
|
|
||||||
public AgelessSentinelsEffect() {
|
public AgelessSentinelsEffect() {
|
||||||
super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.BecomeCreature);
|
super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.BecomeCreature);
|
||||||
staticText = "it becomes a Bird Giant";
|
staticText = "it becomes a Bird Giant";
|
||||||
|
}
|
||||||
|
|
||||||
|
private AgelessSentinelsEffect(final AgelessSentinelsEffect effect) {
|
||||||
|
super(effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AgelessSentinelsEffect copy() {
|
||||||
|
return new AgelessSentinelsEffect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source) {
|
||||||
|
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||||
|
if (permanent == null) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
permanent.removeAllCreatureTypes(game);
|
||||||
|
permanent.addSubType(game, SubType.BIRD, SubType.GIANT);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public AgelessSentinelsEffect(final AgelessSentinelsEffect effect) {
|
@Override
|
||||||
super(effect);
|
public boolean hasLayer(Layer layer) {
|
||||||
}
|
return layer == Layer.TypeChangingEffects_4;
|
||||||
|
|
||||||
@Override
|
|
||||||
public AgelessSentinelsEffect copy() {
|
|
||||||
return new AgelessSentinelsEffect(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean apply(Game game, Ability source) {
|
|
||||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
|
||||||
if (permanent == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
permanent.removeAllCreatureTypes(game);
|
|
||||||
permanent.addSubType(game, SubType.BIRD, SubType.GIANT);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasLayer(Layer layer) {
|
|
||||||
return layer == Layer.TypeChangingEffects_4;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,7 @@ class AkoumHellkiteTriggeredAbility extends TriggeredAbilityImpl {
|
||||||
super(Zone.BATTLEFIELD, new AkoumHellkiteDamageEffect());
|
super(Zone.BATTLEFIELD, new AkoumHellkiteDamageEffect());
|
||||||
}
|
}
|
||||||
|
|
||||||
public AkoumHellkiteTriggeredAbility(final AkoumHellkiteTriggeredAbility ability) {
|
private AkoumHellkiteTriggeredAbility(final AkoumHellkiteTriggeredAbility ability) {
|
||||||
super(ability);
|
super(ability);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,19 +75,21 @@ class AkoumHellkiteTriggeredAbility extends TriggeredAbilityImpl {
|
||||||
@Override
|
@Override
|
||||||
public boolean checkTrigger(GameEvent event, Game game) {
|
public boolean checkTrigger(GameEvent event, Game game) {
|
||||||
Permanent permanent = game.getPermanent(event.getTargetId());
|
Permanent permanent = game.getPermanent(event.getTargetId());
|
||||||
if (permanent != null
|
if (permanent == null) { return false; }
|
||||||
&& permanent.isLand(game)
|
|
||||||
&& permanent.isControlledBy(getControllerId())) {
|
if (!permanent.isLand(game) || !permanent.isControlledBy(getControllerId())) { return false; }
|
||||||
Permanent sourcePermanent = game.getPermanent(getSourceId());
|
|
||||||
if (sourcePermanent != null) {
|
Permanent sourcePermanent = game.getPermanent(getSourceId());
|
||||||
for (Effect effect : getEffects()) {
|
if (sourcePermanent == null) { return false; }
|
||||||
if (effect instanceof AkoumHellkiteDamageEffect) {
|
|
||||||
effect.setTargetPointer(new FixedTarget(permanent, game));
|
for (Effect effect : getEffects()) {
|
||||||
}
|
if (effect instanceof AkoumHellkiteDamageEffect) {
|
||||||
return true;
|
effect.setTargetPointer(new FixedTarget(permanent, game));
|
||||||
}
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
// The Hellkit somehow lost it's damage effect but not it's landfall ability
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,24 +118,22 @@ class AkoumHellkiteDamageEffect extends OneShotEffect {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Permanent land = getTargetPointer().getFirstTargetPermanentOrLKI(game, source);
|
Permanent land = getTargetPointer().getFirstTargetPermanentOrLKI(game, source);
|
||||||
|
if (land == null) { return false; }
|
||||||
|
|
||||||
|
int damage = land.hasSubtype(SubType.MOUNTAIN, game) ? 2 : 1;
|
||||||
|
|
||||||
|
// Get target for damange
|
||||||
Player player = game.getPlayer(source.getFirstTarget());
|
Player player = game.getPlayer(source.getFirstTarget());
|
||||||
if (land != null && player != null) {
|
|
||||||
if (land.hasSubtype(SubType.MOUNTAIN, game)) {
|
|
||||||
player.damage(2, source.getSourceId(), source, game);
|
|
||||||
} else {
|
|
||||||
player.damage(1, source.getSourceId(), source, game);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
Permanent permanent = game.getPermanent(source.getFirstTarget());
|
Permanent permanent = game.getPermanent(source.getFirstTarget());
|
||||||
if (land != null && permanent != null) {
|
if (player == null && permanent == null) { return false; }
|
||||||
if (land.hasSubtype(SubType.MOUNTAIN, game)) {
|
|
||||||
permanent.damage(2, source.getSourceId(), source, game);
|
if (player != null) {
|
||||||
} else {
|
// Target is a player
|
||||||
permanent.damage(1, source.getSourceId(), source, game);
|
player.damage(damage, source.getSourceId(), source, game);
|
||||||
}
|
} else {
|
||||||
return true;
|
// Target is a permanent
|
||||||
|
permanent.damage(damage, source.getSourceId(), source, game);
|
||||||
}
|
}
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,8 +37,10 @@ public final class AkroanHorse extends CardImpl {
|
||||||
|
|
||||||
// Defender
|
// Defender
|
||||||
this.addAbility(DefenderAbility.getInstance());
|
this.addAbility(DefenderAbility.getInstance());
|
||||||
|
|
||||||
// When Akroan Horse enters the battlefield, an opponent gains control of it.
|
// When Akroan Horse enters the battlefield, an opponent gains control of it.
|
||||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new AkroanHorseChangeControlEffect(), false));
|
this.addAbility(new EntersBattlefieldTriggeredAbility(new AkroanHorseChangeControlEffect(), false));
|
||||||
|
|
||||||
// At the beginning of your upkeep, each opponent create a 1/1 white Soldier creature token.
|
// At the beginning of your upkeep, each opponent create a 1/1 white Soldier creature token.
|
||||||
this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new AkroanHorseCreateTokenEffect(), TargetController.YOU, false));
|
this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new AkroanHorseCreateTokenEffect(), TargetController.YOU, false));
|
||||||
}
|
}
|
||||||
|
@ -60,7 +62,7 @@ class AkroanHorseChangeControlEffect extends OneShotEffect {
|
||||||
this.staticText = "an opponent gains control of it";
|
this.staticText = "an opponent gains control of it";
|
||||||
}
|
}
|
||||||
|
|
||||||
public AkroanHorseChangeControlEffect(final AkroanHorseChangeControlEffect effect) {
|
private AkroanHorseChangeControlEffect(final AkroanHorseChangeControlEffect effect) {
|
||||||
super(effect);
|
super(effect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,7 +90,7 @@ class AkroanHorseChangeControlEffect extends OneShotEffect {
|
||||||
|
|
||||||
class AkroanHorseGainControlEffect extends ContinuousEffectImpl {
|
class AkroanHorseGainControlEffect extends ContinuousEffectImpl {
|
||||||
|
|
||||||
UUID controller;
|
private final UUID controller;
|
||||||
|
|
||||||
public AkroanHorseGainControlEffect(Duration duration, UUID controller) {
|
public AkroanHorseGainControlEffect(Duration duration, UUID controller) {
|
||||||
super(duration, Layer.ControlChangingEffects_2, SubLayer.NA, Outcome.GainControl);
|
super(duration, Layer.ControlChangingEffects_2, SubLayer.NA, Outcome.GainControl);
|
||||||
|
@ -107,14 +109,18 @@ class AkroanHorseGainControlEffect extends ContinuousEffectImpl {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Permanent permanent = game.getPermanent(source.getFirstTarget());
|
Permanent permanent;
|
||||||
if (targetPointer != null) {
|
|
||||||
|
if (targetPointer == null) {
|
||||||
|
permanent = game.getPermanent(source.getFirstTarget());
|
||||||
|
} else {
|
||||||
permanent = game.getPermanent(targetPointer.getFirst(game, source));
|
permanent = game.getPermanent(targetPointer.getFirst(game, source));
|
||||||
}
|
}
|
||||||
if (permanent != null) {
|
|
||||||
return permanent.changeControllerId(controller, game, source);
|
if (permanent == null) { return false; }
|
||||||
}
|
|
||||||
return false;
|
return permanent.changeControllerId(controller, game, source);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -130,7 +136,7 @@ class AkroanHorseCreateTokenEffect extends OneShotEffect {
|
||||||
this.staticText = "each opponent creates a 1/1 white Soldier creature token";
|
this.staticText = "each opponent creates a 1/1 white Soldier creature token";
|
||||||
}
|
}
|
||||||
|
|
||||||
public AkroanHorseCreateTokenEffect(final AkroanHorseCreateTokenEffect effect) {
|
private AkroanHorseCreateTokenEffect(final AkroanHorseCreateTokenEffect effect) {
|
||||||
super(effect);
|
super(effect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -106,7 +106,7 @@ class AkromaVisionOfIxidorEffect extends OneShotEffect {
|
||||||
StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE,
|
StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE,
|
||||||
source.getControllerId(), source.getSourceId(), game
|
source.getControllerId(), source.getSourceId(), game
|
||||||
)) {
|
)) {
|
||||||
Abilities abilities = permanent.getAbilities(game);
|
Abilities<Ability> abilities = permanent.getAbilities(game);
|
||||||
int count = classes
|
int count = classes
|
||||||
.stream()
|
.stream()
|
||||||
.map(clazz -> abilities.stream().anyMatch(clazz::isInstance))
|
.map(clazz -> abilities.stream().anyMatch(clazz::isInstance))
|
||||||
|
|
|
@ -65,27 +65,26 @@ class AliFromCairoReplacementEffect extends ReplacementEffectImpl {
|
||||||
@Override
|
@Override
|
||||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||||
if (permanent != null) {
|
if (permanent == null) { return false; }
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
|
||||||
if (controller != null
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
&& (controller.getLife() > 0) &&(controller.getLife() - event.getAmount()) < 1
|
if (controller == null) { return false; }
|
||||||
&& event.getPlayerId().equals(controller.getId())
|
|
||||||
) {
|
return (controller.getLife() > 0) && (controller.getLife() - event.getAmount()) < 1
|
||||||
return true;
|
&& event.getPlayerId().equals(controller.getId());
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
if (controller != null) {
|
if (controller == null) { return false; }
|
||||||
// 10/1/2008: The ability doesn't change how much damage is dealt;
|
|
||||||
// it just changes how much life that damage makes you lose.
|
// 10/1/2008: The ability doesn't change how much damage is dealt;
|
||||||
// An effect such as Spirit Link will see the full amount of damage being dealt.
|
// it just changes how much life that damage makes you lose.
|
||||||
event.setAmount(controller.getLife() - 1);
|
// An effect such as Spirit Link will see the full amount of damage being dealt.
|
||||||
}
|
event.setAmount(controller.getLife() - 1);
|
||||||
|
|
||||||
|
// TODO: Is this supposed to be false? Seem suspicious
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,20 +70,20 @@ class AlignedHedronNetworkExileEffect extends OneShotEffect {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
|
if (controller == null) { return false;}
|
||||||
|
|
||||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||||
|
if (permanent == null) { return false; }
|
||||||
|
|
||||||
// If Whale leaves the battlefield before its triggered ability resolves,
|
// If Whale leaves the battlefield before its triggered ability resolves,
|
||||||
// the target creature won't be exiled.
|
// the target creature won't be exiled.
|
||||||
if (controller != null && permanent != null) {
|
Set<Card> toExile = new LinkedHashSet<>(game.getBattlefield().getActivePermanents(filter, controller.getId(), source.getSourceId(), game));
|
||||||
Set<Card> toExile = new LinkedHashSet<>();
|
if (toExile.isEmpty()) { return false; }
|
||||||
for (Permanent creature : game.getBattlefield().getActivePermanents(filter, controller.getId(), source.getSourceId(), game)) {
|
|
||||||
toExile.add(creature);
|
controller.moveCardsToExile(toExile, source, game, true, CardUtil.getCardExileZoneId(game, source), permanent.getIdName());
|
||||||
}
|
new CreateDelayedTriggeredAbilityEffect(new OnLeaveReturnExiledToBattlefieldAbility()).apply(game, source);
|
||||||
if (!toExile.isEmpty()) {
|
|
||||||
controller.moveCardsToExile(toExile, source, game, true, CardUtil.getCardExileZoneId(game, source), permanent.getIdName());
|
return true;
|
||||||
new CreateDelayedTriggeredAbilityEffect(new OnLeaveReturnExiledToBattlefieldAbility()).apply(game, source);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import mage.abilities.dynamicvalue.common.StaticValue;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.abilities.effects.common.ExileSpellEffect;
|
import mage.abilities.effects.common.ExileSpellEffect;
|
||||||
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
||||||
|
import mage.abilities.effects.common.counter.RemoveCounterSourceEffect;
|
||||||
import mage.cards.*;
|
import mage.cards.*;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
|
@ -34,10 +35,18 @@ public final class AllHallowsEve extends CardImpl {
|
||||||
this.getSpellAbility().addEffect(new ExileSpellEffect());
|
this.getSpellAbility().addEffect(new ExileSpellEffect());
|
||||||
this.getSpellAbility().addEffect(new AddCountersSourceEffect(
|
this.getSpellAbility().addEffect(new AddCountersSourceEffect(
|
||||||
CounterType.SCREAM.createInstance(), StaticValue.get(2), true, true
|
CounterType.SCREAM.createInstance(), StaticValue.get(2), true, true
|
||||||
).setText("with 2 scream counters on it"));
|
).setText("with two scream counters on it"));
|
||||||
|
|
||||||
// At the beginning of your upkeep, if All Hallow's Eve is exiled with a scream counter on it, remove a scream counter from it. If there are no more scream counters on it, put it into your graveyard and each player returns all creature cards from their graveyard to the battlefield.
|
// At the beginning of your upkeep, if All Hallow's Eve is exiled with a scream counter on it, remove a scream counter from it.
|
||||||
this.addAbility(new ConditionalInterveningIfTriggeredAbility(new BeginningOfUpkeepTriggeredAbility(Zone.EXILED, new AllHallowsEveEffect(), TargetController.YOU, false), AllHallowsEveCondition.instance, "At the beginning of your upkeep, if {this} is exiled with a scream counter on it, remove a scream counter from it. If there are no more scream counters on it, put it into your graveyard and each player returns all creature cards from their graveyard to the battlefield."));
|
// If there are no more scream counters on it, put it into your graveyard and each player returns all creature cards from their graveyard to the battlefield.
|
||||||
|
Ability ability = new BeginningOfUpkeepTriggeredAbility(
|
||||||
|
Zone.EXILED,
|
||||||
|
new RemoveCounterSourceEffect(CounterType.SCREAM.createInstance(1)),
|
||||||
|
TargetController.YOU,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
ability.addEffect(new AllHallowsEveEffect());
|
||||||
|
this.addAbility(ability);
|
||||||
}
|
}
|
||||||
|
|
||||||
private AllHallowsEve(final AllHallowsEve card) {
|
private AllHallowsEve(final AllHallowsEve card) {
|
||||||
|
@ -50,23 +59,12 @@ public final class AllHallowsEve extends CardImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum AllHallowsEveCondition implements Condition {
|
|
||||||
instance;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean apply(Game game, Ability source) {
|
|
||||||
MageObject sourceObject = source.getSourceObjectIfItStillExists(game);
|
|
||||||
return sourceObject != null
|
|
||||||
&& game.getState().getZone(source.getSourceId()) == Zone.EXILED
|
|
||||||
&& sourceObject instanceof Card
|
|
||||||
&& ((Card) sourceObject).getMainCard().getCounters(game).getCount(CounterType.SCREAM) > 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class AllHallowsEveEffect extends OneShotEffect {
|
class AllHallowsEveEffect extends OneShotEffect {
|
||||||
|
|
||||||
AllHallowsEveEffect() {
|
AllHallowsEveEffect() {
|
||||||
super(Outcome.PutCreatureInPlay);
|
super(Outcome.PutCreatureInPlay);
|
||||||
|
staticText = "If there are no more scream counters on it, put it into your graveyard " +
|
||||||
|
"and each player returns all creature cards from their graveyard to the battlefield.";
|
||||||
}
|
}
|
||||||
|
|
||||||
private AllHallowsEveEffect(final AllHallowsEveEffect effect) {
|
private AllHallowsEveEffect(final AllHallowsEveEffect effect) {
|
||||||
|
@ -80,13 +78,15 @@ class AllHallowsEveEffect extends OneShotEffect {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Card card = (Card) source.getSourceObject(game);
|
Card allHallowsEveCard = (Card) source.getSourceObject(game);
|
||||||
|
if (allHallowsEveCard == null) { return false; }
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
if (card == null || controller == null) {
|
if (controller == null) { return false; }
|
||||||
return false;
|
|
||||||
}
|
if (allHallowsEveCard.getCounters(game).getCount(CounterType.SCREAM) > 0) { return false; }
|
||||||
controller.moveCards(card, Zone.GRAVEYARD, source, game);
|
|
||||||
Cards cards = new CardsImpl();
|
controller.moveCards(allHallowsEveCard, Zone.GRAVEYARD, source, game);
|
||||||
|
Cards allCreatureCardsInGraveyards = new CardsImpl();
|
||||||
game.getState()
|
game.getState()
|
||||||
.getPlayersInRange(source.getControllerId(), game)
|
.getPlayersInRange(source.getControllerId(), game)
|
||||||
.stream()
|
.stream()
|
||||||
|
@ -96,8 +96,9 @@ class AllHallowsEveEffect extends OneShotEffect {
|
||||||
.map(g -> g.getCards(game))
|
.map(g -> g.getCards(game))
|
||||||
.flatMap(Collection::stream)
|
.flatMap(Collection::stream)
|
||||||
.filter(card1 -> card1.isCreature(game))
|
.filter(card1 -> card1.isCreature(game))
|
||||||
.forEach(cards::add);
|
.forEach(allCreatureCardsInGraveyards::add);
|
||||||
controller.moveCards(card, Zone.BATTLEFIELD, source, game, false, false, true, null);
|
|
||||||
|
controller.moveCards(allCreatureCardsInGraveyards.getCards(game), Zone.BATTLEFIELD, source, game, false, false, true, null);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,8 +71,8 @@ class AltarOfTheLostManaCondition implements Condition {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
MageObject object = game.getObject(source.getSourceId());
|
MageObject object = game.getObject(source.getSourceId());
|
||||||
if (game != null && game.inCheckPlayableState()) {
|
if (game.inCheckPlayableState()) {
|
||||||
if (object instanceof Card && game.getState().getZone(source.getSourceId()).equals(Zone.GRAVEYARD)) {
|
if (object instanceof Card && game.getState().getZone(source.getSourceId()) == Zone.GRAVEYARD) {
|
||||||
for (Ability ability : ((Card) object).getAbilities(game)) {
|
for (Ability ability : ((Card) object).getAbilities(game)) {
|
||||||
if (ability instanceof FlashbackAbility) {
|
if (ability instanceof FlashbackAbility) {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -37,7 +37,8 @@ public class AminatousAugury extends CardImpl {
|
||||||
public AminatousAugury(UUID ownerId, CardSetInfo setInfo) {
|
public AminatousAugury(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{6}{U}{U}");
|
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{6}{U}{U}");
|
||||||
|
|
||||||
// Exile the top eight cards of your library. You may put a land card from among them onto the battlefield.
|
// Exile the top eight cards of your library.
|
||||||
|
// You may put a land card from among them onto the battlefield.
|
||||||
// Until end of turn, for each nonland card type, you may cast a card of that type from among the exiled cards
|
// Until end of turn, for each nonland card type, you may cast a card of that type from among the exiled cards
|
||||||
// without paying its mana cost.
|
// without paying its mana cost.
|
||||||
this.getSpellAbility().addEffect(new AminatousAuguryEffect());
|
this.getSpellAbility().addEffect(new AminatousAuguryEffect());
|
||||||
|
@ -58,9 +59,10 @@ class AminatousAuguryEffect extends OneShotEffect {
|
||||||
|
|
||||||
public AminatousAuguryEffect() {
|
public AminatousAuguryEffect() {
|
||||||
super(Outcome.PlayForFree);
|
super(Outcome.PlayForFree);
|
||||||
staticText = "Exile the top eight cards of your library. You may put a land card from among them onto the"
|
staticText = "Exile the top eight cards of your library. " +
|
||||||
+ " battlefield. Until end of turn, for each nonland card type, you may cast a card of that type from"
|
"You may put a land card from among them onto the battlefield. " +
|
||||||
+ " among the exiled cards without paying its mana cost.";
|
"Until end of turn, for each nonland card type, " +
|
||||||
|
"you may cast a card of that type from among the exiled cards without paying its mana cost.";
|
||||||
}
|
}
|
||||||
|
|
||||||
public AminatousAuguryEffect(final AminatousAuguryEffect effect) {
|
public AminatousAuguryEffect(final AminatousAuguryEffect effect) {
|
||||||
|
@ -74,41 +76,42 @@ class AminatousAuguryEffect extends OneShotEffect {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
|
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
|
if (controller == null) { return false; }
|
||||||
|
|
||||||
MageObject sourceObject = source.getSourceObject(game);
|
MageObject sourceObject = source.getSourceObject(game);
|
||||||
if (controller != null && sourceObject != null) {
|
if (sourceObject == null) { return false; }
|
||||||
// move cards from library to exile
|
|
||||||
controller.moveCardsToExile(controller.getLibrary().getTopCards(game, 8), source, game, true, source.getSourceId(), CardUtil.createObjectRealtedWindowTitle(source, game, null));
|
// move cards from library to exile
|
||||||
ExileZone auguryExileZone = game.getExile().getExileZone(source.getSourceId());
|
controller.moveCardsToExile(controller.getLibrary().getTopCards(game, 8), source, game, true, source.getSourceId(), CardUtil.createObjectRealtedWindowTitle(source, game, null));
|
||||||
if (auguryExileZone == null) {
|
ExileZone auguryExileZone = game.getExile().getExileZone(source.getSourceId());
|
||||||
return true;
|
if (auguryExileZone == null) { return true; }
|
||||||
}
|
|
||||||
Cards cardsToCast = new CardsImpl();
|
Cards cardsToCast = new CardsImpl();
|
||||||
cardsToCast.addAll(auguryExileZone.getCards(game));
|
cardsToCast.addAll(auguryExileZone.getCards(game));
|
||||||
// put a land card from among them onto the battlefield
|
|
||||||
TargetCard target = new TargetCard(
|
// put a land card from among them onto the battlefield
|
||||||
Zone.EXILED,
|
TargetCard target = new TargetCard(Zone.EXILED, StaticFilters.FILTER_CARD_LAND_A);
|
||||||
StaticFilters.FILTER_CARD_LAND_A
|
|
||||||
);
|
if (cardsToCast.count(StaticFilters.FILTER_CARD_LAND, game) == 0) { return true; }
|
||||||
if (cardsToCast.count(StaticFilters.FILTER_CARD_LAND, game) > 0) {
|
|
||||||
if (controller.chooseUse(Outcome.PutLandInPlay, "Put a land from among the exiled cards into play?", source, game)) {
|
if (controller.chooseUse(Outcome.PutLandInPlay, "Put a land from among the exiled cards into play?", source, game)) {
|
||||||
if (controller.choose(Outcome.PutLandInPlay, cardsToCast, target, game)) {
|
if (controller.choose(Outcome.PutLandInPlay, cardsToCast, target, game)) {
|
||||||
Card card = cardsToCast.get(target.getFirstTarget(), game);
|
Card card = cardsToCast.get(target.getFirstTarget(), game);
|
||||||
if (card != null) {
|
if (card != null) {
|
||||||
cardsToCast.remove(card);
|
cardsToCast.remove(card);
|
||||||
controller.moveCards(card, Zone.BATTLEFIELD, source, game, false, false, true, null);
|
controller.moveCards(card, Zone.BATTLEFIELD, source, game, false, false, true, null);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (Card card : cardsToCast.getCards(StaticFilters.FILTER_CARD_NON_LAND, game)) {
|
|
||||||
AminatousAuguryCastFromExileEffect effect = new AminatousAuguryCastFromExileEffect();
|
|
||||||
effect.setTargetPointer(new FixedTarget(card, game));
|
|
||||||
game.addEffect(effect, source);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
|
for (Card card : cardsToCast.getCards(StaticFilters.FILTER_CARD_NON_LAND, game)) {
|
||||||
|
AminatousAuguryCastFromExileEffect effect = new AminatousAuguryCastFromExileEffect();
|
||||||
|
effect.setTargetPointer(new FixedTarget(card, game));
|
||||||
|
game.addEffect(effect, source);
|
||||||
|
}
|
||||||
|
// TODO: I think this should be returning true
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,51 +139,54 @@ class AminatousAuguryCastFromExileEffect extends AsThoughEffectImpl {
|
||||||
@Override
|
@Override
|
||||||
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
|
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
|
||||||
Player player = game.getPlayer(affectedControllerId);
|
Player player = game.getPlayer(affectedControllerId);
|
||||||
EnumSet<CardType> usedCardTypes = EnumSet.noneOf(CardType.class);
|
if (player == null) { return false; }
|
||||||
|
|
||||||
if (game.getState().getValue(source.getSourceId().toString() + "cardTypes") != null) {
|
if (!affectedControllerId.equals(source.getControllerId())) { return false; }
|
||||||
|
|
||||||
|
EnumSet<CardType> usedCardTypes;
|
||||||
|
if (game.getState().getValue(source.getSourceId().toString() + "cardTypes") == null) {
|
||||||
|
// The effect has not been applied fully yet, so there are no previously cast times
|
||||||
|
usedCardTypes = EnumSet.noneOf(CardType.class);
|
||||||
|
} else {
|
||||||
usedCardTypes = (EnumSet<CardType>) game.getState().getValue(source.getSourceId().toString() + "cardTypes");
|
usedCardTypes = (EnumSet<CardType>) game.getState().getValue(source.getSourceId().toString() + "cardTypes");
|
||||||
}
|
}
|
||||||
if (player != null
|
|
||||||
&& objectId != null
|
if (objectId == null || !objectId.equals(getTargetPointer().getFirst(game, source))) { return false; }
|
||||||
&& objectId.equals(getTargetPointer().getFirst(game, source))
|
|
||||||
&& affectedControllerId.equals(source.getControllerId())) {
|
if (game.getState().getZone(objectId) != Zone.EXILED) { return false; }
|
||||||
Card card = game.getCard(objectId);
|
|
||||||
if (card != null
|
Card card = game.getCard(objectId);
|
||||||
&& game.getState().getZone(objectId) == Zone.EXILED) {
|
if (card == null) { return false; }
|
||||||
EnumSet<CardType> unusedCardTypes = EnumSet.noneOf(CardType.class);
|
|
||||||
for (CardType cardT : card.getCardType(game)) {
|
// Figure out which of the current card's types have not been cast before
|
||||||
if (!usedCardTypes.contains(cardT)) {
|
EnumSet<CardType> unusedCardTypes = EnumSet.noneOf(CardType.class);
|
||||||
unusedCardTypes.add(cardT);
|
for (CardType cardT : card.getCardType(game)) {
|
||||||
}
|
if (!usedCardTypes.contains(cardT)) {
|
||||||
}
|
unusedCardTypes.add(cardT);
|
||||||
if (!unusedCardTypes.isEmpty()) {
|
|
||||||
if (!game.inCheckPlayableState()) { // some actions may not be done while the game only checks if a card can be cast
|
|
||||||
// Select the card type to consume and remove all not seleczted card types
|
|
||||||
if (unusedCardTypes.size() > 1) {
|
|
||||||
Choice choice = new ChoiceImpl(true);
|
|
||||||
choice.setMessage("Which card type do you want to consume?");
|
|
||||||
Set<String> choices = choice.getChoices();
|
|
||||||
for (CardType cardType : unusedCardTypes) {
|
|
||||||
choices.add(cardType.toString());
|
|
||||||
}
|
|
||||||
player.choose(Outcome.Detriment, choice, game);
|
|
||||||
for (Iterator<CardType> iterator = unusedCardTypes.iterator(); iterator.hasNext();) {
|
|
||||||
CardType next = iterator.next();
|
|
||||||
if (!next.toString().equals(choice.getChoice())) {
|
|
||||||
iterator.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
usedCardTypes.add(CardType.fromString(choice.getChoice()));
|
|
||||||
}
|
|
||||||
usedCardTypes.addAll(unusedCardTypes);
|
|
||||||
game.getState().setValue(source.getSourceId().toString() + "cardTypes", usedCardTypes);
|
|
||||||
}
|
|
||||||
player.setCastSourceIdWithAlternateMana(objectId, null, card.getSpellAbility().getCosts());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
|
// The current card has only card types that have been cast before, so it can't be cast
|
||||||
|
if (unusedCardTypes.isEmpty()) { return false; }
|
||||||
|
|
||||||
|
// some actions may not be done while the game only checks if a card can be cast
|
||||||
|
if (!game.inCheckPlayableState()) {
|
||||||
|
// Select the card type to consume and remove all not selected card types
|
||||||
|
if (unusedCardTypes.size() > 1) {
|
||||||
|
Choice choice = new ChoiceImpl(true);
|
||||||
|
choice.setMessage("Which card type do you want to consume?");
|
||||||
|
Set<String> choices = choice.getChoices();
|
||||||
|
for (CardType cardType : unusedCardTypes) {
|
||||||
|
choices.add(cardType.toString());
|
||||||
|
}
|
||||||
|
player.choose(Outcome.Detriment, choice, game);
|
||||||
|
unusedCardTypes.removeIf(next -> !next.toString().equals(choice.getChoice()));
|
||||||
|
usedCardTypes.add(CardType.fromString(choice.getChoice()));
|
||||||
|
}
|
||||||
|
usedCardTypes.addAll(unusedCardTypes);
|
||||||
|
game.getState().setValue(source.getSourceId().toString() + "cardTypes", usedCardTypes);
|
||||||
|
}
|
||||||
|
player.setCastSourceIdWithAlternateMana(objectId, null, card.getSpellAbility().getCosts());
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,16 +61,17 @@ class AnHavvaConstableEffect extends ContinuousEffectImpl {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
if (controller != null) {
|
if (controller == null) { return false; }
|
||||||
MageObject mageObject = game.getObject(source.getSourceId());
|
|
||||||
if (mageObject != null) {
|
MageObject mageObject = game.getObject(source.getSourceId());
|
||||||
FilterCreaturePermanent filter = new FilterCreaturePermanent("green creatures");
|
if (mageObject == null) { return false; }
|
||||||
filter.add(new ColorPredicate(ObjectColor.GREEN));
|
|
||||||
int number = game.getBattlefield().count(filter, source.getSourceId(), source.getControllerId(), game);
|
FilterCreaturePermanent filter = new FilterCreaturePermanent("green creatures");
|
||||||
mageObject.getToughness().setValue(number + 1);
|
filter.add(new ColorPredicate(ObjectColor.GREEN));
|
||||||
return true;
|
int numberOfGreenCreatures = game.getBattlefield().count(filter, source.getSourceId(), source.getControllerId(), game);
|
||||||
}
|
|
||||||
}
|
mageObject.getToughness().setValue(1 + numberOfGreenCreatures);
|
||||||
return false;
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,13 +102,14 @@ class ArcaneAdaptationEffect extends ContinuousEffectImpl {
|
||||||
// commander in command zone
|
// commander in command zone
|
||||||
for (CommandObject commandObject : game.getState().getCommand()) {
|
for (CommandObject commandObject : game.getState().getCommand()) {
|
||||||
if (commandObject instanceof Commander) {
|
if (commandObject instanceof Commander) {
|
||||||
Card card = game.getCard(((Commander) commandObject).getId());
|
Card card = game.getCard((commandObject).getId());
|
||||||
if (card != null && card.isOwnedBy(controller.getId())
|
if (card != null && card.isOwnedBy(controller.getId())
|
||||||
&& card.isCreature(game) && !card.hasSubtype(subType, game)) {
|
&& card.isCreature(game) && !card.hasSubtype(subType, game)) {
|
||||||
game.getState().getCreateMageObjectAttribute(card, game).getSubtype().add(subType);
|
game.getState().getCreateMageObjectAttribute(card, game).getSubtype().add(subType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// TODO: Why is this not using the for-in loop like all the others?
|
||||||
// creature spells you control
|
// creature spells you control
|
||||||
for (Iterator<StackObject> iterator = game.getStack().iterator(); iterator.hasNext(); ) {
|
for (Iterator<StackObject> iterator = game.getStack().iterator(); iterator.hasNext(); ) {
|
||||||
StackObject stackObject = iterator.next();
|
StackObject stackObject = iterator.next();
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package mage.cards.a;
|
package mage.cards.a;
|
||||||
|
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
|
import mage.MageObject;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.DealsDamageToOpponentTriggeredAbility;
|
import mage.abilities.common.DealsDamageToOpponentTriggeredAbility;
|
||||||
import mage.abilities.common.SimpleActivatedAbility;
|
import mage.abilities.common.SimpleActivatedAbility;
|
||||||
|
@ -38,7 +39,7 @@ public final class AtemsisAllSeeing extends CardImpl {
|
||||||
|
|
||||||
// {2}{U}, {T}: Draw two cards, then discard a card.
|
// {2}{U}, {T}: Draw two cards, then discard a card.
|
||||||
Ability ability = new SimpleActivatedAbility(
|
Ability ability = new SimpleActivatedAbility(
|
||||||
new DrawDiscardControllerEffect(2, 1), new ManaCostsImpl("{2}{U}")
|
new DrawDiscardControllerEffect(2, 1), new ManaCostsImpl<>("{2}{U}")
|
||||||
);
|
);
|
||||||
ability.addCost(new TapSourceCost());
|
ability.addCost(new TapSourceCost());
|
||||||
this.addAbility(ability);
|
this.addAbility(ability);
|
||||||
|
@ -88,7 +89,7 @@ class AtemsisAllSeeingEffect extends OneShotEffect {
|
||||||
.getHand()
|
.getHand()
|
||||||
.getCards(game)
|
.getCards(game)
|
||||||
.stream()
|
.stream()
|
||||||
.map(card -> card.getManaValue())
|
.map(MageObject::getManaValue)
|
||||||
.distinct()
|
.distinct()
|
||||||
.count() > 5) {
|
.count() > 5) {
|
||||||
opponent.lost(game);
|
opponent.lost(game);
|
||||||
|
|
|
@ -35,11 +35,11 @@ public final class AuraFinesse extends CardImpl {
|
||||||
public AuraFinesse(UUID ownerId, CardSetInfo setInfo) {
|
public AuraFinesse(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{U}");
|
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{U}");
|
||||||
|
|
||||||
|
|
||||||
// Attach target Aura you control to target creature.
|
// Attach target Aura you control to target creature.
|
||||||
this.getSpellAbility().addEffect(new AuraFinesseEffect());
|
this.getSpellAbility().addEffect(new AuraFinesseEffect());
|
||||||
this.getSpellAbility().addTarget(new TargetPermanent(filter));
|
this.getSpellAbility().addTarget(new TargetPermanent(filter));
|
||||||
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
|
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
|
||||||
|
|
||||||
// Draw a card.
|
// Draw a card.
|
||||||
this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1).concatBy("<br>"));
|
this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1).concatBy("<br>"));
|
||||||
}
|
}
|
||||||
|
@ -70,26 +70,28 @@ class AuraFinesseEffect extends OneShotEffect {
|
||||||
return new AuraFinesseEffect(this);
|
return new AuraFinesseEffect(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 15/06/2010 As Aura Finesse resolves, if either target is illegal,
|
||||||
|
// the spell resolves but the Aura doesn’t move. You still draw a card.
|
||||||
|
// If both targets are illegal, Aura Finesse doesn’t resolve and you don’t draw a card.
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
if (controller != null) {
|
if (controller == null) { return false; }
|
||||||
Permanent aura = game.getPermanent(source.getFirstTarget());
|
|
||||||
Permanent creature = game.getPermanent(source.getTargets().get(1).getFirstTarget());
|
Permanent aura = game.getPermanent(source.getFirstTarget());
|
||||||
if (aura != null && creature != null) {
|
Permanent creature = game.getPermanent(source.getTargets().get(1).getFirstTarget());
|
||||||
Permanent oldCreature = game.getPermanent(aura.getAttachedTo());
|
if (aura != null && creature != null) {
|
||||||
if (oldCreature != null && !oldCreature.equals(creature)) {
|
Permanent oldCreature = game.getPermanent(aura.getAttachedTo());
|
||||||
Target auraTarget = aura.getSpellAbility().getTargets().get(0);
|
if (oldCreature != null && !oldCreature.equals(creature)) {
|
||||||
if (!auraTarget.canTarget(creature.getId(), game)) {
|
Target auraTarget = aura.getSpellAbility().getTargets().get(0);
|
||||||
game.informPlayers(aura.getLogName() + " was not attched to " +creature.getLogName() + " because it's no legal target for the aura" );
|
if (!auraTarget.canTarget(creature.getId(), game)) {
|
||||||
} else if (oldCreature.removeAttachment(aura.getId(), source, game)) {
|
game.informPlayers(aura.getLogName() + " was not attched to " +creature.getLogName() + " because it's no legal target for the aura" );
|
||||||
game.informPlayers(aura.getLogName() + " was unattached from " + oldCreature.getLogName() + " and attached to " + creature.getLogName());
|
} else if (oldCreature.removeAttachment(aura.getId(), source, game)) {
|
||||||
creature.addAttachment(aura.getId(), source, game);
|
game.informPlayers(aura.getLogName() + " was unattached from " + oldCreature.getLogName() + " and attached to " + creature.getLogName());
|
||||||
}
|
creature.addAttachment(aura.getId(), source, game);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ import java.util.UUID;
|
||||||
*/
|
*/
|
||||||
public final class AuriokEdgewright extends CardImpl {
|
public final class AuriokEdgewright extends CardImpl {
|
||||||
|
|
||||||
protected static String effectText = "<i>Metalcraft</i> — Auriok Edgewright has double strike as long as you control three or more artifacts.";
|
private static final String effectText = "<i>Metalcraft</i> — Auriok Edgewright has double strike as long as you control three or more artifacts.";
|
||||||
|
|
||||||
public AuriokEdgewright(UUID ownerId, CardSetInfo setInfo) {
|
public AuriokEdgewright(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}{W}");
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}{W}");
|
||||||
|
|
|
@ -70,14 +70,9 @@ class AutumnWillowEffect extends AsThoughEffectImpl {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) {
|
public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) {
|
||||||
if (affectedControllerId.equals(source.getFirstTarget())) {
|
if (!affectedControllerId.equals(source.getFirstTarget())) { return false; }
|
||||||
Permanent creature = game.getPermanent(sourceId);
|
Permanent creature = game.getPermanent(sourceId);
|
||||||
if (creature != null) {
|
|
||||||
if (sourceId.equals(source.getSourceId())) {
|
return creature != null &&sourceId.equals(source.getSourceId());
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,9 +66,6 @@ class AvatarOfWoeCondition implements Condition {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
if (AvatarOfWoe.graveyardCount.calculate(game, source, null) >= 10) {
|
return AvatarOfWoe.graveyardCount.calculate(game, source, null) >= 10;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.SubType;
|
import mage.constants.SubType;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
import mage.filter.FilterPermanent;
|
import mage.filter.StaticFilters;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.GameEvent;
|
import mage.game.events.GameEvent;
|
||||||
import mage.game.events.ZoneChangeEvent;
|
import mage.game.events.ZoneChangeEvent;
|
||||||
|
@ -24,8 +24,6 @@ import java.util.UUID;
|
||||||
*/
|
*/
|
||||||
public final class AzoriusAethermage extends CardImpl {
|
public final class AzoriusAethermage extends CardImpl {
|
||||||
|
|
||||||
private static final String rule = "Whenever a permanent is returned to your hand, ";
|
|
||||||
|
|
||||||
public AzoriusAethermage(UUID ownerId, CardSetInfo setInfo) {
|
public AzoriusAethermage(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}{U}");
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}{U}");
|
||||||
|
|
||||||
|
@ -35,8 +33,8 @@ public final class AzoriusAethermage extends CardImpl {
|
||||||
this.toughness = new MageInt(1);
|
this.toughness = new MageInt(1);
|
||||||
|
|
||||||
// Whenever a permanent is returned to your hand, you may pay {1}. If you do, draw a card.
|
// Whenever a permanent is returned to your hand, you may pay {1}. If you do, draw a card.
|
||||||
Effect effect = new DoIfCostPaid(new DrawCardSourceControllerEffect(1), new ManaCostsImpl("{1}"));
|
Effect effect = new DoIfCostPaid(new DrawCardSourceControllerEffect(1), new ManaCostsImpl<>("{1}"));
|
||||||
this.addAbility(new AzoriusAEthermageAbility(Zone.BATTLEFIELD, Zone.BATTLEFIELD, Zone.HAND, effect, new FilterPermanent(), rule, false));
|
this.addAbility(new AzoriusAEthermageAbility(effect));
|
||||||
}
|
}
|
||||||
|
|
||||||
private AzoriusAethermage(final AzoriusAethermage card) {
|
private AzoriusAethermage(final AzoriusAethermage card) {
|
||||||
|
@ -51,25 +49,14 @@ public final class AzoriusAethermage extends CardImpl {
|
||||||
|
|
||||||
class AzoriusAEthermageAbility extends TriggeredAbilityImpl {
|
class AzoriusAEthermageAbility extends TriggeredAbilityImpl {
|
||||||
|
|
||||||
protected FilterPermanent filter;
|
private static final String rule = "Whenever a permanent is returned to your hand, ";
|
||||||
protected Zone fromZone;
|
|
||||||
protected Zone toZone;
|
|
||||||
protected String rule;
|
|
||||||
|
|
||||||
public AzoriusAEthermageAbility(Zone zone, Zone fromZone, Zone toZone, Effect effect, FilterPermanent filter, String rule, boolean optional) {
|
public AzoriusAEthermageAbility(Effect effect) {
|
||||||
super(zone, effect, optional);
|
super(Zone.BATTLEFIELD, effect, false);
|
||||||
this.fromZone = fromZone;
|
|
||||||
this.toZone = toZone;
|
|
||||||
this.rule = rule;
|
|
||||||
this.filter = filter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public AzoriusAEthermageAbility(final AzoriusAEthermageAbility ability) {
|
private AzoriusAEthermageAbility(final AzoriusAEthermageAbility ability) {
|
||||||
super(ability);
|
super(ability);
|
||||||
this.fromZone = ability.fromZone;
|
|
||||||
this.toZone = ability.toZone;
|
|
||||||
this.rule = ability.rule;
|
|
||||||
this.filter = ability.filter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -80,35 +67,29 @@ class AzoriusAEthermageAbility extends TriggeredAbilityImpl {
|
||||||
@Override
|
@Override
|
||||||
public boolean checkTrigger(GameEvent event, Game game) {
|
public boolean checkTrigger(GameEvent event, Game game) {
|
||||||
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
|
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
|
||||||
if ((fromZone == null || zEvent.getFromZone() == fromZone)
|
if (zEvent.getFromZone() != Zone.BATTLEFIELD || zEvent.getToZone() != Zone.HAND) {
|
||||||
&& (toZone == null || zEvent.getToZone() == toZone)) {
|
return false;
|
||||||
Permanent permanentThatMoved = null;
|
|
||||||
if (zEvent.getTarget() != null) {
|
|
||||||
permanentThatMoved = zEvent.getTarget();
|
|
||||||
}
|
|
||||||
//The controller's hand is where the permanent moved to.
|
|
||||||
return permanentThatMoved != null
|
|
||||||
&& filter.match(permanentThatMoved, sourceId, controllerId, game)
|
|
||||||
&& zEvent.getPlayerId().equals(controllerId);
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
|
if (!zEvent.getPlayerId().equals(controllerId)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Permanent permanentThatMoved = zEvent.getTarget();
|
||||||
|
if (permanentThatMoved == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return StaticFilters.FILTER_PERMANENT_CREATURE.match(permanentThatMoved, sourceId, controllerId, game);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getTriggerPhrase() {
|
public String getTriggerPhrase() {
|
||||||
return rule ;
|
return rule;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AzoriusAEthermageAbility copy() {
|
public AzoriusAEthermageAbility copy() {
|
||||||
return new AzoriusAEthermageAbility(this);
|
return new AzoriusAEthermageAbility(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Zone getFromZone() {
|
|
||||||
return fromZone;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Zone getToZone() {
|
|
||||||
return toZone;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,9 @@ public final class AzorsGateway extends CardImpl {
|
||||||
this.addSuperType(SuperType.LEGENDARY);
|
this.addSuperType(SuperType.LEGENDARY);
|
||||||
this.secondSideCardClazz = mage.cards.s.SanctumOfTheSun.class;
|
this.secondSideCardClazz = mage.cards.s.SanctumOfTheSun.class;
|
||||||
|
|
||||||
// {1}, {T}: Draw a card, then exile a card from your hand. If cards with five or more different converted mana costs are exiled with Azor's Gateway, you gain 5 life, untap Azor's Gateway, and transform it.
|
// {1}, {T}: Draw a card, then exile a card from your hand.
|
||||||
|
// If cards with five or more different converted mana costs are exiled with Azor's Gateway,
|
||||||
|
// you gain 5 life, untap Azor's Gateway, and transform it.
|
||||||
this.addAbility(new TransformAbility());
|
this.addAbility(new TransformAbility());
|
||||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new AzorsGatewayEffect(), new GenericManaCost(1));
|
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new AzorsGatewayEffect(), new GenericManaCost(1));
|
||||||
ability.addCost(new TapSourceCost());
|
ability.addCost(new TapSourceCost());
|
||||||
|
@ -59,7 +61,9 @@ class AzorsGatewayEffect extends OneShotEffect {
|
||||||
|
|
||||||
public AzorsGatewayEffect() {
|
public AzorsGatewayEffect() {
|
||||||
super(Outcome.Benefit);
|
super(Outcome.Benefit);
|
||||||
this.staticText = "Draw a card, then exile a card from your hand. If cards with five or more different mana values are exiled with {this}, you gain 5 life, untap Azor's Gateway, and transform it";
|
this.staticText = "Draw a card, then exile a card from your hand. " +
|
||||||
|
"If cards with five or more different mana values are exiled with {this}, " +
|
||||||
|
"you gain 5 life, untap Azor's Gateway, and transform it";
|
||||||
}
|
}
|
||||||
|
|
||||||
public AzorsGatewayEffect(final AzorsGatewayEffect effect) {
|
public AzorsGatewayEffect(final AzorsGatewayEffect effect) {
|
||||||
|
@ -74,30 +78,32 @@ class AzorsGatewayEffect extends OneShotEffect {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
UUID exileId = CardUtil.getCardExileZoneId(game, source);
|
if (controller == null) { return false; }
|
||||||
|
|
||||||
MageObject sourceObject = source.getSourceObject(game);
|
MageObject sourceObject = source.getSourceObject(game);
|
||||||
if (controller != null && exileId != null && sourceObject != null) {
|
if (sourceObject == null) { return false; }
|
||||||
controller.drawCards(1, source, game);
|
|
||||||
TargetCardInHand target = new TargetCardInHand();
|
UUID exileId = CardUtil.getCardExileZoneId(game, source);
|
||||||
controller.choose(outcome, target, source.getSourceId(), game);
|
|
||||||
Card cardToExile = game.getCard(target.getFirstTarget());
|
controller.drawCards(1, source, game);
|
||||||
if (cardToExile != null) {
|
TargetCardInHand target = new TargetCardInHand();
|
||||||
controller.moveCardsToExile(cardToExile, source, game, true, exileId, sourceObject.getIdName());
|
controller.choose(outcome, target, source.getSourceId(), game);
|
||||||
}
|
Card cardToExile = game.getCard(target.getFirstTarget());
|
||||||
Set<Integer> usedCMC = new HashSet<>();
|
if (cardToExile != null) {
|
||||||
ExileZone exileZone = game.getExile().getExileZone(exileId);
|
controller.moveCardsToExile(cardToExile, source, game, true, exileId, sourceObject.getIdName());
|
||||||
if (exileZone != null) {
|
|
||||||
for (Card card : exileZone.getCards(game)) {
|
|
||||||
usedCMC.add(card.getManaValue());
|
|
||||||
}
|
|
||||||
if (usedCMC.size() > 4) {
|
|
||||||
controller.gainLife(4, game, source);
|
|
||||||
new UntapSourceEffect().apply(game, source);
|
|
||||||
new TransformSourceEffect().apply(game, source);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
Set<Integer> usedCMC = new HashSet<>();
|
||||||
|
ExileZone exileZone = game.getExile().getExileZone(exileId);
|
||||||
|
if (exileZone != null) {
|
||||||
|
for (Card card : exileZone.getCards(game)) {
|
||||||
|
usedCMC.add(card.getManaValue());
|
||||||
|
}
|
||||||
|
if (usedCMC.size() > 4) {
|
||||||
|
controller.gainLife(4, game, source);
|
||||||
|
new UntapSourceEffect().apply(game, source);
|
||||||
|
new TransformSourceEffect().apply(game, source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -162,7 +162,7 @@ class BaneAlleyBrokerReturnToHandEffect extends OneShotEffect {
|
||||||
if (card == null) {
|
if (card == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return card != null && player.moveCards(card, Zone.HAND, source, game);
|
return player.moveCards(card, Zone.HAND, source, game);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@ public final class Banefire extends CardImpl {
|
||||||
// Banefire deals X damage to any target.
|
// Banefire deals X damage to any target.
|
||||||
this.getSpellAbility().addEffect(new BaneFireEffect());
|
this.getSpellAbility().addEffect(new BaneFireEffect());
|
||||||
this.getSpellAbility().addTarget(new TargetAnyTarget());
|
this.getSpellAbility().addTarget(new TargetAnyTarget());
|
||||||
|
|
||||||
// If X is 5 or more, Banefire can't be countered and the damage can't be prevented.
|
// If X is 5 or more, Banefire can't be countered and the damage can't be prevented.
|
||||||
this.addAbility(new SimpleStaticAbility(Zone.STACK, new BanefireCantCounterEffect()));
|
this.addAbility(new SimpleStaticAbility(Zone.STACK, new BanefireCantCounterEffect()));
|
||||||
}
|
}
|
||||||
|
@ -50,8 +51,8 @@ public final class Banefire extends CardImpl {
|
||||||
|
|
||||||
class testCondition implements Condition {
|
class testCondition implements Condition {
|
||||||
|
|
||||||
private DynamicValue xValue;
|
private final DynamicValue xValue;
|
||||||
private int limit;
|
private final int limit;
|
||||||
|
|
||||||
public testCondition(DynamicValue xValue, int limit) {
|
public testCondition(DynamicValue xValue, int limit) {
|
||||||
this.xValue = xValue;
|
this.xValue = xValue;
|
||||||
|
@ -105,7 +106,7 @@ class BaneFireEffect extends OneShotEffect {
|
||||||
|
|
||||||
class BanefireCantCounterEffect extends ContinuousRuleModifyingEffectImpl {
|
class BanefireCantCounterEffect extends ContinuousRuleModifyingEffectImpl {
|
||||||
|
|
||||||
Condition condition = new testCondition(ManacostVariableValue.REGULAR, 5);
|
private Condition condition = new testCondition(ManacostVariableValue.REGULAR, 5);
|
||||||
|
|
||||||
public BanefireCantCounterEffect() {
|
public BanefireCantCounterEffect() {
|
||||||
super(Duration.WhileOnStack, Outcome.Benefit);
|
super(Duration.WhileOnStack, Outcome.Benefit);
|
||||||
|
@ -129,18 +130,14 @@ class BanefireCantCounterEffect extends ContinuousRuleModifyingEffectImpl {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||||
if (event.getType() == GameEvent.EventType.COUNTER) {
|
if (event.getType() != GameEvent.EventType.COUNTER) { return false; }
|
||||||
Card card = game.getCard(source.getSourceId());
|
|
||||||
if (card != null) {
|
|
||||||
UUID spellId = card.getSpellAbility().getId();
|
|
||||||
if (event.getTargetId().equals(spellId)) {
|
|
||||||
if (condition.apply(game, source)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
Card card = game.getCard(source.getSourceId());
|
||||||
|
if (card == null) { return false; }
|
||||||
|
|
||||||
|
UUID spellId = card.getSpellAbility().getId();
|
||||||
|
if (!event.getTargetId().equals(spellId)) { return false; }
|
||||||
|
|
||||||
|
return condition.apply(game, source);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,10 +65,10 @@ class BathaHerdEffect extends OneShotEffect {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
if (controller != null) {
|
if (controller == null) { return false; }
|
||||||
int xValue = ((BecomesMonstrousSourceTriggeredAbility) source).getMonstrosityValue();
|
|
||||||
return new CreateTokenEffect(new TuskenRaiderToken(), xValue).apply(game, source);
|
int xValue = ((BecomesMonstrousSourceTriggeredAbility) source).getMonstrosityValue();
|
||||||
}
|
|
||||||
return false;
|
return new CreateTokenEffect(new TuskenRaiderToken(), xValue).apply(game, source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,34 +70,32 @@ class BatheInLightEffect extends OneShotEffect {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
if (controller != null) {
|
if (controller == null) { return false; }
|
||||||
Permanent target = game.getPermanent(getTargetPointer().getFirst(game, source));
|
|
||||||
if (target != null) {
|
|
||||||
ChoiceColor colorChoice = new ChoiceColor();
|
|
||||||
if (!controller.choose(Outcome.Benefit, colorChoice, game)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
game.informPlayers(target.getName() + ": " + controller.getLogName() + " has chosen " + colorChoice.getChoice());
|
|
||||||
game.getState().setValue(target.getId() + "_color", colorChoice.getColor());
|
|
||||||
|
|
||||||
ObjectColor protectColor = (ObjectColor) game.getState().getValue(target.getId() + "_color");
|
Permanent target = game.getPermanent(getTargetPointer().getFirst(game, source));
|
||||||
if (protectColor != null) {
|
if (target == null) { return false; }
|
||||||
ContinuousEffect effect = new ProtectionChosenColorTargetEffect();
|
|
||||||
game.addEffect(effect, source);
|
|
||||||
ObjectColor color = target.getColor(game);
|
|
||||||
for (Permanent permanent : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), source.getSourceId(), game)) {
|
|
||||||
if (!permanent.getId().equals(target.getId()) && permanent.getColor(game).shares(color)) {
|
|
||||||
game.getState().setValue(permanent.getId() + "_color", colorChoice.getColor());
|
|
||||||
effect.setTargetPointer(new FixedTarget(permanent, game));
|
|
||||||
game.addEffect(effect, source);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
ChoiceColor colorChoice = new ChoiceColor();
|
||||||
return true;
|
if (!controller.choose(Outcome.Benefit, colorChoice, game)) { return false; }
|
||||||
|
|
||||||
|
game.informPlayers(target.getName() + ": " + controller.getLogName() + " has chosen " + colorChoice.getChoice());
|
||||||
|
game.getState().setValue(target.getId() + "_color", colorChoice.getColor());
|
||||||
|
|
||||||
|
ObjectColor protectColor = (ObjectColor) game.getState().getValue(target.getId() + "_color");
|
||||||
|
if (protectColor == null) { return true; }
|
||||||
|
|
||||||
|
ContinuousEffect effect = new ProtectionChosenColorTargetEffect();
|
||||||
|
game.addEffect(effect, source);
|
||||||
|
ObjectColor color = target.getColor(game);
|
||||||
|
for (Permanent permanent : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), source.getSourceId(), game)) {
|
||||||
|
if (!permanent.getId().equals(target.getId()) && permanent.getColor(game).shares(color)) {
|
||||||
|
game.getState().setValue(permanent.getId() + "_color", colorChoice.getColor());
|
||||||
|
effect.setTargetPointer(new FixedTarget(permanent, game));
|
||||||
|
game.addEffect(effect, source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,19 +126,20 @@ class ProtectionChosenColorTargetEffect extends ContinuousEffectImpl {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
|
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
|
||||||
if (permanent != null) {
|
if (permanent == null) { return false; }
|
||||||
ObjectColor color = (ObjectColor) game.getState().getValue(permanent.getId() + "_color");
|
|
||||||
if (color != null && (protectionAbility == null || !color.equals(chosenColor))) {
|
ObjectColor color = (ObjectColor) game.getState().getValue(permanent.getId() + "_color");
|
||||||
chosenColor = color;
|
if (color != null && (protectionAbility == null || !color.equals(chosenColor))) {
|
||||||
FilterObject protectionFilter = new FilterObject(chosenColor.getDescription());
|
chosenColor = color;
|
||||||
protectionFilter.add(new ColorPredicate(chosenColor));
|
FilterObject protectionFilter = new FilterObject<>(chosenColor.getDescription());
|
||||||
protectionAbility = new ProtectionAbility(protectionFilter);
|
protectionFilter.add(new ColorPredicate(chosenColor));
|
||||||
}
|
protectionAbility = new ProtectionAbility(protectionFilter);
|
||||||
if (protectionAbility != null) {
|
|
||||||
permanent.addAbility(protectionAbility, source.getSourceId(), game);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (protectionAbility != null) {
|
||||||
|
permanent.addAbility(protectionAbility, source.getSourceId(), game);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,7 +66,7 @@ class BattlefieldThaumaturgeSpellsCostReductionEffect extends CostModificationEf
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source, Ability abilityToModify) {
|
public boolean apply(Game game, Ability source, Ability abilityToModify) {
|
||||||
int reduceAmount = 0;
|
int reduceAmount;
|
||||||
if (game.inCheckPlayableState()) {
|
if (game.inCheckPlayableState()) {
|
||||||
// checking state (search max possible targets)
|
// checking state (search max possible targets)
|
||||||
reduceAmount = getMaxPossibleTargetCreatures(abilityToModify, game);
|
reduceAmount = getMaxPossibleTargetCreatures(abilityToModify, game);
|
||||||
|
@ -117,7 +117,7 @@ class BattlefieldThaumaturgeSpellsCostReductionEffect extends CostModificationEf
|
||||||
&& abilityToModify.isControlledBy(source.getControllerId())) {
|
&& abilityToModify.isControlledBy(source.getControllerId())) {
|
||||||
Spell spell = (Spell) game.getStack().getStackObject(abilityToModify.getId());
|
Spell spell = (Spell) game.getStack().getStackObject(abilityToModify.getId());
|
||||||
if (spell != null) {
|
if (spell != null) {
|
||||||
return spell != null && StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY.match(spell, game);
|
return StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY.match(spell, game);
|
||||||
} else {
|
} else {
|
||||||
Card sourceCard = game.getCard(abilityToModify.getSourceId());
|
Card sourceCard = game.getCard(abilityToModify.getSourceId());
|
||||||
return sourceCard != null && StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY.match(sourceCard, game);
|
return sourceCard != null && StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY.match(sourceCard, game);
|
||||||
|
|
|
@ -24,15 +24,17 @@ public final class BehemothSledge extends CardImpl {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}{G}{W}");
|
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}{G}{W}");
|
||||||
this.subtype.add(SubType.EQUIPMENT);
|
this.subtype.add(SubType.EQUIPMENT);
|
||||||
|
|
||||||
|
// Equipped creature gets +2/+2 and has trample and lifelink.
|
||||||
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(2, 2));
|
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(2, 2));
|
||||||
ability.addEffect(new GainAbilityAttachedEffect(TrampleAbility.getInstance(), AttachmentType.EQUIPMENT).setText("and has trample"));
|
ability.addEffect(new GainAbilityAttachedEffect(TrampleAbility.getInstance(), AttachmentType.EQUIPMENT).setText("and has trample"));
|
||||||
ability.addEffect(new GainAbilityAttachedEffect(LifelinkAbility.getInstance(), AttachmentType.EQUIPMENT).setText("and lifelink"));
|
ability.addEffect(new GainAbilityAttachedEffect(LifelinkAbility.getInstance(), AttachmentType.EQUIPMENT).setText("and lifelink"));
|
||||||
this.addAbility(ability);
|
this.addAbility(ability);
|
||||||
|
|
||||||
|
// Equip {3}
|
||||||
this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(3)));
|
this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(3)));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected BehemothSledge(BehemothSledge me) {
|
private BehemothSledge(BehemothSledge me) {
|
||||||
super(me);
|
super(me);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,122 +64,123 @@ class BendOrBreakEffect extends OneShotEffect {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
if (controller != null) {
|
if (controller == null) { return false; }
|
||||||
|
|
||||||
// Map of players and their piles
|
// Map of players and their piles
|
||||||
Map<UUID, List<List<Permanent>>> playerPermanents = new LinkedHashMap<>();
|
Map<UUID, List<List<Permanent>>> playerPermanents = new LinkedHashMap<>();
|
||||||
|
|
||||||
PlayerList playerList = game.getState().getPlayerList().copy();
|
PlayerList playerList = game.getState().getPlayerList().copy();
|
||||||
while (!playerList.get().equals(source.getControllerId()) && controller.canRespond()) {
|
while (!playerList.get().equals(source.getControllerId()) && controller.canRespond()) {
|
||||||
playerList.getNext();
|
playerList.getNext();
|
||||||
}
|
|
||||||
Player currentPlayer = game.getPlayer(playerList.get());
|
|
||||||
Player nextPlayer;
|
|
||||||
UUID firstNextPlayer = null;
|
|
||||||
|
|
||||||
while (!getNextPlayerInDirection(true, playerList).equals(firstNextPlayer) && controller.canRespond()) {
|
|
||||||
nextPlayer = game.getPlayer(playerList.get());
|
|
||||||
if (nextPlayer == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (firstNextPlayer == null) {
|
|
||||||
firstNextPlayer = nextPlayer.getId();
|
|
||||||
}
|
|
||||||
if (!nextPlayer.canRespond()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// Each player separates all nontoken lands they control into two piles
|
|
||||||
if (currentPlayer != null && game.getState().getPlayersInRange(controller.getId(), game).contains(currentPlayer.getId())) {
|
|
||||||
List<Permanent> firstPile = new ArrayList<>();
|
|
||||||
List<Permanent> secondPile = new ArrayList<>();
|
|
||||||
FilterControlledLandPermanent filter = new FilterControlledLandPermanent("lands you control to assign to the first pile (lands not chosen will be assigned to the second pile)");
|
|
||||||
TargetPermanent target = new TargetControlledPermanent(0, Integer.MAX_VALUE, filter, true);
|
|
||||||
if (target.canChoose(source.getSourceId(), currentPlayer.getId(), game)) {
|
|
||||||
// TODO: add support for AI (50/50), need AI hints mechanic here
|
|
||||||
currentPlayer.chooseTarget(Outcome.Neutral, target, source, game);
|
|
||||||
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, currentPlayer.getId(), game)) {
|
|
||||||
if (target.getTargets().contains(permanent.getId())) {
|
|
||||||
firstPile.add(permanent);
|
|
||||||
} else {
|
|
||||||
secondPile.add(permanent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder("First pile of ").append(currentPlayer.getLogName()).append(": ");
|
|
||||||
sb.append(firstPile.stream().map(Permanent::getLogName).collect(Collectors.joining(", ")));
|
|
||||||
|
|
||||||
game.informPlayers(sb.toString());
|
|
||||||
|
|
||||||
sb = new StringBuilder("Second pile of ").append(currentPlayer.getLogName()).append(": ");
|
|
||||||
sb.append(secondPile.stream().map(Permanent::getLogName).collect(Collectors.joining(", ")));
|
|
||||||
|
|
||||||
game.informPlayers(sb.toString());
|
|
||||||
}
|
|
||||||
List<List<Permanent>> playerPiles = new ArrayList<>();
|
|
||||||
playerPiles.add(firstPile);
|
|
||||||
playerPiles.add(secondPile);
|
|
||||||
playerPermanents.put(currentPlayer.getId(), playerPiles);
|
|
||||||
}
|
|
||||||
currentPlayer = nextPlayer;
|
|
||||||
}
|
|
||||||
|
|
||||||
// For each player, one of their piles is chosen by one of their opponents of their choice
|
|
||||||
for (Map.Entry<UUID, List<List<Permanent>>> playerPiles : playerPermanents.entrySet()) {
|
|
||||||
Player player = game.getPlayer(playerPiles.getKey());
|
|
||||||
if (player != null) {
|
|
||||||
FilterPlayer filter = new FilterPlayer("opponent");
|
|
||||||
List<PlayerIdPredicate> opponentPredicates = new ArrayList<>();
|
|
||||||
for (UUID opponentId : game.getOpponents(player.getId())) {
|
|
||||||
opponentPredicates.add(new PlayerIdPredicate(opponentId));
|
|
||||||
}
|
|
||||||
filter.add(Predicates.or(opponentPredicates));
|
|
||||||
Target target = new TargetPlayer(1, 1, true, filter);
|
|
||||||
target.setTargetController(player.getId());
|
|
||||||
target.setAbilityController(source.getControllerId());
|
|
||||||
if (player.chooseTarget(outcome, target, source, game)) {
|
|
||||||
Player chosenOpponent = game.getPlayer(target.getFirstTarget());
|
|
||||||
if (chosenOpponent != null) {
|
|
||||||
List<Permanent> firstPile = playerPiles.getValue().get(0);
|
|
||||||
List<Permanent> secondPile = playerPiles.getValue().get(1);
|
|
||||||
game.informPlayers(player.getLogName() + " chose " + chosenOpponent.getLogName() + " to choose their pile");
|
|
||||||
if (chosenOpponent.choosePile(outcome, "Piles of " + player.getName(), firstPile, secondPile, game)) {
|
|
||||||
List<List<Permanent>> lists = playerPiles.getValue();
|
|
||||||
lists.clear();
|
|
||||||
lists.add(firstPile);
|
|
||||||
lists.add(secondPile);
|
|
||||||
game.informPlayers(player.getLogName() + " will have their first pile destroyed");
|
|
||||||
} else {
|
|
||||||
List<List<Permanent>> lists = playerPiles.getValue();
|
|
||||||
lists.clear();
|
|
||||||
lists.add(secondPile);
|
|
||||||
lists.add(firstPile);
|
|
||||||
game.informPlayers(player.getLogName() + " will have their second pile destroyed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Destroy all lands in the chosen piles. Tap all lands in the other piles
|
|
||||||
for (Map.Entry<UUID, List<List<Permanent>>> playerPiles : playerPermanents.entrySet()) {
|
|
||||||
Player player = game.getPlayer(playerPiles.getKey());
|
|
||||||
if (player != null) {
|
|
||||||
List<Permanent> pileToSac = playerPiles.getValue().get(0);
|
|
||||||
List<Permanent> pileToTap = playerPiles.getValue().get(1);
|
|
||||||
for (Permanent permanent : pileToSac) {
|
|
||||||
if (permanent != null) {
|
|
||||||
permanent.destroy(source, game, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (Permanent permanent : pileToTap) {
|
|
||||||
if (permanent != null) {
|
|
||||||
permanent.tap(source, game);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
Player currentPlayer = game.getPlayer(playerList.get());
|
||||||
|
Player nextPlayer;
|
||||||
|
UUID firstNextPlayer = null;
|
||||||
|
|
||||||
|
while (!getNextPlayerInDirection(true, playerList).equals(firstNextPlayer) && controller.canRespond()) {
|
||||||
|
nextPlayer = game.getPlayer(playerList.get());
|
||||||
|
if (nextPlayer == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (firstNextPlayer == null) {
|
||||||
|
firstNextPlayer = nextPlayer.getId();
|
||||||
|
}
|
||||||
|
if (!nextPlayer.canRespond()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Each player separates all nontoken lands they control into two piles
|
||||||
|
if (currentPlayer == null || !game.getState().getPlayersInRange(controller.getId(), game).contains(currentPlayer.getId())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
List<Permanent> firstPile = new ArrayList<>();
|
||||||
|
List<Permanent> secondPile = new ArrayList<>();
|
||||||
|
FilterControlledLandPermanent filter = new FilterControlledLandPermanent("lands you control to assign to the first pile (lands not chosen will be assigned to the second pile)");
|
||||||
|
TargetPermanent target = new TargetControlledPermanent(0, Integer.MAX_VALUE, filter, true);
|
||||||
|
if (!target.canChoose(source.getSourceId(), currentPlayer.getId(), game)) { continue; }
|
||||||
|
|
||||||
|
// TODO: add support for AI (50/50), need AI hints mechanic here
|
||||||
|
currentPlayer.chooseTarget(Outcome.Neutral, target, source, game);
|
||||||
|
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, currentPlayer.getId(), game)) {
|
||||||
|
if (target.getTargets().contains(permanent.getId())) {
|
||||||
|
firstPile.add(permanent);
|
||||||
|
} else {
|
||||||
|
secondPile.add(permanent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder("First pile of ").append(currentPlayer.getLogName()).append(": ");
|
||||||
|
sb.append(firstPile.stream().map(Permanent::getLogName).collect(Collectors.joining(", ")));
|
||||||
|
|
||||||
|
game.informPlayers(sb.toString());
|
||||||
|
|
||||||
|
sb = new StringBuilder("Second pile of ").append(currentPlayer.getLogName()).append(": ");
|
||||||
|
sb.append(secondPile.stream().map(Permanent::getLogName).collect(Collectors.joining(", ")));
|
||||||
|
|
||||||
|
game.informPlayers(sb.toString());
|
||||||
|
|
||||||
|
List<List<Permanent>> playerPiles = new ArrayList<>();
|
||||||
|
playerPiles.add(firstPile);
|
||||||
|
playerPiles.add(secondPile);
|
||||||
|
playerPermanents.put(currentPlayer.getId(), playerPiles);
|
||||||
|
|
||||||
|
currentPlayer = nextPlayer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For each player, one of their piles is chosen by one of their opponents of their choice
|
||||||
|
for (Map.Entry<UUID, List<List<Permanent>>> playerPiles : playerPermanents.entrySet()) {
|
||||||
|
Player player = game.getPlayer(playerPiles.getKey());
|
||||||
|
if (player == null) { continue; }
|
||||||
|
|
||||||
|
FilterPlayer filter = new FilterPlayer("opponent");
|
||||||
|
List<PlayerIdPredicate> opponentPredicates = new ArrayList<>();
|
||||||
|
for (UUID opponentId : game.getOpponents(player.getId())) {
|
||||||
|
opponentPredicates.add(new PlayerIdPredicate(opponentId));
|
||||||
|
}
|
||||||
|
filter.add(Predicates.or(opponentPredicates));
|
||||||
|
Target target = new TargetPlayer(1, 1, true, filter);
|
||||||
|
target.setTargetController(player.getId());
|
||||||
|
target.setAbilityController(source.getControllerId());
|
||||||
|
if (!player.chooseTarget(outcome, target, source, game)) { continue; }
|
||||||
|
|
||||||
|
Player chosenOpponent = game.getPlayer(target.getFirstTarget());
|
||||||
|
if (chosenOpponent == null) { continue; }
|
||||||
|
|
||||||
|
List<Permanent> firstPile = playerPiles.getValue().get(0);
|
||||||
|
List<Permanent> secondPile = playerPiles.getValue().get(1);
|
||||||
|
game.informPlayers(player.getLogName() + " chose " + chosenOpponent.getLogName() + " to choose their pile");
|
||||||
|
if (chosenOpponent.choosePile(outcome, "Piles of " + player.getName(), firstPile, secondPile, game)) {
|
||||||
|
List<List<Permanent>> lists = playerPiles.getValue();
|
||||||
|
lists.clear();
|
||||||
|
lists.add(firstPile);
|
||||||
|
lists.add(secondPile);
|
||||||
|
game.informPlayers(player.getLogName() + " will have their first pile destroyed");
|
||||||
|
} else {
|
||||||
|
List<List<Permanent>> lists = playerPiles.getValue();
|
||||||
|
lists.clear();
|
||||||
|
lists.add(secondPile);
|
||||||
|
lists.add(firstPile);
|
||||||
|
game.informPlayers(player.getLogName() + " will have their second pile destroyed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Destroy all lands in the chosen piles. Tap all lands in the other piles
|
||||||
|
for (Map.Entry<UUID, List<List<Permanent>>> playerPiles : playerPermanents.entrySet()) {
|
||||||
|
Player player = game.getPlayer(playerPiles.getKey());
|
||||||
|
if (player == null) { continue; }
|
||||||
|
|
||||||
|
List<Permanent> pileToSac = playerPiles.getValue().get(0);
|
||||||
|
List<Permanent> pileToTap = playerPiles.getValue().get(1);
|
||||||
|
for (Permanent permanent : pileToSac) {
|
||||||
|
if (permanent != null) {
|
||||||
|
permanent.destroy(source, game, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (Permanent permanent : pileToTap) {
|
||||||
|
if (permanent != null) {
|
||||||
|
permanent.tap(source, game);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private UUID getNextPlayerInDirection(boolean left, PlayerList playerList) {
|
private UUID getNextPlayerInDirection(boolean left, PlayerList playerList) {
|
||||||
|
|
|
@ -63,19 +63,18 @@ class BenevolentOfferingEffect1 extends OneShotEffect {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
if (controller != null) {
|
if (controller == null) { return false; }
|
||||||
Target target = new TargetOpponent(true);
|
|
||||||
target.choose(Outcome.Sacrifice, source.getControllerId(), source.getSourceId(), game);
|
Target target = new TargetOpponent(true);
|
||||||
Player opponent = game.getPlayer(target.getFirstTarget());
|
target.choose(Outcome.Sacrifice, source.getControllerId(), source.getSourceId(), game);
|
||||||
if (opponent != null) {
|
Player opponent = game.getPlayer(target.getFirstTarget());
|
||||||
Effect effect = new CreateTokenTargetEffect(new SpiritWhiteToken(), 3);
|
if (opponent == null) { return false; }
|
||||||
effect.setTargetPointer(new FixedTarget(opponent.getId()));
|
|
||||||
effect.apply(game, source);
|
Effect effect = new CreateTokenTargetEffect(new SpiritWhiteToken(), 3);
|
||||||
new CreateTokenEffect(new SpiritWhiteToken(), 3).apply(game, source);
|
effect.setTargetPointer(new FixedTarget(opponent.getId()));
|
||||||
return true;
|
effect.apply(game, source);
|
||||||
}
|
new CreateTokenEffect(new SpiritWhiteToken(), 3).apply(game, source);
|
||||||
}
|
return true;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,18 +97,18 @@ class BenevolentOfferingEffect2 extends OneShotEffect {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
if (controller != null) {
|
if (controller == null) { return false; }
|
||||||
Target target = new TargetOpponent(true);
|
|
||||||
target.choose(Outcome.Sacrifice, source.getControllerId(), source.getSourceId(), game);
|
Target target = new TargetOpponent(true);
|
||||||
Player opponent = game.getPlayer(target.getFirstTarget());
|
target.choose(Outcome.Sacrifice, source.getControllerId(), source.getSourceId(), game);
|
||||||
if (opponent != null) {
|
Player opponent = game.getPlayer(target.getFirstTarget());
|
||||||
int count = game.getBattlefield().countAll(StaticFilters.FILTER_PERMANENT_CREATURE, controller.getId(), game) * 2;
|
if (opponent == null) { return false; }
|
||||||
controller.gainLife(count, game, source);
|
|
||||||
count = game.getBattlefield().countAll(StaticFilters.FILTER_PERMANENT_CREATURE, opponent.getId(), game) * 2;
|
int count = game.getBattlefield().countAll(StaticFilters.FILTER_PERMANENT_CREATURE, controller.getId(), game) * 2;
|
||||||
opponent.gainLife(count, game, source);
|
controller.gainLife(count, game, source);
|
||||||
return true;
|
count = game.getBattlefield().countAll(StaticFilters.FILTER_PERMANENT_CREATURE, opponent.getId(), game) * 2;
|
||||||
}
|
opponent.gainLife(count, game, source);
|
||||||
}
|
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,7 +67,7 @@ public final class BenthicExplorers extends CardImpl {
|
||||||
|
|
||||||
class BenthicExplorersCost extends CostImpl {
|
class BenthicExplorersCost extends CostImpl {
|
||||||
|
|
||||||
TargetLandPermanent target;
|
private final TargetLandPermanent target;
|
||||||
|
|
||||||
public BenthicExplorersCost(TargetLandPermanent target) {
|
public BenthicExplorersCost(TargetLandPermanent target) {
|
||||||
this.target = target;
|
this.target = target;
|
||||||
|
@ -155,59 +155,60 @@ class BenthicExplorersManaEffect extends ManaEffect {
|
||||||
@Override
|
@Override
|
||||||
public Mana produceMana(Game game, Ability source) {
|
public Mana produceMana(Game game, Ability source) {
|
||||||
Mana mana = new Mana();
|
Mana mana = new Mana();
|
||||||
if (game == null) {
|
if (game == null) { return mana; }
|
||||||
return mana;
|
|
||||||
}
|
|
||||||
Choice choice = ManaType.getChoiceOfManaTypes(getManaTypes(game, source), false);
|
Choice choice = ManaType.getChoiceOfManaTypes(getManaTypes(game, source), false);
|
||||||
if (!choice.getChoices().isEmpty()) {
|
if (choice.getChoices().isEmpty()) { return mana; }
|
||||||
Player player = game.getPlayer(source.getControllerId());
|
|
||||||
if (choice.getChoices().size() == 1) {
|
Player player = game.getPlayer(source.getControllerId());
|
||||||
choice.setChoice(choice.getChoices().iterator().next());
|
if (choice.getChoices().size() == 1) {
|
||||||
} else {
|
choice.setChoice(choice.getChoices().iterator().next());
|
||||||
if (player == null
|
} else {
|
||||||
|| !player.choose(Outcome.Neutral, choice, game)) {
|
if (player == null
|
||||||
return mana;
|
|| !player.choose(Outcome.Neutral, choice, game)) {
|
||||||
}
|
return mana;
|
||||||
}
|
|
||||||
if (choice.getChoice() != null) {
|
|
||||||
switch (choice.getChoice()) {
|
|
||||||
case "Black":
|
|
||||||
mana.setBlack(1);
|
|
||||||
break;
|
|
||||||
case "Blue":
|
|
||||||
mana.setBlue(1);
|
|
||||||
break;
|
|
||||||
case "Red":
|
|
||||||
mana.setRed(1);
|
|
||||||
break;
|
|
||||||
case "Green":
|
|
||||||
mana.setGreen(1);
|
|
||||||
break;
|
|
||||||
case "White":
|
|
||||||
mana.setWhite(1);
|
|
||||||
break;
|
|
||||||
case "Colorless":
|
|
||||||
mana.setColorless(1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (choice.getChoice() == null) { return mana; }
|
||||||
|
|
||||||
|
switch (choice.getChoice()) {
|
||||||
|
case "Black":
|
||||||
|
mana.setBlack(1);
|
||||||
|
break;
|
||||||
|
case "Blue":
|
||||||
|
mana.setBlue(1);
|
||||||
|
break;
|
||||||
|
case "Red":
|
||||||
|
mana.setRed(1);
|
||||||
|
break;
|
||||||
|
case "Green":
|
||||||
|
mana.setGreen(1);
|
||||||
|
break;
|
||||||
|
case "White":
|
||||||
|
mana.setWhite(1);
|
||||||
|
break;
|
||||||
|
case "Colorless":
|
||||||
|
mana.setColorless(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return mana;
|
return mana;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Set<ManaType> getManaTypes(Game game, Ability source) {
|
private Set<ManaType> getManaTypes(Game game, Ability source) {
|
||||||
Set<ManaType> types = EnumSet.noneOf(ManaType.class);
|
Set<ManaType> types = EnumSet.noneOf(ManaType.class);
|
||||||
if (game == null
|
if (game == null || game.getPhase() == null) {
|
||||||
|| game.getPhase() == null) {
|
|
||||||
return types;
|
return types;
|
||||||
}
|
}
|
||||||
|
|
||||||
Permanent land = (Permanent) game.getState().getValue("UntapTargetCost" + source.getSourceId().toString());
|
Permanent land = (Permanent) game.getState().getValue("UntapTargetCost" + source.getSourceId().toString());
|
||||||
if (land != null) {
|
if (land == null) { return types; }
|
||||||
Abilities<ActivatedManaAbilityImpl> mana = land.getAbilities().getActivatedManaAbilities(Zone.BATTLEFIELD);
|
|
||||||
for (ActivatedManaAbilityImpl ability : mana) {
|
Abilities<ActivatedManaAbilityImpl> mana = land.getAbilities().getActivatedManaAbilities(Zone.BATTLEFIELD);
|
||||||
if (ability.definesMana(game)) {
|
for (ActivatedManaAbilityImpl ability : mana) {
|
||||||
types.addAll(ability.getProducableManaTypes(game));
|
if (ability.definesMana(game)) {
|
||||||
}
|
types.addAll(ability.getProducableManaTypes(game));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return types;
|
return types;
|
||||||
|
|
|
@ -127,15 +127,15 @@ class BerserkDestroyEffect extends OneShotEffect {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
if (controller != null) {
|
if (controller == null) { return false; }
|
||||||
//create delayed triggered ability
|
|
||||||
Effect effect = new BerserkDelayedDestroyEffect();
|
//create delayed triggered ability
|
||||||
effect.setTargetPointer(new FixedTarget(this.getTargetPointer().getFirst(game, source), game));
|
Effect effect = new BerserkDelayedDestroyEffect();
|
||||||
AtTheBeginOfNextEndStepDelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(effect);
|
effect.setTargetPointer(new FixedTarget(this.getTargetPointer().getFirst(game, source), game));
|
||||||
game.addDelayedTriggeredAbility(delayedAbility, source);
|
AtTheBeginOfNextEndStepDelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(effect);
|
||||||
return true;
|
game.addDelayedTriggeredAbility(delayedAbility, source);
|
||||||
}
|
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,15 +158,15 @@ class BerserkDelayedDestroyEffect extends OneShotEffect {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
if (controller != null) {
|
if (controller == null) { return false; }
|
||||||
Permanent permanent = game.getPermanent(this.getTargetPointer().getFirst(game, source));
|
|
||||||
if (permanent != null) {
|
Permanent permanent = game.getPermanent(this.getTargetPointer().getFirst(game, source));
|
||||||
AttackedThisTurnWatcher watcher = game.getState().getWatcher(AttackedThisTurnWatcher.class);
|
if (permanent == null) { return false; }
|
||||||
if (watcher.getAttackedThisTurnCreatures().contains(new MageObjectReference(permanent, game))) {
|
|
||||||
return permanent.destroy(source, game, false);
|
AttackedThisTurnWatcher watcher = game.getState().getWatcher(AttackedThisTurnWatcher.class);
|
||||||
}
|
if (watcher == null) { return false; }
|
||||||
}
|
|
||||||
}
|
return watcher.getAttackedThisTurnCreatures().contains(new MageObjectReference(permanent, game))
|
||||||
return false;
|
&& permanent.destroy(source, game, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,6 @@ public final class BiomanticMastery extends CardImpl {
|
||||||
// Draw a card for each creature target player controls, then draw a card for each creature another target player controls.
|
// Draw a card for each creature target player controls, then draw a card for each creature another target player controls.
|
||||||
this.getSpellAbility().addEffect(new BiomanticMasteryEffect());
|
this.getSpellAbility().addEffect(new BiomanticMasteryEffect());
|
||||||
this.getSpellAbility().addTarget(new TargetPlayer(2));
|
this.getSpellAbility().addTarget(new TargetPlayer(2));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private BiomanticMastery(final BiomanticMastery card) {
|
private BiomanticMastery(final BiomanticMastery card) {
|
||||||
|
@ -58,16 +57,15 @@ class BiomanticMasteryEffect extends OneShotEffect {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
if (controller != null) {
|
if (controller == null) { return false; }
|
||||||
for (UUID playerId : getTargetPointer().getTargets(game, source)) {
|
|
||||||
Player player = game.getPlayer(playerId);
|
for (UUID playerId : getTargetPointer().getTargets(game, source)) {
|
||||||
if (player != null) {
|
Player player = game.getPlayer(playerId);
|
||||||
int creatures = game.getBattlefield().countAll(StaticFilters.FILTER_PERMANENT_CREATURE, playerId, game);
|
if (player == null) { continue; }
|
||||||
controller.drawCards(creatures, source, game);
|
|
||||||
}
|
int creatures = game.getBattlefield().countAll(StaticFilters.FILTER_PERMANENT_CREATURE, playerId, game);
|
||||||
}
|
controller.drawCards(creatures, source, game);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,23 +63,27 @@ class BitterFeudEntersBattlefieldEffect extends OneShotEffect {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
|
if (controller == null) { return false; }
|
||||||
|
|
||||||
Permanent permanent = game.getPermanentEntering(source.getSourceId());
|
Permanent permanent = game.getPermanentEntering(source.getSourceId());
|
||||||
if (controller != null && permanent != null) {
|
if (permanent == null) { return false; }
|
||||||
TargetPlayer target = new TargetPlayer(2, 2, true);
|
|
||||||
controller.chooseTarget(outcome, target, source, game);
|
TargetPlayer target = new TargetPlayer(2, 2, true);
|
||||||
Player player1 = game.getPlayer(target.getFirstTarget());
|
controller.chooseTarget(outcome, target, source, game);
|
||||||
if (target.getTargets().size() > 1) {
|
Player player1 = game.getPlayer(target.getFirstTarget());
|
||||||
Player player2 = game.getPlayer(target.getTargets().get(1));
|
if (player1 == null) { return false; }
|
||||||
if (player1 != null && player2 != null) {
|
|
||||||
game.getState().setValue(source.getSourceId() + "_player1", player1);
|
if (target.getTargets().size() <= 1) { return false; }
|
||||||
game.getState().setValue(source.getSourceId() + "_player2", player2);
|
|
||||||
game.informPlayers(permanent.getLogName() + ": " + controller.getLogName() + " has chosen " + player1.getLogName() + " and " + player2.getLogName());
|
Player player2 = game.getPlayer(target.getTargets().get(1));
|
||||||
permanent.addInfo("chosen players", "<font color = 'blue'>Chosen players: " + player1.getName() + ", " + player2.getName() + "</font>", game);
|
if (player2 == null) { return false; }
|
||||||
return true;
|
|
||||||
}
|
game.getState().setValue(source.getSourceId() + "_player1", player1);
|
||||||
}
|
game.getState().setValue(source.getSourceId() + "_player2", player2);
|
||||||
}
|
game.informPlayers(permanent.getLogName() + ": " + controller.getLogName() + " has chosen " + player1.getLogName() + " and " + player2.getLogName());
|
||||||
return false;
|
permanent.addInfo("chosen players", "<font color = 'blue'>Chosen players: " + player1.getName() + ", " + player2.getName() + "</font>", game);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -91,8 +95,8 @@ class BitterFeudEntersBattlefieldEffect extends OneShotEffect {
|
||||||
|
|
||||||
class BitterFeudEffect extends ReplacementEffectImpl {
|
class BitterFeudEffect extends ReplacementEffectImpl {
|
||||||
|
|
||||||
Player player1;
|
private Player player1;
|
||||||
Player player2;
|
private Player player2;
|
||||||
|
|
||||||
public BitterFeudEffect() {
|
public BitterFeudEffect() {
|
||||||
super(Duration.WhileOnBattlefield, Outcome.Damage);
|
super(Duration.WhileOnBattlefield, Outcome.Damage);
|
||||||
|
@ -101,6 +105,8 @@ class BitterFeudEffect extends ReplacementEffectImpl {
|
||||||
|
|
||||||
public BitterFeudEffect(final BitterFeudEffect effect) {
|
public BitterFeudEffect(final BitterFeudEffect effect) {
|
||||||
super(effect);
|
super(effect);
|
||||||
|
this.player1 = effect.player1;
|
||||||
|
this.player2 = effect.player2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -110,54 +116,50 @@ class BitterFeudEffect extends ReplacementEffectImpl {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean checksEventType(GameEvent event, Game game) {
|
public boolean checksEventType(GameEvent event, Game game) {
|
||||||
switch (event.getType()) {
|
return event.getType() == GameEvent.EventType.DAMAGE_PERMANENT && event.getType() == GameEvent.EventType.DAMAGE_PLAYER;
|
||||||
case DAMAGE_PERMANENT:
|
|
||||||
case DAMAGE_PLAYER:
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||||
player1 = (Player) game.getState().getValue(source.getSourceId() + "_player1");
|
player1 = (Player) game.getState().getValue(source.getSourceId() + "_player1");
|
||||||
player2 = (Player) game.getState().getValue(source.getSourceId() + "_player2");
|
if (player1 == null) { return false; }
|
||||||
if (player1 != null && player2 != null) {
|
|
||||||
UUID targetPlayerId = null;
|
|
||||||
switch (event.getType()) {
|
|
||||||
case DAMAGE_PLAYER:
|
|
||||||
targetPlayerId = event.getTargetId();
|
|
||||||
break;
|
|
||||||
case DAMAGE_PERMANENT:
|
|
||||||
Permanent permanent = game.getPermanent(event.getTargetId());
|
|
||||||
if (permanent != null) {
|
|
||||||
targetPlayerId = permanent.getControllerId();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (player1.getId().equals(targetPlayerId) || player2.getId().equals(targetPlayerId)) {
|
player2 = (Player) game.getState().getValue(source.getSourceId() + "_player2");
|
||||||
UUID sourcePlayerId = null;
|
if (player2 == null) { return false; }
|
||||||
MageObject damageSource = game.getObject(event.getSourceId());
|
|
||||||
if (damageSource instanceof StackObject) {
|
UUID targetPlayerId;
|
||||||
sourcePlayerId = ((StackObject) damageSource).getControllerId();
|
switch (event.getType()) {
|
||||||
} else if (damageSource instanceof Permanent) {
|
case DAMAGE_PLAYER:
|
||||||
sourcePlayerId = ((Permanent) damageSource).getControllerId();
|
targetPlayerId = event.getTargetId();
|
||||||
} else if (damageSource instanceof Card) {
|
break;
|
||||||
sourcePlayerId = ((Card) damageSource).getOwnerId();
|
case DAMAGE_PERMANENT:
|
||||||
}
|
Permanent permanent = game.getPermanent(event.getTargetId());
|
||||||
if (sourcePlayerId != null
|
if (permanent == null) { return false; }
|
||||||
&& (player1.getId().equals(sourcePlayerId) || player2.getId().equals(sourcePlayerId))
|
|
||||||
&& !sourcePlayerId.equals(targetPlayerId)) {
|
targetPlayerId = permanent.getControllerId();
|
||||||
return true;
|
break;
|
||||||
}
|
default:
|
||||||
}
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
if (!player1.getId().equals(targetPlayerId) && !player2.getId().equals(targetPlayerId)) { return false; }
|
||||||
|
|
||||||
|
UUID sourcePlayerId;
|
||||||
|
MageObject damageSource = game.getObject(event.getSourceId());
|
||||||
|
|
||||||
|
if (damageSource instanceof StackObject) {
|
||||||
|
sourcePlayerId = ((StackObject) damageSource).getControllerId();
|
||||||
|
} else if (damageSource instanceof Permanent) {
|
||||||
|
sourcePlayerId = ((Permanent) damageSource).getControllerId();
|
||||||
|
} else if (damageSource instanceof Card) {
|
||||||
|
sourcePlayerId = ((Card) damageSource).getOwnerId();
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sourcePlayerId != null
|
||||||
|
&& (player1.getId().equals(sourcePlayerId) || player2.getId().equals(sourcePlayerId))
|
||||||
|
&& !sourcePlayerId.equals(targetPlayerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -57,12 +57,12 @@ class BlasphemousCostReductionEffect extends CostModificationEffectImpl {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source, Ability abilityToModify) {
|
public boolean apply(Game game, Ability source, Ability abilityToModify) {
|
||||||
Player player = game.getPlayer(source.getControllerId());
|
Player player = game.getPlayer(source.getControllerId());
|
||||||
if (player != null) {
|
if (player == null) { return false; }
|
||||||
int reductionAmount = game.getBattlefield().count(StaticFilters.FILTER_PERMANENT_CREATURE, source.getSourceId(), source.getControllerId(), game);
|
|
||||||
CardUtil.reduceCost(abilityToModify, reductionAmount);
|
int reductionAmount = game.getBattlefield().count(StaticFilters.FILTER_PERMANENT_CREATURE, source.getSourceId(), source.getControllerId(), game);
|
||||||
return true;
|
CardUtil.reduceCost(abilityToModify, reductionAmount);
|
||||||
}
|
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -89,15 +89,16 @@ class BlazingEffigyWatcher extends Watcher {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void watch(GameEvent event, Game game) {
|
public void watch(GameEvent event, Game game) {
|
||||||
if (event.getType() == GameEvent.EventType.DAMAGED_PERMANENT) {
|
if (event.getType() != GameEvent.EventType.DAMAGED_PERMANENT) { return; }
|
||||||
if (!event.getSourceId().equals(event.getTargetId())) {
|
|
||||||
MageObjectReference damageSourceRef = new MageObjectReference(event.getSourceId(), game);
|
if (event.getSourceId().equals(event.getTargetId())) { return; }
|
||||||
MageObjectReference damageTargetRef = new MageObjectReference(event.getTargetId(), game);
|
|
||||||
if (game.getPermanentOrLKIBattlefield(event.getSourceId()) != null && game.getPermanentOrLKIBattlefield(event.getSourceId()).getName().equals("Blazing Effigy")) {
|
// TODO: Should damageSourceRef be used for anything?
|
||||||
damagedObjects.putIfAbsent(damageTargetRef, 0);
|
MageObjectReference damageSourceRef = new MageObjectReference(event.getSourceId(), game);
|
||||||
damagedObjects.compute(damageTargetRef, (k, damage) -> damage + event.getAmount());
|
MageObjectReference damageTargetRef = new MageObjectReference(event.getTargetId(), game);
|
||||||
}
|
if (game.getPermanentOrLKIBattlefield(event.getSourceId()) != null && game.getPermanentOrLKIBattlefield(event.getSourceId()).getName().equals("Blazing Effigy")) {
|
||||||
}
|
damagedObjects.putIfAbsent(damageTargetRef, 0);
|
||||||
|
damagedObjects.compute(damageTargetRef, (k, damage) -> damage + event.getAmount());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,9 +23,9 @@ public final class BlinkmothInfusion extends CardImpl {
|
||||||
public BlinkmothInfusion(UUID ownerId, CardSetInfo setInfo) {
|
public BlinkmothInfusion(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{12}{U}{U}");
|
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{12}{U}{U}");
|
||||||
|
|
||||||
|
|
||||||
// Affinity for artifacts
|
// Affinity for artifacts
|
||||||
this.addAbility(new AffinityForArtifactsAbility());
|
this.addAbility(new AffinityForArtifactsAbility());
|
||||||
|
|
||||||
// Untap all artifacts.
|
// Untap all artifacts.
|
||||||
this.getSpellAbility().addEffect(new UntapAllArtifactsEffect());
|
this.getSpellAbility().addEffect(new UntapAllArtifactsEffect());
|
||||||
}
|
}
|
||||||
|
@ -54,13 +54,12 @@ class UntapAllArtifactsEffect extends OneShotEffect {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Player player = game.getPlayer(source.getControllerId());
|
Player player = game.getPlayer(source.getControllerId());
|
||||||
if (player != null) {
|
if (player == null) { return false; }
|
||||||
for (Permanent artifact: game.getBattlefield().getAllActivePermanents(new FilterArtifactPermanent(), game)) {
|
|
||||||
artifact.untap(game);
|
for (Permanent artifact: game.getBattlefield().getAllActivePermanents(new FilterArtifactPermanent(), game)) {
|
||||||
}
|
artifact.untap(game);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -32,7 +32,6 @@ public final class BloodBaronOfVizkopa extends CardImpl {
|
||||||
|
|
||||||
// As long as you have 30 or more life and an opponent has 10 or less life, Blood Baron of Vizkopa gets +6/+6 and has flying.
|
// As long as you have 30 or more life and an opponent has 10 or less life, Blood Baron of Vizkopa gets +6/+6 and has flying.
|
||||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BloodBaronOfVizkopaEffect()));
|
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BloodBaronOfVizkopaEffect()));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private BloodBaronOfVizkopa(final BloodBaronOfVizkopa card) {
|
private BloodBaronOfVizkopa(final BloodBaronOfVizkopa card) {
|
||||||
|
@ -53,7 +52,7 @@ class BloodBaronOfVizkopaEffect extends ContinuousEffectImpl {
|
||||||
staticText = "As long as you have 30 or more life and an opponent has 10 or less life, {this} gets +6/+6 and has flying";
|
staticText = "As long as you have 30 or more life and an opponent has 10 or less life, {this} gets +6/+6 and has flying";
|
||||||
}
|
}
|
||||||
|
|
||||||
public BloodBaronOfVizkopaEffect(final BloodBaronOfVizkopaEffect effect) {
|
private BloodBaronOfVizkopaEffect(final BloodBaronOfVizkopaEffect effect) {
|
||||||
super(effect);
|
super(effect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,41 +63,45 @@ class BloodBaronOfVizkopaEffect extends ContinuousEffectImpl {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
|
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
|
||||||
if (conditionState(source, game)) {
|
if (!conditionState(source, game)) { return false; }
|
||||||
Permanent creature = game.getPermanent(source.getSourceId());
|
|
||||||
if (creature != null) {
|
Permanent creature = game.getPermanent(source.getSourceId());
|
||||||
switch (layer) {
|
if (creature == null) { return false; }
|
||||||
case PTChangingEffects_7:
|
|
||||||
if (sublayer == SubLayer.ModifyPT_7c) {
|
switch (layer) {
|
||||||
creature.addPower(6);
|
case PTChangingEffects_7:
|
||||||
creature.addToughness(6);
|
if (sublayer == SubLayer.ModifyPT_7c) {
|
||||||
}
|
creature.addPower(6);
|
||||||
break;
|
creature.addToughness(6);
|
||||||
case AbilityAddingRemovingEffects_6:
|
|
||||||
if (sublayer == SubLayer.NA) {
|
|
||||||
creature.addAbility(FlyingAbility.getInstance(), source.getSourceId(), game);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
}
|
}
|
||||||
return true;
|
break;
|
||||||
}
|
case AbilityAddingRemovingEffects_6:
|
||||||
|
if (sublayer == SubLayer.NA) {
|
||||||
|
creature.addAbility(FlyingAbility.getInstance(), source.getSourceId(), game);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean conditionState(Ability source, Game game) {
|
private boolean conditionState(Ability source, Game game) {
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
if (controller != null && controller.getLife() >= 30) {
|
if (controller == null) { return false; }
|
||||||
for (UUID opponentId : game.getState().getPlayersInRange(controller.getId(), game)) {
|
|
||||||
if (controller.hasOpponent(opponentId, game)) {
|
if (controller.getLife() < 30) { return false; }
|
||||||
Player opponent = game.getPlayer(opponentId);
|
|
||||||
if (opponent != null && opponent.getLife() < 11) {
|
for (UUID opponentId : game.getState().getPlayersInRange(controller.getId(), game)) {
|
||||||
return true;
|
if (!controller.hasOpponent(opponentId, game)) { return false; }
|
||||||
}
|
|
||||||
}
|
Player opponent = game.getPlayer(opponentId);
|
||||||
}
|
if (opponent == null) { return false; }
|
||||||
|
|
||||||
|
return opponent.getLife() < 11;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,8 +112,6 @@ class BloodBaronOfVizkopaEffect extends ContinuousEffectImpl {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasLayer(Layer layer) {
|
public boolean hasLayer(Layer layer) {
|
||||||
return (layer == Layer.AbilityAddingRemovingEffects_6 || layer == layer.PTChangingEffects_7);
|
return (layer == Layer.AbilityAddingRemovingEffects_6 || layer == Layer.PTChangingEffects_7);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,31 +67,34 @@ class BloodlineShamanEffect extends OneShotEffect {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
|
if (controller == null) { return false; }
|
||||||
|
|
||||||
MageObject sourceObject = game.getObject(source.getSourceId());
|
MageObject sourceObject = game.getObject(source.getSourceId());
|
||||||
|
if (sourceObject == null) { return false; }
|
||||||
|
|
||||||
Choice typeChoice = new ChoiceCreatureType(sourceObject);
|
Choice typeChoice = new ChoiceCreatureType(sourceObject);
|
||||||
if (controller != null && sourceObject != null && controller.choose(outcome, typeChoice, game)) {
|
if (!controller.choose(outcome, typeChoice, game)) { return false; }
|
||||||
game.informPlayers(sourceObject.getLogName() + " chosen type: " + typeChoice.getChoice());
|
|
||||||
FilterCard filterSubtype = new FilterCard();
|
|
||||||
filterSubtype.add(SubType.byDescription(typeChoice.getChoice()).getPredicate());
|
|
||||||
|
|
||||||
// Reveal the top card of your library.
|
game.informPlayers(sourceObject.getLogName() + " chosen type: " + typeChoice.getChoice());
|
||||||
if (controller.getLibrary().hasCards()) {
|
FilterCard filterSubtype = new FilterCard();
|
||||||
Card card = controller.getLibrary().getFromTop(game);
|
filterSubtype.add(SubType.byDescription(typeChoice.getChoice()).getPredicate());
|
||||||
Cards cards = new CardsImpl(card);
|
|
||||||
controller.revealCards(sourceObject.getIdName(), cards, game);
|
|
||||||
|
|
||||||
if (card != null) {
|
// Reveal the top card of your library.
|
||||||
// If that card is a creature card of the chosen type, put it into your hand.
|
if (controller.getLibrary().hasCards()) {
|
||||||
if (filterSubtype.match(card, game)) {
|
Card card = controller.getLibrary().getFromTop(game);
|
||||||
controller.moveCards(card, Zone.HAND, source, game);
|
Cards cards = new CardsImpl(card);
|
||||||
// Otherwise, put it into your graveyard.
|
controller.revealCards(sourceObject.getIdName(), cards, game);
|
||||||
} else {
|
|
||||||
controller.moveCards(card, Zone.GRAVEYARD, source, game);
|
if (card != null) {
|
||||||
}
|
// If that card is a creature card of the chosen type, put it into your hand.
|
||||||
|
if (filterSubtype.match(card, game)) {
|
||||||
|
controller.moveCards(card, Zone.HAND, source, game);
|
||||||
|
// Otherwise, put it into your graveyard.
|
||||||
|
} else {
|
||||||
|
controller.moveCards(card, Zone.GRAVEYARD, source, game);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,8 +30,7 @@ public final class Blustersquall extends CardImpl {
|
||||||
this.getSpellAbility().addEffect(new TapTargetEffect());
|
this.getSpellAbility().addEffect(new TapTargetEffect());
|
||||||
|
|
||||||
// Overload {3}{U} (You may cast this spell for its overload cost. If you do, change its text by replacing all instances of "target" with "each.")
|
// Overload {3}{U} (You may cast this spell for its overload cost. If you do, change its text by replacing all instances of "target" with "each.")
|
||||||
this.addAbility(new OverloadAbility(this, new BlustersqallTapAllEffect(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL), new ManaCostsImpl("{3}{U}")));
|
this.addAbility(new OverloadAbility(this, new BlustersqallTapAllEffect(), new ManaCostsImpl("{3}{U}")));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Blustersquall(final Blustersquall card) {
|
private Blustersquall(final Blustersquall card) {
|
||||||
|
@ -46,22 +45,18 @@ public final class Blustersquall extends CardImpl {
|
||||||
|
|
||||||
class BlustersqallTapAllEffect extends OneShotEffect {
|
class BlustersqallTapAllEffect extends OneShotEffect {
|
||||||
|
|
||||||
protected FilterCreaturePermanent filter;
|
BlustersqallTapAllEffect() {
|
||||||
|
|
||||||
BlustersqallTapAllEffect(FilterCreaturePermanent filter) {
|
|
||||||
super(Outcome.Tap);
|
super(Outcome.Tap);
|
||||||
this.filter = filter;
|
|
||||||
staticText = "Tap each creature you don't control";
|
staticText = "Tap each creature you don't control";
|
||||||
}
|
}
|
||||||
|
|
||||||
private BlustersqallTapAllEffect(final BlustersqallTapAllEffect effect) {
|
private BlustersqallTapAllEffect(final BlustersqallTapAllEffect effect) {
|
||||||
super(effect);
|
super(effect);
|
||||||
this.filter = effect.filter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
for (Permanent creature : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) {
|
for (Permanent creature : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL, source.getControllerId(), source.getSourceId(), game)) {
|
||||||
creature.tap(source, game);
|
creature.tap(source, game);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -64,7 +64,7 @@ public final class BoneyardScourge extends CardImpl {
|
||||||
|
|
||||||
class DiesWhileInGraveyardTriggeredAbility extends TriggeredAbilityImpl {
|
class DiesWhileInGraveyardTriggeredAbility extends TriggeredAbilityImpl {
|
||||||
|
|
||||||
protected FilterCreaturePermanent filter;
|
private final FilterCreaturePermanent filter;
|
||||||
|
|
||||||
public DiesWhileInGraveyardTriggeredAbility(Effect effect, FilterCreaturePermanent filter) {
|
public DiesWhileInGraveyardTriggeredAbility(Effect effect, FilterCreaturePermanent filter) {
|
||||||
super(Zone.GRAVEYARD, effect, false);
|
super(Zone.GRAVEYARD, effect, false);
|
||||||
|
@ -89,22 +89,19 @@ class DiesWhileInGraveyardTriggeredAbility extends TriggeredAbilityImpl {
|
||||||
@Override
|
@Override
|
||||||
public boolean checkTrigger(GameEvent event, Game game) {
|
public boolean checkTrigger(GameEvent event, Game game) {
|
||||||
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
|
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
|
||||||
|
if (!zEvent.isDiesEvent()) { return false; }
|
||||||
|
|
||||||
for (Zone z : Zone.values()) {
|
for (Zone z : Zone.values()) {
|
||||||
if (game.getShortLivingLKI(sourceId, z) && z != Zone.GRAVEYARD) {
|
if (game.getShortLivingLKI(sourceId, z) && z != Zone.GRAVEYARD) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (zEvent.isDiesEvent()) {
|
|
||||||
if (filter.match(zEvent.getTarget(), sourceId, controllerId, game)) {
|
return filter.match(zEvent.getTarget(), sourceId, controllerId, game);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getTriggerPhrase() {
|
public String getTriggerPhrase() {
|
||||||
return "Whenever " + filter.getMessage() + " dies while {this} is in your graveyard, " ;
|
return "Whenever " + filter.getMessage() + " dies while {this} is in your graveyard, " ;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,8 @@ class BoonweaverGiantEffect extends OneShotEffect {
|
||||||
|
|
||||||
public BoonweaverGiantEffect() {
|
public BoonweaverGiantEffect() {
|
||||||
super(Outcome.UnboostCreature);
|
super(Outcome.UnboostCreature);
|
||||||
this.staticText = "you may search your graveyard, hand, and/or library for an Aura card and put it onto the battlefield attached to {this}. If you search your library this way, shuffle.";
|
this.staticText = "you may search your graveyard, hand, and/or library for an Aura card and put it onto the battlefield attached to {this}." +
|
||||||
|
"If you search your library this way, shuffle.";
|
||||||
}
|
}
|
||||||
|
|
||||||
public BoonweaverGiantEffect(final BoonweaverGiantEffect effect) {
|
public BoonweaverGiantEffect(final BoonweaverGiantEffect effect) {
|
||||||
|
@ -69,45 +70,40 @@ class BoonweaverGiantEffect extends OneShotEffect {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
if (controller == null) {
|
if (controller == null) { return false; }
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
FilterCard filter = new FilterCard("Aura card");
|
FilterCard filter = new FilterCard("Aura card");
|
||||||
filter.add(CardType.ENCHANTMENT.getPredicate());
|
filter.add(CardType.ENCHANTMENT.getPredicate());
|
||||||
filter.add(SubType.AURA.getPredicate());
|
filter.add(SubType.AURA.getPredicate());
|
||||||
|
|
||||||
Card card = null;
|
Card card = null;
|
||||||
Zone zone = null;
|
|
||||||
|
// Choose card from graveyard
|
||||||
if (controller.chooseUse(Outcome.Neutral, "Search your graveyard for an Aura card?", source, game)) {
|
if (controller.chooseUse(Outcome.Neutral, "Search your graveyard for an Aura card?", source, game)) {
|
||||||
TargetCardInYourGraveyard target = new TargetCardInYourGraveyard(filter);
|
TargetCardInYourGraveyard target = new TargetCardInYourGraveyard(filter);
|
||||||
if (controller.choose(Outcome.PutCardInPlay, controller.getGraveyard(), target, game)) {
|
if (controller.choose(Outcome.PutCardInPlay, controller.getGraveyard(), target, game)) {
|
||||||
card = game.getCard(target.getFirstTarget());
|
card = game.getCard(target.getFirstTarget());
|
||||||
if (card != null) {
|
|
||||||
zone = Zone.GRAVEYARD;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Choose card from your hand
|
||||||
if (card == null && controller.chooseUse(Outcome.Neutral, "Search your Hand for an Aura card?", source, game)) {
|
if (card == null && controller.chooseUse(Outcome.Neutral, "Search your Hand for an Aura card?", source, game)) {
|
||||||
TargetCardInHand target = new TargetCardInHand(filter);
|
TargetCardInHand target = new TargetCardInHand(filter);
|
||||||
if (controller.choose(Outcome.PutCardInPlay, controller.getHand(), target, game)) {
|
if (controller.choose(Outcome.PutCardInPlay, controller.getHand(), target, game)) {
|
||||||
card = game.getCard(target.getFirstTarget());
|
card = game.getCard(target.getFirstTarget());
|
||||||
if (card != null) {
|
|
||||||
zone = Zone.HAND;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Choose a card from your library
|
||||||
if (card == null) {
|
if (card == null) {
|
||||||
TargetCardInLibrary target = new TargetCardInLibrary(filter);
|
TargetCardInLibrary target = new TargetCardInLibrary(filter);
|
||||||
if (controller.searchLibrary(target, source, game)) {
|
if (controller.searchLibrary(target, source, game)) {
|
||||||
card = game.getCard(target.getFirstTarget());
|
card = game.getCard(target.getFirstTarget());
|
||||||
if (card != null) {
|
|
||||||
zone = Zone.LIBRARY;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
controller.shuffleLibrary(source, game);
|
controller.shuffleLibrary(source, game);
|
||||||
}
|
}
|
||||||
// aura card found - attach it
|
|
||||||
|
// Aura card found - attach it
|
||||||
if (card != null) {
|
if (card != null) {
|
||||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||||
if (permanent != null) {
|
if (permanent != null) {
|
||||||
|
|
|
@ -109,13 +109,13 @@ class BosiumStripReplacementEffect extends ReplacementEffectImpl {
|
||||||
@Override
|
@Override
|
||||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
if (controller != null) {
|
if (controller == null) { return false; }
|
||||||
Card card = (Card) game.getState().getValue("BosiumStrip");
|
|
||||||
if (card != null) {
|
Card card = (Card) game.getState().getValue("BosiumStrip");
|
||||||
((ZoneChangeEvent) event).setToZone(Zone.EXILED);
|
if (card == null) { return false; }
|
||||||
}
|
|
||||||
}
|
((ZoneChangeEvent) event).setToZone(Zone.EXILED);
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -126,16 +126,16 @@ class BosiumStripReplacementEffect extends ReplacementEffectImpl {
|
||||||
@Override
|
@Override
|
||||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||||
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
|
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
|
||||||
if (zEvent.getToZone() == Zone.GRAVEYARD) {
|
if (zEvent.getToZone() != Zone.GRAVEYARD) { return false; }
|
||||||
Card card = game.getCard(event.getSourceId());
|
|
||||||
if (card != null
|
Card card = game.getCard(event.getSourceId());
|
||||||
&& StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY.match(card, game)) {
|
if (card == null) { return false; }
|
||||||
CastFromGraveyardWatcher watcher = game.getState().getWatcher(CastFromGraveyardWatcher.class);
|
|
||||||
return watcher != null
|
if (!StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY.match(card, game)) { return false; }
|
||||||
&& watcher.spellWasCastFromGraveyard(event.getTargetId(),
|
|
||||||
game.getState().getZoneChangeCounter(event.getTargetId()));
|
CastFromGraveyardWatcher watcher = game.getState().getWatcher(CastFromGraveyardWatcher.class);
|
||||||
}
|
return watcher != null
|
||||||
}
|
&& watcher.spellWasCastFromGraveyard(event.getTargetId(),
|
||||||
return false;
|
game.getState().getZoneChangeCounter(event.getTargetId()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,9 +26,10 @@ public final class BountyOfTheLuxa extends CardImpl {
|
||||||
public BountyOfTheLuxa(UUID ownerId, CardSetInfo setInfo) {
|
public BountyOfTheLuxa(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}{U}");
|
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}{U}");
|
||||||
|
|
||||||
//At the beginning of your precombat main phase, remove all flood counters from Bounty of the Luxa. If no counters were removed this way, put a flood counter on Bounty of the Luxa and draw a card. Otherwise, add {C}{G}{U}.
|
// At the beginning of your precombat main phase, remove all flood counters from Bounty of the Luxa.
|
||||||
|
// If no counters were removed this way, put a flood counter on Bounty of the Luxa and draw a card.
|
||||||
|
// Otherwise, add {C}{G}{U}.
|
||||||
this.addAbility(new BeginningOfPreCombatMainTriggeredAbility(new BountyOfTheLuxaEffect(), TargetController.YOU, false));
|
this.addAbility(new BeginningOfPreCombatMainTriggeredAbility(new BountyOfTheLuxaEffect(), TargetController.YOU, false));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private BountyOfTheLuxa(final BountyOfTheLuxa card) {
|
private BountyOfTheLuxa(final BountyOfTheLuxa card) {
|
||||||
|
@ -46,7 +47,9 @@ class BountyOfTheLuxaEffect extends OneShotEffect {
|
||||||
|
|
||||||
public BountyOfTheLuxaEffect() {
|
public BountyOfTheLuxaEffect() {
|
||||||
super(Outcome.Benefit);
|
super(Outcome.Benefit);
|
||||||
staticText = "remove all flood counters from {this}. If no counters were removed this way, put a flood counter on {this} and draw a card. Otherwise, add {C}{G}{U}";
|
staticText = "remove all flood counters from {this}. " +
|
||||||
|
"If no counters were removed this way, put a flood counter on {this} and draw a card. " +
|
||||||
|
"Otherwise, add {C}{G}{U}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public BountyOfTheLuxaEffect(final BountyOfTheLuxaEffect effect) {
|
public BountyOfTheLuxaEffect(final BountyOfTheLuxaEffect effect) {
|
||||||
|
@ -65,26 +68,25 @@ class BountyOfTheLuxaEffect extends OneShotEffect {
|
||||||
if (bountyOfLuxa != null && bountyOfLuxa.getZoneChangeCounter(game) != source.getSourceObjectZoneChangeCounter()) {
|
if (bountyOfLuxa != null && bountyOfLuxa.getZoneChangeCounter(game) != source.getSourceObjectZoneChangeCounter()) {
|
||||||
bountyOfLuxa = null;
|
bountyOfLuxa = null;
|
||||||
}
|
}
|
||||||
if (controller != null) {
|
if (controller == null) { return false; }
|
||||||
if (bountyOfLuxa != null
|
|
||||||
&& bountyOfLuxa.getCounters(game).getCount(CounterType.FLOOD) > 0) {
|
if (bountyOfLuxa != null
|
||||||
bountyOfLuxa.removeCounters(CounterType.FLOOD.createInstance(bountyOfLuxa.getCounters(game).getCount(CounterType.FLOOD)), source, game);
|
&& bountyOfLuxa.getCounters(game).getCount(CounterType.FLOOD) > 0) {
|
||||||
if (bountyOfLuxa.getCounters(game).getCount(CounterType.FLOOD) == 0) {
|
bountyOfLuxa.removeCounters(CounterType.FLOOD.createInstance(bountyOfLuxa.getCounters(game).getCount(CounterType.FLOOD)), source, game);
|
||||||
Mana manaToAdd = new Mana();
|
if (bountyOfLuxa.getCounters(game).getCount(CounterType.FLOOD) == 0) {
|
||||||
manaToAdd.increaseColorless();
|
Mana manaToAdd = new Mana();
|
||||||
manaToAdd.increaseGreen();
|
manaToAdd.increaseColorless();
|
||||||
manaToAdd.increaseBlue();
|
manaToAdd.increaseGreen();
|
||||||
controller.getManaPool().addMana(manaToAdd, game, source);
|
manaToAdd.increaseBlue();
|
||||||
}
|
controller.getManaPool().addMana(manaToAdd, game, source);
|
||||||
} else {
|
|
||||||
if (bountyOfLuxa != null) {
|
|
||||||
new AddCountersSourceEffect(CounterType.FLOOD.createInstance()).apply(game, source);
|
|
||||||
}
|
|
||||||
controller.drawCards(1, source, game);
|
|
||||||
}
|
}
|
||||||
return true;
|
} else {
|
||||||
|
if (bountyOfLuxa != null) {
|
||||||
|
new AddCountersSourceEffect(CounterType.FLOOD.createInstance()).apply(game, source);
|
||||||
|
}
|
||||||
|
controller.drawCards(1, source, game);
|
||||||
}
|
}
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,24 +72,23 @@ class BraceForImpactPreventDamageTargetEffect extends PreventionEffectImpl {
|
||||||
@Override
|
@Override
|
||||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||||
GameEvent preventEvent = new PreventDamageEvent(event.getTargetId(), source.getSourceId(), source, source.getControllerId(), event.getAmount(), ((DamageEvent) event).isCombatDamage());
|
GameEvent preventEvent = new PreventDamageEvent(event.getTargetId(), source.getSourceId(), source, source.getControllerId(), event.getAmount(), ((DamageEvent) event).isCombatDamage());
|
||||||
if (!game.replaceEvent(preventEvent)) {
|
if (game.replaceEvent(preventEvent)) { return false; }
|
||||||
int prevented = 0;
|
int prevented;
|
||||||
int damage = event.getAmount();
|
int damage = event.getAmount();
|
||||||
event.setAmount(0);
|
event.setAmount(0);
|
||||||
game.fireEvent(new PreventedDamageEvent(event.getTargetId(), source.getSourceId(), source, source.getControllerId(), damage));
|
game.fireEvent(new PreventedDamageEvent(event.getTargetId(), source.getSourceId(), source, source.getControllerId(), damage));
|
||||||
prevented = damage;
|
prevented = damage;
|
||||||
|
|
||||||
// add counters now
|
// add counters now
|
||||||
if (prevented > 0) {
|
if (prevented > 0) {
|
||||||
Permanent targetPermanent = game.getPermanent(source.getTargets().getFirstTarget());
|
Permanent targetPermanent = game.getPermanent(source.getTargets().getFirstTarget());
|
||||||
if (targetPermanent != null) {
|
if (targetPermanent != null) {
|
||||||
targetPermanent.addCounters(CounterType.P1P1.createInstance(prevented), source.getControllerId(), source, game);
|
targetPermanent.addCounters(CounterType.P1P1.createInstance(prevented), source.getControllerId(), source, game);
|
||||||
game.informPlayers("Brace for Impact: Prevented " + prevented + " damage ");
|
game.informPlayers("Brace for Impact: Prevented " + prevented + " damage ");
|
||||||
game.informPlayers("Brace for Impact: Adding " + prevented + " +1/+1 counters to " + targetPermanent.getName());
|
game.informPlayers("Brace for Impact: Adding " + prevented + " +1/+1 counters to " + targetPermanent.getName());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -57,7 +57,7 @@ public final class BridgeFromBelow extends CardImpl {
|
||||||
|
|
||||||
class BridgeFromBelowAbility extends TriggeredAbilityImpl {
|
class BridgeFromBelowAbility extends TriggeredAbilityImpl {
|
||||||
|
|
||||||
protected FilterCreaturePermanent filter;
|
private final FilterCreaturePermanent filter;
|
||||||
|
|
||||||
public BridgeFromBelowAbility(Effect effect, FilterCreaturePermanent filter) {
|
public BridgeFromBelowAbility(Effect effect, FilterCreaturePermanent filter) {
|
||||||
super(Zone.GRAVEYARD, effect, false);
|
super(Zone.GRAVEYARD, effect, false);
|
||||||
|
@ -82,14 +82,12 @@ class BridgeFromBelowAbility extends TriggeredAbilityImpl {
|
||||||
@Override
|
@Override
|
||||||
public boolean checkTrigger(GameEvent event, Game game) {
|
public boolean checkTrigger(GameEvent event, Game game) {
|
||||||
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
|
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
|
||||||
if (zEvent.isDiesEvent()) {
|
if (!zEvent.isDiesEvent()) { return false; }
|
||||||
Permanent permanent = (Permanent) game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD);
|
|
||||||
if (permanent != null
|
Permanent permanent = (Permanent) game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD);
|
||||||
&& filter.match(permanent, sourceId, controllerId, game)) {
|
if (permanent == null) { return false; }
|
||||||
return true;
|
|
||||||
}
|
return filter.match(permanent, sourceId, controllerId, game);
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -64,24 +64,24 @@ class BrightflameEffect extends OneShotEffect {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Permanent target = game.getPermanent(targetPointer.getFirst(game, source));
|
|
||||||
int damageDealt = 0;
|
int damageDealt = 0;
|
||||||
if (target != null) {
|
|
||||||
ObjectColor color = target.getColor(game);
|
|
||||||
damageDealt += target.damage(amount.calculate(game, source, this), source.getSourceId(), source, game);
|
|
||||||
for (Permanent p : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), game)) {
|
|
||||||
if (!target.getId().equals(p.getId()) && p.getColor(game).shares(color)) {
|
|
||||||
damageDealt += p.damage(amount.calculate(game, source, this), source.getSourceId(), source, game, false, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Player you = game.getPlayer(source.getControllerId());
|
Permanent target = game.getPermanent(targetPointer.getFirst(game, source));
|
||||||
if (you != null && damageDealt > 0) {
|
if (target == null) { return false; }
|
||||||
you.gainLife(damageDealt, game, source);
|
|
||||||
|
ObjectColor color = target.getColor(game);
|
||||||
|
damageDealt += target.damage(amount.calculate(game, source, this), source.getSourceId(), source, game);
|
||||||
|
for (Permanent p : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), game)) {
|
||||||
|
if (!target.getId().equals(p.getId()) && p.getColor(game).shares(color)) {
|
||||||
|
damageDealt += p.damage(amount.calculate(game, source, this), source.getSourceId(), source, game, false, true);
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
|
Player you = game.getPlayer(source.getControllerId());
|
||||||
|
if (you != null && damageDealt > 0) {
|
||||||
|
you.gainLife(damageDealt, game, source);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -75,31 +75,30 @@ class BrimazKingOfOreskosEffect extends OneShotEffect {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
|
if (controller == null) { return false; }
|
||||||
|
|
||||||
if (controller != null) {
|
Token token = new CatSoldierCreatureToken();
|
||||||
Token token = new CatSoldierCreatureToken();
|
token.putOntoBattlefield(1, game, source, source.getControllerId());
|
||||||
token.putOntoBattlefield(1, game, source, source.getControllerId());
|
Permanent attackingCreature = game.getPermanent(getTargetPointer().getFirst(game, source));
|
||||||
Permanent attackingCreature = game.getPermanent(getTargetPointer().getFirst(game, source));
|
if (attackingCreature == null || game.getState().getCombat() == null) { return true; }
|
||||||
if (attackingCreature != null && game.getState().getCombat() != null) {
|
|
||||||
// Possible ruling (see Aetherplasm)
|
// Possible ruling (see Aetherplasm)
|
||||||
// The token you created is blocking the attacking creature,
|
// The token you created is blocking the attacking creature,
|
||||||
// even if the block couldn't legally be declared (for example, if that creature
|
// even if the block couldn't legally be declared (for example, if that creature
|
||||||
// enters the battlefield tapped, or it can't block, or the attacking creature
|
// enters the battlefield tapped, or it can't block, or the attacking creature
|
||||||
// has protection from it)
|
// has protection from it)
|
||||||
CombatGroup combatGroup = game.getState().getCombat().findGroup(attackingCreature.getId());
|
CombatGroup combatGroup = game.getState().getCombat().findGroup(attackingCreature.getId());
|
||||||
if (combatGroup != null) {
|
if (combatGroup == null) { return true; }
|
||||||
for (UUID tokenId : token.getLastAddedTokenIds()) {
|
|
||||||
Permanent catToken = game.getPermanent(tokenId);
|
for (UUID tokenId : token.getLastAddedTokenIds()) {
|
||||||
if (catToken != null) {
|
Permanent catToken = game.getPermanent(tokenId);
|
||||||
combatGroup.addBlocker(tokenId, source.getControllerId(), game);
|
if (catToken == null) { continue; }
|
||||||
game.getCombat().addBlockingGroup(tokenId, attackingCreature.getId(), controller.getId(), game);
|
|
||||||
}
|
combatGroup.addBlocker(tokenId, source.getControllerId(), game);
|
||||||
}
|
game.getCombat().addBlockingGroup(tokenId, attackingCreature.getId(), controller.getId(), game);
|
||||||
combatGroup.pickBlockerOrder(attackingCreature.getControllerId(), game);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
combatGroup.pickBlockerOrder(attackingCreature.getControllerId(), game);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,26 +68,27 @@ class BrineHagEffect extends OneShotEffect {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
|
if (controller == null) { return false; }
|
||||||
|
|
||||||
Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId());
|
Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId());
|
||||||
if (sourcePermanent != null) {
|
if (sourcePermanent == null) { return false; }
|
||||||
List<Permanent> list = new ArrayList<>();
|
|
||||||
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
|
List<Permanent> list = new ArrayList<>();
|
||||||
Player player = game.getPlayer(playerId);
|
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
|
||||||
if (player != null) {
|
Player player = game.getPlayer(playerId);
|
||||||
for (Permanent creature : game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, playerId, game)) {
|
if (player == null) { continue; }
|
||||||
if (sourcePermanent.getDealtDamageByThisTurn().contains(new MageObjectReference(creature.getId(), game))) {
|
|
||||||
list.add(creature);
|
for (Permanent creature : game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, playerId, game)) {
|
||||||
}
|
if (sourcePermanent.getDealtDamageByThisTurn().contains(new MageObjectReference(creature.getId(), game))) {
|
||||||
}
|
list.add(creature);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!list.isEmpty()) {
|
|
||||||
FilterCreaturePermanent filter = new FilterCreaturePermanent();
|
|
||||||
filter.add(new PermanentInListPredicate(list));
|
|
||||||
game.addEffect(new SetPowerToughnessAllEffect(0, 2, Duration.Custom, filter, true), source);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
if (!list.isEmpty()) {
|
||||||
|
FilterCreaturePermanent filter = new FilterCreaturePermanent();
|
||||||
|
filter.add(new PermanentInListPredicate(list));
|
||||||
|
game.addEffect(new SetPowerToughnessAllEffect(0, 2, Duration.Custom, filter, true), source);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,8 +32,9 @@ public final class BroodhatchNantuko extends CardImpl {
|
||||||
|
|
||||||
// Whenever Broodhatch Nantuko is dealt damage, you may create that many 1/1 green Insect creature tokens.
|
// Whenever Broodhatch Nantuko is dealt damage, you may create that many 1/1 green Insect creature tokens.
|
||||||
this.addAbility(new DealtDamageToSourceTriggeredAbility(new BroodhatchNantukoDealDamageEffect(), true, false));
|
this.addAbility(new DealtDamageToSourceTriggeredAbility(new BroodhatchNantukoDealDamageEffect(), true, false));
|
||||||
|
|
||||||
// Morph {2}{G}
|
// Morph {2}{G}
|
||||||
this.addAbility(new MorphAbility(this, new ManaCostsImpl("{2}{G}")));
|
this.addAbility(new MorphAbility(this, new ManaCostsImpl<>("{2}{G}")));
|
||||||
}
|
}
|
||||||
|
|
||||||
private BroodhatchNantuko(final BroodhatchNantuko card) {
|
private BroodhatchNantuko(final BroodhatchNantuko card) {
|
||||||
|
@ -65,12 +66,11 @@ class BroodhatchNantukoDealDamageEffect extends OneShotEffect {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Player player = game.getPlayer(source.getControllerId());
|
Player player = game.getPlayer(source.getControllerId());
|
||||||
if (player != null) {
|
if (player == null) { return false; }
|
||||||
int amount = (Integer) getValue("damage");
|
|
||||||
if (amount > 0) {
|
int amount = (Integer) getValue("damage");
|
||||||
return new CreateTokenEffect(new InsectToken(), amount).apply(game, source);
|
if (amount <= 0) { return false; }
|
||||||
}
|
|
||||||
}
|
return new CreateTokenEffect(new InsectToken(), amount).apply(game, source);
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ import mage.game.permanent.token.DragonToken;
|
||||||
*/
|
*/
|
||||||
public final class BroodmateDragon extends CardImpl {
|
public final class BroodmateDragon extends CardImpl {
|
||||||
|
|
||||||
private static DragonToken dragonToken = new DragonToken();
|
private static final DragonToken dragonToken = new DragonToken();
|
||||||
|
|
||||||
public BroodmateDragon(UUID ownerId, CardSetInfo setInfo) {
|
public BroodmateDragon(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{B}{R}{G}");
|
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{B}{R}{G}");
|
||||||
|
|
|
@ -75,8 +75,10 @@ class BrunaLightOfAlabasterEffect extends OneShotEffect {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
UUID bruna = source.getSourceId();
|
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
|
if (controller == null) { return false; }
|
||||||
|
|
||||||
|
UUID bruna = source.getSourceId();
|
||||||
|
|
||||||
FilterPermanent filterAura = new FilterPermanent("Aura");
|
FilterPermanent filterAura = new FilterPermanent("Aura");
|
||||||
FilterCard filterAuraCard = new FilterCard("Aura card");
|
FilterCard filterAuraCard = new FilterCard("Aura card");
|
||||||
|
@ -88,13 +90,9 @@ class BrunaLightOfAlabasterEffect extends OneShotEffect {
|
||||||
filterAuraCard.add(SubType.AURA.getPredicate());
|
filterAuraCard.add(SubType.AURA.getPredicate());
|
||||||
filterAuraCard.add(new AuraCardCanAttachToPermanentId(bruna));
|
filterAuraCard.add(new AuraCardCanAttachToPermanentId(bruna));
|
||||||
|
|
||||||
if (controller == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
|
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
|
||||||
if (sourcePermanent == null) {
|
if (sourcePermanent == null) { return false; }
|
||||||
return false;
|
|
||||||
}
|
|
||||||
List<Permanent> fromBattlefield = new ArrayList<>();
|
List<Permanent> fromBattlefield = new ArrayList<>();
|
||||||
List<Card> fromHandGraveyard = new ArrayList<>();
|
List<Card> fromHandGraveyard = new ArrayList<>();
|
||||||
|
|
||||||
|
@ -104,16 +102,17 @@ class BrunaLightOfAlabasterEffect extends OneShotEffect {
|
||||||
&& controller.chooseUse(Outcome.Benefit, "Attach an Aura from the battlefield?", source, game)) {
|
&& controller.chooseUse(Outcome.Benefit, "Attach an Aura from the battlefield?", source, game)) {
|
||||||
Target targetAura = new TargetPermanent(filterAura);
|
Target targetAura = new TargetPermanent(filterAura);
|
||||||
targetAura.setNotTarget(true);
|
targetAura.setNotTarget(true);
|
||||||
if (controller.choose(Outcome.Benefit, targetAura, source.getSourceId(), game)) {
|
if (!controller.choose(Outcome.Benefit, targetAura, source.getSourceId(), game)) { continue; }
|
||||||
Permanent aura = game.getPermanent(targetAura.getFirstTarget());
|
|
||||||
if (aura != null) {
|
Permanent aura = game.getPermanent(targetAura.getFirstTarget());
|
||||||
Target target = aura.getSpellAbility().getTargets().get(0);
|
if (aura == null) { continue; }
|
||||||
if (target != null) {
|
|
||||||
fromBattlefield.add(aura);
|
Target target = aura.getSpellAbility().getTargets().get(0);
|
||||||
filterAura.add(Predicates.not(new CardIdPredicate(aura.getId())));
|
if (target == null) { continue; }
|
||||||
}
|
|
||||||
}
|
fromBattlefield.add(aura);
|
||||||
}
|
filterAura.add(Predicates.not(new CardIdPredicate(aura.getId())));
|
||||||
|
|
||||||
countBattlefield = game.getBattlefield().getAllActivePermanents(filterAura, game).size() - sourcePermanent.getAttachments().size();
|
countBattlefield = game.getBattlefield().getAllActivePermanents(filterAura, game).size() - sourcePermanent.getAttachments().size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,16 +121,16 @@ class BrunaLightOfAlabasterEffect extends OneShotEffect {
|
||||||
&& countHand > 0
|
&& countHand > 0
|
||||||
&& controller.chooseUse(Outcome.Benefit, "Attach an Aura from your hand?", source, game)) {
|
&& controller.chooseUse(Outcome.Benefit, "Attach an Aura from your hand?", source, game)) {
|
||||||
TargetCard targetAura = new TargetCard(Zone.HAND, filterAuraCard);
|
TargetCard targetAura = new TargetCard(Zone.HAND, filterAuraCard);
|
||||||
if (controller.choose(Outcome.Benefit, controller.getHand(), targetAura, game)) {
|
if (!controller.choose(Outcome.Benefit, controller.getHand(), targetAura, game)) { continue; }
|
||||||
Card aura = game.getCard(targetAura.getFirstTarget());
|
|
||||||
if (aura != null) {
|
Card aura = game.getCard(targetAura.getFirstTarget());
|
||||||
Target target = aura.getSpellAbility().getTargets().get(0);
|
if (aura == null) { continue; }
|
||||||
if (target != null) {
|
|
||||||
fromHandGraveyard.add(aura);
|
Target target = aura.getSpellAbility().getTargets().get(0);
|
||||||
filterAuraCard.add(Predicates.not(new CardIdPredicate(aura.getId())));
|
if (target == null) { continue; }
|
||||||
}
|
fromHandGraveyard.add(aura);
|
||||||
}
|
filterAuraCard.add(Predicates.not(new CardIdPredicate(aura.getId())));
|
||||||
}
|
|
||||||
countHand = controller.getHand().count(filterAuraCard, game);
|
countHand = controller.getHand().count(filterAuraCard, game);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,18 +139,20 @@ class BrunaLightOfAlabasterEffect extends OneShotEffect {
|
||||||
&& countGraveyard > 0
|
&& countGraveyard > 0
|
||||||
&& controller.chooseUse(Outcome.Benefit, "Attach an Aura from your graveyard?", source, game)) {
|
&& controller.chooseUse(Outcome.Benefit, "Attach an Aura from your graveyard?", source, game)) {
|
||||||
TargetCard targetAura = new TargetCard(Zone.GRAVEYARD, filterAuraCard);
|
TargetCard targetAura = new TargetCard(Zone.GRAVEYARD, filterAuraCard);
|
||||||
if (controller.choose(Outcome.Benefit, controller.getGraveyard(), targetAura, game)) {
|
if (!controller.choose(Outcome.Benefit, controller.getGraveyard(), targetAura, game)) { continue; }
|
||||||
Card aura = game.getCard(targetAura.getFirstTarget());
|
|
||||||
if (aura != null) {
|
Card aura = game.getCard(targetAura.getFirstTarget());
|
||||||
Target target = aura.getSpellAbility().getTargets().get(0);
|
if (aura == null) { continue; }
|
||||||
if (target != null) {
|
|
||||||
fromHandGraveyard.add(aura);
|
Target target = aura.getSpellAbility().getTargets().get(0);
|
||||||
filterAuraCard.add(Predicates.not(new CardIdPredicate(aura.getId())));
|
if (target == null) { continue; }
|
||||||
}
|
|
||||||
}
|
fromHandGraveyard.add(aura);
|
||||||
}
|
filterAuraCard.add(Predicates.not(new CardIdPredicate(aura.getId())));
|
||||||
|
|
||||||
countGraveyard = controller.getGraveyard().count(filterAuraCard, game);
|
countGraveyard = controller.getGraveyard().count(filterAuraCard, game);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move permanents
|
// Move permanents
|
||||||
for (Permanent aura : fromBattlefield) {
|
for (Permanent aura : fromBattlefield) {
|
||||||
Permanent attachedTo = game.getPermanent(aura.getAttachedTo());
|
Permanent attachedTo = game.getPermanent(aura.getAttachedTo());
|
||||||
|
@ -160,13 +161,14 @@ class BrunaLightOfAlabasterEffect extends OneShotEffect {
|
||||||
}
|
}
|
||||||
sourcePermanent.addAttachment(aura.getId(), source, game);
|
sourcePermanent.addAttachment(aura.getId(), source, game);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move cards
|
// Move cards
|
||||||
for (Card aura : fromHandGraveyard) {
|
for (Card aura : fromHandGraveyard) {
|
||||||
if (aura != null) {
|
if (aura == null) { continue; }
|
||||||
game.getState().setValue("attachTo:" + aura.getId(), sourcePermanent);
|
|
||||||
controller.moveCards(aura, Zone.BATTLEFIELD, source, game);
|
game.getState().setValue("attachTo:" + aura.getId(), sourcePermanent);
|
||||||
sourcePermanent.addAttachment(aura.getId(), source, game);
|
controller.moveCards(aura, Zone.BATTLEFIELD, source, game);
|
||||||
}
|
sourcePermanent.addAttachment(aura.getId(), source, game);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,13 +70,12 @@ class BudokaGardenerEffect extends OneShotEffect {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
if (controller != null) {
|
if (controller == null) { return false; }
|
||||||
if (game.getBattlefield().count(filterLands, source.getSourceId(), source.getControllerId(), game) >= 10) {
|
if (game.getBattlefield().count(filterLands, source.getSourceId(), source.getControllerId(), game) < 10) {
|
||||||
new FlipSourceEffect(new DokaiWeaverofLife()).apply(game, source);
|
return false;
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
|
return new FlipSourceEffect(new DokaiWeaverofLife()).apply(game, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -15,7 +15,7 @@ import java.util.UUID;
|
||||||
|
|
||||||
public final class BullElephant extends CardImpl {
|
public final class BullElephant extends CardImpl {
|
||||||
|
|
||||||
private static FilterControlledLandPermanent controlledForest = new FilterControlledLandPermanent("Forests");
|
private static final FilterControlledLandPermanent controlledForest = new FilterControlledLandPermanent("Forests");
|
||||||
|
|
||||||
static {
|
static {
|
||||||
controlledForest.add(SubType.FOREST.getPredicate());
|
controlledForest.add(SubType.FOREST.getPredicate());
|
||||||
|
@ -25,10 +25,14 @@ public final class BullElephant extends CardImpl {
|
||||||
public BullElephant(UUID cardId, CardSetInfo cardSetInfo) {
|
public BullElephant(UUID cardId, CardSetInfo cardSetInfo) {
|
||||||
super(cardId, cardSetInfo, new CardType[]{CardType.CREATURE}, "{3}{G}");
|
super(cardId, cardSetInfo, new CardType[]{CardType.CREATURE}, "{3}{G}");
|
||||||
this.subtype.add(SubType.ELEPHANT);
|
this.subtype.add(SubType.ELEPHANT);
|
||||||
|
|
||||||
power = new MageInt(4);
|
power = new MageInt(4);
|
||||||
toughness = new MageInt(4);
|
toughness = new MageInt(4);
|
||||||
//When Bull Elephant enters the battlefield, sacrifice it unless you return two Forests you control to their owner's hand.
|
|
||||||
addAbility(new EntersBattlefieldTriggeredAbility(new SacrificeSourceUnlessPaysEffect(new ReturnToHandChosenControlledPermanentCost(new TargetControlledPermanent(2, 2, controlledForest, false)))));
|
// When Bull Elephant enters the battlefield, sacrifice it unless you return two Forests you control to their owner's hand.
|
||||||
|
addAbility(new EntersBattlefieldTriggeredAbility(new SacrificeSourceUnlessPaysEffect(new ReturnToHandChosenControlledPermanentCost(
|
||||||
|
new TargetControlledPermanent(2, 2, controlledForest, false)
|
||||||
|
))));
|
||||||
}
|
}
|
||||||
|
|
||||||
public BullElephant(BullElephant other) {
|
public BullElephant(BullElephant other) {
|
||||||
|
|
|
@ -32,7 +32,6 @@ public final class BurnFromWithin extends CardImpl {
|
||||||
// If that creature would die this turn, exile it instead.
|
// If that creature would die this turn, exile it instead.
|
||||||
this.getSpellAbility().addEffect(new BurnFromWithinEffect());
|
this.getSpellAbility().addEffect(new BurnFromWithinEffect());
|
||||||
this.getSpellAbility().addTarget(new TargetAnyTarget());
|
this.getSpellAbility().addTarget(new TargetAnyTarget());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private BurnFromWithin(final BurnFromWithin card) {
|
private BurnFromWithin(final BurnFromWithin card) {
|
||||||
|
@ -49,7 +48,9 @@ class BurnFromWithinEffect extends OneShotEffect {
|
||||||
|
|
||||||
public BurnFromWithinEffect() {
|
public BurnFromWithinEffect() {
|
||||||
super(Outcome.Benefit);
|
super(Outcome.Benefit);
|
||||||
this.staticText = "{this} deals X damage to any target. If a creature is dealt damage this way, it loses indestructible until end of turn. If that creature would die this turn, exile it instead";
|
this.staticText = "{this} deals X damage to any target. " +
|
||||||
|
"If a creature is dealt damage this way, it loses indestructible until end of turn. " +
|
||||||
|
"If that creature would die this turn, exile it instead";
|
||||||
}
|
}
|
||||||
|
|
||||||
public BurnFromWithinEffect(final BurnFromWithinEffect effect) {
|
public BurnFromWithinEffect(final BurnFromWithinEffect effect) {
|
||||||
|
@ -64,25 +65,31 @@ class BurnFromWithinEffect extends OneShotEffect {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
if (controller != null) {
|
if (controller == null) { return false; }
|
||||||
Permanent creature = game.getPermanent(getTargetPointer().getFirst(game, source));
|
|
||||||
int amount = source.getManaCostsToPay().getX();
|
int amount = source.getManaCostsToPay().getX();
|
||||||
if (creature != null) {
|
|
||||||
game.addEffect(new DiesReplacementEffect(new MageObjectReference(creature, game), Duration.EndOfTurn), source);
|
// Target is a creature
|
||||||
int damageDealt = creature.damage(amount, source.getSourceId(), source, game, false, true);
|
Permanent creature = game.getPermanent(getTargetPointer().getFirst(game, source));
|
||||||
if (damageDealt > 0) {
|
if (creature != null) {
|
||||||
ContinuousEffect effect = new LoseAbilityTargetEffect(IndestructibleAbility.getInstance(), Duration.EndOfTurn);
|
game.addEffect(new DiesReplacementEffect(new MageObjectReference(creature, game), Duration.EndOfTurn), source);
|
||||||
effect.setTargetPointer(new FixedTarget(creature.getId(), game));
|
int damageDealt = creature.damage(amount, source.getSourceId(), source, game, false, true);
|
||||||
game.addEffect(effect, source);
|
if (damageDealt > 0) {
|
||||||
}
|
ContinuousEffect effect = new LoseAbilityTargetEffect(IndestructibleAbility.getInstance(), Duration.EndOfTurn);
|
||||||
return true;
|
effect.setTargetPointer(new FixedTarget(creature.getId(), game));
|
||||||
}
|
game.addEffect(effect, source);
|
||||||
Player targetPlayer = game.getPlayer(this.getTargetPointer().getFirst(game, source));
|
|
||||||
if (targetPlayer != null) {
|
|
||||||
targetPlayer.damage(amount, source.getSourceId(), source, game);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Target is a player
|
||||||
|
Player targetPlayer = game.getPlayer(this.getTargetPointer().getFirst(game, source));
|
||||||
|
if (targetPlayer != null) {
|
||||||
|
targetPlayer.damage(amount, source.getSourceId(), source, game);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No valid target
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -145,7 +145,7 @@ class BurningCinderFuryOfCrimsonChaosFireEffect extends OneShotEffect {
|
||||||
|
|
||||||
class BurningCinderFuryOfCrimsonChaosFireCreatureGainControlEffect extends ContinuousEffectImpl {
|
class BurningCinderFuryOfCrimsonChaosFireCreatureGainControlEffect extends ContinuousEffectImpl {
|
||||||
|
|
||||||
private UUID controller;
|
private final UUID controller;
|
||||||
|
|
||||||
public BurningCinderFuryOfCrimsonChaosFireCreatureGainControlEffect(Duration duration, UUID controller) {
|
public BurningCinderFuryOfCrimsonChaosFireCreatureGainControlEffect(Duration duration, UUID controller) {
|
||||||
super(duration, Layer.ControlChangingEffects_2, SubLayer.NA, Outcome.GainControl);
|
super(duration, Layer.ControlChangingEffects_2, SubLayer.NA, Outcome.GainControl);
|
||||||
|
|
|
@ -61,22 +61,21 @@ class BurningOfXinyeEffect extends OneShotEffect{
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
boolean abilityApplied = false;
|
boolean abilityApplied = false;
|
||||||
|
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
|
||||||
|
|
||||||
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
if (controller != null) {
|
if (controller != null) {
|
||||||
abilityApplied |= playerDestroys(game, source, controller);
|
abilityApplied |= playerDestroys(game, source, controller);
|
||||||
}
|
}
|
||||||
|
|
||||||
Player opponent = game.getPlayer(source.getFirstTarget());
|
|
||||||
|
|
||||||
if (controller != null) {
|
Player opponent = game.getPlayer(source.getFirstTarget());
|
||||||
|
if (opponent != null) {
|
||||||
abilityApplied |= playerDestroys(game, source, opponent);
|
abilityApplied |= playerDestroys(game, source, opponent);
|
||||||
}
|
}
|
||||||
|
|
||||||
return abilityApplied;
|
return abilityApplied;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean playerDestroys(Game game, Ability source,Player player){
|
private boolean playerDestroys(Game game, Ability source, Player player){
|
||||||
boolean abilityApplied = false;
|
boolean abilityApplied = false;
|
||||||
|
|
||||||
int realCount = game.getBattlefield().countAll(filter, player.getId(), game);
|
int realCount = game.getBattlefield().countAll(filter, player.getId(), game);
|
||||||
|
@ -88,10 +87,10 @@ class BurningOfXinyeEffect extends OneShotEffect{
|
||||||
player.choose(Outcome.Sacrifice, target, source.getSourceId(), game);
|
player.choose(Outcome.Sacrifice, target, source.getSourceId(), game);
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( int idx = 0; idx < target.getTargets().size(); idx++) {
|
for (UUID targetId : target.getTargets()) {
|
||||||
Permanent permanent = game.getPermanent(target.getTargets().get(idx));
|
Permanent permanent = game.getPermanent(targetId);
|
||||||
|
|
||||||
if ( permanent != null ) {
|
if (permanent != null) {
|
||||||
abilityApplied |= permanent.destroy(source, game, false);
|
abilityApplied |= permanent.destroy(source, game, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,5 +102,4 @@ class BurningOfXinyeEffect extends OneShotEffect{
|
||||||
public BurningOfXinyeEffect copy() {
|
public BurningOfXinyeEffect copy() {
|
||||||
return new BurningOfXinyeEffect(this);
|
return new BurningOfXinyeEffect(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -37,10 +37,11 @@ public final class KnowledgePool extends CardImpl {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{6}");
|
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{6}");
|
||||||
|
|
||||||
// Imprint - When Knowledge Pool enters the battlefield, each player exiles the top three cards of their library
|
// Imprint - When Knowledge Pool enters the battlefield, each player exiles the top three cards of their library
|
||||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new KnowledgePoolEffect1(), false).setAbilityWord(AbilityWord.IMPRINT));
|
this.addAbility(new EntersBattlefieldTriggeredAbility(new KnowledgePoolExileThreeCardsEffect(), false).setAbilityWord(AbilityWord.IMPRINT));
|
||||||
|
|
||||||
// Whenever a player casts a spell from their hand, that player exiles it. If the player does, they may cast another nonland card exiled with Knowledge Pool without paying that card's mana cost.
|
// Whenever a player casts a spell from their hand, that player exiles it.
|
||||||
this.addAbility(new KnowledgePoolAbility());
|
// If the player does, they may cast another nonland card exiled with Knowledge Pool without paying that card's mana cost.
|
||||||
|
this.addAbility(new KnowledgePoolWhenCastFromHandAbility());
|
||||||
}
|
}
|
||||||
|
|
||||||
private KnowledgePool(final KnowledgePool card) {
|
private KnowledgePool(final KnowledgePool card) {
|
||||||
|
@ -51,58 +52,62 @@ public final class KnowledgePool extends CardImpl {
|
||||||
public KnowledgePool copy() {
|
public KnowledgePool copy() {
|
||||||
return new KnowledgePool(this);
|
return new KnowledgePool(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class KnowledgePoolEffect1 extends OneShotEffect {
|
class KnowledgePoolExileThreeCardsEffect extends OneShotEffect {
|
||||||
|
|
||||||
public KnowledgePoolEffect1() {
|
public KnowledgePoolExileThreeCardsEffect() {
|
||||||
super(Outcome.Neutral);
|
super(Outcome.Neutral);
|
||||||
staticText = "each player exiles the top three cards of their library";
|
staticText = "each player exiles the top three cards of their library";
|
||||||
}
|
}
|
||||||
|
|
||||||
public KnowledgePoolEffect1(final KnowledgePoolEffect1 effect) {
|
public KnowledgePoolExileThreeCardsEffect(final KnowledgePoolExileThreeCardsEffect effect) {
|
||||||
super(effect);
|
super(effect);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
|
if (controller == null) { return false; }
|
||||||
|
|
||||||
MageObject sourceObject = game.getObject(source.getSourceId());
|
MageObject sourceObject = game.getObject(source.getSourceId());
|
||||||
if (controller == null || sourceObject == null) {
|
if (sourceObject == null) { return false; }
|
||||||
return false;
|
|
||||||
}
|
|
||||||
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
|
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
|
||||||
Player player = game.getPlayer(playerId);
|
Player player = game.getPlayer(playerId);
|
||||||
if (player != null) {
|
if (player == null) { continue; }
|
||||||
player.moveCardsToExile(player.getLibrary().getTopCards(game, 3), source, game, true,
|
|
||||||
CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter()),
|
player.moveCardsToExile(
|
||||||
sourceObject.getIdName() + " (" + sourceObject.getZoneChangeCounter(game) + ')');
|
player.getLibrary().getTopCards(game, 3),
|
||||||
}
|
source,
|
||||||
|
game,
|
||||||
|
true,
|
||||||
|
CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter()),
|
||||||
|
sourceObject.getIdName() + " (" + sourceObject.getZoneChangeCounter(game) + ')'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public KnowledgePoolEffect1 copy() {
|
public KnowledgePoolExileThreeCardsEffect copy() {
|
||||||
return new KnowledgePoolEffect1(this);
|
return new KnowledgePoolExileThreeCardsEffect(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class KnowledgePoolAbility extends TriggeredAbilityImpl {
|
class KnowledgePoolWhenCastFromHandAbility extends TriggeredAbilityImpl {
|
||||||
|
|
||||||
public KnowledgePoolAbility() {
|
public KnowledgePoolWhenCastFromHandAbility() {
|
||||||
super(Zone.BATTLEFIELD, new KnowledgePoolEffect2(), false);
|
super(Zone.BATTLEFIELD, new KnowledgePoolExileAndPlayEffect(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public KnowledgePoolAbility(final KnowledgePoolAbility ability) {
|
private KnowledgePoolWhenCastFromHandAbility(final KnowledgePoolWhenCastFromHandAbility ability) {
|
||||||
super(ability);
|
super(ability);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public KnowledgePoolAbility copy() {
|
public KnowledgePoolWhenCastFromHandAbility copy() {
|
||||||
return new KnowledgePoolAbility(this);
|
return new KnowledgePoolWhenCastFromHandAbility(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -112,72 +117,76 @@ class KnowledgePoolAbility extends TriggeredAbilityImpl {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean checkTrigger(GameEvent event, Game game) {
|
public boolean checkTrigger(GameEvent event, Game game) {
|
||||||
if (event.getZone() == Zone.HAND) {
|
if (event.getZone() != Zone.HAND) { return false; }
|
||||||
Spell spell = game.getStack().getSpell(event.getTargetId());
|
|
||||||
if (spell != null) {
|
|
||||||
for (Effect effect : this.getEffects()) {
|
|
||||||
effect.setTargetPointer(new FixedTarget(event.getTargetId()));
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
Spell spell = game.getStack().getSpell(event.getTargetId());
|
||||||
|
if (spell == null) { return false; }
|
||||||
|
|
||||||
|
for (Effect effect : this.getEffects()) {
|
||||||
|
effect.setTargetPointer(new FixedTarget(event.getTargetId()));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class KnowledgePoolEffect2 extends OneShotEffect {
|
class KnowledgePoolExileAndPlayEffect extends OneShotEffect {
|
||||||
|
|
||||||
private static FilterNonlandCard filter = new FilterNonlandCard("nonland card exiled with Knowledge Pool");
|
public KnowledgePoolExileAndPlayEffect() {
|
||||||
|
|
||||||
public KnowledgePoolEffect2() {
|
|
||||||
super(Outcome.Neutral);
|
super(Outcome.Neutral);
|
||||||
staticText = "Whenever a player casts a spell from their hand, that player exiles it. If the player does, they may cast another nonland card exiled with {this} without paying that card's mana cost";
|
staticText = "Whenever a player casts a spell from their hand, that player exiles it. If the player does, they may cast another nonland card exiled with {this} without paying that card's mana cost";
|
||||||
}
|
}
|
||||||
|
|
||||||
public KnowledgePoolEffect2(final KnowledgePoolEffect2 effect) {
|
private KnowledgePoolExileAndPlayEffect(final KnowledgePoolExileAndPlayEffect effect) {
|
||||||
super(effect);
|
super(effect);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Spell spell = game.getStack().getSpell(targetPointer.getFirst(game, source));
|
Spell spell = game.getStack().getSpell(targetPointer.getFirst(game, source));
|
||||||
if (spell == null) {
|
if (spell == null) { return false; }
|
||||||
|
|
||||||
|
Permanent sourceObject = game.getPermanentOrLKIBattlefield(source.getSourceId());
|
||||||
|
if (sourceObject == null ) { return false; }
|
||||||
|
|
||||||
|
Player spellController = game.getPlayer(spell.getControllerId());
|
||||||
|
if (spellController == null) { return false; }
|
||||||
|
|
||||||
|
UUID exileZoneId = CardUtil.getExileZoneId(game, source.getSourceId(), sourceObject.getZoneChangeCounter(game));
|
||||||
|
|
||||||
|
if (!spellController.moveCardsToExile(spell, source, game, true, exileZoneId, sourceObject.getIdName())) {
|
||||||
|
// The card didn't make it to exile, none of Knowledge Pool's effect applied
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Permanent sourceObject = game.getPermanentOrLKIBattlefield(source.getSourceId());
|
|
||||||
Player spellController = game.getPlayer(spell.getControllerId());
|
// From here on down the function returns true since at least part of the effect went off
|
||||||
if (spellController != null
|
|
||||||
&& sourceObject != null) {
|
if (!spellController.chooseUse(Outcome.PlayForFree, "Cast another nonland card exiled with " + sourceObject.getLogName() + " without paying that card's mana cost?", source, game)) {
|
||||||
UUID exileZoneId = CardUtil.getExileZoneId(game, source.getSourceId(), sourceObject.getZoneChangeCounter(game));
|
// Pleyer didn't want to cast another spell BUT their original spell was exiled with Knowledge Pool, so return true.
|
||||||
if (exileZoneId == null) {
|
return true;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (spellController.moveCardsToExile(spell, source, game, true, exileZoneId, sourceObject.getIdName())) {
|
|
||||||
if (spellController.chooseUse(Outcome.PlayForFree, "Cast another nonland card exiled with " + sourceObject.getLogName() + " without paying that card's mana cost?", source, game)) {
|
|
||||||
FilterNonlandCard realFilter = filter.copy();
|
|
||||||
realFilter.add(Predicates.not(new CardIdPredicate(spell.getSourceId())));
|
|
||||||
TargetCardInExile target = new TargetCardInExile(0, 1, realFilter, source.getSourceId());
|
|
||||||
target.setNotTarget(true);
|
|
||||||
if (spellController.choose(Outcome.PlayForFree, game.getExile().getExileZone(exileZoneId), target, game)) {
|
|
||||||
Card card = game.getCard(target.getFirstTarget());
|
|
||||||
if (card != null
|
|
||||||
&& !card.getId().equals(spell.getSourceId())) {
|
|
||||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
|
|
||||||
spellController.cast(spellController.chooseAbilityForCast(card, game, true), game, true, new ApprovingObject(source, game));
|
|
||||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false;
|
FilterNonlandCard filter = new FilterNonlandCard("nonland card exiled with Knowledge Pool");
|
||||||
|
filter.add(Predicates.not(new CardIdPredicate(spell.getSourceId())));
|
||||||
|
|
||||||
|
TargetCardInExile target = new TargetCardInExile(0, 1, filter, source.getSourceId());
|
||||||
|
target.setNotTarget(true);
|
||||||
|
|
||||||
|
if (!spellController.choose(Outcome.PlayForFree, game.getExile().getExileZone(exileZoneId), target, game)) {
|
||||||
|
// Player chose to not cast any ofthe spells
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Card card = game.getCard(target.getFirstTarget());
|
||||||
|
if (card == null || card.getId().equals(spell.getSourceId())) { return true; }
|
||||||
|
|
||||||
|
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
|
||||||
|
spellController.cast(spellController.chooseAbilityForCast(card, game, true), game, true, new ApprovingObject(source, game));
|
||||||
|
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public KnowledgePoolEffect2 copy() {
|
public KnowledgePoolExileAndPlayEffect copy() {
|
||||||
return new KnowledgePoolEffect2(this);
|
return new KnowledgePoolExileAndPlayEffect(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,16 +70,15 @@ class PossibilityStormTriggeredAbility extends TriggeredAbilityImpl {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean checkTrigger(GameEvent event, Game game) {
|
public boolean checkTrigger(GameEvent event, Game game) {
|
||||||
if (event.getZone() == Zone.HAND) {
|
if (event.getZone() != Zone.HAND) { return false; }
|
||||||
Spell spell = game.getStack().getSpell(event.getTargetId());
|
|
||||||
if (spell != null) {
|
Spell spell = game.getStack().getSpell(event.getTargetId());
|
||||||
for (Effect effect : this.getEffects()) {
|
if (spell == null) { return false; }
|
||||||
effect.setTargetPointer(new FixedTarget(event.getTargetId()));
|
|
||||||
}
|
for (Effect effect : this.getEffects()) {
|
||||||
return true;
|
effect.setTargetPointer(new FixedTarget(event.getTargetId()));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -107,43 +106,44 @@ class PossibilityStormEffect extends OneShotEffect {
|
||||||
spell = ((Spell) game.getLastKnownInformation(targetPointer.getFirst(game, source), Zone.STACK));
|
spell = ((Spell) game.getLastKnownInformation(targetPointer.getFirst(game, source), Zone.STACK));
|
||||||
noLongerOnStack = true;
|
noLongerOnStack = true;
|
||||||
}
|
}
|
||||||
|
if (spell == null) { return false; }
|
||||||
|
|
||||||
|
Player spellController = game.getPlayer(spell.getControllerId());
|
||||||
|
if (spellController == null) { return false; }
|
||||||
|
|
||||||
MageObject sourceObject = source.getSourceObject(game);
|
MageObject sourceObject = source.getSourceObject(game);
|
||||||
if (sourceObject != null && spell != null) {
|
if (sourceObject == null) { return false; }
|
||||||
Player spellController = game.getPlayer(spell.getControllerId());
|
|
||||||
if (spellController != null) {
|
|
||||||
if (!noLongerOnStack) {
|
|
||||||
spellController.moveCardsToExile(spell, source, game, true, source.getSourceId(), sourceObject.getIdName());
|
|
||||||
}
|
|
||||||
if (spellController.getLibrary().hasCards()) {
|
|
||||||
Library library = spellController.getLibrary();
|
|
||||||
Card card;
|
|
||||||
do {
|
|
||||||
card = library.getFromTop(game);
|
|
||||||
if (card != null) {
|
|
||||||
spellController.moveCardsToExile(card, source, game, true, source.getSourceId(), sourceObject.getIdName());
|
|
||||||
}
|
|
||||||
} while (library.hasCards() && card != null && !sharesType(card, spell.getCardType(game), game));
|
|
||||||
|
|
||||||
if (card != null && sharesType(card, spell.getCardType(game), game)
|
if (!noLongerOnStack) {
|
||||||
&& !card.isLand(game)
|
spellController.moveCardsToExile(spell, source, game, true, source.getSourceId(), sourceObject.getIdName());
|
||||||
&& card.getSpellAbility().canChooseTarget(game, spellController.getId())) {
|
}
|
||||||
if (spellController.chooseUse(Outcome.PlayForFree, "Cast " + card.getLogName() + " without paying cost?", source, game)) {
|
|
||||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
|
|
||||||
spellController.cast(spellController.chooseAbilityForCast(card, game, true), game, true, new ApprovingObject(source, game));
|
|
||||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ExileZone exile = game.getExile().getExileZone(source.getSourceId());
|
if (!spellController.getLibrary().hasCards()) { return true; }
|
||||||
if (exile != null) {
|
Library library = spellController.getLibrary();
|
||||||
spellController.putCardsOnBottomOfLibrary(exile, game, source, false);
|
Card card;
|
||||||
}
|
do {
|
||||||
|
card = library.getFromTop(game);
|
||||||
|
if (card != null) {
|
||||||
|
spellController.moveCardsToExile(card, source, game, true, source.getSourceId(), sourceObject.getIdName());
|
||||||
|
}
|
||||||
|
} while (library.hasCards() && card != null && !sharesType(card, spell.getCardType(game), game));
|
||||||
|
|
||||||
}
|
if (card != null && sharesType(card, spell.getCardType(game), game)
|
||||||
return true;
|
&& !card.isLand(game)
|
||||||
|
&& card.getSpellAbility().canChooseTarget(game, spellController.getId())) {
|
||||||
|
if (spellController.chooseUse(Outcome.PlayForFree, "Cast " + card.getLogName() + " without paying cost?", source, game)) {
|
||||||
|
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
|
||||||
|
spellController.cast(spellController.chooseAbilityForCast(card, game, true), game, true, new ApprovingObject(source, game));
|
||||||
|
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
|
ExileZone exile = game.getExile().getExileZone(source.getSourceId());
|
||||||
|
if (exile != null) {
|
||||||
|
spellController.putCardsOnBottomOfLibrary(exile, game, source, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean sharesType(Card card, List<CardType> cardTypes, Game game) {
|
private boolean sharesType(Card card, List<CardType> cardTypes, Game game) {
|
||||||
|
|
|
@ -27,7 +27,9 @@ public final class ThievesAuction extends CardImpl {
|
||||||
public ThievesAuction(UUID ownerId, CardSetInfo setInfo) {
|
public ThievesAuction(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{R}{R}{R}");
|
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{R}{R}{R}");
|
||||||
|
|
||||||
// Exile all nontoken permanents. Starting with you, each player chooses one of the exiled cards and puts it onto the battlefield tapped under their control. Repeat this process until all cards exiled this way have been chosen.
|
// Exile all nontoken permanents.
|
||||||
|
// Starting with you, each player chooses one of the exiled cards and puts it onto the battlefield tapped under their control.
|
||||||
|
// Repeat this process until all cards exiled this way have been chosen.
|
||||||
this.getSpellAbility().addEffect(new ThievesAuctionEffect());
|
this.getSpellAbility().addEffect(new ThievesAuctionEffect());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,7 +56,7 @@ class ThievesAuctionEffect extends OneShotEffect {
|
||||||
this.staticText = "Exile all nontoken permanents. Starting with you, each player chooses one of the exiled cards and puts it onto the battlefield tapped under their control. Repeat this process until all cards exiled this way have been chosen";
|
this.staticText = "Exile all nontoken permanents. Starting with you, each player chooses one of the exiled cards and puts it onto the battlefield tapped under their control. Repeat this process until all cards exiled this way have been chosen";
|
||||||
}
|
}
|
||||||
|
|
||||||
ThievesAuctionEffect(final ThievesAuctionEffect effect) {
|
private ThievesAuctionEffect(final ThievesAuctionEffect effect) {
|
||||||
super(effect);
|
super(effect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,36 +68,39 @@ class ThievesAuctionEffect extends OneShotEffect {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
if (controller != null) {
|
if (controller == null) { return false; }
|
||||||
// Exile all nontoken permanents.
|
|
||||||
Cards exiledCards = new CardsImpl();
|
// Exile all nontoken permanents.
|
||||||
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) {
|
Cards exiledCards = new CardsImpl();
|
||||||
exiledCards.add(permanent);
|
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) {
|
||||||
controller.moveCardsToExile(permanent, source, game, true, CardUtil.getCardExileZoneId(game, source.getSourceId()), "Thieves' Auction");
|
exiledCards.add(permanent);
|
||||||
}
|
controller.moveCardsToExile(permanent, source, game, true, CardUtil.getCardExileZoneId(game, source.getSourceId()), "Thieves' Auction");
|
||||||
// Starting with you, each player
|
|
||||||
PlayerList playerList = game.getState().getPlayersInRange(controller.getId(), game);
|
|
||||||
Player player = playerList.getCurrent(game);
|
|
||||||
while (player != null && !exiledCards.isEmpty() && !game.hasEnded()) {
|
|
||||||
if (player.canRespond()) {
|
|
||||||
// chooses one of the exiled cards
|
|
||||||
TargetCard target = new TargetCardInExile(new FilterCard());
|
|
||||||
if (player.choose(Outcome.PutCardInPlay, exiledCards, target, game)) {
|
|
||||||
// and puts it onto the battlefield tapped under their control.
|
|
||||||
Card chosenCard = exiledCards.get(target.getFirstTarget(), game);
|
|
||||||
if (chosenCard != null) {
|
|
||||||
player.moveCards(chosenCard, Zone.BATTLEFIELD, source, game, true, false, false, null);
|
|
||||||
}
|
|
||||||
exiledCards.remove(chosenCard);
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Repeat this process until all cards exiled this way have been chosen.
|
|
||||||
player = playerList.getNext(game, false);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
|
// Starting with you, each player
|
||||||
|
PlayerList playerList = game.getState().getPlayersInRange(controller.getId(), game);
|
||||||
|
Player player = playerList.getCurrent(game);
|
||||||
|
while (player != null && !exiledCards.isEmpty() && !game.hasEnded()) {
|
||||||
|
if (!player.canRespond()) { continue; }
|
||||||
|
|
||||||
|
// chooses one of the exiled cards
|
||||||
|
TargetCard target = new TargetCardInExile(new FilterCard());
|
||||||
|
if (player.choose(Outcome.PutCardInPlay, exiledCards, target, game)) {
|
||||||
|
// and puts it onto the battlefield tapped under their control.
|
||||||
|
Card chosenCard = exiledCards.get(target.getFirstTarget(), game);
|
||||||
|
if (chosenCard != null) {
|
||||||
|
player.moveCards(chosenCard, Zone.BATTLEFIELD, source, game, true, false, false, null);
|
||||||
|
}
|
||||||
|
exiledCards.remove(chosenCard);
|
||||||
|
} else {
|
||||||
|
// TODO Why does this break?
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Repeat this process until all cards exiled this way have been chosen.
|
||||||
|
player = playerList.getNext(game, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
package org.mage.test.cards.single.dis;
|
||||||
|
|
||||||
|
import mage.constants.PhaseStep;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||||
|
|
||||||
|
public class AzoriusAethermageTest extends CardTestPlayerBase {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whenever you bounce a permanent (tokens included) you may pay {1}, if you do, draw a card
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testBouncedLand() {
|
||||||
|
/*
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3); // Used for paying ability cost
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Island", 2*3);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Toggo, Goblin Weaponsmith");
|
||||||
|
addCard(Zone.HAND, playerA, "Boomerang",3);
|
||||||
|
|
||||||
|
// Permanents to bounce
|
||||||
|
addCard(Zone.HAND, playerA, "Plains", 1);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Azorius Aethermage");
|
||||||
|
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Plains"); // Create a Rock token with Toggo
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Boomerang", "Plains");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA, true);
|
||||||
|
setChoice(playerA, "Yes");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Boomerang", "Rock");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA, true);
|
||||||
|
setChoice(playerA, "Yes");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Boomerang", "Azorius Aethermage");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA, true);
|
||||||
|
setChoice(playerA, "Yes");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertAllCommandsUsed();
|
||||||
|
|
||||||
|
// 3 cards bounced: plains, token, and aethermage, but the token never makes it to the hand -> +2 cards in hand
|
||||||
|
// 3 cards drawn -> +3 cards in hand
|
||||||
|
assertHandCount(playerA, (1+1) + (1) + (1+1));
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,108 @@
|
||||||
|
package org.mage.test.cards.single.hou;
|
||||||
|
|
||||||
|
import mage.constants.PhaseStep;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||||
|
|
||||||
|
|
||||||
|
public class AbandonedSarcophagusTest extends CardTestPlayerBase {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* You may cast non-land card with cycling from your graveyard
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void castNonLandFromGraveyard() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Abandoned Sarcophagus");
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Plains", 3);
|
||||||
|
addCard(Zone.GRAVEYARD, playerA, "Astral Drift"); // {2}{W} Enchantment
|
||||||
|
addCard(Zone.GRAVEYARD, playerA, "Ash Barrens"); // Land
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Astral Drift");
|
||||||
|
// Can't play lands with this ability
|
||||||
|
checkPlayableAbility("before play", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Play Ash Barrens", false);
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertAllCommandsUsed();
|
||||||
|
|
||||||
|
assertPermanentCount(playerA, "Astral Drift", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* You can only cast the card from the graveyard, you CANNOT cycle it
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void cantCycleFromGraveyard() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Abandoned Sarcophagus");
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Plains", 3);
|
||||||
|
addCard(Zone.GRAVEYARD, playerA, "Astral Drift"); // {2}{W} Enchantment
|
||||||
|
addCard(Zone.GRAVEYARD, playerA, "Ash Barrens"); // Land
|
||||||
|
|
||||||
|
checkPlayableAbility("before play", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cycling", false);
|
||||||
|
checkPlayableAbility("before play", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Basic landcycling", false);
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertAllCommandsUsed();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When a card with cycling is cycled it still goes to the graveyard
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void cycledCardGoesToGraveyard() {
|
||||||
|
addCard(Zone.LIBRARY, playerA, "Forest", 5);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Abandoned Sarcophagus");
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Plains", 4);
|
||||||
|
addCard(Zone.HAND, playerA, "Astral Drift"); // {2}{W} Enchantment
|
||||||
|
addCard(Zone.HAND, playerA, "Ash Barrens"); // Land
|
||||||
|
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Basic landcycling");
|
||||||
|
addTarget(playerA, "Forest");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cycling");
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertAllCommandsUsed();
|
||||||
|
|
||||||
|
assertHandCount(playerA, 2);
|
||||||
|
assertGraveyardCount(playerA, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When a card goes to the graveyard and it WAS NOT cycled, it gets exiled
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void nonCycledCardGoesToExile() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Abandoned Sarcophagus");
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Plains", 4);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Forest", 6);
|
||||||
|
addCard(Zone.HAND, playerA, "Astral Drift"); // {2}{W} Enchantment
|
||||||
|
addCard(Zone.HAND, playerA, "Ash Barrens"); // Land
|
||||||
|
addCard(Zone.HAND, playerA, "Beast Within", 2);
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Astral Drift");
|
||||||
|
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Ash Barrens");
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Beast Within", "Astral Drift");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Beast Within", "Ash Barrens");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertAllCommandsUsed();
|
||||||
|
|
||||||
|
assertExileCount(playerA, 2);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue