diff --git a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/DuelCommander.java b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/DuelCommander.java index 697de25bcef..cc4e1c45827 100644 --- a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/DuelCommander.java +++ b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/DuelCommander.java @@ -13,17 +13,20 @@ public class DuelCommander extends Commander { banned.add("Balance"); banned.add("Bazaar of Baghdad"); banned.add("Black Lotus"); + banned.add("Blood Moon"); banned.add("Capture of Jingzhou"); banned.add("Cavern of Souls"); banned.add("Channel"); banned.add("Chrome Mox"); banned.add("Comet, Stellar Pup"); + banned.add("Dark Ritual"); banned.add("Deadly Rollick"); banned.add("Deflecting Swat"); banned.add("Dig Through Time"); banned.add("Emrakul, the Aeons Torn"); banned.add("Entomb"); banned.add("Fastbond"); + banned.add("Force of Will"); banned.add("Field of the Dead"); banned.add("Fierce Guardianship"); banned.add("Flawless Maneuver"); @@ -82,6 +85,7 @@ public class DuelCommander extends Commander { banned.add("Tolarian Academy"); banned.add("Trazyn The Infinite"); banned.add("Treasure Cruise"); + banned.add("Underworld Breach"); banned.add("Uro, Titan of Nature's Wrath"); banned.add("Vampiric Tutor"); banned.add("Wasteland"); diff --git a/Mage.Sets/src/mage/cards/a/AccursedWitch.java b/Mage.Sets/src/mage/cards/a/AccursedWitch.java index 242b3f8c0df..c214b37dd02 100644 --- a/Mage.Sets/src/mage/cards/a/AccursedWitch.java +++ b/Mage.Sets/src/mage/cards/a/AccursedWitch.java @@ -23,6 +23,8 @@ import java.util.UUID; */ public final class AccursedWitch extends CardImpl { + private static final FilterCard filter = new FilterCard("spells"); + public AccursedWitch(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}"); this.subtype.add(SubType.HUMAN); @@ -34,7 +36,7 @@ public final class AccursedWitch extends CardImpl { // Spells your opponents cast that target Accursed Witch cost {1} less to cast. this.addAbility(new SimpleStaticAbility( - new SpellsCostModificationThatTargetSourceEffect(-1, new FilterCard("Spells"), TargetController.OPPONENT)) + new SpellsCostModificationThatTargetSourceEffect(-1, filter, TargetController.OPPONENT)) ); // When Accursed Witch dies, return it to the battlefield transformed under your control attached to target opponent. 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/ArchdemonOfGreed.java b/Mage.Sets/src/mage/cards/a/ArchdemonOfGreed.java index b4c8c7a0518..6698dcde482 100644 --- a/Mage.Sets/src/mage/cards/a/ArchdemonOfGreed.java +++ b/Mage.Sets/src/mage/cards/a/ArchdemonOfGreed.java @@ -1,21 +1,18 @@ package mage.cards.a; import mage.MageInt; -import mage.abilities.Ability; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.effects.common.DamageControllerEffect; +import mage.abilities.effects.common.DoIfCostPaid; +import mage.abilities.effects.common.TapSourceEffect; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.TrampleAbility; import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.SubType; import mage.filter.common.FilterControlledPermanent; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.players.Player; -import mage.target.common.TargetSacrifice; import java.util.UUID; @@ -24,11 +21,7 @@ import java.util.UUID; */ public final class ArchdemonOfGreed extends CardImpl { - private static final FilterControlledPermanent filter = new FilterControlledPermanent("Human"); - - static { - filter.add(SubType.HUMAN.getPredicate()); - } + private static final FilterControlledPermanent filter = new FilterControlledPermanent(SubType.HUMAN, "Human"); public ArchdemonOfGreed(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, ""); @@ -44,7 +37,10 @@ public final class ArchdemonOfGreed extends CardImpl { this.addAbility(TrampleAbility.getInstance()); // At the beginning of your upkeep, sacrifice a Human. If you can't, tap Archdemon of Greed and it deals 9 damage to you. - this.addAbility(new BeginningOfUpkeepTriggeredAbility(new ArchdemonOfGreedEffect())); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new DoIfCostPaid( + null, new TapSourceEffect(), new SacrificeTargetCost(filter), false + ).addOtherwiseEffect(new DamageControllerEffect(9)) + .setText("sacrifice a Human. If you can't, tap {this} and it deals 9 damage to you"))); } private ArchdemonOfGreed(final ArchdemonOfGreed card) { @@ -55,48 +51,4 @@ public final class ArchdemonOfGreed extends CardImpl { public ArchdemonOfGreed copy() { return new ArchdemonOfGreed(this); } - - static class ArchdemonOfGreedEffect extends OneShotEffect { - - public ArchdemonOfGreedEffect() { - super(Outcome.Damage); - this.staticText = "sacrifice a Human. If you can't, tap {this} and it deals 9 damage to you."; - } - - private ArchdemonOfGreedEffect(final ArchdemonOfGreedEffect effect) { - super(effect); - } - - @Override - public ArchdemonOfGreedEffect copy() { - return new ArchdemonOfGreedEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(source.getSourceId()); - - if (permanent != null) { - // create cost for sacrificing a human - Player player = game.getPlayer(source.getControllerId()); - if (player != null) { - TargetSacrifice target = new TargetSacrifice(filter); - // if they can pay the cost, then they must pay - if (target.canChoose(player.getId(), source, game)) { - player.choose(Outcome.Sacrifice, target, source, game); - Permanent humanSacrifice = game.getPermanent(target.getFirstTarget()); - if (humanSacrifice != null) { - // sacrifice the chosen card - return humanSacrifice.sacrifice(source, game); - } - } else { - permanent.tap(source, game); - player.damage(9, source.getSourceId(), source, game); - } - } - return true; - } - return false; - } - } } 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/ArlinnEmbracedByTheMoon.java b/Mage.Sets/src/mage/cards/a/ArlinnEmbracedByTheMoon.java index 8e470214cdd..8a6b011c2e0 100644 --- a/Mage.Sets/src/mage/cards/a/ArlinnEmbracedByTheMoon.java +++ b/Mage.Sets/src/mage/cards/a/ArlinnEmbracedByTheMoon.java @@ -1,9 +1,7 @@ - package mage.cards.a; -import java.util.UUID; +import mage.abilities.Ability; import mage.abilities.LoyaltyAbility; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.GetEmblemEffect; import mage.abilities.effects.common.TransformSourceEffect; @@ -21,8 +19,9 @@ import mage.filter.StaticFilters; import mage.game.command.emblems.ArlinnEmbracedByTheMoonEmblem; import mage.target.common.TargetAnyTarget; +import java.util.UUID; + /** - * * @author fireshoes */ public final class ArlinnEmbracedByTheMoon extends CardImpl { @@ -37,12 +36,14 @@ public final class ArlinnEmbracedByTheMoon extends CardImpl { this.nightCard = true; // +1: Creatures you control get +1/+1 and gain trample until end of turn. - Effect effect = new BoostControlledEffect(1, 1, Duration.EndOfTurn, StaticFilters.FILTER_PERMANENT_CREATURE); - effect.setText("Creatures you control get +1/+1"); - LoyaltyAbility ability = new LoyaltyAbility(effect, 1); - effect = new GainAbilityControlledEffect(TrampleAbility.getInstance(), Duration.EndOfTurn, StaticFilters.FILTER_PERMANENT_CREATURE); - effect.setText("and gain trample until end of turn"); - ability.addEffect(effect); + Ability ability = new LoyaltyAbility(new BoostControlledEffect( + 1, 1, Duration.EndOfTurn, + StaticFilters.FILTER_PERMANENT_CREATURE + ).setText("Creatures you control get +1/+1"), 1); + ability.addEffect(new GainAbilityControlledEffect( + TrampleAbility.getInstance(), Duration.EndOfTurn, + StaticFilters.FILTER_PERMANENT_CREATURE + ).setText("and gain trample until end of turn")); this.addAbility(ability); // -1: Arlinn, Embraced by the Moon deals 3 damage to any target. Transform Arlinn, Embraced by the Moon. diff --git a/Mage.Sets/src/mage/cards/a/ArlinnKord.java b/Mage.Sets/src/mage/cards/a/ArlinnKord.java index 6a61cf53703..dbb9593deb6 100644 --- a/Mage.Sets/src/mage/cards/a/ArlinnKord.java +++ b/Mage.Sets/src/mage/cards/a/ArlinnKord.java @@ -1,9 +1,7 @@ - package mage.cards.a; -import java.util.UUID; +import mage.abilities.Ability; import mage.abilities.LoyaltyAbility; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.effects.common.continuous.BoostTargetEffect; @@ -20,14 +18,15 @@ import mage.constants.SuperType; import mage.game.permanent.token.WolfToken; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author fireshoes */ public final class ArlinnKord extends CardImpl { public ArlinnKord(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.PLANESWALKER},"{2}{R}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{2}{R}{G}"); this.supertype.add(SuperType.LEGENDARY); this.subtype.add(SubType.ARLINN); @@ -36,15 +35,15 @@ public final class ArlinnKord extends CardImpl { this.setStartingLoyalty(3); // +1: Until end of turn, up to one target creature gets +2/+2 and gains vigilance and haste. - Effect effect = new BoostTargetEffect(2, 2, Duration.EndOfTurn); - effect.setText("Until end of turn, up to one target creature gets +2/+2"); - LoyaltyAbility ability = new LoyaltyAbility(effect, 1); - effect = new GainAbilityTargetEffect(VigilanceAbility.getInstance(), Duration.EndOfTurn); - effect.setText("and gains vigilance"); - ability.addEffect(effect); - effect = new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn); - effect.setText("and haste"); - ability.addEffect(effect); + Ability ability = new LoyaltyAbility(new BoostTargetEffect( + 2, 2, Duration.EndOfTurn + ).setText("until end of turn, up to one target creature gets +2/+2"), 1); + ability.addEffect(new GainAbilityTargetEffect( + VigilanceAbility.getInstance(), Duration.EndOfTurn + ).setText("and gains vigilance")); + ability.addEffect(new GainAbilityTargetEffect( + HasteAbility.getInstance(), Duration.EndOfTurn + ).setText("and haste")); ability.addTarget(new TargetCreaturePermanent(0, 1)); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/a/AshmouthBlade.java b/Mage.Sets/src/mage/cards/a/AshmouthBlade.java index 7ada6ce0445..4fe8866988e 100644 --- a/Mage.Sets/src/mage/cards/a/AshmouthBlade.java +++ b/Mage.Sets/src/mage/cards/a/AshmouthBlade.java @@ -1,44 +1,40 @@ - package mage.cards.a; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.continuous.BoostEquippedEffect; import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; import mage.abilities.keyword.EquipAbility; import mage.abilities.keyword.FirstStrikeAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.constants.AttachmentType; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; /** - * * @author fireshoes */ public final class AshmouthBlade extends CardImpl { public AshmouthBlade(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},""); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, ""); this.subtype.add(SubType.EQUIPMENT); // this card is the second face of double-faced card this.nightCard = true; - // Equipped creature gets +3/+3 + // Equipped creature gets +3/+3 and has first strike. Ability ability = new SimpleStaticAbility(new BoostEquippedEffect(3, 3)); + ability.addEffect(new GainAbilityAttachedEffect( + FirstStrikeAbility.getInstance(), AttachmentType.EQUIPMENT + ).setText("and has first strike")); this.addAbility(ability); - // and has first strike. - Effect effect = new GainAbilityAttachedEffect(FirstStrikeAbility.getInstance(), AttachmentType.EQUIPMENT); - effect.setText("and has first strike"); - ability.addEffect(effect); - // Equip {3} - this.addAbility(new EquipAbility(Outcome.BoostCreature, new GenericManaCost(3), new TargetControlledCreaturePermanent(), false)); + this.addAbility(new EquipAbility(3, false)); } private AshmouthBlade(final AshmouthBlade card) { diff --git a/Mage.Sets/src/mage/cards/a/AutumnalGloom.java b/Mage.Sets/src/mage/cards/a/AutumnalGloom.java index 684727c24dd..b7d0f232ddf 100644 --- a/Mage.Sets/src/mage/cards/a/AutumnalGloom.java +++ b/Mage.Sets/src/mage/cards/a/AutumnalGloom.java @@ -1,22 +1,21 @@ package mage.cards.a; -import java.util.UUID; - -import mage.abilities.Ability; -import mage.abilities.dynamicvalue.common.CardTypesInGraveyardCount; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.common.DeliriumCondition; import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.dynamicvalue.common.CardTypesInGraveyardCount; import mage.abilities.effects.common.MillCardsControllerEffect; 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.AbilityWord; import mage.constants.CardType; import mage.constants.TargetController; +import java.util.UUID; + /** * @author LevelX2 */ @@ -31,10 +30,9 @@ public final class AutumnalGloom extends CardImpl { // Delirium — At the beginning of your end step, if there are four or more card types among cards in your graveyard, transform Autumnal Gloom. this.addAbility(new TransformAbility()); - Ability ability = new BeginningOfEndStepTriggeredAbility(TargetController.YOU, new TransformSourceEffect(), false, DeliriumCondition.instance); - ability.setAbilityWord(AbilityWord.DELIRIUM); - ability.addHint(CardTypesInGraveyardCount.YOU.getHint()); - this.addAbility(ability); + this.addAbility(new BeginningOfEndStepTriggeredAbility( + TargetController.YOU, new TransformSourceEffect(), false, DeliriumCondition.instance + ).setAbilityWord(AbilityWord.DELIRIUM).addHint(CardTypesInGraveyardCount.YOU.getHint())); } private AutumnalGloom(final AutumnalGloom 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/a/AzorsGateway.java b/Mage.Sets/src/mage/cards/a/AzorsGateway.java index 6ac44610cf8..4a6f94a4a39 100644 --- a/Mage.Sets/src/mage/cards/a/AzorsGateway.java +++ b/Mage.Sets/src/mage/cards/a/AzorsGateway.java @@ -1,12 +1,15 @@ - package mage.cards.a; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.condition.Condition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.decorator.ConditionalOneShotEffect; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.effects.common.UntapSourceEffect; import mage.abilities.keyword.TransformAbility; @@ -19,11 +22,10 @@ import mage.constants.SuperType; import mage.game.ExileZone; import mage.game.Game; import mage.players.Player; +import mage.target.TargetCard; import mage.target.common.TargetCardInHand; import mage.util.CardUtil; -import java.util.HashSet; -import java.util.Set; import java.util.UUID; /** @@ -41,8 +43,13 @@ public final class AzorsGateway extends CardImpl { // If cards with five or more different converted mana costs are exiled with Azor's Gateway, // you gain 5 life, untap Azor's Gateway, and transform it. this.addAbility(new TransformAbility()); - Ability ability = new SimpleActivatedAbility(new AzorsGatewayEffect(), new GenericManaCost(1)); + Ability ability = new SimpleActivatedAbility(new DrawCardSourceControllerEffect(1), new GenericManaCost(1)); ability.addCost(new TapSourceCost()); + ability.addEffect(new AzorsGatewayEffect()); + ability.addEffect(new ConditionalOneShotEffect( + new GainLifeEffect(5), AzorsGatewayCondition.instance, "If cards with five or more " + + "different mana values are exiled with {this}, you gain 5 life, untap {this}, and transform it." + ).addEffect(new UntapSourceEffect()).addEffect(new TransformSourceEffect())); this.addAbility(ability); } @@ -56,13 +63,28 @@ public final class AzorsGateway extends CardImpl { } } +enum AzorsGatewayCondition implements Condition { + instance; + + @Override + public boolean apply(Game game, Ability source) { + ExileZone exileZone = game.getExile().getExileZone(CardUtil.getExileZoneId(game, source)); + return exileZone != null + && exileZone + .getCards(game) + .stream() + .map(MageObject::getManaValue) + .distinct() + .mapToInt(x -> 1) + .sum() >= 5; + } +} + class AzorsGatewayEffect extends OneShotEffect { AzorsGatewayEffect() { super(Outcome.Benefit); - this.staticText = "Draw a card, then exile a card from your hand. " + - "If cards with five or more different mana values are exiled with {this}, " + - "you gain 5 life, untap {this}, and transform it"; + this.staticText = ", then exile a card from your hand"; } private AzorsGatewayEffect(final AzorsGatewayEffect effect) { @@ -76,37 +98,18 @@ class AzorsGatewayEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller == null) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null || player.getHand().isEmpty()) { return false; } - - MageObject sourceObject = source.getSourceObject(game); - if (sourceObject == null) { - return false; - } - - UUID exileId = CardUtil.getCardExileZoneId(game, source); - - controller.drawCards(1, source, game); - TargetCardInHand target = new TargetCardInHand(); - controller.choose(outcome, target, source, game); - Card cardToExile = game.getCard(target.getFirstTarget()); - if (cardToExile != null) { - controller.moveCardsToExile(cardToExile, source, game, true, exileId, sourceObject.getIdName()); - } - Set usedCMC = new HashSet<>(); - ExileZone exileZone = game.getExile().getExileZone(exileId); - if (exileZone != null) { - for (Card card : exileZone.getCards(game)) { - usedCMC.add(card.getManaValue()); - } - if (usedCMC.size() > 4) { - controller.gainLife(4, game, source); - new UntapSourceEffect().apply(game, source); - new TransformSourceEffect().apply(game, source); - } - } - return true; + TargetCard target = new TargetCardInHand(); + target.withChooseHint("to exile"); + player.choose(outcome, player.getHand(), target, source, game); + Card card = game.getCard(target.getFirstTarget()); + return card != null && player.moveCardsToExile( + card, source, game, true, + CardUtil.getExileZoneId(game, source), + CardUtil.getSourceLogName(game, source) + ); } } 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/ChandraFireOfKaladesh.java b/Mage.Sets/src/mage/cards/c/ChandraFireOfKaladesh.java index 10885efa17e..cbe8871a1aa 100644 --- a/Mage.Sets/src/mage/cards/c/ChandraFireOfKaladesh.java +++ b/Mage.Sets/src/mage/cards/c/ChandraFireOfKaladesh.java @@ -1,13 +1,12 @@ package mage.cards.c; -import java.util.UUID; import mage.MageInt; import mage.ObjectColor; import mage.abilities.Ability; -import mage.constants.Pronoun; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SpellCastControllerTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.SourceDealtDamageCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.decorator.ConditionalOneShotEffect; @@ -23,8 +22,9 @@ import mage.filter.predicate.mageobject.ColorPredicate; import mage.target.common.TargetPlayerOrPlaneswalker; import mage.watchers.common.DamageDoneWatcher; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class ChandraFireOfKaladesh extends CardImpl { @@ -35,6 +35,8 @@ public final class ChandraFireOfKaladesh extends CardImpl { filter.add(new ColorPredicate(ObjectColor.RED)); } + private static final Condition condition = new SourceDealtDamageCondition(3); + public ChandraFireOfKaladesh(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}{R}"); this.supertype.add(SuperType.LEGENDARY); @@ -51,10 +53,11 @@ public final class ChandraFireOfKaladesh extends CardImpl { // {T}: Chandra, Fire of Kaladesh deals 1 damage to target player. If Chandra has dealt 3 or more damage this turn, exile her, then return her to the battlefield transformed under her owner's control. this.addAbility(new TransformAbility()); Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(1), new TapSourceCost()); - ability.addEffect(new ConditionalOneShotEffect(new ExileAndReturnSourceEffect(PutCards.BATTLEFIELD_TRANSFORMED,Pronoun.SHE), new SourceDealtDamageCondition(3))); + ability.addEffect(new ConditionalOneShotEffect( + new ExileAndReturnSourceEffect(PutCards.BATTLEFIELD_TRANSFORMED, Pronoun.SHE), condition + )); ability.addTarget(new TargetPlayerOrPlaneswalker()); this.addAbility(ability, new DamageDoneWatcher()); - } private ChandraFireOfKaladesh(final ChandraFireOfKaladesh card) { diff --git a/Mage.Sets/src/mage/cards/c/ChandraRoaringFlame.java b/Mage.Sets/src/mage/cards/c/ChandraRoaringFlame.java index f1cec24e163..9759367aa57 100644 --- a/Mage.Sets/src/mage/cards/c/ChandraRoaringFlame.java +++ b/Mage.Sets/src/mage/cards/c/ChandraRoaringFlame.java @@ -47,7 +47,6 @@ public final class ChandraRoaringFlame extends CardImpl { //-7: Chandra, Roaring Flame deals 6 damage to each opponent. Each player dealt damage this way gets an emblem with "At the beginning of your upkeep, this emblem deals 3 damage to you." this.addAbility(new LoyaltyAbility(new ChandraRoaringFlameEmblemEffect(), -7)); - } private ChandraRoaringFlame(final ChandraRoaringFlame card) { @@ -79,20 +78,19 @@ class ChandraRoaringFlameEmblemEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - List opponentsEmblem = new ArrayList<>(); - for (UUID playerId : game.getOpponents(controller.getId())) { - Player opponent = game.getPlayer(playerId); - if (opponent != null) { - if (opponent.damage(6, source.getSourceId(), source, game) > 0) { - opponentsEmblem.add(opponent); - } - } - } - for (Player opponent : opponentsEmblem) { - game.addEmblem(new ChandraRoaringFlameEmblem(), source.getSourceObject(game), opponent.getId()); + if (controller == null) { + return false; + } + List opponentsEmblem = new ArrayList<>(); + for (UUID playerId : game.getOpponents(controller.getId())) { + Player opponent = game.getPlayer(playerId); + if (opponent != null && opponent.damage(6, source, game) > 0) { + opponentsEmblem.add(opponent); } } + for (Player opponent : opponentsEmblem) { + game.addEmblem(new ChandraRoaringFlameEmblem(), source.getSourceObject(game), opponent.getId()); + } return false; } } 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/CivilizedScholar.java b/Mage.Sets/src/mage/cards/c/CivilizedScholar.java index 8baaa504abc..9d9315204fe 100644 --- a/Mage.Sets/src/mage/cards/c/CivilizedScholar.java +++ b/Mage.Sets/src/mage/cards/c/CivilizedScholar.java @@ -1,24 +1,24 @@ package mage.cards.c; -import java.util.UUID; - import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.keyword.TransformAbility; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Outcome; -import mage.constants.Zone; +import mage.constants.SubType; import mage.game.Game; -import mage.game.permanent.Permanent; import mage.players.Player; +import java.util.Optional; +import java.util.UUID; + /** * @author nantuko */ @@ -35,8 +35,10 @@ public final class CivilizedScholar extends CardImpl { this.toughness = new MageInt(1); // {tap}: Draw a card, then discard a card. If a creature card is discarded this way, untap Civilized Scholar, then transform it. - this.addAbility(new SimpleActivatedAbility(new CivilizedScholarEffect(), new TapSourceCost())); + Ability ability = new SimpleActivatedAbility(new DrawCardSourceControllerEffect(1), new TapSourceCost()); + ability.addEffect(new CivilizedScholarEffect()); this.addAbility(new TransformAbility()); + this.addAbility(ability); } private CivilizedScholar(final CivilizedScholar card) { @@ -50,12 +52,11 @@ public final class CivilizedScholar extends CardImpl { } - class CivilizedScholarEffect extends OneShotEffect { CivilizedScholarEffect() { super(Outcome.DrawCard); - staticText = "Draw a card, then discard a card. If a creature card is discarded this way, untap {this}, then transform it"; + staticText = ", then discard a card. If a creature card is discarded this way, untap {this}, then transform it"; } private CivilizedScholarEffect(final CivilizedScholarEffect effect) { @@ -70,18 +71,18 @@ class CivilizedScholarEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player player = game.getPlayer(source.getControllerId()); - if (player != null) { - player.drawCards(1, source, game); - Card card = player.discardOne(false, false, source, game); - if (card != null && card.isCreature(game)) { - Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent != null) { - permanent.untap(game); - permanent.transform(source, game); - } - } + if (player == null) { + return false; + } + Card card = player.discardOne(false, false, source, game); + if (card == null || !card.isCreature(game)) { return true; } - return false; + Optional.ofNullable(source.getSourcePermanentIfItStillExists(game)) + .ifPresent(permanent -> { + permanent.untap(game); + permanent.transform(source, game); + }); + return true; } } 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/ConduitOfEmrakul.java b/Mage.Sets/src/mage/cards/c/ConduitOfEmrakul.java index ce9612de660..ec2a8fc337e 100644 --- a/Mage.Sets/src/mage/cards/c/ConduitOfEmrakul.java +++ b/Mage.Sets/src/mage/cards/c/ConduitOfEmrakul.java @@ -1,28 +1,26 @@ - package mage.cards.c; -import java.util.UUID; import mage.MageInt; import mage.Mana; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.common.delayed.AtTheBeginOfMainPhaseDelayedTriggeredAbility; -import mage.abilities.effects.Effect; -import mage.abilities.effects.mana.AddManaToManaPoolSourceControllerEffect; import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; +import mage.abilities.effects.mana.AddManaToManaPoolSourceControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.TargetController; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class ConduitOfEmrakul extends CardImpl { public ConduitOfEmrakul(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},""); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, ""); this.subtype.add(SubType.ELDRAZI); this.subtype.add(SubType.WEREWOLF); this.power = new MageInt(5); @@ -32,11 +30,12 @@ public final class ConduitOfEmrakul extends CardImpl { this.nightCard = true; // Whenever Conduit of Emrakul attacks, add {C}{C} at the beginning of your next main phase this turn. - Effect effect = new CreateDelayedTriggeredAbilityEffect( + this.addAbility(new AttacksTriggeredAbility(new CreateDelayedTriggeredAbilityEffect( new AtTheBeginOfMainPhaseDelayedTriggeredAbility( - new AddManaToManaPoolSourceControllerEffect(Mana.GenericMana(2)), false, TargetController.YOU, AtTheBeginOfMainPhaseDelayedTriggeredAbility.PhaseSelection.NEXT_MAIN_THIS_TURN)); - effect.setText("add {C}{C} at the beginning of your next main phase this turn"); - this.addAbility(new AttacksTriggeredAbility(effect, false)); + new AddManaToManaPoolSourceControllerEffect(Mana.GenericMana(2)), false, + TargetController.YOU, AtTheBeginOfMainPhaseDelayedTriggeredAbility.PhaseSelection.NEXT_MAIN_THIS_TURN + ) + ).setText("add {C}{C} at the beginning of your next main phase this turn"), false)); } private ConduitOfEmrakul(final ConduitOfEmrakul card) { diff --git a/Mage.Sets/src/mage/cards/c/ConduitOfStorms.java b/Mage.Sets/src/mage/cards/c/ConduitOfStorms.java index c0e8f602938..0fdf2d7098f 100644 --- a/Mage.Sets/src/mage/cards/c/ConduitOfStorms.java +++ b/Mage.Sets/src/mage/cards/c/ConduitOfStorms.java @@ -1,33 +1,30 @@ - package mage.cards.c; -import java.util.UUID; import mage.MageInt; import mage.Mana; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.delayed.AtTheBeginOfMainPhaseDelayedTriggeredAbility; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.Effect; -import mage.abilities.effects.mana.AddManaToManaPoolSourceControllerEffect; import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; import mage.abilities.effects.common.TransformSourceEffect; +import mage.abilities.effects.mana.AddManaToManaPoolSourceControllerEffect; import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.TargetController; -import mage.constants.Zone; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class ConduitOfStorms extends CardImpl { public ConduitOfStorms(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}"); this.subtype.add(SubType.WEREWOLF); this.subtype.add(SubType.HORROR); this.power = new MageInt(2); @@ -36,11 +33,13 @@ public final class ConduitOfStorms extends CardImpl { this.secondSideCardClazz = mage.cards.c.ConduitOfEmrakul.class; // Whenever Conduit of Storms attacks, add {R} at the beginning of your next main phase this turn. - Effect effect = new CreateDelayedTriggeredAbilityEffect( + this.addAbility(new AttacksTriggeredAbility(new CreateDelayedTriggeredAbilityEffect( new AtTheBeginOfMainPhaseDelayedTriggeredAbility( - new AddManaToManaPoolSourceControllerEffect(Mana.RedMana(1)), false, TargetController.YOU, AtTheBeginOfMainPhaseDelayedTriggeredAbility.PhaseSelection.NEXT_MAIN_THIS_TURN)); - effect.setText("add {R} at the beginning of your next main phase this turn"); - this.addAbility(new AttacksTriggeredAbility(effect, false)); + new AddManaToManaPoolSourceControllerEffect(Mana.RedMana(1)), false, + TargetController.YOU, AtTheBeginOfMainPhaseDelayedTriggeredAbility.PhaseSelection.NEXT_MAIN_THIS_TURN + ) + ).setText("add {R} at the beginning of your next main phase this turn"), false)); + // {3}{R}{R}: Transform Conduit of Storms. this.addAbility(new TransformAbility()); this.addAbility(new SimpleActivatedAbility(new TransformSourceEffect(), new ManaCostsImpl<>("{3}{R}{R}"))); 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/DelverOfSecrets.java b/Mage.Sets/src/mage/cards/d/DelverOfSecrets.java index ec29df45be6..0b89a031e26 100644 --- a/Mage.Sets/src/mage/cards/d/DelverOfSecrets.java +++ b/Mage.Sets/src/mage/cards/d/DelverOfSecrets.java @@ -1,23 +1,20 @@ - package mage.cards.d; -import java.util.UUID; - import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.*; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Outcome; -import mage.filter.FilterCard; -import mage.filter.common.FilterInstantOrSorceryCard; +import mage.constants.SubType; import mage.game.Game; -import mage.game.permanent.Permanent; import mage.players.Player; +import mage.util.CardUtil; + +import java.util.Optional; +import java.util.UUID; /** * @author Alvin @@ -51,11 +48,10 @@ public final class DelverOfSecrets extends CardImpl { class DelverOfSecretsEffect extends OneShotEffect { - private static final FilterCard filter = new FilterInstantOrSorceryCard(); - public DelverOfSecretsEffect() { super(Outcome.Benefit); - this.staticText = "look at the top card of your library. You may reveal that card. If an instant or sorcery card is revealed this way, transform {this}"; + this.staticText = "look at the top card of your library. You may reveal that card. " + + "If an instant or sorcery card is revealed this way, transform {this}"; } private DelverOfSecretsEffect(final DelverOfSecretsEffect effect) { @@ -70,25 +66,22 @@ class DelverOfSecretsEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player player = game.getPlayer(source.getControllerId()); - Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); - if (player == null || sourcePermanent == null) { + if (player == null || !player.getLibrary().hasCards()) { return false; } - if (player.getLibrary().hasCards()) { - Card card = player.getLibrary().getFromTop(game); - if(card == null){ - return false; - } - Cards cards = new CardsImpl(); - cards.add(card); - player.lookAtCards(sourcePermanent.getName(), cards, game); - if (player.chooseUse(Outcome.DrawCard, "Reveal the top card of your library?", source, game)) { - player.revealCards(sourcePermanent.getName(), cards, game); - if (filter.match(card, game)) { - return new TransformSourceEffect().apply(game, source); - } - } - + Card card = player.getLibrary().getFromTop(game); + if (card == null) { + return false; + } + Cards cards = new CardsImpl(card); + player.lookAtCards(CardUtil.getSourceLogName(game, source), cards, game); + if (!player.chooseUse(Outcome.DrawCard, "Reveal the top card of your library?", source, game)) { + return false; + } + player.revealCards(source, cards, game); + if (card.isInstantOrSorcery(game)) { + Optional.ofNullable(source.getSourcePermanentIfItStillExists(game)) + .ifPresent(permanent -> permanent.transform(source, game)); } return true; } 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/DocentOfPerfection.java b/Mage.Sets/src/mage/cards/d/DocentOfPerfection.java index db808cdc156..129e98d02db 100644 --- a/Mage.Sets/src/mage/cards/d/DocentOfPerfection.java +++ b/Mage.Sets/src/mage/cards/d/DocentOfPerfection.java @@ -1,42 +1,40 @@ - package mage.cards.d; -import java.util.UUID; - import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SpellCastControllerTriggeredAbility; -import mage.abilities.effects.Effect; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.TransformSourceEffect; +import mage.abilities.hint.Hint; +import mage.abilities.hint.ValueHint; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; +import mage.constants.ComparisonType; import mage.constants.SubType; -import mage.constants.TargetController; -import mage.filter.FilterPermanent; -import mage.filter.FilterSpell; -import mage.filter.predicate.Predicates; -import mage.game.Game; +import mage.filter.StaticFilters; +import mage.filter.common.FilterControlledPermanent; import mage.game.permanent.token.HumanWizardToken; -import mage.players.Player; + +import java.util.UUID; /** * @author fireshoes */ public final class DocentOfPerfection extends CardImpl { - private static final FilterSpell filterSpell = new FilterSpell("an instant or sorcery spell"); - - static { - filterSpell.add(Predicates.or( - CardType.INSTANT.getPredicate(), - CardType.SORCERY.getPredicate())); - } + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterControlledPermanent(SubType.WIZARD), ComparisonType.MORE_THAN, 2 + ); + private static final Hint hint = new ValueHint( + "Wizards you control", new PermanentsOnBattlefieldCount(new FilterControlledPermanent(SubType.WIZARD)) + ); public DocentOfPerfection(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}{U}"); @@ -53,10 +51,15 @@ public final class DocentOfPerfection extends CardImpl { // Whenever you cast an instant or sorcery spell, create a 1/1 blue Human Wizard creature token. // Then if you control three or more Wizards, transform Docent of Perfection. this.addAbility(new TransformAbility()); - Effect effect = new DocentOfPerfectionEffect(); - Ability ability = new SpellCastControllerTriggeredAbility(new CreateTokenEffect(new HumanWizardToken()), filterSpell, false); - ability.addEffect(effect); - this.addAbility(ability); + Ability ability = new SpellCastControllerTriggeredAbility( + new CreateTokenEffect(new HumanWizardToken()), + StaticFilters.FILTER_SPELL_AN_INSTANT_OR_SORCERY, false + ); + ability.addEffect(new ConditionalOneShotEffect( + new TransformSourceEffect(), condition, + "Then if you control three or more Wizards, transform {this}" + )); + this.addAbility(ability.addHint(hint)); } private DocentOfPerfection(final DocentOfPerfection card) { @@ -68,38 +71,3 @@ public final class DocentOfPerfection extends CardImpl { return new DocentOfPerfection(this); } } - -class DocentOfPerfectionEffect extends OneShotEffect { - - private static final FilterPermanent filter = new FilterPermanent("Wizards"); - - static { - filter.add(SubType.WIZARD.getPredicate()); - filter.add(TargetController.YOU.getControllerPredicate()); - } - - public DocentOfPerfectionEffect() { - super(Outcome.Benefit); - staticText = "Then if you control three or more Wizards, transform {this}"; - } - - private DocentOfPerfectionEffect(final DocentOfPerfectionEffect effect) { - super(effect); - } - - @Override - public DocentOfPerfectionEffect copy() { - return new DocentOfPerfectionEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - if (game.getBattlefield().count(filter, source.getControllerId(), source, game) >= 3) { - return new TransformSourceEffect().apply(game, source); - } - } - return false; - } -} \ No newline at end of file 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/DowsingDagger.java b/Mage.Sets/src/mage/cards/d/DowsingDagger.java index 8a2f5db3934..a5b02e21193 100644 --- a/Mage.Sets/src/mage/cards/d/DowsingDagger.java +++ b/Mage.Sets/src/mage/cards/d/DowsingDagger.java @@ -1,8 +1,6 @@ package mage.cards.d; -import java.util.UUID; - import mage.abilities.Ability; import mage.abilities.common.DealsDamageToAPlayerAttachedTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; @@ -13,16 +11,16 @@ import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.effects.common.continuous.BoostEquippedEffect; import mage.abilities.keyword.EquipAbility; import mage.abilities.keyword.TransformAbility; -import mage.constants.SubType; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Outcome; -import mage.constants.Zone; +import mage.constants.SubType; import mage.game.permanent.token.DefenderPlantToken; -import mage.target.Target; import mage.target.common.TargetOpponent; +import java.util.UUID; + /** * @author TheElk801 */ @@ -37,8 +35,7 @@ public final class DowsingDagger extends CardImpl { // When Dowsing Dagger enters the battlefield, target opponent creates two 0/2 green Plant creature tokens with defender. Ability ability = new EntersBattlefieldTriggeredAbility(new CreateTokenTargetEffect(new DefenderPlantToken(), 2), false); - Target target = new TargetOpponent(); - ability.addTarget(target); + ability.addTarget(new TargetOpponent()); this.addAbility(ability); // Equipped creature gets +2/+1. 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/e/ElbrusTheBindingBlade.java b/Mage.Sets/src/mage/cards/e/ElbrusTheBindingBlade.java index 3b3e67f5c3b..8612d8b1dfa 100644 --- a/Mage.Sets/src/mage/cards/e/ElbrusTheBindingBlade.java +++ b/Mage.Sets/src/mage/cards/e/ElbrusTheBindingBlade.java @@ -1,25 +1,23 @@ package mage.cards.e; -import java.util.UUID; - import mage.abilities.Ability; import mage.abilities.common.DealsDamageToAPlayerAttachedTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.effects.common.continuous.BoostEquippedEffect; import mage.abilities.keyword.EquipAbility; import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Outcome; +import mage.constants.SubType; import mage.constants.SuperType; -import mage.constants.Zone; import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.target.common.TargetControlledCreaturePermanent; + +import java.util.Optional; +import java.util.UUID; /** * @author BetaSteward @@ -36,10 +34,16 @@ public final class ElbrusTheBindingBlade extends CardImpl { // Equipped creature gets +1/+0. this.addAbility(new SimpleStaticAbility(new BoostEquippedEffect(1, 0))); + // When equipped creature deals combat damage to a player, unattach Elbrus, the Binding Blade, then transform it. - this.addAbility(new DealsDamageToAPlayerAttachedTriggeredAbility(new ElbrusTheBindingBladeEffect(), "equipped", false)); + Ability ability = new DealsDamageToAPlayerAttachedTriggeredAbility( + new ElbrusTheBindingBladeEffect(), "equipped", false + ); + ability.addEffect(new TransformSourceEffect(true).concatBy(", then")); + this.addAbility(ability); + // Equip {1} - this.addAbility(new EquipAbility(Outcome.BoostCreature, new GenericManaCost(1), new TargetControlledCreaturePermanent(), false)); + this.addAbility(new EquipAbility(1, false)); } private ElbrusTheBindingBlade(final ElbrusTheBindingBlade card) { @@ -64,20 +68,12 @@ class ElbrusTheBindingBladeEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Permanent equipment = game.getPermanent(source.getSourceId()); - if (equipment != null && equipment.getAttachedTo() != null) { - Permanent attachedTo = game.getPermanent(equipment.getAttachedTo()); - if (attachedTo != null) { - attachedTo.removeAttachment(equipment.getId(), source, game); - equipment.transform(source, game); - } - } - return false; + Optional.ofNullable(source.getSourcePermanentIfItStillExists(game)).ifPresent(permanent -> permanent.unattach(game)); + return true; } @Override public ElbrusTheBindingBladeEffect copy() { return new ElbrusTheBindingBladeEffect(this); } - } diff --git a/Mage.Sets/src/mage/cards/f/FinalIteration.java b/Mage.Sets/src/mage/cards/f/FinalIteration.java index 7ef4c765c72..de5fab8d202 100644 --- a/Mage.Sets/src/mage/cards/f/FinalIteration.java +++ b/Mage.Sets/src/mage/cards/f/FinalIteration.java @@ -1,43 +1,37 @@ - package mage.cards.f; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SpellCastControllerTriggeredAbility; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.continuous.BoostControlledEffect; -import mage.abilities.effects.common.continuous.GainAbilityAllEffect; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; -import mage.filter.FilterSpell; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.Predicates; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; import mage.game.permanent.token.HumanWizardToken; +import java.util.UUID; + /** - * * @author fireshoes */ public final class FinalIteration extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Wizards"); - private static final FilterSpell filterSpell = new FilterSpell("an instant or sorcery spell"); + private static final FilterPermanent filter = new FilterPermanent("Wizards"); static { filter.add(SubType.WIZARD.getPredicate()); - filter.add(TargetController.YOU.getControllerPredicate()); - filterSpell.add(Predicates.or( - CardType.INSTANT.getPredicate(), - CardType.SORCERY.getPredicate())); } public FinalIteration(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},""); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, ""); this.subtype.add(SubType.ELDRAZI); this.subtype.add(SubType.INSECT); this.power = new MageInt(6); @@ -50,14 +44,19 @@ public final class FinalIteration extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // Wizards you control get +2/+1 and have flying. - Ability ability = new SimpleStaticAbility(new BoostControlledEffect(2, 1, Duration.WhileOnBattlefield, filter, false)); - Effect effect = new GainAbilityAllEffect(FlyingAbility.getInstance(), Duration.WhileOnBattlefield, filter, false); - effect.setText("and have flying"); - ability.addEffect(effect); + Ability ability = new SimpleStaticAbility(new BoostControlledEffect( + 2, 1, Duration.WhileOnBattlefield, filter, false + )); + ability.addEffect(new GainAbilityControlledEffect( + FlyingAbility.getInstance(), Duration.WhileOnBattlefield, filter + ).setText("and have flying")); this.addAbility(ability); // Whenever you cast an instant or sorcery spell, create a 1/1 blue Human Wizard creature token. - this.addAbility(new SpellCastControllerTriggeredAbility(new CreateTokenEffect(new HumanWizardToken()), filterSpell, false)); + this.addAbility(new SpellCastControllerTriggeredAbility( + new CreateTokenEffect(new HumanWizardToken()), + StaticFilters.FILTER_SPELL_AN_INSTANT_OR_SORCERY, false + )); } private FinalIteration(final FinalIteration card) { diff --git a/Mage.Sets/src/mage/cards/g/GarrukRelentless.java b/Mage.Sets/src/mage/cards/g/GarrukRelentless.java index 5a26e6a9fab..b22ae5c3b93 100644 --- a/Mage.Sets/src/mage/cards/g/GarrukRelentless.java +++ b/Mage.Sets/src/mage/cards/g/GarrukRelentless.java @@ -1,4 +1,3 @@ - package mage.cards.g; import mage.abilities.Ability; @@ -6,6 +5,7 @@ import mage.abilities.LoyaltyAbility; import mage.abilities.StateTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; @@ -39,13 +39,13 @@ public final class GarrukRelentless extends CardImpl { this.addAbility(new GarrukRelentlessStateTrigger()); // 0: Garruk Relentless deals 3 damage to target creature. That creature deals damage equal to its power to him - LoyaltyAbility ability1 = new LoyaltyAbility(new GarrukRelentlessDamageEffect(), 0); - ability1.addTarget(new TargetCreaturePermanent()); - this.addAbility(ability1); + Ability ability = new LoyaltyAbility(new DamageTargetEffect(3), 0); + ability.addEffect(new GarrukRelentlessDamageEffect()); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); // 0: Create a 2/2 green Wolf creature token. - LoyaltyAbility ability2 = new LoyaltyAbility(new CreateTokenEffect(new WolfToken()), 0); - this.addAbility(ability2); + this.addAbility(new LoyaltyAbility(new CreateTokenEffect(new WolfToken()), 0)); } private GarrukRelentless(final GarrukRelentless card) { @@ -89,7 +89,7 @@ class GarrukRelentlessDamageEffect extends OneShotEffect { GarrukRelentlessDamageEffect() { super(Outcome.Damage); - staticText = "{this} deals 3 damage to target creature. That creature deals damage equal to its power to him"; + staticText = "That creature deals damage equal to its power to him"; } private GarrukRelentlessDamageEffect(final GarrukRelentlessDamageEffect effect) { @@ -98,19 +98,11 @@ class GarrukRelentlessDamageEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); - if (permanent != null) { - int damage = permanent.getPower().getValue(); - permanent.damage(3, source.getSourceId(), source, game, false, true); - if (damage > 0) { - Permanent garruk = game.getPermanent(source.getSourceId()); - if (garruk != null) { - garruk.damage(damage, permanent.getId(), source, game, false, true); - } - } - return true; - } - return false; + Permanent permanent = source.getSourcePermanentIfItStillExists(game); + Permanent creature = game.getPermanentOrLKIBattlefield(getTargetPointer().getFirst(game, source)); + return permanent != null + && creature != null + && permanent.damage(creature.getPower().getValue(), creature.getId(), source, game) > 0; } @Override 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/GideonBattleForged.java b/Mage.Sets/src/mage/cards/g/GideonBattleForged.java index a2adb7e3c1a..a1158494564 100644 --- a/Mage.Sets/src/mage/cards/g/GideonBattleForged.java +++ b/Mage.Sets/src/mage/cards/g/GideonBattleForged.java @@ -1,10 +1,8 @@ package mage.cards.g; -import mage.MageInt; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.LoyaltyAbility; -import mage.abilities.effects.Effect; import mage.abilities.effects.RequirementEffect; import mage.abilities.effects.common.PreventAllDamageToSourceEffect; import mage.abilities.effects.common.UntapTargetEffect; @@ -14,12 +12,11 @@ import mage.abilities.keyword.IndestructibleAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; -import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.game.permanent.token.TokenImpl; -import mage.target.TargetPermanent; +import mage.game.permanent.token.custom.CreatureToken; import mage.target.common.TargetCreaturePermanent; +import mage.target.common.TargetOpponentsCreaturePermanent; import java.util.UUID; @@ -28,12 +25,6 @@ import java.util.UUID; */ public final class GideonBattleForged extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); - - static { - filter.add(TargetController.OPPONENT.getControllerPredicate()); - } - public GideonBattleForged(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, ""); this.supertype.add(SuperType.LEGENDARY); @@ -46,27 +37,26 @@ public final class GideonBattleForged extends CardImpl { this.setStartingLoyalty(3); // +2: Up to one target creature an opponent controls attacks Gideon, Battle-Forged during its controller's next turn if able. - LoyaltyAbility loyaltyAbility = new LoyaltyAbility(new GideonBattleForgedAttacksIfAbleTargetEffect(Duration.Custom), 2); - loyaltyAbility.addTarget(new TargetPermanent(0, 1, filter)); - this.addAbility(loyaltyAbility); + Ability ability = new LoyaltyAbility(new GideonBattleForgedEffect(), 2); + ability.addTarget(new TargetOpponentsCreaturePermanent(0, 1)); + this.addAbility(ability); // +1: Until your next turn, target creature gains indestructible. Untap that creature. - Effect effect = new GainAbilityTargetEffect(IndestructibleAbility.getInstance(), Duration.UntilYourNextTurn); - effect.setText("Until your next turn, target creature gains indestructible"); - loyaltyAbility = new LoyaltyAbility(effect, 1); - loyaltyAbility.addTarget(new TargetCreaturePermanent()); - effect = new UntapTargetEffect(); - effect.setText("Untap that creature"); - loyaltyAbility.addEffect(effect); - this.addAbility(loyaltyAbility); + ability = new LoyaltyAbility(new GainAbilityTargetEffect( + IndestructibleAbility.getInstance(), Duration.UntilYourNextTurn + ).setText("Until your next turn, target creature gains indestructible"), 1); + ability.addEffect(new UntapTargetEffect().setText("Untap that creature")); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); // 0: Until end of turn, Gideon, Battle-Forged becomes a 4/4 Human Soldier creature with indestructible that's still a planeswalker. Prevent all damage that would be dealt to him this turn. - LoyaltyAbility ability3 = new LoyaltyAbility(new BecomesCreatureSourceEffect(new GideonBattleForgedToken(), CardType.PLANESWALKER, Duration.EndOfTurn), 0); - effect = new PreventAllDamageToSourceEffect(Duration.EndOfTurn); - effect.setText("Prevent all damage that would be dealt to him this turn"); - ability3.addEffect(effect); - this.addAbility(ability3); - + ability = new LoyaltyAbility(new BecomesCreatureSourceEffect(new CreatureToken( + 4, 4, "4/4 Human Soldier creature " + + "with indestructible", SubType.HUMAN, SubType.SOLDIER + ).withAbility(IndestructibleAbility.getInstance()), CardType.PLANESWALKER, Duration.EndOfTurn), 0); + ability.addEffect(new PreventAllDamageToSourceEffect(Duration.EndOfTurn) + .setText("Prevent all damage that would be dealt to him this turn")); + this.addAbility(ability); } private GideonBattleForged(final GideonBattleForged card) { @@ -79,44 +69,23 @@ public final class GideonBattleForged extends CardImpl { } } -class GideonBattleForgedToken extends TokenImpl { - - public GideonBattleForgedToken() { - super("", "4/4 Human Soldier creature with indestructible"); - cardType.add(CardType.CREATURE); - subtype.add(SubType.HUMAN); - subtype.add(SubType.SOLDIER); - power = new MageInt(4); - toughness = new MageInt(4); - this.addAbility(IndestructibleAbility.getInstance()); - } - - private GideonBattleForgedToken(final GideonBattleForgedToken token) { - super(token); - } - - public GideonBattleForgedToken copy() { - return new GideonBattleForgedToken(this); - } -} - -class GideonBattleForgedAttacksIfAbleTargetEffect extends RequirementEffect { +class GideonBattleForgedEffect extends RequirementEffect { protected MageObjectReference targetPermanentReference; - public GideonBattleForgedAttacksIfAbleTargetEffect(Duration duration) { - super(duration); - staticText = "Up to one target creature an opponent controls attacks {this} during its controller's next turn if able"; + GideonBattleForgedEffect() { + super(Duration.Custom); + staticText = "up to one target creature an opponent controls attacks {this} during its controller's next turn if able"; } - private GideonBattleForgedAttacksIfAbleTargetEffect(final GideonBattleForgedAttacksIfAbleTargetEffect effect) { + private GideonBattleForgedEffect(final GideonBattleForgedEffect effect) { super(effect); this.targetPermanentReference = effect.targetPermanentReference; } @Override - public GideonBattleForgedAttacksIfAbleTargetEffect copy() { - return new GideonBattleForgedAttacksIfAbleTargetEffect(this); + public GideonBattleForgedEffect copy() { + return new GideonBattleForgedEffect(this); } @Override @@ -143,17 +112,16 @@ class GideonBattleForgedAttacksIfAbleTargetEffect extends RequirementEffect { @Override public boolean applies(Permanent permanent, Ability source, Game game) { - if (permanent.getId().equals(getTargetPointer().getFirst(game, source))) { - if (game.isActivePlayer(permanent.getControllerId())) { - Permanent planeswalker = game.getPermanent(source.getSourceId()); - if (planeswalker != null) { - return true; - } else { - discard(); - } - } + if (!permanent.getId().equals(getTargetPointer().getFirst(game, source)) + || !game.isActivePlayer(permanent.getControllerId())) { + return false; } - return false; + Permanent planeswalker = source.getSourcePermanentIfItStillExists(game); + if (planeswalker == null) { + discard(); + return false; + } + return true; } @Override @@ -170,5 +138,4 @@ class GideonBattleForgedAttacksIfAbleTargetEffect extends RequirementEffect { public boolean mustBlock(Game game) { return false; } - } diff --git a/Mage.Sets/src/mage/cards/g/GoldenGuardian.java b/Mage.Sets/src/mage/cards/g/GoldenGuardian.java index af1a5657715..d30b0a5cf7a 100644 --- a/Mage.Sets/src/mage/cards/g/GoldenGuardian.java +++ b/Mage.Sets/src/mage/cards/g/GoldenGuardian.java @@ -104,17 +104,11 @@ class GoldenGuardianReturnTransformedEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - if (game.getState().getZone(source.getSourceId()) == Zone.GRAVEYARD) { - game.getState().setValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + source.getSourceId(), Boolean.TRUE); - Card card = game.getCard(source.getSourceId()); - if (card != null) { - controller.moveCards(card, Zone.BATTLEFIELD, source, game); - } - } - return true; + if (controller == null || game.getState().getZone(source.getSourceId()) != Zone.GRAVEYARD) { + return false; } - return false; + game.getState().setValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + source.getSourceId(), Boolean.TRUE); + Card card = game.getCard(source.getSourceId()); + return card != null && controller.moveCards(card, Zone.BATTLEFIELD, source, game); } - } diff --git a/Mage.Sets/src/mage/cards/g/GrislyAnglerfish.java b/Mage.Sets/src/mage/cards/g/GrislyAnglerfish.java index 60a4e8a6058..a8eace0c588 100644 --- a/Mage.Sets/src/mage/cards/g/GrislyAnglerfish.java +++ b/Mage.Sets/src/mage/cards/g/GrislyAnglerfish.java @@ -1,29 +1,25 @@ - package mage.cards.g; -import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.RequirementEffect; +import mage.abilities.effects.common.combat.AttacksIfAbleAllEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Duration; -import mage.constants.Zone; -import mage.game.Game; -import mage.game.permanent.Permanent; +import mage.constants.SubType; +import mage.filter.StaticFilters; + +import java.util.UUID; /** - * * @author fireshoes */ public final class GrislyAnglerfish extends CardImpl { public GrislyAnglerfish(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},""); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, ""); this.subtype.add(SubType.ELDRAZI); this.subtype.add(SubType.FISH); this.power = new MageInt(4); @@ -33,7 +29,9 @@ public final class GrislyAnglerfish extends CardImpl { this.nightCard = true; // {6}: Creatures your opponents control attack this turn if able. - this.addAbility(new SimpleActivatedAbility(new GrislyAnglerfishMustAttackEffect(), new ManaCostsImpl<>("{6}"))); + this.addAbility(new SimpleActivatedAbility(new AttacksIfAbleAllEffect( + StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURES, Duration.EndOfTurn + ), new ManaCostsImpl<>("{6}"))); } private GrislyAnglerfish(final GrislyAnglerfish card) { @@ -45,39 +43,3 @@ public final class GrislyAnglerfish extends CardImpl { return new GrislyAnglerfish(this); } } - -class GrislyAnglerfishMustAttackEffect extends RequirementEffect { - - GrislyAnglerfishMustAttackEffect() { - super(Duration.EndOfTurn); - staticText = "Creatures your opponents control attack this turn if able"; - } - - private GrislyAnglerfishMustAttackEffect(final GrislyAnglerfishMustAttackEffect effect) { - super(effect); - } - - @Override - public GrislyAnglerfishMustAttackEffect copy() { - return new GrislyAnglerfishMustAttackEffect(this); - } - - @Override - public boolean applies(Permanent permanent, Ability source, Game game) { - if (game.getOpponents(source.getControllerId()).contains(permanent.getControllerId())) { - return true; - } - return false; - } - - @Override - public boolean mustAttack(Game game) { - return true; - } - - @Override - public boolean mustBlock(Game game) { - return false; - } - -} diff --git a/Mage.Sets/src/mage/cards/g/GrizzledAngler.java b/Mage.Sets/src/mage/cards/g/GrizzledAngler.java index 9b31af0fff7..dbe16de1fbc 100644 --- a/Mage.Sets/src/mage/cards/g/GrizzledAngler.java +++ b/Mage.Sets/src/mage/cards/g/GrizzledAngler.java @@ -1,23 +1,22 @@ - package mage.cards.g; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.CardsInControllerGraveyardCondition; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.common.MillCardsControllerEffect; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.SubType; -import mage.constants.Zone; +import mage.filter.FilterCard; import mage.filter.common.FilterCreatureCard; import mage.filter.predicate.mageobject.ColorlessPredicate; -import mage.game.Game; -import mage.players.Player; import java.util.UUID; @@ -26,6 +25,14 @@ import java.util.UUID; */ public final class GrizzledAngler extends CardImpl { + private static final FilterCard filter = new FilterCreatureCard(); + + static { + filter.add(ColorlessPredicate.instance); + } + + private static final Condition condition = new CardsInControllerGraveyardCondition(1, filter); + public GrizzledAngler(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}"); this.subtype.add(SubType.HUMAN); @@ -36,7 +43,11 @@ public final class GrizzledAngler extends CardImpl { // {T}: Put the top two cards of your library into your graveyard. Then if there is a colorless creature card in your graveyard, transform Grizzled Angler. this.addAbility(new TransformAbility()); - this.addAbility(new SimpleActivatedAbility(new GrizzledAnglerEffect(), new TapSourceCost())); + Ability ability = new SimpleActivatedAbility(new MillCardsControllerEffect(2), new TapSourceCost()); + ability.addEffect(new ConditionalOneShotEffect( + new TransformSourceEffect(), condition, + "Then if there is a colorless creature card in your graveyard, transform {this}" + )); } private GrizzledAngler(final GrizzledAngler card) { @@ -48,38 +59,3 @@ public final class GrizzledAngler extends CardImpl { return new GrizzledAngler(this); } } - -class GrizzledAnglerEffect extends OneShotEffect { - - private static final FilterCreatureCard filter = new FilterCreatureCard("a colorless creature card in your graveyard"); - - static { - filter.add(ColorlessPredicate.instance); - } - - public GrizzledAnglerEffect() { - super(Outcome.Benefit); - staticText = "Mill two cards. Then if there is a colorless creature card in your graveyard, transform {this}"; - } - - private GrizzledAnglerEffect(final GrizzledAnglerEffect effect) { - super(effect); - } - - @Override - public GrizzledAnglerEffect copy() { - return new GrizzledAnglerEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - controller.millCards(2, source, game); - if (controller.getGraveyard().count(filter, source.getControllerId(), source, game) >= 1) { - return new TransformSourceEffect().apply(game, source); - } - } - return false; - } -} 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/i/InsidiousMist.java b/Mage.Sets/src/mage/cards/i/InsidiousMist.java index fee4e67eaf6..25546fc0589 100644 --- a/Mage.Sets/src/mage/cards/i/InsidiousMist.java +++ b/Mage.Sets/src/mage/cards/i/InsidiousMist.java @@ -1,13 +1,10 @@ - package mage.cards.i; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AttacksAndIsNotBlockedTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.DoIfCostPaid; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.effects.common.combat.CantBeBlockedSourceEffect; @@ -18,18 +15,18 @@ import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Duration; -import mage.constants.Zone; +import mage.constants.SubType; + +import java.util.UUID; /** - * * @author fireshoes */ public final class InsidiousMist extends CardImpl { public InsidiousMist(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},""); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, ""); this.subtype.add(SubType.ELEMENTAL); this.power = new MageInt(0); this.toughness = new MageInt(1); @@ -45,9 +42,7 @@ public final class InsidiousMist extends CardImpl { // Insideous Mist can't block and can't be blocked. Ability ability = new SimpleStaticAbility(new CantBlockSourceEffect(Duration.WhileOnBattlefield)); - Effect effect = new CantBeBlockedSourceEffect(); - effect.setText("and can't be blocked"); - ability.addEffect(effect); + ability.addEffect(new CantBeBlockedSourceEffect().setText("and can't be blocked")); this.addAbility(ability); // Whenever Insideous Mist attacks and isn't blocked, you may pay {2}{B}. If you do, transform it. diff --git a/Mage.Sets/src/mage/cards/j/JaceTelepathUnbound.java b/Mage.Sets/src/mage/cards/j/JaceTelepathUnbound.java index bcf3a7cd88e..66e1b793d62 100644 --- a/Mage.Sets/src/mage/cards/j/JaceTelepathUnbound.java +++ b/Mage.Sets/src/mage/cards/j/JaceTelepathUnbound.java @@ -2,7 +2,6 @@ package mage.cards.j; import mage.abilities.Ability; import mage.abilities.LoyaltyAbility; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.GetEmblemEffect; import mage.abilities.effects.common.MayCastTargetCardEffect; import mage.abilities.effects.common.continuous.BoostTargetEffect; @@ -35,9 +34,9 @@ public final class JaceTelepathUnbound extends CardImpl { this.setStartingLoyalty(5); // +1: Up to one target creature gets -2/-0 until your next turn. - Effect effect = new BoostTargetEffect(-2, 0, Duration.UntilYourNextTurn); - effect.setText("Up to one target creature gets -2/-0 until your next turn"); - Ability ability = new LoyaltyAbility(effect, 1); + Ability ability = new LoyaltyAbility(new BoostTargetEffect( + -2, 0, Duration.UntilYourNextTurn + ).setText("Up to one target creature gets -2/-0 until your next turn"), 1); ability.addTarget(new TargetCreaturePermanent(0, 1)); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/j/JaceVrynsProdigy.java b/Mage.Sets/src/mage/cards/j/JaceVrynsProdigy.java index 12945820c6f..7c8eb721011 100644 --- a/Mage.Sets/src/mage/cards/j/JaceVrynsProdigy.java +++ b/Mage.Sets/src/mage/cards/j/JaceVrynsProdigy.java @@ -1,15 +1,12 @@ - package mage.cards.j; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.constants.Pronoun; import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.CardsInControllerGraveyardCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.decorator.ConditionalOneShotEffect; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.DrawDiscardControllerEffect; import mage.abilities.effects.common.ExileAndReturnSourceEffect; import mage.abilities.keyword.TransformAbility; @@ -17,14 +14,17 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class JaceVrynsProdigy extends CardImpl { + private static final Condition condition = new CardsInControllerGraveyardCondition(5); + public JaceVrynsProdigy(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}"); this.supertype.add(SuperType.LEGENDARY); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.WIZARD); @@ -35,11 +35,13 @@ public final class JaceVrynsProdigy extends CardImpl { // {T}: Draw a card, then discard a card. If there are five or more cards in your graveyard, exile Jace, Vryn's Prodigy, then return him to the battefield transformed under his owner's control. this.addAbility(new TransformAbility()); - Ability ability = new SimpleActivatedAbility(new DrawDiscardControllerEffect(1, 1), new TapSourceCost()); - Effect effect = new ConditionalOneShotEffect(new ExileAndReturnSourceEffect(PutCards.BATTLEFIELD_TRANSFORMED,Pronoun.HE), new CardsInControllerGraveyardCondition(5)); - ability.addEffect(effect); + Ability ability = new SimpleActivatedAbility( + new DrawDiscardControllerEffect(1, 1), new TapSourceCost() + ); + ability.addEffect(new ConditionalOneShotEffect( + new ExileAndReturnSourceEffect(PutCards.BATTLEFIELD_TRANSFORMED, Pronoun.HE), condition + )); this.addAbility(ability); - } private JaceVrynsProdigy(final JaceVrynsProdigy card) { diff --git a/Mage.Sets/src/mage/cards/j/JourneyToEternity.java b/Mage.Sets/src/mage/cards/j/JourneyToEternity.java index ef16a392044..f3759a3341d 100644 --- a/Mage.Sets/src/mage/cards/j/JourneyToEternity.java +++ b/Mage.Sets/src/mage/cards/j/JourneyToEternity.java @@ -1,8 +1,6 @@ package mage.cards.j; -import java.util.UUID; - import mage.abilities.Ability; import mage.abilities.common.DiesAttachedTriggeredAbility; import mage.abilities.effects.OneShotEffect; @@ -13,16 +11,14 @@ import mage.abilities.keyword.TransformAbility; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.SubType; -import mage.constants.SuperType; -import mage.constants.Zone; +import mage.constants.*; import mage.filter.StaticFilters; import mage.game.Game; import mage.players.Player; import mage.target.TargetPermanent; +import java.util.UUID; + /** * @author LevelX2 */ @@ -40,12 +36,11 @@ public final class JourneyToEternity extends CardImpl { TargetPermanent auraTarget = new TargetPermanent(StaticFilters.FILTER_PERMANENT_CREATURE_CONTROLLED); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); - Ability ability = new EnchantAbility(auraTarget); - this.addAbility(ability); + this.addAbility(new EnchantAbility(auraTarget)); // When enchanted creature dies, return it to the battlefield under your control, then return Journey to Eternity to the battlefield transformed under your control. this.addAbility(new TransformAbility()); - ability = new DiesAttachedTriggeredAbility(new ReturnToBattlefieldUnderYourControlAttachedEffect("it"), "enchanted creature"); + Ability ability = new DiesAttachedTriggeredAbility(new ReturnToBattlefieldUnderYourControlAttachedEffect("it"), "enchanted creature"); ability.addEffect(new JourneyToEternityReturnTransformedSourceEffect()); this.addAbility(ability); 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/LambholtPacifist.java b/Mage.Sets/src/mage/cards/l/LambholtPacifist.java index baf535a3d1d..36969373dc5 100644 --- a/Mage.Sets/src/mage/cards/l/LambholtPacifist.java +++ b/Mage.Sets/src/mage/cards/l/LambholtPacifist.java @@ -1,18 +1,20 @@ package mage.cards.l; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.WerewolfFrontTriggeredAbility; -import mage.abilities.effects.RestrictionEffect; +import mage.abilities.condition.Condition; +import mage.abilities.condition.InvertCondition; +import mage.abilities.condition.common.FerociousCondition; +import mage.abilities.decorator.ConditionalRestrictionEffect; +import mage.abilities.effects.common.combat.CantAttackSourceEffect; +import mage.abilities.hint.common.FerociousHint; import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; -import mage.filter.common.FilterControlledCreaturePermanent; -import mage.filter.predicate.mageobject.PowerPredicate; -import mage.game.Game; -import mage.game.permanent.Permanent; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; import java.util.UUID; @@ -21,6 +23,8 @@ import java.util.UUID; */ public final class LambholtPacifist extends CardImpl { + private static final Condition condition = new InvertCondition(FerociousCondition.instance); + public LambholtPacifist(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}"); this.subtype.add(SubType.HUMAN); @@ -32,7 +36,10 @@ public final class LambholtPacifist extends CardImpl { this.secondSideCardClazz = mage.cards.l.LambholtButcher.class; // Lambholt Pacifist can't attack unless you control a creature with power 4 or greater. - this.addAbility(new SimpleStaticAbility(new LambholtPacifistEffect())); + this.addAbility(new SimpleStaticAbility(new ConditionalRestrictionEffect( + new CantAttackSourceEffect(Duration.WhileOnBattlefield), condition, + "{this} can't attack unless you control a creature with power 4 or greater" + )).addHint(FerociousHint.instance)); // At the beginning of each upkeep, if no spells were cast last turn, transform Lambholt Pacifist. this.addAbility(new TransformAbility()); @@ -48,39 +55,3 @@ public final class LambholtPacifist extends CardImpl { return new LambholtPacifist(this); } } - -class LambholtPacifistEffect extends RestrictionEffect { - - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("a creature with power 4 or greater"); - - static { - filter.add(new PowerPredicate(ComparisonType.MORE_THAN, 3)); - } - - public LambholtPacifistEffect() { - super(Duration.WhileOnBattlefield); - staticText = "{this} can't attack unless you control a creature with power 4 or greater"; - } - - private LambholtPacifistEffect(final LambholtPacifistEffect effect) { - super(effect); - } - - @Override - public LambholtPacifistEffect copy() { - return new LambholtPacifistEffect(this); - } - - @Override - public boolean canAttack(Game game, boolean canUseChooseDialogs) { - return false; - } - - @Override - public boolean applies(Permanent permanent, Ability source, Game game) { - if (permanent.getId().equals(source.getSourceId())) { - return game.getBattlefield().countAll(filter, source.getControllerId(), game) <= 0; - } // do not apply to other creatures. - return false; - } -} 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/LegionsLanding.java b/Mage.Sets/src/mage/cards/l/LegionsLanding.java index deca2d827c1..7051affd2a3 100644 --- a/Mage.Sets/src/mage/cards/l/LegionsLanding.java +++ b/Mage.Sets/src/mage/cards/l/LegionsLanding.java @@ -1,23 +1,19 @@ package mage.cards.l; -import java.util.UUID; - -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.AttacksWithCreaturesTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; -import mage.constants.SuperType; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Zone; -import mage.game.Game; -import mage.game.events.GameEvent; +import mage.constants.SuperType; import mage.game.permanent.token.IxalanVampireToken; +import java.util.UUID; + /** * @author TheElk801 */ @@ -35,7 +31,7 @@ public final class LegionsLanding extends CardImpl { // When you attack with three or more creatures, transform Legion's Landing. this.addAbility(new TransformAbility()); - this.addAbility(new LegionsLandingTriggeredAbility(new TransformSourceEffect())); + this.addAbility(new AttacksWithCreaturesTriggeredAbility(new TransformSourceEffect(), 3).setTriggerPhrase("When you attack with three or more creatures, ")); } private LegionsLanding(final LegionsLanding card) { @@ -47,30 +43,3 @@ public final class LegionsLanding extends CardImpl { return new LegionsLanding(this); } } - -class LegionsLandingTriggeredAbility extends TriggeredAbilityImpl { - - public LegionsLandingTriggeredAbility(Effect effect) { - super(Zone.BATTLEFIELD, effect, false); - setTriggerPhrase("When you attack with three or more creatures, " ); - } - - private LegionsLandingTriggeredAbility(final LegionsLandingTriggeredAbility ability) { - super(ability); - } - - @Override - public LegionsLandingTriggeredAbility copy() { - return new LegionsLandingTriggeredAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.DECLARED_ATTACKERS; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - return game.getCombat().getAttackers().size() >= 3 && game.getCombat().getAttackingPlayerId().equals(getControllerId()); - } -} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/l/LilianaDefiantNecromancer.java b/Mage.Sets/src/mage/cards/l/LilianaDefiantNecromancer.java index cefbd5b0def..a4250a436d0 100644 --- a/Mage.Sets/src/mage/cards/l/LilianaDefiantNecromancer.java +++ b/Mage.Sets/src/mage/cards/l/LilianaDefiantNecromancer.java @@ -23,7 +23,7 @@ import java.util.UUID; */ public final class LilianaDefiantNecromancer extends CardImpl { - protected static final FilterCreatureCard filter = new FilterCreatureCard("nonlegendary creature card with mana value X from your graveyard"); + private static final FilterCreatureCard filter = new FilterCreatureCard("nonlegendary creature card with mana value X from your graveyard"); static { filter.add(Predicates.not(SuperType.LEGENDARY.getPredicate())); diff --git a/Mage.Sets/src/mage/cards/l/LilianaHereticalHealer.java b/Mage.Sets/src/mage/cards/l/LilianaHereticalHealer.java index e0c42b03e97..2f3557624a4 100644 --- a/Mage.Sets/src/mage/cards/l/LilianaHereticalHealer.java +++ b/Mage.Sets/src/mage/cards/l/LilianaHereticalHealer.java @@ -1,7 +1,6 @@ package mage.cards.l; import mage.MageInt; -import mage.constants.Pronoun; import mage.abilities.common.DiesCreatureTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.ExileAndReturnSourceEffect; @@ -10,7 +9,8 @@ import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; -import mage.filter.common.FilterCreaturePermanent; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.mageobject.AnotherPredicate; import mage.filter.predicate.permanent.TokenPredicate; import mage.game.permanent.token.ZombieToken; @@ -22,10 +22,9 @@ import java.util.UUID; */ public final class LilianaHereticalHealer extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another nontoken creature you control"); + private static final FilterPermanent filter = new FilterControlledCreaturePermanent("another nontoken creature you control"); static { - filter.add(TargetController.YOU.getControllerPredicate()); filter.add(AnotherPredicate.instance); filter.add(TokenPredicate.FALSE); } diff --git a/Mage.Sets/src/mage/cards/l/LoneRider.java b/Mage.Sets/src/mage/cards/l/LoneRider.java index 4043af88cec..c6450c5473a 100644 --- a/Mage.Sets/src/mage/cards/l/LoneRider.java +++ b/Mage.Sets/src/mage/cards/l/LoneRider.java @@ -3,9 +3,8 @@ package mage.cards.l; import mage.MageInt; import mage.abilities.condition.Condition; import mage.abilities.condition.common.YouGainedLifeCondition; +import mage.abilities.dynamicvalue.common.ControllerGainedLifeCount; import mage.abilities.effects.common.TransformSourceEffect; -import mage.abilities.hint.ConditionHint; -import mage.abilities.hint.Hint; import mage.abilities.keyword.FirstStrikeAbility; import mage.abilities.keyword.LifelinkAbility; import mage.abilities.keyword.TransformAbility; @@ -26,7 +25,6 @@ import java.util.UUID; public final class LoneRider extends CardImpl { private static final Condition condition = new YouGainedLifeCondition(ComparisonType.MORE_THAN, 2); - private static final Hint hint = new ConditionHint(condition); public LoneRider(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}"); @@ -47,7 +45,7 @@ public final class LoneRider extends CardImpl { this.addAbility(new TransformAbility()); this.addAbility(new BeginningOfEndStepTriggeredAbility( TargetController.NEXT, new TransformSourceEffect(), false - ).withInterveningIf(condition).addHint(hint), new PlayerGainedLifeWatcher()); + ).withInterveningIf(condition).addHint(ControllerGainedLifeCount.getHint()), new PlayerGainedLifeWatcher()); } private LoneRider(final LoneRider card) { diff --git a/Mage.Sets/src/mage/cards/l/LostVale.java b/Mage.Sets/src/mage/cards/l/LostVale.java index 0c9a1ee88bb..2936d1430ff 100644 --- a/Mage.Sets/src/mage/cards/l/LostVale.java +++ b/Mage.Sets/src/mage/cards/l/LostVale.java @@ -1,17 +1,15 @@ - package mage.cards.l; -import java.util.UUID; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.effects.mana.AddManaOfAnyColorEffect; import mage.abilities.mana.SimpleManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Zone; + +import java.util.UUID; /** - * * @author TheElk801 */ public final class LostVale extends CardImpl { @@ -22,7 +20,7 @@ public final class LostVale extends CardImpl { this.nightCard = true; // T: Add three mana of any one color. - this.addAbility(new SimpleManaAbility(Zone.BATTLEFIELD, new AddManaOfAnyColorEffect(3), new TapSourceCost())); + this.addAbility(new SimpleManaAbility(new AddManaOfAnyColorEffect(3), new TapSourceCost())); } private LostVale(final LostVale card) { diff --git a/Mage.Sets/src/mage/cards/l/LudevicsTestSubject.java b/Mage.Sets/src/mage/cards/l/LudevicsTestSubject.java index e14febe228d..4dd297875f1 100644 --- a/Mage.Sets/src/mage/cards/l/LudevicsTestSubject.java +++ b/Mage.Sets/src/mage/cards/l/LudevicsTestSubject.java @@ -1,11 +1,13 @@ - package mage.cards.l; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.SourceHasCounterCondition; 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.counter.AddCountersSourceEffect; import mage.abilities.keyword.DefenderAbility; @@ -13,12 +15,8 @@ import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; 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; import java.util.UUID; @@ -27,6 +25,8 @@ import java.util.UUID; */ public final class LudevicsTestSubject extends CardImpl { + private static final Condition condition = new SourceHasCounterCondition(CounterType.HATCHLING, 5); + public LudevicsTestSubject(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}"); this.subtype.add(SubType.LIZARD, SubType.EGG); @@ -37,10 +37,16 @@ public final class LudevicsTestSubject extends CardImpl { this.secondSideCardClazz = mage.cards.l.LudevicsAbomination.class; this.addAbility(DefenderAbility.getInstance()); + // {1}{U}: Put a hatchling counter on Ludevic's Test Subject. Then if there are five or more hatchling counters on it, remove all of them and transform it. this.addAbility(new TransformAbility()); - Ability ability = new SimpleActivatedAbility(new AddCountersSourceEffect(CounterType.HATCHLING.createInstance()), new ManaCostsImpl<>("{1}{U}")); - ability.addEffect(new LudevicsTestSubjectEffect()); + Ability ability = new SimpleActivatedAbility( + new AddCountersSourceEffect(CounterType.HATCHLING.createInstance()), new ManaCostsImpl<>("{1}{U}") + ); + ability.addEffect(new ConditionalOneShotEffect( + new RemoveAllCountersSourceEffect(CounterType.HATCHLING), condition, + "Then if there are five or more hatchling counters on it, remove all of them and transform it" + ).addEffect(new TransformSourceEffect())); this.addAbility(ability); } @@ -53,35 +59,3 @@ public final class LudevicsTestSubject extends CardImpl { return new LudevicsTestSubject(this); } } - -class LudevicsTestSubjectEffect extends OneShotEffect { - - LudevicsTestSubjectEffect() { - super(Outcome.Benefit); - staticText = "Then if there are five or more hatchling counters on it, remove all of them and transform it"; - } - - private LudevicsTestSubjectEffect(final LudevicsTestSubjectEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent == null) { - return false; - } - - if (permanent.getCounters(game).getCount(CounterType.HATCHLING) >= 5) { - permanent.removeAllCounters(CounterType.HATCHLING.getName(), source, game); - TransformSourceEffect effect = new TransformSourceEffect(); - return effect.apply(game, source); - } - return false; - } - - @Override - public LudevicsTestSubjectEffect copy() { - return new LudevicsTestSubjectEffect(this); - } -} 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/l/LunarchInquisitors.java b/Mage.Sets/src/mage/cards/l/LunarchInquisitors.java index 715cfc59b25..191be943d48 100644 --- a/Mage.Sets/src/mage/cards/l/LunarchInquisitors.java +++ b/Mage.Sets/src/mage/cards/l/LunarchInquisitors.java @@ -8,9 +8,7 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.filter.FilterPermanent; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.filter.StaticFilters; import mage.target.TargetPermanent; import java.util.UUID; @@ -20,12 +18,6 @@ import java.util.UUID; */ public final class LunarchInquisitors extends CardImpl { - private static final FilterPermanent filter = new FilterCreaturePermanent("another target creature"); - - static { - filter.add(AnotherPredicate.instance); - } - public LunarchInquisitors(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, ""); this.subtype.add(SubType.HUMAN); @@ -39,7 +31,7 @@ public final class LunarchInquisitors extends CardImpl { // When this creature transforms into Lunarch Inquisitors, you may exile another target creature until Lunarch Inquisitors leaves the battlefield. Ability ability = new TransformIntoSourceTriggeredAbility(new ExileUntilSourceLeavesEffect(), true); - ability.addTarget(new TargetPermanent(filter)); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/m/MetzaliTowerOfTriumph.java b/Mage.Sets/src/mage/cards/m/MetzaliTowerOfTriumph.java index 0581ccc1d20..8ff50743a8a 100644 --- a/Mage.Sets/src/mage/cards/m/MetzaliTowerOfTriumph.java +++ b/Mage.Sets/src/mage/cards/m/MetzaliTowerOfTriumph.java @@ -1,10 +1,5 @@ package mage.cards.m; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; -import java.util.UUID; -import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapSourceCost; @@ -18,15 +13,16 @@ import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.SuperType; import mage.constants.TargetController; -import mage.constants.Zone; import mage.game.Game; import mage.game.permanent.Permanent; import mage.util.RandomUtil; -import mage.watchers.Watcher; import mage.watchers.common.AttackedThisTurnWatcher; +import java.util.Objects; +import java.util.UUID; +import java.util.stream.Collectors; + /** - * * @author LevelX2 */ public final class MetzaliTowerOfTriumph extends CardImpl { @@ -51,7 +47,6 @@ public final class MetzaliTowerOfTriumph extends CardImpl { ability = new SimpleActivatedAbility(new MetzaliTowerOfTriumphEffect(), new ManaCostsImpl<>("{2}{W}")); ability.addCost(new TapSourceCost()); this.addAbility(ability); - } private MetzaliTowerOfTriumph(final MetzaliTowerOfTriumph card) { @@ -69,7 +64,7 @@ class MetzaliTowerOfTriumphEffect extends OneShotEffect { MetzaliTowerOfTriumphEffect() { super(Outcome.DestroyPermanent); - this.staticText = "Choose a creature at random that attacked this turn. Destroy that creature"; + this.staticText = "choose a creature at random that attacked this turn. Destroy that creature"; } private MetzaliTowerOfTriumphEffect(final MetzaliTowerOfTriumphEffect effect) { @@ -83,24 +78,15 @@ class MetzaliTowerOfTriumphEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Watcher watcher = game.getState().getWatcher(AttackedThisTurnWatcher.class); - if (watcher instanceof AttackedThisTurnWatcher) { - Set attackedThisTurn = ((AttackedThisTurnWatcher) watcher).getAttackedThisTurnCreatures(); - List available = new ArrayList<>(); - for (MageObjectReference mor : attackedThisTurn) { - Permanent permanent = mor.getPermanent(game); - if (permanent != null && permanent.isCreature(game)) { - available.add(permanent); - } - } - if (!available.isEmpty()) { - Permanent permanent = available.get(RandomUtil.nextInt(available.size())); - if (permanent != null) { - permanent.destroy(source, game, false); - } - } - return true; - } - return false; + Permanent permanent = RandomUtil.randomFromCollection( + game.getState() + .getWatcher(AttackedThisTurnWatcher.class) + .getAttackedThisTurnCreatures() + .stream() + .map(mor -> mor.getPermanent(game)) + .filter(Objects::nonNull) + .collect(Collectors.toSet()) + ); + return permanent != null && permanent.destroy(source, game); } } 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/n/NeglectedHeirloom.java b/Mage.Sets/src/mage/cards/n/NeglectedHeirloom.java index a4db3dfc9be..9fa4c5d6e11 100644 --- a/Mage.Sets/src/mage/cards/n/NeglectedHeirloom.java +++ b/Mage.Sets/src/mage/cards/n/NeglectedHeirloom.java @@ -2,7 +2,6 @@ package mage.cards.n; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.effects.common.continuous.BoostEquippedEffect; import mage.abilities.keyword.EquipAbility; @@ -10,13 +9,13 @@ import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.SubType; import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.game.permanent.Permanent; +import java.util.Optional; import java.util.UUID; /** @@ -38,7 +37,7 @@ public final class NeglectedHeirloom extends CardImpl { this.addAbility(new NeglectedHeirloomTriggeredAbility()); // Equip {1} - this.addAbility(new EquipAbility(Outcome.BoostCreature, new GenericManaCost(1), new TargetControlledCreaturePermanent(), false)); + this.addAbility(new EquipAbility(1, false)); } private NeglectedHeirloom(final NeglectedHeirloom card) { @@ -56,6 +55,7 @@ class NeglectedHeirloomTriggeredAbility extends TriggeredAbilityImpl { public NeglectedHeirloomTriggeredAbility() { super(Zone.BATTLEFIELD, new TransformSourceEffect(), false); + setTriggerPhrase("When equipped creature transforms, "); } private NeglectedHeirloomTriggeredAbility(final NeglectedHeirloomTriggeredAbility ability) { @@ -69,21 +69,15 @@ class NeglectedHeirloomTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - if (event.getType() == GameEvent.EventType.TRANSFORMED) { - if (game.getPermanent(event.getTargetId()).getAttachments().contains(this.getSourceId())) { - return true; - } - } - return false; + return Optional + .ofNullable(getSourcePermanentIfItStillExists(game)) + .map(Permanent::getAttachedTo) + .filter(event.getTargetId()::equals) + .isPresent(); } @Override public NeglectedHeirloomTriggeredAbility copy() { return new NeglectedHeirloomTriggeredAbility(this); } - - @Override - public String getRule() { - return "When equipped creature transforms, transform {this}."; - } } 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/p/PrimalAmulet.java b/Mage.Sets/src/mage/cards/p/PrimalAmulet.java index a687c4d3aba..fcf75d1ecbf 100644 --- a/Mage.Sets/src/mage/cards/p/PrimalAmulet.java +++ b/Mage.Sets/src/mage/cards/p/PrimalAmulet.java @@ -4,14 +4,13 @@ import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SpellCastControllerTriggeredAbility; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.effects.common.cost.SpellsCostReductionControllerEffect; +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.constants.Zone; import mage.counters.CounterType; import mage.filter.FilterCard; import mage.filter.StaticFilters; @@ -27,7 +26,7 @@ import java.util.UUID; */ public final class PrimalAmulet extends CardImpl { - private static final FilterCard filter = new FilterCard("Instant and sorcery spells"); + private static final FilterCard filter = new FilterCard("instant and sorcery spells"); static { filter.add(Predicates.or( @@ -45,7 +44,12 @@ public final class PrimalAmulet extends CardImpl { // Whenever you cast an instant or sorcery spell, put a charge counter on Primal Amulet. Then if there are four or more charge counters on it, you may remove those counters and transform it. this.addAbility(new TransformAbility()); - this.addAbility(new SpellCastControllerTriggeredAbility(new PrimalAmuletEffect(), StaticFilters.FILTER_SPELL_AN_INSTANT_OR_SORCERY, false)); + Ability ability = new SpellCastControllerTriggeredAbility( + new AddCountersSourceEffect(CounterType.CHARGE.createInstance()), + StaticFilters.FILTER_SPELL_AN_INSTANT_OR_SORCERY, false + ); + ability.addEffect(new PrimalAmuletEffect()); + this.addAbility(ability); } private PrimalAmulet(final PrimalAmulet card) { @@ -62,9 +66,8 @@ class PrimalAmuletEffect extends OneShotEffect { PrimalAmuletEffect() { super(Outcome.Benefit); - this.staticText = "put a charge counter on {this}. " - + "Then if there are four or more charge counters on it, " - + "you may remove those counters and transform it"; + this.staticText = "Then if there are four or more charge counters on it, " + + "you may remove those counters and transform it"; } private PrimalAmuletEffect(final PrimalAmuletEffect effect) { @@ -79,16 +82,15 @@ class PrimalAmuletEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player player = game.getPlayer(source.getControllerId()); - Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent != null && player != null) { - permanent.addCounters(CounterType.CHARGE.createInstance(), source.getControllerId(), source, game); - int counters = permanent.getCounters(game).getCount(CounterType.CHARGE); - if (counters > 3 && player.chooseUse(Outcome.Benefit, "Transform this?", source, game)) { - permanent.removeCounters(CounterType.CHARGE.getName(), counters, source, game); - new TransformSourceEffect().apply(game, source); - } - return true; + Permanent permanent = source.getSourcePermanentIfItStillExists(game); + if (permanent == null + || player == null + || permanent.getCounters(game).getCount(CounterType.CHARGE) <= 3 + || !player.chooseUse(Outcome.Benefit, "Remove all charge counters from this and transform it?", source, game)) { + return false; } - return false; + permanent.removeAllCounters(CounterType.CHARGE.getName(), source, game); + permanent.transform(source, game); + return true; } } diff --git a/Mage.Sets/src/mage/cards/p/PrimalWellspring.java b/Mage.Sets/src/mage/cards/p/PrimalWellspring.java index 46e8959f144..024e7274a48 100644 --- a/Mage.Sets/src/mage/cards/p/PrimalWellspring.java +++ b/Mage.Sets/src/mage/cards/p/PrimalWellspring.java @@ -1,7 +1,5 @@ - package mage.cards.p; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.Effect; @@ -17,8 +15,9 @@ import mage.game.events.GameEvent; import mage.game.stack.Spell; import mage.target.targetpointer.FixedTarget; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class PrimalWellspring extends CardImpl { @@ -33,9 +32,10 @@ public final class PrimalWellspring extends CardImpl { this.addAbility(ability); // When that mana is spent to cast an instant or sorcery spell, copy that spell and you may choose new targets for the copy. - Effect effect = new CopyTargetStackObjectEffect(true); - effect.setText("copy that spell and you may choose new targets for the copy"); - this.addAbility(new PyrimalWellspringTriggeredAbility(ability.getOriginalId(), effect)); + this.addAbility(new PrimalWellspringTriggeredAbility( + ability.getOriginalId(), new CopyTargetStackObjectEffect(true) + .setText("copy that spell and you may choose new targets for the copy") + )); } private PrimalWellspring(final PrimalWellspring card) { @@ -48,26 +48,26 @@ public final class PrimalWellspring extends CardImpl { } } -class PyrimalWellspringTriggeredAbility extends TriggeredAbilityImpl { +class PrimalWellspringTriggeredAbility extends TriggeredAbilityImpl { private static final FilterInstantOrSorcerySpell filter = new FilterInstantOrSorcerySpell(); String abilityOriginalId; - public PyrimalWellspringTriggeredAbility(UUID abilityOriginalId, Effect effect) { + public PrimalWellspringTriggeredAbility(UUID abilityOriginalId, Effect effect) { super(Zone.ALL, effect, false); this.abilityOriginalId = abilityOriginalId.toString(); setTriggerPhrase("When that mana is used to cast an instant or sorcery spell, "); } - private PyrimalWellspringTriggeredAbility(final PyrimalWellspringTriggeredAbility ability) { + private PrimalWellspringTriggeredAbility(final PrimalWellspringTriggeredAbility ability) { super(ability); this.abilityOriginalId = ability.abilityOriginalId; } @Override - public PyrimalWellspringTriggeredAbility copy() { - return new PyrimalWellspringTriggeredAbility(this); + public PrimalWellspringTriggeredAbility copy() { + return new PrimalWellspringTriggeredAbility(this); } @Override diff --git a/Mage.Sets/src/mage/cards/p/ProfaneProcession.java b/Mage.Sets/src/mage/cards/p/ProfaneProcession.java index ae78c26a88a..881bab6e555 100644 --- a/Mage.Sets/src/mage/cards/p/ProfaneProcession.java +++ b/Mage.Sets/src/mage/cards/p/ProfaneProcession.java @@ -1,28 +1,25 @@ package mage.cards.p; -import java.util.UUID; - -import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.condition.Condition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.ExileTargetEffect; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.common.ExileTargetForSourceEffect; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.SuperType; -import mage.constants.Zone; -import mage.game.ExileZone; import mage.game.Game; -import mage.players.Player; import mage.target.common.TargetCreaturePermanent; import mage.util.CardUtil; +import java.util.Optional; +import java.util.UUID; + /** * @author LevelX2 */ @@ -37,7 +34,11 @@ public final class ProfaneProcession extends CardImpl { // {3}{W}{B}: Exile target creature. Then if there are three or more cards exiled with Profane Procession, transform it. this.addAbility(new TransformAbility()); - Ability ability = new SimpleActivatedAbility(new ProfaneProcessionEffect(), new ManaCostsImpl<>("{3}{W}{B}")); + Ability ability = new SimpleActivatedAbility(new ExileTargetForSourceEffect(), new ManaCostsImpl<>("{3}{W}{B}")); + ability.addEffect(new ConditionalOneShotEffect( + new TransformSourceEffect(), ProfaneProcessionCondition.instance, + "Then if there are three or more cards exiled with {this}, transform it" + )); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); } @@ -52,36 +53,14 @@ public final class ProfaneProcession extends CardImpl { } } -class ProfaneProcessionEffect extends OneShotEffect { - - ProfaneProcessionEffect() { - super(Outcome.Exile); - this.staticText = "Exile target creature. Then if there are three or more cards exiled with {this}, transform it."; - } - - private ProfaneProcessionEffect(final ProfaneProcessionEffect effect) { - super(effect); - } - - @Override - public ProfaneProcessionEffect copy() { - return new ProfaneProcessionEffect(this); - } +enum ProfaneProcessionCondition implements Condition { + instance; @Override public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - UUID exileId = CardUtil.getCardExileZoneId(game, source); - MageObject sourceObject = source.getSourceObject(game); - if (controller != null && exileId != null && sourceObject != null) { - new ExileTargetEffect(exileId, sourceObject.getIdName()).setTargetPointer(this.getTargetPointer().copy()).apply(game, source); - game.processAction(); - ExileZone exileZone = game.getExile().getExileZone(exileId); - if (exileZone != null && exileZone.size() > 2) { - new TransformSourceEffect().apply(game, source); - } - return true; - } - return false; + return Optional + .ofNullable(game.getExile().getExileZone(CardUtil.getExileZoneId(game, source))) + .filter(cards -> cards.size() >= 3) + .isPresent(); } } diff --git a/Mage.Sets/src/mage/cards/r/RavagerOfTheFells.java b/Mage.Sets/src/mage/cards/r/RavagerOfTheFells.java index 365f3243085..f5e141d7811 100644 --- a/Mage.Sets/src/mage/cards/r/RavagerOfTheFells.java +++ b/Mage.Sets/src/mage/cards/r/RavagerOfTheFells.java @@ -19,6 +19,7 @@ import mage.game.stack.StackObject; import mage.players.Player; import mage.target.TargetPermanent; import mage.target.common.TargetOpponentOrPlaneswalker; +import mage.target.targetpointer.EachTargetPointer; import java.util.HashSet; import java.util.Set; @@ -69,6 +70,7 @@ class RavagerOfTheFellsEffect extends OneShotEffect { RavagerOfTheFellsEffect() { super(Outcome.Damage); + this.setTargetPointer(new EachTargetPointer()); staticText = "it deals 2 damage to target opponent or planeswalker and 2 damage " + "to up to one target creature that player or that planeswalker's controller controls."; } @@ -84,10 +86,11 @@ class RavagerOfTheFellsEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - game.damagePlayerOrPermanent(source.getTargets().get(0).getFirstTarget(), 2, source.getSourceId(), source, game, false, true); - Permanent creature = game.getPermanent(source.getTargets().get(1).getFirstTarget()); - if (creature != null) { - creature.damage(2, source.getSourceId(), source, game, false, true); + for (UUID targetId : getTargetPointer().getTargets(game, source)) { + game.damagePlayerOrPermanent( + targetId, 2, source.getSourceId(), source, + game, false, true + ); } return true; } diff --git a/Mage.Sets/src/mage/cards/r/RavenousDemon.java b/Mage.Sets/src/mage/cards/r/RavenousDemon.java index cef1ce7b990..3feef6706d8 100644 --- a/Mage.Sets/src/mage/cards/r/RavenousDemon.java +++ b/Mage.Sets/src/mage/cards/r/RavenousDemon.java @@ -1,8 +1,5 @@ - package mage.cards.r; -import java.util.UUID; - import mage.MageInt; import mage.abilities.common.ActivateAsSorceryActivatedAbility; import mage.abilities.costs.common.SacrificeTargetCost; @@ -12,19 +9,16 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; import mage.filter.common.FilterControlledPermanent; -import mage.target.common.TargetControlledPermanent; + +import java.util.UUID; /** * @author intimidatingant */ public final class RavenousDemon extends CardImpl { - private static final FilterControlledPermanent filter = new FilterControlledPermanent("Human"); - static { - filter.add(SubType.HUMAN.getPredicate()); - } + private static final FilterControlledPermanent filter = new FilterControlledPermanent(SubType.HUMAN, "Human"); public RavenousDemon(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{B}"); @@ -37,7 +31,7 @@ public final class RavenousDemon extends CardImpl { // Sacrifice a Human: Transform Ravenous Demon. Activate this ability only any time you could cast a sorcery. this.addAbility(new TransformAbility()); - this.addAbility(new ActivateAsSorceryActivatedAbility(Zone.BATTLEFIELD, new TransformSourceEffect(), new SacrificeTargetCost(filter))); + this.addAbility(new ActivateAsSorceryActivatedAbility(new TransformSourceEffect(), new SacrificeTargetCost(filter))); } private RavenousDemon(final RavenousDemon 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/SageOfAncientLore.java b/Mage.Sets/src/mage/cards/s/SageOfAncientLore.java index 36105114896..156aa64d14e 100644 --- a/Mage.Sets/src/mage/cards/s/SageOfAncientLore.java +++ b/Mage.Sets/src/mage/cards/s/SageOfAncientLore.java @@ -4,9 +4,8 @@ import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.WerewolfFrontTriggeredAbility; -import mage.abilities.condition.common.TransformedCondition; +import mage.abilities.condition.common.NotTransformedCondition; import mage.abilities.decorator.ConditionalContinuousEffect; -import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.CardsInControllerHandCount; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.continuous.SetBasePowerToughnessSourceEffect; @@ -35,10 +34,13 @@ public final class SageOfAncientLore extends CardImpl { this.secondSideCardClazz = mage.cards.w.WerewolfOfAncientHunger.class; // Sage of Ancient Lore's power and toughness are each equal to the number of cards in your hand. - DynamicValue xValue = CardsInControllerHandCount.ANY; - this.addAbility(new SimpleStaticAbility(Zone.ALL, - new ConditionalContinuousEffect(new SetBasePowerToughnessSourceEffect(xValue), - new TransformedCondition(true), "{this}'s power and toughness are each equal to the total number of cards in your hand"))); + this.addAbility(new SimpleStaticAbility( + Zone.ALL, + new ConditionalContinuousEffect( + new SetBasePowerToughnessSourceEffect(CardsInControllerHandCount.ANY), NotTransformedCondition.instance, + "{this}'s power and toughness are each equal to the total number of cards in your hand" + ) + )); // When Sage of Ancient Lore enters the battlefield, draw a card. this.addAbility(new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1), false)); diff --git a/Mage.Sets/src/mage/cards/s/ScroungedScythe.java b/Mage.Sets/src/mage/cards/s/ScroungedScythe.java index 0c1473693d5..0d3e7b0075b 100644 --- a/Mage.Sets/src/mage/cards/s/ScroungedScythe.java +++ b/Mage.Sets/src/mage/cards/s/ScroungedScythe.java @@ -1,11 +1,8 @@ - - package mage.cards.s; -import java.util.UUID; import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.EquippedHasSubtypeCondition; -import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.decorator.ConditionalContinuousEffect; import mage.abilities.effects.common.continuous.BoostEquippedEffect; import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; @@ -13,17 +10,21 @@ import mage.abilities.keyword.EquipAbility; import mage.abilities.keyword.MenaceAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.constants.AttachmentType; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; /** - * * @author fireshoes */ public final class ScroungedScythe extends CardImpl { + private static final Condition condition = new EquippedHasSubtypeCondition(SubType.HUMAN); + public ScroungedScythe(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},""); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, ""); this.subtype.add(SubType.EQUIPMENT); this.nightCard = true; @@ -32,15 +33,14 @@ public final class ScroungedScythe extends CardImpl { this.addAbility(new SimpleStaticAbility(new BoostEquippedEffect(1, 1))); // As long as equipped creature is a Human, it has menace. - this.addAbility(new SimpleStaticAbility( - new ConditionalContinuousEffect( - new GainAbilityAttachedEffect(new MenaceAbility(), AttachmentType.EQUIPMENT), - new EquippedHasSubtypeCondition(SubType.HUMAN), - "As long as equipped creature is a Human, it has menace. " + - "(It can't be blocked except by two or more creatures.)"))); + this.addAbility(new SimpleStaticAbility(new ConditionalContinuousEffect( + new GainAbilityAttachedEffect(new MenaceAbility(false), AttachmentType.EQUIPMENT), + condition, "As long as equipped creature is a Human, it has menace. " + + "(It can't be blocked except by two or more creatures.)" + ))); // Equip {2} - this.addAbility(new EquipAbility(Outcome.BoostCreature, new GenericManaCost(2), new TargetControlledCreaturePermanent(), false)); + this.addAbility(new EquipAbility(2, false)); } private ScroungedScythe(final ScroungedScythe 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/SmolderingWerewolf.java b/Mage.Sets/src/mage/cards/s/SmolderingWerewolf.java index 4edc054e0f8..d20600ca9b2 100644 --- a/Mage.Sets/src/mage/cards/s/SmolderingWerewolf.java +++ b/Mage.Sets/src/mage/cards/s/SmolderingWerewolf.java @@ -1,14 +1,10 @@ - package mage.cards.s; -import java.util.UUID; - import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; @@ -16,9 +12,10 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** * @author fireshoes */ @@ -34,9 +31,7 @@ public final class SmolderingWerewolf extends CardImpl { this.secondSideCardClazz = mage.cards.e.EruptingDreadwolf.class; // When Smoldering Werewolf enters the battlefield, it deals 1 damage to each of up to two target creatures. - Effect effect = new DamageTargetEffect(1); - effect.setText("it deals 1 damage to each of up to two target creatures"); - Ability ability = new EntersBattlefieldTriggeredAbility(effect, false); + Ability ability = new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(1, "it")); ability.addTarget(new TargetCreaturePermanent(0, 2)); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/s/SoulSeizer.java b/Mage.Sets/src/mage/cards/s/SoulSeizer.java index 5dc4a1fe428..aa0cebb6f39 100644 --- a/Mage.Sets/src/mage/cards/s/SoulSeizer.java +++ b/Mage.Sets/src/mage/cards/s/SoulSeizer.java @@ -68,12 +68,12 @@ class SoulSeizerEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(source.getSourceId()); + Permanent permanent = source.getSourcePermanentIfItStillExists(game); if (permanent == null || !permanent.transform(source, game)) { return false; } Permanent attachTo = game.getPermanent(getTargetPointer().getFirst(game, source)); - return attachTo != null && attachTo.addAttachment(source.getSourceId(), source, game); + return attachTo != null && attachTo.addAttachment(permanent.getId(), source, game); } @Override 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/SpiresOfOrazca.java b/Mage.Sets/src/mage/cards/s/SpiresOfOrazca.java index 2e8945aa7e9..49d9508989b 100644 --- a/Mage.Sets/src/mage/cards/s/SpiresOfOrazca.java +++ b/Mage.Sets/src/mage/cards/s/SpiresOfOrazca.java @@ -1,35 +1,30 @@ - package mage.cards.s; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.RemoveFromCombatTargetEffect; import mage.abilities.effects.common.UntapTargetEffect; import mage.abilities.mana.ColorlessManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.TargetController; -import mage.constants.Zone; -import mage.filter.common.FilterCreaturePermanent; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterOpponentsCreaturePermanent; import mage.filter.predicate.permanent.AttackingPredicate; import mage.target.TargetPermanent; -import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; /** - * * @author TheElk801 */ public final class SpiresOfOrazca extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("attacking creature an opponent controls"); + private static final FilterPermanent filter = new FilterOpponentsCreaturePermanent("attacking creature an opponent controls"); static { filter.add(AttackingPredicate.instance); - filter.add(TargetController.OPPONENT.getControllerPredicate()); } public SpiresOfOrazca(UUID ownerId, CardSetInfo setInfo) { @@ -40,12 +35,12 @@ public final class SpiresOfOrazca extends CardImpl { this.addAbility(new ColorlessManaAbility()); // {T}: Untap target attacking creature an opponent controls and remove it from combat. - Effect effect = new UntapTargetEffect(); - effect.setText("Untap target attacking creature an opponent controls and remove it from combat."); - Ability ability = new SimpleActivatedAbility(effect, new TapSourceCost()); - effect = new RemoveFromCombatTargetEffect(); - effect.setText(" "); - ability.addEffect(effect); + Ability ability = new SimpleActivatedAbility( + new UntapTargetEffect() + .setText("Untap target attacking creature an opponent controls"), + new TapSourceCost() + ); + ability.addEffect(new RemoveFromCombatTargetEffect().setText("and remove it from combat")); ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } 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/TempleOfAclazotz.java b/Mage.Sets/src/mage/cards/t/TempleOfAclazotz.java index 9493630ae49..ca7fc5af6cb 100644 --- a/Mage.Sets/src/mage/cards/t/TempleOfAclazotz.java +++ b/Mage.Sets/src/mage/cards/t/TempleOfAclazotz.java @@ -1,27 +1,21 @@ - package mage.cards.t; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; -import mage.abilities.costs.Cost; import mage.abilities.costs.common.SacrificeTargetCost; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.dynamicvalue.common.SacrificeCostCreaturesToughness; +import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.mana.BlackManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.SuperType; -import mage.constants.Zone; import mage.filter.StaticFilters; -import mage.game.Game; -import mage.players.Player; -import mage.target.common.TargetControlledCreaturePermanent; + +import java.util.UUID; /** - * * @author TheElk801 */ public final class TempleOfAclazotz extends CardImpl { @@ -36,7 +30,8 @@ public final class TempleOfAclazotz extends CardImpl { this.addAbility(new BlackManaAbility()); // {T}, Sacrifice a creature: You gain life equal to the sacrificed creature's toughness. - Ability ability = new SimpleActivatedAbility(new TempleOfAclazotzEffect(), new TapSourceCost()); + Ability ability = new SimpleActivatedAbility(new GainLifeEffect(SacrificeCostCreaturesToughness.instance) + .setText("you gain life equal to the sacrificed creature's toughness"), new TapSourceCost()); ability.addCost(new SacrificeTargetCost(StaticFilters.FILTER_PERMANENT_CREATURE)); this.addAbility(ability); } @@ -50,37 +45,3 @@ public final class TempleOfAclazotz extends CardImpl { return new TempleOfAclazotz(this); } } - -class TempleOfAclazotzEffect extends OneShotEffect { - - TempleOfAclazotzEffect() { - super(Outcome.GainLife); - this.staticText = "You gain life equal to the sacrificed creature's toughness"; - } - - private TempleOfAclazotzEffect(final TempleOfAclazotzEffect effect) { - super(effect); - } - - @Override - public TempleOfAclazotzEffect copy() { - return new TempleOfAclazotzEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - for (Cost cost : source.getCosts()) { - if (cost instanceof SacrificeTargetCost) { - int amount = ((SacrificeTargetCost) cost).getPermanents().get(0).getToughness().getValue(); - if (amount > 0) { - controller.gainLife(amount, game, source); - } - } - } - return true; - } - return false; - } -} diff --git a/Mage.Sets/src/mage/cards/t/TombOfTheDuskRose.java b/Mage.Sets/src/mage/cards/t/TombOfTheDuskRose.java index 35cffef463a..46a7ecf9733 100644 --- a/Mage.Sets/src/mage/cards/t/TombOfTheDuskRose.java +++ b/Mage.Sets/src/mage/cards/t/TombOfTheDuskRose.java @@ -1,7 +1,5 @@ package mage.cards.t; -import java.util.UUID; -import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapSourceCost; @@ -20,10 +18,12 @@ import mage.game.ExileZone; import mage.game.Game; import mage.players.Player; import mage.target.TargetCard; +import mage.target.common.TargetCardInExile; import mage.util.CardUtil; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class TombOfTheDuskRose extends CardImpl { @@ -60,7 +60,7 @@ class TombOfTheDuskRoseEffect extends OneShotEffect { TombOfTheDuskRoseEffect() { super(Outcome.PutCardInPlay); - this.staticText = "Put a creature card exiled with this permanent onto the battlefield under your control"; + this.staticText = "put a creature card exiled with this permanent onto the battlefield under your control"; } private TombOfTheDuskRoseEffect(final TombOfTheDuskRoseEffect effect) { @@ -75,20 +75,17 @@ class TombOfTheDuskRoseEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - UUID exileId = CardUtil.getCardExileZoneId(game, source); - MageObject sourceObject = source.getSourceObject(game); - if (controller != null && exileId != null && sourceObject != null) { - ExileZone exileZone = game.getExile().getExileZone(exileId); - if (exileZone != null) { - TargetCard targetCard = new TargetCard(Zone.EXILED, StaticFilters.FILTER_CARD_CREATURE); - controller.chooseTarget(outcome, exileZone, targetCard, source, game); - Card card = game.getCard(targetCard.getFirstTarget()); - if (card != null) { - controller.moveCards(card, Zone.BATTLEFIELD, source, game); - } - } - return true; + if (controller == null) { + return false; } - return false; + ExileZone exileZone = game.getExile().getExileZone(CardUtil.getExileZoneId(game, source)); + if (exileZone == null || exileZone.count(StaticFilters.FILTER_CARD_CREATURE, game) < 1) { + return false; + } + TargetCard targetCard = new TargetCardInExile(StaticFilters.FILTER_CARD_CREATURE, exileZone.getId()); + targetCard.withNotTarget(true); + controller.choose(outcome, targetCard, source, game); + Card card = game.getCard(targetCard.getFirstTarget()); + return card != null && controller.moveCards(card, Zone.BATTLEFIELD, source, game); } } diff --git a/Mage.Sets/src/mage/cards/t/TovolarsMagehunter.java b/Mage.Sets/src/mage/cards/t/TovolarsMagehunter.java index 0fcba4dc888..3879bc96f68 100644 --- a/Mage.Sets/src/mage/cards/t/TovolarsMagehunter.java +++ b/Mage.Sets/src/mage/cards/t/TovolarsMagehunter.java @@ -1,17 +1,16 @@ package mage.cards.t; import mage.MageInt; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.SpellCastOpponentTriggeredAbility; import mage.abilities.common.WerewolfBackTriggeredAbility; import mage.abilities.effects.common.DamageTargetEffect; 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.game.Game; -import mage.game.events.GameEvent; -import mage.target.targetpointer.FixedTarget; +import mage.filter.StaticFilters; import java.util.UUID; @@ -32,7 +31,10 @@ public final class TovolarsMagehunter extends CardImpl { this.nightCard = true; // Whenever an opponent casts a spell, Tovolar's Magehunter deals 2 damage to that player. - this.addAbility(new TovolarsMagehunterTriggeredAbility()); + this.addAbility(new SpellCastOpponentTriggeredAbility( + Zone.BATTLEFIELD, new DamageTargetEffect(2, true, "that player"), + StaticFilters.FILTER_SPELL_A, false, SetTargetPointer.PLAYER + )); // At the beginning of each upkeep, if a player cast two or more spells last turn, transform Tovolar's Magehunter. this.addAbility(new WerewolfBackTriggeredAbility()); @@ -47,38 +49,3 @@ public final class TovolarsMagehunter extends CardImpl { return new TovolarsMagehunter(this); } } - -class TovolarsMagehunterTriggeredAbility extends TriggeredAbilityImpl { - - TovolarsMagehunterTriggeredAbility() { - super(Zone.BATTLEFIELD, new DamageTargetEffect(2), false); - } - - private TovolarsMagehunterTriggeredAbility(final TovolarsMagehunterTriggeredAbility ability) { - super(ability); - } - - @Override - public TovolarsMagehunterTriggeredAbility copy() { - return new TovolarsMagehunterTriggeredAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.SPELL_CAST; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (game.getOpponents(controllerId).contains(event.getPlayerId())) { - this.getEffects().setTargetPointer(new FixedTarget(event.getPlayerId())); - return true; - } - return false; - } - - @Override - public String getRule() { - return "Whenever an opponent casts a spell, {this} deals 2 damage to that player."; - } -} diff --git a/Mage.Sets/src/mage/cards/t/TreasureMap.java b/Mage.Sets/src/mage/cards/t/TreasureMap.java index 073470aaa2a..224fbd8290d 100644 --- a/Mage.Sets/src/mage/cards/t/TreasureMap.java +++ b/Mage.Sets/src/mage/cards/t/TreasureMap.java @@ -2,22 +2,22 @@ package mage.cards.t; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.SourceHasCounterCondition; 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.CreateTokenEffect; +import mage.abilities.effects.common.RemoveAllCountersSourceEffect; import mage.abilities.effects.common.TransformSourceEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.effects.keyword.ScryEffect; import mage.abilities.keyword.TransformAbility; 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.game.permanent.token.TreasureToken; -import mage.players.Player; import java.util.UUID; @@ -26,6 +26,8 @@ import java.util.UUID; */ public final class TreasureMap extends CardImpl { + private static final Condition condition = new SourceHasCounterCondition(CounterType.LANDMARK, 3); + public TreasureMap(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}"); @@ -33,8 +35,13 @@ public final class TreasureMap extends CardImpl { // {1}, {T}: Scry 1. Put a landmark counter on Treasure Map. Then if there are three or more landmark counters on it, remove those counters, transform Treasure Map, and create three colorless Treasure artifact tokens with "{T}, Sacrifice this artifact: Add one mana of any color." this.addAbility(new TransformAbility()); - Ability ability = new SimpleActivatedAbility(new TreasureMapEffect(), new ManaCostsImpl<>("{1}")); + Ability ability = new SimpleActivatedAbility(new ScryEffect(1, false), new ManaCostsImpl<>("{1}")); ability.addCost(new TapSourceCost()); + ability.addEffect(new AddCountersSourceEffect(CounterType.LANDMARK.createInstance())); + ability.addEffect(new ConditionalOneShotEffect( + new RemoveAllCountersSourceEffect(CounterType.LANDMARK), condition, "Then if there are three or " + + "more landmark counters on it, remove those counters, transform {this}, and create three Treasure tokens" + ).addEffect(new TransformSourceEffect()).addEffect(new CreateTokenEffect(new TreasureToken(), 3))); this.addAbility(ability); } @@ -47,43 +54,3 @@ public final class TreasureMap extends CardImpl { return new TreasureMap(this); } } - -class TreasureMapEffect extends OneShotEffect { - - TreasureMapEffect() { - super(Outcome.Benefit); - this.staticText = "Scry 1. Put a landmark counter on {this}. " - + "Then if there are three or more landmark counters on it, " - + "remove those counters, transform {this}, and create " - + "three Treasure tokens"; - } - - private TreasureMapEffect(final TreasureMapEffect effect) { - super(effect); - } - - @Override - public TreasureMapEffect copy() { - return new TreasureMapEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(source.getSourceId()); - Player player = game.getPlayer(source.getControllerId()); - if (player != null) { - player.scry(1, source, game); - if (permanent != null) { - permanent.addCounters(CounterType.LANDMARK.createInstance(), source.getControllerId(), source, game); - int counters = permanent.getCounters(game).getCount(CounterType.LANDMARK); - if (counters > 2) { - permanent.removeCounters(CounterType.LANDMARK.getName(), counters, source, game); - new TransformSourceEffect().apply(game, source); - new CreateTokenEffect(new TreasureToken(), 3).apply(game, source); - } - return true; - } - } - 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/v/VancesBlastingCannons.java b/Mage.Sets/src/mage/cards/v/VancesBlastingCannons.java index ca95508a8df..481660bf8b7 100644 --- a/Mage.Sets/src/mage/cards/v/VancesBlastingCannons.java +++ b/Mage.Sets/src/mage/cards/v/VancesBlastingCannons.java @@ -3,21 +3,18 @@ package mage.cards.v; import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; -import mage.abilities.effects.AsThoughEffectImpl; -import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; import mage.game.Game; import mage.game.events.GameEvent; -import mage.game.permanent.Permanent; import mage.players.Player; -import mage.target.targetpointer.FixedTarget; +import mage.util.CardUtil; import mage.watchers.common.CastSpellLastTurnWatcher; import java.util.UUID; @@ -38,7 +35,7 @@ public final class VancesBlastingCannons extends CardImpl { // Whenever you cast your third spell in a turn, transform Vance's Blasting Cannons. this.addAbility(new TransformAbility()); - this.addAbility(new VancesBlastingCannonsFlipTrigger()); + this.addAbility(new VancesBlastingCannonsTriggeredAbility()); } private VancesBlastingCannons(final VancesBlastingCannons card) { @@ -69,72 +66,36 @@ class VancesBlastingCannonsExileEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); - if (controller != null && sourcePermanent != null) { - Card card = controller.getLibrary().getFromTop(game); - if (card != null) { - String exileName = sourcePermanent.getIdName() + (card.isLand(game) ? "" : " player.damage(3, source, game)); return true; } } diff --git a/Mage.Sets/src/mage/cards/w/WithengarUnbound.java b/Mage.Sets/src/mage/cards/w/WithengarUnbound.java index 032eae161b0..4b170ef2642 100644 --- a/Mage.Sets/src/mage/cards/w/WithengarUnbound.java +++ b/Mage.Sets/src/mage/cards/w/WithengarUnbound.java @@ -1,4 +1,3 @@ - package mage.cards.w; import mage.MageInt; @@ -20,13 +19,12 @@ import mage.game.events.GameEvent; import java.util.UUID; /** - * * @author BetaSteward */ public final class WithengarUnbound extends CardImpl { public WithengarUnbound(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},""); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, ""); this.supertype.add(SuperType.LEGENDARY); this.subtype.add(SubType.DEMON); this.color.setBlack(true); @@ -40,9 +38,9 @@ public final class WithengarUnbound extends CardImpl { this.addAbility(FlyingAbility.getInstance()); this.addAbility(IntimidateAbility.getInstance()); this.addAbility(TrampleAbility.getInstance()); + // Whenever a player loses the game, put thirteen +1/+1 counters on Withengar Unbound. this.addAbility(new WithengarUnboundTriggeredAbility()); - } private WithengarUnbound(final WithengarUnbound card) { @@ -57,8 +55,9 @@ public final class WithengarUnbound extends CardImpl { class WithengarUnboundTriggeredAbility extends TriggeredAbilityImpl { - public WithengarUnboundTriggeredAbility() { + WithengarUnboundTriggeredAbility() { super(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.P1P1.createInstance(13)), false); + setTriggerPhrase("Whenever a player loses the game, "); } private WithengarUnboundTriggeredAbility(final WithengarUnboundTriggeredAbility ability) { @@ -79,9 +78,4 @@ class WithengarUnboundTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { return true; } - - @Override - public String getRule() { - return "Whenever a player loses the game, put thirteen +1/+1 counters on {this}."; - } } diff --git a/Mage.Sets/src/mage/sets/SecretLairDrop.java b/Mage.Sets/src/mage/sets/SecretLairDrop.java index 02ad3042856..8bc16a19e10 100644 --- a/Mage.Sets/src/mage/sets/SecretLairDrop.java +++ b/Mage.Sets/src/mage/sets/SecretLairDrop.java @@ -76,7 +76,7 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("Narset, Enlightened Master", 53, Rarity.MYTHIC, mage.cards.n.NarsetEnlightenedMaster.class)); cards.add(new SetCardInfo("Oona, Queen of the Fae", 54, Rarity.MYTHIC, mage.cards.o.OonaQueenOfTheFae.class)); cards.add(new SetCardInfo("Saskia the Unyielding", 55, Rarity.MYTHIC, mage.cards.s.SaskiaTheUnyielding.class)); - cards.add(new SetCardInfo("Arcbound Ravager", 56, Rarity.RARE, mage.cards.a.ArcboundRavager.class)); + cards.add(new SetCardInfo("Arcbound Ravager", 56, Rarity.RARE, mage.cards.a.ArcboundRavager.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Darksteel Colossus", 57, Rarity.MYTHIC, mage.cards.d.DarksteelColossus.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Walking Ballista", 58, Rarity.RARE, mage.cards.w.WalkingBallista.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Squire", 59, Rarity.RARE, mage.cards.s.Squire.class)); @@ -812,6 +812,7 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("Seven Dwarves", 814, Rarity.RARE, mage.cards.s.SevenDwarves.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Seven Dwarves", 815, Rarity.RARE, mage.cards.s.SevenDwarves.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Seven Dwarves", 816, Rarity.RARE, mage.cards.s.SevenDwarves.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Seven Dwarves", 817, Rarity.RARE, mage.cards.s.SevenDwarves.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Arcane Signet", 820, Rarity.RARE, mage.cards.a.ArcaneSignet.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Arcane Signet", "820*", Rarity.RARE, mage.cards.a.ArcaneSignet.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Echo of Eons", 821, Rarity.RARE, mage.cards.e.EchoOfEons.class, RETRO_ART)); @@ -823,6 +824,7 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("Norin the Wary", 827, Rarity.RARE, mage.cards.n.NorinTheWary.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Norin the Wary", "827b", Rarity.RARE, mage.cards.n.NorinTheWary.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Keen Duelist", 828, Rarity.RARE, mage.cards.k.KeenDuelist.class)); + cards.add(new SetCardInfo("Cleaver Skaab", 834, Rarity.RARE, mage.cards.c.CleaverSkaab.class, RETRO_ART)); cards.add(new SetCardInfo("Fatestitcher", 835, Rarity.RARE, mage.cards.f.Fatestitcher.class, RETRO_ART)); cards.add(new SetCardInfo("Undead Alchemist", 836, Rarity.RARE, mage.cards.u.UndeadAlchemist.class, RETRO_ART)); cards.add(new SetCardInfo("Champion of the Perished", 837, Rarity.RARE, mage.cards.c.ChampionOfThePerished.class, RETRO_ART)); @@ -835,13 +837,17 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("Headless Rider", 844, Rarity.RARE, mage.cards.h.HeadlessRider.class, RETRO_ART)); cards.add(new SetCardInfo("Liliana's Standard Bearer", 845, Rarity.RARE, mage.cards.l.LilianasStandardBearer.class, RETRO_ART)); cards.add(new SetCardInfo("Mikaeus, the Unhallowed", 846, Rarity.MYTHIC, mage.cards.m.MikaeusTheUnhallowed.class, RETRO_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Phyrexian Crusader", 847, Rarity.RARE, mage.cards.p.PhyrexianCrusader.class, RETRO_ART_USE_VARIOUS)); cards.add(new SetCardInfo("Pontiff of Blight", 848, Rarity.RARE, mage.cards.p.PontiffOfBlight.class, RETRO_ART)); cards.add(new SetCardInfo("Ravenous Rotbelly", 849, Rarity.RARE, mage.cards.r.RavenousRotbelly.class, RETRO_ART)); cards.add(new SetCardInfo("Relentless Dead", 850, Rarity.MYTHIC, mage.cards.r.RelentlessDead.class, RETRO_ART)); + cards.add(new SetCardInfo("Rot Hulk", 851, Rarity.MYTHIC, mage.cards.r.RotHulk.class, RETRO_ART)); cards.add(new SetCardInfo("Rotting Regisaur", 852, Rarity.RARE, mage.cards.r.RottingRegisaur.class, RETRO_ART)); + cards.add(new SetCardInfo("Stitcher's Supplier", 853, Rarity.RARE, mage.cards.s.StitchersSupplier.class, RETRO_ART_USE_VARIOUS)); cards.add(new SetCardInfo("Tomb Tyrant", 854, Rarity.RARE, mage.cards.t.TombTyrant.class, RETRO_ART)); cards.add(new SetCardInfo("Tormod, the Desecrator", 855, Rarity.RARE, mage.cards.t.TormodTheDesecrator.class, RETRO_ART)); cards.add(new SetCardInfo("Vindictive Lich", 856, Rarity.RARE, mage.cards.v.VindictiveLich.class, RETRO_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Neheb, Dreadhorde Champion", 857, Rarity.RARE, mage.cards.n.NehebDreadhordeChampion.class, RETRO_ART)); cards.add(new SetCardInfo("Diregraf Captain", 858, Rarity.RARE, mage.cards.d.DiregrafCaptain.class, RETRO_ART)); cards.add(new SetCardInfo("Havengul Lich", 859, Rarity.MYTHIC, mage.cards.h.HavengulLich.class, RETRO_ART)); cards.add(new SetCardInfo("Nekusar, the Mindrazer", 860, Rarity.MYTHIC, mage.cards.n.NekusarTheMindrazer.class, RETRO_ART_USE_VARIOUS)); @@ -983,7 +989,7 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("Contagion Engine", 1095, Rarity.RARE, mage.cards.c.ContagionEngine.class)); cards.add(new SetCardInfo("Sword of Truth and Justice", 1096, Rarity.MYTHIC, mage.cards.s.SwordOfTruthAndJustice.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Laboratory Maniac", 1097, Rarity.RARE, mage.cards.l.LaboratoryManiac.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Stitcher's Supplier", 1098, Rarity.RARE, mage.cards.s.StitchersSupplier.class)); + cards.add(new SetCardInfo("Stitcher's Supplier", 1098, Rarity.RARE, mage.cards.s.StitchersSupplier.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Beast Whisperer", 1099, Rarity.RARE, mage.cards.b.BeastWhisperer.class)); cards.add(new SetCardInfo("Vizier of the Menagerie", 1100, Rarity.MYTHIC, mage.cards.v.VizierOfTheMenagerie.class)); cards.add(new SetCardInfo("Wood Elves", 1101, Rarity.RARE, mage.cards.w.WoodElves.class)); @@ -1105,7 +1111,7 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("Westvale Abbey", 1212, Rarity.RARE, mage.cards.w.WestvaleAbbey.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Ormendahl, Profane Prince", 1212, Rarity.RARE, mage.cards.o.OrmendahlProfanePrince.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Phyrexian Unlife", 1213, Rarity.RARE, mage.cards.p.PhyrexianUnlife.class)); - cards.add(new SetCardInfo("Phyrexian Crusader", 1214, Rarity.RARE, mage.cards.p.PhyrexianCrusader.class)); + cards.add(new SetCardInfo("Phyrexian Crusader", 1214, Rarity.RARE, mage.cards.p.PhyrexianCrusader.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Plague Engineer", 1215, Rarity.RARE, mage.cards.p.PlagueEngineer.class)); cards.add(new SetCardInfo("Ertai, the Corrupted", 1216, Rarity.RARE, mage.cards.e.ErtaiTheCorrupted.class)); cards.add(new SetCardInfo("Glissa, the Traitor", 1217, Rarity.MYTHIC, mage.cards.g.GlissaTheTraitor.class)); @@ -1978,9 +1984,9 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("Constant Mists", 2026, Rarity.RARE, mage.cards.c.ConstantMists.class)); cards.add(new SetCardInfo("Song of the Dryads", 2027, Rarity.RARE, mage.cards.s.SongOfTheDryads.class)); cards.add(new SetCardInfo("Consecrated Sphinx", 2028, Rarity.MYTHIC, mage.cards.c.ConsecratedSphinx.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Resculpt", 2029, Rarity.RARE, mage.cards.r.Resculpt.class)); - cards.add(new SetCardInfo("Mirage Mirror", 2030, Rarity.RARE, mage.cards.m.MirageMirror.class)); - cards.add(new SetCardInfo("Scion of Draco", 2031, Rarity.MYTHIC, mage.cards.s.ScionOfDraco.class)); + cards.add(new SetCardInfo("Resculpt", 2029, Rarity.RARE, mage.cards.r.Resculpt.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Mirage Mirror", 2030, Rarity.RARE, mage.cards.m.MirageMirror.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Scion of Draco", 2031, Rarity.MYTHIC, mage.cards.s.ScionOfDraco.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Lava Dart", 2037, Rarity.RARE, mage.cards.l.LavaDart.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Monastery Swiftspear", 2038, Rarity.RARE, mage.cards.m.MonasterySwiftspear.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Soul-Scar Mage", 2039, Rarity.RARE, mage.cards.s.SoulScarMage.class, NON_FULL_USE_VARIOUS)); @@ -2037,6 +2043,16 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("Hammer of Nazahn", 2098, Rarity.RARE, mage.cards.h.HammerOfNazahn.class)); cards.add(new SetCardInfo("Lightning Greaves", 2099, Rarity.RARE, mage.cards.l.LightningGreaves.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Weatherlight", 2100, Rarity.MYTHIC, mage.cards.w.Weatherlight.class)); + cards.add(new SetCardInfo("Ethersworn Canonist", 2102, Rarity.RARE, mage.cards.e.EtherswornCanonist.class)); + cards.add(new SetCardInfo("Goblin Engineer", 2103, Rarity.RARE, mage.cards.g.GoblinEngineer.class)); + cards.add(new SetCardInfo("Dance of the Manse", 2104, Rarity.RARE, mage.cards.d.DanceOfTheManse.class)); + cards.add(new SetCardInfo("Arcbound Ravager", 2105, Rarity.RARE, mage.cards.a.ArcboundRavager.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Foundry Inspector", 2106, Rarity.RARE, mage.cards.f.FoundryInspector.class)); + cards.add(new SetCardInfo("Reprocess", 2107, Rarity.RARE, mage.cards.r.Reprocess.class)); + cards.add(new SetCardInfo("Aggressive Mining", 2108, Rarity.RARE, mage.cards.a.AggressiveMining.class)); + cards.add(new SetCardInfo("Sylvan Safekeeper", 2109, Rarity.RARE, mage.cards.s.SylvanSafekeeper.class)); + cards.add(new SetCardInfo("Crucible of Worlds", 2110, Rarity.MYTHIC, mage.cards.c.CrucibleOfWorlds.class)); + cards.add(new SetCardInfo("Zuran Orb", 2111, Rarity.RARE, mage.cards.z.ZuranOrb.class)); cards.add(new SetCardInfo("Feed the Swarm", 7001, Rarity.RARE, mage.cards.f.FeedTheSwarm.class)); cards.add(new SetCardInfo("Forge Anew", 7002, Rarity.RARE, mage.cards.f.ForgeAnew.class)); cards.add(new SetCardInfo("Silence", 7003, Rarity.RARE, mage.cards.s.Silence.class, NON_FULL_USE_VARIOUS)); @@ -2049,9 +2065,22 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("Counterspell", 7010, Rarity.RARE, mage.cards.c.Counterspell.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Dismember", 7011, Rarity.RARE, mage.cards.d.Dismember.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Command Tower", 7012, Rarity.RARE, mage.cards.c.CommandTower.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Goblin Bombardment", 7022, Rarity.RARE, mage.cards.g.GoblinBombardment.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Consecrated Sphinx", 7023, Rarity.MYTHIC, mage.cards.c.ConsecratedSphinx.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Resculpt", 7024, Rarity.RARE, mage.cards.r.Resculpt.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Mirage Mirror", 7025, Rarity.RARE, mage.cards.m.MirageMirror.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Scion of Draco", 7026, Rarity.MYTHIC, mage.cards.s.ScionOfDraco.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Tibalt's Trickery", 7027, Rarity.RARE, mage.cards.t.TibaltsTrickery.class)); cards.add(new SetCardInfo("Minds Aglow", 7028, Rarity.RARE, mage.cards.m.MindsAglow.class)); cards.add(new SetCardInfo("Command Tower", 7029, Rarity.RARE, mage.cards.c.CommandTower.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Command Tower", 7030, Rarity.RARE, mage.cards.c.CommandTower.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Lotus Petal", 7031, Rarity.MYTHIC, mage.cards.l.LotusPetal.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Lotus Petal", 7032, Rarity.MYTHIC, mage.cards.l.LotusPetal.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Lotus Petal", 7033, Rarity.MYTHIC, mage.cards.l.LotusPetal.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Lotus Petal", 7034, Rarity.MYTHIC, mage.cards.l.LotusPetal.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Lotus Petal", 7035, Rarity.MYTHIC, mage.cards.l.LotusPetal.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Lotus Petal", 7036, Rarity.MYTHIC, mage.cards.l.LotusPetal.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Lotus Petal", 7037, Rarity.MYTHIC, mage.cards.l.LotusPetal.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Jace, the Mind Sculptor", 8001, Rarity.MYTHIC, mage.cards.j.JaceTheMindSculptor.class)); cards.add(new SetCardInfo("Doom Blade", 9990, Rarity.RARE, mage.cards.d.DoomBlade.class)); cards.add(new SetCardInfo("Massacre", 9991, Rarity.RARE, mage.cards.m.Massacre.class)); diff --git a/Mage/src/main/java/mage/abilities/condition/common/NotTransformedCondition.java b/Mage/src/main/java/mage/abilities/condition/common/NotTransformedCondition.java new file mode 100644 index 00000000000..5df2942cec1 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/condition/common/NotTransformedCondition.java @@ -0,0 +1,19 @@ +package mage.abilities.condition.common; + +import mage.abilities.Ability; +import mage.abilities.condition.Condition; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * @author noxx + */ +public enum NotTransformedCondition implements Condition { + instance; + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(source.getSourceId()); + return permanent != null && !permanent.isTransformed(); + } +} diff --git a/Mage/src/main/java/mage/abilities/condition/common/TransformedCondition.java b/Mage/src/main/java/mage/abilities/condition/common/TransformedCondition.java deleted file mode 100644 index b8057e8914a..00000000000 --- a/Mage/src/main/java/mage/abilities/condition/common/TransformedCondition.java +++ /dev/null @@ -1,43 +0,0 @@ - -package mage.abilities.condition.common; - -import mage.abilities.Ability; -import mage.abilities.condition.Condition; -import mage.game.Game; -import mage.game.permanent.Permanent; - -/** - * - * @author noxx - */ -public class TransformedCondition implements Condition { - - protected boolean notCondition; - - public TransformedCondition() { - this(false); - } - - /** - * The condition checks whether a permanent is transformed or not. - * - * @param notCondition if true the condition is true when the permanent is not transformed - * @return true if the condition is true, false if the condition is false - */ - public TransformedCondition(boolean notCondition) { - this.notCondition = notCondition; - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent != null) { - if (notCondition) { - return !permanent.isTransformed(); - } else { - return permanent.isTransformed(); - } - } - return false; - } -} 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")); + } }