diff --git a/Mage.Sets/src/mage/cards/b/BonehoardDracosaur.java b/Mage.Sets/src/mage/cards/b/BonehoardDracosaur.java new file mode 100644 index 00000000000..5fc7268a220 --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BonehoardDracosaur.java @@ -0,0 +1,118 @@ +package mage.cards.b; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.game.ExileZone; +import mage.game.Game; +import mage.game.permanent.token.Dinosaur31Token; +import mage.game.permanent.token.TreasureToken; +import mage.players.Player; +import mage.target.targetpointer.FixedTargets; +import mage.util.CardUtil; + +import java.util.Set; +import java.util.UUID; + +/** + * @author Susucr + */ +public final class BonehoardDracosaur extends CardImpl { + + public BonehoardDracosaur(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}{R}"); + + this.subtype.add(SubType.DINOSAUR); + this.subtype.add(SubType.DRAGON); + this.power = new MageInt(5); + this.toughness = new MageInt(5); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // First strike + this.addAbility(FirstStrikeAbility.getInstance()); + + // At the beginning of your upkeep, exile the top two cards of your library. You may play them this turn. If you exiled a land card this way, create a 3/1 red Dinosaur creature token. If you exiled a nonland card this way, create a Treasure token. + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new BoneahoardDracosaurEffect(), TargetController.YOU, false)); + } + + private BonehoardDracosaur(final BonehoardDracosaur card) { + super(card); + } + + @Override + public BonehoardDracosaur copy() { + return new BonehoardDracosaur(this); + } +} + +class BoneahoardDracosaurEffect extends OneShotEffect { + + BoneahoardDracosaurEffect() { + super(Outcome.Benefit); + staticText = "exile the top two cards of your library. You may play them this turn. " + + "If you exiled a land card this way, create a 3/1 red Dinosaur creature token. " + + "If you exiled a nonland card this way, create a Treasure token."; + } + + private BoneahoardDracosaurEffect(final BoneahoardDracosaurEffect effect) { + super(effect); + } + + @Override + public BoneahoardDracosaurEffect copy() { + return new BoneahoardDracosaurEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } + + Set cards = controller.getLibrary().getTopCards(game, 2); + if (cards.isEmpty()) { + return true; + } + + UUID exileId = CardUtil.getExileZoneId("BonehoardDragon::" + source.getSourceId() + "::" + game.getTurn(), game); + String exileName = CardUtil.getSourceIdName(game, source) + " turn:" + game.getTurnNum(); + + controller.moveCardsToExile(cards, source, game, true, exileId, exileName); + ExileZone zone = game.getExile().getExileZone(exileId); + zone.setCleanupOnEndTurn(true); + + // remove cards that could not be moved to exile + cards.removeIf(card -> !Zone.EXILED.equals(game.getState().getZone(card.getId()))); + if (!cards.isEmpty()) { + game.addEffect(new PlayFromNotOwnHandZoneTargetEffect(Zone.EXILED, Duration.EndOfTurn) + .setTargetPointer(new FixedTargets(cards, game)), source); + } + + boolean exiledLand = cards.stream().anyMatch(c -> c.isLand(game)); + boolean exiledNonLand = cards.stream().anyMatch(c -> !c.isLand(game)); + + if (exiledLand) { + new CreateTokenEffect(new Dinosaur31Token()) + .apply(game, source); + } + if (exiledNonLand) { + new CreateTokenEffect(new TreasureToken()) + .apply(game, source); + } + + return true; + } + +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/TheLostCavernsOfIxalan.java b/Mage.Sets/src/mage/sets/TheLostCavernsOfIxalan.java index 5eba33b912e..6da47cf25bc 100644 --- a/Mage.Sets/src/mage/sets/TheLostCavernsOfIxalan.java +++ b/Mage.Sets/src/mage/sets/TheLostCavernsOfIxalan.java @@ -28,6 +28,7 @@ public final class TheLostCavernsOfIxalan extends ExpansionSet { cards.add(new SetCardInfo("Bedrock Tortoise", 176, Rarity.RARE, mage.cards.b.BedrockTortoise.class)); cards.add(new SetCardInfo("Bladewheel Chariot", 36, Rarity.UNCOMMON, mage.cards.b.BladewheelChariot.class)); cards.add(new SetCardInfo("Bloodletter of Aclazotz", 92, Rarity.MYTHIC, mage.cards.b.BloodletterOfAclazotz.class)); + cards.add(new SetCardInfo("Bonehoard Dracosaur", 134, Rarity.MYTHIC, mage.cards.b.BonehoardDracosaur.class)); cards.add(new SetCardInfo("Breeches, Eager Pillager", 137, Rarity.RARE, mage.cards.b.BreechesEagerPillager.class)); cards.add(new SetCardInfo("Broodrage Mycoid", 95, Rarity.COMMON, mage.cards.b.BroodrageMycoid.class)); cards.add(new SetCardInfo("Captain Storm, Cosmium Raider", 227, Rarity.UNCOMMON, mage.cards.c.CaptainStormCosmiumRaider.class)); diff --git a/Mage/src/main/java/mage/util/CardUtil.java b/Mage/src/main/java/mage/util/CardUtil.java index d5901f7feb4..56d634fdc4a 100644 --- a/Mage/src/main/java/mage/util/CardUtil.java +++ b/Mage/src/main/java/mage/util/CardUtil.java @@ -1016,8 +1016,9 @@ public final class CardUtil { /** * For finding the spell or ability on the stack for "becomes the target" triggers. + * * @param event the GameEvent.EventType.TARGETED from checkTrigger() or watch() - * @param game the Game from checkTrigger() or watch() + * @param game the Game from checkTrigger() or watch() * @return the StackObject which targeted the source, or null if not found */ public static StackObject getTargetingStackObject(GameEvent event, Game game) { @@ -1042,10 +1043,11 @@ public final class CardUtil { * For ensuring that spells/abilities that target the same object twice only trigger each "becomes the target" ability once. * If this is the first attempt at triggering for a given ability targeting a given object, * this method records that in the game state for later checks by this same method. + * * @param checkingReference must be unique for each usage (this.id.toString() of the TriggeredAbility, or this.getKey() of the watcher) - * @param targetingObject from getTargetingStackObject - * @param event the GameEvent.EventType.TARGETED from checkTrigger() or watch() - * @param game the Game from checkTrigger() or watch() + * @param targetingObject from getTargetingStackObject + * @param event the GameEvent.EventType.TARGETED from checkTrigger() or watch() + * @param game the Game from checkTrigger() or watch() * @return true if already triggered/watched, false if this is the first/only trigger/watch */ public static boolean checkTargetedEventAlreadyUsed(String checkingReference, StackObject targetingObject, GameEvent event, Game game) { @@ -1294,7 +1296,7 @@ public final class CardUtil { /** * Retrieves a list of all castable components from a given card based on certain conditions. - * + *

* Castable components are parts of a card that can be played or cast, * such as the adventure and main side of adventure spells or both sides of a fuse card. * @@ -1592,6 +1594,11 @@ public final class CardUtil { return sourceObject != null ? sourceObject.getName() : ""; } + public static String getSourceIdName(Game game, Ability source) { + MageObject sourceObject = source.getSourceObject(game); + return sourceObject != null ? sourceObject.getIdName() : ""; + } + /** * Generates source log name to insert into log messages *