mirror of
https://github.com/correl/mage.git
synced 2024-11-28 19:19:55 +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.common.FilterPermanentCard;
|
||||
import mage.filter.predicate.mageobject.ManaValuePredicate;
|
||||
import mage.filter.predicate.mageobject.PermanentPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.util.CardUtil;
|
||||
|
@ -85,6 +86,7 @@ class InSearchOfGreatnessEffect extends OneShotEffect {
|
|||
.orElse(0);
|
||||
FilterCard filter = new FilterPermanentCard();
|
||||
filter.add(new ManaValuePredicate(ComparisonType.EQUAL_TO, manaValue + 1));
|
||||
filter.add(PermanentPredicate.instance);
|
||||
return CardUtil.castSpellWithAttributesForFree(
|
||||
controller, source, game, new CardsImpl(controller.getHand()), filter
|
||||
) || controller.scry(1, source, game);
|
||||
|
|
|
@ -16,11 +16,10 @@ import mage.constants.TargetController;
|
|||
import mage.filter.FilterSpell;
|
||||
import mage.filter.FilterStackObject;
|
||||
import mage.filter.common.FilterInstantOrSorcerySpell;
|
||||
import mage.filter.predicate.Predicate;
|
||||
import mage.filter.predicate.mageobject.PermanentPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.stack.StackAbility;
|
||||
import mage.game.stack.StackObject;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetSpell;
|
||||
import mage.target.common.TargetActivatedOrTriggeredAbility;
|
||||
|
@ -43,7 +42,7 @@ public final class LithoformEngine extends CardImpl {
|
|||
filter.add(TargetController.YOU.getControllerPredicate());
|
||||
filter2.add(TargetController.YOU.getControllerPredicate());
|
||||
filter3.add(TargetController.YOU.getControllerPredicate());
|
||||
filter3.add(LithoformEnginePredicate.instance);
|
||||
filter3.add(PermanentPredicate.instance);
|
||||
}
|
||||
|
||||
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 {
|
||||
|
||||
public LithoformEngineEffect() {
|
||||
|
|
|
@ -16,9 +16,7 @@ import mage.constants.SuperType;
|
|||
import mage.constants.TargetController;
|
||||
import mage.counters.CounterType;
|
||||
import mage.filter.FilterSpell;
|
||||
import mage.filter.predicate.Predicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.stack.StackObject;
|
||||
import mage.filter.predicate.mageobject.PermanentPredicate;
|
||||
import mage.target.TargetSpell;
|
||||
import mage.watchers.common.CastFromHandWatcher;
|
||||
|
||||
|
@ -30,9 +28,10 @@ import java.util.UUID;
|
|||
public class MyojinOfCrypticDreams extends CardImpl {
|
||||
|
||||
private static final FilterSpell permanentSpellFilter = new FilterSpell("permanent spell you control");
|
||||
|
||||
static {
|
||||
permanentSpellFilter.add(TargetController.YOU.getControllerPredicate());
|
||||
permanentSpellFilter.add(MyojinOfCrypticDreamsPredicate.instance);
|
||||
permanentSpellFilter.add(PermanentPredicate.instance);
|
||||
}
|
||||
|
||||
public MyojinOfCrypticDreams(UUID ownderId, CardSetInfo setInfo) {
|
||||
|
@ -63,17 +62,12 @@ public class MyojinOfCrypticDreams extends CardImpl {
|
|||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
private MyojinOfCrypticDreams(final MyojinOfCrypticDreams card) { super(card); }
|
||||
private MyojinOfCrypticDreams(final MyojinOfCrypticDreams card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
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);
|
||||
public MyojinOfCrypticDreams copy() {
|
||||
return new MyojinOfCrypticDreams(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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("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("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("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));
|
||||
|
|
|
@ -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;
|
||||
|
||||
import mage.constants.CardType;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.filter.predicate.mageobject.PermanentPredicate;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Plopman
|
||||
*/
|
||||
public class FilterPermanentCard extends FilterCard {
|
||||
|
@ -18,13 +14,7 @@ public class FilterPermanentCard extends FilterCard {
|
|||
|
||||
public FilterPermanentCard(String name) {
|
||||
super(name);
|
||||
this.add(
|
||||
Predicates.or(
|
||||
CardType.ARTIFACT.getPredicate(),
|
||||
CardType.CREATURE.getPredicate(),
|
||||
CardType.ENCHANTMENT.getPredicate(),
|
||||
CardType.LAND.getPredicate(),
|
||||
CardType.PLANESWALKER.getPredicate()));
|
||||
this.add(PermanentPredicate.instance);
|
||||
}
|
||||
|
||||
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