mirror of
https://github.com/correl/mage.git
synced 2024-11-25 03:00:11 +00:00
[DMU] Implement Defiler cycle (Ready for review) (#9460)
* [DMU] Implemented Defiler of Faith * [DMU] Implemented Defiler of Dreams * [DMU] Implemented Defiler of Flesh * [DMU] Implemented Defiler of Instinct * [DMU] Implemented Defiler of Vigor * create PermanentPredicate * initial attempt at Defiler ability * some nonfunctional recommended changes * a few more requested changes * change arguments to ObjectColor from String * fix a dumb mistake * add test * a few requested changes
This commit is contained in:
parent
835d90f0da
commit
d165072ac9
13 changed files with 572 additions and 38 deletions
59
Mage.Sets/src/mage/cards/d/DefilerOfDreams.java
Normal file
59
Mage.Sets/src/mage/cards/d/DefilerOfDreams.java
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
package mage.cards.d;
|
||||||
|
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.ObjectColor;
|
||||||
|
import mage.abilities.common.MayPay2LifeForColorAbility;
|
||||||
|
import mage.abilities.common.SpellCastControllerTriggeredAbility;
|
||||||
|
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
||||||
|
import mage.abilities.keyword.FlyingAbility;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.SubType;
|
||||||
|
import mage.filter.FilterSpell;
|
||||||
|
import mage.filter.predicate.mageobject.ColorPredicate;
|
||||||
|
import mage.filter.predicate.mageobject.PermanentPredicate;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public final class DefilerOfDreams extends CardImpl {
|
||||||
|
|
||||||
|
private static final FilterSpell filter = new FilterSpell("a blue permanent spell");
|
||||||
|
|
||||||
|
static {
|
||||||
|
filter.add(new ColorPredicate(ObjectColor.BLUE));
|
||||||
|
filter.add(PermanentPredicate.instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DefilerOfDreams(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}{U}");
|
||||||
|
|
||||||
|
this.subtype.add(SubType.PHYREXIAN);
|
||||||
|
this.subtype.add(SubType.SPHINX);
|
||||||
|
this.power = new MageInt(4);
|
||||||
|
this.toughness = new MageInt(3);
|
||||||
|
|
||||||
|
// Flying
|
||||||
|
this.addAbility(FlyingAbility.getInstance());
|
||||||
|
|
||||||
|
// As an additional cost to cast blue permanent spells, you may pay 2 life. Those spells cost {U} less to cast if you paid life this way. This effect reduces only the amount of blue mana you pay.
|
||||||
|
this.addAbility(new MayPay2LifeForColorAbility(ObjectColor.BLUE));
|
||||||
|
|
||||||
|
// Whenever you cast a blue permanent spell, draw a card.
|
||||||
|
this.addAbility(new SpellCastControllerTriggeredAbility(
|
||||||
|
new DrawCardSourceControllerEffect(1), filter, false
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
private DefilerOfDreams(final DefilerOfDreams card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DefilerOfDreams copy() {
|
||||||
|
return new DefilerOfDreams(this);
|
||||||
|
}
|
||||||
|
}
|
60
Mage.Sets/src/mage/cards/d/DefilerOfFaith.java
Normal file
60
Mage.Sets/src/mage/cards/d/DefilerOfFaith.java
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
package mage.cards.d;
|
||||||
|
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.ObjectColor;
|
||||||
|
import mage.abilities.common.MayPay2LifeForColorAbility;
|
||||||
|
import mage.abilities.common.SpellCastControllerTriggeredAbility;
|
||||||
|
import mage.abilities.effects.common.CreateTokenEffect;
|
||||||
|
import mage.abilities.keyword.VigilanceAbility;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.SubType;
|
||||||
|
import mage.filter.FilterSpell;
|
||||||
|
import mage.filter.predicate.mageobject.ColorPredicate;
|
||||||
|
import mage.filter.predicate.mageobject.PermanentPredicate;
|
||||||
|
import mage.game.permanent.token.SoldierToken;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public final class DefilerOfFaith extends CardImpl {
|
||||||
|
|
||||||
|
private static final FilterSpell filter = new FilterSpell("a white permanent spell");
|
||||||
|
|
||||||
|
static {
|
||||||
|
filter.add(new ColorPredicate(ObjectColor.WHITE));
|
||||||
|
filter.add(PermanentPredicate.instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DefilerOfFaith(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}{W}");
|
||||||
|
|
||||||
|
this.subtype.add(SubType.PHYREXIAN);
|
||||||
|
this.subtype.add(SubType.HUMAN);
|
||||||
|
this.power = new MageInt(5);
|
||||||
|
this.toughness = new MageInt(5);
|
||||||
|
|
||||||
|
// Vigilance
|
||||||
|
this.addAbility(VigilanceAbility.getInstance());
|
||||||
|
|
||||||
|
// As an additional cost to cast white permanent spells, you may pay 2 life. Those spells cost {W} less to cast if you paid life this way. This effect reduces only the amount of white mana you pay.
|
||||||
|
this.addAbility(new MayPay2LifeForColorAbility(ObjectColor.WHITE));
|
||||||
|
|
||||||
|
// Whenever you cast a white permanent spell, create a 1/1 white Soldier creature token.
|
||||||
|
this.addAbility(new SpellCastControllerTriggeredAbility(
|
||||||
|
new CreateTokenEffect(new SoldierToken()), filter, false
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
private DefilerOfFaith(final DefilerOfFaith card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DefilerOfFaith copy() {
|
||||||
|
return new DefilerOfFaith(this);
|
||||||
|
}
|
||||||
|
}
|
68
Mage.Sets/src/mage/cards/d/DefilerOfFlesh.java
Normal file
68
Mage.Sets/src/mage/cards/d/DefilerOfFlesh.java
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
package mage.cards.d;
|
||||||
|
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.ObjectColor;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.common.MayPay2LifeForColorAbility;
|
||||||
|
import mage.abilities.common.SpellCastControllerTriggeredAbility;
|
||||||
|
import mage.abilities.effects.common.continuous.BoostTargetEffect;
|
||||||
|
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
|
||||||
|
import mage.abilities.keyword.MenaceAbility;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.SubType;
|
||||||
|
import mage.filter.FilterSpell;
|
||||||
|
import mage.filter.predicate.mageobject.ColorPredicate;
|
||||||
|
import mage.filter.predicate.mageobject.PermanentPredicate;
|
||||||
|
import mage.target.common.TargetControlledCreaturePermanent;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public final class DefilerOfFlesh extends CardImpl {
|
||||||
|
|
||||||
|
private static final FilterSpell filter = new FilterSpell("a black permanent spell");
|
||||||
|
|
||||||
|
static {
|
||||||
|
filter.add(new ColorPredicate(ObjectColor.BLACK));
|
||||||
|
filter.add(PermanentPredicate.instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DefilerOfFlesh(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}{B}");
|
||||||
|
|
||||||
|
this.subtype.add(SubType.PHYREXIAN);
|
||||||
|
this.subtype.add(SubType.HORROR);
|
||||||
|
this.power = new MageInt(4);
|
||||||
|
this.toughness = new MageInt(4);
|
||||||
|
|
||||||
|
// Menace
|
||||||
|
this.addAbility(new MenaceAbility(false));
|
||||||
|
|
||||||
|
// As an additional cost to cast black permanent spells, you may pay 2 life. Those spells cost {B} less to cast if you paid life this way. This effect reduces only the amount of black mana you pay.
|
||||||
|
this.addAbility(new MayPay2LifeForColorAbility(ObjectColor.BLACK));
|
||||||
|
|
||||||
|
// Whenever you cast a black permanent spell, target creature you control gets +1/+1 and gains menace until end of turn.
|
||||||
|
Ability ability = new SpellCastControllerTriggeredAbility(
|
||||||
|
new BoostTargetEffect(1, 1)
|
||||||
|
.setText("target creature you control gets +1/+1"),
|
||||||
|
filter, false
|
||||||
|
);
|
||||||
|
ability.addEffect(new GainAbilityTargetEffect(new MenaceAbility(false))
|
||||||
|
.setText("and gains menace until end of turn"));
|
||||||
|
ability.addTarget(new TargetControlledCreaturePermanent());
|
||||||
|
this.addAbility(ability);
|
||||||
|
}
|
||||||
|
|
||||||
|
private DefilerOfFlesh(final DefilerOfFlesh card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DefilerOfFlesh copy() {
|
||||||
|
return new DefilerOfFlesh(this);
|
||||||
|
}
|
||||||
|
}
|
63
Mage.Sets/src/mage/cards/d/DefilerOfInstinct.java
Normal file
63
Mage.Sets/src/mage/cards/d/DefilerOfInstinct.java
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
package mage.cards.d;
|
||||||
|
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.ObjectColor;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.common.MayPay2LifeForColorAbility;
|
||||||
|
import mage.abilities.common.SpellCastControllerTriggeredAbility;
|
||||||
|
import mage.abilities.effects.common.DamageTargetEffect;
|
||||||
|
import mage.abilities.keyword.FirstStrikeAbility;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.SubType;
|
||||||
|
import mage.filter.FilterSpell;
|
||||||
|
import mage.filter.predicate.mageobject.ColorPredicate;
|
||||||
|
import mage.filter.predicate.mageobject.PermanentPredicate;
|
||||||
|
import mage.target.common.TargetAnyTarget;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public final class DefilerOfInstinct extends CardImpl {
|
||||||
|
|
||||||
|
private static final FilterSpell filter = new FilterSpell("a red permanent spell");
|
||||||
|
|
||||||
|
static {
|
||||||
|
filter.add(new ColorPredicate(ObjectColor.RED));
|
||||||
|
filter.add(PermanentPredicate.instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DefilerOfInstinct(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}{R}");
|
||||||
|
|
||||||
|
this.subtype.add(SubType.PHYREXIAN);
|
||||||
|
this.subtype.add(SubType.KAVU);
|
||||||
|
this.power = new MageInt(4);
|
||||||
|
this.toughness = new MageInt(4);
|
||||||
|
|
||||||
|
// First strike
|
||||||
|
this.addAbility(FirstStrikeAbility.getInstance());
|
||||||
|
|
||||||
|
// As an additional cost to cast red permanent spells, you may pay 2 life. Those spells cost {R} less to cast if you paid life this way. This effect reduces only the amount of red mana you pay.
|
||||||
|
this.addAbility(new MayPay2LifeForColorAbility(ObjectColor.RED));
|
||||||
|
|
||||||
|
// Whenever you cast a red permanent spell, Defiler of Instinct deals 1 damage to any target.
|
||||||
|
Ability ability = new SpellCastControllerTriggeredAbility(
|
||||||
|
new DamageTargetEffect(1), filter, false
|
||||||
|
);
|
||||||
|
ability.addTarget(new TargetAnyTarget());
|
||||||
|
this.addAbility(ability);
|
||||||
|
}
|
||||||
|
|
||||||
|
private DefilerOfInstinct(final DefilerOfInstinct card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DefilerOfInstinct copy() {
|
||||||
|
return new DefilerOfInstinct(this);
|
||||||
|
}
|
||||||
|
}
|
64
Mage.Sets/src/mage/cards/d/DefilerOfVigor.java
Normal file
64
Mage.Sets/src/mage/cards/d/DefilerOfVigor.java
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
package mage.cards.d;
|
||||||
|
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.ObjectColor;
|
||||||
|
import mage.abilities.common.MayPay2LifeForColorAbility;
|
||||||
|
import mage.abilities.common.SpellCastControllerTriggeredAbility;
|
||||||
|
import mage.abilities.effects.common.counter.AddCountersAllEffect;
|
||||||
|
import mage.abilities.keyword.TrampleAbility;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.SubType;
|
||||||
|
import mage.counters.CounterType;
|
||||||
|
import mage.filter.FilterSpell;
|
||||||
|
import mage.filter.StaticFilters;
|
||||||
|
import mage.filter.predicate.mageobject.ColorPredicate;
|
||||||
|
import mage.filter.predicate.mageobject.PermanentPredicate;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public final class DefilerOfVigor extends CardImpl {
|
||||||
|
|
||||||
|
private static final FilterSpell filter = new FilterSpell("a green permanent spell");
|
||||||
|
|
||||||
|
static {
|
||||||
|
filter.add(new ColorPredicate(ObjectColor.GREEN));
|
||||||
|
filter.add(PermanentPredicate.instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DefilerOfVigor(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}{G}");
|
||||||
|
|
||||||
|
this.subtype.add(SubType.PHYREXIAN);
|
||||||
|
this.subtype.add(SubType.WURM);
|
||||||
|
this.power = new MageInt(6);
|
||||||
|
this.toughness = new MageInt(6);
|
||||||
|
|
||||||
|
// Trample
|
||||||
|
this.addAbility(TrampleAbility.getInstance());
|
||||||
|
|
||||||
|
// As an additional cost to cast green permanent spells, you may pay 2 life. Those spells cost {G} less to cast if you paid life this way. This effect reduces only the amount of green mana you pay.
|
||||||
|
this.addAbility(new MayPay2LifeForColorAbility(ObjectColor.GREEN));
|
||||||
|
|
||||||
|
// Whenever you cast a green permanent spell, put a +1/+1 counter on each creature you control.
|
||||||
|
this.addAbility(new SpellCastControllerTriggeredAbility(
|
||||||
|
new AddCountersAllEffect(
|
||||||
|
CounterType.P1P1.createInstance(),
|
||||||
|
StaticFilters.FILTER_CONTROLLED_CREATURE
|
||||||
|
), filter, false
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
private DefilerOfVigor(final DefilerOfVigor card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DefilerOfVigor copy() {
|
||||||
|
return new DefilerOfVigor(this);
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,6 +16,7 @@ import mage.filter.FilterCard;
|
||||||
import mage.filter.StaticFilters;
|
import mage.filter.StaticFilters;
|
||||||
import mage.filter.common.FilterPermanentCard;
|
import mage.filter.common.FilterPermanentCard;
|
||||||
import mage.filter.predicate.mageobject.ManaValuePredicate;
|
import mage.filter.predicate.mageobject.ManaValuePredicate;
|
||||||
|
import mage.filter.predicate.mageobject.PermanentPredicate;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.util.CardUtil;
|
import mage.util.CardUtil;
|
||||||
|
@ -85,6 +86,7 @@ class InSearchOfGreatnessEffect extends OneShotEffect {
|
||||||
.orElse(0);
|
.orElse(0);
|
||||||
FilterCard filter = new FilterPermanentCard();
|
FilterCard filter = new FilterPermanentCard();
|
||||||
filter.add(new ManaValuePredicate(ComparisonType.EQUAL_TO, manaValue + 1));
|
filter.add(new ManaValuePredicate(ComparisonType.EQUAL_TO, manaValue + 1));
|
||||||
|
filter.add(PermanentPredicate.instance);
|
||||||
return CardUtil.castSpellWithAttributesForFree(
|
return CardUtil.castSpellWithAttributesForFree(
|
||||||
controller, source, game, new CardsImpl(controller.getHand()), filter
|
controller, source, game, new CardsImpl(controller.getHand()), filter
|
||||||
) || controller.scry(1, source, game);
|
) || controller.scry(1, source, game);
|
||||||
|
|
|
@ -16,11 +16,10 @@ import mage.constants.TargetController;
|
||||||
import mage.filter.FilterSpell;
|
import mage.filter.FilterSpell;
|
||||||
import mage.filter.FilterStackObject;
|
import mage.filter.FilterStackObject;
|
||||||
import mage.filter.common.FilterInstantOrSorcerySpell;
|
import mage.filter.common.FilterInstantOrSorcerySpell;
|
||||||
import mage.filter.predicate.Predicate;
|
import mage.filter.predicate.mageobject.PermanentPredicate;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.game.stack.StackAbility;
|
import mage.game.stack.StackAbility;
|
||||||
import mage.game.stack.StackObject;
|
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.target.TargetSpell;
|
import mage.target.TargetSpell;
|
||||||
import mage.target.common.TargetActivatedOrTriggeredAbility;
|
import mage.target.common.TargetActivatedOrTriggeredAbility;
|
||||||
|
@ -43,7 +42,7 @@ public final class LithoformEngine extends CardImpl {
|
||||||
filter.add(TargetController.YOU.getControllerPredicate());
|
filter.add(TargetController.YOU.getControllerPredicate());
|
||||||
filter2.add(TargetController.YOU.getControllerPredicate());
|
filter2.add(TargetController.YOU.getControllerPredicate());
|
||||||
filter3.add(TargetController.YOU.getControllerPredicate());
|
filter3.add(TargetController.YOU.getControllerPredicate());
|
||||||
filter3.add(LithoformEnginePredicate.instance);
|
filter3.add(PermanentPredicate.instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
public LithoformEngine(UUID ownerId, CardSetInfo setInfo) {
|
public LithoformEngine(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
@ -82,15 +81,6 @@ public final class LithoformEngine extends CardImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum LithoformEnginePredicate implements Predicate<StackObject> {
|
|
||||||
instance;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean apply(StackObject input, Game game) {
|
|
||||||
return input.isPermanent(game);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class LithoformEngineEffect extends OneShotEffect {
|
class LithoformEngineEffect extends OneShotEffect {
|
||||||
|
|
||||||
public LithoformEngineEffect() {
|
public LithoformEngineEffect() {
|
||||||
|
|
|
@ -16,9 +16,7 @@ import mage.constants.SuperType;
|
||||||
import mage.constants.TargetController;
|
import mage.constants.TargetController;
|
||||||
import mage.counters.CounterType;
|
import mage.counters.CounterType;
|
||||||
import mage.filter.FilterSpell;
|
import mage.filter.FilterSpell;
|
||||||
import mage.filter.predicate.Predicate;
|
import mage.filter.predicate.mageobject.PermanentPredicate;
|
||||||
import mage.game.Game;
|
|
||||||
import mage.game.stack.StackObject;
|
|
||||||
import mage.target.TargetSpell;
|
import mage.target.TargetSpell;
|
||||||
import mage.watchers.common.CastFromHandWatcher;
|
import mage.watchers.common.CastFromHandWatcher;
|
||||||
|
|
||||||
|
@ -30,9 +28,10 @@ import java.util.UUID;
|
||||||
public class MyojinOfCrypticDreams extends CardImpl {
|
public class MyojinOfCrypticDreams extends CardImpl {
|
||||||
|
|
||||||
private static final FilterSpell permanentSpellFilter = new FilterSpell("permanent spell you control");
|
private static final FilterSpell permanentSpellFilter = new FilterSpell("permanent spell you control");
|
||||||
|
|
||||||
static {
|
static {
|
||||||
permanentSpellFilter.add(TargetController.YOU.getControllerPredicate());
|
permanentSpellFilter.add(TargetController.YOU.getControllerPredicate());
|
||||||
permanentSpellFilter.add(MyojinOfCrypticDreamsPredicate.instance);
|
permanentSpellFilter.add(PermanentPredicate.instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MyojinOfCrypticDreams(UUID ownderId, CardSetInfo setInfo) {
|
public MyojinOfCrypticDreams(UUID ownderId, CardSetInfo setInfo) {
|
||||||
|
@ -63,17 +62,12 @@ public class MyojinOfCrypticDreams extends CardImpl {
|
||||||
this.addAbility(ability);
|
this.addAbility(ability);
|
||||||
}
|
}
|
||||||
|
|
||||||
private MyojinOfCrypticDreams(final MyojinOfCrypticDreams card) { super(card); }
|
private MyojinOfCrypticDreams(final MyojinOfCrypticDreams card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MyojinOfCrypticDreams copy() { return new MyojinOfCrypticDreams(this); }
|
public MyojinOfCrypticDreams copy() {
|
||||||
}
|
return new MyojinOfCrypticDreams(this);
|
||||||
|
|
||||||
enum MyojinOfCrypticDreamsPredicate implements Predicate<StackObject> {
|
|
||||||
instance;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean apply(StackObject input, Game game) {
|
|
||||||
return input.isPermanent(game);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,6 +88,11 @@ public final class DominariaUnited extends ExpansionSet {
|
||||||
cards.add(new SetCardInfo("Cut Down", 89, Rarity.UNCOMMON, mage.cards.c.CutDown.class));
|
cards.add(new SetCardInfo("Cut Down", 89, Rarity.UNCOMMON, mage.cards.c.CutDown.class));
|
||||||
cards.add(new SetCardInfo("Danitha, Benalia's Hope", 15, Rarity.RARE, mage.cards.d.DanithaBenaliasHope.class));
|
cards.add(new SetCardInfo("Danitha, Benalia's Hope", 15, Rarity.RARE, mage.cards.d.DanithaBenaliasHope.class));
|
||||||
cards.add(new SetCardInfo("Deathbloom Gardener", 159, Rarity.COMMON, mage.cards.d.DeathbloomGardener.class));
|
cards.add(new SetCardInfo("Deathbloom Gardener", 159, Rarity.COMMON, mage.cards.d.DeathbloomGardener.class));
|
||||||
|
cards.add(new SetCardInfo("Defiler of Dreams", 46, Rarity.RARE, mage.cards.d.DefilerOfDreams.class));
|
||||||
|
cards.add(new SetCardInfo("Defiler of Faith", 16, Rarity.RARE, mage.cards.d.DefilerOfFaith.class));
|
||||||
|
cards.add(new SetCardInfo("Defiler of Flesh", 90, Rarity.RARE, mage.cards.d.DefilerOfFlesh.class));
|
||||||
|
cards.add(new SetCardInfo("Defiler of Instinct", 119, Rarity.RARE, mage.cards.d.DefilerOfInstinct.class));
|
||||||
|
cards.add(new SetCardInfo("Defiler of Vigor", 160, Rarity.RARE, mage.cards.d.DefilerOfVigor.class));
|
||||||
cards.add(new SetCardInfo("Destroy Evil", 17, Rarity.COMMON, mage.cards.d.DestroyEvil.class));
|
cards.add(new SetCardInfo("Destroy Evil", 17, Rarity.COMMON, mage.cards.d.DestroyEvil.class));
|
||||||
cards.add(new SetCardInfo("Djinn of the Fountain", 47, Rarity.UNCOMMON, mage.cards.d.DjinnOfTheFountain.class));
|
cards.add(new SetCardInfo("Djinn of the Fountain", 47, Rarity.UNCOMMON, mage.cards.d.DjinnOfTheFountain.class));
|
||||||
cards.add(new SetCardInfo("Drag to the Bottom", 91, Rarity.RARE, mage.cards.d.DragToTheBottom.class));
|
cards.add(new SetCardInfo("Drag to the Bottom", 91, Rarity.RARE, mage.cards.d.DragToTheBottom.class));
|
||||||
|
|
|
@ -0,0 +1,118 @@
|
||||||
|
package org.mage.test.cards.cost.additional;
|
||||||
|
|
||||||
|
import mage.constants.PhaseStep;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import mage.counters.CounterType;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public class DefilersTest extends CardTestPlayerBase {
|
||||||
|
private static final String greenDefiler = "Defiler of Vigor";
|
||||||
|
private static final String redDefiler = "Defiler of Instinct";
|
||||||
|
private static final String bear = "Grizzly Bears";
|
||||||
|
private static final String tusker = "Kalonian Tusker";
|
||||||
|
private static final String goblin = "Scarwood Goblins";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRegularAccept() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Forest");
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, greenDefiler);
|
||||||
|
addCard(Zone.HAND, playerA, bear);
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, bear);
|
||||||
|
setChoice(playerA, true);
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertLife(playerA, 20 - 2);
|
||||||
|
assertPermanentCount(playerA, bear, 1);
|
||||||
|
assertCounterCount(playerA, greenDefiler, CounterType.P1P1, 1);
|
||||||
|
assertTappedCount("Forest", true, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRegularDecline() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Forest", 2);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, greenDefiler);
|
||||||
|
addCard(Zone.HAND, playerA, bear);
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, bear);
|
||||||
|
setChoice(playerA, false);
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertLife(playerA, 20);
|
||||||
|
assertPermanentCount(playerA, bear, 1);
|
||||||
|
assertCounterCount(playerA, greenDefiler, CounterType.P1P1, 1);
|
||||||
|
assertTappedCount("Forest", true, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDoubleReduceOne() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Forest");
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, greenDefiler, 2);
|
||||||
|
addCard(Zone.HAND, playerA, bear);
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, bear);
|
||||||
|
setChoice(playerA, true);
|
||||||
|
setChoice(playerA, true);
|
||||||
|
setChoice(playerA, "");
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertLife(playerA, 20 - 2 - 2);
|
||||||
|
assertPermanentCount(playerA, bear, 1);
|
||||||
|
assertCounterCount(playerA, greenDefiler, CounterType.P1P1, 2);
|
||||||
|
assertTappedCount("Forest", true, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDoubleReduceBoth() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, greenDefiler, 2);
|
||||||
|
addCard(Zone.HAND, playerA, tusker);
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, tusker);
|
||||||
|
setChoice(playerA, true);
|
||||||
|
setChoice(playerA, true);
|
||||||
|
setChoice(playerA, "");
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertLife(playerA, 20 - 2 - 2);
|
||||||
|
assertPermanentCount(playerA, tusker, 1);
|
||||||
|
assertCounterCount(playerA, greenDefiler, CounterType.P1P1, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTwoColors() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, greenDefiler);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, redDefiler);
|
||||||
|
addCard(Zone.HAND, playerA, goblin);
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, goblin);
|
||||||
|
setChoice(playerA, true);
|
||||||
|
setChoice(playerA, true);
|
||||||
|
setChoice(playerA, "");
|
||||||
|
addTarget(playerA, playerB);
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertLife(playerA, 20 - 2 - 2);
|
||||||
|
assertLife(playerB, 20 - 1);
|
||||||
|
assertPermanentCount(playerA, goblin, 1);
|
||||||
|
assertCounterCount(playerA, greenDefiler, CounterType.P1P1, 1);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,104 @@
|
||||||
|
package mage.abilities.common;
|
||||||
|
|
||||||
|
import mage.ObjectColor;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.SpellAbility;
|
||||||
|
import mage.abilities.StaticAbility;
|
||||||
|
import mage.abilities.costs.Cost;
|
||||||
|
import mage.abilities.costs.common.PayLifeCost;
|
||||||
|
import mage.abilities.costs.mana.ManaCost;
|
||||||
|
import mage.abilities.costs.mana.ManaCosts;
|
||||||
|
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
|
import mage.abilities.effects.common.cost.CostModificationEffectImpl;
|
||||||
|
import mage.cards.Card;
|
||||||
|
import mage.constants.CostModificationType;
|
||||||
|
import mage.constants.Duration;
|
||||||
|
import mage.constants.Outcome;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.players.Player;
|
||||||
|
import mage.util.CardUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public class MayPay2LifeForColorAbility extends StaticAbility {
|
||||||
|
|
||||||
|
private final String rule;
|
||||||
|
|
||||||
|
public MayPay2LifeForColorAbility(ObjectColor color) {
|
||||||
|
super(Zone.BATTLEFIELD, new MayPay2LifeEffect(color));
|
||||||
|
this.rule = makeRule(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
private MayPay2LifeForColorAbility(final MayPay2LifeForColorAbility ability) {
|
||||||
|
super(ability);
|
||||||
|
this.rule = ability.rule;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MayPay2LifeForColorAbility copy() {
|
||||||
|
return new MayPay2LifeForColorAbility(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getRule() {
|
||||||
|
return rule;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String makeRule(ObjectColor color) {
|
||||||
|
return "As an additional cost to cast " + color.getDescription() +
|
||||||
|
" permanent spells, you may pay 2 life. Those spells cost {" + color +
|
||||||
|
"} less to cast if you paid life this way. This effect reduces only " +
|
||||||
|
"the amount of " + color.getDescription() + " mana you pay.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MayPay2LifeEffect extends CostModificationEffectImpl {
|
||||||
|
|
||||||
|
private final ObjectColor color;
|
||||||
|
private final ManaCosts<ManaCost> manaCost;
|
||||||
|
|
||||||
|
MayPay2LifeEffect(ObjectColor color) {
|
||||||
|
super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.REDUCE_COST);
|
||||||
|
this.color = color;
|
||||||
|
this.manaCost = new ManaCostsImpl<>("{" + color + "}");
|
||||||
|
}
|
||||||
|
|
||||||
|
private MayPay2LifeEffect(final MayPay2LifeEffect effect) {
|
||||||
|
super(effect);
|
||||||
|
this.color = effect.color;
|
||||||
|
this.manaCost = effect.manaCost;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MayPay2LifeEffect copy() {
|
||||||
|
return new MayPay2LifeEffect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source, Ability abilityToModify) {
|
||||||
|
Player player = game.getPlayer(abilityToModify.getControllerId());
|
||||||
|
Cost cost = new PayLifeCost(2);
|
||||||
|
if (!cost.canPay(abilityToModify, source, source.getControllerId(), game)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (game.inCheckPlayableState() || (
|
||||||
|
player.chooseUse(outcome, "Pay 2 life to reduce the cost by {" + color + "}?", source, game)
|
||||||
|
&& cost.pay(abilityToModify, game, source, source.getControllerId(), true)
|
||||||
|
)) {
|
||||||
|
CardUtil.adjustCost((SpellAbility) abilityToModify, manaCost, false);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean applies(Ability abilityToModify, Ability source, Game game) {
|
||||||
|
if (!(abilityToModify instanceof SpellAbility)
|
||||||
|
|| !abilityToModify.isControlledBy(source.getControllerId())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Card spellCard = ((SpellAbility) abilityToModify).getCharacteristics(game);
|
||||||
|
return spellCard.isPermanent(game) && spellCard.getColor(game).contains(color);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,13 +1,9 @@
|
||||||
|
|
||||||
|
|
||||||
package mage.filter.common;
|
package mage.filter.common;
|
||||||
|
|
||||||
import mage.constants.CardType;
|
|
||||||
import mage.filter.FilterCard;
|
import mage.filter.FilterCard;
|
||||||
import mage.filter.predicate.Predicates;
|
import mage.filter.predicate.mageobject.PermanentPredicate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author Plopman
|
* @author Plopman
|
||||||
*/
|
*/
|
||||||
public class FilterPermanentCard extends FilterCard {
|
public class FilterPermanentCard extends FilterCard {
|
||||||
|
@ -18,13 +14,7 @@ public class FilterPermanentCard extends FilterCard {
|
||||||
|
|
||||||
public FilterPermanentCard(String name) {
|
public FilterPermanentCard(String name) {
|
||||||
super(name);
|
super(name);
|
||||||
this.add(
|
this.add(PermanentPredicate.instance);
|
||||||
Predicates.or(
|
|
||||||
CardType.ARTIFACT.getPredicate(),
|
|
||||||
CardType.CREATURE.getPredicate(),
|
|
||||||
CardType.ENCHANTMENT.getPredicate(),
|
|
||||||
CardType.LAND.getPredicate(),
|
|
||||||
CardType.PLANESWALKER.getPredicate()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public FilterPermanentCard(final FilterPermanentCard filter) {
|
public FilterPermanentCard(final FilterPermanentCard filter) {
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
package mage.filter.predicate.mageobject;
|
||||||
|
|
||||||
|
import mage.MageObject;
|
||||||
|
import mage.filter.predicate.Predicate;
|
||||||
|
import mage.game.Game;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public enum PermanentPredicate implements Predicate<MageObject> {
|
||||||
|
instance;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(MageObject input, Game game) {
|
||||||
|
return input.isPermanent(game);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue