mirror of
https://github.com/magefree/mage.git
synced 2025-12-20 10:40:06 -08:00
refactor: add FilterSource to match TargetSource (#13703)
Small fix of enabling TargetSource to choose/target a Command Object
This commit is contained in:
parent
fc15cefa23
commit
cfd51d7dce
42 changed files with 522 additions and 278 deletions
|
|
@ -11,6 +11,7 @@ import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.filter.FilterCard;
|
import mage.filter.FilterCard;
|
||||||
|
import mage.filter.FilterPermanent;
|
||||||
import mage.filter.common.FilterCreaturePermanent;
|
import mage.filter.common.FilterCreaturePermanent;
|
||||||
import mage.filter.predicate.mageobject.NamePredicate;
|
import mage.filter.predicate.mageobject.NamePredicate;
|
||||||
|
|
||||||
|
|
@ -22,6 +23,7 @@ import java.util.UUID;
|
||||||
public final class AjanisAid extends CardImpl {
|
public final class AjanisAid extends CardImpl {
|
||||||
|
|
||||||
private static final FilterCard filter = new FilterCard("Ajani, Valiant Protector");
|
private static final FilterCard filter = new FilterCard("Ajani, Valiant Protector");
|
||||||
|
private static final FilterPermanent filterPrevent = new FilterCreaturePermanent("creature of your choice");
|
||||||
|
|
||||||
static {
|
static {
|
||||||
filter.add(new NamePredicate("Ajani, Valiant Protector"));
|
filter.add(new NamePredicate("Ajani, Valiant Protector"));
|
||||||
|
|
@ -35,7 +37,7 @@ public final class AjanisAid extends CardImpl {
|
||||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new SearchLibraryGraveyardPutInHandEffect(filter), true));
|
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.
|
// Sacrifice Ajani's Aid: Prevent all combat damage a creature of your choice would deal this turn.
|
||||||
Effect effect = new PreventDamageByChosenSourceEffect(new FilterCreaturePermanent("creature of your choice"), true);
|
Effect effect = new PreventDamageByChosenSourceEffect(filterPrevent, true);
|
||||||
this.addAbility(new SimpleActivatedAbility(effect, new SacrificeSourceCost()));
|
this.addAbility(new SimpleActivatedAbility(effect, new SacrificeSourceCost()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ import mage.constants.Zone;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.GameEvent;
|
import mage.game.events.GameEvent;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.target.TargetSource;
|
import mage.target.Target;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
@ -53,7 +53,7 @@ public final class BoneMask extends CardImpl {
|
||||||
enum BoneMaskEffectPreventionApplier implements PreventNextDamageFromChosenSourceEffect.ApplierOnPrevention {
|
enum BoneMaskEffectPreventionApplier implements PreventNextDamageFromChosenSourceEffect.ApplierOnPrevention {
|
||||||
instance;
|
instance;
|
||||||
|
|
||||||
public boolean apply(PreventionEffectData data, TargetSource targetSource, GameEvent event, Ability source, Game game) {
|
public boolean apply(PreventionEffectData data, Target target, GameEvent event, Ability source, Game game) {
|
||||||
if (data == null || data.getPreventedDamage() <= 0) {
|
if (data == null || data.getPreventedDamage() <= 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.SubType;
|
import mage.constants.SubType;
|
||||||
import mage.filter.FilterObject;
|
import mage.filter.FilterSource;
|
||||||
import mage.filter.predicate.mageobject.ColorPredicate;
|
import mage.filter.predicate.mageobject.ColorPredicate;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
@ -21,10 +21,10 @@ import java.util.UUID;
|
||||||
*/
|
*/
|
||||||
public final class BurrentonForgeTender extends CardImpl {
|
public final class BurrentonForgeTender extends CardImpl {
|
||||||
|
|
||||||
private static final FilterObject filterObject = new FilterObject("a red");
|
private static final FilterSource filter = new FilterSource("a red source");
|
||||||
|
|
||||||
static {
|
static {
|
||||||
filterObject.add(new ColorPredicate(ObjectColor.RED));
|
filter.add(new ColorPredicate(ObjectColor.RED));
|
||||||
}
|
}
|
||||||
|
|
||||||
public BurrentonForgeTender(UUID ownerId, CardSetInfo setInfo) {
|
public BurrentonForgeTender(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
|
@ -38,7 +38,7 @@ public final class BurrentonForgeTender extends CardImpl {
|
||||||
this.addAbility(ProtectionAbility.from(ObjectColor.RED));
|
this.addAbility(ProtectionAbility.from(ObjectColor.RED));
|
||||||
|
|
||||||
// Sacrifice Burrenton Forge-Tender: Prevent all damage a red source of your choice would deal this turn.
|
// Sacrifice Burrenton Forge-Tender: Prevent all damage a red source of your choice would deal this turn.
|
||||||
this.addAbility(new SimpleActivatedAbility(new PreventDamageByChosenSourceEffect(filterObject), new SacrificeSourceCost()));
|
this.addAbility(new SimpleActivatedAbility(new PreventDamageByChosenSourceEffect(filter), new SacrificeSourceCost()));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Duration;
|
import mage.constants.Duration;
|
||||||
import mage.filter.FilterObject;
|
import mage.filter.FilterSource;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
|
@ -18,7 +18,7 @@ import java.util.UUID;
|
||||||
*/
|
*/
|
||||||
public final class CircleOfProtectionArtifacts extends CardImpl {
|
public final class CircleOfProtectionArtifacts extends CardImpl {
|
||||||
|
|
||||||
private static final FilterObject filter = new FilterObject("artifact source");
|
private static final FilterSource filter = new FilterSource("artifact source");
|
||||||
|
|
||||||
static {
|
static {
|
||||||
filter.add(CardType.ARTIFACT.getPredicate());
|
filter.add(CardType.ARTIFACT.getPredicate());
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Duration;
|
import mage.constants.Duration;
|
||||||
import mage.filter.FilterObject;
|
import mage.filter.FilterSource;
|
||||||
import mage.filter.predicate.mageobject.ColorPredicate;
|
import mage.filter.predicate.mageobject.ColorPredicate;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
@ -20,7 +20,7 @@ import java.util.UUID;
|
||||||
*/
|
*/
|
||||||
public final class CircleOfProtectionBlack extends CardImpl {
|
public final class CircleOfProtectionBlack extends CardImpl {
|
||||||
|
|
||||||
private static final FilterObject filter = new FilterObject("black source");
|
private static final FilterSource filter = new FilterSource("black source");
|
||||||
|
|
||||||
static {
|
static {
|
||||||
filter.add(new ColorPredicate(ObjectColor.BLACK));
|
filter.add(new ColorPredicate(ObjectColor.BLACK));
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Duration;
|
import mage.constants.Duration;
|
||||||
import mage.filter.FilterObject;
|
import mage.filter.FilterSource;
|
||||||
import mage.filter.predicate.mageobject.ColorPredicate;
|
import mage.filter.predicate.mageobject.ColorPredicate;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
@ -20,7 +20,7 @@ import java.util.UUID;
|
||||||
*/
|
*/
|
||||||
public final class CircleOfProtectionBlue extends CardImpl {
|
public final class CircleOfProtectionBlue extends CardImpl {
|
||||||
|
|
||||||
private static final FilterObject filter = new FilterObject("blue source");
|
private static final FilterSource filter = new FilterSource("blue source");
|
||||||
|
|
||||||
static {
|
static {
|
||||||
filter.add(new ColorPredicate(ObjectColor.BLUE));
|
filter.add(new ColorPredicate(ObjectColor.BLUE));
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Duration;
|
import mage.constants.Duration;
|
||||||
import mage.filter.FilterObject;
|
import mage.filter.FilterSource;
|
||||||
import mage.filter.predicate.mageobject.ColorPredicate;
|
import mage.filter.predicate.mageobject.ColorPredicate;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
@ -20,7 +20,7 @@ import java.util.UUID;
|
||||||
*/
|
*/
|
||||||
public final class CircleOfProtectionGreen extends CardImpl {
|
public final class CircleOfProtectionGreen extends CardImpl {
|
||||||
|
|
||||||
private static final FilterObject filter = new FilterObject("green source");
|
private static final FilterSource filter = new FilterSource("green source");
|
||||||
|
|
||||||
static {
|
static {
|
||||||
filter.add(new ColorPredicate(ObjectColor.GREEN));
|
filter.add(new ColorPredicate(ObjectColor.GREEN));
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Duration;
|
import mage.constants.Duration;
|
||||||
import mage.filter.FilterObject;
|
import mage.filter.FilterSource;
|
||||||
import mage.filter.predicate.mageobject.ColorPredicate;
|
import mage.filter.predicate.mageobject.ColorPredicate;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
@ -20,7 +20,7 @@ import java.util.UUID;
|
||||||
*/
|
*/
|
||||||
public final class CircleOfProtectionRed extends CardImpl {
|
public final class CircleOfProtectionRed extends CardImpl {
|
||||||
|
|
||||||
private static final FilterObject filter = new FilterObject("red source");
|
private static final FilterSource filter = new FilterSource("red source");
|
||||||
|
|
||||||
static {
|
static {
|
||||||
filter.add(new ColorPredicate(ObjectColor.RED));
|
filter.add(new ColorPredicate(ObjectColor.RED));
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Duration;
|
import mage.constants.Duration;
|
||||||
|
import mage.filter.FilterPermanent;
|
||||||
import mage.filter.common.FilterCreaturePermanent;
|
import mage.filter.common.FilterCreaturePermanent;
|
||||||
import mage.filter.predicate.mageobject.AbilityPredicate;
|
import mage.filter.predicate.mageobject.AbilityPredicate;
|
||||||
|
|
||||||
|
|
@ -20,7 +21,7 @@ import java.util.UUID;
|
||||||
*/
|
*/
|
||||||
public final class CircleOfProtectionShadow extends CardImpl {
|
public final class CircleOfProtectionShadow extends CardImpl {
|
||||||
|
|
||||||
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("a creature of your choice with shadow");
|
private static final FilterPermanent filter = new FilterCreaturePermanent("a creature of your choice with shadow");
|
||||||
|
|
||||||
static {
|
static {
|
||||||
filter.add(new AbilityPredicate(ShadowAbility.class));
|
filter.add(new AbilityPredicate(ShadowAbility.class));
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Duration;
|
import mage.constants.Duration;
|
||||||
import mage.filter.FilterObject;
|
import mage.filter.FilterSource;
|
||||||
import mage.filter.predicate.mageobject.ColorPredicate;
|
import mage.filter.predicate.mageobject.ColorPredicate;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
@ -20,7 +20,7 @@ import java.util.UUID;
|
||||||
*/
|
*/
|
||||||
public final class CircleOfProtectionWhite extends CardImpl {
|
public final class CircleOfProtectionWhite extends CardImpl {
|
||||||
|
|
||||||
private static final FilterObject filter = new FilterObject("white source");
|
private static final FilterSource filter = new FilterSource("white source");
|
||||||
|
|
||||||
static {
|
static {
|
||||||
filter.add(new ColorPredicate(ObjectColor.WHITE));
|
filter.add(new ColorPredicate(ObjectColor.WHITE));
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
|
|
||||||
package mage.cards.c;
|
package mage.cards.c;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||||
import mage.abilities.common.SimpleActivatedAbility;
|
import mage.abilities.common.SimpleActivatedAbility;
|
||||||
import mage.abilities.costs.common.PayEnergyCost;
|
import mage.abilities.costs.common.PayEnergyCost;
|
||||||
|
|
@ -11,11 +10,10 @@ import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Duration;
|
import mage.constants.Duration;
|
||||||
import mage.constants.Zone;
|
|
||||||
import mage.filter.FilterObject;
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author LevelX2
|
* @author LevelX2
|
||||||
*/
|
*/
|
||||||
public final class ConsulateSurveillance extends CardImpl {
|
public final class ConsulateSurveillance extends CardImpl {
|
||||||
|
|
@ -28,7 +26,7 @@ public final class ConsulateSurveillance extends CardImpl {
|
||||||
|
|
||||||
// Pay {E}{E}: Prevent all damage that would be dealt to you this turn by a source of your choice.
|
// Pay {E}{E}: Prevent all damage that would be dealt to you this turn by a source of your choice.
|
||||||
this.addAbility(new SimpleActivatedAbility(
|
this.addAbility(new SimpleActivatedAbility(
|
||||||
new PreventAllDamageFromChosenSourceToYouEffect(Duration.EndOfTurn, new FilterObject("source"), false),
|
new PreventAllDamageFromChosenSourceToYouEffect(Duration.EndOfTurn),
|
||||||
new PayEnergyCost(2)));
|
new PayEnergyCost(2)));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,28 +1,25 @@
|
||||||
|
|
||||||
package mage.cards.d;
|
package mage.cards.d;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
import mage.MageObject;
|
import mage.MageObject;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.SimpleActivatedAbility;
|
import mage.abilities.common.SimpleActivatedAbility;
|
||||||
import mage.abilities.costs.common.SacrificeSourceCost;
|
import mage.abilities.costs.common.SacrificeSourceCost;
|
||||||
import mage.abilities.costs.common.TapSourceCost;
|
import mage.abilities.costs.common.TapSourceCost;
|
||||||
import mage.abilities.effects.ReplacementEffectImpl;
|
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceEffect;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Duration;
|
import mage.constants.Duration;
|
||||||
import mage.constants.Outcome;
|
import mage.filter.FilterSource;
|
||||||
import mage.constants.Zone;
|
|
||||||
import mage.filter.FilterObject;
|
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.DamageEvent;
|
import mage.game.events.DamageEvent;
|
||||||
import mage.game.events.GameEvent;
|
import mage.game.events.GameEvent;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.target.TargetSource;
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author ThomasLerner
|
* @author ThomasLerner
|
||||||
*/
|
*/
|
||||||
public final class DarkSphere extends CardImpl {
|
public final class DarkSphere extends CardImpl {
|
||||||
|
|
@ -48,19 +45,17 @@ public final class DarkSphere extends CardImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class DarkSpherePreventionEffect extends ReplacementEffectImpl {
|
class DarkSpherePreventionEffect extends PreventNextDamageFromChosenSourceEffect {
|
||||||
|
|
||||||
private final TargetSource targetSource;
|
private static final FilterSource filter = new FilterSource("source");
|
||||||
|
|
||||||
public DarkSpherePreventionEffect() {
|
public DarkSpherePreventionEffect() {
|
||||||
super(Duration.OneUse, Outcome.RedirectDamage);
|
super(Duration.EndOfTurn, true, filter);
|
||||||
this.staticText = "The next time a source of your choice would deal damage to you this turn, prevent half that damage, rounded down";
|
this.staticText = "The next time a source of your choice would deal damage to you this turn, prevent half that damage, rounded down";
|
||||||
this.targetSource = new TargetSource(new FilterObject("source of your choice"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private DarkSpherePreventionEffect(final DarkSpherePreventionEffect effect) {
|
private DarkSpherePreventionEffect(final DarkSpherePreventionEffect effect) {
|
||||||
super(effect);
|
super(effect);
|
||||||
this.targetSource = effect.targetSource.copy();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -68,40 +63,24 @@ class DarkSpherePreventionEffect extends ReplacementEffectImpl {
|
||||||
return new DarkSpherePreventionEffect(this);
|
return new DarkSpherePreventionEffect(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
|
@Override
|
||||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
MageObject sourceObject = game.getObject(source);
|
MageObject sourceObject = game.getObject(source);
|
||||||
DamageEvent damageEvent = (DamageEvent) event;
|
DamageEvent damageEvent = (DamageEvent) event;
|
||||||
if (controller != null) {
|
int damage = damageEvent.getAmount();
|
||||||
controller.damage((int) Math.ceil(damageEvent.getAmount() / 2.0), damageEvent.getSourceId(), source, game, damageEvent.isCombatDamage(), damageEvent.isPreventable(), damageEvent.getAppliedEffects());
|
if (controller == null || damage <= 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
controller.damage(
|
||||||
|
(int) Math.ceil(damage / 2.0), damageEvent.getSourceId(), source, game,
|
||||||
|
damageEvent.isCombatDamage(), damageEvent.isPreventable(), damageEvent.getAppliedEffects()
|
||||||
|
);
|
||||||
StringBuilder sb = new StringBuilder(sourceObject != null ? sourceObject.getLogName() : "");
|
StringBuilder sb = new StringBuilder(sourceObject != null ? sourceObject.getLogName() : "");
|
||||||
sb.append(": ").append(damageEvent.getAmount() / 2).append(" damage prevented");
|
sb.append(": ").append(damage / 2).append(" damage prevented");
|
||||||
sb.append(" from ").append(controller.getLogName());
|
sb.append(" from ").append(controller.getLogName());
|
||||||
game.informPlayers(sb.toString());
|
game.informPlayers(sb.toString());
|
||||||
discard(); // only one use
|
discard(); // only one use
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checksEventType(GameEvent event, Game game) {
|
|
||||||
return event.getType() == GameEvent.EventType.DAMAGE_PLAYER;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
|
||||||
if (event.getSourceId().equals(targetSource.getFirstTarget()) && event.getTargetId().equals(source.getControllerId())) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import mage.constants.Duration;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.GameEvent;
|
import mage.game.events.GameEvent;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.target.TargetSource;
|
import mage.target.Target;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
|
@ -44,12 +44,12 @@ public final class DeflectingPalm extends CardImpl {
|
||||||
enum DeflectingPalmPreventionApplier implements PreventNextDamageFromChosenSourceEffect.ApplierOnPrevention {
|
enum DeflectingPalmPreventionApplier implements PreventNextDamageFromChosenSourceEffect.ApplierOnPrevention {
|
||||||
instance;
|
instance;
|
||||||
|
|
||||||
public boolean apply(PreventionEffectData data, TargetSource targetSource, GameEvent event, Ability source, Game game) {
|
public boolean apply(PreventionEffectData data, Target target, GameEvent event, Ability source, Game game) {
|
||||||
if (data == null || data.getPreventedDamage() <= 0) {
|
if (data == null || data.getPreventedDamage() <= 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int prevented = data.getPreventedDamage();
|
int prevented = data.getPreventedDamage();
|
||||||
UUID objectControllerId = game.getControllerId(targetSource.getFirstTarget());
|
UUID objectControllerId = game.getControllerId(target.getFirstTarget());
|
||||||
Player objectController = game.getPlayer(objectControllerId);
|
Player objectController = game.getPlayer(objectControllerId);
|
||||||
if (objectController == null) {
|
if (objectController == null) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,6 @@
|
||||||
|
|
||||||
package mage.cards.d;
|
package mage.cards.d;
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.UUID;
|
|
||||||
import mage.MageObject;
|
import mage.MageObject;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.effects.PreventionEffectImpl;
|
import mage.abilities.effects.PreventionEffectImpl;
|
||||||
|
|
@ -14,18 +10,22 @@ import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Duration;
|
import mage.constants.Duration;
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
|
import mage.filter.FilterSource;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.DamageEvent;
|
import mage.game.events.DamageEvent;
|
||||||
import mage.game.events.GameEvent;
|
import mage.game.events.GameEvent;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.game.stack.StackObject;
|
import mage.game.stack.StackObject;
|
||||||
import mage.filter.FilterObject;
|
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.target.TargetSource;
|
import mage.target.TargetSource;
|
||||||
import mage.util.CardUtil;
|
import mage.util.CardUtil;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author L_J
|
* @author L_J
|
||||||
*/
|
*/
|
||||||
public final class DesperateGambit extends CardImpl {
|
public final class DesperateGambit extends CardImpl {
|
||||||
|
|
@ -122,10 +122,14 @@ class DesperateGambitEffect extends PreventionEffectImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: should not be needed with the proper {@link FilterSource}.
|
||||||
|
* make sure it works properly with 108.4a if you do
|
||||||
|
*/
|
||||||
class TargetControlledSource extends TargetSource {
|
class TargetControlledSource extends TargetSource {
|
||||||
|
|
||||||
public TargetControlledSource() {
|
public TargetControlledSource() {
|
||||||
super(1, 1, new FilterObject("source you control"));
|
super(1, 1, new FilterSource("source you control"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private TargetControlledSource(final TargetControlledSource target) {
|
private TargetControlledSource(final TargetControlledSource target) {
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Duration;
|
import mage.constants.Duration;
|
||||||
import mage.filter.FilterObject;
|
import mage.filter.FilterSource;
|
||||||
import mage.filter.predicate.Predicates;
|
import mage.filter.predicate.Predicates;
|
||||||
import mage.filter.predicate.mageobject.ColorPredicate;
|
import mage.filter.predicate.mageobject.ColorPredicate;
|
||||||
|
|
||||||
|
|
@ -21,7 +21,7 @@ import java.util.UUID;
|
||||||
*/
|
*/
|
||||||
public final class GreaterRealmOfPreservation extends CardImpl {
|
public final class GreaterRealmOfPreservation extends CardImpl {
|
||||||
|
|
||||||
private static final FilterObject filter = new FilterObject("black or red source");
|
private static final FilterSource filter = new FilterSource("black or red source");
|
||||||
|
|
||||||
static {
|
static {
|
||||||
filter.add(Predicates.or(new ColorPredicate(ObjectColor.BLACK), new ColorPredicate(ObjectColor.RED)));
|
filter.add(Predicates.or(new ColorPredicate(ObjectColor.BLACK), new ColorPredicate(ObjectColor.RED)));
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
|
|
||||||
package mage.cards.j;
|
package mage.cards.j;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
import mage.MageObject;
|
import mage.MageObject;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.SimpleActivatedAbility;
|
import mage.abilities.common.SimpleActivatedAbility;
|
||||||
|
|
@ -12,8 +11,7 @@ import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Duration;
|
import mage.constants.Duration;
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
import mage.constants.Zone;
|
import mage.filter.FilterSource;
|
||||||
import mage.filter.FilterObject;
|
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.DamageEvent;
|
import mage.game.events.DamageEvent;
|
||||||
import mage.game.events.GameEvent;
|
import mage.game.events.GameEvent;
|
||||||
|
|
@ -23,8 +21,9 @@ import mage.players.Player;
|
||||||
import mage.target.TargetSource;
|
import mage.target.TargetSource;
|
||||||
import mage.target.common.TargetCreaturePermanent;
|
import mage.target.common.TargetCreaturePermanent;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author Quercitron
|
* @author Quercitron
|
||||||
*/
|
*/
|
||||||
public final class JadeMonolith extends CardImpl {
|
public final class JadeMonolith extends CardImpl {
|
||||||
|
|
@ -55,7 +54,7 @@ class JadeMonolithRedirectionEffect extends ReplacementEffectImpl {
|
||||||
public JadeMonolithRedirectionEffect() {
|
public JadeMonolithRedirectionEffect() {
|
||||||
super(Duration.OneUse, Outcome.RedirectDamage);
|
super(Duration.OneUse, Outcome.RedirectDamage);
|
||||||
this.staticText = "The next time a source of your choice would deal damage to target creature this turn, that source deals that damage to you instead";
|
this.staticText = "The next time a source of your choice would deal damage to target creature this turn, that source deals that damage to you instead";
|
||||||
this.targetSource = new TargetSource(new FilterObject("source of your choice"));
|
this.targetSource = new TargetSource(new FilterSource("source of your choice"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private JadeMonolithRedirectionEffect(final JadeMonolithRedirectionEffect effect) {
|
private JadeMonolithRedirectionEffect(final JadeMonolithRedirectionEffect effect) {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
package mage.cards.m;
|
package mage.cards.m;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
import mage.MageObject;
|
import mage.MageObject;
|
||||||
import mage.MageObjectReference;
|
import mage.MageObjectReference;
|
||||||
import mage.ObjectColor;
|
import mage.ObjectColor;
|
||||||
|
|
@ -15,8 +13,11 @@ import mage.abilities.effects.PreventionEffectImpl;
|
||||||
import mage.cards.Card;
|
import mage.cards.Card;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.*;
|
import mage.constants.AbilityWord;
|
||||||
import mage.filter.FilterObject;
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.Duration;
|
||||||
|
import mage.constants.Outcome;
|
||||||
|
import mage.filter.FilterSource;
|
||||||
import mage.filter.predicate.mageobject.SharesColorPredicate;
|
import mage.filter.predicate.mageobject.SharesColorPredicate;
|
||||||
import mage.game.ExileZone;
|
import mage.game.ExileZone;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
|
|
@ -27,8 +28,9 @@ import mage.target.TargetSource;
|
||||||
import mage.target.common.TargetCardInGraveyard;
|
import mage.target.common.TargetCardInGraveyard;
|
||||||
import mage.util.CardUtil;
|
import mage.util.CardUtil;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author noahg
|
* @author noahg
|
||||||
*/
|
*/
|
||||||
public final class MournersShield extends CardImpl {
|
public final class MournersShield extends CardImpl {
|
||||||
|
|
@ -93,6 +95,10 @@ class MournersShieldImprintEffect extends OneShotEffect {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: custom effect should not be needed with the properly set up {@link FilterSource}
|
||||||
|
* and {@link mage.abilities.effects.common.PreventDamageByChosenSourceEffect}
|
||||||
|
*/
|
||||||
class MournersShieldEffect extends PreventionEffectImpl {
|
class MournersShieldEffect extends PreventionEffectImpl {
|
||||||
|
|
||||||
private TargetSource target;
|
private TargetSource target;
|
||||||
|
|
@ -139,9 +145,9 @@ class MournersShieldEffect extends PreventionEffectImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FilterObject filterObject = new FilterObject("a source of your choice that shares a color with the exiled card");
|
FilterSource filterSource = new FilterSource("a source of your choice that shares a color with the exiled card");
|
||||||
filterObject.add(new SharesColorPredicate(colorsAmongImprinted));
|
filterSource.add(new SharesColorPredicate(colorsAmongImprinted));
|
||||||
this.target = new TargetSource(filterObject);
|
this.target = new TargetSource(filterSource);
|
||||||
this.target.choose(Outcome.PreventDamage, source.getControllerId(), source.getSourceId(), source, game);
|
this.target.choose(Outcome.PreventDamage, source.getControllerId(), source.getSourceId(), source, game);
|
||||||
if (target.getFirstTarget() != null) {
|
if (target.getFirstTarget() != null) {
|
||||||
mageObjectReference = new MageObjectReference(target.getFirstTarget(), game);
|
mageObjectReference = new MageObjectReference(target.getFirstTarget(), game);
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ import mage.constants.CardType;
|
||||||
import mage.constants.Duration;
|
import mage.constants.Duration;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.GameEvent;
|
import mage.game.events.GameEvent;
|
||||||
import mage.target.TargetSource;
|
import mage.target.Target;
|
||||||
import mage.target.targetpointer.FixedTarget;
|
import mage.target.targetpointer.FixedTarget;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
@ -47,12 +47,12 @@ public final class NewWayForward extends CardImpl {
|
||||||
enum NewWayForwardPreventionApplier implements PreventNextDamageFromChosenSourceEffect.ApplierOnPrevention {
|
enum NewWayForwardPreventionApplier implements PreventNextDamageFromChosenSourceEffect.ApplierOnPrevention {
|
||||||
instance;
|
instance;
|
||||||
|
|
||||||
public boolean apply(PreventionEffectData data, TargetSource targetSource, GameEvent event, Ability source, Game game) {
|
public boolean apply(PreventionEffectData data, Target target, GameEvent event, Ability source, Game game) {
|
||||||
if (data == null || data.getPreventedDamage() <= 0) {
|
if (data == null || data.getPreventedDamage() <= 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int prevented = data.getPreventedDamage();
|
int prevented = data.getPreventedDamage();
|
||||||
UUID objectControllerId = game.getControllerId(targetSource.getFirstTarget());
|
UUID objectControllerId = game.getControllerId(target.getFirstTarget());
|
||||||
ReflexiveTriggeredAbility ability = new ReflexiveTriggeredAbility(
|
ReflexiveTriggeredAbility ability = new ReflexiveTriggeredAbility(
|
||||||
new DamageTargetEffect(prevented)
|
new DamageTargetEffect(prevented)
|
||||||
.setTargetPointer(new FixedTarget(objectControllerId)),
|
.setTargetPointer(new FixedTarget(objectControllerId)),
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Duration;
|
import mage.constants.Duration;
|
||||||
import mage.filter.FilterObject;
|
import mage.filter.FilterSource;
|
||||||
import mage.filter.predicate.Predicates;
|
import mage.filter.predicate.Predicates;
|
||||||
import mage.filter.predicate.mageobject.ColorPredicate;
|
import mage.filter.predicate.mageobject.ColorPredicate;
|
||||||
|
|
||||||
|
|
@ -20,7 +20,7 @@ import java.util.UUID;
|
||||||
*/
|
*/
|
||||||
public final class Penance extends CardImpl {
|
public final class Penance extends CardImpl {
|
||||||
|
|
||||||
private static final FilterObject filter = new FilterObject("black or red source");
|
private static final FilterSource filter = new FilterSource("black or red source");
|
||||||
|
|
||||||
static {
|
static {
|
||||||
filter.add(Predicates.or(new ColorPredicate(ObjectColor.BLACK), new ColorPredicate(ObjectColor.RED)));
|
filter.add(Predicates.or(new ColorPredicate(ObjectColor.BLACK), new ColorPredicate(ObjectColor.RED)));
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Duration;
|
import mage.constants.Duration;
|
||||||
import mage.constants.SubType;
|
import mage.constants.SubType;
|
||||||
import mage.filter.FilterObject;
|
import mage.filter.FilterSource;
|
||||||
import mage.filter.predicate.mageobject.ColorPredicate;
|
import mage.filter.predicate.mageobject.ColorPredicate;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
@ -23,7 +23,7 @@ import java.util.UUID;
|
||||||
*/
|
*/
|
||||||
public final class PilgrimOfJustice extends CardImpl {
|
public final class PilgrimOfJustice extends CardImpl {
|
||||||
|
|
||||||
private static final FilterObject filter = new FilterObject("red source");
|
private static final FilterSource filter = new FilterSource("red source");
|
||||||
|
|
||||||
static {
|
static {
|
||||||
filter.add(new ColorPredicate(ObjectColor.RED));
|
filter.add(new ColorPredicate(ObjectColor.RED));
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Duration;
|
import mage.constants.Duration;
|
||||||
import mage.constants.SubType;
|
import mage.constants.SubType;
|
||||||
import mage.filter.FilterObject;
|
import mage.filter.FilterSource;
|
||||||
import mage.filter.predicate.mageobject.ColorPredicate;
|
import mage.filter.predicate.mageobject.ColorPredicate;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
@ -23,7 +23,7 @@ import java.util.UUID;
|
||||||
*/
|
*/
|
||||||
public final class PilgrimOfVirtue extends CardImpl {
|
public final class PilgrimOfVirtue extends CardImpl {
|
||||||
|
|
||||||
private static final FilterObject filter = new FilterObject("black source");
|
private static final FilterSource filter = new FilterSource("black source");
|
||||||
|
|
||||||
static {
|
static {
|
||||||
filter.add(new ColorPredicate(ObjectColor.BLACK));
|
filter.add(new ColorPredicate(ObjectColor.BLACK));
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
|
|
||||||
package mage.cards.p;
|
package mage.cards.p;
|
||||||
|
|
||||||
import mage.ObjectColor;
|
|
||||||
import mage.abilities.Ability;
|
|
||||||
import mage.abilities.common.AsEntersBattlefieldAbility;
|
import mage.abilities.common.AsEntersBattlefieldAbility;
|
||||||
import mage.abilities.common.SimpleActivatedAbility;
|
import mage.abilities.common.SimpleActivatedAbility;
|
||||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
|
|
@ -14,9 +12,8 @@ import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Duration;
|
import mage.constants.Duration;
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
import mage.filter.FilterObject;
|
import mage.filter.FilterSource;
|
||||||
import mage.filter.predicate.mageobject.ColorPredicate;
|
import mage.filter.predicate.mageobject.ChosenColorPredicate;
|
||||||
import mage.game.Game;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
|
@ -25,6 +22,12 @@ import java.util.UUID;
|
||||||
*/
|
*/
|
||||||
public final class PrismaticCircle extends CardImpl {
|
public final class PrismaticCircle extends CardImpl {
|
||||||
|
|
||||||
|
private static FilterSource filter = new FilterSource("a source of your choice of the chosen color");
|
||||||
|
|
||||||
|
static {
|
||||||
|
filter.add(ChosenColorPredicate.TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
public PrismaticCircle(UUID ownerId, CardSetInfo setInfo) {
|
public PrismaticCircle(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}");
|
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}");
|
||||||
|
|
||||||
|
|
@ -36,7 +39,7 @@ public final class PrismaticCircle extends CardImpl {
|
||||||
|
|
||||||
// {1}: The next time a source of your choice of the chosen color would deal damage to you this turn, prevent that damage.
|
// {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(
|
this.addAbility(new SimpleActivatedAbility(
|
||||||
new PrismaticCircleEffect(),
|
new PreventNextDamageFromChosenSourceEffect(Duration.EndOfTurn, true, filter),
|
||||||
new ManaCostsImpl<>("{1}")
|
new ManaCostsImpl<>("{1}")
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
@ -50,29 +53,3 @@ public final class PrismaticCircle extends CardImpl {
|
||||||
return new PrismaticCircle(this);
|
return new PrismaticCircle(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: create a FilterSource that can handle ChosenColorPredicate.TRUE and simplify this.
|
|
||||||
class PrismaticCircleEffect extends PreventNextDamageFromChosenSourceEffect {
|
|
||||||
|
|
||||||
PrismaticCircleEffect() {
|
|
||||||
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.";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void init(Ability source, Game game) {
|
|
||||||
super.init(source, game);
|
|
||||||
FilterObject filter = targetSource.getFilter();
|
|
||||||
filter.add(new ColorPredicate((ObjectColor) game.getState().getValue(source.getSourceId() + "_color")));
|
|
||||||
}
|
|
||||||
|
|
||||||
private PrismaticCircleEffect(final PrismaticCircleEffect effect) {
|
|
||||||
super(effect);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PrismaticCircleEffect copy() {
|
|
||||||
return new PrismaticCircleEffect(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Duration;
|
import mage.constants.Duration;
|
||||||
import mage.filter.FilterObject;
|
import mage.filter.FilterSource;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
|
@ -19,7 +19,7 @@ import java.util.UUID;
|
||||||
*/
|
*/
|
||||||
public final class RuneOfProtectionArtifacts extends CardImpl {
|
public final class RuneOfProtectionArtifacts extends CardImpl {
|
||||||
|
|
||||||
private static final FilterObject filter = new FilterObject("artifact source");
|
private static final FilterSource filter = new FilterSource("artifact source");
|
||||||
|
|
||||||
static {
|
static {
|
||||||
filter.add(CardType.ARTIFACT.getPredicate());
|
filter.add(CardType.ARTIFACT.getPredicate());
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Duration;
|
import mage.constants.Duration;
|
||||||
import mage.filter.FilterObject;
|
import mage.filter.FilterSource;
|
||||||
import mage.filter.predicate.mageobject.ColorPredicate;
|
import mage.filter.predicate.mageobject.ColorPredicate;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
@ -21,7 +21,7 @@ import java.util.UUID;
|
||||||
*/
|
*/
|
||||||
public final class RuneOfProtectionBlack extends CardImpl {
|
public final class RuneOfProtectionBlack extends CardImpl {
|
||||||
|
|
||||||
private static final FilterObject filter = new FilterObject("black source");
|
private static final FilterSource filter = new FilterSource("black source");
|
||||||
|
|
||||||
static {
|
static {
|
||||||
filter.add(new ColorPredicate(ObjectColor.BLACK));
|
filter.add(new ColorPredicate(ObjectColor.BLACK));
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Duration;
|
import mage.constants.Duration;
|
||||||
import mage.filter.FilterObject;
|
import mage.filter.FilterSource;
|
||||||
import mage.filter.predicate.mageobject.ColorPredicate;
|
import mage.filter.predicate.mageobject.ColorPredicate;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
@ -21,7 +21,7 @@ import java.util.UUID;
|
||||||
*/
|
*/
|
||||||
public final class RuneOfProtectionBlue extends CardImpl {
|
public final class RuneOfProtectionBlue extends CardImpl {
|
||||||
|
|
||||||
private static final FilterObject filter = new FilterObject("blue source");
|
private static final FilterSource filter = new FilterSource("blue source");
|
||||||
|
|
||||||
static {
|
static {
|
||||||
filter.add(new ColorPredicate(ObjectColor.BLUE));
|
filter.add(new ColorPredicate(ObjectColor.BLUE));
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Duration;
|
import mage.constants.Duration;
|
||||||
import mage.filter.FilterObject;
|
import mage.filter.FilterSource;
|
||||||
import mage.filter.predicate.mageobject.ColorPredicate;
|
import mage.filter.predicate.mageobject.ColorPredicate;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
@ -21,7 +21,7 @@ import java.util.UUID;
|
||||||
*/
|
*/
|
||||||
public final class RuneOfProtectionGreen extends CardImpl {
|
public final class RuneOfProtectionGreen extends CardImpl {
|
||||||
|
|
||||||
private static final FilterObject filter = new FilterObject("green source");
|
private static final FilterSource filter = new FilterSource("green source");
|
||||||
|
|
||||||
static {
|
static {
|
||||||
filter.add(new ColorPredicate(ObjectColor.GREEN));
|
filter.add(new ColorPredicate(ObjectColor.GREEN));
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Duration;
|
import mage.constants.Duration;
|
||||||
import mage.filter.FilterObject;
|
import mage.filter.FilterSource;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
|
@ -19,7 +19,7 @@ import java.util.UUID;
|
||||||
*/
|
*/
|
||||||
public final class RuneOfProtectionLands extends CardImpl {
|
public final class RuneOfProtectionLands extends CardImpl {
|
||||||
|
|
||||||
private static final FilterObject filter = new FilterObject("land source");
|
private static final FilterSource filter = new FilterSource("land source");
|
||||||
|
|
||||||
static {
|
static {
|
||||||
filter.add(CardType.LAND.getPredicate());
|
filter.add(CardType.LAND.getPredicate());
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Duration;
|
import mage.constants.Duration;
|
||||||
import mage.filter.FilterObject;
|
import mage.filter.FilterSource;
|
||||||
import mage.filter.predicate.mageobject.ColorPredicate;
|
import mage.filter.predicate.mageobject.ColorPredicate;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
@ -21,7 +21,7 @@ import java.util.UUID;
|
||||||
*/
|
*/
|
||||||
public final class RuneOfProtectionRed extends CardImpl {
|
public final class RuneOfProtectionRed extends CardImpl {
|
||||||
|
|
||||||
private static final FilterObject filter = new FilterObject("red source");
|
private static final FilterSource filter = new FilterSource("red source");
|
||||||
|
|
||||||
static {
|
static {
|
||||||
filter.add(new ColorPredicate(ObjectColor.RED));
|
filter.add(new ColorPredicate(ObjectColor.RED));
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Duration;
|
import mage.constants.Duration;
|
||||||
import mage.filter.FilterObject;
|
import mage.filter.FilterSource;
|
||||||
import mage.filter.predicate.mageobject.ColorPredicate;
|
import mage.filter.predicate.mageobject.ColorPredicate;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
@ -21,7 +21,7 @@ import java.util.UUID;
|
||||||
*/
|
*/
|
||||||
public final class RuneOfProtectionWhite extends CardImpl {
|
public final class RuneOfProtectionWhite extends CardImpl {
|
||||||
|
|
||||||
private static final FilterObject filter = new FilterObject("white source");
|
private static final FilterSource filter = new FilterSource("white source");
|
||||||
|
|
||||||
static {
|
static {
|
||||||
filter.add(new ColorPredicate(ObjectColor.WHITE));
|
filter.add(new ColorPredicate(ObjectColor.WHITE));
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ import mage.game.Game;
|
||||||
import mage.game.events.GameEvent;
|
import mage.game.events.GameEvent;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.target.TargetSource;
|
import mage.target.Target;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
|
@ -77,11 +77,11 @@ enum ShadowbanePreventionApplier implements PreventNextDamageFromChosenSourceEff
|
||||||
return "If damage from a black source is prevented this way, you gain that much life";
|
return "If damage from a black source is prevented this way, you gain that much life";
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean apply(PreventionEffectData data, TargetSource targetSource, GameEvent event, Ability source, Game game) {
|
public boolean apply(PreventionEffectData data, Target target, GameEvent event, Ability source, Game game) {
|
||||||
if (data == null || data.getPreventedDamage() <= 0) {
|
if (data == null || data.getPreventedDamage() <= 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
MageObject sourceObject = game.getObject(targetSource.getFirstTarget());
|
MageObject sourceObject = game.getObject(target.getFirstTarget());
|
||||||
if (!sourceObject.getColor(game).isBlack()) {
|
if (!sourceObject.getColor(game).isBlack()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
|
|
||||||
package mage.cards.s;
|
package mage.cards.s;
|
||||||
|
|
||||||
import mage.ObjectColor;
|
|
||||||
import mage.abilities.Ability;
|
|
||||||
import mage.abilities.common.AsEntersBattlefieldAbility;
|
import mage.abilities.common.AsEntersBattlefieldAbility;
|
||||||
import mage.abilities.common.SimpleActivatedAbility;
|
import mage.abilities.common.SimpleActivatedAbility;
|
||||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
|
|
@ -13,9 +11,8 @@ import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Duration;
|
import mage.constants.Duration;
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
import mage.filter.FilterObject;
|
import mage.filter.FilterSource;
|
||||||
import mage.filter.predicate.mageobject.ColorPredicate;
|
import mage.filter.predicate.mageobject.ChosenColorPredicate;
|
||||||
import mage.game.Game;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
|
@ -25,6 +22,12 @@ import java.util.UUID;
|
||||||
|
|
||||||
public final class StoryCircle extends CardImpl {
|
public final class StoryCircle extends CardImpl {
|
||||||
|
|
||||||
|
private static FilterSource filter = new FilterSource("a source of your choice of the chosen color");
|
||||||
|
|
||||||
|
static {
|
||||||
|
filter.add(ChosenColorPredicate.TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
public StoryCircle(UUID ownerId, CardSetInfo setInfo) {
|
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}");
|
||||||
|
|
||||||
|
|
@ -32,7 +35,7 @@ public final class StoryCircle extends CardImpl {
|
||||||
this.addAbility(new AsEntersBattlefieldAbility(new ChooseColorEffect(Outcome.Neutral)));
|
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.
|
// {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(
|
this.addAbility(new SimpleActivatedAbility(
|
||||||
new StoryCircleEffect(),
|
new PreventNextDamageFromChosenSourceEffect(Duration.EndOfTurn, true, filter),
|
||||||
new ManaCostsImpl<>("{W}")
|
new ManaCostsImpl<>("{W}")
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
@ -46,29 +49,3 @@ public final class StoryCircle extends CardImpl {
|
||||||
return new StoryCircle(this);
|
return new StoryCircle(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: create a FilterSource that can handle ChosenColorPredicate.TRUE and simplify this.
|
|
||||||
class StoryCircleEffect extends PreventNextDamageFromChosenSourceEffect {
|
|
||||||
|
|
||||||
StoryCircleEffect() {
|
|
||||||
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.";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void init(Ability source, Game game) {
|
|
||||||
super.init(source, game);
|
|
||||||
FilterObject filter = targetSource.getFilter();
|
|
||||||
filter.add(new ColorPredicate((ObjectColor) game.getState().getValue(source.getSourceId() + "_color")));
|
|
||||||
}
|
|
||||||
|
|
||||||
private StoryCircleEffect(final StoryCircleEffect effect) {
|
|
||||||
super(effect);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public StoryCircleEffect copy() {
|
|
||||||
return new StoryCircleEffect(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
package org.mage.test.cards.single.drk;
|
||||||
|
|
||||||
|
import mage.constants.PhaseStep;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Susucr
|
||||||
|
*/
|
||||||
|
public class DarkSphereTest extends CardTestPlayerBase {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link mage.cards.d.DarkSphere Dark Sphere} {0}
|
||||||
|
* Artifact
|
||||||
|
* {T}, Sacrifice this artifact: The next time a source of your choice would deal damage to you this turn, prevent half that damage, rounded down.
|
||||||
|
*/
|
||||||
|
private static final String sphere = "Dark Sphere";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_DamageOnCreature_NoPrevent() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, sphere, 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, "{T}, Sacrifice");
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_DamageOnYou_Prevent() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, sphere, 1);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerB, "Craw Wurm", 1); // 6/4
|
||||||
|
|
||||||
|
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}, Sacrifice");
|
||||||
|
setChoice(playerA, "Craw Wurm"); // source to prevent from
|
||||||
|
|
||||||
|
attack(2, playerB, "Craw Wurm", playerA);
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertLife(playerA, 20 - 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_DoubleStrike_Prevent_ThenConsumedAndNoPrevent() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, sphere, 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, "{T}, Sacrifice");
|
||||||
|
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 - 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -42,7 +42,7 @@ public class CircleOfProtectionTest extends CardTestPlayerBase {
|
||||||
execute();
|
execute();
|
||||||
|
|
||||||
assertDamageReceived(playerA, "Caelorna, Coral Tyrant", 2); // no prevent
|
assertDamageReceived(playerA, "Caelorna, Coral Tyrant", 2); // no prevent
|
||||||
assertLife(playerB, 20);
|
assertLife(playerA, 20);
|
||||||
assertTappedCount("Plains", true, 1);
|
assertTappedCount("Plains", true, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -97,7 +97,7 @@ public class StoryCircleTest extends CardTestPlayerBase {
|
||||||
setChoice(playerA, "Green"); // color chosen
|
setChoice(playerA, "Green"); // color chosen
|
||||||
|
|
||||||
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerA, "{W}");
|
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerA, "{W}");
|
||||||
setChoice(playerA, "Goblin Piker"); // TODO: this should not be a valid choice for TargetSource(chosencolor)
|
// no valid choice
|
||||||
|
|
||||||
attack(2, playerB, "Goblin Piker", playerA);
|
attack(2, playerB, "Goblin Piker", playerA);
|
||||||
|
|
||||||
|
|
@ -105,7 +105,7 @@ public class StoryCircleTest extends CardTestPlayerBase {
|
||||||
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
|
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
|
||||||
execute();
|
execute();
|
||||||
|
|
||||||
assertLife(playerA, 20); // TODO: Should not prevent.
|
assertLife(playerA, 20 - 2);
|
||||||
assertTappedCount("Plains", true, 4);
|
assertTappedCount("Plains", true, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -144,13 +144,13 @@ public class StoryCircleTest extends CardTestPlayerBase {
|
||||||
|
|
||||||
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Lightning Bolt", playerA);
|
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Lightning Bolt", playerA);
|
||||||
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerA, "{W}", null, "Lightning Bolt");
|
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)
|
// no valid choice
|
||||||
|
|
||||||
setStrictChooseMode(true);
|
setStrictChooseMode(true);
|
||||||
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
|
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
|
||||||
execute();
|
execute();
|
||||||
|
|
||||||
assertLife(playerA, 20); // TODO: Should not prevent.
|
assertLife(playerA, 20 - 3);
|
||||||
assertGraveyardCount(playerB, "Lightning Bolt", 1);
|
assertGraveyardCount(playerB, "Lightning Bolt", 1);
|
||||||
assertTappedCount("Plains", true, 4);
|
assertTappedCount("Plains", true, 4);
|
||||||
}
|
}
|
||||||
|
|
@ -192,13 +192,13 @@ public class StoryCircleTest extends CardTestPlayerBase {
|
||||||
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Blisterstick Shaman");
|
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Blisterstick Shaman");
|
||||||
addTarget(playerB, playerA); // target for Shaman trigger
|
addTarget(playerB, playerA); // target for Shaman trigger
|
||||||
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerA, "{W}", null, "stack ability (When");
|
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)
|
// no valid choice
|
||||||
|
|
||||||
setStrictChooseMode(true);
|
setStrictChooseMode(true);
|
||||||
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
|
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
|
||||||
execute();
|
execute();
|
||||||
|
|
||||||
assertLife(playerA, 20); // TODO: Should not prevent.
|
assertLife(playerA, 20 - 1);
|
||||||
assertPermanentCount(playerB, "Blisterstick Shaman", 1);
|
assertPermanentCount(playerB, "Blisterstick Shaman", 1);
|
||||||
assertTappedCount("Plains", true, 4);
|
assertTappedCount("Plains", true, 4);
|
||||||
}
|
}
|
||||||
|
|
@ -238,14 +238,14 @@ public class StoryCircleTest extends CardTestPlayerBase {
|
||||||
|
|
||||||
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerB, "{R},", playerA);
|
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerB, "{R},", playerA);
|
||||||
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerA, "{W}", null, "stack ability ({R}");
|
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)
|
// no valid choice
|
||||||
|
|
||||||
setStrictChooseMode(true);
|
setStrictChooseMode(true);
|
||||||
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
|
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
|
||||||
execute();
|
execute();
|
||||||
|
|
||||||
assertTappedCount("Anaba Shaman", true, 1);
|
assertTappedCount("Anaba Shaman", true, 1);
|
||||||
assertLife(playerA, 20); // TODO: Should not prevent.
|
assertLife(playerA, 20 - 1);
|
||||||
assertTappedCount("Plains", true, 4);
|
assertTappedCount("Plains", true, 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
package org.mage.test.cards.single.tmp;
|
||||||
|
|
||||||
|
import mage.constants.PhaseStep;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Susucr
|
||||||
|
*/
|
||||||
|
public class CircleOfProtectionShadowTest extends CardTestPlayerBase {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link mage.cards.c.CircleOfProtectionShadow Circle of Protection: Shadow} {1}{W}
|
||||||
|
* Enchantment
|
||||||
|
* {1}: The next time a creature of your choice with shadow would deal damage to you this turn, prevent that damage.
|
||||||
|
*/
|
||||||
|
private static final String circle = "Circle of Protection: Shadow";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_NotShadow_NoPrevent() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, circle, 1);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerB, "Goblin Piker", 1); // 2/1
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Plains", 1);
|
||||||
|
|
||||||
|
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}");
|
||||||
|
// no creature with shadow to choose
|
||||||
|
|
||||||
|
attack(2, playerB, "Goblin Piker", playerA);
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertLife(playerA, 20 - 2);
|
||||||
|
assertTappedCount("Plains", true, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_Shadow_Prevent() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, circle, 1);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerB, "Dauthi Marauder", 1); // 2/1
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Plains", 1);
|
||||||
|
|
||||||
|
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}");
|
||||||
|
setChoice(playerA, "Dauthi Marauder");
|
||||||
|
|
||||||
|
attack(2, playerB, "Dauthi Marauder", playerA);
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertLife(playerA, 20);
|
||||||
|
assertTappedCount("Plains", true, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
package org.mage.test.cards.single.tmp;
|
||||||
|
|
||||||
|
import mage.constants.PhaseStep;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Susucr
|
||||||
|
*/
|
||||||
|
public class InvulnerabilityTest extends CardTestPlayerBase {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link mage.cards.i.Invulnerability Invulnerability} {1}{W}
|
||||||
|
* Instant
|
||||||
|
* Buyback {3} (You may pay an additional {3} as you cast this spell. If you do, put this card into your hand as it resolves.)
|
||||||
|
* The next time a source of your choice would deal damage to you this turn, prevent that damage.
|
||||||
|
*/
|
||||||
|
private static final String invulnerability = "Invulnerability";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_EmblemDamage_Prevent() {
|
||||||
|
addCard(Zone.HAND, playerA, invulnerability, 1);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerB, "Chandra, Awakened Inferno", 1); // +2: Each opponent gets an emblem with “At the beginning of your upkeep, this emblem deals 1 damage to you.”
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
|
||||||
|
|
||||||
|
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerB, "+2");
|
||||||
|
|
||||||
|
checkEmblemCount("Chandra Emblem has been created", 2, PhaseStep.POSTCOMBAT_MAIN, playerA, "Emblem Chandra", 1);
|
||||||
|
|
||||||
|
// turn 3: prevent
|
||||||
|
castSpell(3, PhaseStep.UPKEEP, playerA, invulnerability);
|
||||||
|
setChoice(playerA, false); // don't pay for Buyback
|
||||||
|
setChoice(playerA, "Emblem Chandra"); // choice for source
|
||||||
|
checkLife("prevention turn 3", 3, PhaseStep.POSTCOMBAT_MAIN, playerA, 20);
|
||||||
|
|
||||||
|
// turn 5: no prevent to check effect ending
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(5, PhaseStep.POSTCOMBAT_MAIN);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertLife(playerA, 20 - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,7 +4,7 @@ import mage.abilities.Ability;
|
||||||
import mage.abilities.effects.PreventionEffectImpl;
|
import mage.abilities.effects.PreventionEffectImpl;
|
||||||
import mage.constants.Duration;
|
import mage.constants.Duration;
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
import mage.filter.FilterObject;
|
import mage.filter.FilterSource;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.GameEvent;
|
import mage.game.events.GameEvent;
|
||||||
import mage.target.TargetSource;
|
import mage.target.TargetSource;
|
||||||
|
|
@ -17,14 +17,14 @@ public class PreventAllDamageFromChosenSourceToYouEffect extends PreventionEffec
|
||||||
protected final TargetSource targetSource;
|
protected final TargetSource targetSource;
|
||||||
|
|
||||||
public PreventAllDamageFromChosenSourceToYouEffect(Duration duration) {
|
public PreventAllDamageFromChosenSourceToYouEffect(Duration duration) {
|
||||||
this(duration, new FilterObject("source"));
|
this(duration, new FilterSource());
|
||||||
}
|
}
|
||||||
|
|
||||||
public PreventAllDamageFromChosenSourceToYouEffect(Duration duration, FilterObject filter) {
|
public PreventAllDamageFromChosenSourceToYouEffect(Duration duration, FilterSource filter) {
|
||||||
this(duration, filter, false);
|
this(duration, filter, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PreventAllDamageFromChosenSourceToYouEffect(Duration duration, FilterObject filter, boolean onlyCombat) {
|
public PreventAllDamageFromChosenSourceToYouEffect(Duration duration, FilterSource filter, boolean onlyCombat) {
|
||||||
super(duration, Integer.MAX_VALUE, onlyCombat);
|
super(duration, Integer.MAX_VALUE, onlyCombat);
|
||||||
this.targetSource = new TargetSource(filter);
|
this.targetSource = new TargetSource(filter);
|
||||||
this.staticText = setText();
|
this.staticText = setText();
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,12 @@ import mage.abilities.Ability;
|
||||||
import mage.abilities.effects.PreventionEffectImpl;
|
import mage.abilities.effects.PreventionEffectImpl;
|
||||||
import mage.constants.Duration;
|
import mage.constants.Duration;
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
import mage.filter.FilterObject;
|
import mage.filter.FilterPermanent;
|
||||||
|
import mage.filter.FilterSource;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.GameEvent;
|
import mage.game.events.GameEvent;
|
||||||
|
import mage.target.Target;
|
||||||
|
import mage.target.TargetPermanent;
|
||||||
import mage.target.TargetSource;
|
import mage.target.TargetSource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -18,25 +21,30 @@ import mage.target.TargetSource;
|
||||||
|
|
||||||
public class PreventDamageByChosenSourceEffect extends PreventionEffectImpl {
|
public class PreventDamageByChosenSourceEffect extends PreventionEffectImpl {
|
||||||
|
|
||||||
private TargetSource target;
|
private Target target;
|
||||||
private MageObjectReference mageObjectReference;
|
private MageObjectReference mageObjectReference;
|
||||||
|
|
||||||
public PreventDamageByChosenSourceEffect() {
|
public PreventDamageByChosenSourceEffect() {
|
||||||
this(new FilterObject("a source"));
|
this(new FilterSource("a source"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public PreventDamageByChosenSourceEffect(FilterObject filterObject) {
|
public PreventDamageByChosenSourceEffect(FilterSource filterSource) {
|
||||||
this(filterObject, false);
|
this(filterSource, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PreventDamageByChosenSourceEffect(FilterObject filterObject, boolean onlyCombat) {
|
public PreventDamageByChosenSourceEffect(FilterSource filterSource, boolean onlyCombat) {
|
||||||
|
this(new TargetSource(filterSource), filterSource.getMessage(), onlyCombat);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PreventDamageByChosenSourceEffect(FilterPermanent filterPermanent, boolean onlyCombat) {
|
||||||
|
this(new TargetPermanent(filterPermanent), filterPermanent.getMessage(), onlyCombat);
|
||||||
|
}
|
||||||
|
|
||||||
|
private PreventDamageByChosenSourceEffect(Target target, String filterMessage, boolean onlyCombat) {
|
||||||
super(Duration.EndOfTurn, Integer.MAX_VALUE, onlyCombat);
|
super(Duration.EndOfTurn, Integer.MAX_VALUE, onlyCombat);
|
||||||
if (!filterObject.getMessage().endsWith("source")) {
|
this.target = target;
|
||||||
filterObject.setMessage(filterObject.getMessage() + " source");
|
|
||||||
}
|
|
||||||
this.target = new TargetSource(filterObject);
|
|
||||||
staticText = "Prevent all" + (onlyCombat ? " combat" : "")
|
staticText = "Prevent all" + (onlyCombat ? " combat" : "")
|
||||||
+ " damage " + filterObject.getMessage() + " of your choice would deal this turn";
|
+ " damage " + filterMessage + " of your choice would deal this turn";
|
||||||
}
|
}
|
||||||
|
|
||||||
protected PreventDamageByChosenSourceEffect(final PreventDamageByChosenSourceEffect effect) {
|
protected PreventDamageByChosenSourceEffect(final PreventDamageByChosenSourceEffect effect) {
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,13 @@ import mage.abilities.effects.PreventionEffectData;
|
||||||
import mage.abilities.effects.PreventionEffectImpl;
|
import mage.abilities.effects.PreventionEffectImpl;
|
||||||
import mage.constants.Duration;
|
import mage.constants.Duration;
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
import mage.filter.FilterObject;
|
import mage.filter.FilterPermanent;
|
||||||
|
import mage.filter.FilterSource;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.GameEvent;
|
import mage.game.events.GameEvent;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
|
import mage.target.Target;
|
||||||
|
import mage.target.TargetPermanent;
|
||||||
import mage.target.TargetSource;
|
import mage.target.TargetSource;
|
||||||
import mage.util.CardUtil;
|
import mage.util.CardUtil;
|
||||||
|
|
||||||
|
|
@ -20,12 +23,12 @@ import java.util.UUID;
|
||||||
*/
|
*/
|
||||||
public class PreventNextDamageFromChosenSourceEffect extends PreventionEffectImpl {
|
public class PreventNextDamageFromChosenSourceEffect extends PreventionEffectImpl {
|
||||||
|
|
||||||
protected final TargetSource targetSource;
|
protected final Target target;
|
||||||
private final boolean toYou;
|
private final boolean toYou;
|
||||||
private final ApplierOnPrevention onPrevention;
|
private final ApplierOnPrevention onPrevention;
|
||||||
|
|
||||||
public interface ApplierOnPrevention extends Serializable {
|
public interface ApplierOnPrevention extends Serializable {
|
||||||
boolean apply(PreventionEffectData data, TargetSource targetsource, GameEvent event, Ability source, Game game);
|
boolean apply(PreventionEffectData data, Target target, GameEvent event, Ability source, Game game);
|
||||||
|
|
||||||
String getText();
|
String getText();
|
||||||
}
|
}
|
||||||
|
|
@ -35,7 +38,7 @@ public class PreventNextDamageFromChosenSourceEffect extends PreventionEffectImp
|
||||||
return "You gain life equal to the damage prevented this way";
|
return "You gain life equal to the damage prevented this way";
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean apply(PreventionEffectData data, TargetSource targetSource, GameEvent event, Ability source, Game game) {
|
public boolean apply(PreventionEffectData data, Target target, GameEvent event, Ability source, Game game) {
|
||||||
if (data == null || data.getPreventedDamage() <= 0) {
|
if (data == null || data.getPreventedDamage() <= 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -50,24 +53,36 @@ public class PreventNextDamageFromChosenSourceEffect extends PreventionEffectImp
|
||||||
};
|
};
|
||||||
|
|
||||||
public PreventNextDamageFromChosenSourceEffect(Duration duration, boolean toYou) {
|
public PreventNextDamageFromChosenSourceEffect(Duration duration, boolean toYou) {
|
||||||
this(duration, toYou, new FilterObject("source"));
|
this(duration, toYou, new FilterSource());
|
||||||
}
|
}
|
||||||
|
|
||||||
public PreventNextDamageFromChosenSourceEffect(Duration duration, boolean toYou, FilterObject filter) {
|
public PreventNextDamageFromChosenSourceEffect(Duration duration, boolean toYou, FilterSource filterSource) {
|
||||||
this(duration, toYou, filter, false, null);
|
this(duration, toYou, filterSource, false, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PreventNextDamageFromChosenSourceEffect(Duration duration, boolean toYou, ApplierOnPrevention onPrevention) {
|
public PreventNextDamageFromChosenSourceEffect(Duration duration, boolean toYou, ApplierOnPrevention onPrevention) {
|
||||||
this(duration, toYou, new FilterObject("source"), onPrevention);
|
this(duration, toYou, new FilterSource(), onPrevention);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PreventNextDamageFromChosenSourceEffect(Duration duration, boolean toYou, FilterObject filter, ApplierOnPrevention onPrevention) {
|
public PreventNextDamageFromChosenSourceEffect(Duration duration, boolean toYou, FilterSource filterSource, ApplierOnPrevention onPrevention) {
|
||||||
this(duration, toYou, filter, false, onPrevention);
|
this(duration, toYou, filterSource, false, onPrevention);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PreventNextDamageFromChosenSourceEffect(Duration duration, boolean toYou, FilterObject filter, boolean onlyCombat, ApplierOnPrevention onPrevention) {
|
public PreventNextDamageFromChosenSourceEffect(Duration duration, boolean toYou, FilterSource filterSource, boolean onlyCombat, ApplierOnPrevention onPrevention) {
|
||||||
|
this(duration, toYou, new TargetSource(filterSource), onlyCombat, onPrevention);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PreventNextDamageFromChosenSourceEffect(Duration duration, boolean toYou, FilterPermanent filterPermanent) {
|
||||||
|
this(duration, toYou, filterPermanent, false, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PreventNextDamageFromChosenSourceEffect(Duration duration, boolean toYou, FilterPermanent filterPermanent, boolean onlyCombat, ApplierOnPrevention onPrevention) {
|
||||||
|
this(duration, toYou, new TargetPermanent(filterPermanent), onlyCombat, onPrevention);
|
||||||
|
}
|
||||||
|
|
||||||
|
private PreventNextDamageFromChosenSourceEffect(Duration duration, boolean toYou, Target target, boolean onlyCombat, ApplierOnPrevention onPrevention) {
|
||||||
super(duration, Integer.MAX_VALUE, onlyCombat);
|
super(duration, Integer.MAX_VALUE, onlyCombat);
|
||||||
this.targetSource = new TargetSource(filter);
|
this.target = target;
|
||||||
this.toYou = toYou;
|
this.toYou = toYou;
|
||||||
this.onPrevention = onPrevention;
|
this.onPrevention = onPrevention;
|
||||||
this.staticText = setText();
|
this.staticText = setText();
|
||||||
|
|
@ -75,7 +90,7 @@ public class PreventNextDamageFromChosenSourceEffect extends PreventionEffectImp
|
||||||
|
|
||||||
protected PreventNextDamageFromChosenSourceEffect(final PreventNextDamageFromChosenSourceEffect effect) {
|
protected PreventNextDamageFromChosenSourceEffect(final PreventNextDamageFromChosenSourceEffect effect) {
|
||||||
super(effect);
|
super(effect);
|
||||||
this.targetSource = effect.targetSource.copy();
|
this.target = effect.target.copy();
|
||||||
this.toYou = effect.toYou;
|
this.toYou = effect.toYou;
|
||||||
this.onPrevention = effect.onPrevention;
|
this.onPrevention = effect.onPrevention;
|
||||||
}
|
}
|
||||||
|
|
@ -89,8 +104,8 @@ public class PreventNextDamageFromChosenSourceEffect extends PreventionEffectImp
|
||||||
public void init(Ability source, Game game) {
|
public void init(Ability source, Game game) {
|
||||||
super.init(source, game);
|
super.init(source, game);
|
||||||
UUID controllerId = source.getControllerId();
|
UUID controllerId = source.getControllerId();
|
||||||
if (this.targetSource.canChoose(controllerId, source, game)) {
|
if (this.target.canChoose(controllerId, source, game)) {
|
||||||
this.targetSource.choose(Outcome.PreventDamage, controllerId, source.getSourceId(), source, game);
|
this.target.choose(Outcome.PreventDamage, controllerId, source.getSourceId(), source, game);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -99,7 +114,7 @@ public class PreventNextDamageFromChosenSourceEffect extends PreventionEffectImp
|
||||||
PreventionEffectData data = preventDamageAction(event, source, game);
|
PreventionEffectData data = preventDamageAction(event, source, game);
|
||||||
discard();
|
discard();
|
||||||
if (onPrevention != null) {
|
if (onPrevention != null) {
|
||||||
onPrevention.apply(data, targetSource, event, source, game);
|
onPrevention.apply(data, target, event, source, game);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -108,12 +123,12 @@ public class PreventNextDamageFromChosenSourceEffect extends PreventionEffectImp
|
||||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||||
return super.applies(event, source, game)
|
return super.applies(event, source, game)
|
||||||
&& (!toYou || event.getTargetId().equals(source.getControllerId()))
|
&& (!toYou || event.getTargetId().equals(source.getControllerId()))
|
||||||
&& event.getSourceId().equals(targetSource.getFirstTarget());
|
&& target.getTargets().contains(event.getSourceId());
|
||||||
}
|
}
|
||||||
|
|
||||||
private String setText() {
|
private String setText() {
|
||||||
StringBuilder sb = new StringBuilder("The next time ")
|
StringBuilder sb = new StringBuilder("The next time ")
|
||||||
.append(CardUtil.addArticle(targetSource.getFilter().getMessage()));
|
.append(CardUtil.addArticle(target.getFilter().getMessage()));
|
||||||
sb.append(" of your choice would deal damage");
|
sb.append(" of your choice would deal damage");
|
||||||
if (toYou) {
|
if (toYou) {
|
||||||
sb.append(" to you");
|
sb.append(" to you");
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,11 @@
|
||||||
package mage.abilities.effects.common;
|
package mage.abilities.effects.common;
|
||||||
|
|
||||||
import mage.MageObject;
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.Mode;
|
import mage.abilities.Mode;
|
||||||
import mage.abilities.effects.PreventionEffectImpl;
|
import mage.abilities.effects.PreventionEffectImpl;
|
||||||
import mage.constants.Duration;
|
import mage.constants.Duration;
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
import mage.filter.FilterObject;
|
import mage.filter.FilterSource;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.GameEvent;
|
import mage.game.events.GameEvent;
|
||||||
import mage.target.TargetSource;
|
import mage.target.TargetSource;
|
||||||
|
|
@ -19,14 +18,14 @@ public class PreventNextDamageFromChosenSourceToTargetEffect extends PreventionE
|
||||||
protected final TargetSource targetSource;
|
protected final TargetSource targetSource;
|
||||||
|
|
||||||
public PreventNextDamageFromChosenSourceToTargetEffect(Duration duration) {
|
public PreventNextDamageFromChosenSourceToTargetEffect(Duration duration) {
|
||||||
this(duration, new FilterObject<>("source"));
|
this(duration, new FilterSource());
|
||||||
}
|
}
|
||||||
|
|
||||||
public PreventNextDamageFromChosenSourceToTargetEffect(Duration duration, FilterObject<MageObject> filter) {
|
public PreventNextDamageFromChosenSourceToTargetEffect(Duration duration, FilterSource filter) {
|
||||||
this(duration, filter, false);
|
this(duration, filter, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PreventNextDamageFromChosenSourceToTargetEffect(Duration duration, FilterObject<MageObject> filter, boolean onlyCombat) {
|
public PreventNextDamageFromChosenSourceToTargetEffect(Duration duration, FilterSource filter, boolean onlyCombat) {
|
||||||
super(duration, Integer.MAX_VALUE, onlyCombat);
|
super(duration, Integer.MAX_VALUE, onlyCombat);
|
||||||
this.targetSource = new TargetSource(filter);
|
this.targetSource = new TargetSource(filter);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
77
Mage/src/main/java/mage/filter/FilterSource.java
Normal file
77
Mage/src/main/java/mage/filter/FilterSource.java
Normal file
|
|
@ -0,0 +1,77 @@
|
||||||
|
|
||||||
|
package mage.filter;
|
||||||
|
|
||||||
|
import mage.MageObject;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.cards.Card;
|
||||||
|
import mage.filter.predicate.ObjectSourcePlayer;
|
||||||
|
import mage.filter.predicate.ObjectSourcePlayerPredicate;
|
||||||
|
import mage.filter.predicate.Predicate;
|
||||||
|
import mage.filter.predicate.Predicates;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.game.command.CommandObject;
|
||||||
|
import mage.game.permanent.Permanent;
|
||||||
|
import mage.game.stack.StackObject;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Susucr
|
||||||
|
*/
|
||||||
|
public class FilterSource extends FilterObject<MageObject> {
|
||||||
|
|
||||||
|
protected final List<ObjectSourcePlayerPredicate<MageObject>> extraPredicates = new ArrayList<>();
|
||||||
|
|
||||||
|
public FilterSource() {
|
||||||
|
super("source");
|
||||||
|
}
|
||||||
|
|
||||||
|
public FilterSource(String name) {
|
||||||
|
super(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
private FilterSource(final FilterSource filter) {
|
||||||
|
super(filter);
|
||||||
|
this.extraPredicates.addAll(filter.extraPredicates);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FilterSource copy() {
|
||||||
|
return new FilterSource(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FilterSource add(ObjectSourcePlayerPredicate predicate) {
|
||||||
|
if (isLockedFilter()) {
|
||||||
|
throw new UnsupportedOperationException("You may not modify a locked filter");
|
||||||
|
}
|
||||||
|
|
||||||
|
// verify check -- make sure predicates work with all 3 Class that could be a Source
|
||||||
|
Predicates.makeSurePredicateCompatibleWithFilter(predicate, Permanent.class, Card.class, StackObject.class, CommandObject.class);
|
||||||
|
|
||||||
|
extraPredicates.add(predicate);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean checkObjectClass(Object object) {
|
||||||
|
return object instanceof Permanent
|
||||||
|
|| object instanceof Card
|
||||||
|
|| object instanceof StackObject
|
||||||
|
|| object instanceof CommandObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean match(MageObject object, UUID sourceControllerId, Ability source, Game game) {
|
||||||
|
if (!this.match(object, game)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ObjectSourcePlayer<MageObject> osp = new ObjectSourcePlayer<>(object, sourceControllerId, source);
|
||||||
|
return extraPredicates.stream().allMatch(p -> p.apply(osp, game));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Predicate> getExtraPredicates() {
|
||||||
|
return new ArrayList<>(extraPredicates);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,40 +2,52 @@
|
||||||
|
|
||||||
package mage.target;
|
package mage.target;
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
import mage.MageObject;
|
import mage.MageObject;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.cards.Card;
|
import mage.cards.Card;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
import mage.filter.FilterObject;
|
import mage.filter.FilterSource;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
|
import mage.game.command.CommandObject;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.game.stack.StackObject;
|
import mage.game.stack.StackObject;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* 609.7a. If an effect requires a player to choose a source of damage, they may choose a permanent;
|
||||||
|
* a spell on the stack (including a permanent spell); any object referred to by an object on the stack,
|
||||||
|
* by a replacement or prevention effect that's waiting to apply, or by a delayed triggered ability
|
||||||
|
* that's waiting to trigger (even if that object is no longer in the zone it used to be in); or a
|
||||||
|
* face-up object in the command zone. A source doesn't need to be capable of dealing damage to be
|
||||||
|
* a legal choice. The source is chosen when the effect is created. If the player chooses a permanent,
|
||||||
|
* the effect will apply to the next damage dealt by that permanent, regardless of whether it's combat
|
||||||
|
* damage or damage dealt as the result of a spell or ability. If the player chooses a permanent spell,
|
||||||
|
* the effect will apply to any damage dealt by that spell and any damage dealt by the permanent that
|
||||||
|
* spell becomes when it resolves.
|
||||||
|
*
|
||||||
* @author BetaSteward_at_googlemail.com
|
* @author BetaSteward_at_googlemail.com
|
||||||
*/
|
*/
|
||||||
public class TargetSource extends TargetObject {
|
public class TargetSource extends TargetObject {
|
||||||
|
|
||||||
protected final FilterObject filter;
|
protected final FilterSource filter;
|
||||||
|
|
||||||
public TargetSource() {
|
public TargetSource() {
|
||||||
this(1, 1, new FilterObject("source of your choice"));
|
this(1, 1, new FilterSource("source of your choice"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public TargetSource(FilterObject filter) {
|
public TargetSource(FilterSource filter) {
|
||||||
this(1, 1, filter);
|
this(1, 1, filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
public TargetSource(int numTargets, FilterObject filter) {
|
public TargetSource(int numTargets, FilterSource filter) {
|
||||||
this(numTargets, numTargets, filter);
|
this(numTargets, numTargets, filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
public TargetSource(int minNumTargets, int maxNumTargets, FilterObject filter) {
|
public TargetSource(int minNumTargets, int maxNumTargets, FilterSource filter) {
|
||||||
super(minNumTargets, maxNumTargets, Zone.ALL, true);
|
super(minNumTargets, maxNumTargets, Zone.ALL, true);
|
||||||
this.filter = filter;
|
this.filter = filter;
|
||||||
this.targetName = filter.getMessage();
|
this.targetName = filter.getMessage();
|
||||||
|
|
@ -47,7 +59,7 @@ public class TargetSource extends TargetObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FilterObject getFilter() {
|
public FilterSource getFilter() {
|
||||||
return filter;
|
return filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -78,15 +90,16 @@ public class TargetSource extends TargetObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canChoose(UUID sourceControllerId, Ability source, Game game) {
|
public boolean canChoose(UUID sourceControllerId, Game game) {
|
||||||
return canChoose(sourceControllerId, game);
|
return canChoose(sourceControllerId, (Ability) null, game);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canChoose(UUID sourceControllerId, Game game) {
|
public boolean canChoose(UUID sourceControllerId, Ability source, Game game) {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (StackObject stackObject : game.getStack()) {
|
for (StackObject stackObject : game.getStack()) {
|
||||||
if (game.getState().getPlayersInRange(sourceControllerId, game).contains(stackObject.getControllerId()) && filter.match(stackObject, game)) {
|
if (game.getState().getPlayersInRange(sourceControllerId, game).contains(stackObject.getControllerId())
|
||||||
|
&& filter.match(stackObject, sourceControllerId, source, game)) {
|
||||||
count++;
|
count++;
|
||||||
if (count >= this.minNumberOfTargets) {
|
if (count >= this.minNumberOfTargets) {
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -94,7 +107,7 @@ public class TargetSource extends TargetObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (Permanent permanent : game.getBattlefield().getActivePermanents(sourceControllerId, game)) {
|
for (Permanent permanent : game.getBattlefield().getActivePermanents(sourceControllerId, game)) {
|
||||||
if (filter.match(permanent, game)) {
|
if (filter.match(permanent, sourceControllerId, source, game)) {
|
||||||
count++;
|
count++;
|
||||||
if (count >= this.minNumberOfTargets) {
|
if (count >= this.minNumberOfTargets) {
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -103,7 +116,7 @@ public class TargetSource extends TargetObject {
|
||||||
}
|
}
|
||||||
for (Player player : game.getPlayers().values()) {
|
for (Player player : game.getPlayers().values()) {
|
||||||
for (Card card : player.getGraveyard().getCards(game)) {
|
for (Card card : player.getGraveyard().getCards(game)) {
|
||||||
if (filter.match(card, game)) {
|
if (filter.match(card, sourceControllerId, source, game)) {
|
||||||
count++;
|
count++;
|
||||||
if (count >= this.minNumberOfTargets) {
|
if (count >= this.minNumberOfTargets) {
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -112,7 +125,15 @@ public class TargetSource extends TargetObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (Card card : game.getExile().getAllCards(game)) {
|
for (Card card : game.getExile().getAllCards(game)) {
|
||||||
if (filter.match(card, game)) {
|
if (filter.match(card, sourceControllerId, source, game)) {
|
||||||
|
count++;
|
||||||
|
if (count >= this.minNumberOfTargets) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (CommandObject commandObject : game.getState().getCommand()) {
|
||||||
|
if (filter.match(commandObject, sourceControllerId, source, game)) {
|
||||||
count++;
|
count++;
|
||||||
if (count >= this.minNumberOfTargets) {
|
if (count >= this.minNumberOfTargets) {
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -123,35 +144,41 @@ public class TargetSource extends TargetObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<UUID> possibleTargets(UUID sourceControllerId, Ability source, Game game) {
|
public Set<UUID> possibleTargets(UUID sourceControllerId, Game game) {
|
||||||
return possibleTargets(sourceControllerId, game);
|
return possibleTargets(sourceControllerId, (Ability) null, game);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<UUID> possibleTargets(UUID sourceControllerId, Game game) {
|
public Set<UUID> possibleTargets(UUID sourceControllerId, Ability source, Game game) {
|
||||||
Set<UUID> possibleTargets = new HashSet<>();
|
Set<UUID> possibleTargets = new HashSet<>();
|
||||||
for (StackObject stackObject : game.getStack()) {
|
for (StackObject stackObject : game.getStack()) {
|
||||||
if (game.getState().getPlayersInRange(sourceControllerId, game).contains(stackObject.getControllerId()) && filter.match(stackObject, game)) {
|
if (game.getState().getPlayersInRange(sourceControllerId, game).contains(stackObject.getControllerId())
|
||||||
|
&& filter.match(stackObject, sourceControllerId, source, game)) {
|
||||||
possibleTargets.add(stackObject.getId());
|
possibleTargets.add(stackObject.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (Permanent permanent : game.getBattlefield().getActivePermanents(sourceControllerId, game)) {
|
for (Permanent permanent : game.getBattlefield().getActivePermanents(sourceControllerId, game)) {
|
||||||
if (filter.match(permanent, game)) {
|
if (filter.match(permanent, sourceControllerId, source, game)) {
|
||||||
possibleTargets.add(permanent.getId());
|
possibleTargets.add(permanent.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (Player player : game.getPlayers().values()) {
|
for (Player player : game.getPlayers().values()) {
|
||||||
for (Card card : player.getGraveyard().getCards(game)) {
|
for (Card card : player.getGraveyard().getCards(game)) {
|
||||||
if (filter.match(card, game)) {
|
if (filter.match(card, sourceControllerId, source, game)) {
|
||||||
possibleTargets.add(card.getId());
|
possibleTargets.add(card.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (Card card : game.getExile().getAllCards(game)) {
|
for (Card card : game.getExile().getAllCards(game)) {
|
||||||
if (filter.match(card, game)) {
|
if (filter.match(card, sourceControllerId, source, game)) {
|
||||||
possibleTargets.add(card.getId());
|
possibleTargets.add(card.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (CommandObject commandObject : game.getState().getCommand()) {
|
||||||
|
if (filter.match(commandObject, sourceControllerId, source, game)) {
|
||||||
|
possibleTargets.add(commandObject.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
return possibleTargets;
|
return possibleTargets;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue