diff --git a/Mage.Sets/src/mage/sets/futuresight/RiverOfTears.java b/Mage.Sets/src/mage/sets/futuresight/RiverOfTears.java
index 7ba8ddb7251..881bc577850 100644
--- a/Mage.Sets/src/mage/sets/futuresight/RiverOfTears.java
+++ b/Mage.Sets/src/mage/sets/futuresight/RiverOfTears.java
@@ -50,7 +50,7 @@ public class RiverOfTears extends CardImpl {
super(ownerId, 179, "River of Tears", Rarity.RARE, new CardType[]{CardType.LAND}, "");
this.expansionSetCode = "FUT";
- // {tap}: Add {U} to your mana pool. If you played a land this turn, add {B} to your mana pool instead.
+ // {T}: Add {U} to your mana pool. If you played a land this turn, add {B} to your mana pool instead.
this.addAbility(new ConditionalManaAbility(Zone.BATTLEFIELD, new ConditionalManaEffect(
new BasicManaEffect(Mana.BlackMana),
new BasicManaEffect(Mana.BlueMana),
diff --git a/Mage.Sets/src/mage/sets/worldwake/Groundswell.java b/Mage.Sets/src/mage/sets/worldwake/Groundswell.java
index 1296415b715..9598babd39e 100644
--- a/Mage.Sets/src/mage/sets/worldwake/Groundswell.java
+++ b/Mage.Sets/src/mage/sets/worldwake/Groundswell.java
@@ -32,17 +32,13 @@ import java.util.UUID;
import mage.constants.CardType;
import mage.constants.Duration;
-import mage.constants.Layer;
-import mage.constants.Outcome;
import mage.constants.Rarity;
-import mage.constants.SubLayer;
-import mage.abilities.Ability;
-import mage.abilities.effects.ContinuousEffectImpl;
+import mage.abilities.condition.LockedInCondition;
+import mage.abilities.condition.common.LandfallCondition;
+import mage.abilities.decorator.ConditionalContinuousEffect;
+import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.cards.CardImpl;
-import mage.game.Game;
-import mage.game.permanent.Permanent;
import mage.target.common.TargetCreaturePermanent;
-import mage.watchers.Watcher;
import mage.watchers.common.LandfallWatcher;
/**
@@ -55,11 +51,13 @@ public class Groundswell extends CardImpl {
super(ownerId, 104, "Groundswell", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{G}");
this.expansionSetCode = "WWK";
-
- this.getSpellAbility().addTarget(new TargetCreaturePermanent());
- this.getSpellAbility().addEffect(new GroundswellEffect(Duration.EndOfTurn));
-
+ // Target creature gets +2/+2 until end of turn.
+ //Landfall - If you had a land enter the battlefield under your control this turn, that creature gets +4/+4 until end of turn instead.
this.getSpellAbility().addWatcher(new LandfallWatcher());
+ this.getSpellAbility().addEffect(new ConditionalContinuousEffect(new BoostTargetEffect(4, 4, Duration.EndOfTurn), new BoostTargetEffect(2, 2, Duration.EndOfTurn),
+ new LockedInCondition(LandfallCondition.getInstance()),
+ "Target creature gets +2/+2 until end of turn.
Landfall — If you had a land enter the battlefield under your control this turn, that creature gets +4/44 until end of turn instead"));
+ this.getSpellAbility().addTarget(new TargetCreaturePermanent());
}
public Groundswell(final Groundswell card) {
@@ -71,39 +69,3 @@ public class Groundswell extends CardImpl {
return new Groundswell(this);
}
}
-
-class GroundswellEffect extends ContinuousEffectImpl {
-
- public GroundswellEffect(Duration duration) {
- super(duration, Layer.PTChangingEffects_7, SubLayer.ModifyPT_7c, Outcome.BoostCreature);
- staticText = "Target creature gets +2/+2 until end of turn.\nLandfall - If you had a land enter the battlefield under your control this turn, that creature gets +4/+4 until end of turn instead";
- }
-
- public GroundswellEffect(final GroundswellEffect effect) {
- super(effect);
- }
-
- @Override
- public GroundswellEffect copy() {
- return new GroundswellEffect(this);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- Watcher watcher = game.getState().getWatchers().get("LandPlayed", source.getControllerId());
- Permanent target = (Permanent) game.getPermanent(source.getFirstTarget());
- if (target != null) {
- if (watcher != null && watcher.conditionMet()) {
- target.addPower(4);
- target.addToughness(4);
- }
- else{
- target.addPower(2);
- target.addToughness(2);
- }
- return true;
- }
- return false;
- }
-
-}
diff --git a/Mage.Sets/src/mage/sets/worldwake/MysteriesOfTheDeep.java b/Mage.Sets/src/mage/sets/worldwake/MysteriesOfTheDeep.java
index 19a28ff6d7d..804ff917687 100644
--- a/Mage.Sets/src/mage/sets/worldwake/MysteriesOfTheDeep.java
+++ b/Mage.Sets/src/mage/sets/worldwake/MysteriesOfTheDeep.java
@@ -46,7 +46,6 @@ public class MysteriesOfTheDeep extends CardImpl {
super(ownerId, 33, "Mysteries of the Deep", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{4}{U}");
this.expansionSetCode = "WWK";
-
// Draw two cards.
// Landfall - If you had a land enter the battlefield under your control this turn, draw three cards instead.
this.getSpellAbility().addWatcher(new LandfallWatcher());
diff --git a/Mage.Sets/src/mage/sets/worldwake/RestForTheWeary.java b/Mage.Sets/src/mage/sets/worldwake/RestForTheWeary.java
index 890df85a5a4..08a543c1340 100644
--- a/Mage.Sets/src/mage/sets/worldwake/RestForTheWeary.java
+++ b/Mage.Sets/src/mage/sets/worldwake/RestForTheWeary.java
@@ -47,7 +47,6 @@ public class RestForTheWeary extends CardImpl {
super(ownerId, 18, "Rest for the Weary", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{1}{W}");
this.expansionSetCode = "WWK";
-
// Target player gains 4 life.
// Landfall - If you had a land enter the battlefield under your control this turn, that player gains 8 life instead.
this.getSpellAbility().addWatcher(new LandfallWatcher());
diff --git a/Mage.Sets/src/mage/sets/worldwake/SearingBlaze.java b/Mage.Sets/src/mage/sets/worldwake/SearingBlaze.java
index ec39deffdac..c5b2b73ac36 100644
--- a/Mage.Sets/src/mage/sets/worldwake/SearingBlaze.java
+++ b/Mage.Sets/src/mage/sets/worldwake/SearingBlaze.java
@@ -59,7 +59,6 @@ public class SearingBlaze extends CardImpl {
super(ownerId, 90, "Searing Blaze", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{R}{R}");
this.expansionSetCode = "WWK";
-
// Searing Blaze deals 1 damage to target player and 1 damage to target creature that player controls.
// Landfall - If you had a land enter the battlefield under your control this turn, Searing Blaze deals 3 damage to that player and 3 damage to that creature instead.
this.getSpellAbility().addTarget(new TargetPlayer());
diff --git a/Mage.Sets/src/mage/sets/worldwake/TombHex.java b/Mage.Sets/src/mage/sets/worldwake/TombHex.java
index 1204445582d..6a42e79ddcf 100644
--- a/Mage.Sets/src/mage/sets/worldwake/TombHex.java
+++ b/Mage.Sets/src/mage/sets/worldwake/TombHex.java
@@ -50,13 +50,12 @@ public class TombHex extends CardImpl {
super(ownerId, 69, "Tomb Hex", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{2}{B}");
this.expansionSetCode = "WWK";
-
// Target creature gets -2/-2 until end of turn.
// Landfall - If you had a land enter the battlefield under your control this turn, that creature gets -4/-4 until end of turn instead.
this.getSpellAbility().addWatcher(new LandfallWatcher());
this.getSpellAbility().addEffect(new ConditionalContinuousEffect(new BoostTargetEffect(-4, -4, Duration.EndOfTurn), new BoostTargetEffect(-2, -2, Duration.EndOfTurn),
new LockedInCondition(LandfallCondition.getInstance()),
- "Target creature gets -2/-2 until end of turn. Landfall - If you had a land enter the battlefield under your control this turn, that creature gets -4/-4 until end of turn instead"));
+ "Target creature gets -2/-2 until end of turn.
Landfall — If you had a land enter the battlefield under your control this turn, that creature gets -4/-4 until end of turn instead"));
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
}
diff --git a/Mage.Sets/src/mage/sets/zendikar/SurrakarMarauder.java b/Mage.Sets/src/mage/sets/zendikar/SurrakarMarauder.java
index 0e317d3a684..1f10bd4ea43 100644
--- a/Mage.Sets/src/mage/sets/zendikar/SurrakarMarauder.java
+++ b/Mage.Sets/src/mage/sets/zendikar/SurrakarMarauder.java
@@ -52,6 +52,8 @@ public class SurrakarMarauder extends CardImpl {
this.power = new MageInt(2);
this.toughness = new MageInt(1);
+ // Landfall - Whenever a land enters the battlefield under your control, Surrakar Marauder gains intimidate until end of turn.
+ // (It can't be blocked except by artifact creatures and/or creatures that share a color with it.)
this.addAbility(new LandfallAbility(new GainAbilitySourceEffect(IntimidateAbility.getInstance(), Duration.EndOfTurn), false));
}
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/LandfallTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/LandfallTest.java
new file mode 100644
index 00000000000..ef5349b9ae8
--- /dev/null
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/LandfallTest.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of BetaSteward_at_googlemail.com.
+ */
+package org.mage.test.cards.abilities.keywords;
+
+import mage.abilities.keyword.IntimidateAbility;
+import mage.constants.PhaseStep;
+import mage.constants.Zone;
+import org.junit.Test;
+import org.mage.test.serverside.base.CardTestPlayerBase;
+
+/**
+ *
+ * @author LevelX2
+ */
+
+public class LandfallTest extends CardTestPlayerBase {
+
+ @Test
+ public void testNormalUse() {
+ addCard(Zone.BATTLEFIELD, playerA, "Plains",3);
+ addCard(Zone.HAND, playerA, "Plains");
+
+ // Instant - {1}{W}
+ // Target player gains 4 life.
+ // Landfall - If you had a land enter the battlefield under your control this turn, that player gains 8 life instead.
+ addCard(Zone.HAND, playerA, "Rest for the Weary",2);
+
+ playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Plains");
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Rest for the Weary");
+
+ castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerA, "Rest for the Weary");
+
+ setStopAt(2, PhaseStep.BEGIN_COMBAT);
+ execute();
+
+ assertPermanentCount(playerA, "Plains", 4);
+ assertGraveyardCount(playerA, "Rest for the Weary", 2);
+ assertLife(playerA, 32); // + 8 from 1 turn + 4 from second turn
+ assertLife(playerB, 20);
+
+ }
+ /**
+ * If you Hive Mind an opponent's Rest for the Weary and redirect its target to yourself when it's not your turn,
+ * the game spits out this message and rolls back to before Rest for the Weary was cast.
+ *
+ */
+ @Test
+ public void testHiveMind() {
+ addCard(Zone.BATTLEFIELD, playerA, "Plains",2);
+
+ // Whenever a player casts an instant or sorcery spell, each other player copies that spell. Each of those players may choose new targets for his or her copy.
+ addCard(Zone.BATTLEFIELD, playerB, "Hive Mind");
+
+ // Instant - {1}{W}
+ // Target player gains 4 life.
+ // Landfall - If you had a land enter the battlefield under your control this turn, that player gains 8 life instead.
+ addCard(Zone.HAND, playerA, "Rest for the Weary",1);
+
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Rest for the Weary");
+
+ setStopAt(1, PhaseStep.BEGIN_COMBAT);
+ execute();
+
+ assertGraveyardCount(playerA, "Rest for the Weary", 1);
+ assertLife(playerA, 24);
+ assertLife(playerB, 24);
+
+ }
+
+ @Test
+ public void testSurrakarMarauder() {
+ // Landfall - Whenever a land enters the battlefield under your control, Surrakar Marauder gains intimidate until end of turn.
+ addCard(Zone.BATTLEFIELD, playerA, "Surrakar Marauder",1);
+ addCard(Zone.HAND, playerA, "Plains");
+
+ playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Plains");
+
+ setStopAt(1, PhaseStep.BEGIN_COMBAT);
+ execute();
+
+ assertPermanentCount(playerA, "Plains", 1);
+
+ assertAbility(playerA, "Surrakar Marauder", IntimidateAbility.getInstance(), true);
+
+ assertLife(playerA, 20);
+ assertLife(playerB, 20);
+
+ }
+
+}
diff --git a/Mage/src/mage/abilities/common/LandfallAbility.java b/Mage/src/mage/abilities/common/LandfallAbility.java
index 974593e5461..db19efb0ffd 100644
--- a/Mage/src/mage/abilities/common/LandfallAbility.java
+++ b/Mage/src/mage/abilities/common/LandfallAbility.java
@@ -34,7 +34,6 @@ import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.Effect;
import mage.game.Game;
import mage.game.events.GameEvent;
-import mage.game.events.GameEvent.EventType;
import mage.game.permanent.Permanent;
/**
@@ -44,10 +43,10 @@ import mage.game.permanent.Permanent;
public class LandfallAbility extends TriggeredAbilityImpl {
public LandfallAbility(Effect effect, boolean optional) {
- super(Zone.BATTLEFIELD, effect, optional);
+ this(Zone.BATTLEFIELD, effect, optional);
}
- public LandfallAbility ( Zone zone, Effect effect, Boolean optional ) {
+ public LandfallAbility (Zone zone, Effect effect, Boolean optional ) {
super(zone, effect, optional);
}
@@ -63,15 +62,12 @@ public class LandfallAbility extends TriggeredAbilityImpl {
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Permanent permanent = game.getPermanent(event.getTargetId());
- if (permanent != null && permanent.getCardType().contains(CardType.LAND) && permanent.getControllerId().equals(this.controllerId)) {
- return true;
- }
- return false;
+ return permanent != null && permanent.getCardType().contains(CardType.LAND) && permanent.getControllerId().equals(this.controllerId);
}
@Override
public String getRule() {
- return "Landfall - Whenever a land enters the battlefield under your control, " + super.getRule();
+ return "Landfall — Whenever a land enters the battlefield under your control, " + super.getRule();
}
@Override
diff --git a/Mage/src/mage/abilities/condition/common/LandfallCondition.java b/Mage/src/mage/abilities/condition/common/LandfallCondition.java
index ecfa892b968..490e2b157c5 100644
--- a/Mage/src/mage/abilities/condition/common/LandfallCondition.java
+++ b/Mage/src/mage/abilities/condition/common/LandfallCondition.java
@@ -3,13 +3,13 @@ package mage.abilities.condition.common;
import mage.abilities.Ability;
import mage.abilities.condition.Condition;
import mage.game.Game;
-import mage.watchers.Watcher;
+import mage.watchers.common.LandfallWatcher;
/**
* @author Loki
*/
public class LandfallCondition implements Condition {
- private static LandfallCondition instance = new LandfallCondition();
+ private final static LandfallCondition instance = new LandfallCondition();
public static LandfallCondition getInstance() {
return instance;
@@ -20,7 +20,7 @@ public class LandfallCondition implements Condition {
@Override
public boolean apply(Game game, Ability source) {
- Watcher watcher = game.getState().getWatchers().get("LandPlayed", source.getControllerId());
- return watcher.conditionMet();
+ LandfallWatcher watcher = (LandfallWatcher) game.getState().getWatchers().get("LandPlayed");
+ return watcher != null && watcher.landPlayed(source.getControllerId());
}
}
diff --git a/Mage/src/mage/watchers/Watcher.java b/Mage/src/mage/watchers/Watcher.java
index 180b7aac839..e9d8520293c 100644
--- a/Mage/src/mage/watchers/Watcher.java
+++ b/Mage/src/mage/watchers/Watcher.java
@@ -92,7 +92,7 @@ public abstract class Watcher implements Serializable {
public boolean conditionMet() {
return condition;
}
-
+
public void reset() {
condition = false;
}
diff --git a/Mage/src/mage/watchers/common/LandfallWatcher.java b/Mage/src/mage/watchers/common/LandfallWatcher.java
index 3a0a659c6e4..f75d4c0d625 100644
--- a/Mage/src/mage/watchers/common/LandfallWatcher.java
+++ b/Mage/src/mage/watchers/common/LandfallWatcher.java
@@ -1,5 +1,8 @@
package mage.watchers.common;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
import mage.constants.CardType;
import mage.constants.WatcherScope;
import mage.game.Game;
@@ -13,12 +16,15 @@ import mage.watchers.Watcher;
*/
public class LandfallWatcher extends Watcher {
+ Set playerPlayedLand = new HashSet<>();
+
public LandfallWatcher() {
- super("LandPlayed", WatcherScope.PLAYER);
+ super("LandPlayed", WatcherScope.GAME);
}
public LandfallWatcher(final LandfallWatcher watcher) {
super(watcher);
+ playerPlayedLand.addAll(playerPlayedLand);
}
@Override
@@ -28,15 +34,21 @@ public class LandfallWatcher extends Watcher {
@Override
public void watch(GameEvent event, Game game) {
- if (condition == true) { //no need to check - condition has already occured
- return;
- }
if (event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD) {
Permanent permanent = game.getPermanent(event.getTargetId());
- if (permanent.getCardType().contains(CardType.LAND) && permanent.getControllerId().equals(this.controllerId)) {
- condition = true;
+ if (permanent.getCardType().contains(CardType.LAND) && !playerPlayedLand.contains(event.getPlayerId())) {
+ playerPlayedLand.add(event.getPlayerId());
}
}
}
+ @Override
+ public void reset() {
+ playerPlayedLand.clear();
+ super.reset();
+ }
+
+ public boolean landPlayed(UUID playerId) {
+ return playerPlayedLand.contains(playerId);
+ }
}