diff --git a/Mage.Sets/src/mage/cards/c/CasalLurkwoodPathfinder.java b/Mage.Sets/src/mage/cards/c/CasalLurkwoodPathfinder.java index 27e9538d02f..87a3d7580c7 100644 --- a/Mage.Sets/src/mage/cards/c/CasalLurkwoodPathfinder.java +++ b/Mage.Sets/src/mage/cards/c/CasalLurkwoodPathfinder.java @@ -1,19 +1,25 @@ package mage.cards.c; -import mage.MageInt; +import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.TransformIntoSourceTriggeredAbility; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.common.DoIfCostPaid; import mage.abilities.effects.common.TransformSourceEffect; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect; -import mage.abilities.keyword.TransformAbility; +import mage.abilities.keyword.TrampleAbility; import mage.abilities.keyword.VigilanceAbility; -import mage.cards.CardImpl; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardSetInfo; +import mage.cards.TransformingDoubleFacedCard; import mage.constants.CardType; +import mage.constants.Duration; import mage.constants.SubType; import mage.constants.SuperType; +import mage.filter.common.FilterCreaturePermanent; import mage.filter.common.FilterLandCard; import mage.target.common.TargetCardInLibrary; @@ -22,37 +28,59 @@ import java.util.UUID; /** * @author TheElk801 */ -public final class CasalLurkwoodPathfinder extends CardImpl { +public final class CasalLurkwoodPathfinder extends TransformingDoubleFacedCard { private static final FilterLandCard filter = new FilterLandCard("Forest card"); + private static final FilterCreaturePermanent filterLegendary = new FilterCreaturePermanent(); static { filter.add(SubType.FOREST.getPredicate()); + filterLegendary.add(SuperType.LEGENDARY.getPredicate()); } public CasalLurkwoodPathfinder(UUID ownerId, CardSetInfo setInfo) { - super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}"); + super(ownerId, setInfo, + new SuperType[]{SuperType.LEGENDARY}, new CardType[]{CardType.CREATURE}, new SubType[]{SubType.TIEFLING, SubType.DRUID}, "{3}{G}", + "Casal, Pathbreaker Owlbear", + new SuperType[]{SuperType.LEGENDARY}, new CardType[]{CardType.CREATURE}, new SubType[]{SubType.BIRD, SubType.BEAR}, "G" + ); - this.supertype.add(SuperType.LEGENDARY); - this.subtype.add(SubType.TIEFLING); - this.subtype.add(SubType.DRUID); - this.power = new MageInt(3); - this.toughness = new MageInt(3); - this.secondSideCardClazz = CasalPathbreakerOwlbear.class; + // Casal, Lurkwood Pathfinder + this.getLeftHalfCard().setPT(3, 3); // Vigilance - this.addAbility(VigilanceAbility.getInstance()); + this.getLeftHalfCard().addAbility(VigilanceAbility.getInstance()); - // When Doric, Nature's Warden enters the battlefield, search your library for a Forest card, put it into the battlefield tapped, then shuffle. - this.addAbility(new EntersBattlefieldTriggeredAbility( + // When Casal, Lurkwood Pathfinder enters the battlefield, search your library for a Forest card, put it into the battlefield tapped, then shuffle. + this.getLeftHalfCard().addAbility(new EntersBattlefieldTriggeredAbility( new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(filter), true) )); - // Whenever Doric attacks, you may pay {1}{G}. If you do, transform her. - this.addAbility(new TransformAbility()); - this.addAbility(new AttacksTriggeredAbility(new DoIfCostPaid( + // Whenever Casal attacks, you may pay {1}{G}. If you do, transform her. + this.getLeftHalfCard().addAbility(new AttacksTriggeredAbility(new DoIfCostPaid( new TransformSourceEffect().setText("transform her"), new ManaCostsImpl<>("{1}{G}") ))); + + // Casal, Pathbreaker Owlbear + this.getRightHalfCard().setPT(6, 6); + + // Vigilance + this.getRightHalfCard().addAbility(VigilanceAbility.getInstance()); + + // Trample + this.getRightHalfCard().addAbility(TrampleAbility.getInstance()); + + // When this creature transforms into Casal, Pathbreaker Owlbear, other legendary creatures you control get +2/+2 and gain trample until end of turn. + Ability ability = new TransformIntoSourceTriggeredAbility(new BoostControlledEffect( + 2, 2, Duration.EndOfTurn, filterLegendary, true + ).setText("other legendary creatures you control get +2/+2")); + ability.addEffect(new GainAbilityControlledEffect( + TrampleAbility.getInstance(), Duration.EndOfTurn, filterLegendary, true + ).setText("and gain trample until end of turn")); + this.getRightHalfCard().addAbility(ability); + + // At the beginning of your upkeep, transform Casal. + this.getRightHalfCard().addAbility(new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect())); } private CasalLurkwoodPathfinder(final CasalLurkwoodPathfinder card) { diff --git a/Mage.Sets/src/mage/cards/c/CasalPathbreakerOwlbear.java b/Mage.Sets/src/mage/cards/c/CasalPathbreakerOwlbear.java deleted file mode 100644 index 6d62625d256..00000000000 --- a/Mage.Sets/src/mage/cards/c/CasalPathbreakerOwlbear.java +++ /dev/null @@ -1,68 +0,0 @@ -package mage.cards.c; - -import mage.MageInt; -import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; -import mage.abilities.common.TransformIntoSourceTriggeredAbility; -import mage.abilities.effects.common.TransformSourceEffect; -import mage.abilities.effects.common.continuous.BoostControlledEffect; -import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; -import mage.abilities.keyword.TrampleAbility; -import mage.abilities.keyword.VigilanceAbility; -import mage.cards.CardImpl; -import mage.cards.CardSetInfo; -import mage.constants.*; -import mage.filter.common.FilterCreaturePermanent; - -import java.util.UUID; - -/** - * @author TheElk801 - */ -public final class CasalPathbreakerOwlbear extends CardImpl { - - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); - - static { - filter.add(SuperType.LEGENDARY.getPredicate()); - } - - public CasalPathbreakerOwlbear(UUID ownerId, CardSetInfo setInfo) { - super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, ""); - - this.supertype.add(SuperType.LEGENDARY); - this.subtype.add(SubType.BIRD); - this.subtype.add(SubType.BEAR); - this.power = new MageInt(6); - this.toughness = new MageInt(6); - this.color.setGreen(true); - this.nightCard = true; - - // Vigilance - this.addAbility(VigilanceAbility.getInstance()); - - // Trample - this.addAbility(TrampleAbility.getInstance()); - - // When this creature transforms into Doric, Owlbear Avenger, other legendary creatures you control get +2/+2 and gain trample until end of turn. - Ability ability = new TransformIntoSourceTriggeredAbility(new BoostControlledEffect( - 2, 2, Duration.EndOfTurn, filter, true - ).setText("other legendary creatures you control get +2/+2")); - ability.addEffect(new GainAbilityControlledEffect( - TrampleAbility.getInstance(), Duration.EndOfTurn, filter, true - ).setText("and gain trample until end of turn")); - this.addAbility(ability); - - // At the beginning of your upkeep, transform Doric. - this.addAbility(new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect())); - } - - private CasalPathbreakerOwlbear(final CasalPathbreakerOwlbear card) { - super(card); - } - - @Override - public CasalPathbreakerOwlbear copy() { - return new CasalPathbreakerOwlbear(this); - } -} diff --git a/Mage.Sets/src/mage/cards/c/CosmiumCatalyst.java b/Mage.Sets/src/mage/cards/c/CosmiumCatalyst.java deleted file mode 100644 index 292bc3b8620..00000000000 --- a/Mage.Sets/src/mage/cards/c/CosmiumCatalyst.java +++ /dev/null @@ -1,98 +0,0 @@ -package mage.cards.c; - -import java.util.UUID; - -import mage.MageObject; -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.cards.Card; -import mage.cards.CardImpl; -import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.Outcome; -import mage.filter.StaticFilters; -import mage.game.Game; -import mage.players.Player; -import mage.target.Target; -import mage.target.common.TargetCardInExile; -import mage.util.CardUtil; - -/** - * Cosmium Catalyst - * Artifact - * {1}{R}, {T}: Choose an exiled card used to craft Cosmium Catalyst at random. You may cast that card without paying its mana cost. - * - * @author DominionSpy - */ -public class CosmiumCatalyst extends CardImpl { - - public CosmiumCatalyst(UUID ownerId, CardSetInfo setInfo) { - super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, ""); - - this.nightCard = true; - this.color.setRed(true); - - // {1}{R}, {T}: Choose an exiled card used to craft Cosmium Catalyst at random. You may cast that card without paying its mana cost. - Ability ability = new SimpleActivatedAbility(new CosmiumCatalystEffect(), new ManaCostsImpl<>("{1}{R}")); - ability.addCost(new TapSourceCost()); - this.addAbility(ability); - } - - private CosmiumCatalyst(CosmiumCatalyst card) { - super(card); - } - - @Override - public CosmiumCatalyst copy() { - return new CosmiumCatalyst(this); - } -} - -class CosmiumCatalystEffect extends OneShotEffect { - - CosmiumCatalystEffect() { - super(Outcome.PlayForFree); - this.staticText = "Choose an exiled card used to craft {this} at random." + - " You may cast that card without paying its mana cost."; - } - - private CosmiumCatalystEffect(CosmiumCatalystEffect effect) { - super(effect); - } - - @Override - public CosmiumCatalystEffect copy() { - return new CosmiumCatalystEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller == null) { - return false; - } - MageObject sourceObject = game.getObject(source.getSourceId()); - if (sourceObject == null) { - return false; - } - - Target target = new TargetCardInExile(StaticFilters.FILTER_CARD, - CardUtil.getExileZoneId(game, source.getSourceId(), - game.getState().getZoneChangeCounter(source.getSourceId()) - 2 - )); - target.withNotTarget(true); - target.setRandom(true); - if (!target.canChoose(controller.getId(), source, game)) { - return true; - } - target.chooseTarget(outcome, controller.getId(), source, game); - Card chosenCard = game.getCard(target.getFirstTarget()); - if (chosenCard != null) { - CardUtil.castSpellWithAttributesForFree(controller, source, game, chosenCard); - } - return true; - } -} diff --git a/Mage.Sets/src/mage/cards/d/DocentOfPerfection.java b/Mage.Sets/src/mage/cards/d/DocentOfPerfection.java index 129e98d02db..5c6d9e4a605 100644 --- a/Mage.Sets/src/mage/cards/d/DocentOfPerfection.java +++ b/Mage.Sets/src/mage/cards/d/DocentOfPerfection.java @@ -1,7 +1,7 @@ package mage.cards.d; -import mage.MageInt; import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SpellCastControllerTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; @@ -9,15 +9,18 @@ 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.effects.common.continuous.BoostControlledEffect; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; 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.cards.TransformingDoubleFacedCard; import mage.constants.CardType; import mage.constants.ComparisonType; +import mage.constants.Duration; import mage.constants.SubType; +import mage.filter.FilterPermanent; import mage.filter.StaticFilters; import mage.filter.common.FilterControlledPermanent; import mage.game.permanent.token.HumanWizardToken; @@ -27,7 +30,7 @@ import java.util.UUID; /** * @author fireshoes */ -public final class DocentOfPerfection extends CardImpl { +public final class DocentOfPerfection extends TransformingDoubleFacedCard { private static final Condition condition = new PermanentsOnTheBattlefieldCondition( new FilterControlledPermanent(SubType.WIZARD), ComparisonType.MORE_THAN, 2 @@ -35,22 +38,27 @@ public final class DocentOfPerfection extends CardImpl { private static final Hint hint = new ValueHint( "Wizards you control", new PermanentsOnBattlefieldCount(new FilterControlledPermanent(SubType.WIZARD)) ); + private static final FilterPermanent filterWizard = new FilterPermanent("Wizards"); + + static { + filterWizard.add(SubType.WIZARD.getPredicate()); + } public DocentOfPerfection(UUID ownerId, CardSetInfo setInfo) { - super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}{U}"); - this.subtype.add(SubType.INSECT); - this.subtype.add(SubType.HORROR); - this.power = new MageInt(5); - this.toughness = new MageInt(4); + super(ownerId, setInfo, + new CardType[]{CardType.CREATURE}, new SubType[]{SubType.INSECT, SubType.HORROR}, "{3}{U}{U}", + "Final Iteration", + new CardType[]{CardType.CREATURE}, new SubType[]{SubType.ELDRAZI, SubType.INSECT}, "" + ); - this.secondSideCardClazz = mage.cards.f.FinalIteration.class; + // Docent of Perfection + this.getLeftHalfCard().setPT(5, 4); // Flying - this.addAbility(FlyingAbility.getInstance()); + this.getLeftHalfCard().addAbility(FlyingAbility.getInstance()); // 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()); Ability ability = new SpellCastControllerTriggeredAbility( new CreateTokenEffect(new HumanWizardToken()), StaticFilters.FILTER_SPELL_AN_INSTANT_OR_SORCERY, false @@ -59,7 +67,28 @@ public final class DocentOfPerfection extends CardImpl { new TransformSourceEffect(), condition, "Then if you control three or more Wizards, transform {this}" )); - this.addAbility(ability.addHint(hint)); + this.getLeftHalfCard().addAbility(ability.addHint(hint)); + + // Final Iteration + this.getRightHalfCard().setPT(6, 5); + + // Flying + this.getRightHalfCard().addAbility(FlyingAbility.getInstance()); + + // Wizards you control get +2/+1 and have flying. + Ability ability2 = new SimpleStaticAbility(new BoostControlledEffect( + 2, 1, Duration.WhileOnBattlefield, filterWizard, false + )); + ability2.addEffect(new GainAbilityControlledEffect( + FlyingAbility.getInstance(), Duration.WhileOnBattlefield, filterWizard + ).setText("and have flying")); + this.getRightHalfCard().addAbility(ability2); + + // Whenever you cast an instant or sorcery spell, create a 1/1 blue Human Wizard creature token. + this.getRightHalfCard().addAbility(new SpellCastControllerTriggeredAbility( + new CreateTokenEffect(new HumanWizardToken()), + StaticFilters.FILTER_SPELL_AN_INSTANT_OR_SORCERY, false + )); } private DocentOfPerfection(final DocentOfPerfection card) { diff --git a/Mage.Sets/src/mage/cards/f/FinalIteration.java b/Mage.Sets/src/mage/cards/f/FinalIteration.java deleted file mode 100644 index de5fab8d202..00000000000 --- a/Mage.Sets/src/mage/cards/f/FinalIteration.java +++ /dev/null @@ -1,70 +0,0 @@ -package mage.cards.f; - -import mage.MageInt; -import mage.abilities.Ability; -import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.common.SpellCastControllerTriggeredAbility; -import mage.abilities.effects.common.CreateTokenEffect; -import mage.abilities.effects.common.continuous.BoostControlledEffect; -import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; -import mage.abilities.keyword.FlyingAbility; -import mage.cards.CardImpl; -import mage.cards.CardSetInfo; -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 FilterPermanent filter = new FilterPermanent("Wizards"); - - static { - filter.add(SubType.WIZARD.getPredicate()); - } - - public FinalIteration(UUID ownerId, CardSetInfo setInfo) { - super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, ""); - this.subtype.add(SubType.ELDRAZI); - this.subtype.add(SubType.INSECT); - this.power = new MageInt(6); - this.toughness = new MageInt(5); - - // this card is the second face of double-faced card - this.nightCard = true; - - // Flying - 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 - )); - 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()), - StaticFilters.FILTER_SPELL_AN_INSTANT_OR_SORCERY, false - )); - } - - private FinalIteration(final FinalIteration card) { - super(card); - } - - @Override - public FinalIteration copy() { - return new FinalIteration(this); - } -} diff --git a/Mage.Sets/src/mage/cards/g/GristThePlagueSwarm.java b/Mage.Sets/src/mage/cards/g/GristThePlagueSwarm.java deleted file mode 100644 index 41a53240019..00000000000 --- a/Mage.Sets/src/mage/cards/g/GristThePlagueSwarm.java +++ /dev/null @@ -1,163 +0,0 @@ -package mage.cards.g; - -import mage.ObjectColor; -import mage.abilities.Ability; -import mage.abilities.LoyaltyAbility; -import mage.abilities.effects.Effect; -import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.CreateTokenCopyTargetEffect; -import mage.abilities.effects.common.CreateTokenEffect; -import mage.abilities.effects.common.DestroyTargetEffect; -import mage.abilities.effects.common.counter.AddCountersTargetEffect; -import mage.cards.Card; -import mage.cards.CardImpl; -import mage.cards.CardSetInfo; -import mage.cards.Cards; -import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.SubType; -import mage.constants.SuperType; -import mage.counters.CounterType; -import mage.filter.StaticFilters; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.game.permanent.PermanentCard; -import mage.game.permanent.token.IzoniInsectToken; -import mage.players.Player; -import mage.target.TargetPermanent; -import mage.target.targetpointer.FixedTargets; - -import java.util.List; -import java.util.Objects; -import java.util.Set; -import java.util.UUID; -import java.util.stream.Collectors; - -/** - * @author Susucr - */ -public final class GristThePlagueSwarm extends CardImpl { - - public GristThePlagueSwarm(UUID ownerId, CardSetInfo setInfo) { - super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, ""); - - this.supertype.add(SuperType.LEGENDARY); - this.subtype.add(SubType.GRIST); - this.setStartingLoyalty(3); - - this.color.setBlack(true); - this.color.setGreen(true); - this.nightCard = true; - - // +1: Create a 1/1 black and green Insect creature token, then mill two cards. Put a deathtouch counter on the token if a black card was milled this way. - this.addAbility(new LoyaltyAbility(new GristThePlagueSwarmPlus1Effect(), 1)); - - // -2: Destroy target artifact or enchantment. - Ability ability = new LoyaltyAbility(new DestroyTargetEffect(), -2); - ability.addTarget(new TargetPermanent(StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_ENCHANTMENT)); - this.addAbility(ability); - - // -6: For each creature card in your graveyard, create a token that's a copy of it, except it's a 1/1 black and green Insect. - this.addAbility(new LoyaltyAbility(new GristThePlagueSwarmMinus6Effect(), -6)); - } - - private GristThePlagueSwarm(final GristThePlagueSwarm card) { - super(card); - } - - @Override - public GristThePlagueSwarm copy() { - return new GristThePlagueSwarm(this); - } -} - -class GristThePlagueSwarmPlus1Effect extends OneShotEffect { - - GristThePlagueSwarmPlus1Effect() { - super(Outcome.PutCreatureInPlay); - staticText = "Create a 1/1 black and green Insect creature token, then mill two cards. " - + "Put a deathtouch counter on the token if a black card was milled this way."; - } - - private GristThePlagueSwarmPlus1Effect(final GristThePlagueSwarmPlus1Effect effect) { - super(effect); - } - - @Override - public GristThePlagueSwarmPlus1Effect copy() { - return new GristThePlagueSwarmPlus1Effect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller == null) { - return false; - } - - // Create a 1/1 black and green Insect creature token - CreateTokenEffect effect = new CreateTokenEffect(new IzoniInsectToken()); - effect.apply(game, source); - - // Then mill two cards - Cards cards = controller.millCards(2, source, game); - - // Put a deathtouch counter on the token if a black card was milled this way. - if (cards.getCards(game).stream().anyMatch(card -> card.getColor(game).isBlack())) { - List tokens = effect - .getLastAddedTokenIds() - .stream() - .map(game::getPermanent) - .filter(Objects::nonNull) - .collect(Collectors.toList()); - if (!tokens.isEmpty()) { - Effect addEffect = new AddCountersTargetEffect(CounterType.DEATHTOUCH.createInstance()); - addEffect.setTargetPointer(new FixedTargets(tokens, game)); - addEffect.apply(game, source); - } - } - return true; - } -} - -class GristThePlagueSwarmMinus6Effect extends OneShotEffect { - - GristThePlagueSwarmMinus6Effect() { - super(Outcome.PutCreatureInPlay); - staticText = "For each creature card in your graveyard, create a token that's a copy of it, " - + "except it's a 1/1 black and green Insect."; - } - - private GristThePlagueSwarmMinus6Effect(final GristThePlagueSwarmMinus6Effect effect) { - super(effect); - } - - @Override - public GristThePlagueSwarmMinus6Effect copy() { - return new GristThePlagueSwarmMinus6Effect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller == null) { - return false; - } - Set cards = controller.getGraveyard().getCards(StaticFilters.FILTER_CARD_CREATURE, game); - if (cards.isEmpty()) { - return false; - } - for (Card card : cards) { - CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect( - null, null, false, 1, false, - false, null, 1, 1, false - ); - effect.setSavedPermanent(new PermanentCard(card, controller.getId(), game)); - effect.setOnlyColor(new ObjectColor("BG")); - effect.setOnlySubType(SubType.INSECT); - effect.apply(game, source); - } - return true; - } - -} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/g/GristVoraciousLarva.java b/Mage.Sets/src/mage/cards/g/GristVoraciousLarva.java index e685b4684d1..0292cfb325f 100644 --- a/Mage.Sets/src/mage/cards/g/GristVoraciousLarva.java +++ b/Mage.Sets/src/mage/cards/g/GristVoraciousLarva.java @@ -1,46 +1,73 @@ package mage.cards.g; -import mage.MageInt; -import mage.constants.Pronoun; +import mage.ObjectColor; +import mage.abilities.Ability; +import mage.abilities.LoyaltyAbility; import mage.abilities.common.EntersBattlefieldThisOrAnotherTriggeredAbility; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.common.DoIfCostPaid; -import mage.abilities.effects.common.ExileAndReturnSourceEffect; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.*; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; import mage.abilities.keyword.DeathtouchAbility; -import mage.abilities.keyword.TransformAbility; -import mage.cards.CardImpl; +import mage.cards.Card; import mage.cards.CardSetInfo; +import mage.cards.Cards; +import mage.cards.TransformingDoubleFacedCard; import mage.constants.*; +import mage.counters.CounterType; import mage.filter.StaticFilters; import mage.game.Game; import mage.game.events.EntersTheBattlefieldEvent; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; +import mage.game.permanent.PermanentCard; +import mage.game.permanent.token.IzoniInsectToken; import mage.game.stack.Spell; +import mage.players.Player; +import mage.target.TargetPermanent; +import mage.target.targetpointer.FixedTargets; +import java.util.List; +import java.util.Objects; +import java.util.Set; import java.util.UUID; +import java.util.stream.Collectors; /** * @author Susucr */ -public final class GristVoraciousLarva extends CardImpl { +public final class GristVoraciousLarva extends TransformingDoubleFacedCard { public GristVoraciousLarva(UUID ownerId, CardSetInfo setInfo) { - super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}"); + super(ownerId, setInfo, + new SuperType[]{SuperType.LEGENDARY}, new CardType[]{CardType.CREATURE}, new SubType[]{SubType.INSECT}, "{G}", + "Grist, the Plague Swarm", + new SuperType[]{SuperType.LEGENDARY}, new CardType[]{CardType.PLANESWALKER}, new SubType[]{SubType.GRIST}, "BG" + ); - this.supertype.add(SuperType.LEGENDARY); - this.subtype.add(SubType.INSECT); - this.power = new MageInt(1); - this.toughness = new MageInt(2); - - this.secondSideCardClazz = GristThePlagueSwarm.class; + // Grist, Voracious Larva + this.getLeftHalfCard().setPT(1, 2); // Deathtouch - this.addAbility(DeathtouchAbility.getInstance()); + this.getLeftHalfCard().addAbility(DeathtouchAbility.getInstance()); // Whenever Grist, Voracious Larva or another creature you control enters, if it entered from your graveyard or was cast from your graveyard, you may pay {G}. If you do, exile Grist, then return it to the battlefield transformed under its owner's control. - this.addAbility(new TransformAbility()); - this.addAbility(new GristVoraciousLarvaTriggeredAbility()); + this.getLeftHalfCard().addAbility(new GristVoraciousLarvaTriggeredAbility()); + + // Grist, the Plague Swarm + this.getRightHalfCard().setStartingLoyalty(3); + + // +1: Create a 1/1 black and green Insect creature token, then mill two cards. Put a deathtouch counter on the token if a black card was milled this way. + this.getRightHalfCard().addAbility(new LoyaltyAbility(new GristThePlagueSwarmPlus1Effect(), 1)); + + // -2: Destroy target artifact or enchantment. + Ability ability = new LoyaltyAbility(new DestroyTargetEffect(), -2); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_ENCHANTMENT)); + this.getRightHalfCard().addAbility(ability); + + // -6: For each creature card in your graveyard, create a token that's a copy of it, except it's a 1/1 black and green Insect. + this.getRightHalfCard().addAbility(new LoyaltyAbility(new GristThePlagueSwarmMinus6Effect(), -6)); } private GristVoraciousLarva(final GristVoraciousLarva card) { @@ -100,3 +127,93 @@ class GristVoraciousLarvaTriggeredAbility extends EntersBattlefieldThisOrAnother return fromGraveyard && super.checkTrigger(event, game); } } + +class GristThePlagueSwarmPlus1Effect extends OneShotEffect { + + GristThePlagueSwarmPlus1Effect() { + super(Outcome.PutCreatureInPlay); + staticText = "Create a 1/1 black and green Insect creature token, then mill two cards. " + + "Put a deathtouch counter on the token if a black card was milled this way."; + } + + private GristThePlagueSwarmPlus1Effect(final GristThePlagueSwarmPlus1Effect effect) { + super(effect); + } + + @Override + public GristThePlagueSwarmPlus1Effect copy() { + return new GristThePlagueSwarmPlus1Effect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } + + // Create a 1/1 black and green Insect creature token + CreateTokenEffect effect = new CreateTokenEffect(new IzoniInsectToken()); + effect.apply(game, source); + + // Then mill two cards + Cards cards = controller.millCards(2, source, game); + + // Put a deathtouch counter on the token if a black card was milled this way. + if (cards.getCards(game).stream().anyMatch(card -> card.getColor(game).isBlack())) { + List tokens = effect + .getLastAddedTokenIds() + .stream() + .map(game::getPermanent) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + if (!tokens.isEmpty()) { + Effect addEffect = new AddCountersTargetEffect(CounterType.DEATHTOUCH.createInstance()); + addEffect.setTargetPointer(new FixedTargets(tokens, game)); + addEffect.apply(game, source); + } + } + return true; + } +} + +class GristThePlagueSwarmMinus6Effect extends OneShotEffect { + + GristThePlagueSwarmMinus6Effect() { + super(Outcome.PutCreatureInPlay); + staticText = "For each creature card in your graveyard, create a token that's a copy of it, " + + "except it's a 1/1 black and green Insect."; + } + + private GristThePlagueSwarmMinus6Effect(final GristThePlagueSwarmMinus6Effect effect) { + super(effect); + } + + @Override + public GristThePlagueSwarmMinus6Effect copy() { + return new GristThePlagueSwarmMinus6Effect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } + Set cards = controller.getGraveyard().getCards(StaticFilters.FILTER_CARD_CREATURE, game); + if (cards.isEmpty()) { + return false; + } + for (Card card : cards) { + CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect( + null, null, false, 1, false, + false, null, 1, 1, false + ); + effect.setSavedPermanent(new PermanentCard(card, controller.getId(), game)); + effect.setOnlyColor(new ObjectColor("BG")); + effect.setOnlySubType(SubType.INSECT); + effect.apply(game, source); + } + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/o/OreRichStalactite.java b/Mage.Sets/src/mage/cards/o/OreRichStalactite.java index e0b5ea18204..7feb3ac803e 100644 --- a/Mage.Sets/src/mage/cards/o/OreRichStalactite.java +++ b/Mage.Sets/src/mage/cards/o/OreRichStalactite.java @@ -1,18 +1,32 @@ package mage.cards.o; -import java.util.UUID; - +import mage.MageObject; import mage.Mana; import mage.ObjectColor; +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.keyword.CraftAbility; import mage.abilities.mana.ConditionalColoredManaAbility; import mage.abilities.mana.builder.common.InstantOrSorcerySpellManaBuilder; -import mage.cards.CardImpl; +import mage.cards.Card; import mage.cards.CardSetInfo; -import mage.cards.c.CosmiumCatalyst; +import mage.cards.TransformingDoubleFacedCard; import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.filter.StaticFilters; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.game.Game; +import mage.players.Player; +import mage.target.Target; +import mage.target.common.TargetCardInExile; +import mage.util.CardUtil; + +import java.util.UUID; /** * Ore-Rich Stalactite {1}{R} @@ -22,20 +36,30 @@ import mage.filter.predicate.mageobject.ColorPredicate; * * @author DominionSpy */ -public class OreRichStalactite extends CardImpl { +public class OreRichStalactite extends TransformingDoubleFacedCard { public OreRichStalactite(UUID ownerId, CardSetInfo setInfo) { - super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}{R}"); - this.secondSideCardClazz = CosmiumCatalyst.class; + super(ownerId, setInfo, + new CardType[]{CardType.ARTIFACT}, new SubType[]{}, "{1}{R}", + "Cosmium Catalyst", + new CardType[]{CardType.ARTIFACT}, new SubType[]{}, "R" + ); + // Ore-Rich Stalactite // {T}: Add {R}. Spend this mana only to cast an instant or sorcery spell. - this.addAbility(new ConditionalColoredManaAbility(Mana.RedMana(1), new InstantOrSorcerySpellManaBuilder())); + this.getLeftHalfCard().addAbility(new ConditionalColoredManaAbility(Mana.RedMana(1), new InstantOrSorcerySpellManaBuilder())); // Craft with four or more red instant and/or sorcery cards {3}{R}{R} - this.addAbility(new CraftAbility("{3}{R}{R}", "four or more red instant and/or sorcery cards", + this.getLeftHalfCard().addAbility(new CraftAbility("{3}{R}{R}", "four or more red instant and/or sorcery cards", "red instant and/or sorcery cards in your graveyard", 4, Integer.MAX_VALUE, new ColorPredicate(ObjectColor.RED), Predicates.or(CardType.INSTANT.getPredicate(), CardType.SORCERY.getPredicate()))); + + // Cosmium Catalyst + // {1}{R}, {T}: Choose an exiled card used to craft Cosmium Catalyst at random. You may cast that card without paying its mana cost. + Ability ability = new SimpleActivatedAbility(new CosmiumCatalystEffect(), new ManaCostsImpl<>("{1}{R}")); + ability.addCost(new TapSourceCost()); + this.getRightHalfCard().addAbility(ability); } private OreRichStalactite(final OreRichStalactite card) { @@ -43,7 +67,53 @@ public class OreRichStalactite extends CardImpl { } @Override - public OreRichStalactite copy() { + public OreRichStalactite copy() { return new OreRichStalactite(this); } } + +class CosmiumCatalystEffect extends OneShotEffect { + + CosmiumCatalystEffect() { + super(Outcome.PlayForFree); + this.staticText = "Choose an exiled card used to craft {this} at random." + + " You may cast that card without paying its mana cost."; + } + + private CosmiumCatalystEffect(CosmiumCatalystEffect effect) { + super(effect); + } + + @Override + public CosmiumCatalystEffect copy() { + return new CosmiumCatalystEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } + MageObject sourceObject = game.getObject(source.getSourceId()); + if (sourceObject == null) { + return false; + } + + Target target = new TargetCardInExile(StaticFilters.FILTER_CARD, + CardUtil.getExileZoneId(game, source.getSourceId(), + game.getState().getZoneChangeCounter(source.getSourceId()) - 2 + )); + target.withNotTarget(true); + target.setRandom(true); + if (!target.canChoose(controller.getId(), source, game)) { + return true; + } + target.chooseTarget(outcome, controller.getId(), source, game); + Card chosenCard = game.getCard(target.getFirstTarget()); + if (chosenCard != null) { + CardUtil.castSpellWithAttributesForFree(controller, source, game, chosenCard); + } + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/r/RalLeylineProdigy.java b/Mage.Sets/src/mage/cards/r/RalLeylineProdigy.java deleted file mode 100644 index 10e3fac4eb7..00000000000 --- a/Mage.Sets/src/mage/cards/r/RalLeylineProdigy.java +++ /dev/null @@ -1,206 +0,0 @@ -package mage.cards.r; - -import mage.MageIdentifier; -import mage.MageObject; -import mage.MageObjectReference; -import mage.ObjectColor; -import mage.abilities.Ability; -import mage.abilities.LoyaltyAbility; -import mage.abilities.common.EntersBattlefieldAbility; -import mage.abilities.condition.Condition; -import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalOneShotEffect; -import mage.abilities.dynamicvalue.common.InstantAndSorceryCastThisTurn; -import mage.abilities.effects.AsThoughEffectImpl; -import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.DamageMultiEffect; -import mage.abilities.effects.common.DrawCardSourceControllerEffect; -import mage.abilities.effects.common.cost.SpellsCostReductionControllerEffect; -import mage.abilities.effects.common.counter.AddCountersSourceEffect; -import mage.abilities.hint.ConditionHint; -import mage.abilities.hint.Hint; -import mage.cards.Card; -import mage.cards.CardImpl; -import mage.cards.CardSetInfo; -import mage.constants.*; -import mage.counters.CounterType; -import mage.filter.FilterCard; -import mage.filter.FilterPermanent; -import mage.filter.common.FilterInstantOrSorceryCard; -import mage.filter.predicate.mageobject.AnotherPredicate; -import mage.filter.predicate.mageobject.ColorPredicate; -import mage.game.Game; -import mage.players.Player; -import mage.target.common.TargetAnyTargetAmount; -import mage.util.CardUtil; - -import java.util.Set; -import java.util.UUID; - -/** - * @author Susucr - */ -public final class RalLeylineProdigy extends CardImpl { - - private static final FilterPermanent filter = new FilterPermanent("blue permanent other than {this}"); - private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter, true); - private static final Hint hint = new ConditionHint(condition, "you control another blue permanent"); - - static { - filter.add(new ColorPredicate(ObjectColor.BLUE)); - filter.add(AnotherPredicate.instance); - } - - public RalLeylineProdigy(UUID ownerId, CardSetInfo setInfo) { - super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, ""); - - this.supertype.add(SuperType.LEGENDARY); - this.subtype.add(SubType.RAL); - this.setStartingLoyalty(2); - - this.color.setBlue(true); - this.color.setRed(true); - this.nightCard = true; - - // Ral, Leyline Prodigy enters the battlefield with an additional loyalty counter on him for each instant and sorcery spell you've cast this turn. - this.addAbility(new EntersBattlefieldAbility( - new AddCountersSourceEffect(CounterType.LOYALTY.createInstance(), InstantAndSorceryCastThisTurn.YOU, - false) - .setText("with an additional loyalty counter on him for each instant and sorcery spell you've cast this turn")) - .addHint(InstantAndSorceryCastThisTurn.YOU.getHint()) - ); - - // +1: Until your next turn, instant and sorcery spells you cast cost {1} less to cast. - this.addAbility(new LoyaltyAbility(new RalLeylineProdigyCostReductionEffect(), 1)); - - // -2: Ral deals 2 damage divided as you choose among one or two targets. Draw a card if you control a blue permanent other than Ral. - Ability ability = new LoyaltyAbility(new DamageMultiEffect(), -2); - ability.addTarget(new TargetAnyTargetAmount(2)); - ability.addEffect(new ConditionalOneShotEffect( - new DrawCardSourceControllerEffect(1), - condition, "Draw a card if you control a blue permanent other than {this}" - )); - ability.addHint(hint); - this.addAbility(ability); - - // -8: Exile the top eight cards of your library. You may cast instant and sorcery spells from among them this turn without paying their mana costs. - this.addAbility(new LoyaltyAbility(new RalLeylineProdigyMinusEightEffect(), -8) - .setIdentifier(MageIdentifier.WithoutPayingManaCostAlternateCast)); - } - - private RalLeylineProdigy(final RalLeylineProdigy card) { - super(card); - } - - @Override - public RalLeylineProdigy copy() { - return new RalLeylineProdigy(this); - } -} - -class RalLeylineProdigyCostReductionEffect extends OneShotEffect { - - private static final FilterCard filter = new FilterInstantOrSorceryCard("instant and sorcery spells"); - - RalLeylineProdigyCostReductionEffect() { - super(Outcome.Benefit); - this.staticText = "Until your next turn, instant and sorcery spells you cast cost {1} less to cast"; - } - - private RalLeylineProdigyCostReductionEffect(final RalLeylineProdigyCostReductionEffect effect) { - super(effect); - } - - @Override - public RalLeylineProdigyCostReductionEffect copy() { - return new RalLeylineProdigyCostReductionEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - SpellsCostReductionControllerEffect effect = new SpellsCostReductionControllerEffect(filter, 1); - effect.setDuration(Duration.UntilYourNextTurn); - game.addEffect(effect, source); - return true; - } -} - -class RalLeylineProdigyMinusEightEffect extends OneShotEffect { - - RalLeylineProdigyMinusEightEffect() { - super(Outcome.Benefit); - staticText = "Exile the top eight cards of your library. " - + "You may cast instant and sorcery spells from among them this turn without paying their mana costs"; - } - - private RalLeylineProdigyMinusEightEffect(final RalLeylineProdigyMinusEightEffect effect) { - super(effect); - } - - @Override - public RalLeylineProdigyMinusEightEffect copy() { - return new RalLeylineProdigyMinusEightEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - MageObject sourceObject = game.getObject(source); - if (player == null || sourceObject == null) { - return false; - } - Set cards = player.getLibrary().getTopCards(game, 8); - UUID exileId = CardUtil.getExileZoneId(game, source.getSourceId(), source.getStackMomentSourceZCC()); - player.moveCardsToExile(cards, source, game, true, exileId, sourceObject.getIdName()); - for (Card card : cards) { - if (game.getState().getZone(card.getId()) == Zone.EXILED) { - game.addEffect(new RalLeylineProdigyCastEffect(new MageObjectReference(card, game)), source); - } - } - return true; - } - -} - -class RalLeylineProdigyCastEffect extends AsThoughEffectImpl { - - private final MageObjectReference mor; - - public RalLeylineProdigyCastEffect(MageObjectReference mor) { - super(AsThoughEffectType.CAST_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfTurn, Outcome.Benefit); - this.mor = mor; - } - - private RalLeylineProdigyCastEffect(final RalLeylineProdigyCastEffect effect) { - super(effect); - this.mor = effect.mor; - } - - @Override - public RalLeylineProdigyCastEffect copy() { - return new RalLeylineProdigyCastEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - return true; - } - - @Override - public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { - if (mor.getCard(game) == null) { - discard(); - return false; - } - Card theCard = game.getCard(objectId); - if (theCard == null || !theCard.isInstantOrSorcery(game)) { - return false; - } - UUID mainId = theCard.getMainCard().getId(); // for split cards/MDFC/Adventure cards - if (!source.isControlledBy(affectedControllerId) || !mor.refersTo(mainId, game)) { - return false; - } - allowCardToPlayWithoutMana(mainId, source, affectedControllerId, MageIdentifier.WithoutPayingManaCostAlternateCast, game); - return true; - } -} diff --git a/Mage.Sets/src/mage/cards/r/RalMonsoonMage.java b/Mage.Sets/src/mage/cards/r/RalMonsoonMage.java index c579098b09c..88f51bb66ce 100644 --- a/Mage.Sets/src/mage/cards/r/RalMonsoonMage.java +++ b/Mage.Sets/src/mage/cards/r/RalMonsoonMage.java @@ -1,53 +1,107 @@ package mage.cards.r; -import mage.MageInt; +import mage.MageIdentifier; +import mage.MageObject; +import mage.MageObjectReference; +import mage.ObjectColor; import mage.abilities.Ability; -import mage.abilities.dynamicvalue.common.InstantAndSorceryCastThisTurn; -import mage.constants.Pronoun; +import mage.abilities.LoyaltyAbility; +import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SpellCastControllerTriggeredAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.dynamicvalue.common.InstantAndSorceryCastThisTurn; +import mage.abilities.effects.AsThoughEffectImpl; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DamageControllerEffect; +import mage.abilities.effects.common.DamageMultiEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.ExileAndReturnSourceEffect; import mage.abilities.effects.common.cost.SpellsCostReductionControllerEffect; -import mage.abilities.keyword.TransformAbility; -import mage.cards.CardImpl; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.hint.ConditionHint; +import mage.abilities.hint.Hint; +import mage.cards.Card; import mage.cards.CardSetInfo; +import mage.cards.TransformingDoubleFacedCard; import mage.constants.*; +import mage.counters.CounterType; import mage.filter.FilterCard; +import mage.filter.FilterPermanent; import mage.filter.StaticFilters; import mage.filter.common.FilterInstantOrSorceryCard; +import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.filter.predicate.mageobject.ColorPredicate; import mage.game.Game; import mage.game.events.GameEvent; import mage.players.Player; +import mage.target.common.TargetAnyTargetAmount; +import mage.util.CardUtil; +import java.util.Set; import java.util.UUID; /** * @author Susucr */ -public final class RalMonsoonMage extends CardImpl { +public final class RalMonsoonMage extends TransformingDoubleFacedCard { private static final FilterCard filter = new FilterInstantOrSorceryCard("Instant and sorcery spells"); + private static final FilterPermanent filterBlue = new FilterPermanent("blue permanent other than {this}"); + private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filterBlue, true); + private static final Hint hint = new ConditionHint(condition, "you control another blue permanent"); + + static { + filterBlue.add(new ColorPredicate(ObjectColor.BLUE)); + filterBlue.add(AnotherPredicate.instance); + } public RalMonsoonMage(UUID ownerId, CardSetInfo setInfo) { - super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}"); + super(ownerId, setInfo, + new SuperType[]{SuperType.LEGENDARY}, new CardType[]{CardType.CREATURE}, new SubType[]{SubType.HUMAN, SubType.WIZARD}, "{1}{R}", + "Ral, Leyline Prodigy", + new SuperType[]{SuperType.LEGENDARY}, new CardType[]{CardType.PLANESWALKER}, new SubType[]{SubType.RAL}, "UR" + ); - this.supertype.add(SuperType.LEGENDARY); - this.subtype.add(SubType.HUMAN); - this.subtype.add(SubType.WIZARD); - this.power = new MageInt(1); - this.toughness = new MageInt(3); - - this.secondSideCardClazz = RalLeylineProdigy.class; + // Ral, Monsoon Mage + this.getLeftHalfCard().setPT(1, 3); // Instant and sorcery spells you cast cost {1} less to cast. - this.addAbility(new SimpleStaticAbility(new SpellsCostReductionControllerEffect(filter, 1))); + this.getLeftHalfCard().addAbility(new SimpleStaticAbility(new SpellsCostReductionControllerEffect(filter, 1))); // Whenever you cast an instant or sorcery spell during your turn, flip a coin. If you lose the flip, Ral, Monsoon Mage deals 1 damage to you. If you win the flip, you may exile Ral. If you do, return him to the battlefield transformed under his owner control. - this.addAbility(new TransformAbility()); - this.addAbility(new RalMonsoonMageTriggeredAbility() + this.getLeftHalfCard().addAbility(new RalMonsoonMageTriggeredAbility() .addHint(InstantAndSorceryCastThisTurn.YOU.getHint())); + + // Ral, Leyline Prodigy + this.getRightHalfCard().setStartingLoyalty(2); + + // Ral, Leyline Prodigy enters the battlefield with an additional loyalty counter on him for each instant and sorcery spell you've cast this turn. + this.getRightHalfCard().addAbility(new EntersBattlefieldAbility( + new AddCountersSourceEffect(CounterType.LOYALTY.createInstance(), InstantAndSorceryCastThisTurn.YOU, + false) + .setText("with an additional loyalty counter on him for each instant and sorcery spell you've cast this turn")) + .addHint(InstantAndSorceryCastThisTurn.YOU.getHint()) + ); + + // +1: Until your next turn, instant and sorcery spells you cast cost {1} less to cast. + this.getRightHalfCard().addAbility(new LoyaltyAbility(new RalLeylineProdigyCostReductionEffect(), 1)); + + // -2: Ral deals 2 damage divided as you choose among one or two targets. Draw a card if you control a blue permanent other than Ral. + Ability ability = new LoyaltyAbility(new DamageMultiEffect(), -2); + ability.addTarget(new TargetAnyTargetAmount(2)); + ability.addEffect(new ConditionalOneShotEffect( + new DrawCardSourceControllerEffect(1), + condition, "Draw a card if you control a blue permanent other than {this}" + )); + ability.addHint(hint); + this.getRightHalfCard().addAbility(ability); + + // -8: Exile the top eight cards of your library. You may cast instant and sorcery spells from among them this turn without paying their mana costs. + this.getRightHalfCard().addAbility(new LoyaltyAbility(new RalLeylineProdigyMinusEightEffect(), -8) + .setIdentifier(MageIdentifier.WithoutPayingManaCostAlternateCast)); } private RalMonsoonMage(final RalMonsoonMage card) { @@ -118,3 +172,109 @@ class RalMonsoonMageEffect extends OneShotEffect { return true; } } + +class RalLeylineProdigyCostReductionEffect extends OneShotEffect { + + private static final FilterCard filter = new FilterInstantOrSorceryCard("instant and sorcery spells"); + + RalLeylineProdigyCostReductionEffect() { + super(Outcome.Benefit); + this.staticText = "Until your next turn, instant and sorcery spells you cast cost {1} less to cast"; + } + + private RalLeylineProdigyCostReductionEffect(final RalLeylineProdigyCostReductionEffect effect) { + super(effect); + } + + @Override + public RalLeylineProdigyCostReductionEffect copy() { + return new RalLeylineProdigyCostReductionEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + SpellsCostReductionControllerEffect effect = new SpellsCostReductionControllerEffect(filter, 1); + effect.setDuration(Duration.UntilYourNextTurn); + game.addEffect(effect, source); + return true; + } +} + +class RalLeylineProdigyMinusEightEffect extends OneShotEffect { + + RalLeylineProdigyMinusEightEffect() { + super(Outcome.Benefit); + staticText = "Exile the top eight cards of your library. " + + "You may cast instant and sorcery spells from among them this turn without paying their mana costs"; + } + + private RalLeylineProdigyMinusEightEffect(final RalLeylineProdigyMinusEightEffect effect) { + super(effect); + } + + @Override + public RalLeylineProdigyMinusEightEffect copy() { + return new RalLeylineProdigyMinusEightEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + MageObject sourceObject = game.getObject(source); + if (player == null || sourceObject == null) { + return false; + } + Set cards = player.getLibrary().getTopCards(game, 8); + UUID exileId = CardUtil.getExileZoneId(game, source.getSourceId(), source.getStackMomentSourceZCC()); + player.moveCardsToExile(cards, source, game, true, exileId, sourceObject.getIdName()); + for (Card card : cards) { + if (game.getState().getZone(card.getId()) == Zone.EXILED) { + game.addEffect(new RalLeylineProdigyCastEffect(new MageObjectReference(card, game)), source); + } + } + return true; + } +} + +class RalLeylineProdigyCastEffect extends AsThoughEffectImpl { + + private final MageObjectReference mor; + + public RalLeylineProdigyCastEffect(MageObjectReference mor) { + super(AsThoughEffectType.CAST_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfTurn, Outcome.Benefit); + this.mor = mor; + } + + private RalLeylineProdigyCastEffect(final RalLeylineProdigyCastEffect effect) { + super(effect); + this.mor = effect.mor; + } + + @Override + public RalLeylineProdigyCastEffect copy() { + return new RalLeylineProdigyCastEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { + if (mor.getCard(game) == null) { + discard(); + return false; + } + Card theCard = game.getCard(objectId); + if (theCard == null || !theCard.isInstantOrSorcery(game)) { + return false; + } + UUID mainId = theCard.getMainCard().getId(); // for split cards/MDFC/Adventure cards + if (!source.isControlledBy(affectedControllerId) || !mor.refersTo(mainId, game)) { + return false; + } + allowCardToPlayWithoutMana(mainId, source, affectedControllerId, MageIdentifier.WithoutPayingManaCostAlternateCast, game); + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/s/SorinOfHouseMarkov.java b/Mage.Sets/src/mage/cards/s/SorinOfHouseMarkov.java index ccbbb37b09e..13eeb95a616 100644 --- a/Mage.Sets/src/mage/cards/s/SorinOfHouseMarkov.java +++ b/Mage.Sets/src/mage/cards/s/SorinOfHouseMarkov.java @@ -1,18 +1,38 @@ package mage.cards.s; -import mage.MageInt; +import mage.ObjectColor; +import mage.abilities.Ability; +import mage.abilities.LoyaltyAbility; import mage.abilities.condition.Condition; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; import mage.abilities.condition.common.YouGainedLifeCondition; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.dynamicvalue.common.ControllerGainedLifeCount; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.ExileAndReturnSourceEffect; +import mage.abilities.effects.common.continuous.BecomesCreatureTypeTargetEffect; +import mage.abilities.effects.common.continuous.GainControlTargetEffect; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; import mage.abilities.hint.ConditionHint; import mage.abilities.hint.Hint; import mage.abilities.keyword.ExtortAbility; import mage.abilities.keyword.LifelinkAbility; -import mage.abilities.keyword.TransformAbility; import mage.abilities.triggers.BeginningOfPostcombatMainTriggeredAbility; -import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.cards.TransformingDoubleFacedCard; import mage.constants.*; +import mage.counters.CounterType; +import mage.filter.FilterPermanent; +import mage.filter.predicate.ObjectSourcePlayer; +import mage.filter.predicate.ObjectSourcePlayerPredicate; +import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.filter.predicate.mageobject.ColorPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.game.permanent.token.FoodToken; +import mage.target.common.TargetAnyTarget; +import mage.target.common.TargetCreaturePermanent; import mage.watchers.common.PlayerGainedLifeWatcher; import java.util.UUID; @@ -20,33 +40,73 @@ import java.util.UUID; /** * @author Susucr */ -public final class SorinOfHouseMarkov extends CardImpl { +public final class SorinOfHouseMarkov extends TransformingDoubleFacedCard { private static final Condition condition = new YouGainedLifeCondition(ComparisonType.MORE_THAN, 2); private static final Hint hint = new ConditionHint(condition); + private static final FilterPermanent filterWhite = new FilterPermanent("white permanent other than that creature or {this}"); + private static final Condition conditionWhite = new PermanentsOnTheBattlefieldCondition(filterWhite, true); + private static final Hint hintWhite = new ConditionHint(conditionWhite, "you control another white permanent"); + + static { + filterWhite.add(new ColorPredicate(ObjectColor.WHITE)); + filterWhite.add(AnotherPredicate.instance); + filterWhite.add(SorinRavenousNeonatePredicate.instance); + } + public SorinOfHouseMarkov(UUID ownerId, CardSetInfo setInfo) { - super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}"); + super(ownerId, setInfo, + new SuperType[]{SuperType.LEGENDARY}, new CardType[]{CardType.CREATURE}, new SubType[]{SubType.HUMAN, SubType.NOBLE}, "{1}{B}", + "Sorin, Ravenous Neonate", + new SuperType[]{SuperType.LEGENDARY}, new CardType[]{CardType.PLANESWALKER}, new SubType[]{SubType.SORIN}, "WB" + ); - this.supertype.add(SuperType.LEGENDARY); - this.subtype.add(SubType.HUMAN); - this.subtype.add(SubType.NOBLE); - this.power = new MageInt(1); - this.toughness = new MageInt(4); + // Sorin of House Markov + this.getLeftHalfCard().setPT(1, 4); - this.secondSideCardClazz = SorinRavenousNeonate.class; - - // Flying - this.addAbility(LifelinkAbility.getInstance()); + // Lifelink + this.getLeftHalfCard().addAbility(LifelinkAbility.getInstance()); // Extort - this.addAbility(new ExtortAbility()); + this.getLeftHalfCard().addAbility(new ExtortAbility()); // At the beginning of your postcombat main phase, if you gained 3 or more life this turn, exile Sorin of House Markov, then return him to the battlefield transformed under his owner's control. - this.addAbility(new TransformAbility()); - this.addAbility(new BeginningOfPostcombatMainTriggeredAbility( + Ability ability = new BeginningOfPostcombatMainTriggeredAbility( new ExileAndReturnSourceEffect(PutCards.BATTLEFIELD_TRANSFORMED, Pronoun.HE), false - ).withInterveningIf(condition).addHint(hint), new PlayerGainedLifeWatcher()); + ).withInterveningIf(condition).addHint(hint); + ability.addWatcher(new PlayerGainedLifeWatcher()); + this.getLeftHalfCard().addAbility(ability); + + // Sorin, Ravenous Neonate + this.getRightHalfCard().setStartingLoyalty(3); + + // Extort + this.getRightHalfCard().addAbility(new ExtortAbility()); + + // +2: Create a Food token. + this.getRightHalfCard().addAbility(new LoyaltyAbility(new CreateTokenEffect(new FoodToken()), 2)); + + // -1: Sorin, Ravenous Neonate deals damage equal to the amount of life you gained this turn to any target. + ability = new LoyaltyAbility( + new DamageTargetEffect(ControllerGainedLifeCount.instance) + .setText("{this} deals damage equal to the amount of life you gained this turn to any target"), + -1 + ); + ability.addTarget(new TargetAnyTarget()); + ability.addWatcher(new PlayerGainedLifeWatcher()); + this.getRightHalfCard().addAbility(ability.addHint(ControllerGainedLifeCount.getHint())); + + // -6: Gain control of target creature. It becomes a Vampire in addition to its other types. Put a lifelink counter on it if you control a white permanent other than that creature or Sorin. + Ability ability2 = new LoyaltyAbility(new GainControlTargetEffect(Duration.EndOfGame), -6); + ability2.addTarget(new TargetCreaturePermanent()); + ability2.addEffect(new BecomesCreatureTypeTargetEffect(Duration.EndOfGame, SubType.VAMPIRE, false) + .setText("It becomes a Vampire in addition to its other types")); + ability2.addEffect(new ConditionalOneShotEffect( + new AddCountersTargetEffect(CounterType.LIFELINK.createInstance()), + conditionWhite, "Put a lifelink counter on it if you control a white permanent other than that creature or {this}" + )); + this.getRightHalfCard().addAbility(ability2.addHint(hintWhite)); } private SorinOfHouseMarkov(final SorinOfHouseMarkov card) { @@ -58,3 +118,16 @@ public final class SorinOfHouseMarkov extends CardImpl { return new SorinOfHouseMarkov(this); } } + +enum SorinRavenousNeonatePredicate implements ObjectSourcePlayerPredicate { + instance; + + @Override + public boolean apply(ObjectSourcePlayer input, Game game) { + Ability source = input.getSource(); + Permanent permanent = input.getObject(); + return source != null + && permanent != null + && !permanent.getId().equals(source.getFirstTarget()); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SorinRavenousNeonate.java b/Mage.Sets/src/mage/cards/s/SorinRavenousNeonate.java deleted file mode 100644 index e294dad377c..00000000000 --- a/Mage.Sets/src/mage/cards/s/SorinRavenousNeonate.java +++ /dev/null @@ -1,113 +0,0 @@ -package mage.cards.s; - -import mage.ObjectColor; -import mage.abilities.Ability; -import mage.abilities.LoyaltyAbility; -import mage.abilities.condition.Condition; -import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalOneShotEffect; -import mage.abilities.dynamicvalue.common.ControllerGainedLifeCount; -import mage.abilities.effects.common.CreateTokenEffect; -import mage.abilities.effects.common.DamageTargetEffect; -import mage.abilities.effects.common.continuous.BecomesCreatureTypeTargetEffect; -import mage.abilities.effects.common.continuous.GainControlTargetEffect; -import mage.abilities.effects.common.counter.AddCountersTargetEffect; -import mage.abilities.hint.ConditionHint; -import mage.abilities.hint.Hint; -import mage.abilities.keyword.ExtortAbility; -import mage.cards.CardImpl; -import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.SubType; -import mage.constants.SuperType; -import mage.counters.CounterType; -import mage.filter.FilterPermanent; -import mage.filter.predicate.ObjectSourcePlayer; -import mage.filter.predicate.ObjectSourcePlayerPredicate; -import mage.filter.predicate.mageobject.AnotherPredicate; -import mage.filter.predicate.mageobject.ColorPredicate; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.game.permanent.token.FoodToken; -import mage.target.common.TargetAnyTarget; -import mage.target.common.TargetCreaturePermanent; -import mage.watchers.common.PlayerGainedLifeWatcher; - -import java.util.UUID; - -/** - * @author Susucr - */ -public final class SorinRavenousNeonate extends CardImpl { - - private static final FilterPermanent filter = new FilterPermanent("white permanent other than that creature or {this}"); - private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter, true); - private static final Hint hint = new ConditionHint(condition, "you control another white permanent"); - - static { - filter.add(new ColorPredicate(ObjectColor.WHITE)); - filter.add(AnotherPredicate.instance); - filter.add(SorinRavenousNeonatePredicate.instance); - } - - public SorinRavenousNeonate(UUID ownerId, CardSetInfo setInfo) { - super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, ""); - - this.supertype.add(SuperType.LEGENDARY); - this.subtype.add(SubType.SORIN); - this.setStartingLoyalty(3); - - this.color.setWhite(true); - this.color.setBlack(true); - this.nightCard = true; - - // Extort - this.addAbility(new ExtortAbility()); - - // +2: Create a Food token. - this.addAbility(new LoyaltyAbility(new CreateTokenEffect(new FoodToken()), 2)); - - // -1: Sorin, Ravenous Neonate deals damage equal to the amount of life you gained this turn to any target. - Ability ability = new LoyaltyAbility( - new DamageTargetEffect(ControllerGainedLifeCount.instance) - .setText("{this} deals damage equal to the amount of life you gained this turn to any target"), - -1 - ); - ability.addTarget(new TargetAnyTarget()); - this.addAbility(ability.addHint(ControllerGainedLifeCount.getHint()), new PlayerGainedLifeWatcher()); - - // -6: Gain control of target creature. It becomes a Vampire in addition to its other types. Put a lifelink counter on it if you control a white permanent other than that creature or Sorin. - ability = new LoyaltyAbility(new GainControlTargetEffect(Duration.EndOfGame), -6); - ability.addTarget(new TargetCreaturePermanent()); - ability.addEffect(new BecomesCreatureTypeTargetEffect(Duration.EndOfGame, SubType.VAMPIRE, false) - .setText("It becomes a Vampire in addition to its other types")); - ability.addEffect(new ConditionalOneShotEffect( - new AddCountersTargetEffect(CounterType.LIFELINK.createInstance()), - condition, "Put a lifelink counter on it if you control a white permanent other than that creature or {this}" - )); - this.addAbility(ability.addHint(hint)); - } - - private SorinRavenousNeonate(final SorinRavenousNeonate card) { - super(card); - } - - @Override - public SorinRavenousNeonate copy() { - return new SorinRavenousNeonate(this); - } -} - -enum SorinRavenousNeonatePredicate implements ObjectSourcePlayerPredicate { - instance; - - @Override - public boolean apply(ObjectSourcePlayer input, Game game) { - Ability source = input.getSource(); - Permanent permanent = input.getObject(); - return source != null - && permanent != null - && !permanent.getId().equals(source.getFirstTarget()); - } -} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/EldritchMoon.java b/Mage.Sets/src/mage/sets/EldritchMoon.java index 139f9fe0845..76aa983a42f 100644 --- a/Mage.Sets/src/mage/sets/EldritchMoon.java +++ b/Mage.Sets/src/mage/sets/EldritchMoon.java @@ -110,7 +110,6 @@ public final class EldritchMoon extends ExpansionSet { cards.add(new SetCardInfo("Falkenrath Reaver", 127, Rarity.COMMON, mage.cards.f.FalkenrathReaver.class)); cards.add(new SetCardInfo("Field Creeper", 195, Rarity.COMMON, mage.cards.f.FieldCreeper.class)); cards.add(new SetCardInfo("Fiend Binder", 26, Rarity.COMMON, mage.cards.f.FiendBinder.class)); - cards.add(new SetCardInfo("Final Iteration", 56, Rarity.RARE, mage.cards.f.FinalIteration.class)); cards.add(new SetCardInfo("Fogwalker", 60, Rarity.COMMON, mage.cards.f.Fogwalker.class)); cards.add(new SetCardInfo("Fortune's Favor", 61, Rarity.UNCOMMON, mage.cards.f.FortunesFavor.class)); cards.add(new SetCardInfo("Foul Emissary", 158, Rarity.UNCOMMON, mage.cards.f.FoulEmissary.class)); diff --git a/Mage.Sets/src/mage/sets/EldritchMoonPromos.java b/Mage.Sets/src/mage/sets/EldritchMoonPromos.java index ff31cab8af7..32cae370100 100644 --- a/Mage.Sets/src/mage/sets/EldritchMoonPromos.java +++ b/Mage.Sets/src/mage/sets/EldritchMoonPromos.java @@ -41,7 +41,6 @@ public class EldritchMoonPromos extends ExpansionSet { cards.add(new SetCardInfo("Emrakul's Evangel", "156s", Rarity.RARE, mage.cards.e.EmrakulsEvangel.class)); cards.add(new SetCardInfo("Emrakul, the Promised End", "6s", Rarity.MYTHIC, mage.cards.e.EmrakulThePromisedEnd.class)); cards.add(new SetCardInfo("Eternal Scourge", "7s", Rarity.RARE, mage.cards.e.EternalScourge.class)); - cards.add(new SetCardInfo("Final Iteration", "56s", Rarity.RARE, mage.cards.f.FinalIteration.class)); cards.add(new SetCardInfo("Geier Reach Sanitarium", "203s", Rarity.RARE, mage.cards.g.GeierReachSanitarium.class)); cards.add(new SetCardInfo("Gisa and Geralf", "183s", Rarity.MYTHIC, mage.cards.g.GisaAndGeralf.class)); cards.add(new SetCardInfo("Gisela, the Broken Blade", "28s", Rarity.MYTHIC, mage.cards.g.GiselaTheBrokenBlade.class)); diff --git a/Mage.Sets/src/mage/sets/InnistradRemastered.java b/Mage.Sets/src/mage/sets/InnistradRemastered.java index 8c14a342ef2..f2644ce218f 100644 --- a/Mage.Sets/src/mage/sets/InnistradRemastered.java +++ b/Mage.Sets/src/mage/sets/InnistradRemastered.java @@ -192,7 +192,6 @@ public class InnistradRemastered extends ExpansionSet { cards.add(new SetCardInfo("Fiend Hunter", 22, Rarity.UNCOMMON, mage.cards.f.FiendHunter.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Fiend Hunter", 340, Rarity.UNCOMMON, mage.cards.f.FiendHunter.class, RETRO_ART_USE_VARIOUS)); cards.add(new SetCardInfo("Fiery Temper", 154, Rarity.UNCOMMON, mage.cards.f.FieryTemper.class)); - cards.add(new SetCardInfo("Final Iteration", 62, Rarity.RARE, mage.cards.f.FinalIteration.class)); cards.add(new SetCardInfo("Fleshtaker", 235, Rarity.UNCOMMON, mage.cards.f.Fleshtaker.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Fleshtaker", 429, Rarity.UNCOMMON, mage.cards.f.Fleshtaker.class, RETRO_ART_USE_VARIOUS)); cards.add(new SetCardInfo("Forbidden Alchemy", 355, Rarity.UNCOMMON, mage.cards.f.ForbiddenAlchemy.class, RETRO_ART_USE_VARIOUS)); diff --git a/Mage.Sets/src/mage/sets/ModernHorizons3.java b/Mage.Sets/src/mage/sets/ModernHorizons3.java index 81aee2e1d69..57fe3560988 100644 --- a/Mage.Sets/src/mage/sets/ModernHorizons3.java +++ b/Mage.Sets/src/mage/sets/ModernHorizons3.java @@ -213,9 +213,6 @@ public final class ModernHorizons3 extends ExpansionSet { cards.add(new SetCardInfo("Gravedig", 96, Rarity.COMMON, mage.cards.g.Gravedig.class)); cards.add(new SetCardInfo("Grim Servant", 97, Rarity.UNCOMMON, mage.cards.g.GrimServant.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Grim Servant", 409, Rarity.UNCOMMON, mage.cards.g.GrimServant.class, RETRO_ART_USE_VARIOUS)); - cards.add(new SetCardInfo("Grist, the Plague Swarm", 251, Rarity.MYTHIC, mage.cards.g.GristThePlagueSwarm.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Grist, the Plague Swarm", 446, Rarity.MYTHIC, mage.cards.g.GristThePlagueSwarm.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Grist, the Plague Swarm", 472, Rarity.MYTHIC, mage.cards.g.GristThePlagueSwarm.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Grist, Voracious Larva", 251, Rarity.MYTHIC, mage.cards.g.GristVoraciousLarva.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Grist, Voracious Larva", 446, Rarity.MYTHIC, mage.cards.g.GristVoraciousLarva.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Grist, Voracious Larva", 472, Rarity.MYTHIC, mage.cards.g.GristVoraciousLarva.class, NON_FULL_USE_VARIOUS)); @@ -381,9 +378,6 @@ public final class ModernHorizons3 extends ExpansionSet { cards.add(new SetCardInfo("Pyretic Rebirth", 200, Rarity.UNCOMMON, mage.cards.p.PyreticRebirth.class)); cards.add(new SetCardInfo("Quest for the Necropolis", 104, Rarity.UNCOMMON, mage.cards.q.QuestForTheNecropolis.class)); cards.add(new SetCardInfo("Ral and the Implicit Maze", 132, Rarity.UNCOMMON, mage.cards.r.RalAndTheImplicitMaze.class)); - cards.add(new SetCardInfo("Ral, Leyline Prodigy", 247, Rarity.MYTHIC, mage.cards.r.RalLeylineProdigy.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Ral, Leyline Prodigy", 445, Rarity.MYTHIC, mage.cards.r.RalLeylineProdigy.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Ral, Leyline Prodigy", 471, Rarity.MYTHIC, mage.cards.r.RalLeylineProdigy.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Ral, Monsoon Mage", 247, Rarity.MYTHIC, mage.cards.r.RalMonsoonMage.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Ral, Monsoon Mage", 445, Rarity.MYTHIC, mage.cards.r.RalMonsoonMage.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Ral, Monsoon Mage", 471, Rarity.MYTHIC, mage.cards.r.RalMonsoonMage.class, NON_FULL_USE_VARIOUS)); @@ -452,9 +446,6 @@ public final class ModernHorizons3 extends ExpansionSet { cards.add(new SetCardInfo("Sorin of House Markov", 245, Rarity.MYTHIC, mage.cards.s.SorinOfHouseMarkov.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sorin of House Markov", 444, Rarity.MYTHIC, mage.cards.s.SorinOfHouseMarkov.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sorin of House Markov", 470, Rarity.MYTHIC, mage.cards.s.SorinOfHouseMarkov.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Sorin, Ravenous Neonate", 245, Rarity.MYTHIC, mage.cards.s.SorinRavenousNeonate.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Sorin, Ravenous Neonate", 444, Rarity.MYTHIC, mage.cards.s.SorinRavenousNeonate.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Sorin, Ravenous Neonate", 470, Rarity.MYTHIC, mage.cards.s.SorinRavenousNeonate.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sowing Mycospawn", 170, Rarity.RARE, mage.cards.s.SowingMycospawn.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sowing Mycospawn", 340, Rarity.RARE, mage.cards.s.SowingMycospawn.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Spawn-Gang Commander", 140, Rarity.UNCOMMON, mage.cards.s.SpawnGangCommander.class)); diff --git a/Mage.Sets/src/mage/sets/SecretLairDrop.java b/Mage.Sets/src/mage/sets/SecretLairDrop.java index a938a1e52c2..4fc7205f1d3 100644 --- a/Mage.Sets/src/mage/sets/SecretLairDrop.java +++ b/Mage.Sets/src/mage/sets/SecretLairDrop.java @@ -1144,7 +1144,6 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("Evin, Waterdeep Opportunist", 1239, Rarity.RARE, mage.cards.e.EvinWaterdeepOpportunist.class)); cards.add(new SetCardInfo("Jurin, Leading the Charge", 1240, Rarity.RARE, mage.cards.j.JurinLeadingTheCharge.class)); cards.add(new SetCardInfo("Casal, Lurkwood Pathfinder", 1241, Rarity.RARE, mage.cards.c.CasalLurkwoodPathfinder.class)); - cards.add(new SetCardInfo("Casal, Pathbreaker Owlbear", 1241, Rarity.RARE, mage.cards.c.CasalPathbreakerOwlbear.class)); cards.add(new SetCardInfo("Bohn, Beguiling Balladeer", 1242, Rarity.RARE, mage.cards.b.BohnBeguilingBalladeer.class)); cards.add(new SetCardInfo("Ugin, the Ineffable", 1243, Rarity.RARE, mage.cards.u.UginTheIneffable.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sorin, Imperious Bloodlord", 1244, Rarity.MYTHIC, mage.cards.s.SorinImperiousBloodlord.class)); diff --git a/Mage.Sets/src/mage/sets/ShadowsOverInnistradRemastered.java b/Mage.Sets/src/mage/sets/ShadowsOverInnistradRemastered.java index 1bb4d1568d6..beae6f1be95 100644 --- a/Mage.Sets/src/mage/sets/ShadowsOverInnistradRemastered.java +++ b/Mage.Sets/src/mage/sets/ShadowsOverInnistradRemastered.java @@ -119,7 +119,6 @@ public class ShadowsOverInnistradRemastered extends ExpansionSet { cards.add(new SetCardInfo("Field Creeper", 251, Rarity.COMMON, mage.cards.f.FieldCreeper.class)); cards.add(new SetCardInfo("Fiend Binder", 29, Rarity.COMMON, mage.cards.f.FiendBinder.class)); cards.add(new SetCardInfo("Fiery Temper", 154, Rarity.UNCOMMON, mage.cards.f.FieryTemper.class)); - cards.add(new SetCardInfo("Final Iteration", 61, Rarity.RARE, mage.cards.f.FinalIteration.class)); cards.add(new SetCardInfo("Flameblade Angel", 155, Rarity.RARE, mage.cards.f.FlamebladeAngel.class)); cards.add(new SetCardInfo("Fleeting Memories", 69, Rarity.UNCOMMON, mage.cards.f.FleetingMemories.class)); cards.add(new SetCardInfo("Fogwalker", 70, Rarity.COMMON, mage.cards.f.Fogwalker.class)); diff --git a/Mage.Sets/src/mage/sets/TheLostCavernsOfIxalanCommander.java b/Mage.Sets/src/mage/sets/TheLostCavernsOfIxalanCommander.java index 007c3f2c2a7..1fccd3b5ec5 100644 --- a/Mage.Sets/src/mage/sets/TheLostCavernsOfIxalanCommander.java +++ b/Mage.Sets/src/mage/sets/TheLostCavernsOfIxalanCommander.java @@ -83,7 +83,6 @@ public final class TheLostCavernsOfIxalanCommander extends ExpansionSet { cards.add(new SetCardInfo("Coralhelm Commander", 148, Rarity.RARE, mage.cards.c.CoralhelmCommander.class)); cards.add(new SetCardInfo("Cordial Vampire", 189, Rarity.RARE, mage.cards.c.CordialVampire.class)); cards.add(new SetCardInfo("Corsair Captain", 149, Rarity.RARE, mage.cards.c.CorsairCaptain.class)); - cards.add(new SetCardInfo("Cosmium Catalyst", 11, Rarity.RARE, mage.cards.c.CosmiumCatalyst.class)); cards.add(new SetCardInfo("Crossway Troublemakers", 190, Rarity.RARE, mage.cards.c.CrosswayTroublemakers.class)); cards.add(new SetCardInfo("Cruel Celebrant", 267, Rarity.UNCOMMON, mage.cards.c.CruelCelebrant.class)); cards.add(new SetCardInfo("Crumbling Necropolis", 326, Rarity.UNCOMMON, mage.cards.c.CrumblingNecropolis.class)); diff --git a/Mage.Sets/src/mage/sets/UniversesWithin.java b/Mage.Sets/src/mage/sets/UniversesWithin.java index c125b00b5e0..cdf48b12faf 100644 --- a/Mage.Sets/src/mage/sets/UniversesWithin.java +++ b/Mage.Sets/src/mage/sets/UniversesWithin.java @@ -26,7 +26,6 @@ public final class UniversesWithin extends ExpansionSet { cards.add(new SetCardInfo("Bohn, Beguiling Balladeer", 30, Rarity.RARE, mage.cards.b.BohnBeguilingBalladeer.class)); cards.add(new SetCardInfo("Bjorna, Nightfall Alchemist", 2, Rarity.RARE, mage.cards.b.BjornaNightfallAlchemist.class)); cards.add(new SetCardInfo("Casal, Lurkwood Pathfinder", 29, Rarity.RARE, mage.cards.c.CasalLurkwoodPathfinder.class)); - cards.add(new SetCardInfo("Casal, Pathbreaker Owlbear", 29, Rarity.RARE, mage.cards.c.CasalPathbreakerOwlbear.class)); cards.add(new SetCardInfo("Cecily, Haunted Mage", 3, Rarity.RARE, mage.cards.c.CecilyHauntedMage.class)); cards.add(new SetCardInfo("Elmar, Ulvenwald Informant", 4, Rarity.RARE, mage.cards.e.ElmarUlvenwaldInformant.class)); cards.add(new SetCardInfo("Enkira, Hostile Scavenger", 20, Rarity.MYTHIC, mage.cards.e.EnkiraHostileScavenger.class));