diff --git a/Mage.Sets/src/mage/sets/avacynrestored/AlchemistsRefuge.java b/Mage.Sets/src/mage/sets/avacynrestored/AlchemistsRefuge.java index 3271bbbb649..d39251608a5 100644 --- a/Mage.Sets/src/mage/sets/avacynrestored/AlchemistsRefuge.java +++ b/Mage.Sets/src/mage/sets/avacynrestored/AlchemistsRefuge.java @@ -41,6 +41,12 @@ import mage.cards.CardImpl; import mage.game.Game; import java.util.UUID; +import mage.ObjectColor; +import mage.abilities.effects.common.continious.CastAsThoughItHadFlashEffect; +import mage.filter.common.FilterCreatureCard; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.predicate.mageobject.ColorPredicate; /** * @@ -49,6 +55,11 @@ import java.util.UUID; */ public class AlchemistsRefuge extends CardImpl { + private static final FilterCreatureCard filter = new FilterCreatureCard("nonland cards"); + static { + filter.add(Predicates.not(new CardTypePredicate(CardType.LAND))); + } + public AlchemistsRefuge(UUID ownerId) { super(ownerId, 225, "Alchemist's Refuge", Rarity.RARE, new CardType[]{CardType.LAND}, ""); this.expansionSetCode = "AVR"; @@ -57,7 +68,9 @@ public class AlchemistsRefuge extends CardImpl { this.addAbility(new ColorlessManaAbility()); // {G}{U}, {tap}: You may cast nonland cards this turn as though they had flash. - this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddContinuousEffectToGame(new AlchemistsRefugeEffect()), new CompositeCost(new ManaCostsImpl("{G}{U}"), new TapSourceCost(), "{G}{U}, {T}"))); + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, + new AddContinuousEffectToGame(new CastAsThoughItHadFlashEffect(Duration.EndOfTurn, filter)), + new CompositeCost(new ManaCostsImpl("{G}{U}"), new TapSourceCost(), "{G}{U}, {T}"))); } public AlchemistsRefuge(final AlchemistsRefuge card) { @@ -69,38 +82,3 @@ public class AlchemistsRefuge extends CardImpl { return new AlchemistsRefuge(this); } } - -class AlchemistsRefugeEffect extends AsThoughEffectImpl { - - public AlchemistsRefugeEffect() { - super(AsThoughEffectType.CAST, Duration.EndOfTurn, Outcome.Benefit); - staticText = "You may cast nonland cards this turn as though they had flash"; - } - - public AlchemistsRefugeEffect(final AlchemistsRefugeEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - return true; - } - - @Override - public AlchemistsRefugeEffect copy() { - return new AlchemistsRefugeEffect(this); - } - - @Override - public boolean applies(UUID sourceId, Ability source, Game game) { - Card card = game.getCard(sourceId); - if (card != null) { - if (!card.getCardType().contains(CardType.LAND) && card.getOwnerId().equals(source.getControllerId())) { - // TODO: Check if this also works for cards that gained e.g. flashback from another source. - return card.getSpellAbility().isInUseableZone(game, card, false); - } - } - return false; - } - -} diff --git a/Mage.Sets/src/mage/sets/magic2013/YevaNaturesHerald.java b/Mage.Sets/src/mage/sets/magic2013/YevaNaturesHerald.java index 028fdd32810..4a775da6be9 100644 --- a/Mage.Sets/src/mage/sets/magic2013/YevaNaturesHerald.java +++ b/Mage.Sets/src/mage/sets/magic2013/YevaNaturesHerald.java @@ -28,20 +28,18 @@ package mage.sets.magic2013; import java.util.UUID; -import mage.constants.AsThoughEffectType; +import mage.MageInt; +import mage.ObjectColor; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.continious.CastAsThoughItHadFlashEffect; +import mage.abilities.keyword.FlashAbility; +import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Duration; -import mage.constants.Outcome; import mage.constants.Rarity; import mage.constants.Zone; -import mage.MageInt; -import mage.abilities.Ability; -import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.AsThoughEffectImpl; -import mage.abilities.keyword.FlashAbility; -import mage.cards.Card; -import mage.cards.CardImpl; -import mage.game.Game; +import mage.filter.common.FilterCreatureCard; +import mage.filter.predicate.mageobject.ColorPredicate; /** * @@ -49,6 +47,11 @@ import mage.game.Game; */ public class YevaNaturesHerald extends CardImpl { + private static final FilterCreatureCard filter = new FilterCreatureCard("green creature cards"); + static { + filter.add(new ColorPredicate(ObjectColor.GREEN)); + } + public YevaNaturesHerald(UUID ownerId) { super(ownerId, 197, "Yeva, Nature's Herald", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{2}{G}{G}"); this.expansionSetCode = "M13"; @@ -63,7 +66,7 @@ public class YevaNaturesHerald extends CardImpl { // Flash this.addAbility(FlashAbility.getInstance()); // You may cast green creature cards as though they had flash. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new YevaNaturesHeraldEffect())); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CastAsThoughItHadFlashEffect(Duration.WhileOnBattlefield, filter))); } public YevaNaturesHerald(final YevaNaturesHerald card) { @@ -75,38 +78,3 @@ public class YevaNaturesHerald extends CardImpl { return new YevaNaturesHerald(this); } } - -class YevaNaturesHeraldEffect extends AsThoughEffectImpl { - - public YevaNaturesHeraldEffect() { - super(AsThoughEffectType.CAST, Duration.WhileOnBattlefield, Outcome.Benefit); - staticText = "You may cast green creature cards as though they had flash"; - } - - public YevaNaturesHeraldEffect(final YevaNaturesHeraldEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - return true; - } - - @Override - public YevaNaturesHeraldEffect copy() { - return new YevaNaturesHeraldEffect(this); - } - - @Override - public boolean applies(UUID sourceId, Ability source, Game game) { - Card card = game.getCard(sourceId); - if (card != null) { - if (card.getCardType().contains(CardType.CREATURE) && card.getColor().isGreen() - && card.getOwnerId().equals(source.getControllerId())) { - // TODO: Maybe this check is not enough - return card.getSpellAbility().isInUseableZone(game, card, false); - } - } - return false; - } -} diff --git a/Mage.Sets/src/mage/sets/shardsofalara/QasaliAmbusher.java b/Mage.Sets/src/mage/sets/shardsofalara/QasaliAmbusher.java index 055f2122d20..751151f18b1 100644 --- a/Mage.Sets/src/mage/sets/shardsofalara/QasaliAmbusher.java +++ b/Mage.Sets/src/mage/sets/shardsofalara/QasaliAmbusher.java @@ -28,8 +28,6 @@ package mage.sets.shardsofalara; import java.util.UUID; - -import mage.constants.*; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.ActivatedAbilityImpl; @@ -39,6 +37,11 @@ import mage.abilities.effects.OneShotEffect; import mage.abilities.keyword.ReachAbility; import mage.cards.Card; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.TimingRule; +import mage.constants.Zone; import mage.filter.common.FilterControlledLandPermanent; import mage.filter.predicate.mageobject.SubtypePredicate; import mage.game.Game; @@ -66,7 +69,7 @@ public class QasaliAmbusher extends CardImpl { this.addAbility(ReachAbility.getInstance()); // If a creature is attacking you and you control a Forest and a Plains, you may casbt Qasali Ambusher without paying its mana cost and as though it had flash. this.addAbility(new QasaliAmbusherAbility()); - + } public QasaliAmbusher(final QasaliAmbusher card) { @@ -79,15 +82,16 @@ public class QasaliAmbusher extends CardImpl { } } - class QasaliAmbusherAbility extends ActivatedAbilityImpl { private static final FilterControlledLandPermanent filterPlains = new FilterControlledLandPermanent(); private static final FilterControlledLandPermanent filterForest = new FilterControlledLandPermanent(); + static { filterPlains.add(new SubtypePredicate("Plains")); filterForest.add(new SubtypePredicate("Forest")); } + public QasaliAmbusherAbility() { super(Zone.HAND, new QasaliAmbusherEffect(), new ManaCostsImpl()); this.timing = TimingRule.INSTANT; @@ -105,11 +109,11 @@ class QasaliAmbusherAbility extends ActivatedAbilityImpl @Override public boolean canActivate(UUID playerId, Game game) { - if(super.canActivate(playerId, game)){ - if(game.getBattlefield().getActivePermanents(filterPlains, this.getControllerId(), this.getSourceId(), game).size() > 0 - && game.getBattlefield().getActivePermanents(filterForest, this.getControllerId(), this.getSourceId(), game).size() > 0){ - for(CombatGroup group : game.getCombat().getGroups()){ - if(group.getDefenderId().equals(getControllerId())){ + if (super.canActivate(playerId, game)) { + if (game.getBattlefield().getActivePermanents(filterPlains, this.getControllerId(), this.getSourceId(), game).size() > 0 + && game.getBattlefield().getActivePermanents(filterForest, this.getControllerId(), this.getSourceId(), game).size() > 0) { + for (CombatGroup group : game.getCombat().getGroups()) { + if (group.getDefenderId().equals(getControllerId())) { return true; } } @@ -118,8 +122,6 @@ class QasaliAmbusherAbility extends ActivatedAbilityImpl return false; } - - @Override public String getRule(boolean all) { return this.getRule(); @@ -127,7 +129,7 @@ class QasaliAmbusherAbility extends ActivatedAbilityImpl @Override public String getRule() { - return "If a creature is attacking you and you control a Forest and a Plains, you may casbt Qasali Ambusher without paying its mana cost and as though it had flash"; + return "If a creature is attacking you and you control a Forest and a Plains, you may cast {this} without paying its mana cost and as though it had flash."; } } @@ -154,7 +156,6 @@ class QasaliAmbusherEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { SpellAbility spellAbility = card.getSpellAbility(); - spellAbility.clear(); return controller.cast(spellAbility, game, true); } @@ -162,4 +163,3 @@ class QasaliAmbusherEffect extends OneShotEffect { return false; } } - diff --git a/Mage.Sets/src/mage/sets/theros/ProphetOfKruphix.java b/Mage.Sets/src/mage/sets/theros/ProphetOfKruphix.java index 8d6d2e7efda..08d63c6c25c 100644 --- a/Mage.Sets/src/mage/sets/theros/ProphetOfKruphix.java +++ b/Mage.Sets/src/mage/sets/theros/ProphetOfKruphix.java @@ -35,6 +35,7 @@ import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.AsThoughEffectImpl; import mage.abilities.effects.Effect; import mage.abilities.effects.common.UntapAllControllerEffect; +import mage.abilities.effects.common.continious.CastAsThoughItHadFlashEffect; import mage.cards.Card; import mage.cards.CardImpl; import mage.constants.AsThoughEffectType; @@ -45,6 +46,7 @@ import mage.constants.Rarity; import mage.constants.TargetController; import mage.constants.Zone; import mage.filter.FilterPermanent; +import mage.filter.common.FilterCreatureCard; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.CardTypePredicate; import mage.game.Game; @@ -77,7 +79,7 @@ public class ProphetOfKruphix extends CardImpl { Effect effect = new UntapAllControllerEffect(filter, "Untap all creatures and lands you control"); this.addAbility(new BeginningOfUntapTriggeredAbility(Zone.BATTLEFIELD, effect, TargetController.NOT_YOU, false)); // You may cast creature cards as though they had flash. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ProphetOfKruphixEffect())); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CastAsThoughItHadFlashEffect(Duration.WhileOnBattlefield, new FilterCreatureCard("creature cards")))); } @@ -90,37 +92,3 @@ public class ProphetOfKruphix extends CardImpl { return new ProphetOfKruphix(this); } } - -class ProphetOfKruphixEffect extends AsThoughEffectImpl { - - public ProphetOfKruphixEffect() { - super(AsThoughEffectType.CAST, Duration.WhileOnBattlefield, Outcome.Benefit); - staticText = "You may cast creature cards as though they had flash"; - } - - public ProphetOfKruphixEffect(final ProphetOfKruphixEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - return true; - } - - @Override - public ProphetOfKruphixEffect copy() { - return new ProphetOfKruphixEffect(this); - } - - @Override - public boolean applies(UUID sourceId, Ability source, Game game) { - Card card = game.getCard(sourceId); - if (card != null) { - if (card.getCardType().contains(CardType.CREATURE) - && card.getOwnerId().equals(source.getControllerId())) { - return card.getSpellAbility().isInUseableZone(game, card, false); - } - } - return false; - } -} diff --git a/Mage/src/mage/abilities/effects/common/continious/CastAsThoughItHadFlashEffect.java b/Mage/src/mage/abilities/effects/common/continious/CastAsThoughItHadFlashEffect.java new file mode 100644 index 00000000000..9a41dc99531 --- /dev/null +++ b/Mage/src/mage/abilities/effects/common/continious/CastAsThoughItHadFlashEffect.java @@ -0,0 +1,114 @@ +/* + * Copyright 2011 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 mage.abilities.effects.common.continious; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.AsThoughEffectImpl; +import mage.cards.Card; +import mage.constants.AsThoughEffectType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.filter.FilterCard; +import mage.game.Game; +import mage.players.Player; + +/** + * + * @author LevelX2 + */ + +public class CastAsThoughItHadFlashEffect extends AsThoughEffectImpl { + + private final FilterCard filter; + private final boolean anyPlayer; + + public CastAsThoughItHadFlashEffect(Duration duration, FilterCard filter) { + this(duration, filter, false); + } + + public CastAsThoughItHadFlashEffect(Duration duration, FilterCard filter, boolean anyPlayer) { + super(AsThoughEffectType.CAST, duration, Outcome.Benefit); + this.filter = filter; + this.anyPlayer = anyPlayer; + staticText = setText(); + } + + public CastAsThoughItHadFlashEffect(final CastAsThoughItHadFlashEffect effect) { + super(effect); + this.filter = effect.filter; + this.anyPlayer = effect.anyPlayer; + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public CastAsThoughItHadFlashEffect copy() { + return new CastAsThoughItHadFlashEffect(this); + } + + @Override + public boolean applies(UUID sourceId, Ability source, Game game) { + Card card = game.getCard(sourceId); + if (card != null && filter.match(card, game) && card.getSpellAbility().isInUseableZone(game, card, false)) { + if (anyPlayer) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + return controller.getInRange().contains(card.getOwnerId()); + } + } else { + return card.getOwnerId().equals(source.getControllerId()); + } + } + return false; + } + + private String setText() { + StringBuilder sb = new StringBuilder(); + if (anyPlayer) { + sb.append("Any player"); + } else { + sb.append("You"); + } + sb.append(" may cast "); + sb.append(filter.getMessage()); + if (!duration.toString().isEmpty()) { + if (duration.equals(Duration.EndOfTurn)) { + sb.append(" this turn"); + } else { + sb.append(" "); + sb.append(duration.toString()); + } + } + return sb.append(" as though they had flash").toString(); + } +} diff --git a/Mage/src/mage/constants/Duration.java b/Mage/src/mage/constants/Duration.java index 3fa393e6492..4a94d4482f1 100644 --- a/Mage/src/mage/constants/Duration.java +++ b/Mage/src/mage/constants/Duration.java @@ -14,7 +14,7 @@ public enum Duration { EndOfCombat("until end of combat"), Custom(""); - private String text; + private final String text; Duration(String text) { this.text = text;