From f8f21bd8cefaa7f9f4a88d1ba2947396e77a9ca0 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sat, 30 May 2015 10:14:15 +0200 Subject: [PATCH] * Landfall - Fixed that it also works for Instant and Soceries copied from opponents. Corrected tooltip text formating. --- .../mage/sets/futuresight/RiverOfTears.java | 2 +- .../src/mage/sets/worldwake/Groundswell.java | 58 ++------- .../sets/worldwake/MysteriesOfTheDeep.java | 1 - .../mage/sets/worldwake/RestForTheWeary.java | 1 - .../src/mage/sets/worldwake/SearingBlaze.java | 1 - .../src/mage/sets/worldwake/TombHex.java | 3 +- .../mage/sets/zendikar/SurrakarMarauder.java | 2 + .../abilities/keywords/LandfallTest.java | 115 ++++++++++++++++++ .../abilities/common/LandfallAbility.java | 12 +- .../condition/common/LandfallCondition.java | 8 +- Mage/src/mage/watchers/Watcher.java | 2 +- .../mage/watchers/common/LandfallWatcher.java | 24 +++- 12 files changed, 156 insertions(+), 73 deletions(-) create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/LandfallTest.java 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); + } }