diff --git a/Mage.Sets/src/mage/cards/h/HistoryOfBenalia.java b/Mage.Sets/src/mage/cards/h/HistoryOfBenalia.java new file mode 100644 index 00000000000..833b4783b84 --- /dev/null +++ b/Mage.Sets/src/mage/cards/h/HistoryOfBenalia.java @@ -0,0 +1,72 @@ +/* + * 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.cards.h; + +import java.util.UUID; +import mage.abilities.common.SagaAbility; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SagaChapter; +import mage.constants.SubType; +import mage.filter.common.FilterCreaturePermanent; +import mage.game.permanent.token.KnightToken; + +/** + * + * @author LevelX2 + */ +public class HistoryOfBenalia extends CardImpl { + + public HistoryOfBenalia(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}{W}"); + + this.subtype.add(SubType.SAGA); + + // (As this Saga enters and after your draw step, add a lore counter. Sacrifice after III.) + SagaAbility sagaAbility = new SagaAbility(this, SagaChapter.CHAPTER_III); + // I, II — Create a 2/2 white Knight creature token with vigilance. + sagaAbility.addChapterEffect(this, SagaChapter.CHAPTER_I, SagaChapter.CHAPTER_II, new CreateTokenEffect(new KnightToken())); + // III — Knights you control get +2/+1 until end of turn. + sagaAbility.addChapterEffect(this, SagaChapter.CHAPTER_III, + new BoostControlledEffect(2, 1, Duration.EndOfTurn, new FilterCreaturePermanent(SubType.KNIGHT, "Knights"))); + this.addAbility(sagaAbility); + } + + public HistoryOfBenalia(final HistoryOfBenalia card) { + super(card); + } + + @Override + public HistoryOfBenalia copy() { + return new HistoryOfBenalia(this); + } +} diff --git a/Mage.Sets/src/mage/cards/i/InOketrasName.java b/Mage.Sets/src/mage/cards/i/InOketrasName.java index eeb67bcc7b9..c5b5bdb0786 100644 --- a/Mage.Sets/src/mage/cards/i/InOketrasName.java +++ b/Mage.Sets/src/mage/cards/i/InOketrasName.java @@ -44,11 +44,9 @@ import mage.filter.predicate.mageobject.SubtypePredicate; */ public class InOketrasName extends CardImpl { - private static final FilterCreaturePermanent filterZombies = new FilterCreaturePermanent("Zombies"); private static final FilterCreaturePermanent filterNotZombies = new FilterCreaturePermanent("Other creatures"); static { - filterZombies.add(new SubtypePredicate(SubType.ZOMBIE)); filterNotZombies.add(Predicates.not(new SubtypePredicate(SubType.ZOMBIE))); } @@ -56,7 +54,7 @@ public class InOketrasName extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}"); // Zombies you control get +2/+1 until end of turn. Other creatures you control get +1/+1 until end of turn. - getSpellAbility().addEffect(new BoostControlledEffect(2, 1, Duration.EndOfTurn, filterZombies)); + getSpellAbility().addEffect(new BoostControlledEffect(2, 1, Duration.EndOfTurn, new FilterCreaturePermanent(SubType.ZOMBIE, "Zombies"))); getSpellAbility().addEffect(new BoostControlledEffect(1, 1, Duration.EndOfTurn, filterNotZombies)); } diff --git a/Mage.Sets/src/mage/cards/t/TheMirariConjecture.java b/Mage.Sets/src/mage/cards/t/TheMirariConjecture.java new file mode 100644 index 00000000000..c1fbcf8a47d --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TheMirariConjecture.java @@ -0,0 +1,128 @@ +/* + * 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.cards.t; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.DelayedTriggeredAbility; +import mage.abilities.common.SagaAbility; +import mage.abilities.effects.common.CopyTargetSpellEffect; +import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; +import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SagaChapter; +import mage.constants.SubType; +import mage.filter.FilterCard; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; +import mage.game.stack.Spell; +import mage.target.common.TargetCardInYourGraveyard; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author LevelX2 + */ +public class TheMirariConjecture extends CardImpl { + + public TheMirariConjecture(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{4}{U}"); + + this.subtype.add(SubType.SAGA); + + // (As this Saga enters and after your draw step, add a lore counter. Sacrifice after III.) + SagaAbility sagaAbility = new SagaAbility(this, SagaChapter.CHAPTER_III); + // I — Return target instant card from your graveyard to your hand. + FilterCard filterInstantCard = new FilterCard("instant card from your graveyard"); + filterInstantCard.add(new CardTypePredicate(CardType.INSTANT)); + Ability ability = sagaAbility.addChapterEffect(this, SagaChapter.CHAPTER_I, new ReturnFromGraveyardToHandTargetEffect()); + ability.addTarget(new TargetCardInYourGraveyard(filterInstantCard)); + // II — Return target sorcery card from your graveyard to your hand. + FilterCard filterSorceryCard = new FilterCard("sorcery card from your graveyard"); + filterSorceryCard.add(new CardTypePredicate(CardType.SORCERY)); + ability = sagaAbility.addChapterEffect(this, SagaChapter.CHAPTER_II, new ReturnFromGraveyardToHandTargetEffect()); + ability.addTarget(new TargetCardInYourGraveyard(filterSorceryCard)); + // III — Until end of turn, whenever you cast an instant or sorcery spell, copy it. You may choose new targets for the copy. + sagaAbility.addChapterEffect(this, SagaChapter.CHAPTER_III, new CreateDelayedTriggeredAbilityEffect(new TheMirariConjectureDelayedTriggeredAbility())); + this.addAbility(sagaAbility); + + } + + public TheMirariConjecture(final TheMirariConjecture card) { + super(card); + } + + @Override + public TheMirariConjecture copy() { + return new TheMirariConjecture(this); + } +} + +class TheMirariConjectureDelayedTriggeredAbility extends DelayedTriggeredAbility { + + public TheMirariConjectureDelayedTriggeredAbility() { + super(new CopyTargetSpellEffect(), Duration.EndOfTurn, false); + } + + public TheMirariConjectureDelayedTriggeredAbility(final TheMirariConjectureDelayedTriggeredAbility ability) { + super(ability); + } + + @Override + public TheMirariConjectureDelayedTriggeredAbility copy() { + return new TheMirariConjectureDelayedTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == EventType.SPELL_CAST; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getPlayerId().equals(this.getControllerId())) { + Spell spell = game.getStack().getSpell(event.getTargetId()); + if (spell != null + && (spell.isInstant() || spell.isSorcery())) { + this.getEffects().setTargetPointer(new FixedTarget(event.getTargetId())); + return true; + } + } + return false; + } + + @Override + public String getRule() { + return "Until end of turn, whenever you cast an instant or sorcery spell, copy it. You may choose new targets for the copy."; + } +} diff --git a/Mage.Sets/src/mage/cards/t/Topple.java b/Mage.Sets/src/mage/cards/t/Topple.java index 6b1a3ab0f53..a74351ad8f8 100644 --- a/Mage.Sets/src/mage/cards/t/Topple.java +++ b/Mage.Sets/src/mage/cards/t/Topple.java @@ -25,11 +25,10 @@ * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package mage.cards.t; -import java.util.List; import java.util.HashSet; +import java.util.List; import java.util.Set; import java.util.UUID; import mage.MageObject; @@ -49,15 +48,15 @@ import mage.target.TargetPermanent; */ public class Topple extends CardImpl { - public Topple (UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{2}{W}"); + public Topple(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{W}"); // Exile target creature with the greatest power among creatures on the battlefield. this.getSpellAbility().addEffect(new ExileTargetEffect()); this.getSpellAbility().addTarget(new ToppleTargetCreature()); } - public Topple (final Topple card) { + public Topple(final Topple card) { super(card); } @@ -83,7 +82,7 @@ class ToppleTargetCreature extends TargetPermanent { public boolean canTarget(UUID controllerId, UUID id, Ability source, Game game) { if (super.canTarget(controllerId, id, source, game)) { int maxPower = 0; - for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getId(), game)) { + for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) { if (permanent.getPower().getValue() > maxPower) { maxPower = permanent.getPower().getValue(); } diff --git a/Mage.Sets/src/mage/cards/t/TriumphOfGerrard.java b/Mage.Sets/src/mage/cards/t/TriumphOfGerrard.java new file mode 100644 index 00000000000..432f4806f4e --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TriumphOfGerrard.java @@ -0,0 +1,147 @@ +/* + * 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.cards.t; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.UUID; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.common.SagaAbility; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.LifelinkAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SagaChapter; +import mage.constants.SubType; +import mage.counters.CounterType; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.common.TargetControlledCreaturePermanent; + +/** + * + * @author LevelX2 + */ +public class TriumphOfGerrard extends CardImpl { + + public TriumphOfGerrard(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}"); + + this.subtype.add(SubType.SAGA); + + // (As this Saga enters and after your draw step, add a lore counter. Sacrifice after III.) + SagaAbility sagaAbility = new SagaAbility(this, SagaChapter.CHAPTER_III); + // I, II — Put a +1/+1 counter on target creature you control with the greatest power. + Ability ability = sagaAbility.addChapterEffect(this, SagaChapter.CHAPTER_I, SagaChapter.CHAPTER_II, new AddCountersTargetEffect(CounterType.P1P1.createInstance())); + ability.addTarget(new TriumphOfGerrardTargetCreature()); + // III — Target creature you control with the greatest power gains flying, first strike, and lifelink until end of turn. + ability = sagaAbility.addChapterEffect(this, SagaChapter.CHAPTER_III, + new GainAbilityTargetEffect(FlyingAbility.getInstance(), Duration.EndOfTurn).setText("Target creature you control with the greatest power gains flying")); + ability.addEffect(new GainAbilityTargetEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn).setText(", first strike")); + ability.addEffect(new GainAbilityTargetEffect(LifelinkAbility.getInstance(), Duration.EndOfTurn).setText(", and lifelink until end of turn")); + ability.addTarget(new TriumphOfGerrardTargetCreature()); + this.addAbility(sagaAbility); + + } + + public TriumphOfGerrard(final TriumphOfGerrard card) { + super(card); + } + + @Override + public TriumphOfGerrard copy() { + return new TriumphOfGerrard(this); + } +} + +class TriumphOfGerrardTargetCreature extends TargetControlledCreaturePermanent { + + public TriumphOfGerrardTargetCreature() { + super(); + setTargetName("creature you control with the greatest power"); + } + + public TriumphOfGerrardTargetCreature(final TriumphOfGerrardTargetCreature target) { + super(target); + } + + @Override + public boolean canTarget(UUID controllerId, UUID id, Ability source, Game game) { + if (super.canTarget(controllerId, id, source, game)) { + int maxPower = 0; + for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) { + if (permanent.getPower().getValue() > maxPower) { + maxPower = permanent.getPower().getValue(); + } + } + Permanent targetPermanent = game.getPermanent(id); + if (targetPermanent != null) { + return targetPermanent.getPower().getValue() == maxPower; + } + } + return false; + } + + @Override + public Set possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) { + int maxPower = 0; + List activePermanents = game.getBattlefield().getActivePermanents(filter, sourceControllerId, sourceId, game); + Set possibleTargets = new HashSet<>(); + MageObject targetSource = game.getObject(sourceId); + for (Permanent permanent : activePermanents) { + if (permanent.getPower().getValue() > maxPower) { + maxPower = permanent.getPower().getValue(); + } + } + for (Permanent permanent : activePermanents) { + if (!targets.containsKey(permanent.getId()) && permanent.canBeTargetedBy(targetSource, sourceControllerId, game)) { + if (permanent.getPower().getValue() == maxPower) { + possibleTargets.add(permanent.getId()); + } + } + } + return possibleTargets; + } + + @Override + public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) { + return !possibleTargets(sourceId, sourceControllerId, game).isEmpty(); + } + + @Override + public TriumphOfGerrardTargetCreature copy() { + return new TriumphOfGerrardTargetCreature(this); + } +} diff --git a/Mage.Sets/src/mage/sets/Dominaria.java b/Mage.Sets/src/mage/sets/Dominaria.java index fcafc9bd95a..87a6b85a466 100644 --- a/Mage.Sets/src/mage/sets/Dominaria.java +++ b/Mage.Sets/src/mage/sets/Dominaria.java @@ -97,6 +97,7 @@ public class Dominaria extends ExpansionSet { cards.add(new SetCardInfo("Guardians of Koilos", 216, Rarity.COMMON, mage.cards.g.GuardiansOfKoilos.class)); cards.add(new SetCardInfo("Helm of the Host", 217, Rarity.RARE, mage.cards.h.HelmOfTheHost.class)); cards.add(new SetCardInfo("Hinterland Harbor", 240, Rarity.RARE, mage.cards.h.HinterlandHarbor.class)); + cards.add(new SetCardInfo("History of Benalia", 21, Rarity.MYTHIC, mage.cards.h.HistoryOfBenalia.class)); cards.add(new SetCardInfo("Homarid Explorer", 53, Rarity.UNCOMMON, mage.cards.h.HomaridExplorer.class)); cards.add(new SetCardInfo("Howling Golem", 218, Rarity.UNCOMMON, mage.cards.h.HowlingGolem.class)); cards.add(new SetCardInfo("Icy Manipulator", 219, Rarity.UNCOMMON, mage.cards.i.IcyManipulator.class)); @@ -159,9 +160,11 @@ public class Dominaria extends ExpansionSet { cards.add(new SetCardInfo("Tatyova, Benthic Druid", 206, Rarity.UNCOMMON, mage.cards.t.TatyovaBenthicDruid.class)); cards.add(new SetCardInfo("Teshar, Ancestor's Apostle", 36, Rarity.RARE, mage.cards.t.TesharAncestorsApostle.class)); cards.add(new SetCardInfo("Tetsuko Umezawa, Fugitive", 69, Rarity.UNCOMMON, mage.cards.t.TetsukoUmezawaFugitive.class)); + cards.add(new SetCardInfo("The Mirari Conjecture", 57, Rarity.RARE, mage.cards.t.TheMirariConjecture.class)); cards.add(new SetCardInfo("Thorn Elemental", 185, Rarity.UNCOMMON, mage.cards.t.ThornElemental.class)); cards.add(new SetCardInfo("Timber Gorge", 279, Rarity.COMMON, mage.cards.t.TimberGorge.class)); cards.add(new SetCardInfo("Tragic Poet", 37, Rarity.COMMON, mage.cards.t.TragicPoet.class)); + cards.add(new SetCardInfo("Triumph of Gerrard", 38, Rarity.UNCOMMON, mage.cards.t.TriumphOfGerrard.class)); cards.add(new SetCardInfo("Untamed Kavu", 186, Rarity.UNCOMMON, mage.cards.u.UntamedKavu.class)); cards.add(new SetCardInfo("Unwind", 72, Rarity.COMMON, mage.cards.u.Unwind.class)); cards.add(new SetCardInfo("Urza's Ruinous Blast", 39, Rarity.RARE, mage.cards.u.UrzasRuinousBlast.class));