forked from External/mage
refactor "counter [spell] unless its controller pays [...]. If they do, [effect]"
closes #13861
This commit is contained in:
parent
8bb1f40bf7
commit
35e0ca2561
5 changed files with 119 additions and 135 deletions
|
|
@ -1,18 +1,13 @@
|
|||
package mage.cards.a;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.costs.mana.GenericManaCost;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.CounterUnlessPaysEffect;
|
||||
import mage.abilities.effects.keyword.IncubateEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.filter.FilterSpell;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetSpell;
|
||||
|
||||
import java.util.UUID;
|
||||
|
|
@ -35,7 +30,10 @@ public final class AssimilateEssence extends CardImpl {
|
|||
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}");
|
||||
|
||||
// Counter target creature or battle spell unless its controller pays {4}. If they do, you incubate 2.
|
||||
this.getSpellAbility().addEffect(new AssimilateEssenceEffect());
|
||||
this.getSpellAbility().addEffect(
|
||||
new CounterUnlessPaysEffect(new GenericManaCost(4))
|
||||
.withIfTheyDo(new IncubateEffect(2).setText("you incubate 2"))
|
||||
);
|
||||
this.getSpellAbility().addTarget(new TargetSpell(filter));
|
||||
}
|
||||
|
||||
|
|
@ -48,35 +46,3 @@ public final class AssimilateEssence extends CardImpl {
|
|||
return new AssimilateEssence(this);
|
||||
}
|
||||
}
|
||||
|
||||
class AssimilateEssenceEffect extends OneShotEffect {
|
||||
|
||||
AssimilateEssenceEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "counter target creature or battle spell unless its controller pays {4}. If they do, you incubate 2";
|
||||
}
|
||||
|
||||
private AssimilateEssenceEffect(final AssimilateEssenceEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AssimilateEssenceEffect copy() {
|
||||
return new AssimilateEssenceEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
UUID targetId = getTargetPointer().getFirst(game, source);
|
||||
Player player = game.getPlayer(game.getControllerId(targetId));
|
||||
Cost cost = new GenericManaCost(4);
|
||||
if (player == null
|
||||
|| !cost.canPay(source, source, player.getId(), game)
|
||||
|| !player.chooseUse(outcome, "Pay {4}?", source, game)
|
||||
|| !cost.pay(source, game, source, player.getId(), false)) {
|
||||
game.getStack().counter(targetId, source, game);
|
||||
return true;
|
||||
}
|
||||
return IncubateEffect.doIncubate(2, source.getControllerId(), game, source);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,18 +1,12 @@
|
|||
package mage.cards.d;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.costs.mana.GenericManaCost;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.CounterUnlessPaysEffect;
|
||||
import mage.abilities.effects.common.CreateTokenEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.token.LanderToken;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetSpell;
|
||||
|
||||
import java.util.UUID;
|
||||
|
|
@ -26,7 +20,10 @@ public final class DivertDisaster extends CardImpl {
|
|||
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}");
|
||||
|
||||
// Counter target spell unless its controller pays {2}. If they do, you create a Lander token.
|
||||
this.getSpellAbility().addEffect(new DivertDisasterEffect());
|
||||
this.getSpellAbility().addEffect(
|
||||
new CounterUnlessPaysEffect(new GenericManaCost(2))
|
||||
.withIfTheyDo(new CreateTokenEffect(new LanderToken()).setText("you create a Lander token"))
|
||||
);
|
||||
this.getSpellAbility().addTarget(new TargetSpell());
|
||||
}
|
||||
|
||||
|
|
@ -39,40 +36,3 @@ public final class DivertDisaster extends CardImpl {
|
|||
return new DivertDisaster(this);
|
||||
}
|
||||
}
|
||||
|
||||
class DivertDisasterEffect extends OneShotEffect {
|
||||
|
||||
DivertDisasterEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "counter target spell unless its controller pays {2}. If they do, you create a Lander token.";
|
||||
}
|
||||
|
||||
private DivertDisasterEffect(final DivertDisasterEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DivertDisasterEffect copy() {
|
||||
return new DivertDisasterEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Spell spell = game.getSpell(getTargetPointer().getFirst(game, source));
|
||||
if (spell == null) {
|
||||
return false;
|
||||
}
|
||||
Player player = game.getPlayer(spell.getControllerId());
|
||||
if (player == null) {
|
||||
return game.getStack().counter(spell.getId(), source, game);
|
||||
}
|
||||
Cost cost = new GenericManaCost(2);
|
||||
if (!cost.canPay(source, source, player.getId(), game)
|
||||
|| !player.chooseUse(outcome, "Pay {2}?", source, game)
|
||||
|| !cost.pay(source, game, source, player.getId(), false)) {
|
||||
return game.getStack().counter(spell.getId(), source, game);
|
||||
}
|
||||
new CreateTokenEffect(new LanderToken()).apply(game, source);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,19 +1,13 @@
|
|||
package mage.cards.d;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.costs.mana.GenericManaCost;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.CounterUnlessPaysEffect;
|
||||
import mage.abilities.effects.keyword.SurveilEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.game.Game;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetSpell;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
|
|
@ -25,7 +19,10 @@ public final class DontMakeASound extends CardImpl {
|
|||
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}");
|
||||
|
||||
// Counter target spell unless its controller pays {2}. If they do, surveil 2.
|
||||
this.getSpellAbility().addEffect(new DontMakeASoundEffect());
|
||||
this.getSpellAbility().addEffect(
|
||||
new CounterUnlessPaysEffect(new GenericManaCost(2))
|
||||
.withIfTheyDo(new SurveilEffect(2))
|
||||
);
|
||||
this.getSpellAbility().addTarget(new TargetSpell());
|
||||
}
|
||||
|
||||
|
|
@ -38,41 +35,3 @@ public final class DontMakeASound extends CardImpl {
|
|||
return new DontMakeASound(this);
|
||||
}
|
||||
}
|
||||
|
||||
class DontMakeASoundEffect extends OneShotEffect {
|
||||
|
||||
DontMakeASoundEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "counter target spell unless its controller pays {2}. If they do, surveil 2";
|
||||
}
|
||||
|
||||
private DontMakeASoundEffect(final DontMakeASoundEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DontMakeASoundEffect copy() {
|
||||
return new DontMakeASoundEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Spell spell = game.getSpell(getTargetPointer().getFirst(game, source));
|
||||
if (spell == null) {
|
||||
return false;
|
||||
}
|
||||
Player player = game.getPlayer(spell.getControllerId());
|
||||
if (player == null) {
|
||||
return game.getStack().counter(spell.getId(), source, game);
|
||||
}
|
||||
Cost cost = new GenericManaCost(2);
|
||||
if (!cost.canPay(source, source, player.getId(), game)
|
||||
|| !player.chooseUse(outcome, "Pay {2}?", source, game)
|
||||
|| !cost.pay(source, game, source, player.getId(), false)) {
|
||||
return game.getStack().counter(spell.getId(), source, game);
|
||||
}
|
||||
Optional.ofNullable(game.getPlayer(source.getControllerId()))
|
||||
.ifPresent(p -> p.surveil(2, source, game));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,79 @@
|
|||
package org.mage.test.cards.single.eoe;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
* @author Susucr
|
||||
*/
|
||||
public class DivertDisasterTest extends CardTestPlayerBase {
|
||||
|
||||
/**
|
||||
* {@link mage.cards.d.DivertDisaster Divert Disaster} {1}{U}
|
||||
* Instant
|
||||
* Counter target spell unless its controller pays {2}. If they do, you create a Lander token.
|
||||
*/
|
||||
private static final String disaster = "Divert Disaster";
|
||||
|
||||
@Test
|
||||
public void test_Pay() {
|
||||
addCard(Zone.HAND, playerA, disaster);
|
||||
addCard(Zone.HAND, playerB, "Elite Vanguard");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 2);
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Plains", 3);
|
||||
|
||||
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Elite Vanguard");
|
||||
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerA, disaster, "Elite Vanguard", "Elite Vanguard");
|
||||
setChoice(playerB, true); // yes to "pays {2}"
|
||||
|
||||
setStopAt(2, PhaseStep.BEGIN_COMBAT);
|
||||
setStrictChooseMode(true);
|
||||
execute();
|
||||
|
||||
assertTappedCount("Plains", true, 3);
|
||||
assertPermanentCount(playerA, "Lander Token", 1);
|
||||
assertPermanentCount(playerB, "Elite Vanguard", 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_NoPay() {
|
||||
addCard(Zone.HAND, playerA, disaster);
|
||||
addCard(Zone.HAND, playerB, "Elite Vanguard");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 2);
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Plains", 3);
|
||||
|
||||
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Elite Vanguard");
|
||||
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerA, disaster, "Elite Vanguard", "Elite Vanguard");
|
||||
setChoice(playerB, false); // yes to "pays {2}"
|
||||
|
||||
setStopAt(2, PhaseStep.BEGIN_COMBAT);
|
||||
setStrictChooseMode(true);
|
||||
execute();
|
||||
|
||||
assertTappedCount("Plains", true, 1);
|
||||
assertPermanentCount(playerA, "Lander Token", 0);
|
||||
assertGraveyardCount(playerB, "Elite Vanguard", 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_CantPay() {
|
||||
addCard(Zone.HAND, playerA, disaster);
|
||||
addCard(Zone.HAND, playerB, "Elite Vanguard");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 2);
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Plains", 1);
|
||||
|
||||
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Elite Vanguard");
|
||||
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerA, disaster, "Elite Vanguard", "Elite Vanguard");
|
||||
setChoice(playerB, false); // yes to "pays {2}"
|
||||
|
||||
setStopAt(2, PhaseStep.BEGIN_COMBAT);
|
||||
setStrictChooseMode(true);
|
||||
execute();
|
||||
|
||||
assertTappedCount("Plains", true, 1);
|
||||
assertPermanentCount(playerA, "Lander Token", 0);
|
||||
assertGraveyardCount(playerB, "Elite Vanguard", 1);
|
||||
}
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ import mage.abilities.Mode;
|
|||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.costs.mana.ManaCost;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.PutCards;
|
||||
|
|
@ -14,13 +15,14 @@ import mage.players.Player;
|
|||
import mage.util.ManaUtil;
|
||||
|
||||
/**
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
* @author BetaSteward_at_googlemail.com, Susucr
|
||||
*/
|
||||
public class CounterUnlessPaysEffect extends OneShotEffect {
|
||||
|
||||
protected Cost cost;
|
||||
protected DynamicValue genericMana;
|
||||
private final boolean exile;
|
||||
private Effect effectIfTheyDo = null; // optional "If they do, [...]" effect
|
||||
|
||||
public CounterUnlessPaysEffect(Cost cost) {
|
||||
this(cost, false);
|
||||
|
|
@ -51,6 +53,17 @@ public class CounterUnlessPaysEffect extends OneShotEffect {
|
|||
this.genericMana = effect.genericMana.copy();
|
||||
}
|
||||
this.exile = effect.exile;
|
||||
if (effect.effectIfTheyDo != null) {
|
||||
this.effectIfTheyDo = effect.effectIfTheyDo.copy();
|
||||
}
|
||||
}
|
||||
|
||||
public CounterUnlessPaysEffect withIfTheyDo(Effect effect) {
|
||||
if (effectIfTheyDo != null) {
|
||||
throw new IllegalStateException("Wrong code usage: only a single 'if they do' effect is expected.");
|
||||
}
|
||||
effectIfTheyDo = effect.copy();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -91,6 +104,9 @@ public class CounterUnlessPaysEffect extends OneShotEffect {
|
|||
game.getStack().counter(spell.getId(), source, game, exile ? PutCards.EXILED : PutCards.GRAVEYARD);
|
||||
} else {
|
||||
game.informPlayers(player.getLogName() + " chooses to pay " + costValueMessage + " to prevent the counter effect");
|
||||
if (effectIfTheyDo != null) {
|
||||
effectIfTheyDo.apply(game, source);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -115,6 +131,10 @@ public class CounterUnlessPaysEffect extends OneShotEffect {
|
|||
if (exile) {
|
||||
sb.append(". If that spell is countered this way, exile it instead of putting it into its owner's graveyard");
|
||||
}
|
||||
if (effectIfTheyDo != null) {
|
||||
sb.append(". If they do, ");
|
||||
sb.append(effectIfTheyDo.getText(mode));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue