diff --git a/Mage.Sets/src/mage/cards/p/PiaNalaarConsulOfRevival.java b/Mage.Sets/src/mage/cards/p/PiaNalaarConsulOfRevival.java index d1afbbf6bb9..d1d824a73c4 100644 --- a/Mage.Sets/src/mage/cards/p/PiaNalaarConsulOfRevival.java +++ b/Mage.Sets/src/mage/cards/p/PiaNalaarConsulOfRevival.java @@ -1,17 +1,18 @@ package mage.cards.p; import mage.MageInt; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.PlayLandOrCastSpellFromExileTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; import mage.abilities.keyword.HasteAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.SuperType; import mage.filter.FilterPermanent; -import mage.game.Game; -import mage.game.events.GameEvent; import mage.game.permanent.token.ThopterColorlessToken; import java.util.UUID; @@ -38,7 +39,7 @@ public final class PiaNalaarConsulOfRevival extends CardImpl { ))); // Whenever you play a land from exile or cast a spell from exile, create a 1/1 colorless Thopter artifact creature token with flying. - this.addAbility(new PiaNalaarConsulOfRevivalTriggeredAbility()); + this.addAbility(new PlayLandOrCastSpellFromExileTriggeredAbility(new CreateTokenEffect(new ThopterColorlessToken()))); } private PiaNalaarConsulOfRevival(final PiaNalaarConsulOfRevival card) { @@ -50,31 +51,3 @@ public final class PiaNalaarConsulOfRevival extends CardImpl { return new PiaNalaarConsulOfRevival(this); } } - -class PiaNalaarConsulOfRevivalTriggeredAbility extends TriggeredAbilityImpl { - - PiaNalaarConsulOfRevivalTriggeredAbility() { - super(Zone.BATTLEFIELD, new CreateTokenEffect(new ThopterColorlessToken())); - setTriggerPhrase("Whenever you play a land from exile or cast a spell from exile, "); - } - - private PiaNalaarConsulOfRevivalTriggeredAbility(final PiaNalaarConsulOfRevivalTriggeredAbility ability) { - super(ability); - } - - @Override - public PiaNalaarConsulOfRevivalTriggeredAbility copy() { - return new PiaNalaarConsulOfRevivalTriggeredAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.LAND_PLAYED - || event.getType() == GameEvent.EventType.SPELL_CAST; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - return isControlledBy(event.getPlayerId()) && event.getZone() == Zone.EXILED; - } -} diff --git a/Mage.Sets/src/mage/cards/u/UriangerAugurelt.java b/Mage.Sets/src/mage/cards/u/UriangerAugurelt.java new file mode 100644 index 00000000000..a72e0d4c91d --- /dev/null +++ b/Mage.Sets/src/mage/cards/u/UriangerAugurelt.java @@ -0,0 +1,155 @@ +package mage.cards.u; + +import mage.MageIdentifier; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.PlayLandOrCastSpellFromExileTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.AsThoughEffectImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.effects.common.asthought.MayLookAtTargetCardEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.game.Controllable; +import mage.game.Game; +import mage.players.Player; +import mage.target.targetpointer.FixedTarget; +import mage.util.CardUtil; + +import java.util.Optional; +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class UriangerAugurelt extends CardImpl { + + public UriangerAugurelt(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}{U}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.ELF); + this.subtype.add(SubType.ADVISOR); + this.power = new MageInt(1); + this.toughness = new MageInt(3); + + // Whenever you play a land from exile or cast a spell from exile, you gain 2 life. + this.addAbility(new PlayLandOrCastSpellFromExileTriggeredAbility(new GainLifeEffect(2))); + + // Draw Arcanum -- {T}: Look at the top card of your library. You may exile it face down. + this.addAbility(new SimpleActivatedAbility( + new UriangerAugureltExileEffect(), new TapSourceCost() + ).withFlavorWord("Draw Arcanum")); + + // Play Arcanum -- {T}: Until end of turn, you may play cards exiled with Urianger Augurelt. Spells you cast this way cost {2} less to cast. + this.addAbility(new SimpleActivatedAbility( + new UriangerAugureltPlayEffect(), new TapSourceCost() + ).setIdentifier(MageIdentifier.UriangerAugureltAlternateCast).withFlavorWord("Play Arcanum")); + } + + private UriangerAugurelt(final UriangerAugurelt card) { + super(card); + } + + @Override + public UriangerAugurelt copy() { + return new UriangerAugurelt(this); + } +} + +class UriangerAugureltExileEffect extends OneShotEffect { + + UriangerAugureltExileEffect() { + super(Outcome.Benefit); + staticText = "look at the top card of your library. You may exile it face down"; + } + + private UriangerAugureltExileEffect(final UriangerAugureltExileEffect effect) { + super(effect); + } + + @Override + public UriangerAugureltExileEffect copy() { + return new UriangerAugureltExileEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return false; + } + Card card = player.getLibrary().getFromTop(game); + if (card == null) { + return false; + } + player.lookAtCards("Top card of library", card, game); + if (!player.chooseUse(Outcome.DrawCard, "Exile " + card.getLogName() + " face down?", source, game)) { + return false; + } + player.moveCardsToExile( + card, source, game, false, + CardUtil.getExileZoneId(game, source), + CardUtil.getSourceName(game, source) + ); + card.setFaceDown(true, game); + game.addEffect(new MayLookAtTargetCardEffect(source.getControllerId()) + .setTargetPointer(new FixedTarget(card, game)), source); + return true; + } +} + +class UriangerAugureltPlayEffect extends AsThoughEffectImpl { + + UriangerAugureltPlayEffect() { + super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, + Duration.EndOfTurn, Outcome.AIDontUseIt); + staticText = "until end of turn, you may play cards exiled " + + "with {this}. Spells you cast this way cost {2} less to cast"; + } + + private UriangerAugureltPlayEffect(final UriangerAugureltPlayEffect effect) { + super(effect); + } + + @Override + public UriangerAugureltPlayEffect copy() { + return new UriangerAugureltPlayEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { + if (!source.isControlledBy(affectedControllerId)) { + return false; + } + Card card = game.getCard(objectId); + if (card == null || !Optional + .ofNullable(CardUtil.getExileZoneId(game, source)) + .map(game.getState().getExile()::getExileZone) + .filter(e -> e.contains(objectId)) + .isPresent()) { + return false; + } + if (card.isLand(game)) { + return true; + } + // TODO: This should ideally apply the reduction while the spell is being cast because effects that increase the cost apply first + Optional.ofNullable(source) + .map(Controllable::getControllerId) + .map(game::getPlayer) + .ifPresent(player -> player.setCastSourceIdWithAlternateMana( + card.getId(), CardUtil.reduceCost(card.getManaCost(), 2), + null, MageIdentifier.UriangerAugureltAlternateCast + )); + return true; + } +} diff --git a/Mage.Sets/src/mage/sets/FinalFantasyCommander.java b/Mage.Sets/src/mage/sets/FinalFantasyCommander.java index a626df8978b..cf475f0bf0d 100644 --- a/Mage.Sets/src/mage/sets/FinalFantasyCommander.java +++ b/Mage.Sets/src/mage/sets/FinalFantasyCommander.java @@ -431,6 +431,8 @@ public final class FinalFantasyCommander extends ExpansionSet { cards.add(new SetCardInfo("Umaro, Raging Yeti", 63, Rarity.RARE, mage.cards.u.UmaroRagingYeti.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Underground River", 439, Rarity.RARE, mage.cards.u.UndergroundRiver.class)); cards.add(new SetCardInfo("Unfinished Business", 259, Rarity.RARE, mage.cards.u.UnfinishedBusiness.class)); + cards.add(new SetCardInfo("Urianger Augurelt", 189, Rarity.RARE, mage.cards.u.UriangerAugurelt.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Urianger Augurelt", 96, Rarity.RARE, mage.cards.u.UriangerAugurelt.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Vandalblast", 298, Rarity.UNCOMMON, mage.cards.v.Vandalblast.class)); cards.add(new SetCardInfo("Vanquish the Horde", 260, Rarity.RARE, mage.cards.v.VanquishTheHorde.class)); cards.add(new SetCardInfo("Vincent, Vengeful Atoner", 157, Rarity.RARE, mage.cards.v.VincentVengefulAtoner.class, NON_FULL_USE_VARIOUS)); diff --git a/Mage/src/main/java/mage/MageIdentifier.java b/Mage/src/main/java/mage/MageIdentifier.java index 2916b50c3ec..a4fc6d9cc7a 100644 --- a/Mage/src/main/java/mage/MageIdentifier.java +++ b/Mage/src/main/java/mage/MageIdentifier.java @@ -83,6 +83,7 @@ public enum MageIdentifier { PrimalPrayersAlternateCast, QuilledGreatwurmAlternateCast, WickerfolkIndomitableAlternateCast, + UriangerAugureltAlternateCast, ValgavothTerrorEaterAlternateCast; /** diff --git a/Mage/src/main/java/mage/abilities/common/PlayLandOrCastSpellFromExileTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/PlayLandOrCastSpellFromExileTriggeredAbility.java new file mode 100644 index 00000000000..ff24dcc6cd6 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/common/PlayLandOrCastSpellFromExileTriggeredAbility.java @@ -0,0 +1,38 @@ +package mage.abilities.common; + +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.Effect; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; + +/** + * @author TheElk801 + */ +public class PlayLandOrCastSpellFromExileTriggeredAbility extends TriggeredAbilityImpl { + + public PlayLandOrCastSpellFromExileTriggeredAbility(Effect effect) { + super(Zone.BATTLEFIELD, effect); + setTriggerPhrase("Whenever you play a land from exile or cast a spell from exile, "); + } + + private PlayLandOrCastSpellFromExileTriggeredAbility(final PlayLandOrCastSpellFromExileTriggeredAbility ability) { + super(ability); + } + + @Override + public PlayLandOrCastSpellFromExileTriggeredAbility copy() { + return new PlayLandOrCastSpellFromExileTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.LAND_PLAYED + || event.getType() == GameEvent.EventType.SPELL_CAST; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + return isControlledBy(event.getPlayerId()) && event.getZone() == Zone.EXILED; + } +}