mirror of
https://github.com/correl/mage.git
synced 2024-11-15 03:00:16 +00:00
Rework Spell.counter using PutCards and reimplement Desertion. Fixes #9299
This commit is contained in:
parent
cbe610d339
commit
e40934921f
27 changed files with 124 additions and 251 deletions
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
package mage.cards.a;
|
package mage.cards.a;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
@ -7,7 +6,7 @@ import mage.abilities.keyword.AffinityForArtifactsAbility;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Zone;
|
import mage.constants.PutCards;
|
||||||
import mage.target.TargetSpell;
|
import mage.target.TargetSpell;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -23,7 +22,7 @@ public final class AssertAuthority extends CardImpl {
|
||||||
// Affinity for artifacts
|
// Affinity for artifacts
|
||||||
this.addAbility(new AffinityForArtifactsAbility());
|
this.addAbility(new AffinityForArtifactsAbility());
|
||||||
// Counter target spell. If that spell is countered this way, exile it instead of putting it into its owner's graveyard.
|
// Counter target spell. If that spell is countered this way, exile it instead of putting it into its owner's graveyard.
|
||||||
this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(Zone.EXILED));
|
this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(PutCards.EXILED));
|
||||||
this.getSpellAbility().addTarget(new TargetSpell());
|
this.getSpellAbility().addTarget(new TargetSpell());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
|
import mage.constants.PutCards;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
import mage.counters.CounterType;
|
import mage.counters.CounterType;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
|
@ -65,7 +66,7 @@ class DelayEffect extends OneShotEffect {
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
Spell spell = game.getStack().getSpell(getTargetPointer().getFirst(game, source));
|
Spell spell = game.getStack().getSpell(getTargetPointer().getFirst(game, source));
|
||||||
if (controller != null && spell != null) {
|
if (controller != null && spell != null) {
|
||||||
Effect effect = new CounterTargetWithReplacementEffect(Zone.EXILED);
|
Effect effect = new CounterTargetWithReplacementEffect(PutCards.EXILED);
|
||||||
effect.setTargetPointer(targetPointer);
|
effect.setTargetPointer(targetPointer);
|
||||||
Card card = game.getCard(spell.getSourceId());
|
Card card = game.getCard(spell.getSourceId());
|
||||||
if (card != null && effect.apply(game, source) && game.getState().getZone(card.getId()) == Zone.EXILED) {
|
if (card != null && effect.apply(game, source) && game.getState().getZone(card.getId()) == Zone.EXILED) {
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
package mage.cards.d;
|
package mage.cards.d;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
@ -6,7 +5,7 @@ import mage.abilities.effects.common.CounterTargetWithReplacementEffect;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Zone;
|
import mage.constants.PutCards;
|
||||||
import mage.filter.common.FilterCreatureSpell;
|
import mage.filter.common.FilterCreatureSpell;
|
||||||
import mage.target.TargetSpell;
|
import mage.target.TargetSpell;
|
||||||
|
|
||||||
|
@ -20,7 +19,7 @@ public final class DenyExistence extends CardImpl {
|
||||||
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{U}");
|
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{U}");
|
||||||
|
|
||||||
// Counter target creature spell. If that spell is countered this way, exile it instead of putting it into its owner's graveyard.
|
// Counter target creature spell. If that spell is countered this way, exile it instead of putting it into its owner's graveyard.
|
||||||
this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(Zone.EXILED));
|
this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(PutCards.EXILED));
|
||||||
this.getSpellAbility().addTarget(new TargetSpell(new FilterCreatureSpell()));
|
this.getSpellAbility().addTarget(new TargetSpell(new FilterCreatureSpell()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ import mage.abilities.effects.common.CounterTargetWithReplacementEffect;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Zone;
|
import mage.constants.PutCards;
|
||||||
import mage.filter.FilterSpell;
|
import mage.filter.FilterSpell;
|
||||||
import mage.filter.predicate.Predicates;
|
import mage.filter.predicate.Predicates;
|
||||||
import mage.target.TargetSpell;
|
import mage.target.TargetSpell;
|
||||||
|
@ -29,7 +29,7 @@ public final class DenyTheDivine extends CardImpl {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{U}");
|
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{U}");
|
||||||
|
|
||||||
// Counter target creature or enchantment spell. If that spell is countered this way, exile it instead of putting it into its owner's graveyard.
|
// Counter target creature or enchantment spell. If that spell is countered this way, exile it instead of putting it into its owner's graveyard.
|
||||||
this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(Zone.EXILED));
|
this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(PutCards.EXILED));
|
||||||
this.getSpellAbility().addTarget(new TargetSpell(filter));
|
this.getSpellAbility().addTarget(new TargetSpell(filter));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,38 +1,30 @@
|
||||||
package mage.cards.d;
|
package mage.cards.d;
|
||||||
|
|
||||||
import mage.MageObject;
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.SimpleStaticAbility;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.abilities.effects.ReplacementEffectImpl;
|
|
||||||
import mage.abilities.effects.common.CounterTargetEffect;
|
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Duration;
|
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
import mage.constants.Zone;
|
import mage.constants.PutCards;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.GameEvent;
|
import mage.game.stack.StackObject;
|
||||||
import mage.game.events.ZoneChangeEvent;
|
|
||||||
import mage.target.TargetSpell;
|
import mage.target.TargetSpell;
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Quercitron
|
* @author awjackson
|
||||||
*/
|
*/
|
||||||
public final class Desertion extends CardImpl {
|
public final class Desertion extends CardImpl {
|
||||||
|
|
||||||
public Desertion(UUID ownerId, CardSetInfo setInfo) {
|
public Desertion(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{U}{U}");
|
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{U}{U}");
|
||||||
|
|
||||||
// Counter target spell.
|
// Counter target spell. If an artifact or creature spell is countered this way,
|
||||||
this.getSpellAbility().addEffect(new CounterTargetEffect());
|
// put that card onto the battlefield under your control instead of into its owner's graveyard.
|
||||||
|
this.getSpellAbility().addEffect(new DesertionEffect());
|
||||||
this.getSpellAbility().addTarget(new TargetSpell());
|
this.getSpellAbility().addTarget(new TargetSpell());
|
||||||
|
|
||||||
// If an artifact or creature spell is countered this way, put that card onto the battlefield under your control instead of into its owner's graveyard.
|
|
||||||
this.addAbility(new SimpleStaticAbility(Zone.STACK, new DesertionReplacementEffect()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Desertion(final Desertion card) {
|
private Desertion(final Desertion card) {
|
||||||
|
@ -45,48 +37,30 @@ public final class Desertion extends CardImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class DesertionReplacementEffect extends ReplacementEffectImpl {
|
class DesertionEffect extends OneShotEffect {
|
||||||
|
|
||||||
DesertionReplacementEffect() {
|
public DesertionEffect() {
|
||||||
super(Duration.WhileOnStack, Outcome.PutCardInPlay);
|
super(Outcome.Detriment);
|
||||||
staticText = "If an artifact or creature spell is countered this way, put that card onto the battlefield under your control instead of into its owner's graveyard";
|
staticText = "counter target spell. If an artifact or creature spell is countered this way, put that card onto the battlefield under your control instead of into its owner's graveyard";
|
||||||
}
|
}
|
||||||
|
|
||||||
private DesertionReplacementEffect(final DesertionReplacementEffect effect) {
|
private DesertionEffect(final DesertionEffect effect) {
|
||||||
super(effect);
|
super(effect);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DesertionReplacementEffect copy() {
|
public DesertionEffect copy() {
|
||||||
return new DesertionReplacementEffect(this);
|
return new DesertionEffect(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
return true;
|
StackObject spell = game.getStack().getStackObject(targetPointer.getFirst(game, source));
|
||||||
}
|
if (spell == null) {
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
|
||||||
ZoneChangeEvent zce = (ZoneChangeEvent) event;
|
|
||||||
zce.setToZone(Zone.BATTLEFIELD);
|
|
||||||
zce.setPlayerId(source.getControllerId());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checksEventType(GameEvent event, Game game) {
|
|
||||||
return event.getType() == GameEvent.EventType.ZONE_CHANGE;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
|
||||||
if (!Objects.equals(event.getSourceId(), source.getSourceId())
|
|
||||||
|| !(((ZoneChangeEvent) event).getToZone() == Zone.GRAVEYARD)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
MageObject mageObject = game.getObject(event.getTargetId());
|
return game.getStack().counter(spell.getId(), source, game,
|
||||||
return mageObject != null
|
spell.isArtifact() || spell.isCreature() ? PutCards.BATTLEFIELD : PutCards.GRAVEYARD
|
||||||
&& (mageObject.isArtifact(game) || mageObject.isCreature(game));
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ import mage.cards.Cards;
|
||||||
import mage.cards.CardsImpl;
|
import mage.cards.CardsImpl;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
import mage.constants.Zone;
|
import mage.constants.PutCards;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.target.TargetSpell;
|
import mage.target.TargetSpell;
|
||||||
|
@ -29,7 +29,7 @@ public final class DeviousCoverUp extends CardImpl {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{U}{U}");
|
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{U}{U}");
|
||||||
|
|
||||||
// Counter target spell. If that spell is countered this way, exile it instead of putting it into its owner's graveyard.
|
// Counter target spell. If that spell is countered this way, exile it instead of putting it into its owner's graveyard.
|
||||||
this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(Zone.EXILED));
|
this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(PutCards.EXILED));
|
||||||
this.getSpellAbility().addTarget(new TargetSpell());
|
this.getSpellAbility().addTarget(new TargetSpell());
|
||||||
|
|
||||||
// You may shuffle up to four target cards from your graveyard into your library.
|
// You may shuffle up to four target cards from your graveyard into your library.
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
package mage.cards.d;
|
package mage.cards.d;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
@ -6,7 +5,7 @@ import mage.abilities.effects.common.CounterTargetWithReplacementEffect;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Zone;
|
import mage.constants.PutCards;
|
||||||
import mage.target.TargetSpell;
|
import mage.target.TargetSpell;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -19,7 +18,7 @@ public final class Dissipate extends CardImpl {
|
||||||
|
|
||||||
|
|
||||||
// Counter target spell. If that spell is countered this way, exile it instead of putting it into its owner's graveyard.
|
// Counter target spell. If that spell is countered this way, exile it instead of putting it into its owner's graveyard.
|
||||||
this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(Zone.EXILED));
|
this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(PutCards.EXILED));
|
||||||
this.getSpellAbility().addTarget(new TargetSpell());
|
this.getSpellAbility().addTarget(new TargetSpell());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
package mage.cards.f;
|
package mage.cards.f;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
@ -7,7 +6,7 @@ import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
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.PutCards;
|
||||||
import mage.filter.FilterSpell;
|
import mage.filter.FilterSpell;
|
||||||
import mage.filter.predicate.Predicates;
|
import mage.filter.predicate.Predicates;
|
||||||
import mage.target.TargetSpell;
|
import mage.target.TargetSpell;
|
||||||
|
@ -30,7 +29,7 @@ public final class FaerieTrickery extends CardImpl {
|
||||||
|
|
||||||
|
|
||||||
// Counter target non-Faerie spell. If that spell is countered this way, exile it instead of putting it into its owner's graveyard.
|
// Counter target non-Faerie spell. If that spell is countered this way, exile it instead of putting it into its owner's graveyard.
|
||||||
this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(Zone.EXILED));
|
this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(PutCards.EXILED));
|
||||||
this.getSpellAbility().addTarget(new TargetSpell(filter));
|
this.getSpellAbility().addTarget(new TargetSpell(filter));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ import mage.abilities.hint.common.NotMyTurnHint;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Zone;
|
import mage.constants.PutCards;
|
||||||
import mage.filter.StaticFilters;
|
import mage.filter.StaticFilters;
|
||||||
import mage.filter.common.FilterOwnedCard;
|
import mage.filter.common.FilterOwnedCard;
|
||||||
import mage.filter.predicate.mageobject.ColorPredicate;
|
import mage.filter.predicate.mageobject.ColorPredicate;
|
||||||
|
@ -40,7 +40,7 @@ public final class ForceOfNegation extends CardImpl {
|
||||||
).addHint(NotMyTurnHint.instance));
|
).addHint(NotMyTurnHint.instance));
|
||||||
|
|
||||||
// Counter target noncreature spell. If that spell is countered this way, exile it instead of putting it into its owner's graveyard.
|
// Counter target noncreature spell. If that spell is countered this way, exile it instead of putting it into its owner's graveyard.
|
||||||
this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(Zone.EXILED));
|
this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(PutCards.EXILED));
|
||||||
this.getSpellAbility().addTarget(new TargetSpell(StaticFilters.FILTER_SPELL_NON_CREATURE));
|
this.getSpellAbility().addTarget(new TargetSpell(StaticFilters.FILTER_SPELL_NON_CREATURE));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
package mage.cards.h;
|
package mage.cards.h;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
@ -6,8 +5,7 @@ import mage.abilities.effects.common.CounterTargetWithReplacementEffect;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Zone;
|
import mage.constants.PutCards;
|
||||||
import mage.constants.ZoneDetail;
|
|
||||||
import mage.target.TargetSpell;
|
import mage.target.TargetSpell;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -20,7 +18,7 @@ public final class Hinder extends CardImpl {
|
||||||
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{U}{U}");
|
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{U}{U}");
|
||||||
|
|
||||||
// Counter target spell. If that spell is countered this way, put that card on the top or bottom of its owner's library instead of into that player's graveyard.
|
// Counter target spell. If that spell is countered this way, put that card on the top or bottom of its owner's library instead of into that player's graveyard.
|
||||||
this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(Zone.LIBRARY, ZoneDetail.CHOOSE));
|
this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(PutCards.TOP_OR_BOTTOM));
|
||||||
this.getSpellAbility().addTarget(new TargetSpell());
|
this.getSpellAbility().addTarget(new TargetSpell());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.ComparisonType;
|
import mage.constants.ComparisonType;
|
||||||
import mage.constants.Zone;
|
import mage.constants.PutCards;
|
||||||
import mage.filter.common.FilterCreatureSpell;
|
import mage.filter.common.FilterCreatureSpell;
|
||||||
import mage.filter.predicate.mageobject.ManaValuePredicate;
|
import mage.filter.predicate.mageobject.ManaValuePredicate;
|
||||||
import mage.target.TargetSpell;
|
import mage.target.TargetSpell;
|
||||||
|
@ -32,7 +32,7 @@ public final class HorriblyAwry extends CardImpl {
|
||||||
this.addAbility(new DevoidAbility(this.color));
|
this.addAbility(new DevoidAbility(this.color));
|
||||||
|
|
||||||
// Counter target creature spell with converted mana cost 4 or less. If that spell is countered this way, exile it instead of putting it into its owner's graveyard.
|
// Counter target creature spell with converted mana cost 4 or less. If that spell is countered this way, exile it instead of putting it into its owner's graveyard.
|
||||||
this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(Zone.EXILED));
|
this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(PutCards.EXILED));
|
||||||
this.getSpellAbility().addTarget(new TargetSpell(filter));
|
this.getSpellAbility().addTarget(new TargetSpell(filter));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -73,7 +73,7 @@ class KheruSpellsnatcherEffect extends OneShotEffect {
|
||||||
MageObject sourceObject = source.getSourceObject(game);
|
MageObject sourceObject = source.getSourceObject(game);
|
||||||
StackObject stackObject = game.getStack().getStackObject(targetPointer.getFirst(game, source));
|
StackObject stackObject = game.getStack().getStackObject(targetPointer.getFirst(game, source));
|
||||||
if (stackObject != null && sourceObject != null
|
if (stackObject != null && sourceObject != null
|
||||||
&& game.getStack().counter(targetPointer.getFirst(game, source), source, game, Zone.EXILED, false, ZoneDetail.NONE)) {
|
&& game.getStack().counter(targetPointer.getFirst(game, source), source, game, PutCards.EXILED)) {
|
||||||
if (!stackObject.isCopy()) {
|
if (!stackObject.isCopy()) {
|
||||||
MageObject card = game.getObject(stackObject.getSourceId());
|
MageObject card = game.getObject(stackObject.getSourceId());
|
||||||
if (card instanceof Card) {
|
if (card instanceof Card) {
|
||||||
|
|
|
@ -6,8 +6,7 @@ import mage.abilities.effects.common.CounterTargetWithReplacementEffect;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Zone;
|
import mage.constants.PutCards;
|
||||||
import mage.constants.ZoneDetail;
|
|
||||||
import mage.target.TargetSpell;
|
import mage.target.TargetSpell;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -20,7 +19,7 @@ public final class LapseOfCertainty extends CardImpl {
|
||||||
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{W}");
|
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{W}");
|
||||||
|
|
||||||
// Counter target spell. If that spell is countered this way, put it on top of its owner's library instead of into that player's graveyard.
|
// Counter target spell. If that spell is countered this way, put it on top of its owner's library instead of into that player's graveyard.
|
||||||
this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(Zone.LIBRARY, ZoneDetail.TOP));
|
this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(PutCards.TOP_ANY));
|
||||||
this.getSpellAbility().addTarget(new TargetSpell());
|
this.getSpellAbility().addTarget(new TargetSpell());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.ComparisonType;
|
import mage.constants.ComparisonType;
|
||||||
import mage.constants.Zone;
|
import mage.constants.PutCards;
|
||||||
import mage.filter.FilterSpell;
|
import mage.filter.FilterSpell;
|
||||||
import mage.filter.predicate.mageobject.ManaValuePredicate;
|
import mage.filter.predicate.mageobject.ManaValuePredicate;
|
||||||
import mage.target.TargetSpell;
|
import mage.target.TargetSpell;
|
||||||
|
@ -28,7 +28,7 @@ public final class Liquify extends CardImpl {
|
||||||
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{U}");
|
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{U}");
|
||||||
|
|
||||||
// Counter target spell with converted mana cost 3 or less. If that spell is countered this way, exile it instead of putting it into its owner's graveyard.
|
// Counter target spell with converted mana cost 3 or less. If that spell is countered this way, exile it instead of putting it into its owner's graveyard.
|
||||||
this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(Zone.EXILED));
|
this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(PutCards.EXILED));
|
||||||
this.getSpellAbility().addTarget(new TargetSpell(filter));
|
this.getSpellAbility().addTarget(new TargetSpell(filter));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,7 @@ import mage.abilities.effects.common.CounterTargetWithReplacementEffect;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Zone;
|
import mage.constants.PutCards;
|
||||||
import mage.constants.ZoneDetail;
|
|
||||||
import mage.target.TargetSpell;
|
import mage.target.TargetSpell;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -20,7 +19,7 @@ public final class MemoryLapse extends CardImpl {
|
||||||
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{U}");
|
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{U}");
|
||||||
|
|
||||||
// Counter target spell. If that spell is countered this way, put it on top of its owner's library instead of into that player's graveyard.
|
// Counter target spell. If that spell is countered this way, put it on top of its owner's library instead of into that player's graveyard.
|
||||||
this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(Zone.LIBRARY, ZoneDetail.TOP));
|
this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(PutCards.TOP_ANY));
|
||||||
this.getSpellAbility().addTarget(new TargetSpell());
|
this.getSpellAbility().addTarget(new TargetSpell());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ import mage.abilities.effects.keyword.ScryEffect;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Zone;
|
import mage.constants.PutCards;
|
||||||
import mage.filter.FilterSpell;
|
import mage.filter.FilterSpell;
|
||||||
import mage.filter.predicate.Predicates;
|
import mage.filter.predicate.Predicates;
|
||||||
import mage.target.TargetSpell;
|
import mage.target.TargetSpell;
|
||||||
|
@ -30,7 +30,7 @@ public final class NoEscape extends CardImpl {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{U}");
|
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{U}");
|
||||||
|
|
||||||
// Counter target creature or planeswalker spell. If that spell is countered this way, exile it instead of putting it into its owner's graveyard.
|
// Counter target creature or planeswalker spell. If that spell is countered this way, exile it instead of putting it into its owner's graveyard.
|
||||||
this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(Zone.EXILED));
|
this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(PutCards.EXILED));
|
||||||
this.getSpellAbility().addTarget(new TargetSpell(filter));
|
this.getSpellAbility().addTarget(new TargetSpell(filter));
|
||||||
|
|
||||||
// Scry 1.
|
// Scry 1.
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
package mage.cards.r;
|
package mage.cards.r;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
@ -7,7 +6,7 @@ import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Zone;
|
import mage.constants.PutCards;
|
||||||
import mage.target.TargetSpell;
|
import mage.target.TargetSpell;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -19,12 +18,11 @@ public final class Remand extends CardImpl {
|
||||||
public Remand(UUID ownerId, CardSetInfo setInfo) {
|
public Remand(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{U}");
|
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{U}");
|
||||||
|
|
||||||
|
|
||||||
// Counter target spell. If that spell is countered this way, put it into its owner's hand instead of into that player's graveyard.
|
// Counter target spell. If that spell is countered this way, put it into its owner's hand instead of into that player's graveyard.
|
||||||
this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(Zone.HAND));
|
this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(PutCards.HAND));
|
||||||
this.getSpellAbility().addTarget(new TargetSpell());
|
this.getSpellAbility().addTarget(new TargetSpell());
|
||||||
// Draw a card.
|
// Draw a card.
|
||||||
this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1));
|
this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1).concatBy("<br>"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Remand(final Remand card) {
|
private Remand(final Remand card) {
|
||||||
|
|
|
@ -1,18 +1,12 @@
|
||||||
|
|
||||||
package mage.cards.s;
|
package mage.cards.s;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.effects.common.CounterTargetWithReplacementEffect;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
|
||||||
import mage.abilities.effects.common.ReturnToLibrarySpellEffect;
|
import mage.abilities.effects.common.ReturnToLibrarySpellEffect;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Outcome;
|
import mage.constants.PutCards;
|
||||||
import mage.constants.Zone;
|
|
||||||
import mage.constants.ZoneDetail;
|
|
||||||
import mage.game.Game;
|
|
||||||
import mage.players.Player;
|
|
||||||
import mage.target.TargetSpell;
|
import mage.target.TargetSpell;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -24,9 +18,11 @@ public final class SpellCrumple extends CardImpl {
|
||||||
public SpellCrumple(UUID ownerId, CardSetInfo setInfo) {
|
public SpellCrumple(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{U}{U}");
|
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{U}{U}");
|
||||||
|
|
||||||
// Counter target spell. If that spell is countered this way, put it on the bottom of its owner's library instead of into that player's graveyard. Put Spell Crumple on the bottom of its owner's library.
|
// Counter target spell. If that spell is countered this way, put it on the
|
||||||
|
// bottom of its owner's library instead of into that player's graveyard.
|
||||||
|
// Put Spell Crumple on the bottom of its owner's library.
|
||||||
this.getSpellAbility().addTarget(new TargetSpell());
|
this.getSpellAbility().addTarget(new TargetSpell());
|
||||||
this.getSpellAbility().addEffect(new SpellCrumpleCounterEffect());
|
this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(PutCards.BOTTOM_ANY));
|
||||||
this.getSpellAbility().addEffect(new ReturnToLibrarySpellEffect(false));
|
this.getSpellAbility().addEffect(new ReturnToLibrarySpellEffect(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,29 +35,3 @@ public final class SpellCrumple extends CardImpl {
|
||||||
return new SpellCrumple(this);
|
return new SpellCrumple(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SpellCrumpleCounterEffect extends OneShotEffect {
|
|
||||||
|
|
||||||
public SpellCrumpleCounterEffect() {
|
|
||||||
super(Outcome.Benefit);
|
|
||||||
this.staticText = "Counter target spell. If that spell is countered this way, put it on the bottom of its owner's library instead of into that player's graveyard";
|
|
||||||
}
|
|
||||||
|
|
||||||
public SpellCrumpleCounterEffect(final SpellCrumpleCounterEffect effect) {
|
|
||||||
super(effect);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SpellCrumpleCounterEffect copy() {
|
|
||||||
return new SpellCrumpleCounterEffect(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean apply(Game game, Ability source) {
|
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
|
||||||
if (controller != null) {
|
|
||||||
return game.getStack().counter(targetPointer.getFirst(game, source), source, game, Zone.LIBRARY, false, ZoneDetail.BOTTOM);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -9,12 +9,7 @@ import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffec
|
||||||
import mage.cards.Card;
|
import mage.cards.Card;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.*;
|
||||||
import mage.constants.Duration;
|
|
||||||
import mage.constants.Outcome;
|
|
||||||
import mage.constants.TargetController;
|
|
||||||
import mage.constants.Zone;
|
|
||||||
import mage.constants.ZoneDetail;
|
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.stack.Spell;
|
import mage.game.stack.Spell;
|
||||||
import mage.game.stack.StackObject;
|
import mage.game.stack.StackObject;
|
||||||
|
@ -68,7 +63,7 @@ class SpelljackEffect extends OneShotEffect {
|
||||||
if (controller != null) {
|
if (controller != null) {
|
||||||
UUID targetId = targetPointer.getFirst(game, source);
|
UUID targetId = targetPointer.getFirst(game, source);
|
||||||
StackObject stackObject = game.getStack().getStackObject(targetId);
|
StackObject stackObject = game.getStack().getStackObject(targetId);
|
||||||
if (stackObject != null && game.getStack().counter(targetId, source, game, Zone.EXILED, false, ZoneDetail.NONE)) {
|
if (stackObject != null && game.getStack().counter(targetId, source, game, PutCards.EXILED)) {
|
||||||
Card card = ((Spell) stackObject).getCard();
|
Card card = ((Spell) stackObject).getCard();
|
||||||
if (card != null) {
|
if (card != null) {
|
||||||
ContinuousEffect effect = new PlayFromNotOwnHandZoneTargetEffect(Zone.EXILED, TargetController.YOU, Duration.Custom, true);
|
ContinuousEffect effect = new PlayFromNotOwnHandZoneTargetEffect(Zone.EXILED, TargetController.YOU, Duration.Custom, true);
|
||||||
|
|
|
@ -7,7 +7,7 @@ import mage.abilities.keyword.DevoidAbility;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Zone;
|
import mage.constants.PutCards;
|
||||||
import mage.target.TargetSpell;
|
import mage.target.TargetSpell;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -23,7 +23,7 @@ public final class VoidShatter extends CardImpl {
|
||||||
this.addAbility(new DevoidAbility(this.color));
|
this.addAbility(new DevoidAbility(this.color));
|
||||||
|
|
||||||
// Counter target spell. If that spell is countered this way, exile it instead of putting it into its owner's graveyard.
|
// Counter target spell. If that spell is countered this way, exile it instead of putting it into its owner's graveyard.
|
||||||
this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(Zone.EXILED));
|
this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(PutCards.EXILED));
|
||||||
this.getSpellAbility().addTarget(new TargetSpell());
|
this.getSpellAbility().addTarget(new TargetSpell());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
|
|
||||||
package mage.abilities.effects.common;
|
package mage.abilities.effects.common;
|
||||||
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.Mode;
|
import mage.abilities.Mode;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
import mage.constants.Zone;
|
import mage.constants.PutCards;
|
||||||
import mage.constants.ZoneDetail;
|
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
|
|
||||||
|
@ -15,29 +13,20 @@ import mage.players.Player;
|
||||||
*/
|
*/
|
||||||
public class CounterTargetWithReplacementEffect extends OneShotEffect {
|
public class CounterTargetWithReplacementEffect extends OneShotEffect {
|
||||||
|
|
||||||
private Zone targetZone;
|
private final PutCards putIt;
|
||||||
private ZoneDetail zoneDetail;
|
|
||||||
|
|
||||||
public CounterTargetWithReplacementEffect(Zone targetZone) {
|
|
||||||
this(targetZone, ZoneDetail.NONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param targetZone
|
* @param putIt
|
||||||
* @param zoneDetail use to specify when moving card to library <ul><li>true
|
|
||||||
* = put on top</li><li>false = put on bottom</li></ul>
|
|
||||||
*/
|
*/
|
||||||
public CounterTargetWithReplacementEffect(Zone targetZone, ZoneDetail zoneDetail) {
|
public CounterTargetWithReplacementEffect(PutCards putIt) {
|
||||||
super(Outcome.Detriment);
|
super(Outcome.Detriment);
|
||||||
this.targetZone = targetZone;
|
this.putIt = putIt;
|
||||||
this.zoneDetail = zoneDetail;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public CounterTargetWithReplacementEffect(final CounterTargetWithReplacementEffect effect) {
|
public CounterTargetWithReplacementEffect(final CounterTargetWithReplacementEffect effect) {
|
||||||
super(effect);
|
super(effect);
|
||||||
this.targetZone = effect.targetZone;
|
this.putIt = effect.putIt;
|
||||||
this.zoneDetail = effect.zoneDetail;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -49,41 +38,26 @@ public class CounterTargetWithReplacementEffect extends OneShotEffect {
|
||||||
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 game.getStack().counter(targetPointer.getFirst(game, source), source, game, targetZone, false, zoneDetail);
|
return game.getStack().counter(getTargetPointer().getFirst(game, source), source, game, putIt);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getText(Mode mode) {
|
public String getText(Mode mode) {
|
||||||
StringBuilder sb = new StringBuilder("Counter target ");
|
if (staticText != null && !staticText.isEmpty()) {
|
||||||
sb.append(mode.getTargets().get(0).getTargetName());
|
return staticText;
|
||||||
|
}
|
||||||
|
StringBuilder sb = new StringBuilder("counter ");
|
||||||
|
sb.append(getTargetPointer().describeTargets(mode.getTargets(), "it"));
|
||||||
sb.append(". If that spell is countered this way, ");
|
sb.append(". If that spell is countered this way, ");
|
||||||
if (targetZone == Zone.EXILED) {
|
if (putIt == PutCards.EXILED) {
|
||||||
sb.append("exile it instead of putting it into its owner's graveyard");
|
sb.append("exile it instead of putting it into its owner's graveyard");
|
||||||
|
} else {
|
||||||
|
sb.append(putIt == PutCards.TOP_OR_BOTTOM ? "put that card " : "put it ");
|
||||||
|
sb.append(putIt.getMessage(true, false));
|
||||||
|
sb.append(" instead of into that player's graveyard");
|
||||||
}
|
}
|
||||||
if (targetZone == Zone.HAND) {
|
|
||||||
sb.append("put it into its owner's hand instead of into that player's graveyard");
|
|
||||||
}
|
|
||||||
if (targetZone == Zone.LIBRARY) {
|
|
||||||
sb.append("put it on ");
|
|
||||||
switch (zoneDetail) {
|
|
||||||
case BOTTOM:
|
|
||||||
sb.append("the bottom");
|
|
||||||
break;
|
|
||||||
case TOP:
|
|
||||||
sb.append("top");
|
|
||||||
break;
|
|
||||||
case CHOOSE:
|
|
||||||
sb.append("top or bottom");
|
|
||||||
break;
|
|
||||||
case NONE:
|
|
||||||
sb.append("<not allowed value>");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
sb.append(" of its owner's library instead of into that player's graveyard");
|
|
||||||
}
|
|
||||||
|
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,8 +7,7 @@ import mage.abilities.costs.mana.ManaCost;
|
||||||
import mage.abilities.dynamicvalue.DynamicValue;
|
import mage.abilities.dynamicvalue.DynamicValue;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
import mage.constants.Zone;
|
import mage.constants.PutCards;
|
||||||
import mage.constants.ZoneDetail;
|
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.stack.StackObject;
|
import mage.game.stack.StackObject;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
|
@ -88,11 +87,7 @@ public class CounterUnlessPaysEffect extends OneShotEffect {
|
||||||
if (!(player.chooseUse(Outcome.Benefit, message, source, game)
|
if (!(player.chooseUse(Outcome.Benefit, message, source, game)
|
||||||
&& costToPay.pay(source, game, source, spell.getControllerId(), false, null))) {
|
&& costToPay.pay(source, game, source, spell.getControllerId(), false, null))) {
|
||||||
game.informPlayers(player.getLogName() + " chooses not to pay " + costValueMessage + " to prevent the counter effect");
|
game.informPlayers(player.getLogName() + " chooses not to pay " + costValueMessage + " to prevent the counter effect");
|
||||||
if (exile) {
|
game.getStack().counter(spell.getId(), source, game, exile ? PutCards.EXILED : PutCards.GRAVEYARD);
|
||||||
game.getStack().counter(spell.getId(), source, game, Zone.EXILED, false, ZoneDetail.NONE);
|
|
||||||
} else {
|
|
||||||
return game.getStack().counter(spell.getId(), source, game);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
game.informPlayers(player.getLogName() + " chooses to pay " + costValueMessage + " to prevent the counter effect");
|
game.informPlayers(player.getLogName() + " chooses to pay " + costValueMessage + " to prevent the counter effect");
|
||||||
return true;
|
return true;
|
||||||
|
@ -103,13 +98,8 @@ public class CounterUnlessPaysEffect extends OneShotEffect {
|
||||||
if (staticText != null && !staticText.isEmpty()) {
|
if (staticText != null && !staticText.isEmpty()) {
|
||||||
return staticText;
|
return staticText;
|
||||||
}
|
}
|
||||||
|
StringBuilder sb = new StringBuilder("counter ");
|
||||||
StringBuilder sb = new StringBuilder();
|
sb.append(getTargetPointer().describeTargets(mode.getTargets(), "it"));
|
||||||
if (mode.getTargets().isEmpty()) {
|
|
||||||
sb.append("counter it");
|
|
||||||
} else {
|
|
||||||
sb.append("counter target ").append(mode.getTargets().get(0).getTargetName());
|
|
||||||
}
|
|
||||||
sb.append(" unless its controller pays ");
|
sb.append(" unless its controller pays ");
|
||||||
if (cost != null) {
|
if (cost != null) {
|
||||||
sb.append(cost.getText());
|
sb.append(cost.getText());
|
||||||
|
@ -121,9 +111,8 @@ public class CounterUnlessPaysEffect extends OneShotEffect {
|
||||||
sb.append(genericMana.getMessage());
|
sb.append(genericMana.getMessage());
|
||||||
}
|
}
|
||||||
if (exile) {
|
if (exile) {
|
||||||
sb.append(". If that spell is countered this way, exile it instead of putting it into its owner's graveyard.");
|
sb.append(". If that spell is countered this way, exile it instead of putting it into its owner's graveyard");
|
||||||
}
|
}
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
|
|
||||||
package mage.constants;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author LevelX2
|
|
||||||
*/
|
|
||||||
public enum ZoneDetail {
|
|
||||||
|
|
||||||
NONE,
|
|
||||||
TOP,
|
|
||||||
BOTTOM,
|
|
||||||
CHOOSE
|
|
||||||
}
|
|
|
@ -413,47 +413,46 @@ public class Spell extends StackObjectImpl implements Card {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void counter(Ability source, Game game) {
|
public void counter(Ability source, Game game) {
|
||||||
this.counter(source, game, Zone.GRAVEYARD, false, ZoneDetail.NONE);
|
this.counter(source, game, PutCards.GRAVEYARD);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void counter(Ability source, Game game, Zone zone, boolean owner, ZoneDetail zoneDetail) {
|
public void counter(Ability source, Game game, PutCards zone) {
|
||||||
// source can be null for fizzled spells, don't use that code in your ZONE_CHANGE watchers/triggers:
|
// source can be null for fizzled spells, don't use that code in your ZONE_CHANGE watchers/triggers:
|
||||||
// event.getSourceId().equals
|
// event.getSourceId().equals
|
||||||
// TODO: so later it must be replaced to another technics with non null source
|
// TODO: fizzled spells are no longer considered "countered" as of current rules; may need refactor
|
||||||
UUID counteringSourceId = (source == null ? null : source.getSourceId());
|
|
||||||
this.countered = true;
|
this.countered = true;
|
||||||
if (!isCopy()) {
|
if (isCopy()) {
|
||||||
Player player = game.getPlayer(game.getControllerId(counteringSourceId));
|
|
||||||
if (player == null) {
|
|
||||||
player = game.getPlayer(getControllerId());
|
|
||||||
}
|
|
||||||
if (player != null) {
|
|
||||||
Ability counteringAbility = null;
|
|
||||||
MageObject counteringObject = game.getObject(counteringSourceId);
|
|
||||||
if (counteringObject instanceof StackObject) {
|
|
||||||
counteringAbility = ((StackObject) counteringObject).getStackAbility();
|
|
||||||
}
|
|
||||||
if (zone == Zone.LIBRARY) {
|
|
||||||
if (zoneDetail == ZoneDetail.CHOOSE) {
|
|
||||||
if (player.chooseUse(Outcome.Detriment, "Move countered spell to the top of the library? (otherwise it goes to the bottom)", counteringAbility, game)) {
|
|
||||||
zoneDetail = ZoneDetail.TOP;
|
|
||||||
} else {
|
|
||||||
zoneDetail = ZoneDetail.BOTTOM;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (zoneDetail == ZoneDetail.TOP) {
|
|
||||||
player.putCardsOnTopOfLibrary(new CardsImpl(card), game, counteringAbility, false);
|
|
||||||
} else {
|
|
||||||
player.putCardsOnBottomOfLibrary(new CardsImpl(card), game, counteringAbility, false);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
player.moveCards(card, zone, counteringAbility, game, false, false, owner, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// copied spell, only remove from stack
|
// copied spell, only remove from stack
|
||||||
game.getStack().remove(this, game);
|
game.getStack().remove(this, game);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Player player = game.getPlayer(source == null ? getControllerId() : source.getControllerId());
|
||||||
|
if (player != null) {
|
||||||
|
switch (zone) {
|
||||||
|
case TOP_OR_BOTTOM:
|
||||||
|
if (player.chooseUse(Outcome.Detriment,
|
||||||
|
"Put the countered spell on the top or bottom of its owner's library?",
|
||||||
|
null, "Top", "Bottom", source, game
|
||||||
|
)) {
|
||||||
|
player.putCardsOnTopOfLibrary(new CardsImpl(card), game, source, false);
|
||||||
|
} else {
|
||||||
|
player.putCardsOnBottomOfLibrary(new CardsImpl(card), game, source, false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TOP_ANY:
|
||||||
|
player.putCardsOnTopOfLibrary(new CardsImpl(card), game, source, false);
|
||||||
|
break;
|
||||||
|
case BOTTOM_ANY:
|
||||||
|
case BOTTOM_RANDOM:
|
||||||
|
player.putCardsOnBottomOfLibrary(new CardsImpl(card), game, source, false);
|
||||||
|
break;
|
||||||
|
case BATTLEFIELD_TAPPED:
|
||||||
|
player.moveCards(card, Zone.BATTLEFIELD, source, game, true, false, false, null);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
player.moveCards(card, zone.getZone(), source, game);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,7 @@ import java.util.Date;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import mage.MageObject;
|
import mage.MageObject;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.constants.Zone;
|
import mage.constants.PutCards;
|
||||||
import mage.constants.ZoneDetail;
|
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.GameEvent;
|
import mage.game.events.GameEvent;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
@ -60,13 +59,10 @@ public class SpellStack extends ArrayDeque<StackObject> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean counter(UUID objectId, Ability source, Game game) {
|
public boolean counter(UUID objectId, Ability source, Game game) {
|
||||||
return counter(objectId, source, game, Zone.GRAVEYARD, false, ZoneDetail.TOP);
|
return counter(objectId, source, game, PutCards.GRAVEYARD);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean counter(UUID objectId, Ability source, Game game, Zone zone, boolean owner, ZoneDetail zoneDetail) {
|
public boolean counter(UUID objectId, Ability source, Game game, PutCards zone) {
|
||||||
// the counter logic is copied by some spells to handle replacement effects of the countered spell
|
|
||||||
// so if logic is changed here check those spells for needed changes too
|
|
||||||
// Concerned cards to check: Hinder, Spell Crumple
|
|
||||||
StackObject stackObject = getStackObject(objectId);
|
StackObject stackObject = getStackObject(objectId);
|
||||||
MageObject sourceObject = game.getObject(source);
|
MageObject sourceObject = game.getObject(source);
|
||||||
if (stackObject != null && sourceObject != null) {
|
if (stackObject != null && sourceObject != null) {
|
||||||
|
@ -86,7 +82,7 @@ public class SpellStack extends ArrayDeque<StackObject> {
|
||||||
if (!(stackObject instanceof Spell)) { // spells are removed from stack by the card movement
|
if (!(stackObject instanceof Spell)) { // spells are removed from stack by the card movement
|
||||||
this.remove(stackObject, game);
|
this.remove(stackObject, game);
|
||||||
}
|
}
|
||||||
stackObject.counter(source, game, zone, owner, zoneDetail);
|
stackObject.counter(source, game, zone);
|
||||||
if (!game.isSimulation()) {
|
if (!game.isSimulation()) {
|
||||||
game.informPlayers(counteredObjectName + " is countered by " + sourceObject.getLogName());
|
game.informPlayers(counteredObjectName + " is countered by " + sourceObject.getLogName());
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,12 +104,12 @@ public class StackAbility extends StackObjectImpl implements Ability {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void counter(Ability source, Game game) {
|
public void counter(Ability source, Game game) {
|
||||||
// zone, owner, top ignored
|
// zone ignored
|
||||||
this.counter(source, game, Zone.GRAVEYARD, true, ZoneDetail.TOP);
|
this.counter(source, game, PutCards.GRAVEYARD);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void counter(Ability source, Game game, Zone zone, boolean owner, ZoneDetail zoneDetail) {
|
public void counter(Ability source, Game game, PutCards zone) {
|
||||||
//20100716 - 603.8
|
//20100716 - 603.8
|
||||||
if (ability instanceof StateTriggeredAbility) {
|
if (ability instanceof StateTriggeredAbility) {
|
||||||
((StateTriggeredAbility) ability).counter(game);
|
((StateTriggeredAbility) ability).counter(game);
|
||||||
|
|
|
@ -3,8 +3,7 @@ package mage.game.stack;
|
||||||
import mage.MageItem;
|
import mage.MageItem;
|
||||||
import mage.MageObject;
|
import mage.MageObject;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.constants.Zone;
|
import mage.constants.PutCards;
|
||||||
import mage.constants.ZoneDetail;
|
|
||||||
import mage.filter.predicate.Predicate;
|
import mage.filter.predicate.Predicate;
|
||||||
import mage.filter.predicate.mageobject.MageObjectReferencePredicate;
|
import mage.filter.predicate.mageobject.MageObjectReferencePredicate;
|
||||||
import mage.game.Controllable;
|
import mage.game.Controllable;
|
||||||
|
@ -25,7 +24,7 @@ public interface StackObject extends MageObject, Controllable {
|
||||||
*/
|
*/
|
||||||
void counter(Ability source, Game game);
|
void counter(Ability source, Game game);
|
||||||
|
|
||||||
void counter(Ability source, Game game, Zone zone, boolean owner, ZoneDetail zoneDetail);
|
void counter(Ability source, Game game, PutCards zone);
|
||||||
|
|
||||||
Ability getStackAbility();
|
Ability getStackAbility();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue