mirror of
https://github.com/magefree/mage.git
synced 2025-12-22 03:22:00 -08:00
Implement Impending mechanic (#12865)
* implement Impending mechanic * add initial test * add more tests * small fix
This commit is contained in:
parent
50f892b935
commit
d923f2941d
9 changed files with 348 additions and 20 deletions
|
|
@ -36,7 +36,7 @@ public final class OverlordOfTheBalemurk extends CardImpl {
|
||||||
this.toughness = new MageInt(5);
|
this.toughness = new MageInt(5);
|
||||||
|
|
||||||
// Impending 5--{1}{B}
|
// Impending 5--{1}{B}
|
||||||
this.addAbility(new ImpendingAbility("{1}{B}", 5));
|
this.addAbility(new ImpendingAbility(5, "{1}{B}"));
|
||||||
|
|
||||||
// Whenever Overlord of the Balemurk enters or attacks, mill four cards, then you may return a non-Avatar creature card or a planeswalker card from your graveyard to your hand.
|
// Whenever Overlord of the Balemurk enters or attacks, mill four cards, then you may return a non-Avatar creature card or a planeswalker card from your graveyard to your hand.
|
||||||
Ability ability = new EntersBattlefieldOrAttacksSourceTriggeredAbility(new MillCardsControllerEffect(4));
|
Ability ability = new EntersBattlefieldOrAttacksSourceTriggeredAbility(new MillCardsControllerEffect(4));
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ public final class OverlordOfTheBoilerbilges extends CardImpl {
|
||||||
this.toughness = new MageInt(5);
|
this.toughness = new MageInt(5);
|
||||||
|
|
||||||
// Impending 4--{2}{R}{R}
|
// Impending 4--{2}{R}{R}
|
||||||
this.addAbility(new ImpendingAbility("{2}{R}{R}"));
|
this.addAbility(new ImpendingAbility(4, "{2}{R}{R}"));
|
||||||
|
|
||||||
// Whenever Overlord of the Boilerbilges enters or attacks, it deals 4 damage to any target.
|
// Whenever Overlord of the Boilerbilges enters or attacks, it deals 4 damage to any target.
|
||||||
Ability ability = new EntersBattlefieldOrAttacksSourceTriggeredAbility(new DamageTargetEffect(4));
|
Ability ability = new EntersBattlefieldOrAttacksSourceTriggeredAbility(new DamageTargetEffect(4));
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ public final class OverlordOfTheFloodpits extends CardImpl {
|
||||||
this.toughness = new MageInt(3);
|
this.toughness = new MageInt(3);
|
||||||
|
|
||||||
// Impending 4--{1}{U}{U}
|
// Impending 4--{1}{U}{U}
|
||||||
this.addAbility(new ImpendingAbility("{1}{U}{U}"));
|
this.addAbility(new ImpendingAbility(4, "{1}{U}{U}"));
|
||||||
|
|
||||||
// Flying
|
// Flying
|
||||||
this.addAbility(FlyingAbility.getInstance());
|
this.addAbility(FlyingAbility.getInstance());
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ public final class OverlordOfTheHauntwoods extends CardImpl {
|
||||||
this.toughness = new MageInt(5);
|
this.toughness = new MageInt(5);
|
||||||
|
|
||||||
// Impending 4--{1}{G}{G}
|
// Impending 4--{1}{G}{G}
|
||||||
this.addAbility(new ImpendingAbility("{1}{G}{G}"));
|
this.addAbility(new ImpendingAbility(4, "{1}{G}{G}"));
|
||||||
|
|
||||||
// Whenever Overlord of the Hauntwoods enters or attacks, create a tapped colorless land token named Everywhere that is every basic land type.
|
// Whenever Overlord of the Hauntwoods enters or attacks, create a tapped colorless land token named Everywhere that is every basic land type.
|
||||||
this.addAbility(new EntersBattlefieldOrAttacksSourceTriggeredAbility(
|
this.addAbility(new EntersBattlefieldOrAttacksSourceTriggeredAbility(
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ public final class OverlordOfTheMistmoors extends CardImpl {
|
||||||
this.toughness = new MageInt(6);
|
this.toughness = new MageInt(6);
|
||||||
|
|
||||||
// Impending 4--{2}{W}{W}
|
// Impending 4--{2}{W}{W}
|
||||||
this.addAbility(new ImpendingAbility("{2}{W}{W}"));
|
this.addAbility(new ImpendingAbility(4, "{2}{W}{W}"));
|
||||||
|
|
||||||
// Whenever Overlord of the Mistmoors enters or attacks, create two 2/1 white Insect creature tokens with flying.
|
// Whenever Overlord of the Mistmoors enters or attacks, create two 2/1 white Insect creature tokens with flying.
|
||||||
this.addAbility(new EntersBattlefieldOrAttacksSourceTriggeredAbility(new CreateTokenEffect(new InsectWhiteToken(), 2)));
|
this.addAbility(new EntersBattlefieldOrAttacksSourceTriggeredAbility(new CreateTokenEffect(new InsectWhiteToken(), 2)));
|
||||||
|
|
|
||||||
|
|
@ -224,7 +224,5 @@ public final class DuskmournHouseOfHorror extends ExpansionSet {
|
||||||
cards.add(new SetCardInfo("Winter, Misanthropic Guide", 240, Rarity.RARE, mage.cards.w.WinterMisanthropicGuide.class));
|
cards.add(new SetCardInfo("Winter, Misanthropic Guide", 240, Rarity.RARE, mage.cards.w.WinterMisanthropicGuide.class));
|
||||||
cards.add(new SetCardInfo("Withering Torment", 124, Rarity.UNCOMMON, mage.cards.w.WitheringTorment.class));
|
cards.add(new SetCardInfo("Withering Torment", 124, Rarity.UNCOMMON, mage.cards.w.WitheringTorment.class));
|
||||||
cards.add(new SetCardInfo("Zimone, All-Questioning", 241, Rarity.RARE, mage.cards.z.ZimoneAllQuestioning.class));
|
cards.add(new SetCardInfo("Zimone, All-Questioning", 241, Rarity.RARE, mage.cards.z.ZimoneAllQuestioning.class));
|
||||||
|
|
||||||
cards.removeIf(setCardInfo -> setCardInfo.getName().startsWith("Overlord"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,226 @@
|
||||||
|
package org.mage.test.cards.abilities.keywords;
|
||||||
|
|
||||||
|
import mage.abilities.keyword.ImpendingAbility;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.PhaseStep;
|
||||||
|
import mage.constants.SubType;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import mage.counters.CounterType;
|
||||||
|
import mage.game.permanent.Permanent;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public class ImpendingTest extends CardTestPlayerBase {
|
||||||
|
|
||||||
|
private static final String hauntwoods = "Overlord of the Hauntwoods";
|
||||||
|
|
||||||
|
public void assertHasImpending(String name, boolean hasAbility) {
|
||||||
|
Permanent permanent = getPermanent(name);
|
||||||
|
Assert.assertEquals(
|
||||||
|
"Should" + (hasAbility ? "" : "n't") + " have Impending ability",
|
||||||
|
hasAbility, permanent.getAbilities(currentGame).containsClass(ImpendingAbility.class)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCastRegular() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Forest", 5);
|
||||||
|
addCard(Zone.HAND, playerA, hauntwoods);
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, hauntwoods);
|
||||||
|
setChoice(playerA, "Cast with no");
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertPermanentCount(playerA, hauntwoods, 1);
|
||||||
|
assertType(hauntwoods, CardType.ENCHANTMENT, true);
|
||||||
|
assertType(hauntwoods, CardType.CREATURE, true);
|
||||||
|
assertSubtype(hauntwoods, SubType.AVATAR);
|
||||||
|
assertSubtype(hauntwoods, SubType.HORROR);
|
||||||
|
assertCounterCount(playerA, hauntwoods, CounterType.TIME, 0);
|
||||||
|
assertPowerToughness(playerA, hauntwoods, 6, 5);
|
||||||
|
assertHasImpending(hauntwoods, true);
|
||||||
|
|
||||||
|
assertPermanentCount(playerA, "Everywhere", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCastImpending() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Forest", 3);
|
||||||
|
addCard(Zone.HAND, playerA, hauntwoods);
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, hauntwoods);
|
||||||
|
setChoice(playerA, "Cast with Impending");
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertPermanentCount(playerA, hauntwoods, 1);
|
||||||
|
assertType(hauntwoods, CardType.ENCHANTMENT, true);
|
||||||
|
assertType(hauntwoods, CardType.CREATURE, false);
|
||||||
|
assertCounterCount(playerA, hauntwoods, CounterType.TIME, 4);
|
||||||
|
assertHasImpending(hauntwoods, true);
|
||||||
|
|
||||||
|
assertPermanentCount(playerA, "Everywhere", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testImpendingRemoveCounter() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Forest", 3);
|
||||||
|
addCard(Zone.HAND, playerA, hauntwoods);
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, hauntwoods);
|
||||||
|
setChoice(playerA, "Cast with Impending");
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertPermanentCount(playerA, hauntwoods, 1);
|
||||||
|
assertType(hauntwoods, CardType.ENCHANTMENT, true);
|
||||||
|
assertType(hauntwoods, CardType.CREATURE, false);
|
||||||
|
assertCounterCount(playerA, hauntwoods, CounterType.TIME, 4 - 1);
|
||||||
|
assertHasImpending(hauntwoods, true);
|
||||||
|
|
||||||
|
assertPermanentCount(playerA, "Everywhere", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCastImpendingRemoveAllCounters() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Forest", 3);
|
||||||
|
addCard(Zone.HAND, playerA, hauntwoods);
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, hauntwoods);
|
||||||
|
setChoice(playerA, "Cast with Impending");
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(8, PhaseStep.POSTCOMBAT_MAIN);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertPermanentCount(playerA, hauntwoods, 1);
|
||||||
|
assertType(hauntwoods, CardType.ENCHANTMENT, true);
|
||||||
|
assertType(hauntwoods, CardType.CREATURE, true);
|
||||||
|
assertSubtype(hauntwoods, SubType.AVATAR);
|
||||||
|
assertSubtype(hauntwoods, SubType.HORROR);
|
||||||
|
assertCounterCount(playerA, hauntwoods, CounterType.TIME, 0);
|
||||||
|
assertPowerToughness(playerA, hauntwoods, 6, 5);
|
||||||
|
assertHasImpending(hauntwoods, false);
|
||||||
|
|
||||||
|
assertPermanentCount(playerA, "Everywhere", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final String hexmage = "Vampire Hexmage";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCastImpendingHexmage() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Forest", 3);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, hexmage);
|
||||||
|
addCard(Zone.HAND, playerA, hauntwoods);
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, hauntwoods);
|
||||||
|
setChoice(playerA, "Cast with Impending");
|
||||||
|
|
||||||
|
activateAbility(1, PhaseStep.BEGIN_COMBAT, playerA, "Sacrifice", hauntwoods);
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertPermanentCount(playerA, hauntwoods, 1);
|
||||||
|
assertType(hauntwoods, CardType.ENCHANTMENT, true);
|
||||||
|
assertType(hauntwoods, CardType.CREATURE, true);
|
||||||
|
assertSubtype(hauntwoods, SubType.AVATAR);
|
||||||
|
assertSubtype(hauntwoods, SubType.HORROR);
|
||||||
|
assertCounterCount(playerA, hauntwoods, CounterType.TIME, 0);
|
||||||
|
assertPowerToughness(playerA, hauntwoods, 6, 5);
|
||||||
|
assertHasImpending(hauntwoods, true);
|
||||||
|
|
||||||
|
assertPermanentCount(playerA, "Everywhere", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCastImpendingHexmageNextTurn() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Forest", 3);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, hexmage);
|
||||||
|
addCard(Zone.HAND, playerA, hauntwoods);
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, hauntwoods);
|
||||||
|
setChoice(playerA, "Cast with Impending");
|
||||||
|
|
||||||
|
activateAbility(1, PhaseStep.BEGIN_COMBAT, playerA, "Sacrifice", hauntwoods);
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertPermanentCount(playerA, hauntwoods, 1);
|
||||||
|
assertType(hauntwoods, CardType.ENCHANTMENT, true);
|
||||||
|
assertType(hauntwoods, CardType.CREATURE, true);
|
||||||
|
assertSubtype(hauntwoods, SubType.AVATAR);
|
||||||
|
assertSubtype(hauntwoods, SubType.HORROR);
|
||||||
|
assertCounterCount(playerA, hauntwoods, CounterType.TIME, 0);
|
||||||
|
assertPowerToughness(playerA, hauntwoods, 6, 5);
|
||||||
|
assertHasImpending(hauntwoods, false);
|
||||||
|
|
||||||
|
assertPermanentCount(playerA, "Everywhere", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final String solemnity = "Solemnity";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCastImpendingSolemnity() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Forest", 3);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, solemnity);
|
||||||
|
addCard(Zone.HAND, playerA, hauntwoods);
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, hauntwoods);
|
||||||
|
setChoice(playerA, "Cast with Impending");
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertPermanentCount(playerA, hauntwoods, 1);
|
||||||
|
assertType(hauntwoods, CardType.ENCHANTMENT, true);
|
||||||
|
assertType(hauntwoods, CardType.CREATURE, true);
|
||||||
|
assertSubtype(hauntwoods, SubType.AVATAR);
|
||||||
|
assertSubtype(hauntwoods, SubType.HORROR);
|
||||||
|
assertCounterCount(playerA, hauntwoods, CounterType.TIME, 0);
|
||||||
|
assertPowerToughness(playerA, hauntwoods, 6, 5);
|
||||||
|
assertHasImpending(hauntwoods, true);
|
||||||
|
|
||||||
|
assertPermanentCount(playerA, "Everywhere", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCastImpendingSolemnityNextTurn() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Forest", 3);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, solemnity);
|
||||||
|
addCard(Zone.HAND, playerA, hauntwoods);
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, hauntwoods);
|
||||||
|
setChoice(playerA, "Cast with Impending");
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertPermanentCount(playerA, hauntwoods, 1);
|
||||||
|
assertType(hauntwoods, CardType.ENCHANTMENT, true);
|
||||||
|
assertType(hauntwoods, CardType.CREATURE, true);
|
||||||
|
assertSubtype(hauntwoods, SubType.AVATAR);
|
||||||
|
assertSubtype(hauntwoods, SubType.HORROR);
|
||||||
|
assertCounterCount(playerA, hauntwoods, CounterType.TIME, 0);
|
||||||
|
assertPowerToughness(playerA, hauntwoods, 6, 5);
|
||||||
|
assertHasImpending(hauntwoods, false);
|
||||||
|
|
||||||
|
assertPermanentCount(playerA, "Everywhere", 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -30,11 +30,15 @@ public abstract class AlternativeSourceCostsImpl extends StaticAbility implement
|
||||||
}
|
}
|
||||||
|
|
||||||
protected AlternativeSourceCostsImpl(String name, String reminderText, Cost cost) {
|
protected AlternativeSourceCostsImpl(String name, String reminderText, Cost cost) {
|
||||||
|
this(name, reminderText, cost, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected AlternativeSourceCostsImpl(String name, String reminderText, Cost cost, String activationKey) {
|
||||||
super(Zone.ALL, null);
|
super(Zone.ALL, null);
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.reminderText = reminderText;
|
this.reminderText = reminderText;
|
||||||
this.alternativeCost = new AlternativeCostImpl<>(name, reminderText, cost);
|
this.alternativeCost = new AlternativeCostImpl<>(name, reminderText, cost);
|
||||||
this.activationKey = getActivationKey(name);
|
this.activationKey = getActivationKey(activationKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected AlternativeSourceCostsImpl(final AlternativeSourceCostsImpl ability) {
|
protected AlternativeSourceCostsImpl(final AlternativeSourceCostsImpl ability) {
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,33 @@
|
||||||
package mage.abilities.keyword;
|
package mage.abilities.keyword;
|
||||||
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.common.BeginningOfEndStepTriggeredAbility;
|
||||||
|
import mage.abilities.common.EntersBattlefieldAbility;
|
||||||
|
import mage.abilities.common.SimpleStaticAbility;
|
||||||
|
import mage.abilities.condition.Condition;
|
||||||
|
import mage.abilities.condition.common.SourceHasCounterCondition;
|
||||||
import mage.abilities.costs.AlternativeSourceCostsImpl;
|
import mage.abilities.costs.AlternativeSourceCostsImpl;
|
||||||
|
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
|
import mage.abilities.decorator.ConditionalOneShotEffect;
|
||||||
|
import mage.abilities.effects.ContinuousEffectImpl;
|
||||||
|
import mage.abilities.effects.common.AddContinuousEffectToGame;
|
||||||
|
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
||||||
|
import mage.abilities.effects.common.counter.RemoveCounterSourceEffect;
|
||||||
|
import mage.constants.*;
|
||||||
|
import mage.counters.CounterType;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
|
import mage.game.permanent.Permanent;
|
||||||
import mage.util.CardUtil;
|
import mage.util.CardUtil;
|
||||||
|
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: Implement this
|
* "Impending N–[cost]" is a keyword that represents multiple abilities.
|
||||||
|
* The official rules are as follows:
|
||||||
|
* (a) You may choose to pay [cost] rather than pay this spell's mana cost.
|
||||||
|
* (b) If you chose to pay this spell's impending cost, it enters the battlefield with N time counters on it.
|
||||||
|
* (c) As long as this permanent has a time counter on it, if it was cast for its impending cost, it's not a creature.
|
||||||
|
* (d) At the beginning of your end step, if this permanent was cast for its impending cost, remove a time counter from it. Then if it has no time counters on it, it loses impending.
|
||||||
*
|
*
|
||||||
* @author TheElk801
|
* @author TheElk801
|
||||||
*/
|
*/
|
||||||
|
|
@ -16,14 +37,24 @@ public class ImpendingAbility extends AlternativeSourceCostsImpl {
|
||||||
private static final String IMPENDING_REMINDER = "If you cast this spell for its impending cost, " +
|
private static final String IMPENDING_REMINDER = "If you cast this spell for its impending cost, " +
|
||||||
"it enters with %s time counters and isn't a creature until the last is removed. " +
|
"it enters with %s time counters and isn't a creature until the last is removed. " +
|
||||||
"At the beginning of your end step, remove a time counter from it.";
|
"At the beginning of your end step, remove a time counter from it.";
|
||||||
|
private static final Condition counterCondition = new SourceHasCounterCondition(CounterType.TIME, 0, 0);
|
||||||
|
|
||||||
public ImpendingAbility(String manaString) {
|
public ImpendingAbility(int amount, String manaString) {
|
||||||
this(manaString, 4);
|
super(IMPENDING_KEYWORD + ' ' + amount, String.format(IMPENDING_REMINDER, CardUtil.numberToText(amount)), new ManaCostsImpl<>(manaString), IMPENDING_KEYWORD);
|
||||||
}
|
|
||||||
|
|
||||||
public ImpendingAbility(String manaString, int amount) {
|
|
||||||
super(IMPENDING_KEYWORD + ' ' + amount, String.format(IMPENDING_REMINDER, CardUtil.numberToText(amount)), manaString);
|
|
||||||
this.setRuleAtTheTop(true);
|
this.setRuleAtTheTop(true);
|
||||||
|
this.addSubAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(
|
||||||
|
new AddCountersSourceEffect(CounterType.TIME.createInstance(amount)), ImpendingCondition.instance, ""
|
||||||
|
), "").setRuleVisible(false));
|
||||||
|
this.addSubAbility(new SimpleStaticAbility(new ImpendingAbilityTypeEffect()).setRuleVisible(false));
|
||||||
|
Ability ability = new BeginningOfEndStepTriggeredAbility(
|
||||||
|
new RemoveCounterSourceEffect(CounterType.TIME.createInstance()),
|
||||||
|
TargetController.YOU, ImpendingCondition.instance, false
|
||||||
|
);
|
||||||
|
ability.addEffect(new ConditionalOneShotEffect(
|
||||||
|
new AddContinuousEffectToGame(new ImpendingAbilityRemoveEffect()),
|
||||||
|
counterCondition, "Then if it has no time counters on it, it loses impending"
|
||||||
|
));
|
||||||
|
this.addSubAbility(ability.setRuleVisible(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
private ImpendingAbility(final ImpendingAbility ability) {
|
private ImpendingAbility(final ImpendingAbility ability) {
|
||||||
|
|
@ -35,12 +66,81 @@ public class ImpendingAbility extends AlternativeSourceCostsImpl {
|
||||||
return new ImpendingAbility(this);
|
return new ImpendingAbility(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isAvailable(Ability source, Game game) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getActivationKey() {
|
public static String getActivationKey() {
|
||||||
return getActivationKey(IMPENDING_KEYWORD);
|
return getActivationKey(IMPENDING_KEYWORD);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum ImpendingCondition implements Condition {
|
||||||
|
instance;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source) {
|
||||||
|
return CardUtil.checkSourceCostsTagExists(game, source, ImpendingAbility.getActivationKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ImpendingAbilityTypeEffect extends ContinuousEffectImpl {
|
||||||
|
|
||||||
|
ImpendingAbilityTypeEffect() {
|
||||||
|
super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Detriment);
|
||||||
|
staticText = "As long as this permanent has a time counter on it, if it was cast for its impending cost, it's not a creature.";
|
||||||
|
}
|
||||||
|
|
||||||
|
private ImpendingAbilityTypeEffect(final ImpendingAbilityTypeEffect effect) {
|
||||||
|
super(effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ImpendingAbilityTypeEffect copy() {
|
||||||
|
return new ImpendingAbilityTypeEffect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source) {
|
||||||
|
if (!ImpendingCondition.instance.apply(game, source)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Permanent permanent = source.getSourcePermanentIfItStillExists(game);
|
||||||
|
if (permanent.getCounters(game).getCount(CounterType.TIME) < 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
permanent.removeCardType(game, CardType.CREATURE);
|
||||||
|
permanent.removeAllCreatureTypes(game);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ImpendingAbilityRemoveEffect extends ContinuousEffectImpl {
|
||||||
|
|
||||||
|
ImpendingAbilityRemoveEffect() {
|
||||||
|
super(Duration.Custom, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.LoseAbility);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ImpendingAbilityRemoveEffect(final ImpendingAbilityRemoveEffect effect) {
|
||||||
|
super(effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ImpendingAbilityRemoveEffect copy() {
|
||||||
|
return new ImpendingAbilityRemoveEffect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source) {
|
||||||
|
Permanent permanent = source.getSourcePermanentIfItStillExists(game);
|
||||||
|
if (permanent == null) {
|
||||||
|
discard();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
permanent.removeAbilities(
|
||||||
|
permanent
|
||||||
|
.getAbilities(game)
|
||||||
|
.stream()
|
||||||
|
.filter(ImpendingAbility.class::isInstance)
|
||||||
|
.collect(Collectors.toList()),
|
||||||
|
source.getSourceId(), game
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue