refactor one-use prevention effect for a chosen source

fixes a few bugs along the way:

[[Pilgrim and Justice]] & [[Pilgrim of Virue]] were incorrectly adding a "to you" to their damage clause.
[[Ajani's Aid]] was improperly a one-use prevention effect.

[[Story Circle]] and [[Prismatic Circle]] have not been refactor as it is not currently possible to have a proper filter for them. Would require a FilterSource with a 4-argument match most likely.
This commit is contained in:
Susucre 2025-05-30 19:23:31 +02:00 committed by Failure
parent 7d62aa9ec5
commit a6ca052106
49 changed files with 1481 additions and 821 deletions

View file

@ -1,24 +1,22 @@
package mage.cards.a;
import java.util.UUID;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.SacrificeSourceCost;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceToYouEffect;
import mage.abilities.effects.common.PreventDamageByChosenSourceEffect;
import mage.abilities.effects.common.search.SearchLibraryGraveyardPutInHandEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.mageobject.NamePredicate;
import java.util.UUID;
/**
*
* @author fireshoes
*/
public final class AjanisAid extends CardImpl {
@ -37,8 +35,7 @@ public final class AjanisAid extends CardImpl {
this.addAbility(new EntersBattlefieldTriggeredAbility(new SearchLibraryGraveyardPutInHandEffect(filter), true));
// Sacrifice Ajani's Aid: Prevent all combat damage a creature of your choice would deal this turn.
Effect effect = new PreventNextDamageFromChosenSourceToYouEffect(Duration.EndOfTurn, new FilterCreaturePermanent("creature of your choice"), true);
effect.setText("Prevent all combat damage a creature of your choice would deal this turn");
Effect effect = new PreventDamageByChosenSourceEffect(new FilterCreaturePermanent("creature of your choice"), true);
this.addAbility(new SimpleActivatedAbility(effect, new SacrificeSourceCost()));
}

View file

@ -1,27 +1,26 @@
package mage.cards.b;
import java.util.Set;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.PreventionEffectData;
import mage.abilities.effects.PreventionEffectImpl;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.players.Player;
import mage.target.TargetSource;
import java.util.Set;
import java.util.UUID;
/**
*
* @author awjackson
*/
public final class BoneMask extends CardImpl {
@ -29,8 +28,14 @@ public final class BoneMask extends CardImpl {
public BoneMask(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}");
// {2}, {tap}: The next time a source of your choice would deal damage to you this turn, prevent that damage. Exile cards from the top of your library equal to the damage prevented this way.
Ability ability = new SimpleActivatedAbility(new BoneMaskEffect(), new GenericManaCost(2));
// {2}, {T}: The next time a source of your choice would deal damage to you this turn, prevent that damage. Exile cards from the top of your library equal to the damage prevented this way.
Ability ability = new SimpleActivatedAbility(
new PreventNextDamageFromChosenSourceEffect(
Duration.EndOfTurn, true,
BoneMaskEffectPreventionApplier.instance
),
new GenericManaCost(2)
);
ability.addCost(new TapSourceCost());
this.addAbility(ability);
}
@ -45,54 +50,24 @@ public final class BoneMask extends CardImpl {
}
}
class BoneMaskEffect extends PreventionEffectImpl {
enum BoneMaskEffectPreventionApplier implements PreventNextDamageFromChosenSourceEffect.ApplierOnPrevention {
instance;
private final TargetSource target;
public BoneMaskEffect() {
super(Duration.EndOfTurn);
this.staticText = "The next time a source of your choice would deal damage to you this turn, prevent that damage. "
+ "Exile cards from the top of your library equal to the damage prevented this way.";
this.target = new TargetSource();
}
private BoneMaskEffect(final BoneMaskEffect effect) {
super(effect);
this.target = effect.target.copy();
}
@Override
public BoneMaskEffect copy() {
return new BoneMaskEffect(this);
}
@Override
public void init(Ability source, Game game) {
super.init(source, game);
this.target.choose(Outcome.PreventDamage, source.getControllerId(), source.getSourceId(), source, game);
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
PreventionEffectData preventionData = preventDamageAction(event, source, game);
this.used = true;
this.discard();
if (preventionData.getPreventedDamage() > 0) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
Set<Card> cards = controller.getLibrary().getTopCards(game, preventionData.getPreventedDamage());
controller.moveCards(cards, Zone.EXILED, source, game);
}
public boolean apply(PreventionEffectData data, TargetSource targetSource, GameEvent event, Ability source, Game game) {
if (data == null || data.getPreventedDamage() <= 0) {
return false;
}
return false;
int prevented = data.getPreventedDamage();
Player controller = game.getPlayer(source.getControllerId());
if (controller == null) {
return false;
}
Set<Card> cards = controller.getLibrary().getTopCards(game, prevented);
controller.moveCards(cards, Zone.EXILED, source, game);
return true;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
return (!this.used
&& super.applies(event, source, game)
&& event.getTargetId().equals(source.getControllerId())
&& event.getSourceId().equals(target.getFirstTarget())
);
public String getText() {
return "Exile cards from the top of your library equal to the damage prevented this way";
}
}

View file

@ -1,23 +1,22 @@
package mage.cards.b;
import java.util.UUID;
import mage.MageInt;
import mage.ObjectColor;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.SacrificeSourceCost;
import mage.abilities.effects.common.PreventDamageBySourceEffect;
import mage.abilities.effects.common.PreventDamageByChosenSourceEffect;
import mage.abilities.keyword.ProtectionAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.FilterObject;
import mage.filter.predicate.mageobject.ColorPredicate;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public final class BurrentonForgeTender extends CardImpl {
@ -29,7 +28,7 @@ public final class BurrentonForgeTender extends CardImpl {
}
public BurrentonForgeTender(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{W}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}");
this.subtype.add(SubType.KITHKIN, SubType.WIZARD);
this.power = new MageInt(1);
@ -37,9 +36,9 @@ public final class BurrentonForgeTender extends CardImpl {
// Protection from red
this.addAbility(ProtectionAbility.from(ObjectColor.RED));
// Sacrifice Burrenton Forge-Tender: Prevent all damage a red source of your choice would deal this turn.
this.addAbility(new SimpleActivatedAbility( new PreventDamageBySourceEffect(filterObject), new SacrificeSourceCost()));
this.addAbility(new SimpleActivatedAbility(new PreventDamageByChosenSourceEffect(filterObject), new SacrificeSourceCost()));
}

View file

@ -1,42 +1,41 @@
package mage.cards.c;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.DiscardCardCost;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.PreventionEffectData;
import mage.abilities.effects.PreventionEffectImpl;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.players.Player;
import mage.target.TargetSource;
import mage.constants.SubType;
import java.util.UUID;
/**
*
* @author anonymous
*/
public final class ChoArrimAlchemist extends CardImpl {
public ChoArrimAlchemist(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{W}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.SPELLSHAPER);
this.power = new MageInt(1);
this.toughness = new MageInt(1);
// {1}{W}{W}, {tap}, Discard a card: The next time a source of your choice would deal damage to you this turn, prevent that damage. You gain life equal to the damage prevented this way.
Ability ability = new SimpleActivatedAbility(new ChoArrimAlchemistEffect(), new ManaCostsImpl<>("{1}{W}{W}"));
// {1}{W}{W}, {T}, Discard a card: The next time a source of your choice would deal damage to you this turn, prevent that damage. You gain life equal to the damage prevented this way.
Ability ability = new SimpleActivatedAbility(
new PreventNextDamageFromChosenSourceEffect(
Duration.EndOfTurn, true,
PreventNextDamageFromChosenSourceEffect.ON_PREVENT_YOU_GAIN_THAT_MUCH_LIFE
),
new ManaCostsImpl<>("{1}{W}{W}")
);
ability.addCost(new TapSourceCost());
ability.addCost(new DiscardCardCost());
this.addAbility(ability);
@ -50,55 +49,4 @@ public final class ChoArrimAlchemist extends CardImpl {
public ChoArrimAlchemist copy() {
return new ChoArrimAlchemist(this);
}
}
class ChoArrimAlchemistEffect extends PreventionEffectImpl {
private final TargetSource target;
public ChoArrimAlchemistEffect() {
super(Duration.EndOfTurn, Integer.MAX_VALUE, false, false);
this.staticText = "The next time a source of your choice would deal damage to you this turn, prevent that damage. You gain life equal to the damage prevented this way.";
this.target = new TargetSource();
}
private ChoArrimAlchemistEffect(final ChoArrimAlchemistEffect effect) {
super(effect);
this.target = effect.target.copy();
}
@Override
public ChoArrimAlchemistEffect copy() {
return new ChoArrimAlchemistEffect(this);
}
@Override
public void init(Ability source, Game game) {
super.init(source, game);
this.target.choose(Outcome.PreventDamage, source.getControllerId(), source.getSourceId(), source, game);
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
PreventionEffectData preventionData = preventDamageAction(event, source, game);
this.used = true;
this.discard(); // only one use
if (preventionData.getPreventedDamage() > 0) {
Player player = game.getPlayer(source.getControllerId());
if (player != null) {
player.gainLife(preventionData.getPreventedDamage(), game, source);
}
}
return true;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (!this.used && super.applies(event, source, game)) {
if (event.getTargetId().equals(source.getControllerId()) && event.getSourceId().equals(target.getFirstTarget())) {
return true;
}
}
return false;
}
}
}

View file

@ -1,20 +1,19 @@
package mage.cards.c;
import java.util.UUID;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceToYouEffect;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Zone;
import mage.filter.FilterObject;
import java.util.UUID;
/**
*
* @author Plopman
*/
public final class CircleOfProtectionArtifacts extends CardImpl {
@ -24,12 +23,12 @@ public final class CircleOfProtectionArtifacts extends CardImpl {
static {
filter.add(CardType.ARTIFACT.getPredicate());
}
public CircleOfProtectionArtifacts(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{W}");
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}");
// {2}: The next time an artifact source of your choice would deal damage to you this turn, prevent that damage.
Effect effect = new PreventNextDamageFromChosenSourceToYouEffect(Duration.EndOfTurn, filter);
Effect effect = new PreventNextDamageFromChosenSourceEffect(Duration.EndOfTurn, true, filter);
this.addAbility(new SimpleActivatedAbility(effect, new ManaCostsImpl<>("{2}")));
}

View file

@ -1,22 +1,21 @@
package mage.cards.c;
import java.util.UUID;
import mage.ObjectColor;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceToYouEffect;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Zone;
import mage.filter.FilterObject;
import mage.filter.predicate.mageobject.ColorPredicate;
import java.util.UUID;
/**
*
* @author Plopman
*/
public final class CircleOfProtectionBlack extends CardImpl {
@ -26,13 +25,13 @@ public final class CircleOfProtectionBlack extends CardImpl {
static {
filter.add(new ColorPredicate(ObjectColor.BLACK));
}
public CircleOfProtectionBlack(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{W}");
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}");
// {1}: The next time a black source of your choice would deal damage to you this turn, prevent that damage.
Effect effect = new PreventNextDamageFromChosenSourceToYouEffect(Duration.EndOfTurn, filter);
Effect effect = new PreventNextDamageFromChosenSourceEffect(Duration.EndOfTurn, true, filter);
this.addAbility(new SimpleActivatedAbility(effect, new ManaCostsImpl<>("{1}")));
}

View file

@ -1,22 +1,21 @@
package mage.cards.c;
import java.util.UUID;
import mage.ObjectColor;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceToYouEffect;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Zone;
import mage.filter.FilterObject;
import mage.filter.predicate.mageobject.ColorPredicate;
import java.util.UUID;
/**
*
* @author Plopman
*/
public final class CircleOfProtectionBlue extends CardImpl {
@ -28,11 +27,11 @@ public final class CircleOfProtectionBlue extends CardImpl {
}
public CircleOfProtectionBlue(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{W}");
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}");
// {1}: The next time a blue source of your choice would deal damage to you this turn, prevent that damage.
Effect effect = new PreventNextDamageFromChosenSourceToYouEffect(Duration.EndOfTurn, filter);
Effect effect = new PreventNextDamageFromChosenSourceEffect(Duration.EndOfTurn, true, filter);
this.addAbility(new SimpleActivatedAbility(effect, new ManaCostsImpl<>("{1}")));
}

View file

@ -1,22 +1,21 @@
package mage.cards.c;
import java.util.UUID;
import mage.ObjectColor;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceToYouEffect;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Zone;
import mage.filter.FilterObject;
import mage.filter.predicate.mageobject.ColorPredicate;
import java.util.UUID;
/**
*
* @author Plopman
*/
public final class CircleOfProtectionGreen extends CardImpl {
@ -28,11 +27,11 @@ public final class CircleOfProtectionGreen extends CardImpl {
}
public CircleOfProtectionGreen(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{W}");
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}");
// {1}: The next time a green source of your choice would deal damage to you this turn, prevent that damage.
Effect effect = new PreventNextDamageFromChosenSourceToYouEffect(Duration.EndOfTurn, filter);
Effect effect = new PreventNextDamageFromChosenSourceEffect(Duration.EndOfTurn, true, filter);
this.addAbility(new SimpleActivatedAbility(effect, new ManaCostsImpl<>("{1}")));
}

View file

@ -1,22 +1,21 @@
package mage.cards.c;
import java.util.UUID;
import mage.ObjectColor;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceToYouEffect;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Zone;
import mage.filter.FilterObject;
import mage.filter.predicate.mageobject.ColorPredicate;
import java.util.UUID;
/**
*
* @author Plopman
*/
public final class CircleOfProtectionRed extends CardImpl {
@ -28,11 +27,11 @@ public final class CircleOfProtectionRed extends CardImpl {
}
public CircleOfProtectionRed(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{W}");
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}");
// {1}: The next time a red source of your choice would deal damage to you this turn, prevent that damage.
Effect effect = new PreventNextDamageFromChosenSourceToYouEffect(Duration.EndOfTurn, filter);
Effect effect = new PreventNextDamageFromChosenSourceEffect(Duration.EndOfTurn, true, filter);
this.addAbility(new SimpleActivatedAbility(effect, new ManaCostsImpl<>("{1}")));
}

View file

@ -1,22 +1,21 @@
package mage.cards.c;
import java.util.UUID;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceToYouEffect;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceEffect;
import mage.abilities.keyword.ShadowAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Zone;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.mageobject.AbilityPredicate;
import java.util.UUID;
/**
*
* @author LoneFox
*/
public final class CircleOfProtectionShadow extends CardImpl {
@ -28,10 +27,10 @@ public final class CircleOfProtectionShadow extends CardImpl {
}
public CircleOfProtectionShadow(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{W}");
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}");
// {1}: The next time a creature of your choice with shadow would deal damage to you this turn, prevent that damage.
Effect effect = new PreventNextDamageFromChosenSourceToYouEffect(Duration.EndOfTurn, filter);
Effect effect = new PreventNextDamageFromChosenSourceEffect(Duration.EndOfTurn, true, filter);
effect.setText("The next time a creature of your choice with shadow would deal damage to you this turn, prevent that damage");
this.addAbility(new SimpleActivatedAbility(effect, new ManaCostsImpl<>("{1}")));
}

View file

@ -1,22 +1,21 @@
package mage.cards.c;
import java.util.UUID;
import mage.ObjectColor;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceToYouEffect;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Zone;
import mage.filter.FilterObject;
import mage.filter.predicate.mageobject.ColorPredicate;
import java.util.UUID;
/**
*
* @author Plopman
*/
public final class CircleOfProtectionWhite extends CardImpl {
@ -28,11 +27,11 @@ public final class CircleOfProtectionWhite extends CardImpl {
}
public CircleOfProtectionWhite(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{W}");
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}");
// {1}: The next time a white source of your choice would deal damage to you this turn, prevent that damage.
Effect effect = new PreventNextDamageFromChosenSourceToYouEffect(Duration.EndOfTurn, filter);
Effect effect = new PreventNextDamageFromChosenSourceEffect(Duration.EndOfTurn, true, filter);
this.addAbility(new SimpleActivatedAbility(effect, new ManaCostsImpl<>("{1}")));
}

View file

@ -2,12 +2,11 @@ package mage.cards.d;
import mage.abilities.Ability;
import mage.abilities.effects.PreventionEffectData;
import mage.abilities.effects.PreventionEffectImpl;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.players.Player;
@ -24,7 +23,12 @@ public final class DeflectingPalm extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{R}{W}");
// The next time a source of your choice would deal damage to you this turn, prevent that damage. If damage is prevented this way, Deflecting Palm deals that much damage to that source's controller.
this.getSpellAbility().addEffect(new DeflectingPalmEffect());
this.getSpellAbility().addEffect(
new PreventNextDamageFromChosenSourceEffect(
Duration.EndOfTurn, true,
DeflectingPalmPreventionApplier.instance
)
);
}
private DeflectingPalm(final DeflectingPalm card) {
@ -37,56 +41,24 @@ public final class DeflectingPalm extends CardImpl {
}
}
class DeflectingPalmEffect extends PreventionEffectImpl {
enum DeflectingPalmPreventionApplier implements PreventNextDamageFromChosenSourceEffect.ApplierOnPrevention {
instance;
private final TargetSource target;
DeflectingPalmEffect() {
super(Duration.EndOfTurn, Integer.MAX_VALUE, false, false);
this.staticText = "the next time a source of your choice would deal damage to you this turn, " +
"prevent that damage. If damage is prevented this way, " +
"{this} deals that much damage to that source's controller";
this.target = new TargetSource();
}
private DeflectingPalmEffect(final DeflectingPalmEffect effect) {
super(effect);
this.target = effect.target.copy();
}
@Override
public DeflectingPalmEffect copy() {
return new DeflectingPalmEffect(this);
}
@Override
public void init(Ability source, Game game) {
super.init(source, game);
this.target.choose(Outcome.PreventDamage, source.getControllerId(), source.getSourceId(), source, game);
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
PreventionEffectData preventionData = preventDamageAction(event, source, game);
this.used = true;
this.discard(); // only one use
if (preventionData.getPreventedDamage() < 1) {
return true;
public boolean apply(PreventionEffectData data, TargetSource targetSource, GameEvent event, Ability source, Game game) {
if (data == null || data.getPreventedDamage() <= 0) {
return false;
}
UUID objectControllerId = game.getControllerId(target.getFirstTarget());
int prevented = data.getPreventedDamage();
UUID objectControllerId = game.getControllerId(targetSource.getFirstTarget());
Player objectController = game.getPlayer(objectControllerId);
if (objectController == null) {
return true;
return false;
}
objectController.damage(preventionData.getPreventedDamage(), source.getSourceId(), source, game);
objectController.damage(prevented, source.getSourceId(), source, game);
return true;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
return !this.used
&& super.applies(event, source, game)
&& event.getTargetId().equals(source.getControllerId())
&& event.getSourceId().equals(target.getFirstTarget());
public String getText() {
return "If damage is prevented this way, {this} deals that much damage to that source's controller";
}
}
}

View file

@ -1,38 +1,38 @@
package mage.cards.g;
import java.util.UUID;
import mage.ObjectColor;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceToYouEffect;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Zone;
import mage.filter.FilterObject;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.ColorPredicate;
import java.util.UUID;
/**
*
* @author L_J
*/
public final class GreaterRealmOfPreservation extends CardImpl {
private static final FilterObject filter = new FilterObject("black or red source");
static{
static {
filter.add(Predicates.or(new ColorPredicate(ObjectColor.BLACK), new ColorPredicate(ObjectColor.RED)));
}
public GreaterRealmOfPreservation(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{W}");
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}");
// {1}{W}: The next time a black or red source of your choice would deal damage to you this turn, prevent that damage.
Effect effect = new PreventNextDamageFromChosenSourceToYouEffect(Duration.EndOfTurn, filter);
Effect effect = new PreventNextDamageFromChosenSourceEffect(Duration.EndOfTurn, true, filter);
this.addAbility(new SimpleActivatedAbility(effect, new ManaCostsImpl<>("{1}{W}")));
}

View file

@ -1,28 +1,27 @@
package mage.cards.h;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceToYouEffect;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceEffect;
import mage.abilities.effects.common.SacrificeSourceUnlessPaysEffect;
import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Zone;
import mage.constants.SubType;
import java.util.UUID;
/**
*
* @author anonymous
*/
public final class HaazdaShieldMate extends CardImpl {
public HaazdaShieldMate(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{W}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.SOLDIER);
this.power = new MageInt(1);
@ -30,9 +29,9 @@ public final class HaazdaShieldMate extends CardImpl {
// At the beginning of your upkeep, sacrifice Haazda Shield Mate unless you pay {W}{W}.
this.addAbility(new BeginningOfUpkeepTriggeredAbility(new SacrificeSourceUnlessPaysEffect(new ManaCostsImpl<>("{W}{W}"))));
// {W}: The next time a source of your choice would deal damage to you this turn, prevent that damage.
this.addAbility(new SimpleActivatedAbility(new PreventNextDamageFromChosenSourceToYouEffect(Duration.EndOfTurn), new ManaCostsImpl<>("{W}")));
this.addAbility(new SimpleActivatedAbility(new PreventNextDamageFromChosenSourceEffect(Duration.EndOfTurn, true), new ManaCostsImpl<>("{W}")));
}
private HaazdaShieldMate(final HaazdaShieldMate card) {

View file

@ -1,28 +1,17 @@
package mage.cards.i;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.delayed.PactDelayedTriggeredAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.PreventionEffectData;
import mage.abilities.effects.PreventionEffectImpl;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.players.Player;
import mage.target.Target;
import mage.target.TargetSource;
import mage.target.targetpointer.FixedTarget;
import java.util.UUID;
/**
*
* @author Plopman
*/
public final class InterventionPact extends CardImpl {
@ -33,7 +22,12 @@ public final class InterventionPact extends CardImpl {
this.color.setWhite(true);
// The next time a source of your choice would deal damage to you this turn, prevent that damage. You gain life equal to the damage prevented this way.
this.getSpellAbility().addEffect(new InterventionPactEffect());
this.getSpellAbility().addEffect(
new PreventNextDamageFromChosenSourceEffect(
Duration.EndOfTurn, true,
PreventNextDamageFromChosenSourceEffect.ON_PREVENT_YOU_GAIN_THAT_MUCH_LIFE
)
);
// At the beginning of your next upkeep, pay {1}{W}{W}. If you don't, you lose the game.
this.getSpellAbility().addEffect(new CreateDelayedTriggeredAbilityEffect(new PactDelayedTriggeredAbility(new ManaCostsImpl<>("{1}{W}{W}")), false));
}
@ -46,78 +40,4 @@ public final class InterventionPact extends CardImpl {
public InterventionPact copy() {
return new InterventionPact(this);
}
}
class InterventionPactEffect extends OneShotEffect {
InterventionPactEffect() {
super(Outcome.PreventDamage);
this.staticText = "The next time a source of your choice would deal damage to you this turn, prevent that damage. You gain life equal to the damage prevented this way";
}
private InterventionPactEffect(final InterventionPactEffect effect) {
super(effect);
}
@Override
public InterventionPactEffect copy() {
return new InterventionPactEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
Target target = new TargetSource();
target.setRequired(true);
target.withNotTarget(true);
if (controller.chooseTarget(outcome, target, source, game)) {
ContinuousEffect continuousEffect = new InterventionPactPreventDamageEffect();
continuousEffect.setTargetPointer(new FixedTarget(target.getFirstTarget(), game));
game.addEffect(continuousEffect, source);
}
return true;
}
return false;
}
}
class InterventionPactPreventDamageEffect extends PreventionEffectImpl {
InterventionPactPreventDamageEffect() {
super(Duration.EndOfTurn, Integer.MAX_VALUE, false, false);
staticText = "The next time a source of your choice would deal damage to you this turn, prevent that damage. You gain life equal to the damage prevented this way";
}
private InterventionPactPreventDamageEffect(final InterventionPactPreventDamageEffect effect) {
super(effect);
}
@Override
public InterventionPactPreventDamageEffect copy() {
return new InterventionPactPreventDamageEffect(this);
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
PreventionEffectData preventEffectData = preventDamageAction(event, source, game);
if (preventEffectData.getPreventedDamage() > 0) {
used = true;
Player player = game.getPlayer(source.getControllerId());
if (player != null) {
player.gainLife(preventEffectData.getPreventedDamage(), game, source);
}
}
return false;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (!this.used && super.applies(event, source, game) && event.getTargetId().equals(source.getControllerId())) {
if (event.getSourceId().equals(getTargetPointer().getFirst(game, source))) {
return true;
}
}
return false;
}
}
}

View file

@ -1,28 +1,28 @@
package mage.cards.i;
import java.util.UUID;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceToYouEffect;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceEffect;
import mage.abilities.keyword.BuybackAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import java.util.UUID;
/**
*
* @author anonymous
*/
public final class Invulnerability extends CardImpl {
public Invulnerability(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{W}");
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}");
// Buyback {3}
this.addAbility(new BuybackAbility("{3}"));
// The next time a source of your choice would deal damage to you this turn, prevent that damage.
this.getSpellAbility().addEffect(new PreventNextDamageFromChosenSourceToYouEffect(Duration.EndOfTurn));
this.getSpellAbility().addEffect(new PreventNextDamageFromChosenSourceEffect(Duration.EndOfTurn, true));
}
private Invulnerability(final Invulnerability card) {

View file

@ -3,14 +3,13 @@ package mage.cards.n;
import mage.abilities.Ability;
import mage.abilities.common.delayed.ReflexiveTriggeredAbility;
import mage.abilities.effects.PreventionEffectData;
import mage.abilities.effects.PreventionEffectImpl;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.target.TargetSource;
@ -27,7 +26,12 @@ public final class NewWayForward extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{U}{R}{W}");
// The next time a source of your choice would deal damage to you this turn, prevent that damage. When damage is prevented this way, New Way Forward deals that much damage to that source's controller and you draw that many cards.
this.getSpellAbility().addEffect(new NewWayForwardEffect());
this.getSpellAbility().addEffect(
new PreventNextDamageFromChosenSourceEffect(
Duration.EndOfTurn, true,
NewWayForwardPreventionApplier.instance
)
);
}
private NewWayForward(final NewWayForward card) {
@ -40,58 +44,26 @@ public final class NewWayForward extends CardImpl {
}
}
class NewWayForwardEffect extends PreventionEffectImpl {
enum NewWayForwardPreventionApplier implements PreventNextDamageFromChosenSourceEffect.ApplierOnPrevention {
instance;
private final TargetSource target;
NewWayForwardEffect() {
super(Duration.EndOfTurn, Integer.MAX_VALUE, false, false);
this.staticText = "the next time a source of your choice would deal damage to you this turn, " +
"prevent that damage. When damage is prevented this way, " +
"{this} deals that much damage to that source's controller and you draw that many cards";
this.target = new TargetSource();
}
private NewWayForwardEffect(final NewWayForwardEffect effect) {
super(effect);
this.target = effect.target.copy();
}
@Override
public NewWayForwardEffect copy() {
return new NewWayForwardEffect(this);
}
@Override
public void init(Ability source, Game game) {
super.init(source, game);
this.target.choose(Outcome.PreventDamage, source.getControllerId(), source.getSourceId(), source, game);
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
PreventionEffectData preventionData = preventDamageAction(event, source, game);
this.used = true;
this.discard(); // only one use
if (preventionData.getPreventedDamage() < 1) {
return true;
public boolean apply(PreventionEffectData data, TargetSource targetSource, GameEvent event, Ability source, Game game) {
if (data == null || data.getPreventedDamage() <= 0) {
return false;
}
UUID objectControllerId = game.getControllerId(target.getFirstTarget());
int prevented = data.getPreventedDamage();
UUID objectControllerId = game.getControllerId(targetSource.getFirstTarget());
ReflexiveTriggeredAbility ability = new ReflexiveTriggeredAbility(
new DamageTargetEffect(preventionData.getPreventedDamage())
new DamageTargetEffect(prevented)
.setTargetPointer(new FixedTarget(objectControllerId)),
false
);
ability.addEffect(new DrawCardSourceControllerEffect(preventionData.getPreventedDamage()));
ability.addEffect(new DrawCardSourceControllerEffect(prevented));
game.fireReflexiveTriggeredAbility(ability, source);
return true;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
return !this.used
&& super.applies(event, source, game)
&& event.getTargetId().equals(source.getControllerId())
&& event.getSourceId().equals(target.getFirstTarget());
public String getText() {
return "When damage is prevented this way, {this} deals that much damage to that source's controller and you draw that many cards";
}
}
}

View file

@ -2,24 +2,24 @@
package mage.cards.p;
import java.util.UUID;
import mage.abilities.effects.common.PreventDamageBySourceEffect;
import mage.abilities.effects.common.PreventDamageByChosenSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
/**
*
* @author jeffwadsworth
*/
public final class PayNoHeed extends CardImpl {
public PayNoHeed(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{W}");
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{W}");
// Prevent all damage a source of your choice would deal this turn.
this.getSpellAbility().addEffect(new PreventDamageBySourceEffect());
this.getSpellAbility().addEffect(new PreventDamageByChosenSourceEffect());
}
private PayNoHeed(final PayNoHeed card) {

View file

@ -1,34 +1,39 @@
package mage.cards.p;
import java.util.UUID;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.PutCardFromHandOnTopOfLibraryCost;
import mage.abilities.effects.PreventionEffectImpl;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.target.TargetSource;
import mage.filter.FilterObject;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.ColorPredicate;
import java.util.UUID;
/**
*
* @author jeffwadsworth
*/
public final class Penance extends CardImpl {
private static final FilterObject filter = new FilterObject("black or red source");
static {
filter.add(Predicates.or(new ColorPredicate(ObjectColor.BLACK), new ColorPredicate(ObjectColor.RED)));
}
public Penance(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}");
// Put a card from your hand on top of your library: The next time a black or red source of your choice would deal damage this turn, prevent that damage.
this.addAbility(new SimpleActivatedAbility(new PenanceEffect(), new PutCardFromHandOnTopOfLibraryCost()));
this.addAbility(new SimpleActivatedAbility(
new PreventNextDamageFromChosenSourceEffect(Duration.EndOfTurn, false, filter),
new PutCardFromHandOnTopOfLibraryCost()
));
}
private Penance(final Penance card) {
@ -39,49 +44,4 @@ public final class Penance extends CardImpl {
public Penance copy() {
return new Penance(this);
}
}
class PenanceEffect extends PreventionEffectImpl {
private final TargetSource target;
public PenanceEffect() {
super(Duration.EndOfTurn, Integer.MAX_VALUE, false, false);
this.staticText = "The next time a black or red source of your choice would deal damage this turn, prevent that damage.";
this.target = new TargetSource();
}
private PenanceEffect(final PenanceEffect effect) {
super(effect);
this.target = effect.target.copy();
}
@Override
public PenanceEffect copy() {
return new PenanceEffect(this);
}
@Override
public void init(Ability source, Game game) {
super.init(source, game);
this.target.choose(Outcome.PreventDamage, source.getControllerId(), source.getSourceId(), source, game);
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
this.used = true;
this.discard(); // only one use
return true;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (!this.used && super.applies(event, source, game)) {
if (event.getSourceId().equals(target.getFirstTarget())) {
return (game.getObject(target.getFirstTarget()).getColor(game).contains(ObjectColor.BLACK)
|| game.getObject(target.getFirstTarget()).getColor(game).contains(ObjectColor.RED));
}
}
return false;
}
}
}

View file

@ -1,29 +1,28 @@
package mage.cards.p;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceToYouEffect;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Zone;
import java.util.UUID;
/**
*
* @author Quercitron
*/
public final class PentagramOfTheAges extends CardImpl {
public PentagramOfTheAges(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{4}");
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}");
// {4}, {tap}: The next time a source of your choice would deal damage to you this turn, prevent that damage.
Ability ability = new SimpleActivatedAbility(new PreventNextDamageFromChosenSourceToYouEffect(Duration.EndOfTurn), new GenericManaCost(4));
// {4}, {T}: The next time a source of your choice would deal damage to you this turn, prevent that damage.
Ability ability = new SimpleActivatedAbility(new PreventNextDamageFromChosenSourceEffect(Duration.EndOfTurn, true), new GenericManaCost(4));
ability.addCost(new TapSourceCost());
this.addAbility(ability);
}

View file

@ -6,19 +6,15 @@ import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.SacrificeSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.PreventionEffectImpl;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceEffect;
import mage.abilities.keyword.ProtectionAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
import mage.filter.FilterObject;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.game.Game;
import mage.game.events.DamageEvent;
import mage.game.events.GameEvent;
import mage.game.events.PreventDamageEvent;
import mage.game.events.PreventedDamageEvent;
import mage.target.TargetSource;
import java.util.UUID;
@ -27,6 +23,12 @@ import java.util.UUID;
*/
public final class PilgrimOfJustice extends CardImpl {
private static final FilterObject filter = new FilterObject("red source");
static {
filter.add(new ColorPredicate(ObjectColor.RED));
}
public PilgrimOfJustice(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}");
this.subtype.add(SubType.HUMAN);
@ -38,7 +40,10 @@ public final class PilgrimOfJustice extends CardImpl {
// Protection from red
this.addAbility(ProtectionAbility.from(ObjectColor.RED));
// {W}, Sacrifice Pilgrim of Justice: The next time a red source of your choice would deal damage this turn, prevent that damage.
Ability ability = new SimpleActivatedAbility(new PilgrimOfJusticeEffect(), new ManaCostsImpl<>("{W}"));
Ability ability = new SimpleActivatedAbility(
new PreventNextDamageFromChosenSourceEffect(Duration.EndOfTurn, false, filter),
new ManaCostsImpl<>("{W}")
);
ability.addCost(new SacrificeSourceCost());
this.addAbility(ability);
}
@ -51,60 +56,4 @@ public final class PilgrimOfJustice extends CardImpl {
public PilgrimOfJustice copy() {
return new PilgrimOfJustice(this);
}
}
class PilgrimOfJusticeEffect extends PreventionEffectImpl {
private static final FilterObject filter = new FilterObject("red source");
static {
filter.add(new ColorPredicate(ObjectColor.RED));
}
private TargetSource target;
public PilgrimOfJusticeEffect() {
super(Duration.EndOfTurn);
target = new TargetSource(filter);
staticText = "The next time a red source of your choice would deal damage to you this turn, prevent that damage";
}
private PilgrimOfJusticeEffect(final PilgrimOfJusticeEffect effect) {
super(effect);
this.target = effect.target.copy();
}
@Override
public PilgrimOfJusticeEffect copy() {
return new PilgrimOfJusticeEffect(this);
}
@Override
public void init(Ability source, Game game) {
super.init(source, game);
this.target.choose(Outcome.PreventDamage, source.getControllerId(), source.getSourceId(), source, game);
}
@Override
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());
if (!game.replaceEvent(preventEvent)) {
int damage = event.getAmount();
event.setAmount(0);
this.used = true; // one time use
game.fireEvent(new PreventedDamageEvent(event.getTargetId(), source.getSourceId(), source, source.getControllerId(), damage));
return true;
}
return false;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (!this.used && super.applies(event, source, game)) {
return event.getTargetId().equals(source.getControllerId()) && event.getSourceId().equals(target.getFirstTarget());
}
return false;
}
}
}

View file

@ -6,19 +6,15 @@ import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.SacrificeSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.PreventionEffectImpl;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceEffect;
import mage.abilities.keyword.ProtectionAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
import mage.filter.FilterObject;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.game.Game;
import mage.game.events.DamageEvent;
import mage.game.events.GameEvent;
import mage.game.events.PreventDamageEvent;
import mage.game.events.PreventedDamageEvent;
import mage.target.TargetSource;
import java.util.UUID;
@ -27,6 +23,12 @@ import java.util.UUID;
*/
public final class PilgrimOfVirtue extends CardImpl {
private static final FilterObject filter = new FilterObject("black source");
static {
filter.add(new ColorPredicate(ObjectColor.BLACK));
}
public PilgrimOfVirtue(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}");
this.subtype.add(SubType.HUMAN);
@ -38,7 +40,10 @@ public final class PilgrimOfVirtue extends CardImpl {
// Protection from black
this.addAbility(ProtectionAbility.from(ObjectColor.BLACK));
// {W}, Sacrifice Pilgrim of Virtue: The next time a black source of your choice would deal damage this turn, prevent that damage.
Ability ability = new SimpleActivatedAbility(new PilgrimOfVirtueEffect(), new ManaCostsImpl<>("{W}"));
Ability ability = new SimpleActivatedAbility(
new PreventNextDamageFromChosenSourceEffect(Duration.EndOfTurn, false, filter),
new ManaCostsImpl<>("{W}")
);
ability.addCost(new SacrificeSourceCost());
this.addAbility(ability);
}
@ -51,60 +56,4 @@ public final class PilgrimOfVirtue extends CardImpl {
public PilgrimOfVirtue copy() {
return new PilgrimOfVirtue(this);
}
}
class PilgrimOfVirtueEffect extends PreventionEffectImpl {
private static final FilterObject filter = new FilterObject("black source");
static {
filter.add(new ColorPredicate(ObjectColor.BLACK));
}
private final TargetSource target;
public PilgrimOfVirtueEffect() {
super(Duration.EndOfTurn);
target = new TargetSource(filter);
staticText = "The next time a black source of your choice would deal damage to you this turn, prevent that damage";
}
private PilgrimOfVirtueEffect(final PilgrimOfVirtueEffect effect) {
super(effect);
this.target = effect.target.copy();
}
@Override
public PilgrimOfVirtueEffect copy() {
return new PilgrimOfVirtueEffect(this);
}
@Override
public void init(Ability source, Game game) {
super.init(source, game);
this.target.choose(Outcome.PreventDamage, source.getControllerId(), source.getSourceId(), source, game);
}
@Override
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());
if (!game.replaceEvent(preventEvent)) {
int damage = event.getAmount();
event.setAmount(0);
this.used = true; // one time use
game.fireEvent(new PreventedDamageEvent(event.getTargetId(), source.getSourceId(), source, source.getControllerId(), damage));
return true;
}
return false;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (!this.used && super.applies(event, source, game)) {
return event.getTargetId().equals(source.getControllerId()) && event.getSourceId().equals(target.getFirstTarget());
}
return false;
}
}
}

View file

@ -2,31 +2,30 @@
package mage.cards.p;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.PreventDamageBySourceEffect;
import mage.abilities.effects.common.PreventDamageByChosenSourceEffect;
import mage.abilities.mana.ColorlessManaAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Zone;
/**
*
* @author LevelX2
*/
public final class PrahvSpiresOfOrder extends CardImpl {
public PrahvSpiresOfOrder(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.LAND},"");
super(ownerId, setInfo, new CardType[]{CardType.LAND}, "");
// {T}: Add {C}.
this.addAbility(new ColorlessManaAbility());
// {4}{W}{U}, {T}: Prevent all damage a source of your choice would deal this turn.
Ability ability = new SimpleActivatedAbility(new PreventDamageBySourceEffect(), new ManaCostsImpl<>("{4}{W}{U}"));
Ability ability = new SimpleActivatedAbility(new PreventDamageByChosenSourceEffect(), new ManaCostsImpl<>("{4}{W}{U}"));
ability.addCost(new TapSourceCost());
this.addAbility(ability);

View file

@ -1,27 +1,26 @@
package mage.cards.p;
import java.util.UUID;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.common.AsEntersBattlefieldAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.ChooseColorEffect;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceToYouEffect;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceEffect;
import mage.abilities.keyword.CumulativeUpkeepAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.FilterObject;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.game.Game;
import java.util.UUID;
/**
*
* @author TheElk801
*/
public final class PrismaticCircle extends CardImpl {
@ -36,7 +35,10 @@ public final class PrismaticCircle extends CardImpl {
this.addAbility(new AsEntersBattlefieldAbility(new ChooseColorEffect(Outcome.Neutral)));
// {1}: The next time a source of your choice of the chosen color would deal damage to you this turn, prevent that damage.
this.addAbility(new SimpleActivatedAbility(new PrismaticCircleEffect(), new ManaCostsImpl<>("{1}")));
this.addAbility(new SimpleActivatedAbility(
new PrismaticCircleEffect(),
new ManaCostsImpl<>("{1}")
));
}
private PrismaticCircle(final PrismaticCircle card) {
@ -49,10 +51,11 @@ public final class PrismaticCircle extends CardImpl {
}
}
class PrismaticCircleEffect extends PreventNextDamageFromChosenSourceToYouEffect {
// TODO: create a FilterSource that can handle ChosenColorPredicate.TRUE and simplify this.
class PrismaticCircleEffect extends PreventNextDamageFromChosenSourceEffect {
PrismaticCircleEffect() {
super(Duration.EndOfTurn);
super(Duration.EndOfTurn, true);
staticText = "The next time a source of your choice of the chosen color would deal damage to you this turn, prevent that damage.";
}

View file

@ -1,32 +1,30 @@
package mage.cards.r;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.PreventionEffectData;
import mage.abilities.effects.PreventionEffectImpl;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.players.Player;
import mage.target.TargetSource;
import java.util.UUID;
/**
*
* @author Quercitron
*/
public final class ReverseDamage extends CardImpl {
public ReverseDamage(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{W}{W}");
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}{W}");
// The next time a source of your choice would deal damage to you this turn, prevent that damage. You gain life equal to the damage prevented this way.
this.getSpellAbility().addEffect(new ReverseDamageEffect());
this.getSpellAbility().addEffect(
new PreventNextDamageFromChosenSourceEffect(
Duration.EndOfTurn, true,
PreventNextDamageFromChosenSourceEffect.ON_PREVENT_YOU_GAIN_THAT_MUCH_LIFE
)
);
}
private ReverseDamage(final ReverseDamage card) {
@ -37,55 +35,4 @@ public final class ReverseDamage extends CardImpl {
public ReverseDamage copy() {
return new ReverseDamage(this);
}
}
class ReverseDamageEffect extends PreventionEffectImpl {
private final TargetSource target;
public ReverseDamageEffect() {
super(Duration.EndOfTurn, Integer.MAX_VALUE, false, false);
this.staticText = "The next time a source of your choice would deal damage to you this turn, prevent that damage. You gain life equal to the damage prevented this way.";
this.target = new TargetSource();
}
private ReverseDamageEffect(final ReverseDamageEffect effect) {
super(effect);
this.target = effect.target.copy();
}
@Override
public ReverseDamageEffect copy() {
return new ReverseDamageEffect(this);
}
@Override
public void init(Ability source, Game game) {
super.init(source, game);
this.target.choose(Outcome.PreventDamage, source.getControllerId(), source.getSourceId(), source, game);
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
PreventionEffectData preventionData = preventDamageAction(event, source, game);
this.used = true;
this.discard(); // only one use
if (preventionData.getPreventedDamage() > 0) {
Player player = game.getPlayer(source.getControllerId());
if (player != null) {
player.gainLife(preventionData.getPreventedDamage(), game, source);
}
}
return true;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (!this.used && super.applies(event, source, game)) {
if (event.getTargetId().equals(source.getControllerId()) && event.getSourceId().equals(target.getFirstTarget())) {
return true;
}
}
return false;
}
}
}

View file

@ -1,31 +1,33 @@
package mage.cards.r;
import java.util.UUID;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.DoUnlessAnyPlayerPaysEffect;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceToYouEffect;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Zone;
import java.util.UUID;
/**
*
* @author djbrez
*/
public final class RhysticCircle extends CardImpl {
public RhysticCircle(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{W}{W}");
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}{W}");
// {1}: Any player may pay {1}. If no one does, the next time a source of your choice would deal damage to you this turn, prevent that damage.
this.addAbility(new SimpleActivatedAbility(
new DoUnlessAnyPlayerPaysEffect(new PreventNextDamageFromChosenSourceToYouEffect(Duration.EndOfTurn),new GenericManaCost(1)),
this.addAbility(new SimpleActivatedAbility(
new DoUnlessAnyPlayerPaysEffect(
new PreventNextDamageFromChosenSourceEffect(Duration.EndOfTurn, true),
new GenericManaCost(1)
),
new ManaCostsImpl<>("{1}")));
}

View file

@ -1,29 +1,31 @@
package mage.cards.r;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.PayLifeCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceToYouEffect;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Zone;
import java.util.UUID;
/**
*
* @author anonymous
*/
public final class RighteousAura extends CardImpl {
public RighteousAura(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{W}");
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}");
// {W}, Pay 2 life: The next time a source of your choice would deal damage to you this turn, prevent that damage.
Ability ability = new SimpleActivatedAbility(new PreventNextDamageFromChosenSourceToYouEffect(Duration.EndOfTurn), new ManaCostsImpl<>("{W}"));
Ability ability = new SimpleActivatedAbility(
new PreventNextDamageFromChosenSourceEffect(Duration.EndOfTurn, true),
new ManaCostsImpl<>("{W}")
);
ability.addCost(new PayLifeCost(2));
this.addAbility(ability);
}

View file

@ -2,10 +2,11 @@
package mage.cards.r;
import java.util.UUID;
import mage.abilities.Mode;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.abilities.effects.common.PreventDamageBySourceEffect;
import mage.abilities.effects.common.PreventDamageByChosenSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
@ -13,13 +14,12 @@ import mage.game.permanent.token.SaprolingToken;
import mage.target.common.TargetNonBasicLandPermanent;
/**
*
* @author FenrisulfrX
*/
public final class RithsCharm extends CardImpl {
public RithsCharm(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{R}{G}{W}");
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{R}{G}{W}");
// Choose one - Destroy target nonbasic land;
this.getSpellAbility().addEffect(new DestroyTargetEffect());
@ -30,7 +30,7 @@ public final class RithsCharm extends CardImpl {
this.getSpellAbility().addMode(mode);
// or prevent all damage a source of your choice would deal this turn.
mode = new Mode(new PreventDamageBySourceEffect());
mode = new Mode(new PreventDamageByChosenSourceEffect());
this.getSpellAbility().addMode(mode);
}

View file

@ -1,36 +1,36 @@
package mage.cards.r;
import java.util.UUID;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceToYouEffect;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceEffect;
import mage.abilities.keyword.CyclingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Zone;
import mage.filter.FilterObject;
import java.util.UUID;
/**
*
* @author fireshoes
*/
public final class RuneOfProtectionArtifacts extends CardImpl {
private static final FilterObject filter = new FilterObject("artifact source");
static {
filter.add(CardType.ARTIFACT.getPredicate());
}
public RuneOfProtectionArtifacts(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{W}");
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}");
// {W}: The next time an artifact source of your choice would deal damage to you this turn, prevent that damage.
Effect effect = new PreventNextDamageFromChosenSourceToYouEffect(Duration.EndOfTurn, filter);
Effect effect = new PreventNextDamageFromChosenSourceEffect(Duration.EndOfTurn, true, filter);
this.addAbility(new SimpleActivatedAbility(effect, new ManaCostsImpl<>("{W}")));
// Cycling {2} ({2}, Discard this card: Draw a card.)
this.addAbility(new CyclingAbility(new ManaCostsImpl<>("{2}")));

View file

@ -1,36 +1,38 @@
package mage.cards.r;
import java.util.UUID;
import mage.ObjectColor;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceToYouEffect;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceEffect;
import mage.abilities.keyword.CyclingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.filter.FilterObject;
import mage.filter.predicate.mageobject.ColorPredicate;
import java.util.UUID;
/**
*
* @author Backfir3
*/
public final class RuneOfProtectionBlack extends CardImpl {
private static final FilterObject filter = new FilterObject("black source");
static {
filter.add(new ColorPredicate(ObjectColor.BLACK));
}
public RuneOfProtectionBlack(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{W}");
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}");
// {W}: The next time a black source of your choice would deal damage to you this turn, prevent that damage.
Effect effect = new PreventNextDamageFromChosenSourceToYouEffect(Duration.EndOfTurn, filter);
Effect effect = new PreventNextDamageFromChosenSourceEffect(Duration.EndOfTurn, true, filter);
this.addAbility(new SimpleActivatedAbility(effect, new ManaCostsImpl<>("{W}")));
// Cycling {2} ({2}, Discard this card: Draw a card.)
this.addAbility(new CyclingAbility(new ManaCostsImpl<>("{2}")));

View file

@ -1,36 +1,38 @@
package mage.cards.r;
import java.util.UUID;
import mage.ObjectColor;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceToYouEffect;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceEffect;
import mage.abilities.keyword.CyclingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.filter.FilterObject;
import mage.filter.predicate.mageobject.ColorPredicate;
import java.util.UUID;
/**
*
* @author Backfir3
*/
public final class RuneOfProtectionBlue extends CardImpl {
private static final FilterObject filter = new FilterObject("blue source");
static {
filter.add(new ColorPredicate(ObjectColor.BLUE));
}
public RuneOfProtectionBlue(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{W}");
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}");
// {W}: The next time a blue source of your choice would deal damage to you this turn, prevent that damage.
Effect effect = new PreventNextDamageFromChosenSourceToYouEffect(Duration.EndOfTurn, filter);
Effect effect = new PreventNextDamageFromChosenSourceEffect(Duration.EndOfTurn, true, filter);
this.addAbility(new SimpleActivatedAbility(effect, new ManaCostsImpl<>("{W}")));
// Cycling {2} ({2}, Discard this card: Draw a card.)
this.addAbility(new CyclingAbility(new ManaCostsImpl<>("{2}")));

View file

@ -1,36 +1,38 @@
package mage.cards.r;
import java.util.UUID;
import mage.ObjectColor;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceToYouEffect;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceEffect;
import mage.abilities.keyword.CyclingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.filter.FilterObject;
import mage.filter.predicate.mageobject.ColorPredicate;
import java.util.UUID;
/**
*
* @author Backfir3
*/
public final class RuneOfProtectionGreen extends CardImpl {
private static final FilterObject filter = new FilterObject("green source");
static {
filter.add(new ColorPredicate(ObjectColor.GREEN));
}
public RuneOfProtectionGreen(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{W}");
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}");
// {W}: The next time a green source of your choice would deal damage to you this turn, prevent that damage.
Effect effect = new PreventNextDamageFromChosenSourceToYouEffect(Duration.EndOfTurn, filter);
Effect effect = new PreventNextDamageFromChosenSourceEffect(Duration.EndOfTurn, true, filter);
this.addAbility(new SimpleActivatedAbility(effect, new ManaCostsImpl<>("{W}")));
// Cycling {2} ({2}, Discard this card: Draw a card.)
this.addAbility(new CyclingAbility(new ManaCostsImpl<>("{2}")));

View file

@ -1,36 +1,36 @@
package mage.cards.r;
import java.util.UUID;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceToYouEffect;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceEffect;
import mage.abilities.keyword.CyclingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Zone;
import mage.filter.FilterObject;
import java.util.UUID;
/**
*
* @author fireshoes
*/
public final class RuneOfProtectionLands extends CardImpl {
private static final FilterObject filter = new FilterObject("land source");
static {
filter.add(CardType.LAND.getPredicate());
}
public RuneOfProtectionLands(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{W}");
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}");
// {W}: The next time a land source of your choice would deal damage to you this turn, prevent that damage.
Effect effect = new PreventNextDamageFromChosenSourceToYouEffect(Duration.EndOfTurn, filter);
Effect effect = new PreventNextDamageFromChosenSourceEffect(Duration.EndOfTurn, true, filter);
this.addAbility(new SimpleActivatedAbility(effect, new ManaCostsImpl<>("{W}")));
// Cycling {2} ({2}, Discard this card: Draw a card.)
this.addAbility(new CyclingAbility(new ManaCostsImpl<>("{2}")));

View file

@ -1,36 +1,38 @@
package mage.cards.r;
import java.util.UUID;
import mage.ObjectColor;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceToYouEffect;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceEffect;
import mage.abilities.keyword.CyclingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.filter.FilterObject;
import mage.filter.predicate.mageobject.ColorPredicate;
import java.util.UUID;
/**
*
* @author Backfir3
*/
public final class RuneOfProtectionRed extends CardImpl {
private static final FilterObject filter = new FilterObject("red source");
static {
filter.add(new ColorPredicate(ObjectColor.RED));
}
public RuneOfProtectionRed(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{W}");
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}");
// {W}: The next time a red source of your choice would deal damage to you this turn, prevent that damage.
Effect effect = new PreventNextDamageFromChosenSourceToYouEffect(Duration.EndOfTurn, filter);
Effect effect = new PreventNextDamageFromChosenSourceEffect(Duration.EndOfTurn, true, filter);
this.addAbility(new SimpleActivatedAbility(effect, new ManaCostsImpl<>("{W}")));
// Cycling {2} ({2}, Discard this card: Draw a card.)
this.addAbility(new CyclingAbility(new ManaCostsImpl<>("{2}")));

View file

@ -1,36 +1,38 @@
package mage.cards.r;
import java.util.UUID;
import mage.ObjectColor;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceToYouEffect;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceEffect;
import mage.abilities.keyword.CyclingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.filter.FilterObject;
import mage.filter.predicate.mageobject.ColorPredicate;
import java.util.UUID;
/**
*
* @author Backfir3
*/
public final class RuneOfProtectionWhite extends CardImpl {
private static final FilterObject filter = new FilterObject("white source");
static {
filter.add(new ColorPredicate(ObjectColor.WHITE));
}
public RuneOfProtectionWhite(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{W}");
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}");
// {W}: The next time a white source of your choice would deal damage to you this turn, prevent that damage.
Effect effect = new PreventNextDamageFromChosenSourceToYouEffect(Duration.EndOfTurn, filter);
Effect effect = new PreventNextDamageFromChosenSourceEffect(Duration.EndOfTurn, true, filter);
this.addAbility(new SimpleActivatedAbility(effect, new ManaCostsImpl<>("{W}")));
// Cycling {2} ({2}, Discard this card: Draw a card.)
this.addAbility(new CyclingAbility(new ManaCostsImpl<>("{2}")));

View file

@ -1,37 +1,37 @@
package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.ExileFromTopOfLibraryCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceToYouEffect;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Zone;
import mage.constants.SubType;
import java.util.UUID;
/**
*
* @author LoneFox
*/
public final class SeasonedTactician extends CardImpl {
public SeasonedTactician(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{W}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.ADVISOR);
this.power = new MageInt(1);
this.toughness = new MageInt(3);
// {3}, Exile the top four cards of your library: The next time a source of your choice would deal damage to you this turn, prevent that damage.
Ability ability = new SimpleActivatedAbility(new PreventNextDamageFromChosenSourceToYouEffect(Duration.EndOfTurn),
new ManaCostsImpl<>("{3}"));
Ability ability = new SimpleActivatedAbility(
new PreventNextDamageFromChosenSourceEffect(Duration.EndOfTurn, true),
new ManaCostsImpl<>("{3}")
);
ability.addCost(new ExileFromTopOfLibraryCost(4));
this.addAbility(ability);
}

View file

@ -1,38 +1,40 @@
package mage.cards.s;
import java.util.UUID;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.common.AsEntersBattlefieldAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.ChooseColorEffect;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceToYouEffect;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.FilterObject;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.game.Game;
import java.util.UUID;
/**
*
* @author LoneFox
*/
public final class StoryCircle extends CardImpl {
public StoryCircle(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{W}{W}");
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}{W}");
// As Story Circle enters the battlefield, choose a color.
this.addAbility(new AsEntersBattlefieldAbility(new ChooseColorEffect(Outcome.Neutral)));
// {W}: The next time a source of your choice of the chosen color would deal damage to you this turn, prevent that damage.
this.addAbility(new SimpleActivatedAbility(new StoryCircleEffect(), new ManaCostsImpl<>("{W}")));
this.addAbility(new SimpleActivatedAbility(
new StoryCircleEffect(),
new ManaCostsImpl<>("{W}")
));
}
private StoryCircle(final StoryCircle card) {
@ -45,10 +47,11 @@ public final class StoryCircle extends CardImpl {
}
}
class StoryCircleEffect extends PreventNextDamageFromChosenSourceToYouEffect {
// TODO: create a FilterSource that can handle ChosenColorPredicate.TRUE and simplify this.
class StoryCircleEffect extends PreventNextDamageFromChosenSourceEffect {
StoryCircleEffect() {
super(Duration.EndOfTurn);
super(Duration.EndOfTurn, true);
staticText = "The next time a source of your choice of the chosen color would deal damage to you this turn, prevent that damage.";
}

View file

@ -0,0 +1,77 @@
package org.mage.test.cards.single.aer;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
* @author Susucr
*/
public class AjanisAidTest extends CardTestPlayerBase {
/**
* {@link mage.cards.a.AjanisAid Ajani's Aid} {2}{G}{W}
* Enchantment
* When this enchantment enters, you may search your library and/or graveyard for a card named Ajani, Valiant Protector, reveal it, and put it into your hand. If you search your library this way, shuffle.
* Sacrifice this enchantment: Prevent all combat damage a creature of your choice would deal this turn.
*/
private static final String aid = "Ajani's Aid";
@Test
public void test_DamageOnCreature_Prevent() {
addCard(Zone.BATTLEFIELD, playerA, aid, 1);
addCard(Zone.BATTLEFIELD, playerB, "Goblin Piker", 1); // 2/1
addCard(Zone.BATTLEFIELD, playerA, "Caelorna, Coral Tyrant"); // 0/8
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerA, "Sacrifice");
setChoice(playerA, "Goblin Piker"); // creature to prevent from
attack(2, playerB, "Goblin Piker", playerA);
block(2, playerA, "Caelorna, Coral Tyrant", "Goblin Piker");
setStrictChooseMode(true);
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertDamageReceived(playerA, "Caelorna, Coral Tyrant", 0);
assertTapped("Goblin Piker", true);
assertGraveyardCount(playerA, aid, 1);
}
@Test
public void test_DamageOnYou_Prevent() {
addCard(Zone.BATTLEFIELD, playerA, aid, 1);
addCard(Zone.BATTLEFIELD, playerB, "Goblin Piker", 1); // 2/1
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerA, "Sacrifice");
setChoice(playerA, "Goblin Piker"); // source to prevent from
attack(2, playerB, "Goblin Piker", playerA);
setStrictChooseMode(true);
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertLife(playerA, 20);
assertTapped("Goblin Piker", true);
assertGraveyardCount(playerA, aid, 1);
}
@Test
public void test_DamageNonCombat_NoPrevent() {
addCard(Zone.BATTLEFIELD, playerA, aid, 1);
addCard(Zone.BATTLEFIELD, playerB, "Prodigal Pyromancer", 1); // {T}: This creature deals 1 damage to any target.
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Sacrifice");
setChoice(playerA, "Prodigal Pyromancer"); // source to prevent from
activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerB, "{T}: ", playerA);
setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertLife(playerA, 20 - 1);
assertGraveyardCount(playerA, aid, 1);
}
}

View file

@ -0,0 +1,61 @@
package org.mage.test.cards.single.exo;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
* @author Susucr
*/
public class PenanceTest extends CardTestPlayerBase {
/**
* {@link mage.cards.p.Penance Penance} {2}{W}
* Enchantment
* Put a card from your hand on top of your library: The next time a black or red source of your choice would deal damage this turn, prevent that damage.
*/
private static final String penance = "Penance";
@Test
public void test_DamageOnCreature_Prevent() {
addCard(Zone.BATTLEFIELD, playerA, penance, 1);
addCard(Zone.BATTLEFIELD, playerB, "Goblin Piker", 1); // 2/1
addCard(Zone.BATTLEFIELD, playerA, "Caelorna, Coral Tyrant"); // 0/8
addCard(Zone.HAND, playerA, "Plains", 1);
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerA, "Put a card");
setChoice(playerA, "Plains"); // card to put on top
setChoice(playerA, "Goblin Piker"); // source to prevent from
attack(2, playerB, "Goblin Piker", playerA);
block(2, playerA, "Caelorna, Coral Tyrant", "Goblin Piker");
setStrictChooseMode(true);
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertDamageReceived(playerA, "Caelorna, Coral Tyrant", 0);
assertTapped("Goblin Piker", true);
}
@Test
public void test_DamageOnYou_Prevent() {
addCard(Zone.BATTLEFIELD, playerA, penance, 1);
addCard(Zone.BATTLEFIELD, playerB, "Goblin Piker", 1); // 2/1
addCard(Zone.HAND, playerA, "Plains", 1);
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerA, "Put a card");
setChoice(playerA, "Plains"); // card to put on top
setChoice(playerA, "Goblin Piker"); // source to prevent from
attack(2, playerB, "Goblin Piker", playerA);
setStrictChooseMode(true);
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertLife(playerA, 20);
assertTapped("Goblin Piker", true);
}
}

View file

@ -0,0 +1,78 @@
package org.mage.test.cards.single.ktk;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
* @author Susucr
*/
public class DeflectingPalmTest extends CardTestPlayerBase {
/**
* {@link mage.cards.d.DeflectingPalm Deflecting Palm} {R}{W}
* Instant
* The next time a source of your choice would deal damage to you this turn, prevent that damage. If damage is prevented this way, Deflecting Palm deals that much damage to that sources controller.
*/
private static final String palm = "Deflecting Palm";
@Test
public void test_DamageOnCreature_NoPrevent() {
addCard(Zone.HAND, playerA, palm, 1);
addCard(Zone.BATTLEFIELD, playerB, "Goblin Piker", 1); // 2/1
addCard(Zone.BATTLEFIELD, playerA, "Caelorna, Coral Tyrant"); // 0/8
addCard(Zone.BATTLEFIELD, playerA, "Plateau", 2);
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerA, palm);
setChoice(playerA, "Goblin Piker"); // source to prevent from
attack(2, playerB, "Goblin Piker", playerA);
block(2, playerA, "Caelorna, Coral Tyrant", "Goblin Piker");
setStrictChooseMode(true);
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertDamageReceived(playerA, "Caelorna, Coral Tyrant", 2); // no prevent
assertLife(playerB, 20);
}
@Test
public void test_DamageOnYou_Prevent() {
addCard(Zone.HAND, playerA, palm, 1);
addCard(Zone.BATTLEFIELD, playerB, "Goblin Piker", 1); // 2/1
addCard(Zone.BATTLEFIELD, playerA, "Plateau", 2);
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerA, palm);
setChoice(playerA, "Goblin Piker"); // source to prevent from
attack(2, playerB, "Goblin Piker", playerA);
setStrictChooseMode(true);
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertLife(playerA, 20);
assertLife(playerB, 20 - 2);
}
@Test
public void test_DoubleStrike_Prevent_ThenConsumedAndNoPrevent() {
addCard(Zone.HAND, playerA, palm, 1);
addCard(Zone.BATTLEFIELD, playerB, "Blade Historian", 1); // 2/3 "Attacking creatures you control have double strike."
addCard(Zone.BATTLEFIELD, playerA, "Plateau", 2);
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerA, palm);
setChoice(playerA, "Blade Historian"); // source to prevent from
attack(2, playerB, "Blade Historian", playerA);
setStrictChooseMode(true);
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertLife(playerA, 20 - 2);
assertLife(playerB, 20 - 2);
}
}

View file

@ -0,0 +1,227 @@
package org.mage.test.cards.single.lea;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
* @author Susucr
*/
public class CircleOfProtectionTest extends CardTestPlayerBase {
/**
* {@link mage.cards.c.CircleOfProtectionRed Circle of Protection: Red} {1}{W}
* Enchantment
* {1}: The next time a red source of your choice would deal damage to you this turn, prevent that damage.
*/
private static final String circleRed = "Circle of Protection: Red";
/**
* {@link mage.cards.c.CircleOfProtectionGreen Circle of Protection: Green} {1}{W}
* Enchantment
* {1}: The next time a green source of your choice would deal damage to you this turn, prevent that damage.
*/
private static final String circleGreen = "Circle of Protection: Green";
@Test
public void test_DamageOnCreature_NoPrevent() {
addCard(Zone.BATTLEFIELD, playerA, circleRed, 1);
addCard(Zone.BATTLEFIELD, playerB, "Goblin Piker", 1); // 2/1
addCard(Zone.BATTLEFIELD, playerA, "Caelorna, Coral Tyrant"); // 0/8
addCard(Zone.BATTLEFIELD, playerA, "Plains", 14);
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}");
setChoice(playerA, "Goblin Piker"); // source to prevent from
attack(2, playerB, "Goblin Piker", playerA);
block(2, playerA, "Caelorna, Coral Tyrant", "Goblin Piker");
setStrictChooseMode(true);
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertDamageReceived(playerA, "Caelorna, Coral Tyrant", 2); // no prevent
assertLife(playerB, 20);
assertTappedCount("Plains", true, 1);
}
@Test
public void test_DamageOnYou_Prevent() {
addCard(Zone.BATTLEFIELD, playerA, circleRed, 1);
addCard(Zone.BATTLEFIELD, playerB, "Goblin Piker", 1); // 2/1
addCard(Zone.BATTLEFIELD, playerA, "Plains", 1);
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}");
setChoice(playerA, "Goblin Piker"); // source to prevent from
attack(2, playerB, "Goblin Piker", playerA);
setStrictChooseMode(true);
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertLife(playerA, 20);
assertTappedCount("Plains", true, 1);
}
@Test
public void test_DoubleStrike_Prevent_ThenConsumedAndNoPrevent() {
addCard(Zone.BATTLEFIELD, playerA, circleRed, 1);
addCard(Zone.BATTLEFIELD, playerB, "Blade Historian", 1); // 2/3 "Attacking creatures you control have double strike."
addCard(Zone.BATTLEFIELD, playerA, "Plains", 1);
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}");
setChoice(playerA, "Blade Historian"); // source to prevent from
attack(2, playerB, "Blade Historian", playerA);
setStrictChooseMode(true);
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertLife(playerA, 20 - 2);
assertTappedCount("Plains", true, 1);
}
@Test
public void test_NoSourceOfCircleColor_NoPrevent() {
addCard(Zone.BATTLEFIELD, playerA, circleGreen, 1);
addCard(Zone.BATTLEFIELD, playerB, "Goblin Piker", 1); // 2/1
addCard(Zone.BATTLEFIELD, playerA, "Plains", 1);
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}");
// No possible choice for a green source
attack(2, playerB, "Goblin Piker", playerA);
setStrictChooseMode(true);
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertLife(playerA, 20 - 2); // no prevention
assertTappedCount("Plains", true, 1);
}
@Test
public void test_SpellDamageOnYou_Prevent() {
addCard(Zone.BATTLEFIELD, playerA, circleRed, 1);
addCard(Zone.HAND, playerB, "Lightning Bolt", 1);
addCard(Zone.BATTLEFIELD, playerA, "Plains", 1);
addCard(Zone.BATTLEFIELD, playerB, "Mountain");
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Lightning Bolt", playerA);
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}", null, "Lightning Bolt");
setChoice(playerA, "Lightning Bolt"); // source to prevent from
setStrictChooseMode(true);
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertLife(playerA, 20);
assertGraveyardCount(playerB, "Lightning Bolt", 1);
assertTappedCount("Plains", true, 1);
}
@Test
public void test_SpellNotChosenColorDamageOnYou_NoPrevent() {
addCard(Zone.BATTLEFIELD, playerA, circleGreen, 1);
addCard(Zone.HAND, playerB, "Lightning Bolt", 1);
addCard(Zone.BATTLEFIELD, playerA, "Plains", 1);
addCard(Zone.BATTLEFIELD, playerB, "Mountain");
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Lightning Bolt", playerA);
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}", null, "Lightning Bolt");
// no possible choice for "a green source"
setStrictChooseMode(true);
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertLife(playerA, 20 - 3);
assertGraveyardCount(playerB, "Lightning Bolt", 1);
assertTappedCount("Plains", true, 1);
}
@Test
public void test_TriggerDamageOnYou_Prevent() {
addCard(Zone.BATTLEFIELD, playerA, circleRed, 1);
addCard(Zone.HAND, playerB, "Blisterstick Shaman", 1); // etb deals 1 to any target
addCard(Zone.BATTLEFIELD, playerA, "Plains", 1);
addCard(Zone.BATTLEFIELD, playerB, "Mountain", 3);
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Blisterstick Shaman");
addTarget(playerB, playerA); // target for Shaman trigger
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}", null, "stack ability (When");
setChoice(playerA, "Blisterstick Shaman"); // source to prevent from
setStrictChooseMode(true);
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertLife(playerA, 20);
assertPermanentCount(playerB, "Blisterstick Shaman", 1);
assertTappedCount("Plains", true, 1);
}
@Test
public void test_TriggerNotChosenColorDamageOnYou_NoPrevent() {
addCard(Zone.BATTLEFIELD, playerA, circleGreen, 1);
addCard(Zone.HAND, playerB, "Blisterstick Shaman", 1); // etb deals 1 to any target
addCard(Zone.BATTLEFIELD, playerA, "Plains", 1);
addCard(Zone.BATTLEFIELD, playerB, "Mountain", 3);
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Blisterstick Shaman");
addTarget(playerB, playerA); // target for Shaman trigger
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}", null, "stack ability (When");
// no possible choice for "a green source"
setStrictChooseMode(true);
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertLife(playerA, 20 - 1);
assertPermanentCount(playerB, "Blisterstick Shaman", 1);
assertTappedCount("Plains", true, 1);
}
@Test
public void test_ActivationDamageOnYou_Prevent() {
addCard(Zone.BATTLEFIELD, playerA, circleRed, 1);
addCard(Zone.BATTLEFIELD, playerB, "Anaba Shaman", 1); // {R}, {T}: This creature deals 1 damage to any target.
addCard(Zone.BATTLEFIELD, playerA, "Plains", 1);
addCard(Zone.BATTLEFIELD, playerB, "Mountain", 1);
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerB, "{R},", playerA);
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}", null, "stack ability ({R}");
setChoice(playerA, "Anaba Shaman"); // source to prevent from
setStrictChooseMode(true);
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertTappedCount("Anaba Shaman", true, 1);
assertTappedCount("Plains", true, 1);
assertLife(playerA, 20);
}
@Test
public void test_ActivationNotChosenColorDamageOnYou_NoPrevent() {
addCard(Zone.BATTLEFIELD, playerA, circleGreen, 1);
addCard(Zone.BATTLEFIELD, playerB, "Anaba Shaman", 1); // {R}, {T}: This creature deals 1 damage to any target.
addCard(Zone.BATTLEFIELD, playerA, "Plains", 1);
addCard(Zone.BATTLEFIELD, playerB, "Mountain", 1);
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerB, "{R},", playerA);
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}", null, "stack ability ({R}");
// no possible choice for "a green source"
setStrictChooseMode(true);
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertTappedCount("Anaba Shaman", true, 1);
assertTappedCount("Plains", true, 1);
assertLife(playerA, 20 - 1);
}
}

View file

@ -0,0 +1,78 @@
package org.mage.test.cards.single.mir;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
* @author Susucr
*/
public class BoneMaskTest extends CardTestPlayerBase {
/**
* {@link mage.cards.b.BoneMask Bone Mask} {4}
* Artifact
* {2}, {T}: The next time a source of your choice would deal damage to you this turn, prevent that damage. Exile cards from the top of your library equal to the damage prevented this way.
*/
private static final String mask = "Bone Mask";
@Test
public void test_DamageOnCreature_NoPrevent() {
addCard(Zone.BATTLEFIELD, playerA, mask, 1);
addCard(Zone.BATTLEFIELD, playerB, "Goblin Piker", 1); // 2/1
addCard(Zone.BATTLEFIELD, playerA, "Caelorna, Coral Tyrant"); // 0/8
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerA, "{2}");
setChoice(playerA, "Goblin Piker"); // source to prevent from
attack(2, playerB, "Goblin Piker", playerA);
block(2, playerA, "Caelorna, Coral Tyrant", "Goblin Piker");
setStrictChooseMode(true);
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertDamageReceived(playerA, "Caelorna, Coral Tyrant", 2); // no prevent
assertExileCount(playerA, 0);
}
@Test
public void test_DamageOnYou_Prevent() {
addCard(Zone.BATTLEFIELD, playerA, mask, 1);
addCard(Zone.BATTLEFIELD, playerB, "Goblin Piker", 1); // 2/1
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerA, "{2}");
setChoice(playerA, "Goblin Piker"); // source to prevent from
attack(2, playerB, "Goblin Piker", playerA);
setStrictChooseMode(true);
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertLife(playerA, 20);
assertExileCount(playerA, 2);
}
@Test
public void test_DoubleStrike_Prevent_ThenConsumedAndNoPrevent() {
addCard(Zone.BATTLEFIELD, playerA, mask, 1);
addCard(Zone.BATTLEFIELD, playerB, "Blade Historian", 1); // 2/3 "Attacking creatures you control have double strike."
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerA, "{2}");
setChoice(playerA, "Blade Historian"); // source to prevent from
attack(2, playerB, "Blade Historian", playerA);
setStrictChooseMode(true);
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertLife(playerA, 20 - 2);
assertExileCount(playerA, 2);
}
}

View file

@ -0,0 +1,86 @@
package org.mage.test.cards.single.mmq;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
* @author Susucr
*/
public class ChoArrimAlchemistTest extends CardTestPlayerBase {
/**
* {@link mage.cards.c.ChoArrimAlchemist Cho-Arrim Alchemist} {W}
* Creature Human Spellshaper
* {1}{W}{W}, {T}, Discard a card: The next time a source of your choice would deal damage to you this turn, prevent that damage. You gain life equal to the damage prevented this way.
* 1/1
*/
private static final String alchemist = "Cho-Arrim Alchemist";
@Test
public void test_DamageOnCreature_NoPrevent() {
addCard(Zone.BATTLEFIELD, playerA, alchemist, 1);
addCard(Zone.HAND, playerA, "Lightning Bolt", 1); // to discard
addCard(Zone.BATTLEFIELD, playerB, "Goblin Piker", 1); // 2/1
addCard(Zone.BATTLEFIELD, playerA, "Caelorna, Coral Tyrant"); // 0/8
addCard(Zone.BATTLEFIELD, playerA, "Plains", 3);
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}{W}{W}");
setChoice(playerA, "Lightning Bolt"); // discard to activate
setChoice(playerA, "Goblin Piker"); // source to prevent from
attack(2, playerB, "Goblin Piker", playerA);
block(2, playerA, "Caelorna, Coral Tyrant", "Goblin Piker");
setStrictChooseMode(true);
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertDamageReceived(playerA, "Caelorna, Coral Tyrant", 2); // no prevent
assertGraveyardCount(playerA, "Lightning Bolt", 1);
}
@Test
public void test_DamageOnYou_Prevent() {
addCard(Zone.BATTLEFIELD, playerA, alchemist, 1);
addCard(Zone.HAND, playerA, "Lightning Bolt", 1); // to discard
addCard(Zone.BATTLEFIELD, playerB, "Goblin Piker", 1); // 2/1
addCard(Zone.BATTLEFIELD, playerA, "Plains", 3);
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}{W}{W}");
setChoice(playerA, "Lightning Bolt"); // discard to activate
setChoice(playerA, "Goblin Piker"); // source to prevent from
attack(2, playerB, "Goblin Piker", playerA);
setStrictChooseMode(true);
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertLife(playerA, 20 + 2);
assertGraveyardCount(playerA, "Lightning Bolt", 1);
}
@Test
public void test_DoubleStrike_Prevent_ThenConsumedAndNoPrevent() {
addCard(Zone.BATTLEFIELD, playerA, alchemist, 1);
addCard(Zone.HAND, playerA, "Lightning Bolt", 1); // to discard
addCard(Zone.BATTLEFIELD, playerB, "Blade Historian", 1); // 2/3 "Attacking creatures you control have double strike."
addCard(Zone.BATTLEFIELD, playerA, "Plains", 3);
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}{W}{W}");
setChoice(playerA, "Lightning Bolt"); // discard to activate
setChoice(playerA, "Blade Historian"); // source to prevent from
attack(2, playerB, "Blade Historian", playerA);
setStrictChooseMode(true);
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertLife(playerA, 20);
assertTapped("Blade Historian", true);
assertGraveyardCount(playerA, "Lightning Bolt", 1);
}
}

View file

@ -0,0 +1,251 @@
package org.mage.test.cards.single.mmq;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
* @author Susucr
*/
public class StoryCircleTest extends CardTestPlayerBase {
/**
* {@link mage.cards.s.StoryCircle Story Circle} {1}{W}{W}
* Enchantment
* As this enchantment enters, choose a color.
* {W}: The next time a source of your choice of the chosen color would deal damage to you this turn, prevent that damage.
*/
private static final String circle = "Story Circle";
@Test
public void test_DamageOnCreature_NoPrevent() {
addCard(Zone.HAND, playerA, circle, 1);
addCard(Zone.BATTLEFIELD, playerB, "Goblin Piker", 1); // 2/1
addCard(Zone.BATTLEFIELD, playerA, "Caelorna, Coral Tyrant"); // 0/8
addCard(Zone.BATTLEFIELD, playerA, "Plains", 4);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, circle);
setChoice(playerA, "Red"); // color chosen
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerA, "{W}");
setChoice(playerA, "Goblin Piker"); // source to prevent from
attack(2, playerB, "Goblin Piker", playerA);
block(2, playerA, "Caelorna, Coral Tyrant", "Goblin Piker");
setStrictChooseMode(true);
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertDamageReceived(playerA, "Caelorna, Coral Tyrant", 2); // no prevent
assertLife(playerB, 20);
assertTappedCount("Plains", true, 4);
}
@Test
public void test_DamageOnYou_Prevent() {
addCard(Zone.HAND, playerA, circle, 1);
addCard(Zone.BATTLEFIELD, playerB, "Goblin Piker", 1); // 2/1
addCard(Zone.BATTLEFIELD, playerA, "Plains", 4);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, circle);
setChoice(playerA, "Red"); // color chosen
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerA, "{W}");
setChoice(playerA, "Goblin Piker"); // source to prevent from
attack(2, playerB, "Goblin Piker", playerA);
setStrictChooseMode(true);
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertLife(playerA, 20);
assertTappedCount("Plains", true, 4);
}
@Test
public void test_DoubleStrike_Prevent_ThenConsumedAndNoPrevent() {
addCard(Zone.HAND, playerA, circle, 1);
addCard(Zone.BATTLEFIELD, playerB, "Blade Historian", 1); // 2/3 "Attacking creatures you control have double strike."
addCard(Zone.BATTLEFIELD, playerA, "Plains", 4);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, circle);
setChoice(playerA, "Red"); // color chosen
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerA, "{W}");
setChoice(playerA, "Blade Historian"); // source to prevent from
attack(2, playerB, "Blade Historian", playerA);
setStrictChooseMode(true);
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertLife(playerA, 20 - 2);
assertTappedCount("Plains", true, 4);
}
@Test
public void test_NoSourceOfChosenColor_NoPrevent() {
addCard(Zone.HAND, playerA, circle, 1);
addCard(Zone.BATTLEFIELD, playerB, "Goblin Piker", 1); // 2/1
addCard(Zone.BATTLEFIELD, playerA, "Plains", 4);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, circle);
setChoice(playerA, "Green"); // color chosen
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerA, "{W}");
setChoice(playerA, "Goblin Piker"); // TODO: this should not be a valid choice for TargetSource(chosencolor)
attack(2, playerB, "Goblin Piker", playerA);
setStrictChooseMode(true);
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertLife(playerA, 20); // TODO: Should not prevent.
assertTappedCount("Plains", true, 4);
}
@Test
public void test_SpellDamageOnYou_Prevent() {
addCard(Zone.HAND, playerA, circle, 1);
addCard(Zone.HAND, playerB, "Lightning Bolt", 1);
addCard(Zone.BATTLEFIELD, playerA, "Plains", 4);
addCard(Zone.BATTLEFIELD, playerB, "Mountain");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, circle);
setChoice(playerA, "Red"); // color chosen
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Lightning Bolt", playerA);
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerA, "{W}", null, "Lightning Bolt");
setChoice(playerA, "Lightning Bolt"); // source to prevent from
setStrictChooseMode(true);
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertLife(playerA, 20);
assertGraveyardCount(playerB, "Lightning Bolt", 1);
assertTappedCount("Plains", true, 4);
}
@Test
public void test_SpellNotChosenColorDamageOnYou_NoPrevent() {
addCard(Zone.HAND, playerA, circle, 1);
addCard(Zone.HAND, playerB, "Lightning Bolt", 1);
addCard(Zone.BATTLEFIELD, playerA, "Plains", 4);
addCard(Zone.BATTLEFIELD, playerB, "Mountain");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, circle);
setChoice(playerA, "Green"); // color chosen
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Lightning Bolt", playerA);
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerA, "{W}", null, "Lightning Bolt");
setChoice(playerA, "Lightning Bolt"); // TODO: this should not be a valid choice for TargetSource(chosencolor)
setStrictChooseMode(true);
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertLife(playerA, 20); // TODO: Should not prevent.
assertGraveyardCount(playerB, "Lightning Bolt", 1);
assertTappedCount("Plains", true, 4);
}
@Test
public void test_TriggerDamageOnYou_Prevent() {
addCard(Zone.HAND, playerA, circle, 1);
addCard(Zone.HAND, playerB, "Blisterstick Shaman", 1); // etb deals 1 to any target
addCard(Zone.BATTLEFIELD, playerA, "Plains", 4);
addCard(Zone.BATTLEFIELD, playerB, "Mountain", 3);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, circle);
setChoice(playerA, "Red"); // color chosen
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Blisterstick Shaman");
addTarget(playerB, playerA); // target for Shaman trigger
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerA, "{W}", null, "stack ability (When");
setChoice(playerA, "Blisterstick Shaman");
setStrictChooseMode(true);
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertLife(playerA, 20);
assertPermanentCount(playerB, "Blisterstick Shaman", 1);
assertTappedCount("Plains", true, 4);
}
@Test
public void test_TriggerNotChosenColorDamageOnYou_NoPrevent() {
addCard(Zone.HAND, playerA, circle, 1);
addCard(Zone.HAND, playerB, "Blisterstick Shaman", 1); // etb deals 1 to any target
addCard(Zone.BATTLEFIELD, playerA, "Plains", 4);
addCard(Zone.BATTLEFIELD, playerB, "Mountain", 3);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, circle);
setChoice(playerA, "Green"); // color chosen
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Blisterstick Shaman");
addTarget(playerB, playerA); // target for Shaman trigger
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerA, "{W}", null, "stack ability (When");
setChoice(playerA, "Blisterstick Shaman"); // TODO: this should not be a valid choice for TargetSource(chosencolor)
setStrictChooseMode(true);
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertLife(playerA, 20); // TODO: Should not prevent.
assertPermanentCount(playerB, "Blisterstick Shaman", 1);
assertTappedCount("Plains", true, 4);
}
@Test
public void test_ActivationDamageOnYou_Prevent() {
addCard(Zone.HAND, playerA, circle, 1);
addCard(Zone.BATTLEFIELD, playerB, "Anaba Shaman", 1); // {R}, {T}: This creature deals 1 damage to any target.
addCard(Zone.BATTLEFIELD, playerA, "Plains", 4);
addCard(Zone.BATTLEFIELD, playerB, "Mountain", 1);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, circle);
setChoice(playerA, "Red"); // color chosen
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerB, "{R},", playerA);
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerA, "{W}", null, "stack ability ({R}");
setChoice(playerA, "Anaba Shaman"); // source to prevent from
setStrictChooseMode(true);
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertTappedCount("Anaba Shaman", true, 1);
assertLife(playerA, 20);
assertTappedCount("Plains", true, 4);
}
@Test
public void test_ActivationNotChosenColorDamageOnYou_NoPrevent() {
addCard(Zone.HAND, playerA, circle, 1);
addCard(Zone.BATTLEFIELD, playerB, "Anaba Shaman", 1); // {R}, {T}: This creature deals 1 damage to any target.
addCard(Zone.BATTLEFIELD, playerA, "Plains", 4);
addCard(Zone.BATTLEFIELD, playerB, "Mountain", 1);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, circle);
setChoice(playerA, "Green"); // color chosen
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerB, "{R},", playerA);
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerA, "{W}", null, "stack ability ({R}");
setChoice(playerA, "Anaba Shaman"); // TODO: this should not be a valid choice for TargetSource(chosencolor)
setStrictChooseMode(true);
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertTappedCount("Anaba Shaman", true, 1);
assertLife(playerA, 20); // TODO: Should not prevent.
assertTappedCount("Plains", true, 4);
}
}

View file

@ -0,0 +1,61 @@
package org.mage.test.cards.single.ody;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
* @author Susucr
*/
public class PilgrimOfJusticeTest extends CardTestPlayerBase {
/**
* {@link mage.cards.p.PilgrimOfJustice Pilgrim of Justice} {2}{W}
* Creature Human Cleric
* Protection from red
* {W}, Sacrifice this creature: The next time a red source of your choice would deal damage this turn, prevent that damage.
* 1/3
*/
private static final String pilgrim = "Pilgrim of Justice";
@Test
public void test_DamageOnCreature_Prevent() {
addCard(Zone.BATTLEFIELD, playerA, pilgrim, 1);
addCard(Zone.BATTLEFIELD, playerB, "Goblin Piker", 1); // 2/1
addCard(Zone.BATTLEFIELD, playerA, "Caelorna, Coral Tyrant"); // 0/8
addCard(Zone.BATTLEFIELD, playerA, "Plains", 1);
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerA, "{W}");
setChoice(playerA, "Goblin Piker"); // source to prevent from
attack(2, playerB, "Goblin Piker", playerA);
block(2, playerA, "Caelorna, Coral Tyrant", "Goblin Piker");
setStrictChooseMode(true);
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertDamageReceived(playerA, "Caelorna, Coral Tyrant", 0);
assertTapped("Goblin Piker", true);
}
@Test
public void test_DamageOnYou_Prevent() {
addCard(Zone.BATTLEFIELD, playerA, pilgrim, 1);
addCard(Zone.BATTLEFIELD, playerB, "Goblin Piker", 1); // 2/1
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerA, "{W}");
setChoice(playerA, "Goblin Piker"); // source to prevent from
attack(2, playerB, "Goblin Piker", playerA);
setStrictChooseMode(true);
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertLife(playerA, 20);
assertTapped("Goblin Piker", true);
}
}

View file

@ -0,0 +1,84 @@
package org.mage.test.cards.single.tdm;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
* @author Susucr
*/
public class NewWayForwardTest extends CardTestPlayerBase {
/**
* {@link mage.cards.n.NewWayForward New Way Forward} {2}{U}{R}{W}
* Instant
* The next time a source of your choice would deal damage to you this turn, prevent that damage. When damage is prevented this way, New Way Forward deals that much damage to that sources controller and you draw that many cards.
*/
private static final String way = "New Way Forward";
@Test
public void test_DamageOnCreature_NoPrevent() {
addCard(Zone.HAND, playerA, way, 1);
addCard(Zone.BATTLEFIELD, playerB, "Goblin Piker", 1); // 2/1
addCard(Zone.BATTLEFIELD, playerA, "Caelorna, Coral Tyrant"); // 0/8
addCard(Zone.BATTLEFIELD, playerA, "Plateau", 2);
addCard(Zone.BATTLEFIELD, playerA, "Island", 3);
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerA, way);
setChoice(playerA, "Goblin Piker"); // source to prevent from
attack(2, playerB, "Goblin Piker", playerA);
block(2, playerA, "Caelorna, Coral Tyrant", "Goblin Piker");
setStrictChooseMode(true);
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertDamageReceived(playerA, "Caelorna, Coral Tyrant", 2); // no prevent
assertLife(playerB, 20);
assertHandCount(playerA, 0);
}
@Test
public void test_DamageOnYou_Prevent() {
addCard(Zone.HAND, playerA, way, 1);
addCard(Zone.BATTLEFIELD, playerB, "Goblin Piker", 1); // 2/1
addCard(Zone.BATTLEFIELD, playerA, "Plateau", 2);
addCard(Zone.BATTLEFIELD, playerA, "Island", 3);
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerA, way);
setChoice(playerA, "Goblin Piker"); // source to prevent from
attack(2, playerB, "Goblin Piker", playerA);
setStrictChooseMode(true);
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertLife(playerA, 20);
assertLife(playerB, 20 - 2);
assertHandCount(playerA, 2);
}
@Test
public void test_DoubleStrike_Prevent_ThenConsumedAndNoPrevent() {
addCard(Zone.HAND, playerA, way, 1);
addCard(Zone.BATTLEFIELD, playerB, "Blade Historian", 1); // 2/3 "Attacking creatures you control have double strike."
addCard(Zone.BATTLEFIELD, playerA, "Plateau", 2);
addCard(Zone.BATTLEFIELD, playerA, "Island", 3);
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerA, way);
setChoice(playerA, "Blade Historian"); // source to prevent from
attack(2, playerB, "Blade Historian", playerA);
setStrictChooseMode(true);
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertLife(playerA, 20 - 2);
assertLife(playerB, 20 - 2);
assertHandCount(playerA, 2);
}
}

View file

@ -16,33 +16,38 @@ import mage.target.TargetSource;
* @author LevelX2
*/
public class PreventDamageBySourceEffect extends PreventionEffectImpl {
public class PreventDamageByChosenSourceEffect extends PreventionEffectImpl {
private TargetSource target;
private MageObjectReference mageObjectReference;
public PreventDamageBySourceEffect() {
this(new FilterObject("a"));
public PreventDamageByChosenSourceEffect() {
this(new FilterObject("a source"));
}
public PreventDamageBySourceEffect(FilterObject filterObject) {
super(Duration.EndOfTurn);
public PreventDamageByChosenSourceEffect(FilterObject filterObject) {
this(filterObject, false);
}
public PreventDamageByChosenSourceEffect(FilterObject filterObject, boolean onlyCombat) {
super(Duration.EndOfTurn, Integer.MAX_VALUE, onlyCombat);
if (!filterObject.getMessage().endsWith("source")) {
filterObject.setMessage(filterObject.getMessage() + " source");
}
this.target = new TargetSource(filterObject);
staticText = "Prevent all damage " + filterObject.getMessage() + " of your choice would deal this turn";
staticText = "Prevent all" + (onlyCombat ? " combat" : "")
+ " damage " + filterObject.getMessage() + " of your choice would deal this turn";
}
protected PreventDamageBySourceEffect(final PreventDamageBySourceEffect effect) {
protected PreventDamageByChosenSourceEffect(final PreventDamageByChosenSourceEffect effect) {
super(effect);
this.target = effect.target.copy();
this.mageObjectReference = effect.mageObjectReference;
}
@Override
public PreventDamageBySourceEffect copy() {
return new PreventDamageBySourceEffect(this);
public PreventDamageByChosenSourceEffect copy() {
return new PreventDamageByChosenSourceEffect(this);
}
@Override

View file

@ -0,0 +1,131 @@
package mage.abilities.effects.common;
import mage.abilities.Ability;
import mage.abilities.effects.PreventionEffectData;
import mage.abilities.effects.PreventionEffectImpl;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.filter.FilterObject;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.players.Player;
import mage.target.TargetSource;
import mage.util.CardUtil;
import java.util.UUID;
/**
* @author Quercitron, Susucr
*/
public class PreventNextDamageFromChosenSourceEffect extends PreventionEffectImpl {
protected final TargetSource targetSource;
private final boolean toYou;
private final ApplierOnPrevention onPrevention;
public interface ApplierOnPrevention {
boolean apply(PreventionEffectData data, TargetSource targetsource, GameEvent event, Ability source, Game game);
String getText();
}
public static ApplierOnPrevention ON_PREVENT_YOU_GAIN_THAT_MUCH_LIFE = new ApplierOnPrevention() {
public String getText() {
return "You gain life equal to the damage prevented this way";
}
public boolean apply(PreventionEffectData data, TargetSource targetSource, GameEvent event, Ability source, Game game) {
if (data == null || data.getPreventedDamage() <= 0) {
return false;
}
int prevented = data.getPreventedDamage();
Player controller = game.getPlayer(source.getControllerId());
if (controller == null) {
return false;
}
controller.gainLife(prevented, game, source);
return true;
}
};
public PreventNextDamageFromChosenSourceEffect(Duration duration, boolean toYou) {
this(duration, toYou, new FilterObject("source"));
}
public PreventNextDamageFromChosenSourceEffect(Duration duration, boolean toYou, FilterObject filter) {
this(duration, toYou, filter, false, null);
}
public PreventNextDamageFromChosenSourceEffect(Duration duration, boolean toYou, ApplierOnPrevention onPrevention) {
this(duration, toYou, new FilterObject("source"), onPrevention);
}
public PreventNextDamageFromChosenSourceEffect(Duration duration, boolean toYou, FilterObject filter, ApplierOnPrevention onPrevention) {
this(duration, toYou, filter, false, onPrevention);
}
public PreventNextDamageFromChosenSourceEffect(Duration duration, boolean toYou, FilterObject filter, boolean onlyCombat, ApplierOnPrevention onPrevention) {
super(duration, Integer.MAX_VALUE, onlyCombat);
this.targetSource = new TargetSource(filter);
this.toYou = toYou;
this.onPrevention = onPrevention;
this.staticText = setText();
}
protected PreventNextDamageFromChosenSourceEffect(final PreventNextDamageFromChosenSourceEffect effect) {
super(effect);
this.targetSource = effect.targetSource.copy();
this.toYou = effect.toYou;
this.onPrevention = effect.onPrevention;
}
@Override
public PreventNextDamageFromChosenSourceEffect copy() {
return new PreventNextDamageFromChosenSourceEffect(this);
}
@Override
public void init(Ability source, Game game) {
super.init(source, game);
UUID controllerId = source.getControllerId();
if (this.targetSource.canChoose(controllerId, source, game)) {
this.targetSource.choose(Outcome.PreventDamage, controllerId, source.getSourceId(), source, game);
}
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
PreventionEffectData data = preventDamageAction(event, source, game);
this.used = true;
if (onPrevention != null) {
onPrevention.apply(data, targetSource, event, source, game);
}
return false;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
return !this.used
&& super.applies(event, source, game)
&& (!toYou || event.getTargetId().equals(source.getControllerId()))
&& event.getSourceId().equals(targetSource.getFirstTarget());
}
private String setText() {
StringBuilder sb = new StringBuilder("The next time ")
.append(CardUtil.addArticle(targetSource.getFilter().getMessage()));
sb.append(" of your choice would deal damage");
if (toYou) {
sb.append(" to you");
}
if (duration == Duration.EndOfTurn) {
sb.append(" this turn");
}
sb.append(", prevent that damage");
if (onPrevention != null) {
sb.append(". ").append(onPrevention.getText());
}
return sb.toString();
}
}

View file

@ -1,77 +0,0 @@
package mage.abilities.effects.common;
import mage.abilities.Ability;
import mage.abilities.effects.PreventionEffectImpl;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.filter.FilterObject;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.target.TargetSource;
import mage.util.CardUtil;
/**
* @author Quercitron
*/
public class PreventNextDamageFromChosenSourceToYouEffect extends PreventionEffectImpl {
protected final TargetSource targetSource;
public PreventNextDamageFromChosenSourceToYouEffect(Duration duration) {
this(duration, new FilterObject("source"));
}
public PreventNextDamageFromChosenSourceToYouEffect(Duration duration, FilterObject filter) {
this(duration, filter, false);
}
public PreventNextDamageFromChosenSourceToYouEffect(Duration duration, FilterObject filter, boolean onlyCombat) {
super(duration, Integer.MAX_VALUE, onlyCombat);
this.targetSource = new TargetSource(filter);
this.staticText = setText();
}
protected PreventNextDamageFromChosenSourceToYouEffect(final PreventNextDamageFromChosenSourceToYouEffect effect) {
super(effect);
this.targetSource = effect.targetSource.copy();
}
@Override
public PreventNextDamageFromChosenSourceToYouEffect copy() {
return new PreventNextDamageFromChosenSourceToYouEffect(this);
}
@Override
public void init(Ability source, Game game) {
super.init(source, game);
this.targetSource.choose(Outcome.PreventDamage, source.getControllerId(), source.getSourceId(), source, game);
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
preventDamageAction(event, source, game);
this.used = true;
return false;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (!this.used && super.applies(event, source, game)) {
if (event.getTargetId().equals(source.getControllerId()) && event.getSourceId().equals(targetSource.getFirstTarget())) {
return true;
}
}
return false;
}
private String setText() {
StringBuilder sb = new StringBuilder("The next time ").append(CardUtil.addArticle(targetSource.getFilter().getMessage()));
sb.append(" of your choice would deal damage to you");
if (duration == Duration.EndOfTurn) {
sb.append(" this turn");
}
sb.append(", prevent that damage");
return sb.toString();
}
}