diff --git a/Mage.Sets/src/mage/cards/a/AshPartyCrasher.java b/Mage.Sets/src/mage/cards/a/AshPartyCrasher.java new file mode 100644 index 00000000000..5e2d9a24d09 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AshPartyCrasher.java @@ -0,0 +1,56 @@ +package mage.cards.a; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.condition.common.CelebrationCondition; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.keyword.HasteAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.AbilityWord; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.counters.CounterType; +import mage.watchers.common.CelebrationWatcher; + +import java.util.UUID; + +/** + * @author Susucr + */ +public final class AshPartyCrasher extends CardImpl { + + public AshPartyCrasher(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{R}{W}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.PEASANT); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Haste + this.addAbility(HasteAbility.getInstance()); + + // Celebration -- Whenever Ash, Party Crasher attacks, if two or more nonland permanents entered the battlefield under your control this turn, put a +1/+1 counter on Ash. + Ability ability = new ConditionalInterveningIfTriggeredAbility( + new AttacksTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance(1)), false), + CelebrationCondition.instance, + "Whenever {this} attacks, if two or more nonland permanents entered the battlefield under your control this turn, put a +1/+1 counter on {this}." + ); + ability.setAbilityWord(AbilityWord.CELEBRATION); + this.addAbility(ability, new CelebrationWatcher()); + } + + private AshPartyCrasher(final AshPartyCrasher card) { + super(card); + } + + @Override + public AshPartyCrasher copy() { + return new AshPartyCrasher(this); + } +} diff --git a/Mage.Sets/src/mage/sets/WildsOfEldraine.java b/Mage.Sets/src/mage/sets/WildsOfEldraine.java index f8bd6a9b377..5010c3be79a 100644 --- a/Mage.Sets/src/mage/sets/WildsOfEldraine.java +++ b/Mage.Sets/src/mage/sets/WildsOfEldraine.java @@ -20,6 +20,7 @@ public final class WildsOfEldraine extends ExpansionSet { this.blockName = "Wilds of Eldraine"; this.hasBoosters = false; // temporary + cards.add(new SetCardInfo("Ash, Party Crasher", 201, Rarity.UNCOMMON, mage.cards.a.AshPartyCrasher.class)); cards.add(new SetCardInfo("Cruel Somnophage", 222, Rarity.RARE, mage.cards.c.CruelSomnophage.class)); cards.add(new SetCardInfo("Evolving Wilds", 256, Rarity.COMMON, mage.cards.e.EvolvingWilds.class)); cards.add(new SetCardInfo("Faerie Dreamthief", 89, Rarity.UNCOMMON, mage.cards.f.FaerieDreamthief.class)); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/woe/AshPartyCrasherTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/woe/AshPartyCrasherTest.java new file mode 100644 index 00000000000..0e4291867dd --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/woe/AshPartyCrasherTest.java @@ -0,0 +1,151 @@ +package org.mage.test.cards.single.woe; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * @author Susucr + */ +public class AshPartyCrasherTest extends CardTestPlayerBase { + + /** + * Ash, Party Crasher + * {R}{W} + * Legendary Creature — Human Peasant + *
+ * Haste
+ * Celebration — Whenever Ash, Party Crasher attacks, if two or more nonland permanents entered the battlefield under your co
+ */
+ private static final String ash = "Ash, Party Crasher";
+
+ // {1}{G} 2/2
+ private static final String bears = "Grizzly Bears";
+
+ /**
+ * Instant {1}{W}
+ * Create two 1/1 white Soldier creature tokens.
+ */
+ private static final String raiseTheAlarm = "Raise the Alarm";
+
+ @Test
+ public void noCelebration() {
+ setStrictChooseMode(true);
+
+ addCard(Zone.BATTLEFIELD, playerA, ash);
+ attack(1, playerA, ash);
+ setStopAt(1, PhaseStep.END_COMBAT);
+ execute();
+
+ assertLife(playerB, 20 - 2);
+ }
+
+ @Test
+ public void celebrationItselfAndBear() {
+ setStrictChooseMode(true);
+
+ addCard(Zone.HAND, playerA, ash);
+ addCard(Zone.HAND, playerA, bears);
+ addCard(Zone.BATTLEFIELD, playerA, "Plateau", 2);
+ addCard(Zone.BATTLEFIELD, playerA, "Forest", 2);
+
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, ash, true);
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, bears);
+
+ attack(1, playerA, ash);
+ setStopAt(1, PhaseStep.END_COMBAT);
+ execute();
+
+ assertLife(playerB, 20 - 3);
+ }
+
+ @Test
+ public void noCelebrationOnLand() {
+ setStrictChooseMode(true);
+
+ addCard(Zone.HAND, playerA, ash);
+ addCard(Zone.HAND, playerA, "Forest");
+ addCard(Zone.BATTLEFIELD, playerA, "Plateau", 2);
+
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, ash, true);
+ playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Forest");
+
+ attack(1, playerA, ash);
+ setStopAt(1, PhaseStep.END_COMBAT);
+ execute();
+
+ assertLife(playerB, 20 - 2);
+ }
+
+ @Test
+ public void celebrationBearThenItself() {
+ setStrictChooseMode(true);
+
+ addCard(Zone.HAND, playerA, ash);
+ addCard(Zone.HAND, playerA, bears);
+ addCard(Zone.BATTLEFIELD, playerA, "Plateau", 2);
+ addCard(Zone.BATTLEFIELD, playerA, "Forest", 2);
+
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, bears, true);
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, ash);
+
+ attack(1, playerA, ash);
+ setStopAt(1, PhaseStep.END_COMBAT);
+ execute();
+
+ assertLife(playerB, 20 - 3);
+ }
+
+ @Test
+ public void celebrationDoubleBear() {
+ setStrictChooseMode(true);
+
+ addCard(Zone.BATTLEFIELD, playerA, ash);
+ addCard(Zone.HAND, playerA, bears, 2);
+ addCard(Zone.BATTLEFIELD, playerA, "Forest", 4);
+
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, bears, true);
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, bears);
+
+ attack(1, playerA, ash);
+ setStopAt(1, PhaseStep.END_COMBAT);
+ execute();
+
+ assertLife(playerB, 20 - 3);
+ }
+
+ @Test
+ public void celebrationRaiseTheAlarm() {
+ setStrictChooseMode(true);
+
+ addCard(Zone.BATTLEFIELD, playerA, ash);
+ addCard(Zone.HAND, playerA, raiseTheAlarm);
+ addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
+
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, raiseTheAlarm);
+
+ attack(1, playerA, ash);
+ setStopAt(1, PhaseStep.END_COMBAT);
+ execute();
+
+ assertLife(playerB, 20 - 3);
+ }
+
+ @Test
+ public void noCelebrationOpponentRaiseTheAlarm() {
+ setStrictChooseMode(true);
+
+ addCard(Zone.BATTLEFIELD, playerA, ash);
+ addCard(Zone.HAND, playerB, raiseTheAlarm);
+ addCard(Zone.BATTLEFIELD, playerB, "Plains", 2);
+
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, raiseTheAlarm);
+
+ attack(1, playerA, ash);
+ setStopAt(1, PhaseStep.END_COMBAT);
+ execute();
+
+ assertLife(playerB, 20 - 2);
+ }
+}
\ No newline at end of file
diff --git a/Mage/src/main/java/mage/abilities/condition/common/CelebrationCondition.java b/Mage/src/main/java/mage/abilities/condition/common/CelebrationCondition.java
new file mode 100644
index 00000000000..1e7c9390dfe
--- /dev/null
+++ b/Mage/src/main/java/mage/abilities/condition/common/CelebrationCondition.java
@@ -0,0 +1,25 @@
+
+package mage.abilities.condition.common;
+
+import mage.abilities.Ability;
+import mage.abilities.condition.Condition;
+import mage.game.Game;
+import mage.watchers.common.CelebrationWatcher;
+
+/**
+ * @author Susucr
+ */
+public enum CelebrationCondition implements Condition {
+ instance;
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ CelebrationWatcher watcher = game.getState().getWatcher(CelebrationWatcher.class);
+ return watcher != null && watcher.celebrationActive(source.getControllerId());
+ }
+
+ @Override
+ public String toString() {
+ return "two or more nonland permanents entered the battlefield under your control this turn";
+ }
+}
diff --git a/Mage/src/main/java/mage/constants/AbilityWord.java b/Mage/src/main/java/mage/constants/AbilityWord.java
index 467171211f4..9f3f197b921 100644
--- a/Mage/src/main/java/mage/constants/AbilityWord.java
+++ b/Mage/src/main/java/mage/constants/AbilityWord.java
@@ -12,6 +12,7 @@ public enum AbilityWord {
ALLIANCE("Alliance"),
BATTALION("Battalion"),
BLOODRUSH("Bloodrush"),
+ CELEBRATION("Celebration"),
CHANNEL("Channel"),
CHROMA("Chroma"),
COHORT("Cohort"),
diff --git a/Mage/src/main/java/mage/watchers/common/CelebrationWatcher.java b/Mage/src/main/java/mage/watchers/common/CelebrationWatcher.java
new file mode 100644
index 00000000000..d191b94f947
--- /dev/null
+++ b/Mage/src/main/java/mage/watchers/common/CelebrationWatcher.java
@@ -0,0 +1,47 @@
+package mage.watchers.common;
+
+import mage.constants.WatcherScope;
+import mage.game.Game;
+import mage.game.events.GameEvent;
+import mage.game.permanent.Permanent;
+import mage.util.CardUtil;
+import mage.watchers.Watcher;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ * @author Susucr
+ */
+public class CelebrationWatcher extends Watcher {
+
+ // playerId -> number of nonland permanents entered the battlefield this turn under that player's control.
+ private final Map