diff --git a/Mage.Sets/src/mage/cards/a/AncestorsEmbrace.java b/Mage.Sets/src/mage/cards/a/AncestorsEmbrace.java index 8929484e38f..ce046048700 100644 --- a/Mage.Sets/src/mage/cards/a/AncestorsEmbrace.java +++ b/Mage.Sets/src/mage/cards/a/AncestorsEmbrace.java @@ -1,11 +1,9 @@ package mage.cards.a; -import mage.abilities.Ability; -import mage.abilities.common.PutIntoGraveFromAnywhereSourceAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.AttachEffect; -import mage.abilities.effects.common.ExileSourceEffect; import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; +import mage.abilities.keyword.DisturbAbility; import mage.abilities.keyword.EnchantAbility; import mage.abilities.keyword.LifelinkAbility; import mage.cards.CardImpl; @@ -32,8 +30,7 @@ public final class AncestorsEmbrace extends CardImpl { TargetPermanent auraTarget = new TargetCreaturePermanent(); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); - Ability ability = new EnchantAbility(auraTarget); - this.addAbility(ability); + this.addAbility(new EnchantAbility(auraTarget)); // Enchanted creature has lifelink. this.addAbility(new SimpleStaticAbility(new GainAbilityAttachedEffect( @@ -41,7 +38,7 @@ public final class AncestorsEmbrace extends CardImpl { ))); // If Ancestor's Embrace would be put into a graveyard from anywhere, exile it instead. - this.addAbility(new PutIntoGraveFromAnywhereSourceAbility(new ExileSourceEffect().setText("exile it instead"))); + this.addAbility(DisturbAbility.makeBackAbility()); } private AncestorsEmbrace(final AncestorsEmbrace card) { diff --git a/Mage.Sets/src/mage/cards/a/ArchiveHaunt.java b/Mage.Sets/src/mage/cards/a/ArchiveHaunt.java index 7516cde5dc8..b4fac23a008 100644 --- a/Mage.Sets/src/mage/cards/a/ArchiveHaunt.java +++ b/Mage.Sets/src/mage/cards/a/ArchiveHaunt.java @@ -2,9 +2,8 @@ package mage.cards.a; import mage.MageInt; import mage.abilities.common.AttacksTriggeredAbility; -import mage.abilities.common.PutIntoGraveFromAnywhereSourceAbility; import mage.abilities.effects.common.DrawDiscardControllerEffect; -import mage.abilities.effects.common.ExileSourceEffect; +import mage.abilities.keyword.DisturbAbility; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -35,7 +34,7 @@ public final class ArchiveHaunt extends CardImpl { this.addAbility(new AttacksTriggeredAbility(new DrawDiscardControllerEffect(1, 1))); // If Archive Haunt would be put into a graveyard from anywhere, exile it instead. - this.addAbility(new PutIntoGraveFromAnywhereSourceAbility(new ExileSourceEffect().setText("exile it instead"))); + this.addAbility(DisturbAbility.makeBackAbility()); } private ArchiveHaunt(final ArchiveHaunt card) { diff --git a/Mage.Sets/src/mage/cards/a/AvabruckCaretaker.java b/Mage.Sets/src/mage/cards/a/AvabruckCaretaker.java index b34392a4b94..eaec30e14aa 100644 --- a/Mage.Sets/src/mage/cards/a/AvabruckCaretaker.java +++ b/Mage.Sets/src/mage/cards/a/AvabruckCaretaker.java @@ -2,10 +2,10 @@ package mage.cards.a; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.abilities.effects.common.counter.AddCountersTargetEffect; import mage.abilities.keyword.DayboundAbility; import mage.abilities.keyword.HexproofAbility; +import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -35,9 +35,7 @@ public final class AvabruckCaretaker extends CardImpl { // At the beginning of combat on your turn, put two +1/+1 counters on another target creature you control. Ability ability = new BeginningOfCombatTriggeredAbility( - new AddCountersTargetEffect( - CounterType.P1P1.createInstance(2) - ) + new AddCountersTargetEffect(CounterType.P1P1.createInstance(2)) ); ability.addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE_YOU_CONTROL)); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/b/BallistaWielder.java b/Mage.Sets/src/mage/cards/b/BallistaWielder.java index 72f2f8b952a..81c2dd0ad50 100644 --- a/Mage.Sets/src/mage/cards/b/BallistaWielder.java +++ b/Mage.Sets/src/mage/cards/b/BallistaWielder.java @@ -3,7 +3,6 @@ package mage.cards.b; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; -import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.combat.CantBlockTargetEffect; @@ -72,15 +71,15 @@ class BallistaWielderEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(source.getFirstTarget()); + Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); if (permanent == null) { - Player player = game.getPlayer(source.getFirstTarget()); + Player player = game.getPlayer(getTargetPointer().getFirst(game, source)); return player != null && player.damage(1, source, game) > 0; } - if (permanent.damage(1, source, game) > 0) { - game.addEffect(new CantBlockTargetEffect(Duration.EndOfTurn), source); - return true; + if (permanent.damage(1, source, game) <= 0) { + return false; } - return false; + game.addEffect(new CantBlockTargetEffect(Duration.EndOfTurn), source); + return true; } } diff --git a/Mage.Sets/src/mage/cards/b/BenevolentGeist.java b/Mage.Sets/src/mage/cards/b/BenevolentGeist.java index d74cbeb9eb5..69c570a5580 100644 --- a/Mage.Sets/src/mage/cards/b/BenevolentGeist.java +++ b/Mage.Sets/src/mage/cards/b/BenevolentGeist.java @@ -1,10 +1,9 @@ package mage.cards.b; import mage.MageInt; -import mage.abilities.common.PutIntoGraveFromAnywhereSourceAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.CantBeCounteredControlledEffect; -import mage.abilities.effects.common.ExileSourceEffect; +import mage.abilities.keyword.DisturbAbility; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -39,7 +38,7 @@ public final class BenevolentGeist extends CardImpl { ))); // If Benevolent Geist would be put into a graveyard from anywhere, exile it instead. - this.addAbility(new PutIntoGraveFromAnywhereSourceAbility(new ExileSourceEffect().setText("exile it instead"))); + this.addAbility(DisturbAbility.makeBackAbility()); } private BenevolentGeist(final BenevolentGeist card) { diff --git a/Mage.Sets/src/mage/cards/b/BrineboundGift.java b/Mage.Sets/src/mage/cards/b/BrineboundGift.java index 03d465a3ff0..254ed7f3601 100644 --- a/Mage.Sets/src/mage/cards/b/BrineboundGift.java +++ b/Mage.Sets/src/mage/cards/b/BrineboundGift.java @@ -1,12 +1,10 @@ package mage.cards.b; -import mage.abilities.Ability; import mage.abilities.common.BecomesTargetAttachedTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.common.PutIntoGraveFromAnywhereSourceAbility; import mage.abilities.effects.common.AttachEffect; import mage.abilities.effects.common.CreateTokenEffect; -import mage.abilities.effects.common.ExileSourceEffect; +import mage.abilities.keyword.DisturbAbility; import mage.abilities.keyword.EnchantAbility; import mage.abilities.meta.OrTriggeredAbility; import mage.cards.CardImpl; @@ -43,8 +41,7 @@ public final class BrineboundGift extends CardImpl { TargetPermanent auraTarget = new TargetCreaturePermanent(); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); - Ability ability = new EnchantAbility(auraTarget); - this.addAbility(ability); + this.addAbility(new EnchantAbility(auraTarget)); // Whenever Brinebound Gift enters the battlefield or enchanted creature becomes the target of an Aura spell, create a 1/1 white Spirit creature token with flying. this.addAbility(new OrTriggeredAbility(Zone.ALL, new CreateTokenEffect(new SpiritWhiteToken()), false, @@ -53,7 +50,7 @@ public final class BrineboundGift extends CardImpl { new BecomesTargetAttachedTriggeredAbility(null, filter, SetTargetPointer.NONE, false))); // If Brinebound Gift would be put into a graveyard from anywhere, exile it instead. - this.addAbility(new PutIntoGraveFromAnywhereSourceAbility(new ExileSourceEffect().setText("exile it instead"))); + this.addAbility(DisturbAbility.makeBackAbility()); } private BrineboundGift(final BrineboundGift card) { diff --git a/Mage.Sets/src/mage/cards/c/CatlikeCuriosity.java b/Mage.Sets/src/mage/cards/c/CatlikeCuriosity.java index 932763c5175..c741013939f 100644 --- a/Mage.Sets/src/mage/cards/c/CatlikeCuriosity.java +++ b/Mage.Sets/src/mage/cards/c/CatlikeCuriosity.java @@ -1,13 +1,11 @@ package mage.cards.c; -import mage.abilities.Ability; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; -import mage.abilities.common.PutIntoGraveFromAnywhereSourceAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.AttachEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; -import mage.abilities.effects.common.ExileSourceEffect; import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; +import mage.abilities.keyword.DisturbAbility; import mage.abilities.keyword.EnchantAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -36,8 +34,7 @@ public final class CatlikeCuriosity extends CardImpl { TargetPermanent auraTarget = new TargetCreaturePermanent(); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); - Ability ability = new EnchantAbility(auraTarget); - this.addAbility(ability); + this.addAbility(new EnchantAbility(auraTarget)); // Enchanted creature has "Whenever this creature deals combat damage to a player, draw a card." this.addAbility(new SimpleStaticAbility(new GainAbilityAttachedEffect( @@ -47,7 +44,7 @@ public final class CatlikeCuriosity extends CardImpl { ))); // If Catlike Curiosity would be put into a graveyard from anywhere, exile it instead. - this.addAbility(new PutIntoGraveFromAnywhereSourceAbility(new ExileSourceEffect().setText("exile it instead"))); + this.addAbility(DisturbAbility.makeBackAbility()); } private CatlikeCuriosity(final CatlikeCuriosity card) { diff --git a/Mage.Sets/src/mage/cards/c/ChapelShieldgeist.java b/Mage.Sets/src/mage/cards/c/ChapelShieldgeist.java index 5c366277c10..eb0d21c98ca 100644 --- a/Mage.Sets/src/mage/cards/c/ChapelShieldgeist.java +++ b/Mage.Sets/src/mage/cards/c/ChapelShieldgeist.java @@ -1,11 +1,10 @@ package mage.cards.c; import mage.MageInt; -import mage.abilities.common.PutIntoGraveFromAnywhereSourceAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.effects.common.ExileSourceEffect; import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.abilities.keyword.DisturbAbility; import mage.abilities.keyword.FirstStrikeAbility; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.WardAbility; @@ -48,7 +47,7 @@ public final class ChapelShieldgeist extends CardImpl { "counter it unless that player pays 1.)"))); // If Chapel Shieldgeist would be put into a graveyard from anywhere, exile it instead. - this.addAbility(new PutIntoGraveFromAnywhereSourceAbility(new ExileSourceEffect().setText("exile it instead"))); + this.addAbility(DisturbAbility.makeBackAbility()); } private ChapelShieldgeist(final ChapelShieldgeist card) { diff --git a/Mage.Sets/src/mage/cards/c/CleverDistraction.java b/Mage.Sets/src/mage/cards/c/CleverDistraction.java index b38b7721651..751b419f195 100644 --- a/Mage.Sets/src/mage/cards/c/CleverDistraction.java +++ b/Mage.Sets/src/mage/cards/c/CleverDistraction.java @@ -2,12 +2,11 @@ package mage.cards.c; import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; -import mage.abilities.common.PutIntoGraveFromAnywhereSourceAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.AttachEffect; -import mage.abilities.effects.common.ExileSourceEffect; import mage.abilities.effects.common.TapTargetEffect; import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; +import mage.abilities.keyword.DisturbAbility; import mage.abilities.keyword.EnchantAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -46,17 +45,16 @@ public final class CleverDistraction extends CardImpl { TargetPermanent auraTarget = new TargetCreaturePermanent(); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); - Ability ability = new EnchantAbility(auraTarget); - this.addAbility(ability); + this.addAbility(new EnchantAbility(auraTarget)); // Enchanted creature has "Whenever this creature attacks, tap target creature defending player controls." - ability = new AttacksTriggeredAbility(new TapTargetEffect()) + Ability ability = new AttacksTriggeredAbility(new TapTargetEffect()) .setTriggerPhrase("Whenever this creature attacks, "); ability.addTarget(new TargetPermanent(filter)); this.addAbility(new SimpleStaticAbility(new GainAbilityAttachedEffect(ability, AttachmentType.AURA))); // If Clever Distracting would be put into a graveyard from anywhere, exile it instead. - this.addAbility(new PutIntoGraveFromAnywhereSourceAbility(new ExileSourceEffect().setText("exile it instead"))); + this.addAbility(DisturbAbility.makeBackAbility()); } private CleverDistraction(final CleverDistraction card) { diff --git a/Mage.Sets/src/mage/cards/c/CovetousGeist.java b/Mage.Sets/src/mage/cards/c/CovetousGeist.java index fbc4f1faec1..7dd65c1bb4f 100644 --- a/Mage.Sets/src/mage/cards/c/CovetousGeist.java +++ b/Mage.Sets/src/mage/cards/c/CovetousGeist.java @@ -1,9 +1,8 @@ package mage.cards.c; import mage.MageInt; -import mage.abilities.common.PutIntoGraveFromAnywhereSourceAbility; -import mage.abilities.effects.common.ExileSourceEffect; import mage.abilities.keyword.DeathtouchAbility; +import mage.abilities.keyword.DisturbAbility; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -34,7 +33,7 @@ public final class CovetousGeist extends CardImpl { this.addAbility(DeathtouchAbility.getInstance()); // If Covetous Geist would be put into a graveyard from anywhere, exile it instead. - this.addAbility(new PutIntoGraveFromAnywhereSourceAbility(new ExileSourceEffect().setText("exile it instead"))); + this.addAbility(DisturbAbility.makeBackAbility()); } private CovetousGeist(final CovetousGeist card) { diff --git a/Mage.Sets/src/mage/cards/d/DeathbonnetHulk.java b/Mage.Sets/src/mage/cards/d/DeathbonnetHulk.java index 5dabd16cdb4..a796956ec84 100644 --- a/Mage.Sets/src/mage/cards/d/DeathbonnetHulk.java +++ b/Mage.Sets/src/mage/cards/d/DeathbonnetHulk.java @@ -2,12 +2,15 @@ package mage.cards.d; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.effects.OneShotEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.Zone; import mage.counters.CounterType; import mage.game.Game; import mage.game.permanent.Permanent; @@ -33,9 +36,7 @@ public final class DeathbonnetHulk extends CardImpl { this.nightCard = true; // At the beginning of your upkeep, you may exile a card from a graveyard. If a creature card was exiled this way, put a +1/+1 counter on Deathbonnet Hulk. - this.addAbility(new BeginningOfUpkeepTriggeredAbility( - new DeathbonnetHulkEffect() - )); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new DeathbonnetHulkEffect())); } private DeathbonnetHulk(final DeathbonnetHulk card) { diff --git a/Mage.Sets/src/mage/cards/d/DennickPiousApparition.java b/Mage.Sets/src/mage/cards/d/DennickPiousApparition.java index 5559ba3a766..ce39618f468 100644 --- a/Mage.Sets/src/mage/cards/d/DennickPiousApparition.java +++ b/Mage.Sets/src/mage/cards/d/DennickPiousApparition.java @@ -2,9 +2,8 @@ package mage.cards.d; import mage.MageInt; import mage.abilities.common.PutCardIntoGraveFromAnywhereAllTriggeredAbility; -import mage.abilities.common.PutIntoGraveFromAnywhereSourceAbility; -import mage.abilities.effects.common.ExileSourceEffect; import mage.abilities.effects.keyword.InvestigateEffect; +import mage.abilities.keyword.DisturbAbility; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -43,7 +42,7 @@ public final class DennickPiousApparition extends CardImpl { ).setTriggersLimitEachTurn(1).setTriggerPhrase("Whenever one or more creature cards are put into graveyards from anywhere, ")); // If Dennick, Pious Apparition would be put into a graveyard from anywhere, exile it instead. - this.addAbility(new PutIntoGraveFromAnywhereSourceAbility(new ExileSourceEffect().setText("exile it instead"))); + this.addAbility(DisturbAbility.makeBackAbility()); } private DennickPiousApparition(final DennickPiousApparition card) { diff --git a/Mage.Sets/src/mage/cards/d/DepartedSoulkeeper.java b/Mage.Sets/src/mage/cards/d/DepartedSoulkeeper.java index c937f9d2991..2503f1601ba 100644 --- a/Mage.Sets/src/mage/cards/d/DepartedSoulkeeper.java +++ b/Mage.Sets/src/mage/cards/d/DepartedSoulkeeper.java @@ -2,8 +2,7 @@ package mage.cards.d; import mage.MageInt; import mage.abilities.common.CanBlockOnlyFlyingAbility; -import mage.abilities.common.PutIntoGraveFromAnywhereSourceAbility; -import mage.abilities.effects.common.ExileSourceEffect; +import mage.abilities.keyword.DisturbAbility; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -34,7 +33,7 @@ public final class DepartedSoulkeeper extends CardImpl { this.addAbility(new CanBlockOnlyFlyingAbility()); // If Departed Soulkeeper would be put into a graveyard from anywhere, exile it instead. - this.addAbility(new PutIntoGraveFromAnywhereSourceAbility(new ExileSourceEffect().setText("exile it instead"))); + this.addAbility(DisturbAbility.makeBackAbility()); } private DepartedSoulkeeper(final DepartedSoulkeeper card) { diff --git a/Mage.Sets/src/mage/cards/d/DevotedGrafkeeper.java b/Mage.Sets/src/mage/cards/d/DevotedGrafkeeper.java index b54e5ad7092..e16068a08a7 100644 --- a/Mage.Sets/src/mage/cards/d/DevotedGrafkeeper.java +++ b/Mage.Sets/src/mage/cards/d/DevotedGrafkeeper.java @@ -1,20 +1,19 @@ package mage.cards.d; import mage.MageInt; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.common.SpellCastControllerTriggeredAbility; import mage.abilities.effects.common.MillCardsControllerEffect; import mage.abilities.effects.common.TapTargetEffect; import mage.abilities.keyword.DisturbAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.SetTargetPointer; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.StaticFilters; -import mage.game.Game; -import mage.game.events.GameEvent; import mage.target.TargetPermanent; import java.util.UUID; @@ -37,7 +36,12 @@ public final class DevotedGrafkeeper extends CardImpl { this.addAbility(new EntersBattlefieldTriggeredAbility(new MillCardsControllerEffect(2))); // Whenever you cast a spell from your graveyard, tap target creature you don't control. - this.addAbility(new DevotedGrafkeeperTriggeredAbility()); + Ability ability = new SpellCastControllerTriggeredAbility( + Zone.BATTLEFIELD, new TapTargetEffect(), StaticFilters.FILTER_SPELL_A, + false, SetTargetPointer.NONE, Zone.GRAVEYARD + ); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + this.addAbility(ability); // Disturb {1}{W}{U} this.addAbility(new DisturbAbility(this, "{1}{W}{U}")); @@ -52,35 +56,3 @@ public final class DevotedGrafkeeper extends CardImpl { return new DevotedGrafkeeper(this); } } - -class DevotedGrafkeeperTriggeredAbility extends TriggeredAbilityImpl { - - DevotedGrafkeeperTriggeredAbility() { - super(Zone.BATTLEFIELD, new TapTargetEffect(), false); - this.addTarget(new TargetPermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); - } - - private DevotedGrafkeeperTriggeredAbility(DevotedGrafkeeperTriggeredAbility ability) { - super(ability); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.SPELL_CAST; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - return isControlledBy(event.getPlayerId()) && event.getZone() == Zone.GRAVEYARD; - } - - @Override - public DevotedGrafkeeperTriggeredAbility copy() { - return new DevotedGrafkeeperTriggeredAbility(this); - } - - @Override - public String getRule() { - return "Whenever you cast a spell from your graveyard, tap target creature you don't control."; - } -} diff --git a/Mage.Sets/src/mage/cards/d/DorotheasRetribution.java b/Mage.Sets/src/mage/cards/d/DorotheasRetribution.java index f884b920053..688994337d7 100644 --- a/Mage.Sets/src/mage/cards/d/DorotheasRetribution.java +++ b/Mage.Sets/src/mage/cards/d/DorotheasRetribution.java @@ -2,14 +2,13 @@ package mage.cards.d; import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; -import mage.abilities.common.PutIntoGraveFromAnywhereSourceAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.delayed.AtTheEndOfCombatDelayedTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.AttachEffect; -import mage.abilities.effects.common.ExileSourceEffect; import mage.abilities.effects.common.SacrificeTargetEffect; import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; +import mage.abilities.keyword.DisturbAbility; import mage.abilities.keyword.EnchantAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -43,8 +42,7 @@ public final class DorotheasRetribution extends CardImpl { TargetPermanent auraTarget = new TargetCreaturePermanent(); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); - Ability ability = new EnchantAbility(auraTarget); - this.addAbility(ability); + this.addAbility(new EnchantAbility(auraTarget)); // Enchanted creature has "Whenever this creature attacks, create a 4/4 white Spirit creature token with flying that's tapped and attacking. Sacrifice that token at end of combat." this.addAbility(new SimpleStaticAbility(new GainAbilityAttachedEffect( @@ -54,7 +52,7 @@ public final class DorotheasRetribution extends CardImpl { ))); // If Dorothea's Retribution would be put into a graveyard from anywhere, exile it instead. - this.addAbility(new PutIntoGraveFromAnywhereSourceAbility(new ExileSourceEffect().setText("exile it instead"))); + this.addAbility(DisturbAbility.makeBackAbility()); } private DorotheasRetribution(final DorotheasRetribution card) { diff --git a/Mage.Sets/src/mage/cards/d/DrogskolArmaments.java b/Mage.Sets/src/mage/cards/d/DrogskolArmaments.java index e071b99cdb0..dd67d25ed9d 100644 --- a/Mage.Sets/src/mage/cards/d/DrogskolArmaments.java +++ b/Mage.Sets/src/mage/cards/d/DrogskolArmaments.java @@ -1,11 +1,9 @@ package mage.cards.d; -import mage.abilities.Ability; -import mage.abilities.common.PutIntoGraveFromAnywhereSourceAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.AttachEffect; -import mage.abilities.effects.common.ExileSourceEffect; import mage.abilities.effects.common.continuous.BoostEnchantedEffect; +import mage.abilities.keyword.DisturbAbility; import mage.abilities.keyword.EnchantAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -33,14 +31,13 @@ public final class DrogskolArmaments extends CardImpl { TargetPermanent auraTarget = new TargetCreaturePermanent(); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); - Ability ability = new EnchantAbility(auraTarget); - this.addAbility(ability); + this.addAbility(new EnchantAbility(auraTarget)); // Enchanted creature gets +2/+2. this.addAbility(new SimpleStaticAbility(new BoostEnchantedEffect(2, 2))); // If Drogskol Armaments would be put into a graveyard from anywhere, exile it instead. - this.addAbility(new PutIntoGraveFromAnywhereSourceAbility(new ExileSourceEffect().setText("exile it instead"))); + this.addAbility(DisturbAbility.makeBackAbility()); } private DrogskolArmaments(final DrogskolArmaments card) { diff --git a/Mage.Sets/src/mage/cards/e/EdgarMarkovsCoffin.java b/Mage.Sets/src/mage/cards/e/EdgarMarkovsCoffin.java index 2b1d0310f07..36ac4be28bd 100644 --- a/Mage.Sets/src/mage/cards/e/EdgarMarkovsCoffin.java +++ b/Mage.Sets/src/mage/cards/e/EdgarMarkovsCoffin.java @@ -1,18 +1,19 @@ package mage.cards.e; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.SourceHasCounterCondition; +import mage.abilities.decorator.ConditionalOneShotEffect; import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.RemoveAllCountersSourceEffect; +import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.SuperType; import mage.counters.CounterType; -import mage.game.Game; -import mage.game.permanent.Permanent; import mage.game.permanent.token.EdgarMarkovsCoffinVampireToken; import java.util.UUID; @@ -22,6 +23,8 @@ import java.util.UUID; */ public final class EdgarMarkovsCoffin extends CardImpl { + private static final Condition condition = new SourceHasCounterCondition(CounterType.BLOODLINE, 3); + public EdgarMarkovsCoffin(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, ""); @@ -31,13 +34,12 @@ public final class EdgarMarkovsCoffin extends CardImpl { this.nightCard = true; // At the beginning of your upkeep, create a 1/1 white and black Vampire creature token with lifelink and put a bloodline counter on Edgar Markov's Coffin. Then if there are three or more bloodline counters on it, remove those counters and transform it. - Ability ability = new BeginningOfUpkeepTriggeredAbility( - new CreateTokenEffect(new EdgarMarkovsCoffinVampireToken()) - ); - ability.addEffect(new AddCountersSourceEffect( - CounterType.BLOODLINE.createInstance() - ).concatBy("and")); - ability.addEffect(new EdgarMarkovsCoffinEffect()); + Ability ability = new BeginningOfUpkeepTriggeredAbility(new CreateTokenEffect(new EdgarMarkovsCoffinVampireToken())); + ability.addEffect(new AddCountersSourceEffect(CounterType.BLOODLINE.createInstance()).concatBy("and")); + ability.addEffect(new ConditionalOneShotEffect( + new RemoveAllCountersSourceEffect(CounterType.BLOODLINE), condition, + "Then if there are three or more bloodline counters on it, remove those counters and transform it" + ).addEffect(new TransformSourceEffect())); this.addAbility(ability); } @@ -50,35 +52,3 @@ public final class EdgarMarkovsCoffin extends CardImpl { return new EdgarMarkovsCoffin(this); } } - -class EdgarMarkovsCoffinEffect extends OneShotEffect { - - EdgarMarkovsCoffinEffect() { - super(Outcome.Benefit); - staticText = "Then if there are three or more bloodline counters on it, remove those counters and transform it"; - } - - private EdgarMarkovsCoffinEffect(final EdgarMarkovsCoffinEffect effect) { - super(effect); - } - - @Override - public EdgarMarkovsCoffinEffect copy() { - return new EdgarMarkovsCoffinEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = source.getSourcePermanentIfItStillExists(game); - if (permanent == null) { - return false; - } - int counters = permanent.getCounters(game).getCount(CounterType.BLOODLINE); - if (counters < 3) { - return false; - } - permanent.removeCounters(CounterType.BLOODLINE.createInstance(counters), source, game); - permanent.transform(source, game); - return true; - } -} diff --git a/Mage.Sets/src/mage/cards/g/GenerousSoul.java b/Mage.Sets/src/mage/cards/g/GenerousSoul.java index d8516e9c39a..d0d85e6ad79 100644 --- a/Mage.Sets/src/mage/cards/g/GenerousSoul.java +++ b/Mage.Sets/src/mage/cards/g/GenerousSoul.java @@ -1,8 +1,7 @@ package mage.cards.g; import mage.MageInt; -import mage.abilities.common.PutIntoGraveFromAnywhereSourceAbility; -import mage.abilities.effects.common.ExileSourceEffect; +import mage.abilities.keyword.DisturbAbility; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.VigilanceAbility; import mage.cards.CardImpl; @@ -29,7 +28,7 @@ public final class GenerousSoul extends CardImpl { this.addAbility(VigilanceAbility.getInstance()); // If Generous Soul would be put into a graveyard from anywhere, exile it instead. - this.addAbility(new PutIntoGraveFromAnywhereSourceAbility(new ExileSourceEffect().setText("exile it instead"))); + this.addAbility(DisturbAbility.makeBackAbility()); } private GenerousSoul(final GenerousSoul card) { diff --git a/Mage.Sets/src/mage/cards/g/GhastlyMimicry.java b/Mage.Sets/src/mage/cards/g/GhastlyMimicry.java index aaa96a259bd..85dce72078a 100644 --- a/Mage.Sets/src/mage/cards/g/GhastlyMimicry.java +++ b/Mage.Sets/src/mage/cards/g/GhastlyMimicry.java @@ -1,13 +1,12 @@ package mage.cards.g; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; -import mage.abilities.common.PutIntoGraveFromAnywhereSourceAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.AttachEffect; import mage.abilities.effects.common.CreateTokenCopyTargetEffect; -import mage.abilities.effects.common.ExileSourceEffect; +import mage.abilities.keyword.DisturbAbility; import mage.abilities.keyword.EnchantAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -37,16 +36,13 @@ public final class GhastlyMimicry extends CardImpl { TargetPermanent auraTarget = new TargetCreaturePermanent(); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); - Ability ability = new EnchantAbility(auraTarget); - this.addAbility(ability); + this.addAbility(new EnchantAbility(auraTarget)); // At the beginning of your upkeep, create a token that's a copy of enchanted creature, except it's a Spirit in addition to its other types. - this.addAbility(new BeginningOfUpkeepTriggeredAbility( - new GhastlyMimicryEffect() - )); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new GhastlyMimicryEffect())); // If Ghastly Mimicry would be put into a graveyard from anywhere, exile it instead. - this.addAbility(new PutIntoGraveFromAnywhereSourceAbility(new ExileSourceEffect().setText("exile it instead"))); + this.addAbility(DisturbAbility.makeBackAbility()); } private GhastlyMimicry(final GhastlyMimicry card) { diff --git a/Mage.Sets/src/mage/cards/g/GhostlyCastigator.java b/Mage.Sets/src/mage/cards/g/GhostlyCastigator.java index 44868f2dd40..bb9f5f62e56 100644 --- a/Mage.Sets/src/mage/cards/g/GhostlyCastigator.java +++ b/Mage.Sets/src/mage/cards/g/GhostlyCastigator.java @@ -3,9 +3,8 @@ package mage.cards.g; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.common.PutIntoGraveFromAnywhereSourceAbility; -import mage.abilities.effects.common.ExileSourceEffect; import mage.abilities.effects.common.ShuffleIntoLibraryTargetEffect; +import mage.abilities.keyword.DisturbAbility; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -38,7 +37,7 @@ public final class GhostlyCastigator extends CardImpl { this.addAbility(ability); // If Ghostly Castigator would be put into a graveyard from anywhere, exile it instead. - this.addAbility(new PutIntoGraveFromAnywhereSourceAbility(new ExileSourceEffect().setText("exile it instead"))); + this.addAbility(DisturbAbility.makeBackAbility()); } private GhostlyCastigator(final GhostlyCastigator card) { diff --git a/Mage.Sets/src/mage/cards/g/GutterShortcut.java b/Mage.Sets/src/mage/cards/g/GutterShortcut.java index 179bfeb8eb2..bfb716b5d02 100644 --- a/Mage.Sets/src/mage/cards/g/GutterShortcut.java +++ b/Mage.Sets/src/mage/cards/g/GutterShortcut.java @@ -1,13 +1,12 @@ package mage.cards.g; import mage.abilities.Ability; -import mage.abilities.common.PutIntoGraveFromAnywhereSourceAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.Condition; import mage.abilities.decorator.ConditionalRestrictionEffect; import mage.abilities.effects.common.AttachEffect; -import mage.abilities.effects.common.ExileSourceEffect; import mage.abilities.effects.common.combat.CantBeBlockedAttachedEffect; +import mage.abilities.keyword.DisturbAbility; import mage.abilities.keyword.EnchantAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -38,8 +37,7 @@ public final class GutterShortcut extends CardImpl { TargetPermanent auraTarget = new TargetCreaturePermanent(); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); - Ability ability = new EnchantAbility(auraTarget); - this.addAbility(ability); + this.addAbility(new EnchantAbility(auraTarget)); // Enchanted creature can't be blocked as long as it's attacking alone. this.addAbility(new SimpleStaticAbility(new ConditionalRestrictionEffect( @@ -48,7 +46,7 @@ public final class GutterShortcut extends CardImpl { ))); // If Gutter Shortcut would be put into a graveyard from anywhere, exile it instead. - this.addAbility(new PutIntoGraveFromAnywhereSourceAbility(new ExileSourceEffect().setText("exile it instead"))); + this.addAbility(DisturbAbility.makeBackAbility()); } private GutterShortcut(final GutterShortcut card) { diff --git a/Mage.Sets/src/mage/cards/h/HeirloomMirror.java b/Mage.Sets/src/mage/cards/h/HeirloomMirror.java index 4d71dcec837..69323e07bc4 100644 --- a/Mage.Sets/src/mage/cards/h/HeirloomMirror.java +++ b/Mage.Sets/src/mage/cards/h/HeirloomMirror.java @@ -2,21 +2,23 @@ package mage.cards.h; import mage.abilities.Ability; import mage.abilities.common.ActivateAsSorceryActivatedAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.SourceHasCounterCondition; import mage.abilities.costs.common.DiscardCardCost; import mage.abilities.costs.common.PayLifeCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.MillCardsControllerEffect; +import mage.abilities.effects.common.RemoveAllCountersSourceEffect; import mage.abilities.effects.common.TransformSourceEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; import mage.counters.CounterType; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.players.Player; import java.util.UUID; @@ -25,6 +27,8 @@ import java.util.UUID; */ public final class HeirloomMirror extends CardImpl { + private static final Condition condition = new SourceHasCounterCondition(CounterType.RITUAL, 3); + public HeirloomMirror(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}{B}"); @@ -32,10 +36,16 @@ public final class HeirloomMirror extends CardImpl { // {1}, {T}, Pay 1 life, Discard a card: Draw a card, mill a card, then put a ritual counter on Heirloom Mirror. Then if it has 3 or more ritual counters on it, remove them and transform it. Activate only as a sorcery. this.addAbility(new TransformAbility()); - Ability ability = new ActivateAsSorceryActivatedAbility(new HeirloomMirrorEffect(), new GenericManaCost(1)); + Ability ability = new ActivateAsSorceryActivatedAbility(new DrawCardSourceControllerEffect(1), new GenericManaCost(1)); ability.addCost(new TapSourceCost()); ability.addCost(new PayLifeCost(1)); ability.addCost(new DiscardCardCost()); + ability.addEffect(new MillCardsControllerEffect(1).concatBy(",")); + ability.addEffect(new AddCountersSourceEffect(CounterType.RITUAL.createInstance()).concatBy(", then")); + ability.addEffect(new ConditionalOneShotEffect( + new RemoveAllCountersSourceEffect(CounterType.RITUAL), condition, + "Then if it has 3 or more ritual counters on it, remove them and transform it" + ).addEffect(new TransformSourceEffect())); this.addAbility(ability); } @@ -48,40 +58,3 @@ public final class HeirloomMirror extends CardImpl { return new HeirloomMirror(this); } } - -class HeirloomMirrorEffect extends OneShotEffect { - - HeirloomMirrorEffect() { - super(Outcome.Benefit); - staticText = "draw a card, mill a card, then put a ritual counter on {this}. " + - "Then if it has three or more ritual counters on it, remove them and transform it"; - } - - private HeirloomMirrorEffect(final HeirloomMirrorEffect effect) { - super(effect); - } - - @Override - public HeirloomMirrorEffect copy() { - return new HeirloomMirrorEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - Permanent permanent = source.getSourcePermanentIfItStillExists(game); - if (player == null || permanent == null) { - return false; - } - player.drawCards(1, source, game); - player.millCards(1, source, game); - permanent.addCounters(CounterType.RITUAL.createInstance(), source.getControllerId(), source, game); - int counters = permanent.getCounters(game).getCount(CounterType.RITUAL); - if (counters < 3) { - return true; - } - permanent.removeCounters(CounterType.RITUAL.createInstance(counters), source, game); - new TransformSourceEffect().apply(game, source); - return true; - } -} diff --git a/Mage.Sets/src/mage/cards/h/HookHauntDrifter.java b/Mage.Sets/src/mage/cards/h/HookHauntDrifter.java index 20484b801dd..b63a9bb5b09 100644 --- a/Mage.Sets/src/mage/cards/h/HookHauntDrifter.java +++ b/Mage.Sets/src/mage/cards/h/HookHauntDrifter.java @@ -1,8 +1,7 @@ package mage.cards.h; import mage.MageInt; -import mage.abilities.common.PutIntoGraveFromAnywhereSourceAbility; -import mage.abilities.effects.common.ExileSourceEffect; +import mage.abilities.keyword.DisturbAbility; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -29,7 +28,7 @@ public final class HookHauntDrifter extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // If Hook-Haunt Drifter would be put into a graveyard from anywhere, exile it instead. - this.addAbility(new PutIntoGraveFromAnywhereSourceAbility(new ExileSourceEffect().setText("exile it instead"))); + this.addAbility(DisturbAbility.makeBackAbility()); } private HookHauntDrifter(final HookHauntDrifter card) { diff --git a/Mage.Sets/src/mage/cards/h/HostileHostel.java b/Mage.Sets/src/mage/cards/h/HostileHostel.java index 7b7e4ae7012..8e8a5a156c4 100644 --- a/Mage.Sets/src/mage/cards/h/HostileHostel.java +++ b/Mage.Sets/src/mage/cards/h/HostileHostel.java @@ -2,32 +2,33 @@ package mage.cards.h; import mage.abilities.Ability; import mage.abilities.common.ActivateAsSorceryActivatedAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.SourceHasCounterCondition; import mage.abilities.costs.common.SacrificeTargetCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.common.RemoveAllCountersSourceEffect; +import mage.abilities.effects.common.TransformSourceEffect; +import mage.abilities.effects.common.UntapSourceEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.keyword.TransformAbility; import mage.abilities.mana.ColorlessManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.Zone; import mage.counters.CounterType; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.players.Player; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.filter.StaticFilters; import java.util.UUID; -import mage.filter.StaticFilters; - /** * @author LePwnerer */ public final class HostileHostel extends CardImpl { + private static final Condition condition = new SourceHasCounterCondition(CounterType.SOUL, 3); + public HostileHostel(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); this.secondSideCardClazz = mage.cards.c.CreepingInn.class; @@ -37,9 +38,13 @@ public final class HostileHostel extends CardImpl { // {1}, {T}, Sacrifice a creature: Put a soul counter on Hostile Hostel. Then if there are three or more soul counters on it, remove those counters, transform it, then untap it. Activate only as a sorcery. this.addAbility(new TransformAbility()); - Ability ability = new ActivateAsSorceryActivatedAbility(Zone.BATTLEFIELD, new HostileHostelEffect(), new ManaCostsImpl<>("{1}")); + Ability ability = new ActivateAsSorceryActivatedAbility(new AddCountersSourceEffect(CounterType.SOUL.createInstance()), new ManaCostsImpl<>("{1}")); ability.addCost(new TapSourceCost()); ability.addCost(new SacrificeTargetCost(StaticFilters.FILTER_PERMANENT_CREATURE)); + ability.addEffect(new ConditionalOneShotEffect( + new RemoveAllCountersSourceEffect(CounterType.SOUL), condition, "Then if there are three " + + "or more soul counters on it, remove those counters, transform it, then untap it" + ).addEffect(new TransformSourceEffect()).addEffect(new UntapSourceEffect())); this.addAbility(ability); } @@ -52,38 +57,3 @@ public final class HostileHostel extends CardImpl { return new HostileHostel(this); } } - -class HostileHostelEffect extends OneShotEffect { - - HostileHostelEffect() { - super(Outcome.Benefit); - this.staticText = "Put a soul counter on {this}. " + - "Then if there are three or more soul counters on it, remove those counters, transform it, then untap it."; - } - - HostileHostelEffect(final mage.cards.h.HostileHostelEffect effect) { - super(effect); - } - - @Override - public mage.cards.h.HostileHostelEffect copy() { - return new mage.cards.h.HostileHostelEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - Permanent permanent = source.getSourcePermanentIfItStillExists(game); - if (permanent != null && player != null) { - permanent.addCounters(CounterType.SOUL.createInstance(), source.getControllerId(), source, game); - int counters = permanent.getCounters(game).getCount(CounterType.SOUL); - if (counters > 2) { - permanent.removeCounters(CounterType.SOUL.getName(), counters, source, game); - permanent.transform(source, game); - permanent.untap(game); - } - return true; - } - return false; - } -} diff --git a/Mage.Sets/src/mage/cards/i/InheritedFiend.java b/Mage.Sets/src/mage/cards/i/InheritedFiend.java index 79afa9126fc..22343bddfb5 100644 --- a/Mage.Sets/src/mage/cards/i/InheritedFiend.java +++ b/Mage.Sets/src/mage/cards/i/InheritedFiend.java @@ -12,9 +12,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.counters.CounterType; -import mage.filter.FilterCard; import mage.filter.StaticFilters; -import mage.filter.common.FilterCreatureCard; import mage.target.common.TargetCardInGraveyard; import java.util.UUID; diff --git a/Mage.Sets/src/mage/cards/i/InnocentTraveler.java b/Mage.Sets/src/mage/cards/i/InnocentTraveler.java index 6dc1f24151b..76e0b94422b 100644 --- a/Mage.Sets/src/mage/cards/i/InnocentTraveler.java +++ b/Mage.Sets/src/mage/cards/i/InnocentTraveler.java @@ -2,9 +2,9 @@ package mage.cards.i; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.keyword.TransformAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -34,9 +34,7 @@ public final class InnocentTraveler extends CardImpl { // At the beginning of your upkeep, any opponent may sacrifice a creature. If no one does, transform Innocent Traveler. this.addAbility(new TransformAbility()); - this.addAbility(new BeginningOfUpkeepTriggeredAbility( - new InnocentTravelerEffect() - )); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new InnocentTravelerEffect())); } private InnocentTraveler(final InnocentTraveler card) { diff --git a/Mage.Sets/src/mage/cards/k/KatildasRisingDawn.java b/Mage.Sets/src/mage/cards/k/KatildasRisingDawn.java index ff48034a4d7..dc2907dacea 100644 --- a/Mage.Sets/src/mage/cards/k/KatildasRisingDawn.java +++ b/Mage.Sets/src/mage/cards/k/KatildasRisingDawn.java @@ -1,20 +1,15 @@ package mage.cards.k; import mage.abilities.Ability; -import mage.abilities.common.PutIntoGraveFromAnywhereSourceAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; import mage.abilities.effects.common.AttachEffect; -import mage.abilities.effects.common.ExileSourceEffect; import mage.abilities.effects.common.continuous.BoostEquippedEffect; import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; import mage.abilities.hint.Hint; import mage.abilities.hint.ValueHint; -import mage.abilities.keyword.EnchantAbility; -import mage.abilities.keyword.FlyingAbility; -import mage.abilities.keyword.LifelinkAbility; -import mage.abilities.keyword.ProtectionAbility; +import mage.abilities.keyword.*; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; @@ -75,7 +70,7 @@ public final class KatildasRisingDawn extends CardImpl { this.addAbility(ability.addHint(hint)); // If Katilda's Rising Dawn would be put into a graveyard from anywhere, exile it instead. - this.addAbility(new PutIntoGraveFromAnywhereSourceAbility(new ExileSourceEffect().setText("exile it instead"))); + this.addAbility(DisturbAbility.makeBackAbility()); } private KatildasRisingDawn(final KatildasRisingDawn card) { diff --git a/Mage.Sets/src/mage/cards/l/LanternsLift.java b/Mage.Sets/src/mage/cards/l/LanternsLift.java index f3a2a2f87d3..7cb53c9d83e 100644 --- a/Mage.Sets/src/mage/cards/l/LanternsLift.java +++ b/Mage.Sets/src/mage/cards/l/LanternsLift.java @@ -1,12 +1,11 @@ package mage.cards.l; import mage.abilities.Ability; -import mage.abilities.common.PutIntoGraveFromAnywhereSourceAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.AttachEffect; -import mage.abilities.effects.common.ExileSourceEffect; import mage.abilities.effects.common.continuous.BoostEnchantedEffect; import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; +import mage.abilities.keyword.DisturbAbility; import mage.abilities.keyword.EnchantAbility; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; @@ -33,11 +32,10 @@ public final class LanternsLift extends CardImpl { TargetPermanent auraTarget = new TargetCreaturePermanent(); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); - Ability ability = new EnchantAbility(auraTarget); - this.addAbility(ability); + this.addAbility(new EnchantAbility(auraTarget)); // Enchanted creature gets +1/+1 and has flying. - ability = new SimpleStaticAbility(new BoostEnchantedEffect( + Ability ability = new SimpleStaticAbility(new BoostEnchantedEffect( 1, 1, Duration.WhileOnBattlefield )); ability.addEffect(new GainAbilityAttachedEffect( @@ -46,7 +44,7 @@ public final class LanternsLift extends CardImpl { this.addAbility(ability); // If Lanterns' Lift would be put into a graveyard from anywhere, exile it instead. - this.addAbility(new PutIntoGraveFromAnywhereSourceAbility(new ExileSourceEffect().setText("exile it instead"))); + this.addAbility(DisturbAbility.makeBackAbility()); } private LanternsLift(final LanternsLift card) { diff --git a/Mage.Sets/src/mage/cards/l/LuminousPhantom.java b/Mage.Sets/src/mage/cards/l/LuminousPhantom.java index 7710801da8d..123b2665457 100644 --- a/Mage.Sets/src/mage/cards/l/LuminousPhantom.java +++ b/Mage.Sets/src/mage/cards/l/LuminousPhantom.java @@ -2,9 +2,8 @@ package mage.cards.l; import mage.MageInt; import mage.abilities.common.LeavesBattlefieldAllTriggeredAbility; -import mage.abilities.common.PutIntoGraveFromAnywhereSourceAbility; -import mage.abilities.effects.common.ExileSourceEffect; import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.keyword.DisturbAbility; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -36,7 +35,7 @@ public final class LuminousPhantom extends CardImpl { this.addAbility(new LeavesBattlefieldAllTriggeredAbility(new GainLifeEffect(1), StaticFilters.FILTER_ANOTHER_CREATURE_YOU_CONTROL)); // If Luminous Phantom would be put into a graveyard from anywhere, exile it instead. - this.addAbility(new PutIntoGraveFromAnywhereSourceAbility(new ExileSourceEffect().setText("exile it instead"))); + this.addAbility(DisturbAbility.makeBackAbility()); } private LuminousPhantom(final LuminousPhantom card) { diff --git a/Mage.Sets/src/mage/cards/m/MorningApparition.java b/Mage.Sets/src/mage/cards/m/MorningApparition.java index 3b04cf354d8..22db5e1d308 100644 --- a/Mage.Sets/src/mage/cards/m/MorningApparition.java +++ b/Mage.Sets/src/mage/cards/m/MorningApparition.java @@ -1,8 +1,7 @@ package mage.cards.m; import mage.MageInt; -import mage.abilities.common.PutIntoGraveFromAnywhereSourceAbility; -import mage.abilities.effects.common.ExileSourceEffect; +import mage.abilities.keyword.DisturbAbility; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.VigilanceAbility; import mage.cards.CardImpl; @@ -34,7 +33,7 @@ public final class MorningApparition extends CardImpl { this.addAbility(VigilanceAbility.getInstance()); // If Morning Apparition would be put into a graveyard from anywhere, exile it instead. - this.addAbility(new PutIntoGraveFromAnywhereSourceAbility(new ExileSourceEffect().setText("exile it instead"))); + this.addAbility(DisturbAbility.makeBackAbility()); } private MorningApparition(final MorningApparition card) { diff --git a/Mage.Sets/src/mage/cards/p/PanickedBystander.java b/Mage.Sets/src/mage/cards/p/PanickedBystander.java index 19a0bc1f76d..fc914a322bb 100644 --- a/Mage.Sets/src/mage/cards/p/PanickedBystander.java +++ b/Mage.Sets/src/mage/cards/p/PanickedBystander.java @@ -1,16 +1,20 @@ package mage.cards.p; import mage.MageInt; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.abilities.common.DiesThisOrAnotherTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.YouGainedLifeCondition; +import mage.abilities.dynamicvalue.common.ControllerGainedLifeCount; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.ComparisonType; +import mage.constants.SubType; +import mage.constants.TargetController; import mage.filter.StaticFilters; import mage.watchers.common.PlayerGainedLifeWatcher; @@ -42,7 +46,7 @@ public final class PanickedBystander extends CardImpl { this.addAbility(new BeginningOfEndStepTriggeredAbility( TargetController.YOU, new TransformSourceEffect(), false, condition - ), new PlayerGainedLifeWatcher()); + ).addHint(ControllerGainedLifeCount.getHint()), new PlayerGainedLifeWatcher()); } private PanickedBystander(final PanickedBystander card) { diff --git a/Mage.Sets/src/mage/cards/r/RunoStromkirk.java b/Mage.Sets/src/mage/cards/r/RunoStromkirk.java index 1dd67837199..158b4130dae 100644 --- a/Mage.Sets/src/mage/cards/r/RunoStromkirk.java +++ b/Mage.Sets/src/mage/cards/r/RunoStromkirk.java @@ -2,17 +2,20 @@ package mage.cards.r; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.PutOnLibraryTargetEffect; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.TransformAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.cards.CardsImpl; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.SuperType; import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; @@ -46,9 +49,7 @@ public final class RunoStromkirk extends CardImpl { // At the beginning of your upkeep, look at the top card of your library. You may reveal that card. If a creature card with mana value 6 or greater is revealed this way, transform Runo Stromkirk. this.addAbility(new TransformAbility()); - this.addAbility(new BeginningOfUpkeepTriggeredAbility( - new RunoStromkirkEffect() - )); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new RunoStromkirkEffect())); } private RunoStromkirk(final RunoStromkirk card) { diff --git a/Mage.Sets/src/mage/cards/s/SinnersJudgment.java b/Mage.Sets/src/mage/cards/s/SinnersJudgment.java index 608c412c013..2014fb6d7d0 100644 --- a/Mage.Sets/src/mage/cards/s/SinnersJudgment.java +++ b/Mage.Sets/src/mage/cards/s/SinnersJudgment.java @@ -1,12 +1,12 @@ package mage.cards.s; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; -import mage.abilities.common.PutIntoGraveFromAnywhereSourceAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.AttachEffect; -import mage.abilities.effects.common.ExileSourceEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.keyword.DisturbAbility; import mage.abilities.keyword.EnchantAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -15,9 +15,9 @@ import mage.constants.SubType; import mage.counters.CounterType; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.players.Player; import mage.target.TargetPlayer; +import java.util.Optional; import java.util.UUID; /** @@ -37,16 +37,15 @@ public final class SinnersJudgment extends CardImpl { TargetPlayer auraTarget = new TargetPlayer(); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); - Ability ability = new EnchantAbility(auraTarget); - this.addAbility(ability); + this.addAbility(new EnchantAbility(auraTarget)); // At the beginning of your upkeep, put a judgment counter on Sinner's Judgment. Then if there are three or more judgment counters on it, enchanted player loses the game. - this.addAbility(new BeginningOfUpkeepTriggeredAbility( - new SinnersJudgmentEffect() - )); + Ability ability = new BeginningOfUpkeepTriggeredAbility(new AddCountersSourceEffect(CounterType.JUDGMENT.createInstance())); + ability.addEffect(new SinnersJudgmentEffect()); + this.addAbility(ability); // If Sinner's Judgment would be put into a graveyard from anywhere, exile it instead. - this.addAbility(new PutIntoGraveFromAnywhereSourceAbility(new ExileSourceEffect().setText("exile it instead"))); + this.addAbility(DisturbAbility.makeBackAbility()); } private SinnersJudgment(final SinnersJudgment card) { @@ -63,8 +62,7 @@ class SinnersJudgmentEffect extends OneShotEffect { SinnersJudgmentEffect() { super(Outcome.Benefit); - staticText = "put a judgment counter on {this}. Then if there are three " + - "or more judgment counters on it, enchanted player loses the game"; + staticText = "Then if there are three or more judgment counters on it, enchanted player loses the game"; } private SinnersJudgmentEffect(final SinnersJudgmentEffect effect) { @@ -78,18 +76,15 @@ class SinnersJudgmentEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Permanent permanent = source.getSourcePermanentIfItStillExists(game); - if (permanent == null) { - return false; - } - permanent.addCounters(CounterType.JUDGMENT.createInstance(), source, game); - if (permanent.getCounters(game).getCount(CounterType.JUDGMENT) < 3) { - return true; - } - Player player = game.getPlayer(permanent.getAttachedTo()); - if (player != null) { - player.lost(game); - } - return true; + return Optional + .ofNullable(source.getSourcePermanentOrLKI(game)) + .filter(permanent -> permanent.getCounters(game).getCount(CounterType.JUDGMENT) >= 3) + .map(Permanent::getAttachedTo) + .map(game::getPlayer) + .filter(player -> { + player.lost(game); + return true; + }) + .isPresent(); } } diff --git a/Mage.Sets/src/mage/cards/s/SmolderingEgg.java b/Mage.Sets/src/mage/cards/s/SmolderingEgg.java index 7ea48b98e7a..7add8019e87 100644 --- a/Mage.Sets/src/mage/cards/s/SmolderingEgg.java +++ b/Mage.Sets/src/mage/cards/s/SmolderingEgg.java @@ -1,22 +1,31 @@ package mage.cards.s; import mage.MageInt; +import mage.Mana; import mage.abilities.Ability; +import mage.abilities.AbilityImpl; import mage.abilities.common.SpellCastControllerTriggeredAbility; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.SourceHasCounterCondition; +import mage.abilities.costs.mana.ManaCost; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.RemoveAllCountersSourceEffect; import mage.abilities.effects.common.TransformSourceEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.keyword.DefenderAbility; import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.SubType; import mage.counters.CounterType; import mage.filter.StaticFilters; import mage.game.Game; -import mage.game.permanent.Permanent; import mage.game.stack.Spell; -import mage.watchers.common.ManaPaidSourceWatcher; +import java.util.Optional; import java.util.UUID; /** @@ -24,6 +33,8 @@ import java.util.UUID; */ public final class SmolderingEgg extends CardImpl { + private static final Condition condition = new SourceHasCounterCondition(CounterType.EMBER, 7); + public SmolderingEgg(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}"); @@ -38,10 +49,16 @@ public final class SmolderingEgg extends CardImpl { // Whenever you cast an instant or sorcery spell, put a number of ember counters on Smoldering Egg equal to the amount of mana spent to cast that spell. Then if Smoldering Egg has seven or more ember counters on it, remove them and transform Smoldering Egg. this.addAbility(new TransformAbility()); - this.addAbility(new SpellCastControllerTriggeredAbility( - new SmolderingEggEffect(), StaticFilters.FILTER_SPELL_AN_INSTANT_OR_SORCERY, - false, SetTargetPointer.SPELL - )); + Ability ability = new SpellCastControllerTriggeredAbility( + new AddCountersSourceEffect(CounterType.EMBER.createInstance(), SmolderingEggValue.instance) + .setText("put a number of ember counters on {this} equal to the amount of mana spent to cast that spell"), + StaticFilters.FILTER_SPELL_AN_INSTANT_OR_SORCERY, false + ); + ability.addEffect(new ConditionalOneShotEffect( + new RemoveAllCountersSourceEffect(CounterType.EMBER), condition, + "Then if {this} has seven or more ember counters on it, remove them and transform {this}" + ).addEffect(new TransformSourceEffect())); + this.addAbility(ability); } private SmolderingEgg(final SmolderingEgg card) { @@ -54,43 +71,32 @@ public final class SmolderingEgg extends CardImpl { } } -class SmolderingEggEffect extends OneShotEffect { +enum SmolderingEggValue implements DynamicValue { + instance; - SmolderingEggEffect() { - super(Outcome.Benefit); - staticText = "put a number of ember counters on {this} equal to the amount of mana spent to cast that spell. " + - "Then if {this} has seven or more ember counters on it, remove them and transform {this}"; - } - - private SmolderingEggEffect(final SmolderingEggEffect effect) { - super(effect); + @Override + public int calculate(Game game, Ability sourceAbility, Effect effect) { + return Optional + .ofNullable((Spell) effect.getValue("spellCast")) + .map(Spell::getSpellAbility) + .map(AbilityImpl::getManaCostsToPay) + .map(ManaCost::getUsedManaToPay) + .map(Mana::count) + .orElse(0); } @Override - public SmolderingEggEffect copy() { - return new SmolderingEggEffect(this); + public SmolderingEggValue copy() { + return this; } @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = source.getSourcePermanentIfItStillExists(game); - if (permanent == null) { - return false; - } - Spell spell = (Spell) getValue("spellCast"); - if (spell != null) { - permanent.addCounters( - CounterType.EMBER.createInstance( - ManaPaidSourceWatcher.getTotalPaid(spell.getId(), game) - ), source.getControllerId(), source, game - ); - } - int counters = permanent.getCounters(game).getCount(CounterType.EMBER); - if (counters < 7) { - return true; - } - permanent.removeCounters(CounterType.EMBER.createInstance(counters), source, game); - new TransformSourceEffect().apply(game, source); - return true; + public String getMessage() { + return ""; + } + + @Override + public String toString() { + return "1"; } } diff --git a/Mage.Sets/src/mage/cards/s/SpectralBinding.java b/Mage.Sets/src/mage/cards/s/SpectralBinding.java index 2e1e000c303..89d2a0f443a 100644 --- a/Mage.Sets/src/mage/cards/s/SpectralBinding.java +++ b/Mage.Sets/src/mage/cards/s/SpectralBinding.java @@ -1,11 +1,9 @@ package mage.cards.s; -import mage.abilities.Ability; -import mage.abilities.common.PutIntoGraveFromAnywhereSourceAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.AttachEffect; -import mage.abilities.effects.common.ExileSourceEffect; import mage.abilities.effects.common.continuous.BoostEnchantedEffect; +import mage.abilities.keyword.DisturbAbility; import mage.abilities.keyword.EnchantAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -33,14 +31,13 @@ public final class SpectralBinding extends CardImpl { TargetPermanent auraTarget = new TargetCreaturePermanent(); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); - Ability ability = new EnchantAbility(auraTarget); - this.addAbility(ability); + this.addAbility(new EnchantAbility(auraTarget)); // Enchanted creature gets -2/-0. this.addAbility(new SimpleStaticAbility(new BoostEnchantedEffect(-2, 0))); // If Spectral Binding would be put into a graveyard from anywhere, exile it instead. - this.addAbility(new PutIntoGraveFromAnywhereSourceAbility(new ExileSourceEffect().setText("exile it instead"))); + this.addAbility(DisturbAbility.makeBackAbility()); } private SpectralBinding(final SpectralBinding card) { diff --git a/Mage.Sets/src/mage/cards/s/StranglingGrasp.java b/Mage.Sets/src/mage/cards/s/StranglingGrasp.java index 443a465ff54..e8b2b3ab4ab 100644 --- a/Mage.Sets/src/mage/cards/s/StranglingGrasp.java +++ b/Mage.Sets/src/mage/cards/s/StranglingGrasp.java @@ -1,10 +1,10 @@ package mage.cards.s; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.AttachEffect; import mage.abilities.keyword.EnchantAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -14,11 +14,14 @@ import mage.constants.TargetController; import mage.filter.FilterPermanent; import mage.filter.common.FilterCreatureOrPlaneswalkerPermanent; import mage.filter.common.FilterNonlandPermanent; +import mage.filter.predicate.permanent.CanBeSacrificedPredicate; +import mage.game.Controllable; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.TargetPermanent; +import java.util.Optional; import java.util.UUID; /** @@ -44,13 +47,10 @@ public final class StranglingGrasp extends CardImpl { TargetPermanent auraTarget = new TargetPermanent(filter); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); - Ability ability = new EnchantAbility(auraTarget); - this.addAbility(ability); + this.addAbility(new EnchantAbility(auraTarget)); // At the beginning of your upkeep, enchanted permanent's controller sacrifices a nonland permanent and loses 1 life. - this.addAbility(new BeginningOfUpkeepTriggeredAbility( - new StranglingGraspEffect() - )); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new StranglingGraspEffect())); } private StranglingGrasp(final StranglingGrasp card) { @@ -69,6 +69,7 @@ class StranglingGraspEffect extends OneShotEffect { static { filter.add(TargetController.YOU.getControllerPredicate()); + filter.add(CanBeSacrificedPredicate.instance); } StranglingGraspEffect() { @@ -87,15 +88,13 @@ class StranglingGraspEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Permanent sourcePermanent = source.getSourcePermanentOrLKI(game); - if (sourcePermanent == null) { - return false; - } - Permanent attachedTo = game.getPermanentOrLKIBattlefield(sourcePermanent.getAttachedTo()); - if (attachedTo == null) { - return false; - } - Player player = game.getPlayer(attachedTo.getControllerId()); + Player player = Optional + .ofNullable(source.getSourcePermanentOrLKI(game)) + .map(Permanent::getAttachedTo) + .map(game::getPermanentOrLKIBattlefield) + .map(Controllable::getControllerId) + .map(game::getPlayer) + .orElse(null); if (player == null) { return false; } diff --git a/Mage.Sets/src/mage/cards/t/TwinbladeInvocation.java b/Mage.Sets/src/mage/cards/t/TwinbladeInvocation.java index 93415a4b48b..1ade18bdba1 100644 --- a/Mage.Sets/src/mage/cards/t/TwinbladeInvocation.java +++ b/Mage.Sets/src/mage/cards/t/TwinbladeInvocation.java @@ -1,11 +1,9 @@ package mage.cards.t; -import mage.abilities.Ability; -import mage.abilities.common.PutIntoGraveFromAnywhereSourceAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.AttachEffect; -import mage.abilities.effects.common.ExileSourceEffect; import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; +import mage.abilities.keyword.DisturbAbility; import mage.abilities.keyword.DoubleStrikeAbility; import mage.abilities.keyword.EnchantAbility; import mage.cards.CardImpl; @@ -35,8 +33,7 @@ public final class TwinbladeInvocation extends CardImpl { TargetPermanent auraTarget = new TargetCreaturePermanent(); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); - Ability ability = new EnchantAbility(auraTarget); - this.addAbility(ability); + this.addAbility(new EnchantAbility(auraTarget)); // Enchanted creature has double strike. this.addAbility(new SimpleStaticAbility(new GainAbilityAttachedEffect( @@ -44,7 +41,7 @@ public final class TwinbladeInvocation extends CardImpl { ))); // If Twinblade Invocation would be put into a graveyard from anywhere, exile it instead. - this.addAbility(new PutIntoGraveFromAnywhereSourceAbility(new ExileSourceEffect().setText("exile it instead"))); + this.addAbility(DisturbAbility.makeBackAbility()); } private TwinbladeInvocation(final TwinbladeInvocation card) { diff --git a/Mage.Sets/src/mage/cards/w/Waildrifter.java b/Mage.Sets/src/mage/cards/w/Waildrifter.java index dec610a203d..321a1d31d12 100644 --- a/Mage.Sets/src/mage/cards/w/Waildrifter.java +++ b/Mage.Sets/src/mage/cards/w/Waildrifter.java @@ -1,8 +1,7 @@ package mage.cards.w; import mage.MageInt; -import mage.abilities.common.PutIntoGraveFromAnywhereSourceAbility; -import mage.abilities.effects.common.ExileSourceEffect; +import mage.abilities.keyword.DisturbAbility; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -30,7 +29,7 @@ public final class Waildrifter extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // If Waildrifter would be put into a graveyard from anywhere, exile it instead. - this.addAbility(new PutIntoGraveFromAnywhereSourceAbility(new ExileSourceEffect().setText("exile it instead"))); + this.addAbility(DisturbAbility.makeBackAbility()); } private Waildrifter(final Waildrifter card) { diff --git a/Mage/src/main/java/mage/abilities/keyword/DisturbAbility.java b/Mage/src/main/java/mage/abilities/keyword/DisturbAbility.java index 0c5d97a8fab..1061efbd2ee 100644 --- a/Mage/src/main/java/mage/abilities/keyword/DisturbAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/DisturbAbility.java @@ -1,8 +1,12 @@ package mage.abilities.keyword; +import mage.abilities.Ability; +import mage.abilities.common.PutIntoGraveFromAnywhereSourceAbility; import mage.abilities.common.SpellTransformedAbility; +import mage.abilities.effects.common.ExileSourceEffect; import mage.cards.Card; -import mage.constants.*; +import mage.constants.SpellAbilityCastMode; +import mage.constants.Zone; import mage.game.Game; import java.util.UUID; @@ -21,6 +25,7 @@ import java.util.UUID; * @author notgreat, weirddan455, JayDi85 */ public class DisturbAbility extends SpellTransformedAbility { + public DisturbAbility(Card card, String manaCost) { super(card, manaCost); @@ -58,4 +63,8 @@ public class DisturbAbility extends SpellTransformedAbility { return "Disturb " + this.manaCost + " (You may cast this card transformed from your graveyard for its disturb cost.)"; } + + public static Ability makeBackAbility() { + return new PutIntoGraveFromAnywhereSourceAbility(new ExileSourceEffect().setText("exile it instead")); + } }