diff --git a/Mage.Sets/src/mage/sets/alarareborn/MeddlingMage.java b/Mage.Sets/src/mage/sets/alarareborn/MeddlingMage.java index b2a3a682f4..c05a1cf39b 100644 --- a/Mage.Sets/src/mage/sets/alarareborn/MeddlingMage.java +++ b/Mage.Sets/src/mage/sets/alarareborn/MeddlingMage.java @@ -28,29 +28,22 @@ package mage.sets.alarareborn; import java.util.UUID; -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.MageObject; import mage.abilities.Ability; import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousRuleModifiyingEffectImpl; -import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.NameACardEffect; import mage.cards.CardImpl; -import mage.cards.repository.CardRepository; -import mage.choices.Choice; -import mage.choices.ChoiceImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; -import mage.game.permanent.Permanent; -import mage.players.Player; -import mage.util.CardUtil; /** * diff --git a/Mage.Sets/src/mage/sets/alarareborn/SpellbreakerBehemoth.java b/Mage.Sets/src/mage/sets/alarareborn/SpellbreakerBehemoth.java index c6773dfb3f..62d61e2c43 100644 --- a/Mage.Sets/src/mage/sets/alarareborn/SpellbreakerBehemoth.java +++ b/Mage.Sets/src/mage/sets/alarareborn/SpellbreakerBehemoth.java @@ -35,8 +35,8 @@ import mage.constants.Rarity; import mage.constants.Zone; import mage.MageInt; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.common.CantCounterControlledEffect; -import mage.abilities.effects.common.CantCounterSourceEffect; +import mage.abilities.effects.common.CantBeCounteredControlledEffect; +import mage.abilities.effects.common.CantBeCounteredSourceEffect; import mage.cards.CardImpl; import mage.filter.Filter; import mage.filter.FilterSpell; @@ -66,8 +66,8 @@ public class SpellbreakerBehemoth extends CardImpl { this.power = new MageInt(5); this.toughness = new MageInt(5); - this.addAbility(new SimpleStaticAbility(Zone.STACK, new CantCounterSourceEffect())); - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantCounterControlledEffect(filter, Duration.WhileOnBattlefield))); + this.addAbility(new SimpleStaticAbility(Zone.STACK, new CantBeCounteredSourceEffect())); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantBeCounteredControlledEffect(filter, Duration.WhileOnBattlefield))); } public SpellbreakerBehemoth(final SpellbreakerBehemoth card) { diff --git a/Mage.Sets/src/mage/sets/betrayersofkamigawa/IsaoEnlightenedBushi.java b/Mage.Sets/src/mage/sets/betrayersofkamigawa/IsaoEnlightenedBushi.java index 149e08b5c3..bbc4609656 100644 --- a/Mage.Sets/src/mage/sets/betrayersofkamigawa/IsaoEnlightenedBushi.java +++ b/Mage.Sets/src/mage/sets/betrayersofkamigawa/IsaoEnlightenedBushi.java @@ -33,7 +33,7 @@ import mage.constants.CardType; import mage.constants.Rarity; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.common.CantCounterAbility; +import mage.abilities.common.CantBeCounteredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.common.RegenerateTargetEffect; @@ -67,7 +67,7 @@ public class IsaoEnlightenedBushi extends CardImpl { this.toughness = new MageInt(1); // Isao, Enlightened Bushi can't be countered. - this.addAbility(new CantCounterAbility()); + this.addAbility(new CantBeCounteredAbility()); this.addAbility(new BushidoAbility(2)); // {2}: Regenerate target Samurai. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new RegenerateTargetEffect(), new GenericManaCost(2)); diff --git a/Mage.Sets/src/mage/sets/bornofthegods/SpiritOfTheLabyrinth.java b/Mage.Sets/src/mage/sets/bornofthegods/SpiritOfTheLabyrinth.java index 6614ba2dc9..8e76586676 100644 --- a/Mage.Sets/src/mage/sets/bornofthegods/SpiritOfTheLabyrinth.java +++ b/Mage.Sets/src/mage/sets/bornofthegods/SpiritOfTheLabyrinth.java @@ -137,13 +137,16 @@ class SpiritOfTheLabyrinthEffect extends ContinuousRuleModifiyingEffectImpl { return true; } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DRAW_CARD; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == GameEvent.EventType.DRAW_CARD) { - SpiritOfTheLabyrinthWatcher watcher = (SpiritOfTheLabyrinthWatcher) game.getState().getWatchers().get("DrewCard"); - if (watcher != null && watcher.hasPlayerDrewCardThisTurn(event.getPlayerId())) { - return true; - } + SpiritOfTheLabyrinthWatcher watcher = (SpiritOfTheLabyrinthWatcher) game.getState().getWatchers().get("DrewCard"); + if (watcher != null && watcher.hasPlayerDrewCardThisTurn(event.getPlayerId())) { + return true; } return false; } diff --git a/Mage.Sets/src/mage/sets/coldsnap/BalduvianRage.java b/Mage.Sets/src/mage/sets/coldsnap/BalduvianRage.java index b4a414ed61..efeeb66713 100644 --- a/Mage.Sets/src/mage/sets/coldsnap/BalduvianRage.java +++ b/Mage.Sets/src/mage/sets/coldsnap/BalduvianRage.java @@ -42,6 +42,7 @@ import mage.target.common.TargetCreaturePermanent; import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; import mage.abilities.common.delayed.AtTheBeginOfNextUpkeepDelayedTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.filter.common.FilterAttackingCreature; /** @@ -52,11 +53,10 @@ public class BalduvianRage extends CardImpl { public BalduvianRage(UUID ownerId) { super(ownerId, 76, "Balduvian Rage", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{X}{R}"); this.expansionSetCode = "CSP"; - this.color.setRed(true); // Target attacking creature gets +X/+0 until end of turn. this.getSpellAbility().addEffect(new BoostTargetEffect(new ManacostVariableValue(), new StaticValue(0), Duration.EndOfTurn)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + this.getSpellAbility().addTarget(new TargetCreaturePermanent(new FilterAttackingCreature())); // Draw a card at the beginning of the next turn's upkeep. this.getSpellAbility().addEffect(new CreateDelayedTriggeredAbilityEffect(new AtTheBeginOfNextUpkeepDelayedTriggeredAbility(new DrawCardSourceControllerEffect(1)),false)); diff --git a/Mage.Sets/src/mage/sets/coldsnap/HaakonStromgaldScourge.java b/Mage.Sets/src/mage/sets/coldsnap/HaakonStromgaldScourge.java new file mode 100644 index 0000000000..a7104b16df --- /dev/null +++ b/Mage.Sets/src/mage/sets/coldsnap/HaakonStromgaldScourge.java @@ -0,0 +1,196 @@ +/* + * 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 mage.sets.coldsnap; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.common.DiesTriggeredAbility; +import mage.abilities.effects.ContinuousRuleModifiyingEffectImpl; +import mage.abilities.effects.AsThoughEffectImpl; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.constants.AsThoughEffectType; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.abilities.effects.common.LoseLifeSourceControllerEffect; + +/** + * + * @author Mainiack11 + */ +public class HaakonStromgaldScourge extends CardImpl { + + public HaakonStromgaldScourge(UUID ownerId) { + super(ownerId, 61, "Haakon, Stromgald Scourge", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{1}{B}{B}"); + this.expansionSetCode = "CSP"; + this.supertype.add("Legendary"); + this.subtype.add("Zombie"); + this.subtype.add("Knight"); + + this.color.setBlack(true); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // You may cast Haakon, Stromgald Scourge from your graveyard, but not from anywhere else. + Ability ability = new SimpleStaticAbility(Zone.ALL, new HaakonStromgaldScourgePlayEffect()); + ability.addEffect(new HaakonStromgaldScourgePlayEffect2()); + this.addAbility(ability); + + // As long as Haakon is on the battlefield, you may play Knight cards from your graveyard. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new HaakonPlayKnightsFromGraveyardEffect())); + + // When Haakon dies, you lose 2 life. + this.addAbility(new DiesTriggeredAbility(new LoseLifeSourceControllerEffect(2))); + + } + + public HaakonStromgaldScourge(final HaakonStromgaldScourge card) { + super(card); + } + + @Override + public HaakonStromgaldScourge copy() { + return new HaakonStromgaldScourge(this); + } + +} + +class HaakonStromgaldScourgePlayEffect extends AsThoughEffectImpl { + + public HaakonStromgaldScourgePlayEffect() { + super(AsThoughEffectType.PLAY_FROM_NON_HAND_ZONE, Duration.EndOfGame, Outcome.Benefit); + staticText = "You may cast {this} from your graveyard"; + } + + public HaakonStromgaldScourgePlayEffect(final HaakonStromgaldScourgePlayEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public HaakonStromgaldScourgePlayEffect copy() { + return new HaakonStromgaldScourgePlayEffect(this); + } + + @Override + public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { + if (objectId.equals(source.getSourceId()) && + affectedControllerId.equals(source.getControllerId())) { + Card card = game.getCard(source.getSourceId()); + if (card != null && game.getState().getZone(source.getSourceId()) == Zone.GRAVEYARD) { + return true; + } + } + return false; + } +} + +class HaakonStromgaldScourgePlayEffect2 extends ContinuousRuleModifiyingEffectImpl { + + public HaakonStromgaldScourgePlayEffect2() { + super(Duration.EndOfGame, Outcome.Detriment); + staticText = ", but not from anywhere else"; + } + + public HaakonStromgaldScourgePlayEffect2 (final HaakonStromgaldScourgePlayEffect2 effect) { + super(effect); + } + + @Override + public HaakonStromgaldScourgePlayEffect2 copy() { + return new HaakonStromgaldScourgePlayEffect2(this); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if(event.getType() == GameEvent.EventType.CAST_SPELL) { + Card card = game.getCard(event.getSourceId()); + if (card != null && card.getId().equals(source.getSourceId())) { + Zone zone = game.getState().getZone(card.getId()); + if (zone != null && (zone != Zone.GRAVEYARD)) { + return true; + } + } + } + return false; + } +} + +class HaakonPlayKnightsFromGraveyardEffect extends AsThoughEffectImpl { + + public HaakonPlayKnightsFromGraveyardEffect () { + super(AsThoughEffectType.PLAY_FROM_NON_HAND_ZONE, Duration.WhileOnBattlefield, Outcome.Benefit); + staticText = "As long as {this} is on the battlefield, you may play Knight cards from your graveyard"; + } + + public HaakonPlayKnightsFromGraveyardEffect(final HaakonPlayKnightsFromGraveyardEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public HaakonPlayKnightsFromGraveyardEffect copy() { + return new HaakonPlayKnightsFromGraveyardEffect(this); + } + + @Override + public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { + if (affectedControllerId.equals(source.getControllerId())) { + Card knightToCast = game.getCard(objectId); + if (knightToCast != null + && knightToCast.hasSubtype("Knight") + && knightToCast.getOwnerId().equals(source.getControllerId()) + && game.getState().getZone(objectId) == Zone.GRAVEYARD) { + return true; + } + } + return false; + } +} + diff --git a/Mage.Sets/src/mage/sets/commander/AkromaAngelOfFury.java b/Mage.Sets/src/mage/sets/commander/AkromaAngelOfFury.java index 5fbae5933d..d1df42ce6c 100644 --- a/Mage.Sets/src/mage/sets/commander/AkromaAngelOfFury.java +++ b/Mage.Sets/src/mage/sets/commander/AkromaAngelOfFury.java @@ -30,7 +30,7 @@ package mage.sets.commander; import java.util.UUID; import mage.MageInt; import mage.ObjectColor; -import mage.abilities.common.CantCounterAbility; +import mage.abilities.common.CantBeCounteredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.common.continious.BoostSourceEffect; @@ -65,12 +65,11 @@ public class AkromaAngelOfFury extends CardImpl { this.supertype.add("Legendary"); this.subtype.add("Angel"); - this.color.setRed(true); this.power = new MageInt(6); this.toughness = new MageInt(6); // Akroma, Angel of Fury can't be countered. - this.addAbility(new CantCounterAbility()); + this.addAbility(new CantBeCounteredAbility()); // Flying this.addAbility(FlyingAbility.getInstance()); // Trample diff --git a/Mage.Sets/src/mage/sets/commander2014/WakeTheDead.java b/Mage.Sets/src/mage/sets/commander2014/WakeTheDead.java index d588f1df4d..5a22ffff0b 100644 --- a/Mage.Sets/src/mage/sets/commander2014/WakeTheDead.java +++ b/Mage.Sets/src/mage/sets/commander2014/WakeTheDead.java @@ -106,9 +106,14 @@ class WakeTheDeadEffect extends ContinuousRuleModifiyingEffectImpl { super(effect); } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.CAST_SPELL; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType().equals(GameEvent.EventType.CAST_SPELL) && event.getSourceId().equals(source.getSourceId())) { + if (event.getSourceId().equals(source.getSourceId())) { if (game.getPhase().getType().equals(TurnPhase.COMBAT)) { return !game.getOpponents(source.getControllerId()).contains(game.getActivePlayerId()); } diff --git a/Mage.Sets/src/mage/sets/conflux/VolcanicFallout.java b/Mage.Sets/src/mage/sets/conflux/VolcanicFallout.java index edc08d563d..9b3dd2fb23 100644 --- a/Mage.Sets/src/mage/sets/conflux/VolcanicFallout.java +++ b/Mage.Sets/src/mage/sets/conflux/VolcanicFallout.java @@ -30,7 +30,7 @@ package mage.sets.conflux; import java.util.UUID; import mage.constants.CardType; import mage.constants.Rarity; -import mage.abilities.common.CantCounterAbility; +import mage.abilities.common.CantBeCounteredAbility; import mage.abilities.effects.common.DamageEverythingEffect; import mage.cards.CardImpl; @@ -47,7 +47,7 @@ public class VolcanicFallout extends CardImpl { this.color.setRed(true); // Volcanic Fallout can't be countered. - this.addAbility(new CantCounterAbility()); + this.addAbility(new CantBeCounteredAbility()); // Volcanic Fallout deals 2 damage to each creature and each player. this.getSpellAbility().addEffect(new DamageEverythingEffect(2)); } diff --git a/Mage.Sets/src/mage/sets/darksteel/LastWord.java b/Mage.Sets/src/mage/sets/darksteel/LastWord.java index d15e2d7559..57a10603b1 100644 --- a/Mage.Sets/src/mage/sets/darksteel/LastWord.java +++ b/Mage.Sets/src/mage/sets/darksteel/LastWord.java @@ -31,7 +31,7 @@ package mage.sets.darksteel; import java.util.UUID; import mage.constants.CardType; import mage.constants.Rarity; -import mage.abilities.common.CantCounterAbility; +import mage.abilities.common.CantBeCounteredAbility; import mage.abilities.effects.common.CounterTargetEffect; import mage.cards.CardImpl; import mage.target.TargetSpell; @@ -46,7 +46,7 @@ public class LastWord extends CardImpl { super(ownerId, 23, "Last Word", Rarity.RARE, new CardType[]{CardType.INSTANT}, "{2}{U}{U}"); this.expansionSetCode = "DST"; this.color.setBlue(true); - this.addAbility(new CantCounterAbility()); + this.addAbility(new CantBeCounteredAbility()); this.getSpellAbility().addEffect(new CounterTargetEffect()); this.getSpellAbility().addTarget(new TargetSpell()); } diff --git a/Mage.Sets/src/mage/sets/dragonsmaze/CouncilOfTheAbsolute.java b/Mage.Sets/src/mage/sets/dragonsmaze/CouncilOfTheAbsolute.java index 4f480c3621..861293bbee 100644 --- a/Mage.Sets/src/mage/sets/dragonsmaze/CouncilOfTheAbsolute.java +++ b/Mage.Sets/src/mage/sets/dragonsmaze/CouncilOfTheAbsolute.java @@ -29,11 +29,6 @@ package mage.sets.dragonsmaze; import java.util.UUID; -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.MageObject; import mage.abilities.Ability; @@ -41,21 +36,20 @@ import mage.abilities.SpellAbility; import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousRuleModifiyingEffectImpl; -import mage.abilities.effects.common.cost.CostModificationEffectImpl; -import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.NameACardEffect; +import mage.abilities.effects.common.cost.CostModificationEffectImpl; import mage.abilities.keyword.FlashbackAbility; import mage.cards.Card; import mage.cards.CardImpl; -import mage.cards.repository.CardRepository; -import mage.choices.Choice; -import mage.choices.ChoiceImpl; +import mage.constants.CardType; import mage.constants.CostModificationType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; -import mage.game.permanent.Permanent; -import mage.players.Player; import mage.util.CardUtil; /** @@ -83,7 +77,6 @@ public class CouncilOfTheAbsolute extends CardImpl { // Spells with the chosen name cost 2 less for you to cast. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CouncilOfTheAbsoluteCostReductionEffect())); - } public CouncilOfTheAbsolute (final CouncilOfTheAbsolute card) { @@ -127,9 +120,14 @@ class CouncilOfTheAbsoluteReplacementEffect extends ContinuousRuleModifiyingEffe return null; } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.CAST_SPELL; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == EventType.CAST_SPELL && game.getOpponents(source.getControllerId()).contains(event.getPlayerId())) { + if (game.getOpponents(source.getControllerId()).contains(event.getPlayerId())) { MageObject object = game.getObject(event.getSourceId()); if (object != null && object.getName().equals(game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY))) { return true; diff --git a/Mage.Sets/src/mage/sets/dragonsmaze/RenderSilent.java b/Mage.Sets/src/mage/sets/dragonsmaze/RenderSilent.java index d78f7383bb..74a0bacd07 100644 --- a/Mage.Sets/src/mage/sets/dragonsmaze/RenderSilent.java +++ b/Mage.Sets/src/mage/sets/dragonsmaze/RenderSilent.java @@ -146,13 +146,16 @@ class RenderSilentEffect extends ContinuousRuleModifiyingEffectImpl { return null; } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.CAST_SPELL; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == GameEvent.EventType.CAST_SPELL ) { - Player player = game.getPlayer(getTargetPointer().getFirst(game, source)); - if (player != null && player.getId().equals(event.getPlayerId())) { - return true; - } + Player player = game.getPlayer(getTargetPointer().getFirst(game, source)); + if (player != null && player.getId().equals(event.getPlayerId())) { + return true; } return false; } diff --git a/Mage.Sets/src/mage/sets/dragonsmaze/Skylasher.java b/Mage.Sets/src/mage/sets/dragonsmaze/Skylasher.java index a9a11beedf..c3a772fd3c 100644 --- a/Mage.Sets/src/mage/sets/dragonsmaze/Skylasher.java +++ b/Mage.Sets/src/mage/sets/dragonsmaze/Skylasher.java @@ -33,7 +33,7 @@ import mage.constants.CardType; import mage.constants.Rarity; import mage.MageInt; import mage.ObjectColor; -import mage.abilities.common.CantCounterAbility; +import mage.abilities.common.CantBeCounteredAbility; import mage.abilities.keyword.FlashAbility; import mage.abilities.keyword.ProtectionAbility; import mage.abilities.keyword.ReachAbility; @@ -65,7 +65,7 @@ public class Skylasher extends CardImpl { // Flash this.addAbility(FlashAbility.getInstance()); // Skylasher can't be countered. - this.addAbility(new CantCounterAbility()); + this.addAbility(new CantBeCounteredAbility()); // Reach, protection from blue this.addAbility(ReachAbility.getInstance()); this.addAbility(new ProtectionAbility(filter)); diff --git a/Mage.Sets/src/mage/sets/eventide/Moonhold.java b/Mage.Sets/src/mage/sets/eventide/Moonhold.java index f2fff80e21..4279bb178e 100644 --- a/Mage.Sets/src/mage/sets/eventide/Moonhold.java +++ b/Mage.Sets/src/mage/sets/eventide/Moonhold.java @@ -110,15 +110,19 @@ class MoonholdEffect extends ContinuousRuleModifiyingEffectImpl { public String getInfoMessage(Ability source, GameEvent event, Game game) { MageObject mageObject = game.getObject(source.getSourceId()); if (mageObject != null) { - return "You can't play land cards this turn (" + mageObject.getLogName() + ")."; + return "you can't play land cards this turn (" + mageObject.getLogName() + ")."; } return null; } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.PLAY_LAND; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == GameEvent.EventType.PLAY_LAND - && event.getPlayerId().equals(source.getFirstTarget())) { + if (event.getPlayerId().equals(source.getFirstTarget())) { return true; } return false; @@ -154,10 +158,14 @@ class MoonholdEffect2 extends ContinuousRuleModifiyingEffectImpl { return null; } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.CAST_SPELL; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == GameEvent.EventType.CAST_SPELL - && event.getPlayerId().equals(source.getFirstTarget())) { + if (event.getPlayerId().equals(source.getFirstTarget())) { Card card = game.getCard(event.getSourceId()); if (card != null && card.getCardType().contains(CardType.CREATURE)) { return true; diff --git a/Mage.Sets/src/mage/sets/fatereforged/Arcbond.java b/Mage.Sets/src/mage/sets/fatereforged/Arcbond.java index fd3badac38..b1b4daae98 100644 --- a/Mage.Sets/src/mage/sets/fatereforged/Arcbond.java +++ b/Mage.Sets/src/mage/sets/fatereforged/Arcbond.java @@ -30,6 +30,7 @@ package mage.sets.fatereforged; import java.util.UUID; import mage.abilities.Ability; import mage.abilities.DelayedTriggeredAbility; +import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; @@ -86,7 +87,7 @@ class ArcbondDelayedTriggeredAbility extends DelayedTriggeredAbility { public boolean checkTrigger(GameEvent event, Game game) { if (event.getType() == GameEvent.EventType.DAMAGED_CREATURE && event.getTargetId().equals(this.getFirstTarget())) { for (Effect effect : this.getEffects()) { - effect.setValue("damage", event.getAmount()); + effect.setValue("damage", event.getAmount()); } return true; } @@ -126,7 +127,7 @@ class ArcbondEffect extends OneShotEffect { if (damage > 0) { FilterPermanent filter = new FilterCreaturePermanent("each other creature"); filter.add(Predicates.not(new PermanentIdPredicate(source.getTargets().getFirstTarget()))); - return new DamageEverythingEffect(damage, filter).apply(game, source); + return new DamageEverythingEffect(new StaticValue(damage), filter, source.getTargets().getFirstTarget()).apply(game, source); } return false; } diff --git a/Mage.Sets/src/mage/sets/fatereforged/HewedStoneRetainers.java b/Mage.Sets/src/mage/sets/fatereforged/HewedStoneRetainers.java index 235cdd2350..e93d63247a 100644 --- a/Mage.Sets/src/mage/sets/fatereforged/HewedStoneRetainers.java +++ b/Mage.Sets/src/mage/sets/fatereforged/HewedStoneRetainers.java @@ -79,9 +79,14 @@ class HewedStoneRetainersEffect extends ContinuousRuleModifiyingEffectImpl { super(effect); } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.CAST_SPELL; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == GameEvent.EventType.CAST_SPELL && event.getSourceId().equals(source.getSourceId())) { + if (event.getSourceId().equals(source.getSourceId())) { CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get("CastSpellLastTurnWatcher"); if (watcher != null && watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(source.getControllerId()) == 0) { return true; diff --git a/Mage.Sets/src/mage/sets/fatereforged/WardscaleDragon.java b/Mage.Sets/src/mage/sets/fatereforged/WardscaleDragon.java index 51b44ea2d5..2ef467bd77 100644 --- a/Mage.Sets/src/mage/sets/fatereforged/WardscaleDragon.java +++ b/Mage.Sets/src/mage/sets/fatereforged/WardscaleDragon.java @@ -96,13 +96,16 @@ class WardscaleDragonRuleEffect extends ContinuousRuleModifiyingEffectImpl { return true; } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.CAST_SPELL; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == GameEvent.EventType.CAST_SPELL ) { - Permanent sourcePermanent = game.getPermanent(source.getSourceId()); - if (sourcePermanent != null && sourcePermanent.isAttacking()) { - return event.getPlayerId() == game.getCombat().getDefendingPlayerId(sourcePermanent.getId(), game); - } + Permanent sourcePermanent = game.getPermanent(source.getSourceId()); + if (sourcePermanent != null && sourcePermanent.isAttacking()) { + return event.getPlayerId() == game.getCombat().getDefendingPlayerId(sourcePermanent.getId(), game); } return false; } diff --git a/Mage.Sets/src/mage/sets/fatereforged/WildSlash.java b/Mage.Sets/src/mage/sets/fatereforged/WildSlash.java index f27ccc2cb5..475556f1bf 100644 --- a/Mage.Sets/src/mage/sets/fatereforged/WildSlash.java +++ b/Mage.Sets/src/mage/sets/fatereforged/WildSlash.java @@ -81,7 +81,7 @@ class DamageCantBePreventedEffect extends ContinuousRuleModifiyingEffectImpl { public DamageCantBePreventedEffect() { super(Duration.EndOfTurn, Outcome.Benefit, false, false); - staticText = "Damage can't be prevented this turn"; + staticText = "damage can't be prevented this turn"; } public DamageCantBePreventedEffect(final DamageCantBePreventedEffect effect) { @@ -98,11 +98,13 @@ class DamageCantBePreventedEffect extends ContinuousRuleModifiyingEffectImpl { return true; } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.PREVENT_DAMAGE; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType().equals(GameEvent.EventType.PREVENT_DAMAGE)) { - return true; - } - return false; + return true; } } diff --git a/Mage.Sets/src/mage/sets/futuresight/VeilstoneAmulet.java b/Mage.Sets/src/mage/sets/futuresight/VeilstoneAmulet.java index 5861cc4a01..b406d81ff7 100644 --- a/Mage.Sets/src/mage/sets/futuresight/VeilstoneAmulet.java +++ b/Mage.Sets/src/mage/sets/futuresight/VeilstoneAmulet.java @@ -28,12 +28,9 @@ package mage.sets.futuresight; import java.util.UUID; - import mage.cards.CardImpl; import mage.constants.Rarity; import mage.constants.CardType; - - import mage.abilities.common.SpellCastControllerTriggeredAbility; import mage.filter.FilterSpell; import mage.abilities.effects.ContinuousRuleModifiyingEffectImpl; @@ -55,10 +52,7 @@ public class VeilstoneAmulet extends CardImpl { this.expansionSetCode = "FUT"; // Whenever you cast a spell, creatures you control can't be the targets of spells or abilities your opponents control this turn. - this.addAbility(new SpellCastControllerTriggeredAbility(new VeilstoneAmuletEffect(), - new FilterSpell(), - false, - "Whenever you cast a spell, creatures you control can't be the targets of spells or abilities your opponents control this turn.")); + this.addAbility(new SpellCastControllerTriggeredAbility(new VeilstoneAmuletEffect(), new FilterSpell("a spell"), false)); } public VeilstoneAmulet(final VeilstoneAmulet card) { @@ -78,6 +72,7 @@ class VeilstoneAmuletEffect extends ContinuousRuleModifiyingEffectImpl { public VeilstoneAmuletEffect() { super(Duration.EndOfTurn, Outcome.Benefit); + staticText = "creatures you control can't be the targets of spells or abilities your opponents control this turn"; } public VeilstoneAmuletEffect(final VeilstoneAmuletEffect effect) { @@ -99,12 +94,9 @@ class VeilstoneAmuletEffect extends ContinuousRuleModifiyingEffectImpl { if (event.getType() == EventType.TARGET) { Permanent permanent = game.getPermanent(event.getTargetId()); if (permanent != null) { - UUID permanentController = permanent.getControllerId(); - UUID abilityController = ability.getControllerId(); - UUID sourceController = event.getPlayerId(); if (permanent.getCardType().contains(CardType.CREATURE) && - permanentController.equals(abilityController) && - game.getPlayer(abilityController).hasOpponent(sourceController, game)) { + permanent.getControllerId().equals(ability.getControllerId()) && + game.getPlayer(ability.getControllerId()).hasOpponent(event.getPlayerId(), game)) { return true; } } diff --git a/Mage.Sets/src/mage/sets/guildpact/InkTreaderNephilim.java b/Mage.Sets/src/mage/sets/guildpact/InkTreaderNephilim.java index 6751f1ddc9..960c5b6a8d 100644 --- a/Mage.Sets/src/mage/sets/guildpact/InkTreaderNephilim.java +++ b/Mage.Sets/src/mage/sets/guildpact/InkTreaderNephilim.java @@ -35,9 +35,7 @@ import mage.constants.CardType; import mage.constants.Rarity; import mage.MageInt; import mage.cards.CardImpl; - import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; @@ -54,8 +52,8 @@ import mage.game.stack.Spell; import java.util.Map; import java.util.List; import mage.target.Target; -import mage.abilities.Modes; import mage.filter.predicate.mageobject.FromSetPredicate; +import mage.players.Player; import mage.target.TargetPermanent; import mage.util.SpellTargetAddress; @@ -68,10 +66,7 @@ public class InkTreaderNephilim extends CardImpl { super(ownerId, 117, "Ink-Treader Nephilim", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{R}{G}{W}{U}"); this.expansionSetCode = "GPT"; this.subtype.add("Nephilim"); - this.color.setRed(true); - this.color.setGreen(true); - this.color.setWhite(true); - this.color.setBlue(true); + this.power = new MageInt(3); this.toughness = new MageInt(3); @@ -117,7 +112,7 @@ class InkTreaderNephilimTriggeredAbility extends TriggeredAbilityImpl { if (event.getType() == GameEvent.EventType.SPELL_CAST) { Spell spell = game.getStack().getSpell(event.getTargetId()); if (spell != null && - spell.getCardType().contains(CardType.INSTANT) || spell.getCardType().contains(CardType.SORCERY)){ + (spell.getCardType().contains(CardType.INSTANT) || spell.getCardType().contains(CardType.SORCERY))){ for (Effect effect : getEffects()) { effect.setValue("TriggeringSpell", spell); } @@ -133,15 +128,11 @@ class InkTreaderNephilimTriggeredAbility extends TriggeredAbilityImpl { if (spell != null) { boolean allTargetsInkTreaderNephilim = true; boolean atLeastOneTargetsInkTreaderNephilim = false; - for (SpellAbility sa: spell.getSpellAbilities()){ - Modes modes = sa.getModes(); - for (UUID mode : modes.getSelectedModes()) { - for (Target targetInstance : modes.get(mode).getTargets()) { - for (UUID target : targetInstance.getTargets()) { - allTargetsInkTreaderNephilim &= target.equals(sourceId); - atLeastOneTargetsInkTreaderNephilim |= target.equals(sourceId); - } - } + for (SpellTargetAddress addr : SpellTargetAddress.walk(spell)) { + Target targetInstance = addr.getTarget(spell); + for (UUID target : targetInstance.getTargets()) { + allTargetsInkTreaderNephilim &= target.equals(sourceId); + atLeastOneTargetsInkTreaderNephilim |= target.equals(sourceId); } } if (allTargetsInkTreaderNephilim && atLeastOneTargetsInkTreaderNephilim) { @@ -153,7 +144,7 @@ class InkTreaderNephilimTriggeredAbility extends TriggeredAbilityImpl { @Override public String getRule() { - return "Whenever a player casts an instant or sorcery spell, if that spell targets only Ink-Treader Nephilim, copy the spell for each other creature that spell could target. Each copy targets a different one of those creatures."; + return "Whenever a player casts an instant or sorcery spell, if that spell targets only {this}, copy the spell for each other creature that spell could target. Each copy targets a different one of those creatures."; } } @@ -167,6 +158,7 @@ class InkTreaderNephilimEffect extends OneShotEffect { public InkTreaderNephilimEffect() { super(Outcome.Copy); + staticText = "copy the spell for each other creature that spell could target. Each copy targets a different one of those creatures"; } public InkTreaderNephilimEffect(final InkTreaderNephilimEffect effect) { @@ -175,13 +167,17 @@ class InkTreaderNephilimEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } Spell spell = (Spell) getValue("TriggeringSpell"); if (spell != null) { Map targetable = new HashMap<>(); - UUID controller = source.getControllerId(); - for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, controller, source.getSourceId(), game)) { + // gather all creatures that can be targeted from the spell to copy + for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, controller.getId(), source.getSourceId(), game)) { Spell copy = spell.copySpell(); - copy.setControllerId(controller); + copy.setControllerId(controller.getId()); copy.setCopiedSpell(true); if (permanent.getId().equals(source.getSourceId())) { continue; // copy only for other creatures @@ -204,28 +200,29 @@ class InkTreaderNephilimEffect extends OneShotEffect { targetable.put(permanent.getId(), copy); } } + // controller while (targetable.size() > 0) { - FilterPermanent filter = new FilterPermanent("creature that spell could target ("+Integer.toString(targetable.size())+" remaining)"); - filter.add(new FromSetPredicate(targetable.keySet())); - TargetPermanent target = new TargetPermanent(0, 1, filter, true); - if (target.possibleTargets(controller, game).size() > 1 - && target.canChoose(source.getSourceId(), controller, game)) { - game.getPlayer(controller).choose(Outcome.Neutral, target, source.getId(), game); + FilterPermanent filterCreatures = new FilterPermanent("creature that spell could target ("+ targetable.size() + " remaining)"); + filterCreatures.add(new FromSetPredicate(targetable.keySet())); + TargetPermanent target = new TargetPermanent(0, 1, filterCreatures, true); + if (target.possibleTargets(controller.getId(), game).size() > 1 + && target.canChoose(source.getSourceId(), controller.getId(), game)) { + controller.choose(Outcome.Neutral, target, source.getId(), game); } - Collection chosen = target.getTargets(); - if (chosen.size() == 0) { - chosen = targetable.keySet(); + Collection choosenIds = target.getTargets(); + if (choosenIds.isEmpty()) { + choosenIds = targetable.keySet(); } List toDelete = new ArrayList<>(); - for (UUID chosenId : chosen) { + for (UUID chosenId : choosenIds) { Spell chosenCopy = targetable.get(chosenId); if (chosenCopy != null) { game.getStack().push(chosenCopy); toDelete.add(chosenId); } } - for (UUID id : toDelete) { - targetable.remove(id); + for (UUID idToDelte : toDelete) { + targetable.remove(idToDelte); } } return true; diff --git a/Mage.Sets/src/mage/sets/guildpact/WreakHavoc.java b/Mage.Sets/src/mage/sets/guildpact/WreakHavoc.java index 718e56db20..8cb7dd07c2 100644 --- a/Mage.Sets/src/mage/sets/guildpact/WreakHavoc.java +++ b/Mage.Sets/src/mage/sets/guildpact/WreakHavoc.java @@ -30,7 +30,7 @@ package mage.sets.guildpact; import java.util.UUID; import mage.constants.CardType; import mage.constants.Rarity; -import mage.abilities.common.CantCounterAbility; +import mage.abilities.common.CantBeCounteredAbility; import mage.abilities.effects.common.DestroyTargetEffect; import mage.cards.CardImpl; import mage.filter.FilterPermanent; @@ -57,7 +57,7 @@ public class WreakHavoc extends CardImpl { this.expansionSetCode = "GPT"; this.color.setRed(true); this.color.setGreen(true); - this.addAbility(new CantCounterAbility()); + this.addAbility(new CantBeCounteredAbility()); this.getSpellAbility().addEffect(new DestroyTargetEffect()); this.getSpellAbility().addTarget(new TargetPermanent(filter)); } diff --git a/Mage.Sets/src/mage/sets/invasion/BlurredMongoose.java b/Mage.Sets/src/mage/sets/invasion/BlurredMongoose.java index 025bc19db6..c36462eaa9 100644 --- a/Mage.Sets/src/mage/sets/invasion/BlurredMongoose.java +++ b/Mage.Sets/src/mage/sets/invasion/BlurredMongoose.java @@ -31,7 +31,7 @@ import java.util.UUID; import mage.constants.CardType; import mage.constants.Rarity; import mage.MageInt; -import mage.abilities.common.CantCounterAbility; +import mage.abilities.common.CantBeCounteredAbility; import mage.abilities.keyword.ShroudAbility; import mage.cards.CardImpl; @@ -51,7 +51,7 @@ public class BlurredMongoose extends CardImpl { this.toughness = new MageInt(1); // Blurred Mongoose can't be countered. - this.addAbility(new CantCounterAbility()); + this.addAbility(new CantBeCounteredAbility()); this.addAbility(ShroudAbility.getInstance()); } diff --git a/Mage.Sets/src/mage/sets/invasion/Obliterate.java b/Mage.Sets/src/mage/sets/invasion/Obliterate.java index 3508b5475b..86fe481c41 100644 --- a/Mage.Sets/src/mage/sets/invasion/Obliterate.java +++ b/Mage.Sets/src/mage/sets/invasion/Obliterate.java @@ -30,7 +30,7 @@ package mage.sets.invasion; import java.util.UUID; import mage.constants.CardType; import mage.constants.Rarity; -import mage.abilities.common.CantCounterAbility; +import mage.abilities.common.CantBeCounteredAbility; import mage.abilities.effects.common.DestroyAllEffect; import mage.cards.CardImpl; import mage.filter.FilterPermanent; @@ -59,7 +59,7 @@ public class Obliterate extends CardImpl { this.color.setRed(true); // Obliterate can't be countered. - this.addAbility(new CantCounterAbility()); + this.addAbility(new CantBeCounteredAbility()); // Destroy all artifacts, creatures, and lands. They can't be regenerated. this.getSpellAbility().addEffect(new DestroyAllEffect(filter)); } diff --git a/Mage.Sets/src/mage/sets/khansoftarkir/PearlLakeAncient.java b/Mage.Sets/src/mage/sets/khansoftarkir/PearlLakeAncient.java index f0933c8568..bd0d7a667c 100644 --- a/Mage.Sets/src/mage/sets/khansoftarkir/PearlLakeAncient.java +++ b/Mage.Sets/src/mage/sets/khansoftarkir/PearlLakeAncient.java @@ -29,7 +29,7 @@ package mage.sets.khansoftarkir; import java.util.UUID; import mage.MageInt; -import mage.abilities.common.CantCounterAbility; +import mage.abilities.common.CantBeCounteredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.ReturnToHandTargetCost; import mage.abilities.effects.common.ReturnToHandSourceEffect; @@ -61,7 +61,7 @@ public class PearlLakeAncient extends CardImpl { this.addAbility(FlashAbility.getInstance()); // Pearl Lake Ancient can't be countered. - this.addAbility(new CantCounterAbility()); + this.addAbility(new CantBeCounteredAbility()); // Prowess this.addAbility(new ProwessAbility()); diff --git a/Mage.Sets/src/mage/sets/khansoftarkir/SurrakDragonclaw.java b/Mage.Sets/src/mage/sets/khansoftarkir/SurrakDragonclaw.java index 3c73555ab8..fcb77af897 100644 --- a/Mage.Sets/src/mage/sets/khansoftarkir/SurrakDragonclaw.java +++ b/Mage.Sets/src/mage/sets/khansoftarkir/SurrakDragonclaw.java @@ -29,9 +29,9 @@ package mage.sets.khansoftarkir; import java.util.UUID; import mage.MageInt; -import mage.abilities.common.CantCounterAbility; +import mage.abilities.common.CantBeCounteredAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.common.CantCounterControlledEffect; +import mage.abilities.effects.common.CantBeCounteredControlledEffect; import mage.abilities.effects.common.continious.GainAbilityControlledEffect; import mage.abilities.keyword.FlashAbility; import mage.abilities.keyword.TrampleAbility; @@ -74,10 +74,10 @@ public class SurrakDragonclaw extends CardImpl { this.addAbility(FlashAbility.getInstance()); // Surrak Dragonclaw can't be countered. - this.addAbility(new CantCounterAbility()); + this.addAbility(new CantBeCounteredAbility()); // Creature spells you control can't be countered. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantCounterControlledEffect(filterTarget, null, Duration.WhileOnBattlefield))); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantBeCounteredControlledEffect(filterTarget, null, Duration.WhileOnBattlefield))); // Other creatures you control have trample. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, diff --git a/Mage.Sets/src/mage/sets/legions/RootSliver.java b/Mage.Sets/src/mage/sets/legions/RootSliver.java index 266b262a54..1291064b61 100644 --- a/Mage.Sets/src/mage/sets/legions/RootSliver.java +++ b/Mage.Sets/src/mage/sets/legions/RootSliver.java @@ -31,8 +31,8 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.common.CantCounterControlledEffect; -import mage.abilities.effects.common.CantCounterSourceEffect; +import mage.abilities.effects.common.CantBeCounteredControlledEffect; +import mage.abilities.effects.common.CantBeCounteredSourceEffect; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Duration; @@ -65,9 +65,9 @@ public class RootSliver extends CardImpl { this.toughness = new MageInt(2); // Root Sliver can't be countered. - this.addAbility(new SimpleStaticAbility(Zone.STACK, new CantCounterSourceEffect())); + this.addAbility(new SimpleStaticAbility(Zone.STACK, new CantBeCounteredSourceEffect())); // Sliver spells can't be countered by spells or abilities. - this.addAbility(new SimpleStaticAbility(Zone.STACK, new CantCounterControlledEffect(filter, new FilterStackObject(), Duration.WhileOnBattlefield))); + this.addAbility(new SimpleStaticAbility(Zone.STACK, new CantBeCounteredControlledEffect(filter, new FilterStackObject(), Duration.WhileOnBattlefield))); } diff --git a/Mage.Sets/src/mage/sets/magic2010/GreatSableStag.java b/Mage.Sets/src/mage/sets/magic2010/GreatSableStag.java index 2cc418e583..a7952ffcae 100644 --- a/Mage.Sets/src/mage/sets/magic2010/GreatSableStag.java +++ b/Mage.Sets/src/mage/sets/magic2010/GreatSableStag.java @@ -35,7 +35,7 @@ import mage.constants.Zone; import mage.MageInt; import mage.ObjectColor; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.common.CantCounterSourceEffect; +import mage.abilities.effects.common.CantBeCounteredSourceEffect; import mage.abilities.keyword.ProtectionAbility; import mage.cards.CardImpl; import mage.filter.FilterCard; @@ -64,7 +64,7 @@ public class GreatSableStag extends CardImpl { this.addAbility(new ProtectionAbility(filter1)); this.addAbility(new ProtectionAbility(filter2)); - this.addAbility(new SimpleStaticAbility(Zone.STACK, new CantCounterSourceEffect())); + this.addAbility(new SimpleStaticAbility(Zone.STACK, new CantBeCounteredSourceEffect())); } public GreatSableStag(final GreatSableStag card) { diff --git a/Mage.Sets/src/mage/sets/magic2011/AngelicArbiter.java b/Mage.Sets/src/mage/sets/magic2011/AngelicArbiter.java index 96690bbdbb..735e1ca769 100644 --- a/Mage.Sets/src/mage/sets/magic2011/AngelicArbiter.java +++ b/Mage.Sets/src/mage/sets/magic2011/AngelicArbiter.java @@ -182,9 +182,14 @@ class AngelicArbiterEffect2 extends ContinuousRuleModifiyingEffectImpl { return true; } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.CAST_SPELL; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == EventType.CAST_SPELL && game.getActivePlayerId().equals(event.getPlayerId()) && game.getOpponents(source.getControllerId()).contains(event.getPlayerId())) { + if (game.getActivePlayerId().equals(event.getPlayerId()) && game.getOpponents(source.getControllerId()).contains(event.getPlayerId())) { AngelicArbiterWatcher2 watcher = (AngelicArbiterWatcher2) game.getState().getWatchers().get("PlayerAttacked"); if (watcher != null && watcher.hasPlayerAttackedThisTurn(event.getPlayerId())) { return true; diff --git a/Mage.Sets/src/mage/sets/magic2011/AutumnsVeil.java b/Mage.Sets/src/mage/sets/magic2011/AutumnsVeil.java index 7f61bcf9ec..ce914b9f8c 100644 --- a/Mage.Sets/src/mage/sets/magic2011/AutumnsVeil.java +++ b/Mage.Sets/src/mage/sets/magic2011/AutumnsVeil.java @@ -33,7 +33,7 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Rarity; import mage.ObjectColor; -import mage.abilities.effects.common.CantCounterControlledEffect; +import mage.abilities.effects.common.CantBeCounteredControlledEffect; import mage.abilities.effects.common.CantBeTargetedAllEffect; import mage.cards.CardImpl; import mage.filter.FilterSpell; @@ -62,7 +62,7 @@ public class AutumnsVeil extends CardImpl { this.expansionSetCode = "M11"; this.color.setGreen(true); // Spells you control can't be countered by blue or black spells this turn - this.getSpellAbility().addEffect(new CantCounterControlledEffect(filterTarget1, filterSource, Duration.EndOfTurn)); + this.getSpellAbility().addEffect(new CantBeCounteredControlledEffect(filterTarget1, filterSource, Duration.EndOfTurn)); // and creatures you control can't be the targets of blue or black spells this turn. this.getSpellAbility().addEffect(new CantBeTargetedAllEffect(filterTarget2, filterSource, Duration.EndOfTurn)); } diff --git a/Mage.Sets/src/mage/sets/magic2011/Combust.java b/Mage.Sets/src/mage/sets/magic2011/Combust.java index 0331377358..434c4320d6 100644 --- a/Mage.Sets/src/mage/sets/magic2011/Combust.java +++ b/Mage.Sets/src/mage/sets/magic2011/Combust.java @@ -34,7 +34,7 @@ import mage.constants.Rarity; import mage.constants.Zone; import mage.ObjectColor; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.common.CantCounterSourceEffect; +import mage.abilities.effects.common.CantBeCounteredSourceEffect; import mage.abilities.effects.common.DamageTargetEffect; import mage.cards.CardImpl; import mage.filter.common.FilterCreaturePermanent; @@ -62,7 +62,7 @@ public class Combust extends CardImpl { this.color.setRed(true); this.getSpellAbility().addEffect(new DamageTargetEffect(5, false)); this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); - this.addAbility(new SimpleStaticAbility(Zone.STACK, new CantCounterSourceEffect())); + this.addAbility(new SimpleStaticAbility(Zone.STACK, new CantBeCounteredSourceEffect())); } public Combust(final Combust card) { diff --git a/Mage.Sets/src/mage/sets/magic2011/GaeasRevenge.java b/Mage.Sets/src/mage/sets/magic2011/GaeasRevenge.java index bbe3a25a37..73adc0a825 100644 --- a/Mage.Sets/src/mage/sets/magic2011/GaeasRevenge.java +++ b/Mage.Sets/src/mage/sets/magic2011/GaeasRevenge.java @@ -36,7 +36,7 @@ import mage.constants.Zone; import mage.MageInt; import mage.ObjectColor; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.common.CantCounterSourceEffect; +import mage.abilities.effects.common.CantBeCounteredSourceEffect; import mage.abilities.effects.common.CantBeTargetedSourceEffect; import mage.abilities.keyword.HasteAbility; import mage.cards.CardImpl; @@ -64,7 +64,7 @@ public class GaeasRevenge extends CardImpl { this.power = new MageInt(8); this.toughness = new MageInt(5); - this.addAbility(new SimpleStaticAbility(Zone.STACK, new CantCounterSourceEffect())); + this.addAbility(new SimpleStaticAbility(Zone.STACK, new CantBeCounteredSourceEffect())); this.addAbility(HasteAbility.getInstance()); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantBeTargetedSourceEffect(filter, Duration.WhileOnBattlefield))); diff --git a/Mage.Sets/src/mage/sets/magic2014/SavageSummoning.java b/Mage.Sets/src/mage/sets/magic2014/SavageSummoning.java index cc050a6b8b..b80573d13c 100644 --- a/Mage.Sets/src/mage/sets/magic2014/SavageSummoning.java +++ b/Mage.Sets/src/mage/sets/magic2014/SavageSummoning.java @@ -35,7 +35,7 @@ import java.util.Set; import java.util.UUID; import mage.MageObject; import mage.abilities.Ability; -import mage.abilities.common.CantCounterAbility; +import mage.abilities.common.CantBeCounteredAbility; import mage.abilities.effects.AsThoughEffectImpl; import mage.abilities.effects.ContinuousRuleModifiyingEffectImpl; import mage.abilities.effects.ReplacementEffectImpl; @@ -67,7 +67,7 @@ public class SavageSummoning extends CardImpl { this.color.setGreen(true); // Savage Summoning can't be countered. - Ability ability = new CantCounterAbility(); + Ability ability = new CantBeCounteredAbility(); ability.setRuleAtTheTop(true); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/sets/magic2015/AggressiveMining.java b/Mage.Sets/src/mage/sets/magic2015/AggressiveMining.java index 3c909a8378..71c982f9c2 100644 --- a/Mage.Sets/src/mage/sets/magic2015/AggressiveMining.java +++ b/Mage.Sets/src/mage/sets/magic2015/AggressiveMining.java @@ -97,9 +97,14 @@ class AggressiveMiningEffect extends ContinuousRuleModifiyingEffectImpl { return true; } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.PLAY_LAND; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - return event.getType().equals(GameEvent.EventType.PLAY_LAND) && event.getPlayerId().equals(source.getControllerId()); + return event.getPlayerId().equals(source.getControllerId()); } } diff --git a/Mage.Sets/src/mage/sets/magic2015/HushwingGryff.java b/Mage.Sets/src/mage/sets/magic2015/HushwingGryff.java index 6ec1eb2247..d369e393d8 100644 --- a/Mage.Sets/src/mage/sets/magic2015/HushwingGryff.java +++ b/Mage.Sets/src/mage/sets/magic2015/HushwingGryff.java @@ -99,17 +99,20 @@ class HushwingGryffEffect extends ContinuousRuleModifiyingEffectImpl { } return null; } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD; + } @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD) { - Permanent permanent = ((EntersTheBattlefieldEvent)event).getTarget(); - if (permanent != null && permanent.getCardType().contains(CardType.CREATURE)) { - // Because replacement events have to be executed - // call replaceEvent here without calling the triggering event after - game.getContinuousEffects().replaceEvent(event, game); - return true; - } + Permanent permanent = ((EntersTheBattlefieldEvent)event).getTarget(); + if (permanent != null && permanent.getCardType().contains(CardType.CREATURE)) { + // Because replacement events have to be executed + // call replaceEvent here without calling the triggering event after + game.getContinuousEffects().replaceEvent(event, game); + return true; } return false; } diff --git a/Mage.Sets/src/mage/sets/mirrodinbesieged/ThrunTheLastTroll.java b/Mage.Sets/src/mage/sets/mirrodinbesieged/ThrunTheLastTroll.java index c0899bf905..fe92b131b4 100644 --- a/Mage.Sets/src/mage/sets/mirrodinbesieged/ThrunTheLastTroll.java +++ b/Mage.Sets/src/mage/sets/mirrodinbesieged/ThrunTheLastTroll.java @@ -36,7 +36,7 @@ import mage.MageInt; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.common.CantCounterSourceEffect; +import mage.abilities.effects.common.CantBeCounteredSourceEffect; import mage.abilities.effects.common.RegenerateSourceEffect; import mage.abilities.keyword.HexproofAbility; import mage.cards.CardImpl; @@ -58,7 +58,7 @@ public class ThrunTheLastTroll extends CardImpl { this.power = new MageInt(4); this.toughness = new MageInt(4); - this.addAbility(new SimpleStaticAbility(Zone.ALL, new CantCounterSourceEffect())); + this.addAbility(new SimpleStaticAbility(Zone.ALL, new CantBeCounteredSourceEffect())); this.addAbility(HexproofAbility.getInstance()); this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new RegenerateSourceEffect(), new ManaCostsImpl("{1}{G}"))); } diff --git a/Mage.Sets/src/mage/sets/odyssey/CeaseFire.java b/Mage.Sets/src/mage/sets/odyssey/CeaseFire.java index e0ac8ec6d3..544ef24b03 100644 --- a/Mage.Sets/src/mage/sets/odyssey/CeaseFire.java +++ b/Mage.Sets/src/mage/sets/odyssey/CeaseFire.java @@ -110,9 +110,14 @@ class CeaseFireEffect extends ContinuousRuleModifiyingEffectImpl { return null; } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.CAST_SPELL; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == GameEvent.EventType.CAST_SPELL && event.getPlayerId().equals(source.getFirstTarget())) { + if (event.getPlayerId().equals(source.getFirstTarget())) { MageObject object = game.getObject(event.getSourceId()); if (filter.match((Spell) object, game)) { return true; diff --git a/Mage.Sets/src/mage/sets/ravnika/BreathOfFury.java b/Mage.Sets/src/mage/sets/ravnika/BreathOfFury.java index 5d493b9e82..9a77b764fc 100644 --- a/Mage.Sets/src/mage/sets/ravnika/BreathOfFury.java +++ b/Mage.Sets/src/mage/sets/ravnika/BreathOfFury.java @@ -28,18 +28,15 @@ package mage.sets.ravnika; import java.util.UUID; - import mage.cards.CardImpl; import mage.constants.Rarity; import mage.constants.CardType; - import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.abilities.effects.common.AttachEffect; import mage.constants.Outcome; import mage.abilities.Ability; import mage.abilities.keyword.EnchantAbility; - import mage.abilities.TriggeredAbilityImpl; import mage.constants.Zone; import mage.game.events.GameEvent; @@ -47,8 +44,6 @@ import mage.game.Game; import mage.game.events.DamagedPlayerEvent; import mage.abilities.effects.OneShotEffect; import mage.game.permanent.Permanent; -import mage.abilities.effects.Effect; -import mage.target.targetpointer.FixedTarget; import mage.players.Player; import mage.target.Target; import mage.filter.common.FilterControlledCreaturePermanent; @@ -66,8 +61,6 @@ public class BreathOfFury extends CardImpl { this.expansionSetCode = "RAV"; this.subtype.add("Aura"); - this.color.setRed(true); - // Enchant creature you control TargetPermanent auraTarget = new TargetControlledCreaturePermanent(); this.getSpellAbility().addTarget(auraTarget); @@ -107,12 +100,11 @@ class BreathOfFuryAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { if (event instanceof DamagedPlayerEvent) { - DamagedPlayerEvent damageEvent = (DamagedPlayerEvent)event; - Permanent p = game.getPermanent(event.getSourceId()); - if (damageEvent.isCombatDamage() && p != null && p.getAttachments().contains(this.getSourceId())) { - for (Effect effect : getEffects()) { - effect.setTargetPointer(new FixedTarget(p.getId())); - } + DamagedPlayerEvent damageEvent = (DamagedPlayerEvent)event; + Permanent enchantment = game.getPermanent(getSourceId()); + if (damageEvent.isCombatDamage() && + enchantment != null && + enchantment.getAttachedTo().equals(event.getSourceId())) { return true; } } @@ -121,7 +113,7 @@ class BreathOfFuryAbility extends TriggeredAbilityImpl { @Override public String getRule() { - return "When enchanted creature deals combat damage to a player, sacrifice it and attach Breath of Fury to a creature you control. If you do, untap all creatures you control and after this phase, there is an additional combat phase."; + return "When enchanted creature deals combat damage to a player, " + super.getRule(); } } @@ -129,7 +121,7 @@ class BreathOfFuryEffect extends OneShotEffect { public BreathOfFuryEffect() { super(Outcome.Benefit); - staticText = "Sacrifice enchanted creature and attach Breath of Fury to a creature you control. If you do, untap all creatures you control and after this phase, there is an additional combat phase."; + staticText = "sacrifice enchanted creature and attach {this} to a creature you control. If you do, untap all creatures you control and after this phase, there is an additional combat phase."; } public BreathOfFuryEffect(final BreathOfFuryEffect effect) { @@ -143,52 +135,37 @@ class BreathOfFuryEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source){ - Permanent enchantedCreature = game.getPermanent(targetPointer.getFirst(game, source)); Permanent enchantment = game.getPermanent(source.getSourceId()); + if (enchantment == null) { + return false; + } + Permanent enchantedCreature = game.getPermanent(enchantment.getAttachedTo()); Player controller = game.getPlayer(source.getControllerId()); - Target target = new TargetControlledCreaturePermanent(new FilterCanBeEnchantedControlledCreaturePermanent(enchantment)); + FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("creature you control that could be enchanted by " + enchantment.getName()); + filter.add(new CanBeEnchantedPredicate(enchantment)); + Target target = new TargetControlledCreaturePermanent(filter); target.setNotTarget(true); - if (enchantedCreature != null && - enchantedCreature.sacrifice(source.getSourceId(), game) && - enchantment != null && - controller != null && - target.canChoose(source.getSourceId(), source.getControllerId(), game)) { - controller.choose(outcome, target, source.getId(), game); + // It's important to check that the creature was successfully sacrificed here. Effects that prevent sacrifice will also prevent Breath of Fury's effect from working. + // Commanders going to the command zone and Rest in Peace style replacement effects don't make Permanent.sacrifice return false. + if (enchantedCreature != null && controller != null + && enchantedCreature.sacrifice(source.getSourceId(), game) + && target.canChoose(source.getSourceId(), source.getControllerId(), game)) { + controller.choose(outcome, target, source.getSourceId(), game); Permanent newCreature = game.getPermanent(target.getFirstTarget()); if (newCreature != null && newCreature.addAttachment(enchantment.getId(), game)) { - for (Permanent permanent : game.getBattlefield().getAllActivePermanents(new FilterControlledCreaturePermanent(), - controller.getId(), game)) { + for (Permanent permanent : game.getBattlefield().getAllActivePermanents(new FilterControlledCreaturePermanent(), controller.getId(), game)) { permanent.untap(game); } + game.getState().getTurnMods().add(new TurnMod(source.getControllerId(), TurnPhase.COMBAT, null, false)); - return true; } + return true; } return false; } } - - -class FilterCanBeEnchantedControlledCreaturePermanent extends FilterControlledCreaturePermanent { - - public FilterCanBeEnchantedControlledCreaturePermanent(final FilterCanBeEnchantedControlledCreaturePermanent filter) { - super(filter); - } - - public FilterCanBeEnchantedControlledCreaturePermanent(MageObject auraEnchantment) { - super("creature you control that could be enchanted by " + auraEnchantment.getName()); - this.add(new CanBeEnchantedPredicate(auraEnchantment)); - } - - @Override - public FilterCanBeEnchantedControlledCreaturePermanent copy() { - return new FilterCanBeEnchantedControlledCreaturePermanent(this); - } -} - - class CanBeEnchantedPredicate implements Predicate { private final MageObject auraEnchantment; diff --git a/Mage.Sets/src/mage/sets/ravnika/RallyTheRighteous.java b/Mage.Sets/src/mage/sets/ravnika/RallyTheRighteous.java index b0c148e0f2..0773e7f478 100644 --- a/Mage.Sets/src/mage/sets/ravnika/RallyTheRighteous.java +++ b/Mage.Sets/src/mage/sets/ravnika/RallyTheRighteous.java @@ -29,7 +29,7 @@ package mage.sets.ravnika; import java.util.UUID; - +import mage.MageObjectReference; import mage.constants.CardType; import mage.constants.Rarity; import mage.constants.Outcome; @@ -55,8 +55,6 @@ public class RallyTheRighteous extends CardImpl { public RallyTheRighteous(UUID ownerId) { super(ownerId, 222, "Rally the Righteous", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{1}{R}{W}"); this.expansionSetCode = "RAV"; - this.color.setRed(true); - this.color.setWhite(true); // Radiance — Untap target creature and each other creature that shares a color with it. Those creatures get +2/+0 until end of turn. this.getSpellAbility().addTarget(new TargetCreaturePermanent()); @@ -79,7 +77,7 @@ class RallyTheRighteousUntapEffect extends OneShotEffect { public RallyTheRighteousUntapEffect() { super(Outcome.Untap); - staticText = "Radiance — Untap target creature and each other creature that shares a color with it."; + staticText = "Radiance — Untap target creature and each other creature that shares a color with it"; } public RallyTheRighteousUntapEffect(final RallyTheRighteousUntapEffect effect) { @@ -93,13 +91,13 @@ class RallyTheRighteousUntapEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Permanent target = game.getPermanent(targetPointer.getFirst(game, source)); + Permanent target = game.getPermanent(getTargetPointer().getFirst(game, source)); if (target != null) { ObjectColor color = target.getColor(); target.untap(game); - for (Permanent p : game.getBattlefield().getActivePermanents(new FilterCreaturePermanent(), source.getControllerId(), game)) { - if (p.getColor().shares(color) && !p.getId().equals(target.getId())) { - p.untap(game); + for (Permanent permanent : game.getBattlefield().getActivePermanents(new FilterCreaturePermanent(), source.getControllerId(), source.getSourceId(), game)) { + if (permanent.getColor().shares(color) && !permanent.getId().equals(target.getId())) { + permanent.untap(game); } } return true; @@ -113,7 +111,7 @@ class RallyTheRighteousBoostEffect extends ContinuousEffectImpl { public RallyTheRighteousBoostEffect() { super(Duration.EndOfTurn, Layer.PTChangingEffects_7, SubLayer.ModifyPT_7c, Outcome.BoostCreature); - staticText = "Radiance — Target creature and each other creature that shares a color with it get +2/+0 until end of turn."; + staticText = "Those creatures get +2/+0 until end of turn"; } public RallyTheRighteousBoostEffect(final RallyTheRighteousBoostEffect effect) { @@ -121,19 +119,30 @@ class RallyTheRighteousBoostEffect extends ContinuousEffectImpl { } @Override - public boolean apply(Game game, Ability source) { - Permanent target = game.getPermanent(targetPointer.getFirst(game, source)); + public void init(Ability source, Game game) { + super.init(source, game); + Permanent target = game.getPermanent(getTargetPointer().getFirst(game, source)); if (target != null) { + affectedObjectList.add(new MageObjectReference(target)); ObjectColor color = target.getColor(); target.addPower(2); - for (Permanent p : game.getBattlefield().getActivePermanents(new FilterCreaturePermanent(), source.getControllerId(), game)) { - if (p.getColor().shares(color) && !p.getId().equals(target.getId())) { - p.addPower(2); + for (Permanent permanent : game.getBattlefield().getActivePermanents(new FilterCreaturePermanent(), source.getControllerId(), source.getSourceId(), game)) { + if (!permanent.getId().equals(target.getId()) && permanent.getColor().shares(color)) { + affectedObjectList.add(new MageObjectReference(permanent)); } } - return true; + } + } + + @Override + public boolean apply(Game game, Ability source) { + for(MageObjectReference mageObjectReference :affectedObjectList) { + Permanent permanent = mageObjectReference.getPermanent(game); + if (permanent != null) { + permanent.addPower(2); + } } - return false; + return true; } @Override diff --git a/Mage.Sets/src/mage/sets/returntoravnica/AbruptDecay.java b/Mage.Sets/src/mage/sets/returntoravnica/AbruptDecay.java index 018cd76e3f..5fda69b454 100644 --- a/Mage.Sets/src/mage/sets/returntoravnica/AbruptDecay.java +++ b/Mage.Sets/src/mage/sets/returntoravnica/AbruptDecay.java @@ -35,7 +35,7 @@ import mage.constants.Zone; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.Effect; -import mage.abilities.effects.common.CantCounterSourceEffect; +import mage.abilities.effects.common.CantBeCounteredSourceEffect; import mage.abilities.effects.common.DestroyTargetEffect; import mage.cards.CardImpl; import mage.filter.Filter; @@ -62,7 +62,7 @@ public class AbruptDecay extends CardImpl { this.color.setBlack(true); // Abrupt Decay can't be countered by spells or abilities. - Effect effect = new CantCounterSourceEffect(); + Effect effect = new CantBeCounteredSourceEffect(); effect.setText("{this} can't be countered by spells or abilities"); Ability ability = new SimpleStaticAbility(Zone.STACK,effect); ability.setRuleAtTheTop(true); diff --git a/Mage.Sets/src/mage/sets/returntoravnica/Counterflux.java b/Mage.Sets/src/mage/sets/returntoravnica/Counterflux.java index 7082d893f9..a0e0597d6a 100644 --- a/Mage.Sets/src/mage/sets/returntoravnica/Counterflux.java +++ b/Mage.Sets/src/mage/sets/returntoravnica/Counterflux.java @@ -38,7 +38,7 @@ import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.CantCounterSourceEffect; +import mage.abilities.effects.common.CantBeCounteredSourceEffect; import mage.abilities.effects.common.CounterTargetEffect; import mage.abilities.keyword.OverloadAbility; import mage.cards.CardImpl; @@ -73,7 +73,7 @@ public class Counterflux extends CardImpl { this.color.setRed(true); // Counterflux can't be countered by spells or abilities. - Effect effect = new CantCounterSourceEffect(); + Effect effect = new CantBeCounteredSourceEffect(); effect.setText("{this} can't be countered by spells or abilities"); Ability ability = new SimpleStaticAbility(Zone.STACK,effect); ability.setRuleAtTheTop(true); diff --git a/Mage.Sets/src/mage/sets/returntoravnica/LoxodonSmiter.java b/Mage.Sets/src/mage/sets/returntoravnica/LoxodonSmiter.java index 802dd72d4b..87e3eb2d8d 100644 --- a/Mage.Sets/src/mage/sets/returntoravnica/LoxodonSmiter.java +++ b/Mage.Sets/src/mage/sets/returntoravnica/LoxodonSmiter.java @@ -30,7 +30,7 @@ package mage.sets.returntoravnica; import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.common.CantCounterAbility; +import mage.abilities.common.CantBeCounteredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ReplacementEffectImpl; import mage.cards.Card; @@ -64,7 +64,7 @@ public class LoxodonSmiter extends CardImpl { this.toughness = new MageInt(4); // Loxodon Smiter can't be countered. - this.addAbility(new CantCounterAbility()); + this.addAbility(new CantBeCounteredAbility()); // If a spell or ability an opponent controls causes you to discard Loxodon Smiter, put it onto the battlefield instead of putting it into your graveyard. this.addAbility(new SimpleStaticAbility(Zone.HAND, new LoxodonSmiterEffect())); diff --git a/Mage.Sets/src/mage/sets/returntoravnica/SlaughterGames.java b/Mage.Sets/src/mage/sets/returntoravnica/SlaughterGames.java index ec7f2dd119..66ef17155c 100644 --- a/Mage.Sets/src/mage/sets/returntoravnica/SlaughterGames.java +++ b/Mage.Sets/src/mage/sets/returntoravnica/SlaughterGames.java @@ -36,7 +36,7 @@ import mage.abilities.Ability; import mage.abilities.Mode; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.Effect; -import mage.abilities.effects.common.CantCounterSourceEffect; +import mage.abilities.effects.common.CantBeCounteredSourceEffect; import mage.abilities.effects.common.search.SearchTargetGraveyardHandLibraryForCardNameAndExileEffect; import mage.cards.Card; import mage.cards.CardImpl; @@ -62,7 +62,7 @@ public class SlaughterGames extends CardImpl { this.color.setRed(true); // Slaughter Games can't be countered by spells or abilities. - Effect effect = new CantCounterSourceEffect(); + Effect effect = new CantBeCounteredSourceEffect(); effect.setText("{this} can't be countered by spells or abilities"); Ability ability = new SimpleStaticAbility(Zone.STACK,effect); ability.setRuleAtTheTop(true); diff --git a/Mage.Sets/src/mage/sets/returntoravnica/SupremeVerdict.java b/Mage.Sets/src/mage/sets/returntoravnica/SupremeVerdict.java index e21a64d9b9..4e3d3dab2a 100644 --- a/Mage.Sets/src/mage/sets/returntoravnica/SupremeVerdict.java +++ b/Mage.Sets/src/mage/sets/returntoravnica/SupremeVerdict.java @@ -30,12 +30,12 @@ package mage.sets.returntoravnica; import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.common.CantCounterAbility; +import mage.abilities.common.CantBeCounteredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.Effect; import mage.constants.CardType; import mage.constants.Rarity; -import mage.abilities.effects.common.CantCounterSourceEffect; +import mage.abilities.effects.common.CantBeCounteredSourceEffect; import mage.abilities.effects.common.DestroyAllEffect; import mage.cards.CardImpl; import mage.constants.Zone; @@ -55,7 +55,7 @@ public class SupremeVerdict extends CardImpl { this.color.setBlue(true); // Supreme Verdict can't be countered. - Ability ability = new CantCounterAbility(); + Ability ability = new CantBeCounteredAbility(); ability.setRuleAtTheTop(true); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/sets/riseoftheeldrazi/EmrakulTheAeonsTorn.java b/Mage.Sets/src/mage/sets/riseoftheeldrazi/EmrakulTheAeonsTorn.java index c93267f37d..d20b48458d 100644 --- a/Mage.Sets/src/mage/sets/riseoftheeldrazi/EmrakulTheAeonsTorn.java +++ b/Mage.Sets/src/mage/sets/riseoftheeldrazi/EmrakulTheAeonsTorn.java @@ -36,7 +36,7 @@ import mage.constants.Zone; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; -import mage.abilities.common.CantCounterAbility; +import mage.abilities.common.CantBeCounteredAbility; import mage.abilities.common.PutIntoGraveFromAnywhereSourceTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.keyword.AnnihilatorAbility; @@ -73,7 +73,7 @@ public class EmrakulTheAeonsTorn extends CardImpl { this.toughness = new MageInt(15); // Emrakul, the Aeons Torn can't be countered. - this.addAbility(new CantCounterAbility()); + this.addAbility(new CantBeCounteredAbility()); // When you cast Emrakul, take an extra turn after this one. this.addAbility(new EmrakulTheAeonsTornOnCastAbility()); // Flying, protection from colored spells, annihilator 6 diff --git a/Mage.Sets/src/mage/sets/scarsofmirrodin/PrecursorGolem.java b/Mage.Sets/src/mage/sets/scarsofmirrodin/PrecursorGolem.java index 73e543efb2..34067fe1ac 100644 --- a/Mage.Sets/src/mage/sets/scarsofmirrodin/PrecursorGolem.java +++ b/Mage.Sets/src/mage/sets/scarsofmirrodin/PrecursorGolem.java @@ -34,10 +34,8 @@ import java.util.List; import java.util.Map; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.CreateTokenEffect; import mage.cards.CardImpl; @@ -55,7 +53,6 @@ import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.game.stack.Spell; import mage.target.Target; -import mage.target.targetpointer.FixedTarget; import java.util.UUID; import mage.filter.predicate.mageobject.FromSetPredicate; @@ -210,7 +207,7 @@ class PrecursorGolemCopySpellEffect extends OneShotEffect { UUID spellController = spell.getControllerId(); while (targetable.size() > 0) { FilterPermanent filter = new FilterPermanent("Golem", - "Golem that spell could target ("+Integer.toString(targetable.size())+" remaining)"); + "Golem that spell could target ("+targetable.size()+" remaining)"); filter.add(new FromSetPredicate(targetable.keySet())); TargetPermanent target = new TargetPermanent(0, 1, filter, true); diff --git a/Mage.Sets/src/mage/sets/scourge/XantidSwarm.java b/Mage.Sets/src/mage/sets/scourge/XantidSwarm.java index ef8da56be5..2939a3cc57 100644 --- a/Mage.Sets/src/mage/sets/scourge/XantidSwarm.java +++ b/Mage.Sets/src/mage/sets/scourge/XantidSwarm.java @@ -129,13 +129,16 @@ class XantidSwarmReplacementEffect extends ContinuousRuleModifiyingEffectImpl { return true; } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.CAST_SPELL; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == GameEvent.EventType.CAST_SPELL ) { - Player player = game.getPlayer(getTargetPointer().getFirst(game, source)); - if (player != null && player.getId().equals(event.getPlayerId())) { - return true; - } + Player player = game.getPlayer(getTargetPointer().getFirst(game, source)); + if (player != null && player.getId().equals(event.getPlayerId())) { + return true; } return false; } diff --git a/Mage.Sets/src/mage/sets/shadowmoor/ManaforgeCinder.java b/Mage.Sets/src/mage/sets/shadowmoor/ManaforgeCinder.java index 52b766ce9b..46d33e9ab6 100644 --- a/Mage.Sets/src/mage/sets/shadowmoor/ManaforgeCinder.java +++ b/Mage.Sets/src/mage/sets/shadowmoor/ManaforgeCinder.java @@ -27,16 +27,24 @@ */ package mage.sets.shadowmoor; +import java.util.LinkedHashSet; +import java.util.Set; import java.util.UUID; import mage.MageInt; import mage.Mana; +import mage.abilities.Ability; import mage.abilities.common.LimitedTimesPerTurnActivatedAbility; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.common.BasicManaEffect; +import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; +import mage.choices.Choice; +import mage.choices.ChoiceImpl; import mage.constants.CardType; +import mage.constants.Outcome; import mage.constants.Rarity; import mage.constants.Zone; +import mage.game.Game; +import mage.players.Player; /** * @@ -53,7 +61,7 @@ public class ManaforgeCinder extends CardImpl { this.toughness = new MageInt(1); // {1}: Add {B} or {R} to your mana pool. Activate this ability no more than three times each turn. - this.addAbility(new LimitedTimesPerTurnActivatedAbility(Zone.BATTLEFIELD, new BasicManaEffect(Mana.BlackMana), new ManaCostsImpl("{1}"), 3)); + this.addAbility(new LimitedTimesPerTurnActivatedAbility(Zone.BATTLEFIELD, new ManaforgeCinderManaEffect(), new ManaCostsImpl("{1}"), 3)); } @@ -66,3 +74,55 @@ public class ManaforgeCinder extends CardImpl { return new ManaforgeCinder(this); } } + + + +class ManaforgeCinderManaEffect extends OneShotEffect { + + public ManaforgeCinderManaEffect() { + super(Outcome.PutManaInPool); + this.staticText = "Add {B} or {R} to your mana pool"; + } + + public ManaforgeCinderManaEffect(final ManaforgeCinderManaEffect effect) { + super(effect); + } + + @Override + public ManaforgeCinderManaEffect copy() { + return new ManaforgeCinderManaEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + Choice manaChoice = new ChoiceImpl(); + Set choices = new LinkedHashSet<>(); + choices.add("Black"); + choices.add("Red"); + manaChoice.setChoices(choices); + manaChoice.setMessage("Select black or red mana to add to your mana pool"); + Mana mana = new Mana(); + while (!controller.choose(Outcome.Benefit, manaChoice, game)) { + if (!controller.isInGame()) { + return false; + } + } + if (manaChoice.getChoice() == null) { + return false; + } + switch (manaChoice.getChoice()) { + case "Black": + mana.addBlack(); + break; + case "Red": + mana.addRed(); + break; + } + controller.getManaPool().addMana(mana, game, source); + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/shadowmoor/MercyKilling.java b/Mage.Sets/src/mage/sets/shadowmoor/MercyKilling.java index 5d31d3636c..572f93919f 100644 --- a/Mage.Sets/src/mage/sets/shadowmoor/MercyKilling.java +++ b/Mage.Sets/src/mage/sets/shadowmoor/MercyKilling.java @@ -51,13 +51,11 @@ public class MercyKilling extends CardImpl { public MercyKilling(UUID ownerId) { super(ownerId, 231, "Mercy Killing", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{2}{G/W}"); this.expansionSetCode = "SHM"; - this.color.setGreen(true); - this.color.setWhite(true); // Target creature's controller sacrifices it, then puts X 1/1 green and white Elf Warrior creature tokens onto the battlefield, where X is that creature's power. - this.getSpellAbility().addTarget(new TargetCreaturePermanent()); - this.getSpellAbility().addEffect(new SacrificeTargetEffect()); + this.getSpellAbility().addEffect(new SacrificeTargetEffect("Target creature's controller sacrifices it")); this.getSpellAbility().addEffect(new MercyKillingTokenEffect()); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); } public MercyKilling(final MercyKilling card) { @@ -74,7 +72,7 @@ class MercyKillingTokenEffect extends OneShotEffect { public MercyKillingTokenEffect() { super(Outcome.PutCreatureInPlay); - staticText = "Its controller puts X 1/1 green and white Elf Warrior creature tokens onto the battlefield, where X is that creature's power."; + staticText = ", then puts X 1/1 green and white Elf Warrior creature tokens onto the battlefield, where X is that creature's power"; } public MercyKillingTokenEffect(final MercyKillingTokenEffect effect) { @@ -88,13 +86,12 @@ class MercyKillingTokenEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Permanent permanent = (Permanent) game.getLastKnownInformation(targetPointer.getFirst(game, source), Zone.BATTLEFIELD); + Permanent permanent = game.getPermanentOrLKIBattlefield(getTargetPointer().getFirst(game, source)); if (permanent != null) { int power = permanent.getPower().getValue(); - MercyKillingToken token = new MercyKillingToken(); - token.putOntoBattlefield(power, game, source.getSourceId(), permanent.getControllerId()); + return new MercyKillingToken().putOntoBattlefield(power, game, source.getSourceId(), permanent.getControllerId()); } - return true; + return false; } } diff --git a/Mage.Sets/src/mage/sets/shadowmoor/VexingShusher.java b/Mage.Sets/src/mage/sets/shadowmoor/VexingShusher.java index 4f8e5592ad..604e9dc16f 100644 --- a/Mage.Sets/src/mage/sets/shadowmoor/VexingShusher.java +++ b/Mage.Sets/src/mage/sets/shadowmoor/VexingShusher.java @@ -31,7 +31,7 @@ import java.util.UUID; import mage.MageInt; import mage.MageObject; import mage.abilities.Ability; -import mage.abilities.common.CantCounterAbility; +import mage.abilities.common.CantBeCounteredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.ContinuousRuleModifiyingEffectImpl; @@ -64,7 +64,7 @@ public class VexingShusher extends CardImpl { this.toughness = new MageInt(2); // Vexing Shusher can't be countered. - this.addAbility(new CantCounterAbility()); + this.addAbility(new CantBeCounteredAbility()); // {R/G}: Target spell can't be countered by spells or abilities. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new VexingShusherCantCounterTargetEffect(), new ManaCostsImpl("{R/G}")); ability.addTarget(new TargetSpell()); @@ -111,9 +111,14 @@ class VexingShusherCantCounterTargetEffect extends ContinuousRuleModifiyingEffec return null; } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.COUNTER; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - return event.getType() == EventType.COUNTER && event.getTargetId().equals(targetPointer.getFirst(game, source)); + return event.getTargetId().equals(targetPointer.getFirst(game, source)); } } diff --git a/Mage.Sets/src/mage/sets/shardsofalara/EtherswornCanonist.java b/Mage.Sets/src/mage/sets/shardsofalara/EtherswornCanonist.java index 1bcb3c3e10..e3e773bbac 100644 --- a/Mage.Sets/src/mage/sets/shardsofalara/EtherswornCanonist.java +++ b/Mage.Sets/src/mage/sets/shardsofalara/EtherswornCanonist.java @@ -144,14 +144,17 @@ class EtherswornCanonistReplacementEffect extends ContinuousRuleModifiyingEffect return new EtherswornCanonistReplacementEffect(this); } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.CAST_SPELL; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == GameEvent.EventType.CAST_SPELL) { - EtherswornCanonistWatcher watcher = (EtherswornCanonistWatcher)game.getState().getWatchers().get("EtherswornCanonistWatcher"); - Card card = game.getCard(event.getSourceId()); - if (card != null && !card.getCardType().contains(CardType.ARTIFACT) && watcher.castNonArtifactSpell(event.getPlayerId())) { - return true; - } + EtherswornCanonistWatcher watcher = (EtherswornCanonistWatcher)game.getState().getWatchers().get("EtherswornCanonistWatcher"); + Card card = game.getCard(event.getSourceId()); + if (card != null && !card.getCardType().contains(CardType.ARTIFACT) && watcher.castNonArtifactSpell(event.getPlayerId())) { + return true; } return false; } diff --git a/Mage.Sets/src/mage/sets/tempest/Scragnoth.java b/Mage.Sets/src/mage/sets/tempest/Scragnoth.java index bfa7fa0bcd..b5cc2219c6 100644 --- a/Mage.Sets/src/mage/sets/tempest/Scragnoth.java +++ b/Mage.Sets/src/mage/sets/tempest/Scragnoth.java @@ -30,7 +30,7 @@ package mage.sets.tempest; import java.util.UUID; import mage.MageInt; import mage.ObjectColor; -import mage.abilities.common.CantCounterAbility; +import mage.abilities.common.CantBeCounteredAbility; import mage.abilities.keyword.ProtectionAbility; import mage.cards.CardImpl; import mage.constants.CardType; @@ -59,7 +59,7 @@ public class Scragnoth extends CardImpl { this.toughness = new MageInt(4); // Scragnoth can't be countered. - this.addAbility(new CantCounterAbility()); + this.addAbility(new CantBeCounteredAbility()); // Protection from blue this.addAbility(new ProtectionAbility(filter)); } diff --git a/Mage.Sets/src/mage/sets/tenth/Incinerate.java b/Mage.Sets/src/mage/sets/tenth/Incinerate.java index 2a74ae3db2..ceef626402 100644 --- a/Mage.Sets/src/mage/sets/tenth/Incinerate.java +++ b/Mage.Sets/src/mage/sets/tenth/Incinerate.java @@ -91,13 +91,16 @@ class IncinerateEffect extends ContinuousRuleModifiyingEffectImpl { return true; } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.REGENERATE; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == EventType.REGENERATE) { - DamagedByWatcher watcher = (DamagedByWatcher) game.getState().getWatchers().get("DamagedByWatcher", source.getSourceId()); - if (watcher != null) { - return watcher.wasDamaged(event.getTargetId(), game); - } + DamagedByWatcher watcher = (DamagedByWatcher) game.getState().getWatchers().get("DamagedByWatcher", source.getSourceId()); + if (watcher != null) { + return watcher.wasDamaged(event.getTargetId(), game); } return false; } diff --git a/Mage.Sets/src/mage/sets/theros/MistcutterHydra.java b/Mage.Sets/src/mage/sets/theros/MistcutterHydra.java index b98c86cab1..8787d4435b 100644 --- a/Mage.Sets/src/mage/sets/theros/MistcutterHydra.java +++ b/Mage.Sets/src/mage/sets/theros/MistcutterHydra.java @@ -32,7 +32,7 @@ import mage.MageInt; import mage.ObjectColor; import mage.abilities.Ability; import mage.abilities.SpellAbility; -import mage.abilities.common.CantCounterAbility; +import mage.abilities.common.CantBeCounteredAbility; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.keyword.HasteAbility; @@ -68,7 +68,7 @@ public class MistcutterHydra extends CardImpl { this.toughness = new MageInt(0); // Mistcutter Hydra can't be countered. - this.addAbility(new CantCounterAbility()); + this.addAbility(new CantBeCounteredAbility()); // Haste this.addAbility(HasteAbility.getInstance()); // protection from blue diff --git a/Mage.Sets/src/mage/sets/theros/RageOfPurphoros.java b/Mage.Sets/src/mage/sets/theros/RageOfPurphoros.java index 0b15bba1cc..66afe5c6b4 100644 --- a/Mage.Sets/src/mage/sets/theros/RageOfPurphoros.java +++ b/Mage.Sets/src/mage/sets/theros/RageOfPurphoros.java @@ -28,19 +28,13 @@ package mage.sets.theros; import java.util.UUID; -import mage.abilities.Ability; -import mage.abilities.effects.ContinuousRuleModifiyingEffectImpl; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.keyword.ScryEffect; import mage.abilities.effects.common.ruleModifying.CantRegenerateTargetEffect; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Duration; -import mage.constants.Outcome; import mage.constants.Rarity; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.events.GameEvent.EventType; import mage.target.common.TargetCreaturePermanent; import mage.watchers.common.DamagedByWatcher; diff --git a/Mage.Sets/src/mage/sets/theros/ShipbreakerKraken.java b/Mage.Sets/src/mage/sets/theros/ShipbreakerKraken.java index 39a92dc639..a62a31ad8b 100644 --- a/Mage.Sets/src/mage/sets/theros/ShipbreakerKraken.java +++ b/Mage.Sets/src/mage/sets/theros/ShipbreakerKraken.java @@ -105,6 +105,13 @@ class ShipbreakerKrakenReplacementEffect extends ContinuousRuleModifiyingEffectI return false; } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.LOST_CONTROL || + event.getType() == GameEvent.EventType.ZONE_CHANGE || + event.getType() == GameEvent.EventType.UNTAP; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { // Source must be on the battlefield (it's neccessary to check here because if as response to the enter diff --git a/Mage.Sets/src/mage/sets/theros/UnderworldCerberus.java b/Mage.Sets/src/mage/sets/theros/UnderworldCerberus.java index fcf12ad5d3..bc4955e92b 100644 --- a/Mage.Sets/src/mage/sets/theros/UnderworldCerberus.java +++ b/Mage.Sets/src/mage/sets/theros/UnderworldCerberus.java @@ -105,16 +105,19 @@ class UnderworldCerberusEffect extends ContinuousRuleModifiyingEffectImpl { return true; } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.TARGET; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == GameEvent.EventType.TARGET) { - Card targetCard = game.getCard(event.getTargetId()); - StackObject stackObject = (StackObject) game.getStack().getStackObject(event.getSourceId()); - if (targetCard != null && stackObject != null) { - Zone zone = game.getState().getZone(targetCard.getId()); - if (zone != null && (zone == Zone.GRAVEYARD)) { - return true; - } + Card targetCard = game.getCard(event.getTargetId()); + StackObject stackObject = (StackObject) game.getStack().getStackObject(event.getSourceId()); + if (targetCard != null && stackObject != null) { + Zone zone = game.getState().getZone(targetCard.getId()); + if (zone != null && (zone == Zone.GRAVEYARD)) { + return true; } } return false; diff --git a/Mage.Sets/src/mage/sets/timespiral/MysticalTeachings.java b/Mage.Sets/src/mage/sets/timespiral/MysticalTeachings.java index 86bbab0247..0de1bbb8ca 100644 --- a/Mage.Sets/src/mage/sets/timespiral/MysticalTeachings.java +++ b/Mage.Sets/src/mage/sets/timespiral/MysticalTeachings.java @@ -49,7 +49,7 @@ import mage.target.common.TargetCardInLibrary; public class MysticalTeachings extends CardImpl { - private static final FilterCard filter = new FilterCard("creature an opponent controls"); + private static final FilterCard filter = new FilterCard("an instant card or a card with flash"); static { filter.add(Predicates.or( diff --git a/Mage.Sets/src/mage/sets/worldwake/AbyssalPersecutor.java b/Mage.Sets/src/mage/sets/worldwake/AbyssalPersecutor.java index 90c1ed0f69..b7716fb511 100644 --- a/Mage.Sets/src/mage/sets/worldwake/AbyssalPersecutor.java +++ b/Mage.Sets/src/mage/sets/worldwake/AbyssalPersecutor.java @@ -87,6 +87,11 @@ class AbyssalPersecutorCannotWinEffect extends ContinuousRuleModifiyingEffectImp super(effect); } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.LOSES || event.getType() == EventType.WINS ; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { if ((event.getType() == EventType.LOSES && game.getOpponents(source.getControllerId()).contains(event.getPlayerId())) diff --git a/Mage.Sets/src/mage/sets/zendikar/TerraStomper.java b/Mage.Sets/src/mage/sets/zendikar/TerraStomper.java index 72b7e44b5b..42f14da676 100644 --- a/Mage.Sets/src/mage/sets/zendikar/TerraStomper.java +++ b/Mage.Sets/src/mage/sets/zendikar/TerraStomper.java @@ -33,7 +33,7 @@ import mage.constants.Rarity; import mage.constants.Zone; import mage.MageInt; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.common.CantCounterSourceEffect; +import mage.abilities.effects.common.CantBeCounteredSourceEffect; import mage.abilities.keyword.TrampleAbility; import mage.cards.CardImpl; @@ -52,7 +52,7 @@ public class TerraStomper extends CardImpl { this.power = new MageInt(8); this.toughness = new MageInt(8); - this.addAbility(new SimpleStaticAbility(Zone.ALL, new CantCounterSourceEffect())); + this.addAbility(new SimpleStaticAbility(Zone.ALL, new CantBeCounteredSourceEffect())); this.addAbility(TrampleAbility.getInstance()); } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ManifestTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ManifestTest.java index 9055fc5763..6b6b280f87 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ManifestTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ManifestTest.java @@ -27,10 +27,8 @@ */ package org.mage.test.cards.abilities.keywords; -import mage.abilities.keyword.HexproofAbility; import mage.constants.PhaseStep; import mage.constants.Zone; -import mage.game.permanent.Permanent; import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBase; @@ -71,4 +69,35 @@ public class ManifestTest extends CardTestPlayerBase { assertTapped("face down creature", false); } + /** + * If Doomwake Giant gets manifested, it's Constellation trigger may not trigger + */ + @Test + public void testETBTriggeredAbilities2() { + addCard(Zone.BATTLEFIELD, playerA, "Plains", 2); + // Manifest the top card of your library {1}{W} + addCard(Zone.HAND, playerA, "Soul Summons"); + + // Constellation - When Doomwake Giant or another enchantment enters the battlefield + // under your control, creatures your opponents control get -1/-1 until end of turn. + addCard(Zone.LIBRARY, playerA, "Doomwake Giant"); + + addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion"); + skipInitShuffling(); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Soul Summons"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + // no life gain + assertLife(playerA, 20); + assertLife(playerB, 20); + // a facedown creature is on the battlefield + assertPermanentCount(playerA, "face down creature", 1); + assertPowerToughness(playerA, "face down creature", 2, 2); + // PlayerB's Silvercoat Lion should not have get -1/-1/ + assertPermanentCount(playerB, "Silvercoat Lion", 1); + assertPowerToughness(playerB, "Silvercoat Lion", 2, 2); + } } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/MorphTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/MorphTest.java index f6cc00537a..689ba24e9f 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/MorphTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/MorphTest.java @@ -401,4 +401,33 @@ public class MorphTest extends CardTestPlayerBase { assertPermanentCount(playerA, "face down creature", 1); } + + /** + * I played a Akroma, Angel of Fury face down, and my opponent tried to counter it. + * The counter failed and Akroma face successfully play face down, when it should have + * been countered. (The card text on akroma should not prevent her from being countered). + */ + + @Test + public void testRuleModifyingEffectsFromManifestedCardWontBeAppliedAbilities() { + addCard(Zone.HAND, playerA, "Akroma, Angel of Fury", 1); + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3); + + addCard(Zone.HAND, playerB, "Counterspell", 1); + addCard(Zone.BATTLEFIELD, playerB, "Island", 2); + + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Akroma, Angel of Fury"); + setChoice(playerA, "Yes"); // cast it face down as 2/2 creature + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Counterspell", "Akroma, Angel of Fury"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertLife(playerB, 20); + + assertGraveyardCount(playerB, "Counterspell", 1); + assertGraveyardCount(playerA, "Akroma, Angel of Fury", 1); + + } } diff --git a/Mage/src/mage/abilities/AbilityImpl.java b/Mage/src/mage/abilities/AbilityImpl.java index 5a5543667b..891e0d01ed 100644 --- a/Mage/src/mage/abilities/AbilityImpl.java +++ b/Mage/src/mage/abilities/AbilityImpl.java @@ -359,7 +359,7 @@ public abstract class AbilityImpl implements Ability { } else if (effect instanceof DynamicManaEffect) { mana = ((DynamicManaEffect)effect).getMana(game, this); } - if (mana != null) { // if mana == null the event has to be fires in the mana effect + if (mana != null) { // if mana == null the event has to be fired in the mana effect game.fireEvent(new ManaEvent(GameEvent.EventType.TAPPED_FOR_MANA, sourceId, sourceId, controllerId, mana)); } break; diff --git a/Mage/src/mage/abilities/abilityword/ConstellationAbility.java b/Mage/src/mage/abilities/abilityword/ConstellationAbility.java index 7b3fc33149..fd656686f4 100644 --- a/Mage/src/mage/abilities/abilityword/ConstellationAbility.java +++ b/Mage/src/mage/abilities/abilityword/ConstellationAbility.java @@ -30,7 +30,6 @@ package mage.abilities.abilityword; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.Effect; -import mage.constants.AbilityWord; import mage.constants.CardType; import mage.constants.Zone; import mage.game.Game; diff --git a/Mage/src/mage/abilities/common/CantCounterAbility.java b/Mage/src/mage/abilities/common/CantBeCounteredAbility.java similarity index 83% rename from Mage/src/mage/abilities/common/CantCounterAbility.java rename to Mage/src/mage/abilities/common/CantBeCounteredAbility.java index bf5bd6d152..fac6b58e28 100644 --- a/Mage/src/mage/abilities/common/CantCounterAbility.java +++ b/Mage/src/mage/abilities/common/CantBeCounteredAbility.java @@ -29,20 +29,20 @@ package mage.abilities.common; import mage.abilities.StaticAbility; -import mage.abilities.effects.common.CantCounterSourceEffect; +import mage.abilities.effects.common.CantBeCounteredSourceEffect; import mage.constants.Zone; /** * * @author BetaSteward_at_googlemail.com */ -public class CantCounterAbility extends StaticAbility { +public class CantBeCounteredAbility extends StaticAbility { - public CantCounterAbility() { - super(Zone.STACK, new CantCounterSourceEffect()); + public CantBeCounteredAbility() { + super(Zone.STACK, new CantBeCounteredSourceEffect()); } - public CantCounterAbility(CantCounterAbility ability) { + public CantBeCounteredAbility(CantBeCounteredAbility ability) { super(ability); } @@ -52,7 +52,7 @@ public class CantCounterAbility extends StaticAbility { } @Override - public CantCounterAbility copy() { - return new CantCounterAbility(this); + public CantBeCounteredAbility copy() { + return new CantBeCounteredAbility(this); } } diff --git a/Mage/src/mage/abilities/decorator/ConditionalContinuousRuleModifyingEffect.java b/Mage/src/mage/abilities/decorator/ConditionalContinuousRuleModifyingEffect.java index 03f7f71cbd..51e1a1ec80 100644 --- a/Mage/src/mage/abilities/decorator/ConditionalContinuousRuleModifyingEffect.java +++ b/Mage/src/mage/abilities/decorator/ConditionalContinuousRuleModifyingEffect.java @@ -99,6 +99,16 @@ public class ConditionalContinuousRuleModifyingEffect extends ContinuousRuleModi return false; } + @Override + public boolean checksEventType(GameEvent event, Game game) { + if (effect.checksEventType(event, game)) { + return true; + } else if (otherwiseEffect != null) { + return otherwiseEffect.checksEventType(event, game); + } + return false; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { if (!initDone) { // if simpleStaticAbility, init won't be called diff --git a/Mage/src/mage/abilities/effects/ContinuousEffects.java b/Mage/src/mage/abilities/effects/ContinuousEffects.java index d769ef989a..2bbc85cf77 100644 --- a/Mage/src/mage/abilities/effects/ContinuousEffects.java +++ b/Mage/src/mage/abilities/effects/ContinuousEffects.java @@ -67,6 +67,7 @@ import mage.game.events.GameEvent.EventType; import mage.game.events.ZoneChangeEvent; import mage.game.permanent.Permanent; import mage.game.permanent.PermanentCard; +import mage.game.stack.Spell; import mage.players.Player; import mage.target.common.TargetCardInHand; import org.apache.log4j.Logger; @@ -416,6 +417,11 @@ public class ContinuousEffects implements Serializable { if (permanent.isFaceDown() && !ability.getWorksFaceDown()) { return false; } + } else if (object instanceof Spell) { + Spell spell = (Spell)object; + if (spell.isFaceDown() && !ability.getWorksFaceDown()) { + return false; + } } } return exists; @@ -646,26 +652,31 @@ public class ContinuousEffects implements Serializable { */ public boolean preventedByRuleModification(GameEvent event, Ability targetAbility, Game game, boolean checkPlayableMode) { for (ContinuousRuleModifiyingEffect effect: continuousRuleModifyingEffects) { + if (!effect.checksEventType(event, game)) { + continue; + } for (Ability sourceAbility : continuousRuleModifyingEffects.getAbility(effect.getId())) { if (!(sourceAbility instanceof StaticAbility) || sourceAbility.isInUseableZone(game, null, false)) { - if (effect.getDuration() != Duration.OneUse || !effect.isUsed()) { - effect.setValue("targetAbility", targetAbility); - if (effect.applies(event, sourceAbility, game)) { - if (!checkPlayableMode) { - String message = effect.getInfoMessage(sourceAbility, event, game); - if (message != null && !message.isEmpty()) { - if (effect.sendMessageToUser()) { - Player player = game.getPlayer(event.getPlayerId()); - if (player != null) { - game.informPlayer(player, message); + if (checkAbilityStillExists(sourceAbility, effect, event, game)) { + if (effect.getDuration() != Duration.OneUse || !effect.isUsed()) { + effect.setValue("targetAbility", targetAbility); + if (effect.applies(event, sourceAbility, game)) { + if (!checkPlayableMode) { + String message = effect.getInfoMessage(sourceAbility, event, game); + if (message != null && !message.isEmpty()) { + if (effect.sendMessageToUser()) { + Player player = game.getPlayer(event.getPlayerId()); + if (player != null) { + game.informPlayer(player, message); + } + } + if (effect.sendMessageToGameLog()) { + game.informPlayers(message); } } - if (effect.sendMessageToGameLog()) { - game.informPlayers(message); - } } + return true; } - return true; } } } diff --git a/Mage/src/mage/abilities/effects/ContinuousRuleModifiyingEffect.java b/Mage/src/mage/abilities/effects/ContinuousRuleModifiyingEffect.java index 60e2754368..f6bc9981b6 100644 --- a/Mage/src/mage/abilities/effects/ContinuousRuleModifiyingEffect.java +++ b/Mage/src/mage/abilities/effects/ContinuousRuleModifiyingEffect.java @@ -38,6 +38,15 @@ import mage.game.events.GameEvent; */ public interface ContinuousRuleModifiyingEffect extends ContinuousEffect { + /** + * This check for the relevant events is called at first to prevent further actions if + * the current event is ignored from this effect + * @param event + * @param game + * @return + */ + boolean checksEventType(GameEvent event, Game game); + /** * * @param event the event to check if it may happen diff --git a/Mage/src/mage/abilities/effects/ContinuousRuleModifiyingEffectImpl.java b/Mage/src/mage/abilities/effects/ContinuousRuleModifiyingEffectImpl.java index 9d4f756bab..ee3fdadb0e 100644 --- a/Mage/src/mage/abilities/effects/ContinuousRuleModifiyingEffectImpl.java +++ b/Mage/src/mage/abilities/effects/ContinuousRuleModifiyingEffectImpl.java @@ -78,6 +78,11 @@ public abstract class ContinuousRuleModifiyingEffectImpl extends ContinuousEffec this.messageToGameLog = effect.messageToGameLog; } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return true; + } + @Override public boolean apply(Game game, Ability source) { return true; diff --git a/Mage/src/mage/abilities/effects/common/AddManaOfAnyColorEffect.java b/Mage/src/mage/abilities/effects/common/AddManaOfAnyColorEffect.java index 55ff35d170..5a080336e7 100644 --- a/Mage/src/mage/abilities/effects/common/AddManaOfAnyColorEffect.java +++ b/Mage/src/mage/abilities/effects/common/AddManaOfAnyColorEffect.java @@ -73,7 +73,7 @@ public class AddManaOfAnyColorEffect extends BasicManaEffect { if (controller.choose(outcome, choice, game)) { if (choice.getColor() == null) { - return false; // it happenes, don't know how + return false; // it happens, don't know how } Mana createdMana = null; if (choice.getColor().isBlack()) { @@ -89,6 +89,7 @@ public class AddManaOfAnyColorEffect extends BasicManaEffect { } if (createdMana != null) { controller.getManaPool().addMana(createdMana, game, source); + checkToFirePossibleEvents(createdMana, game, source); } return true; } diff --git a/Mage/src/mage/abilities/effects/common/CantActivateAbilitiesAttachedEffect.java b/Mage/src/mage/abilities/effects/common/CantActivateAbilitiesAttachedEffect.java index c3a3ad2041..6870b413cf 100644 --- a/Mage/src/mage/abilities/effects/common/CantActivateAbilitiesAttachedEffect.java +++ b/Mage/src/mage/abilities/effects/common/CantActivateAbilitiesAttachedEffect.java @@ -61,14 +61,17 @@ public class CantActivateAbilitiesAttachedEffect extends ContinuousRuleModifiyin return true; } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.ACTIVATE_ABILITY; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == GameEvent.EventType.ACTIVATE_ABILITY) { - Permanent enchantment = game.getPermanent(source.getSourceId()); - if (enchantment != null && enchantment.getAttachedTo() != null) { - if (event.getSourceId().equals(enchantment.getAttachedTo())) { - return true; - } + Permanent enchantment = game.getPermanent(source.getSourceId()); + if (enchantment != null && enchantment.getAttachedTo() != null) { + if (event.getSourceId().equals(enchantment.getAttachedTo())) { + return true; } } return false; diff --git a/Mage/src/mage/abilities/effects/common/CantCounterControlledEffect.java b/Mage/src/mage/abilities/effects/common/CantBeCounteredControlledEffect.java similarity index 74% rename from Mage/src/mage/abilities/effects/common/CantCounterControlledEffect.java rename to Mage/src/mage/abilities/effects/common/CantBeCounteredControlledEffect.java index 93179db339..45a6ea29b2 100644 --- a/Mage/src/mage/abilities/effects/common/CantCounterControlledEffect.java +++ b/Mage/src/mage/abilities/effects/common/CantBeCounteredControlledEffect.java @@ -44,23 +44,23 @@ import mage.game.stack.Spell; * * @author BetaSteward_at_googlemail.com */ -public class CantCounterControlledEffect extends ContinuousRuleModifiyingEffectImpl { +public class CantBeCounteredControlledEffect extends ContinuousRuleModifiyingEffectImpl { private FilterSpell filterTarget; private FilterObject filterSource; - public CantCounterControlledEffect(FilterSpell filterTarget, FilterObject filterSource, Duration duration) { + public CantBeCounteredControlledEffect(FilterSpell filterTarget, FilterObject filterSource, Duration duration) { super(duration, Outcome.Benefit); this.filterTarget = filterTarget; this.filterSource = filterSource; setText(); } - public CantCounterControlledEffect(FilterSpell filterTarget, Duration duration) { + public CantBeCounteredControlledEffect(FilterSpell filterTarget, Duration duration) { this(filterTarget, null, duration); } - public CantCounterControlledEffect(final CantCounterControlledEffect effect) { + public CantBeCounteredControlledEffect(final CantBeCounteredControlledEffect effect) { super(effect); if (effect.filterTarget != null) { this.filterTarget = effect.filterTarget.copy(); @@ -71,8 +71,8 @@ public class CantCounterControlledEffect extends ContinuousRuleModifiyingEffectI } @Override - public CantCounterControlledEffect copy() { - return new CantCounterControlledEffect(this); + public CantBeCounteredControlledEffect copy() { + return new CantBeCounteredControlledEffect(this); } @Override @@ -80,19 +80,22 @@ public class CantCounterControlledEffect extends ContinuousRuleModifiyingEffectI return true; } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.COUNTER; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == EventType.COUNTER) { - Spell spell = game.getStack().getSpell(event.getTargetId()); - if (spell != null && spell.getControllerId().equals(source.getControllerId()) - && filterTarget.match(spell, game)) { - if (filterSource == null) { + Spell spell = game.getStack().getSpell(event.getTargetId()); + if (spell != null && spell.getControllerId().equals(source.getControllerId()) + && filterTarget.match(spell, game)) { + if (filterSource == null) { + return true; + } else { + MageObject sourceObject = game.getObject(source.getSourceId()); + if (sourceObject != null && filterSource.match(sourceObject, game)) { return true; - } else { - MageObject sourceObject = game.getObject(source.getSourceId()); - if (sourceObject != null && filterSource.match(sourceObject, game)) { - return true; - } } } } diff --git a/Mage/src/mage/abilities/effects/common/CantCounterSourceEffect.java b/Mage/src/mage/abilities/effects/common/CantBeCounteredSourceEffect.java similarity index 81% rename from Mage/src/mage/abilities/effects/common/CantCounterSourceEffect.java rename to Mage/src/mage/abilities/effects/common/CantBeCounteredSourceEffect.java index f845cc6612..56e13eb14a 100644 --- a/Mage/src/mage/abilities/effects/common/CantCounterSourceEffect.java +++ b/Mage/src/mage/abilities/effects/common/CantBeCounteredSourceEffect.java @@ -43,20 +43,20 @@ import mage.game.stack.StackObject; * * @author BetaSteward_at_googlemail.com */ -public class CantCounterSourceEffect extends ContinuousRuleModifiyingEffectImpl { +public class CantBeCounteredSourceEffect extends ContinuousRuleModifiyingEffectImpl { - public CantCounterSourceEffect() { + public CantBeCounteredSourceEffect() { super(Duration.WhileOnStack, Outcome.Benefit, false, true); staticText = "{this} can't be countered"; } - public CantCounterSourceEffect(final CantCounterSourceEffect effect) { + public CantBeCounteredSourceEffect(final CantBeCounteredSourceEffect effect) { super(effect); } @Override - public CantCounterSourceEffect copy() { - return new CantCounterSourceEffect(this); + public CantBeCounteredSourceEffect copy() { + return new CantBeCounteredSourceEffect(this); } @Override @@ -74,14 +74,18 @@ public class CantCounterSourceEffect extends ContinuousRuleModifiyingEffectImpl return staticText; } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.COUNTER; + } + + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == EventType.COUNTER) { - Spell spell = game.getStack().getSpell(event.getTargetId()); - if (spell != null) { - if (spell.getSourceId().equals(source.getSourceId())) { - return true; - } + Spell spell = game.getStack().getSpell(event.getTargetId()); + if (spell != null) { + if (spell.getSourceId().equals(source.getSourceId())) { + return true; } } return false; diff --git a/Mage/src/mage/abilities/effects/common/CantBeTargetedAllEffect.java b/Mage/src/mage/abilities/effects/common/CantBeTargetedAllEffect.java index d030c329dc..8c8f68724e 100644 --- a/Mage/src/mage/abilities/effects/common/CantBeTargetedAllEffect.java +++ b/Mage/src/mage/abilities/effects/common/CantBeTargetedAllEffect.java @@ -81,20 +81,23 @@ public class CantBeTargetedAllEffect extends ContinuousRuleModifiyingEffectImpl return true; } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.TARGET; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == EventType.TARGET) { - Permanent permanent = game.getPermanent(event.getTargetId()); - if (permanent != null && filterTarget.match(permanent, source.getSourceId(), source.getControllerId(), game)) { - if (filterSource == null) { + Permanent permanent = game.getPermanent(event.getTargetId()); + if (permanent != null && filterTarget.match(permanent, source.getSourceId(), source.getControllerId(), game)) { + if (filterSource == null) { + return true; + } + else { + StackObject sourceObject = game.getStack().getStackObject(event.getSourceId()); + if (sourceObject != null && filterSource.match(sourceObject, sourceObject.getSourceId(), game)) { return true; } - else { - StackObject sourceObject = game.getStack().getStackObject(event.getSourceId()); - if (sourceObject != null && filterSource.match(sourceObject, sourceObject.getSourceId(), game)) { - return true; - } - } } } return false; diff --git a/Mage/src/mage/abilities/effects/common/CantBeTargetedAttachedEffect.java b/Mage/src/mage/abilities/effects/common/CantBeTargetedAttachedEffect.java index 0b1e988940..5971c1ac3d 100644 --- a/Mage/src/mage/abilities/effects/common/CantBeTargetedAttachedEffect.java +++ b/Mage/src/mage/abilities/effects/common/CantBeTargetedAttachedEffect.java @@ -72,15 +72,18 @@ public class CantBeTargetedAttachedEffect extends ContinuousRuleModifiyingEffect return true; } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.TARGET; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == EventType.TARGET) { - Permanent attachment = game.getPermanent(source.getSourceId()); - if (attachment != null && event.getTargetId().equals(attachment.getAttachedTo())) { - StackObject sourceObject = game.getStack().getStackObject(event.getSourceId()); - if (sourceObject != null && filterSource.match(sourceObject, source.getControllerId(), game)) { - return true; - } + Permanent attachment = game.getPermanent(source.getSourceId()); + if (attachment != null && event.getTargetId().equals(attachment.getAttachedTo())) { + StackObject sourceObject = game.getStack().getStackObject(event.getSourceId()); + if (sourceObject != null && filterSource.match(sourceObject, source.getControllerId(), game)) { + return true; } } return false; diff --git a/Mage/src/mage/abilities/effects/common/CantBeTargetedSourceEffect.java b/Mage/src/mage/abilities/effects/common/CantBeTargetedSourceEffect.java index e00e75831d..f8165a0f4b 100644 --- a/Mage/src/mage/abilities/effects/common/CantBeTargetedSourceEffect.java +++ b/Mage/src/mage/abilities/effects/common/CantBeTargetedSourceEffect.java @@ -66,10 +66,15 @@ public class CantBeTargetedSourceEffect extends ContinuousRuleModifiyingEffectIm public boolean apply(Game game, Ability source) { return true; } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.TARGET; + } @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == EventType.TARGET && event.getTargetId().equals(source.getSourceId())) { + if (event.getTargetId().equals(source.getSourceId())) { StackObject sourceObject = game.getStack().getStackObject(event.getSourceId()); if (sourceObject != null && filterSource.match(sourceObject, source.getControllerId(), game)) { return true; diff --git a/Mage/src/mage/abilities/effects/common/CantBeTargetedTargetEffect.java b/Mage/src/mage/abilities/effects/common/CantBeTargetedTargetEffect.java index a8c3c1bb1d..f79af2655e 100644 --- a/Mage/src/mage/abilities/effects/common/CantBeTargetedTargetEffect.java +++ b/Mage/src/mage/abilities/effects/common/CantBeTargetedTargetEffect.java @@ -67,9 +67,14 @@ public class CantBeTargetedTargetEffect extends ContinuousRuleModifiyingEffectIm return true; } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.TARGET; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == EventType.TARGET && getTargetPointer().getTargets(game, source).contains(event.getTargetId())) { + if (getTargetPointer().getTargets(game, source).contains(event.getTargetId())) { StackObject sourceObject = game.getStack().getStackObject(event.getSourceId()); if (sourceObject != null && filterSource.match(sourceObject, source.getControllerId(), game)) { return true; diff --git a/Mage/src/mage/abilities/effects/common/DamageEverythingEffect.java b/Mage/src/mage/abilities/effects/common/DamageEverythingEffect.java index e45f227091..cb5fab6149 100644 --- a/Mage/src/mage/abilities/effects/common/DamageEverythingEffect.java +++ b/Mage/src/mage/abilities/effects/common/DamageEverythingEffect.java @@ -49,6 +49,7 @@ public class DamageEverythingEffect extends OneShotEffect { private DynamicValue amount; private FilterPermanent filter; + private UUID damageSource; public DamageEverythingEffect(int amount) { this(new StaticValue(amount), new FilterCreaturePermanent()); @@ -57,11 +58,15 @@ public class DamageEverythingEffect extends OneShotEffect { public DamageEverythingEffect(int amount, FilterPermanent filter) { this(new StaticValue(amount), filter); } - public DamageEverythingEffect(DynamicValue amount, FilterPermanent filter) { + this(amount, filter, null); + } + + public DamageEverythingEffect(DynamicValue amount, FilterPermanent filter, UUID damageSource) { super(Outcome.Damage); this.amount = amount; this.filter = filter; + this.damageSource = damageSource; staticText = "{source} deals " + amount.toString() + " damage to each " + filter.getMessage() + " and each player"; } @@ -69,6 +74,7 @@ public class DamageEverythingEffect extends OneShotEffect { super(effect); this.amount = effect.amount; this.filter = effect.filter; + this.damageSource = effect.damageSource; } @Override @@ -81,12 +87,12 @@ public class DamageEverythingEffect extends OneShotEffect { int damage = amount.calculate(game, source, this); List permanents = game.getBattlefield().getActivePermanents(filter, source.getControllerId(), game); for (Permanent permanent: permanents) { - permanent.damage(damage, source.getSourceId(), game, false, true); + permanent.damage(damage, damageSource == null ? source.getSourceId(): damageSource, game, false, true); } for (UUID playerId: game.getPlayer(source.getControllerId()).getInRange()) { Player player = game.getPlayer(playerId); if (player != null) { - player.damage(damage, source.getSourceId(), game, false, true); + player.damage(damage, damageSource == null ? source.getSourceId(): damageSource, game, false, true); } } return true; diff --git a/Mage/src/mage/abilities/effects/common/DontUntapInControllersNextUntapStepSourceEffect.java b/Mage/src/mage/abilities/effects/common/DontUntapInControllersNextUntapStepSourceEffect.java index e9158b91f2..ebca00685a 100644 --- a/Mage/src/mage/abilities/effects/common/DontUntapInControllersNextUntapStepSourceEffect.java +++ b/Mage/src/mage/abilities/effects/common/DontUntapInControllersNextUntapStepSourceEffect.java @@ -42,7 +42,11 @@ public class DontUntapInControllersNextUntapStepSourceEffect extends ContinuousR return null; } - + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.UNTAP_STEP || event.getType() == GameEvent.EventType.UNTAP; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { // the check for turn number is needed if multiple effects are added to prevent untap in next untap step @@ -55,7 +59,7 @@ public class DontUntapInControllersNextUntapStepSourceEffect extends ContinuousR return false; } // remember the turn of the untap step the effect has to be applied - if (GameEvent.EventType.UNTAP_STEP.equals(event.getType()) + if (GameEvent.EventType.UNTAP_STEP.equals(event.getType()) && game.getActivePlayerId().equals(source.getControllerId())) { if (validForTurnNum == game.getTurnNum()) { // the turn has a second untap step but the effect is already related to the first untap step discard(); diff --git a/Mage/src/mage/abilities/effects/common/DontUntapInControllersNextUntapStepTargetEffect.java b/Mage/src/mage/abilities/effects/common/DontUntapInControllersNextUntapStepTargetEffect.java index 1702e81da4..356838b0a5 100644 --- a/Mage/src/mage/abilities/effects/common/DontUntapInControllersNextUntapStepTargetEffect.java +++ b/Mage/src/mage/abilities/effects/common/DontUntapInControllersNextUntapStepTargetEffect.java @@ -86,6 +86,11 @@ public class DontUntapInControllersNextUntapStepTargetEffect extends ContinuousR } return null; } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.UNTAP_STEP || event.getType() == EventType.UNTAP; + } @Override public boolean applies(GameEvent event, Ability source, Game game) { @@ -99,7 +104,7 @@ public class DontUntapInControllersNextUntapStepTargetEffect extends ContinuousR return false; } // remember the turn of the untap step the effect has to be applied - if (GameEvent.EventType.UNTAP_STEP.equals(event.getType())) { + if (GameEvent.EventType.UNTAP_STEP.equals(event.getType())) { UUID controllerId = null; for(UUID targetId : getTargetPointer().getTargets(game, source)) { Permanent permanent = game.getPermanent(targetId); @@ -109,17 +114,16 @@ public class DontUntapInControllersNextUntapStepTargetEffect extends ContinuousR } if (controllerId == null) { // no more targets on the battlefield, effect can be discarded discard(); - return false; + return false; } - - if (game.getActivePlayerId().equals(controllerId)) { + + if (game.getActivePlayerId().equals(controllerId)) { if (validForTurnNum == game.getTurnNum()) { // the turn has a second untap step but the effect is already related to the first untap step discard(); - return false; + return false; } validForTurnNum = game.getTurnNum(); } - } if (game.getTurn().getStepType() == PhaseStep.UNTAP && event.getType() == EventType.UNTAP) { diff --git a/Mage/src/mage/abilities/effects/common/DontUntapInControllersUntapStepAllEffect.java b/Mage/src/mage/abilities/effects/common/DontUntapInControllersUntapStepAllEffect.java index 87561e97f3..2b203c2222 100644 --- a/Mage/src/mage/abilities/effects/common/DontUntapInControllersUntapStepAllEffect.java +++ b/Mage/src/mage/abilities/effects/common/DontUntapInControllersUntapStepAllEffect.java @@ -41,6 +41,7 @@ import static mage.constants.TargetController.YOU; import mage.filter.FilterPermanent; import mage.game.Game; import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; import mage.game.permanent.Permanent; import mage.players.Player; @@ -76,10 +77,15 @@ public class DontUntapInControllersUntapStepAllEffect extends ContinuousRuleModi public boolean apply(Game game, Ability source) { return false; } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.UNTAP; + } @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (GameEvent.EventType.UNTAP.equals(event.getType()) && PhaseStep.UNTAP.equals(game.getTurn().getStepType())) { + if (PhaseStep.UNTAP.equals(game.getTurn().getStepType())) { Permanent permanent = game.getPermanent(event.getTargetId()); if (permanent != null) { switch(targetController) { diff --git a/Mage/src/mage/abilities/effects/common/DontUntapInControllersUntapStepEnchantedEffect.java b/Mage/src/mage/abilities/effects/common/DontUntapInControllersUntapStepEnchantedEffect.java index 350f260174..164ec3bced 100644 --- a/Mage/src/mage/abilities/effects/common/DontUntapInControllersUntapStepEnchantedEffect.java +++ b/Mage/src/mage/abilities/effects/common/DontUntapInControllersUntapStepEnchantedEffect.java @@ -45,10 +45,14 @@ public class DontUntapInControllersUntapStepEnchantedEffect extends ContinuousRu return null; } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.UNTAP; + } @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (GameEvent.EventType.UNTAP.equals(event.getType()) && PhaseStep.UNTAP.equals(game.getTurn().getStepType())) { + if (PhaseStep.UNTAP.equals(game.getTurn().getStepType())) { Permanent enchantment = game.getPermanent(source.getSourceId()); if (enchantment != null && enchantment.getAttachedTo() != null && event.getTargetId().equals(enchantment.getAttachedTo())) { Permanent permanent = game.getPermanent(enchantment.getAttachedTo()); diff --git a/Mage/src/mage/abilities/effects/common/DontUntapInControllersUntapStepSourceEffect.java b/Mage/src/mage/abilities/effects/common/DontUntapInControllersUntapStepSourceEffect.java index f309574aa6..694098bf19 100644 --- a/Mage/src/mage/abilities/effects/common/DontUntapInControllersUntapStepSourceEffect.java +++ b/Mage/src/mage/abilities/effects/common/DontUntapInControllersUntapStepSourceEffect.java @@ -62,10 +62,14 @@ public class DontUntapInControllersUntapStepSourceEffect extends ContinuousRuleM return false; } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.UNTAP; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { if (game.getTurn().getStepType() == PhaseStep.UNTAP - && event.getType() == EventType.UNTAP && event.getTargetId().equals(source.getSourceId())) { Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent != null && permanent.getControllerId().equals(game.getActivePlayerId())) { diff --git a/Mage/src/mage/abilities/effects/common/DontUntapInControllersUntapStepTargetEffect.java b/Mage/src/mage/abilities/effects/common/DontUntapInControllersUntapStepTargetEffect.java index 9bdcc13d54..327a85d02b 100644 --- a/Mage/src/mage/abilities/effects/common/DontUntapInControllersUntapStepTargetEffect.java +++ b/Mage/src/mage/abilities/effects/common/DontUntapInControllersUntapStepTargetEffect.java @@ -38,7 +38,6 @@ import mage.constants.Outcome; import mage.constants.PhaseStep; import mage.game.Game; import mage.game.events.GameEvent; -import mage.game.events.GameEvent.EventType; import mage.game.permanent.Permanent; /** @@ -74,10 +73,15 @@ public class DontUntapInControllersUntapStepTargetEffect extends ContinuousRuleM } return null; } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.UNTAP; + } @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (GameEvent.EventType.UNTAP.equals(event.getType()) && PhaseStep.UNTAP.equals(game.getTurn().getStepType())) { + if (PhaseStep.UNTAP.equals(game.getTurn().getStepType())) { for (UUID targetId : targetPointer.getTargets(game, source)) { if (event.getTargetId().equals(targetId)) { Permanent permanent = game.getPermanent(targetId); diff --git a/Mage/src/mage/abilities/effects/common/EpicEffect.java b/Mage/src/mage/abilities/effects/common/EpicEffect.java index a161e9cc01..325f3d3ded 100644 --- a/Mage/src/mage/abilities/effects/common/EpicEffect.java +++ b/Mage/src/mage/abilities/effects/common/EpicEffect.java @@ -108,11 +108,15 @@ class EpicReplacementEffect extends ContinuousRuleModifiyingEffectImpl { } return null; } - + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.CAST_SPELL; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == GameEvent.EventType.CAST_SPELL - && source.getControllerId() == event.getPlayerId()) { + if (source.getControllerId() == event.getPlayerId()) { MageObject object = game.getObject(event.getSourceId()); if (object != null) { return true; diff --git a/Mage/src/mage/abilities/effects/common/continious/CantCastMoreThanOneSpellEffect.java b/Mage/src/mage/abilities/effects/common/continious/CantCastMoreThanOneSpellEffect.java index 85c37b476d..81d04070fc 100644 --- a/Mage/src/mage/abilities/effects/common/continious/CantCastMoreThanOneSpellEffect.java +++ b/Mage/src/mage/abilities/effects/common/continious/CantCastMoreThanOneSpellEffect.java @@ -68,35 +68,38 @@ public class CantCastMoreThanOneSpellEffect extends ContinuousRuleModifiyingEffe return true; } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.CAST_SPELL; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == GameEvent.EventType.CAST_SPELL) { - switch (targetController) { - case YOU: - if (!event.getPlayerId().equals(source.getControllerId())) { - return false; - } - break; - case NOT_YOU: - if (event.getPlayerId().equals(source.getControllerId())) { - return false; - } - break; - case OPPONENT: - if (!game.getOpponents(source.getControllerId()).contains(event.getPlayerId())) { - return false; - } - break; - case CONTROLLER_ATTACHED_TO: - Permanent attachment = game.getPermanent(source.getSourceId()); - if (attachment == null || !attachment.getAttachedTo().equals(event.getPlayerId())) { - return false; - } - } - CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get("CastSpellLastTurnWatcher"); - if (watcher != null && watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(event.getPlayerId())> 0) { - return true; - } + switch (targetController) { + case YOU: + if (!event.getPlayerId().equals(source.getControllerId())) { + return false; + } + break; + case NOT_YOU: + if (event.getPlayerId().equals(source.getControllerId())) { + return false; + } + break; + case OPPONENT: + if (!game.getOpponents(source.getControllerId()).contains(event.getPlayerId())) { + return false; + } + break; + case CONTROLLER_ATTACHED_TO: + Permanent attachment = game.getPermanent(source.getSourceId()); + if (attachment == null || !attachment.getAttachedTo().equals(event.getPlayerId())) { + return false; + } + } + CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get("CastSpellLastTurnWatcher"); + if (watcher != null && watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(event.getPlayerId())> 0) { + return true; } return false; } diff --git a/Mage/src/mage/abilities/effects/common/ruleModifying/CantRegenerateTargetEffect.java b/Mage/src/mage/abilities/effects/common/ruleModifying/CantRegenerateTargetEffect.java index ba4f29177f..ce6693c4a6 100644 --- a/Mage/src/mage/abilities/effects/common/ruleModifying/CantRegenerateTargetEffect.java +++ b/Mage/src/mage/abilities/effects/common/ruleModifying/CantRegenerateTargetEffect.java @@ -35,6 +35,7 @@ import mage.constants.Duration; import mage.constants.Outcome; import mage.game.Game; import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; /** * @@ -62,13 +63,16 @@ public class CantRegenerateTargetEffect extends ContinuousRuleModifiyingEffectIm return true; } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.REGENERATE; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (GameEvent.EventType.REGENERATE.equals(event.getType())) { - UUID targetId = getTargetPointer().getFirst(game, source); - if (targetId != null) { - return targetId.equals(event.getTargetId()); - } + UUID targetId = getTargetPointer().getFirst(game, source); + if (targetId != null) { + return targetId.equals(event.getTargetId()); } return false; } diff --git a/Mage/src/mage/abilities/keyword/SplitSecondAbility.java b/Mage/src/mage/abilities/keyword/SplitSecondAbility.java index 8e583142db..72bb0f8ac6 100644 --- a/Mage/src/mage/abilities/keyword/SplitSecondAbility.java +++ b/Mage/src/mage/abilities/keyword/SplitSecondAbility.java @@ -55,6 +55,11 @@ class SplitSecondEffect extends ContinuousRuleModifiyingEffectImpl { return "You can't cast spells or activate abilities that aren't mana abilities (Split second)."; } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.CAST_SPELL || event.getType() == GameEvent.EventType.ACTIVATE_ABILITY; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { if (event.getType() == GameEvent.EventType.CAST_SPELL) { diff --git a/Mage/src/mage/filter/predicate/mageobject/FromSetPredicate.java b/Mage/src/mage/filter/predicate/mageobject/FromSetPredicate.java index 0c0822e3d2..a106b23293 100644 --- a/Mage/src/mage/filter/predicate/mageobject/FromSetPredicate.java +++ b/Mage/src/mage/filter/predicate/mageobject/FromSetPredicate.java @@ -29,22 +29,24 @@ package mage.filter.predicate.mageobject; import java.util.Set; import java.util.UUID; -import mage.MageObject; import mage.filter.predicate.ObjectPlayer; import mage.filter.predicate.ObjectPlayerPredicate; +import mage.game.Controllable; import mage.game.Game; /** * @author duncancmt */ -public class FromSetPredicate> implements ObjectPlayerPredicate { +public class FromSetPredicate implements ObjectPlayerPredicate> { + protected Set set; public FromSetPredicate(Set set) { this.set = set; } - public boolean apply(T input, Game game) { + @Override + public boolean apply(ObjectPlayer input, Game game) { return set.contains(input.getObject().getId()); } } diff --git a/Mage/src/mage/game/permanent/PermanentImpl.java b/Mage/src/mage/game/permanent/PermanentImpl.java index 7b3692e29d..432fa0631a 100644 --- a/Mage/src/mage/game/permanent/PermanentImpl.java +++ b/Mage/src/mage/game/permanent/PermanentImpl.java @@ -37,6 +37,7 @@ import java.util.List; import java.util.Map; import java.util.UUID; import mage.MageObject; +import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.Effect; @@ -854,6 +855,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent { //20091005 - 701.13 if (!game.replaceEvent(GameEvent.getEvent(EventType.SACRIFICE_PERMANENT, objectId, sourceId, controllerId))) { // Commander replacement effect or Rest in Peace (exile instead of graveyard) in play does not prevent successful sacrifice + // so the return value of the moveToZone is not taken into account here moveToZone(Zone.GRAVEYARD, sourceId, game, false); Player player = game.getPlayer(getControllerId()); if (player != null) {