diff --git a/Mage.Sets/src/mage/cards/s/SeverancePriest.java b/Mage.Sets/src/mage/cards/s/SeverancePriest.java new file mode 100644 index 00000000000..ff17d0efc7b --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SeverancePriest.java @@ -0,0 +1,98 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.LeavesBattlefieldTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateXXTokenExiledEffectManaValueEffect; +import mage.abilities.keyword.DeathtouchAbility; +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.filter.StaticFilters; +import mage.game.Game; +import mage.game.permanent.token.SpiritXXToken; +import mage.players.Player; +import mage.target.TargetCard; +import mage.target.common.TargetCardInHand; +import mage.target.common.TargetOpponent; +import mage.util.CardUtil; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SeverancePriest extends CardImpl { + + public SeverancePriest(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}{B}{G}"); + + this.subtype.add(SubType.DJINN); + this.subtype.add(SubType.CLERIC); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Deathtouch + this.addAbility(DeathtouchAbility.getInstance()); + + // When this creature enters, target opponent reveals their hand. You may choose a nonland card from it. If you do, exile that card. + Ability ability = new EntersBattlefieldTriggeredAbility(new SeverancePriestEffect()); + ability.addTarget(new TargetOpponent()); + this.addAbility(ability); + + // When this creature leaves the battlefield, the exiled card's owner creates an X/X white Spirit creature token, where X is the mana value of the exiled card. + this.addAbility(new LeavesBattlefieldTriggeredAbility( + new CreateXXTokenExiledEffectManaValueEffect(SpiritXXToken::new, "white Spirit") + )); + } + + private SeverancePriest(final SeverancePriest card) { + super(card); + } + + @Override + public SeverancePriest copy() { + return new SeverancePriest(this); + } +} + +class SeverancePriestEffect extends OneShotEffect { + + SeverancePriestEffect() { + super(Outcome.Benefit); + staticText = "target opponent reveals their hand. You may choose " + + "a nonland card from it. If you do, exile that card"; + } + + private SeverancePriestEffect(final SeverancePriestEffect effect) { + super(effect); + } + + @Override + public SeverancePriestEffect copy() { + return new SeverancePriestEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Player opponent = game.getPlayer(getTargetPointer().getFirst(game, source)); + if (controller == null || opponent == null || opponent.getHand().isEmpty()) { + return false; + } + opponent.revealCards(source, opponent.getHand(), game); + TargetCard target = new TargetCardInHand(0, 1, StaticFilters.FILTER_CARD_NON_LAND); + controller.choose(Outcome.Discard, opponent.getHand(), target, source, game); + Card card = game.getCard(target.getFirstTarget()); + return card != null && controller.moveCardsToExile( + card, source, game, true, + CardUtil.getExileZoneId(game, source), + CardUtil.getSourceName(game, source) + ); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SkyclaveApparition.java b/Mage.Sets/src/mage/cards/s/SkyclaveApparition.java index a4997e653f1..5b17917216b 100644 --- a/Mage.Sets/src/mage/cards/s/SkyclaveApparition.java +++ b/Mage.Sets/src/mage/cards/s/SkyclaveApparition.java @@ -1,29 +1,24 @@ package mage.cards.s; import mage.MageInt; -import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.LeavesBattlefieldTriggeredAbility; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateXXTokenExiledEffectManaValueEffect; import mage.abilities.effects.common.ExileTargetForSourceEffect; 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.FilterPermanent; import mage.filter.common.FilterNonlandPermanent; import mage.filter.predicate.mageobject.ManaValuePredicate; import mage.filter.predicate.permanent.TokenPredicate; -import mage.game.ExileZone; -import mage.game.Game; -import mage.game.permanent.Permanent; import mage.game.permanent.token.CustomIllusionToken; import mage.target.TargetPermanent; -import mage.util.CardUtil; -import java.util.HashSet; -import java.util.Objects; -import java.util.Set; import java.util.UUID; /** @@ -55,7 +50,9 @@ public final class SkyclaveApparition extends CardImpl { this.addAbility(ability); // When Skyclave Apparition leaves the battlefield, the exiled card's owner creates an X/X blue Illusion creature token, where X is the converted mana cost of the exiled card. - this.addAbility(new LeavesBattlefieldTriggeredAbility(new SkyclaveApparitionEffect(), false)); + this.addAbility(new LeavesBattlefieldTriggeredAbility( + new CreateXXTokenExiledEffectManaValueEffect(CustomIllusionToken::new, "blue Illusion") + )); } private SkyclaveApparition(final SkyclaveApparition card) { @@ -67,50 +64,3 @@ public final class SkyclaveApparition extends CardImpl { return new SkyclaveApparition(this); } } - -class SkyclaveApparitionEffect extends OneShotEffect { - - SkyclaveApparitionEffect() { - super(Outcome.Benefit); - staticText = "the exiled card's owner creates an X/X blue Illusion creature token, " + - "where X is the mana value of the exiled card"; - } - - private SkyclaveApparitionEffect(final SkyclaveApparitionEffect effect) { - super(effect); - } - - @Override - public SkyclaveApparitionEffect copy() { - return new SkyclaveApparitionEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent permanentLeftBattlefield = (Permanent) getValue("permanentLeftBattlefield"); - ExileZone exile = game.getExile().getExileZone( - CardUtil.getExileZoneId(game, source.getSourceId(), permanentLeftBattlefield.getZoneChangeCounter(game)) - ); - if (exile == null || exile.isEmpty()) { - return false; - } - // From ZNR Release Notes: - // https://magic.wizards.com/en/articles/archive/feature/zendikar-rising-release-notes-2020-09-10 - // If Skyclave Apparition's first ability exiled more than one card owned by a single player, - // that player creates a token with power and toughness equal to the sum of those cards' converted mana costs. - // If the first ability exiled cards owned by more than one player, each of those players creates a token - // with power and toughness equal to the sum of the converted mana costs of all cards exiled by the first ability. - Set owners = new HashSet<>(); - int totalCMC = exile - .getCards(game) - .stream() - .filter(Objects::nonNull) - .map(card -> owners.add(card.getOwnerId()) ? card : card) - .mapToInt(MageObject::getManaValue) - .sum(); - for (UUID playerId : owners) { - new CustomIllusionToken(totalCMC).putOntoBattlefield(1, game, source, playerId); - } - return true; - } -} diff --git a/Mage.Sets/src/mage/sets/TarkirDragonstorm.java b/Mage.Sets/src/mage/sets/TarkirDragonstorm.java index fd5d4d498bc..28c91b3358f 100644 --- a/Mage.Sets/src/mage/sets/TarkirDragonstorm.java +++ b/Mage.Sets/src/mage/sets/TarkirDragonstorm.java @@ -1,8 +1,5 @@ package mage.sets; -import java.util.Arrays; -import java.util.List; - import mage.cards.ExpansionSet; import mage.constants.Rarity; import mage.constants.SetType; @@ -222,6 +219,7 @@ public final class TarkirDragonstorm extends ExpansionSet { cards.add(new SetCardInfo("Scavenger Regent", 90, Rarity.RARE, mage.cards.s.ScavengerRegent.class)); cards.add(new SetCardInfo("Scoured Barrens", 267, Rarity.COMMON, mage.cards.s.ScouredBarrens.class)); cards.add(new SetCardInfo("Seize Opportunity", 119, Rarity.COMMON, mage.cards.s.SeizeOpportunity.class)); + cards.add(new SetCardInfo("Severance Priest", 222, Rarity.RARE, mage.cards.s.SeverancePriest.class)); cards.add(new SetCardInfo("Shiko, Paragon of the Way", 223, Rarity.MYTHIC, mage.cards.s.ShikoParagonOfTheWay.class)); cards.add(new SetCardInfo("Shock Brigade", 120, Rarity.COMMON, mage.cards.s.ShockBrigade.class)); cards.add(new SetCardInfo("Shocking Sharpshooter", 121, Rarity.UNCOMMON, mage.cards.s.ShockingSharpshooter.class)); diff --git a/Mage/src/main/java/mage/abilities/effects/common/CreateXXTokenExiledEffectManaValueEffect.java b/Mage/src/main/java/mage/abilities/effects/common/CreateXXTokenExiledEffectManaValueEffect.java new file mode 100644 index 00000000000..3b58617a27c --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/CreateXXTokenExiledEffectManaValueEffect.java @@ -0,0 +1,74 @@ +package mage.abilities.effects.common; + +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.constants.Outcome; +import mage.game.ExileZone; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.game.permanent.token.Token; +import mage.util.CardUtil; + +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; +import java.util.UUID; +import java.util.function.Function; + +/** + * @author TheElk801 + */ +public class CreateXXTokenExiledEffectManaValueEffect extends OneShotEffect { + + private final Function tokenMaker; + + public CreateXXTokenExiledEffectManaValueEffect(Function tokenMaker, String description) { + super(Outcome.Benefit); + this.tokenMaker = tokenMaker; + staticText = "the exiled card's owner creates an X/X " + description + + "creature token, where X is the mana value of the exiled card"; + } + + private CreateXXTokenExiledEffectManaValueEffect(final CreateXXTokenExiledEffectManaValueEffect effect) { + super(effect); + this.tokenMaker = effect.tokenMaker; + } + + @Override + public CreateXXTokenExiledEffectManaValueEffect copy() { + return new CreateXXTokenExiledEffectManaValueEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanentLeftBattlefield = (Permanent) getValue("permanentLeftBattlefield"); + ExileZone exile = game.getExile().getExileZone( + CardUtil.getExileZoneId(game, source.getSourceId(), permanentLeftBattlefield.getZoneChangeCounter(game)) + ); + if (exile == null || exile.isEmpty()) { + return false; + } + // From ZNR Release Notes: + // https://magic.wizards.com/en/articles/archive/feature/zendikar-rising-release-notes-2020-09-10 + // If Skyclave Apparition's first ability exiled more than one card owned by a single player, + // that player creates a token with power and toughness equal to the sum of those cards' converted mana costs. + // If the first ability exiled cards owned by more than one player, each of those players creates a token + // with power and toughness equal to the sum of the converted mana costs of all cards exiled by the first ability. + Set owners = new HashSet<>(); + int totalCMC = exile + .getCards(game) + .stream() + .filter(Objects::nonNull) + .map(card -> { + owners.add(card.getOwnerId()); + return card; + }) + .mapToInt(MageObject::getManaValue) + .sum(); + for (UUID playerId : owners) { + tokenMaker.apply(totalCMC).putOntoBattlefield(1, game, source, playerId); + } + return true; + } +}