diff --git a/Mage.Sets/src/mage/sets/dragonsoftarkir/OjutaiExemplars.java b/Mage.Sets/src/mage/sets/dragonsoftarkir/OjutaiExemplars.java new file mode 100644 index 0000000000..a6f534e785 --- /dev/null +++ b/Mage.Sets/src/mage/sets/dragonsoftarkir/OjutaiExemplars.java @@ -0,0 +1,136 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.dragonsoftarkir; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.common.SpellCastControllerTriggeredAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.TapTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.abilities.keyword.LifelinkAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.FilterSpell; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author fireshoes + */ +public class OjutaiExemplars extends CardImpl { + + private static final FilterSpell filter = new FilterSpell("creature spell"); + + static { + filter.add(Predicates.not(new CardTypePredicate(CardType.CREATURE))); + } + + public OjutaiExemplars(UUID ownerId) { + super(ownerId, 27, "Ojutai Exemplars", Rarity.MYTHIC, new CardType[]{CardType.CREATURE}, "{2}{W}{W}"); + this.expansionSetCode = "DTK"; + this.subtype.add("Human"); + this.subtype.add("Monk"); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // Whenever you cast a noncreature spell, choose one - Tap target creature; + Ability ability = new SpellCastControllerTriggeredAbility(new TapTargetEffect(), filter, false); + ability.addTarget(new TargetCreaturePermanent()); + + // Ojutai Exemplars gain first strike and lifelink until end of turn; + Mode mode = new Mode(); + Effect effect = new GainAbilitySourceEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn); + effect.setText("{this} gains first strike"); + mode.getEffects().add(effect); + Effect effect2 = new GainAbilitySourceEffect(LifelinkAbility.getInstance(), Duration.EndOfTurn); + effect2.setText("and lifelink"); + mode.getEffects().add(effect2); + ability.addMode(mode); + + // or Exile Ojutai Exemplars, then return it to the battlefield tapped under its owner's control. + mode = new Mode(); + mode.getEffects().add(new OjutaiExemplarsEffect()); + ability.addMode(mode); + + this.addAbility(ability); + } + + public OjutaiExemplars(final OjutaiExemplars card) { + super(card); + } + + @Override + public OjutaiExemplars copy() { + return new OjutaiExemplars(this); + } +} + +class OjutaiExemplarsEffect extends OneShotEffect { + + public OjutaiExemplarsEffect() { + super(Outcome.Neutral); + this.staticText = "Exile {this}, then return it to the battlefield tapped under its owner's control"; + } + + public OjutaiExemplarsEffect(final OjutaiExemplarsEffect effect) { + super(effect); + } + + @Override + public OjutaiExemplarsEffect copy() { + return new OjutaiExemplarsEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent ojutaiExemplars = game.getPermanent(source.getSourceId()); + if (ojutaiExemplars != null) { + if (ojutaiExemplars.moveToExile(source.getSourceId(), "Ojutai Exemplars", source.getSourceId(), game)) { + Card card = game.getExile().getCard(source.getSourceId(), game); + if (card != null) { + return card.moveToZone(Zone.BATTLEFIELD, source.getSourceId(), game, true); + } + } + } + return false; + } +} \ No newline at end of file diff --git a/Mage/src/mage/target/common/TargetCreatureOrPlaneswalkerAmount.java b/Mage/src/mage/target/common/TargetCreatureOrPlaneswalkerAmount.java new file mode 100644 index 0000000000..e21c763d71 --- /dev/null +++ b/Mage/src/mage/target/common/TargetCreatureOrPlaneswalkerAmount.java @@ -0,0 +1,178 @@ + /* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + package mage.target.common; + + import java.util.HashSet; + import java.util.Set; + import java.util.UUID; + import mage.constants.Zone; + import mage.MageObject; + import mage.abilities.Ability; + import mage.abilities.dynamicvalue.DynamicValue; + import mage.abilities.dynamicvalue.common.StaticValue; + import mage.filter.Filter; + import mage.filter.common.FilterCreatureOrPlaneswalkerPermanent; + import mage.filter.common.FilterCreaturePermanent; + import mage.game.Game; + import mage.game.permanent.Permanent; + import mage.target.TargetAmount; + + /** + * + * @author BetaSteward_at_googlemail.com + */ + public class TargetCreatureOrPlaneswalkerAmount extends TargetAmount { + + protected FilterCreatureOrPlaneswalkerPermanent filter; + + public TargetCreatureOrPlaneswalkerAmount(int amount) { + // 107.1c If a rule or ability instructs a player to choose “any number,” that player may choose + // any positive number or zero, unless something (such as damage or counters) is being divided + // or distributed among “any number” of players and/or objects. In that case, a nonzero number + // of players and/or objects must be chosen if possible. + this(new StaticValue(amount)); + this.minNumberOfTargets = 1; + } + + public TargetCreatureOrPlaneswalkerAmount(DynamicValue amount) { + super(amount); + this.zone = Zone.ALL; + this.filter = new FilterCreatureOrPlaneswalkerPermanent(); + this.targetName = filter.getMessage(); + } + + public TargetCreatureOrPlaneswalkerAmount(final TargetCreatureOrPlaneswalkerAmount target) { + super(target); + this.filter = target.filter.copy(); + } + + @Override + public Filter getFilter() { + return this.filter; + } + + @Override + public boolean canTarget(UUID id, Game game) { + Permanent permanent = game.getPermanent(id); + if (permanent != null) { + return filter.match(permanent, game); + } + return false; + } + + @Override + public boolean canTarget(UUID id, Ability source, Game game) { + Permanent permanent = game.getPermanent(id); + if (source != null) { + MageObject targetSource = game.getObject(source.getSourceId()); + if (permanent != null) { + return permanent.canBeTargetedBy(targetSource, source.getControllerId(), game) && filter.match(permanent, source.getSourceId(), source.getControllerId(), game); + } + } + + if (permanent != null) { + return filter.match(permanent, game); + } + return false; + } + + @Override + public boolean canTarget(UUID playerId, UUID id, Ability source, Game game) { + return canTarget(id, source, game); + } + + @Override + public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) { + int count = 0; + MageObject targetSource = game.getObject(sourceId); + for (Permanent permanent : game.getBattlefield().getActivePermanents(new FilterCreaturePermanent(), sourceControllerId, game)) { + if (permanent.canBeTargetedBy(targetSource, sourceControllerId, game) && filter.match(permanent, sourceId, sourceControllerId, game)) { + count++; + if (count >= this.minNumberOfTargets) { + return true; + } + } + } + return false; + } + + @Override + public boolean canChoose(UUID sourceControllerId, Game game) { + int count = 0; + for (Permanent permanent : game.getBattlefield().getActivePermanents(new FilterCreaturePermanent(), sourceControllerId, game)) { + if (filter.match(permanent, null, sourceControllerId, game)) { + count++; + if (count >= this.minNumberOfTargets) { + return true; + } + } + } + return false; + } + + @Override + public Set<UUID> possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) { + Set<UUID> possibleTargets = new HashSet<>(); + MageObject targetSource = game.getObject(sourceId); + for (Permanent permanent : game.getBattlefield().getActivePermanents(new FilterCreaturePermanent(), sourceControllerId, game)) { + if (permanent.canBeTargetedBy(targetSource, sourceControllerId, game) && filter.match(permanent, sourceId, sourceControllerId, game)) { + possibleTargets.add(permanent.getId()); + } + } + return possibleTargets; + } + + @Override + public Set<UUID> possibleTargets(UUID sourceControllerId, Game game) { + Set<UUID> possibleTargets = new HashSet<>(); + for (Permanent permanent : game.getBattlefield().getActivePermanents(new FilterCreaturePermanent(), sourceControllerId, game)) { + if (filter.match(permanent, null, sourceControllerId, game)) { + possibleTargets.add(permanent.getId()); + } + } + return possibleTargets; + } + + @Override + public String getTargetedName(Game game) { + StringBuilder sb = new StringBuilder(); + for (UUID targetId : getTargets()) { + Permanent permanent = game.getPermanent(targetId); + if (permanent != null) { + sb.append(permanent.getLogName()).append("(").append(getTargetAmount(targetId)).append(") "); + } + } + return sb.toString(); + } + + @Override + public TargetCreatureOrPlaneswalkerAmount copy() { + return new TargetCreatureOrPlaneswalkerAmount(this); + } + + } diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index c8ce7577d1..a2b40b1f33 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -25746,6 +25746,7 @@ Savage Ventmaw|Dragons of Tarkir|231|U|{4}{R}{G}|Creature - Dragon|4|4|Flying$Wh Silumgar's Command|Dragons of Tarkir|232|R|{3}{U}{B}|Instant|||Choose two - Counter target noncreature spell; or Return target permanent to its owner's hand; or Target creature gets -3/-3 until end of turn; or Destroy target planeswalker.| Swift Warkite|Dragons of Tarkir|233|U|{4}{B}{R}|Creature - Dragon|4|4|Flying$When Swift Warkite enters the battlefield, you may put a creature card with converted mana cost 3 or less from your hand or graveyard onto the battlefield. That creature gains haste. Return it to your hand at the beginning of the next end step.| Evolving Wilds|Dragons of Tarkir|248|C||Land|||{T}, Sacrifice Evolving Wilds: Search your library for a basic land card and put it onto the battlefield tapped. Then shuffle your library.| +Haven of the Spirit Dragon|Dragons of Tarkir|249|R||Land|||{T}: Add {1} to your mana pool.${T}: add one mana of any color to your mana pool. Spend this mana only to cast a Dragon creature spell.${2}, {T}, Sacrifice Haven of the Spirit Dragon: Return target Dragon creature card or Ugin planeswalker card from your graveyard to your hand.| Emrakul, the Aeons Torn|Modern Masters 2015|3|M|{15}|Legendary Creature - Eldrazi|15|15|Emrakul, the Aeons Torn can't be countered.$When you cast Emrakul, take an extra turn after this one.$Flying, protection from colored spells, annihilator 6$When Emrakul is put into a graveyard from anywhere, its owner shuffles his or her graveyard into his or her library.| Karn Liberated|Modern Masters 2015|4|M|{7}|Planeswalker - Karn|||+4: Target player exiles a card from his or her hand.$-3: Exile target permanent.$-14: Restart the game, leaving in exile all non-Aura permanent cards exiled with Karn Liberated. Then put those cards onto the battlefield under your control.| Tarmogoyf|Modern Masters 2015|165|M|{1}{G}|Creature - Lhurgoyf|*|1+*|Tarmogoyf's power is equal to the number of card types among cards in all graveyards and its toughness is equal to that number plus 1. <i>(Artifact, creature, enchantment, instant, land, planeswalker, sorcery, and tribal are card types.)</i>|