From 3ff34e2e95f8075115c4300fcebcc876954d43d9 Mon Sep 17 00:00:00 2001 From: fireshoes Date: Mon, 21 Mar 2016 19:11:00 -0500 Subject: [PATCH] [SOI] Implemented rare cycle of lands, Sin Prodder, Tireless Tracker, Ulvenwald Mysteries, and Call the Bloodline. --- .../src/mage/sets/ravnica/DarkConfidant.java | 2 +- .../CallTheBloodline.java | 65 +++++++++ .../shadowsoverinnistrad/ChokedEstuary.java | 78 +++++++++++ .../shadowsoverinnistrad/ForebodingRuins.java | 78 +++++++++++ .../FortifiedVillage.java | 78 +++++++++++ .../sets/shadowsoverinnistrad/GameTrail.java | 78 +++++++++++ .../sets/shadowsoverinnistrad/PortTown.java | 78 +++++++++++ .../sets/shadowsoverinnistrad/SinProdder.java | 130 ++++++++++++++++++ .../shadowsoverinnistrad/TirelessTracker.java | 107 ++++++++++++++ .../UlvenwaldMysteries.java | 112 +++++++++++++++ Utils/mtg-cards-data.txt | 4 +- 11 files changed, 807 insertions(+), 3 deletions(-) create mode 100644 Mage.Sets/src/mage/sets/shadowsoverinnistrad/CallTheBloodline.java create mode 100644 Mage.Sets/src/mage/sets/shadowsoverinnistrad/ChokedEstuary.java create mode 100644 Mage.Sets/src/mage/sets/shadowsoverinnistrad/ForebodingRuins.java create mode 100644 Mage.Sets/src/mage/sets/shadowsoverinnistrad/FortifiedVillage.java create mode 100644 Mage.Sets/src/mage/sets/shadowsoverinnistrad/GameTrail.java create mode 100644 Mage.Sets/src/mage/sets/shadowsoverinnistrad/PortTown.java create mode 100644 Mage.Sets/src/mage/sets/shadowsoverinnistrad/SinProdder.java create mode 100644 Mage.Sets/src/mage/sets/shadowsoverinnistrad/TirelessTracker.java create mode 100644 Mage.Sets/src/mage/sets/shadowsoverinnistrad/UlvenwaldMysteries.java diff --git a/Mage.Sets/src/mage/sets/ravnica/DarkConfidant.java b/Mage.Sets/src/mage/sets/ravnica/DarkConfidant.java index d5c22e87007..d854cd20cd3 100644 --- a/Mage.Sets/src/mage/sets/ravnica/DarkConfidant.java +++ b/Mage.Sets/src/mage/sets/ravnica/DarkConfidant.java @@ -95,7 +95,7 @@ class DarkConfidantEffect extends OneShotEffect { if (card != null) { Cards cards = new CardsImpl(card); controller.revealCards(sourcePermanent.getIdName(), cards, game); - controller.moveCards(card, null, Zone.HAND, source, game); + controller.moveCards(card, Zone.HAND, source, game); controller.loseLife(card.getManaCost().convertedManaCost(), game); } diff --git a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/CallTheBloodline.java b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/CallTheBloodline.java new file mode 100644 index 00000000000..d12da963564 --- /dev/null +++ b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/CallTheBloodline.java @@ -0,0 +1,65 @@ +/* + * 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.shadowsoverinnistrad; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.LimitedTimesPerTurnActivatedAbility; +import mage.abilities.costs.common.DiscardCardCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; + +/** + * + * @author fireshoes + */ +public class CallTheBloodline extends CardImpl { + + public CallTheBloodline(UUID ownerId) { + super(ownerId, 103, "Call the Bloodline", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT}, "{1}{B}"); + this.expansionSetCode = "SOI"; + + // {1}, Discard a card: Put a 1/1 black Vampire Knight token with lifelink onto the battlefield. Activate this ability only once each turn. + Ability ability = new LimitedTimesPerTurnActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new VampireKnightToken()), new GenericManaCost(1)); + ability.addCost(new DiscardCardCost()); + this.addAbility(ability); + } + + public CallTheBloodline(final CallTheBloodline card) { + super(card); + } + + @Override + public CallTheBloodline copy() { + return new CallTheBloodline(this); + } +} diff --git a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/ChokedEstuary.java b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/ChokedEstuary.java new file mode 100644 index 00000000000..2179c7b757d --- /dev/null +++ b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/ChokedEstuary.java @@ -0,0 +1,78 @@ +/* + * 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.shadowsoverinnistrad; + +import java.util.UUID; +import mage.abilities.common.AsEntersBattlefieldAbility; +import mage.abilities.costs.common.RevealTargetFromHandCost; +import mage.abilities.effects.common.TapSourceUnlessPaysEffect; +import mage.abilities.mana.BlackManaAbility; +import mage.abilities.mana.BlueManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.FilterCard; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.target.common.TargetCardInHand; + +/** + * + * @author fireshoes + */ +public class ChokedEstuary extends CardImpl { + + private static final FilterCard filter = new FilterCard("an Island or Swamp card from your hand"); + + static { + filter.add(Predicates.or(new SubtypePredicate("Island"), + new SubtypePredicate("Swamp"))); + } + + public ChokedEstuary(UUID ownerId) { + super(ownerId, 270, "Choked Estuary", Rarity.RARE, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "SOI"; + + // As Choked Estuary enters the battlefield, you may reveal an Island or Swamp card from your hand. If you don't, Choked Estuary enters the battlefield tapped. + this.addAbility(new AsEntersBattlefieldAbility(new TapSourceUnlessPaysEffect(new RevealTargetFromHandCost(new TargetCardInHand(filter))), + "you may reveal an Island or Swamp card from your hand. If you don't, {this} enters the battlefield tapped")); + + // {T}: Add {U} or {B} to your mana pool. + this.addAbility(new BlueManaAbility()); + this.addAbility(new BlackManaAbility()); + } + + public ChokedEstuary(final ChokedEstuary card) { + super(card); + } + + @Override + public ChokedEstuary copy() { + return new ChokedEstuary(this); + } +} diff --git a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/ForebodingRuins.java b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/ForebodingRuins.java new file mode 100644 index 00000000000..63a72bfec57 --- /dev/null +++ b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/ForebodingRuins.java @@ -0,0 +1,78 @@ +/* + * 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.shadowsoverinnistrad; + +import java.util.UUID; +import mage.abilities.common.AsEntersBattlefieldAbility; +import mage.abilities.costs.common.RevealTargetFromHandCost; +import mage.abilities.effects.common.TapSourceUnlessPaysEffect; +import mage.abilities.mana.BlackManaAbility; +import mage.abilities.mana.RedManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.FilterCard; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.target.common.TargetCardInHand; + +/** + * + * @author fireshoes + */ +public class ForebodingRuins extends CardImpl { + + private static final FilterCard filter = new FilterCard("a Swamp or Mountain card from your hand"); + + static { + filter.add(Predicates.or(new SubtypePredicate("Swamp"), + new SubtypePredicate("Mountain"))); + } + + public ForebodingRuins(UUID ownerId) { + super(ownerId, 272, "Foreboding Ruins", Rarity.RARE, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "SOI"; + + // As Foreboding Ruins enters the battlefield, you may reveal a Swamp or Mountain card from your hand. If you don't Foreboding Ruins enters the battlefield tapped. + this.addAbility(new AsEntersBattlefieldAbility(new TapSourceUnlessPaysEffect(new RevealTargetFromHandCost(new TargetCardInHand(filter))), + "you may reveal a Swamp or Mountain card from your hand. If you don't, {this} enters the battlefield tapped")); + + // {T}: Add {B} or {R} to your mana pool. + this.addAbility(new BlackManaAbility()); + this.addAbility(new RedManaAbility()); + } + + public ForebodingRuins(final ForebodingRuins card) { + super(card); + } + + @Override + public ForebodingRuins copy() { + return new ForebodingRuins(this); + } +} diff --git a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/FortifiedVillage.java b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/FortifiedVillage.java new file mode 100644 index 00000000000..f4b0b9de141 --- /dev/null +++ b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/FortifiedVillage.java @@ -0,0 +1,78 @@ +/* + * 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.shadowsoverinnistrad; + +import java.util.UUID; +import mage.abilities.common.AsEntersBattlefieldAbility; +import mage.abilities.costs.common.RevealTargetFromHandCost; +import mage.abilities.effects.common.TapSourceUnlessPaysEffect; +import mage.abilities.mana.GreenManaAbility; +import mage.abilities.mana.WhiteManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.FilterCard; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.target.common.TargetCardInHand; + +/** + * + * @author fireshoes + */ +public class FortifiedVillage extends CardImpl { + + private static final FilterCard filter = new FilterCard("a Forest or Plains card from your hand"); + + static { + filter.add(Predicates.or(new SubtypePredicate("Forest"), + new SubtypePredicate("Plains"))); + } + + public FortifiedVillage(UUID ownerId) { + super(ownerId, 274, "Fortified Village", Rarity.RARE, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "SOI"; + + // As Fortified Village enters the battlefield, you may reveal a Forest or Plains card from your hand. If you don't, Fortified Village enters the battlefield tapped. + this.addAbility(new AsEntersBattlefieldAbility(new TapSourceUnlessPaysEffect(new RevealTargetFromHandCost(new TargetCardInHand(filter))), + "you may reveal a Forest or Plains card from your hand. If you don't, {this} enters the battlefield tapped")); + + // {T}: Add {G} or {W} to your mana pool. + this.addAbility(new GreenManaAbility()); + this.addAbility(new WhiteManaAbility()); + } + + public FortifiedVillage(final FortifiedVillage card) { + super(card); + } + + @Override + public FortifiedVillage copy() { + return new FortifiedVillage(this); + } +} diff --git a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/GameTrail.java b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/GameTrail.java new file mode 100644 index 00000000000..33ce93e4cb5 --- /dev/null +++ b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/GameTrail.java @@ -0,0 +1,78 @@ +/* + * 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.shadowsoverinnistrad; + +import java.util.UUID; +import mage.abilities.common.AsEntersBattlefieldAbility; +import mage.abilities.costs.common.RevealTargetFromHandCost; +import mage.abilities.effects.common.TapSourceUnlessPaysEffect; +import mage.abilities.mana.GreenManaAbility; +import mage.abilities.mana.RedManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.FilterCard; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.target.common.TargetCardInHand; + +/** + * + * @author fireshoes + */ +public class GameTrail extends CardImpl { + + private static final FilterCard filter = new FilterCard("a Mountain or Forest card from your hand"); + + static { + filter.add(Predicates.or(new SubtypePredicate("Mountain"), + new SubtypePredicate("Forest"))); + } + + public GameTrail(UUID ownerId) { + super(ownerId, 276, "Game Trail", Rarity.RARE, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "SOI"; + + // As Game Trail enters the battlefield, you may reveal a Mountain or Forest card from your hand. If you don't, Game Trail enters the battlefield tapped. + this.addAbility(new AsEntersBattlefieldAbility(new TapSourceUnlessPaysEffect(new RevealTargetFromHandCost(new TargetCardInHand(filter))), + "you may reveal a Mountain or Forest card from your hand. If you don't, {this} enters the battlefield tapped")); + + // {T}: Add {R} or {G} to your mana pool. + this.addAbility(new RedManaAbility()); + this.addAbility(new GreenManaAbility()); + } + + public GameTrail(final GameTrail card) { + super(card); + } + + @Override + public GameTrail copy() { + return new GameTrail(this); + } +} diff --git a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/PortTown.java b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/PortTown.java new file mode 100644 index 00000000000..2808d02f731 --- /dev/null +++ b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/PortTown.java @@ -0,0 +1,78 @@ +/* + * 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.shadowsoverinnistrad; + +import java.util.UUID; +import mage.abilities.common.AsEntersBattlefieldAbility; +import mage.abilities.costs.common.RevealTargetFromHandCost; +import mage.abilities.effects.common.TapSourceUnlessPaysEffect; +import mage.abilities.mana.BlueManaAbility; +import mage.abilities.mana.WhiteManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.FilterCard; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.target.common.TargetCardInHand; + +/** + * + * @author fireshoes + */ +public class PortTown extends CardImpl { + + private static final FilterCard filter = new FilterCard("a Plains or Island card from your hand"); + + static { + filter.add(Predicates.or(new SubtypePredicate("Plains"), + new SubtypePredicate("Island"))); + } + + public PortTown(UUID ownerId) { + super(ownerId, 278, "Port Town", Rarity.RARE, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "SOI"; + + // As Port Town enters the battlefield, you may reveal a Plains or Island card from your hand. If you don't, Port Town enters the battlefield tapped. + this.addAbility(new AsEntersBattlefieldAbility(new TapSourceUnlessPaysEffect(new RevealTargetFromHandCost(new TargetCardInHand(filter))), + "you may reveal a Plains or Island card from your hand. If you don't, {this} enters the battlefield tapped")); + + // {T}: Add {W} or {U} to your mana pool. + this.addAbility(new WhiteManaAbility()); + this.addAbility(new BlueManaAbility()); + } + + public PortTown(final PortTown card) { + super(card); + } + + @Override + public PortTown copy() { + return new PortTown(this); + } +} diff --git a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/SinProdder.java b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/SinProdder.java new file mode 100644 index 00000000000..883466ef326 --- /dev/null +++ b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/SinProdder.java @@ -0,0 +1,130 @@ +/* + * 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.shadowsoverinnistrad; + +import java.util.Set; +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.MenaceAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.Cards; +import mage.cards.CardsImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; + +/** + * + * @author fireshoes + */ +public class SinProdder extends CardImpl { + + public SinProdder(UUID ownerId) { + super(ownerId, 181, "Sin Prodder", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{2}{R}"); + this.expansionSetCode = "SOI"; + this.subtype.add("Devil"); + this.power = new MageInt(3); + this.toughness = new MageInt(2); + + // Menace + this.addAbility(new MenaceAbility()); + + // At the beginning of your upkeep, reveal the top card of your library. Any opponent may have you put that card into your graveyard. If a player does, + // Sin Prodder deals damage to that player equal to that card's converted mana cost. Otherwise, put that card into your hand. + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new SinProdderEffect(), TargetController.YOU, false)); + } + + public SinProdder(final SinProdder card) { + super(card); + } + + @Override + public SinProdder copy() { + return new SinProdder(this); + } +} + +class SinProdderEffect extends OneShotEffect { + + public SinProdderEffect() { + super(Outcome.DrawCard); + this.staticText = "reveal the top card of your library. Any opponent may have you put that card into your graveyard. If a player does, " + + "{this} deals damage to that player equal to that card's converted mana cost. Otherwise, put that card into your hand"; + } + + public SinProdderEffect(final SinProdderEffect effect) { + super(effect); + } + + @Override + public SinProdderEffect copy() { + return new SinProdderEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); + if (controller != null && sourcePermanent != null) { + if (controller.getLibrary().size() > 0) { + Card card = controller.getLibrary().removeFromTop(game); + if (card != null) { + Cards cards = new CardsImpl(card); + controller.revealCards(sourcePermanent.getIdName(), cards, game); + StringBuilder sb = new StringBuilder(); + sb.append("Put ").append(card.getName()).append(" in ").append(controller.getLogName()).append("'s graveyard?"); + boolean putInGraveyard = false; + Set opponents = game.getOpponents(source.getControllerId()); + for (UUID opponentUuid : opponents) { + Player opponent = game.getPlayer(opponentUuid); + if (opponent != null && !putInGraveyard && opponent.chooseUse(Outcome.Damage, sb.toString(), source, game)) { + putInGraveyard = true; + opponent.damage(card.getManaCost().convertedManaCost(), source.getSourceId(), game, false, true); + } + } + if (putInGraveyard) { + controller.moveCards(card, Zone.GRAVEYARD, source, game); + } else { + controller.moveCards(card, Zone.HAND, source, game); + } + return true; + } + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/TirelessTracker.java b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/TirelessTracker.java new file mode 100644 index 00000000000..25abafc4316 --- /dev/null +++ b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/TirelessTracker.java @@ -0,0 +1,107 @@ +/* + * 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.shadowsoverinnistrad; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.effects.keyword.InvestigateEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.filter.common.FilterLandPermanent; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; + +/** + * + * @author fireshoes + */ +public class TirelessTracker extends CardImpl { + + public TirelessTracker(UUID ownerId) { + super(ownerId, 233, "Tireless Tracker", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{2}{G}"); + this.expansionSetCode = "SOI"; + this.subtype.add("Human"); + this.subtype.add("Scout"); + this.power = new MageInt(3); + this.toughness = new MageInt(2); + + // Whenever a land enters the battlefield under your control, investigate. (Put a colorless Clue artifact token onto the battlefield with "{2}, Sacrifice this artifact: Draw a card.") + this.addAbility(new EntersBattlefieldAllTriggeredAbility(Zone.BATTLEFIELD, new InvestigateEffect(), new FilterLandPermanent("a land"), false, null, true)); + + // Whenever you sacrifice a Clue, put a +1/+1 counter on Tireless Tracker. + this.addAbility(new TirelessTrackerTriggeredAbility()); + } + + public TirelessTracker(final TirelessTracker card) { + super(card); + } + + @Override + public TirelessTracker copy() { + return new TirelessTracker(this); + } +} + +class TirelessTrackerTriggeredAbility extends TriggeredAbilityImpl { + + public TirelessTrackerTriggeredAbility() { + super(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.P1P1.createInstance())); + } + + public TirelessTrackerTriggeredAbility(final TirelessTrackerTriggeredAbility ability) { + super(ability); + } + + @Override + public TirelessTrackerTriggeredAbility copy() { + return new TirelessTrackerTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == EventType.SACRIFICED_PERMANENT; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + return event.getPlayerId().equals(this.getControllerId()) + && game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD).getSubtype().contains("Clue"); + } + + @Override + public String getRule() { + return "When you sacrifice a Clue, " + super.getRule(); + } +} diff --git a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/UlvenwaldMysteries.java b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/UlvenwaldMysteries.java new file mode 100644 index 00000000000..4fa7ce87b0a --- /dev/null +++ b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/UlvenwaldMysteries.java @@ -0,0 +1,112 @@ +/* + * 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.shadowsoverinnistrad; + +import java.util.UUID; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.DiesCreatureTriggeredAbility; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.keyword.InvestigateEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.filter.predicate.permanent.TokenPredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; + +/** + * + * @author fireshoes + */ +public class UlvenwaldMysteries extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nontoken creature you control"); + + static { + filter.add(new ControllerPredicate(TargetController.YOU)); + filter.add(Predicates.not(new TokenPredicate())); + } + + public UlvenwaldMysteries(UUID ownerId) { + super(ownerId, 236, "Ulvenwald Mysteries", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}"); + this.expansionSetCode = "SOI"; + + // Whenever a nontoken creature you control dies, investigate. (Put a colorless Clue artifact token onto the battlefield with "{2}, Sacrifice this artifact: Draw a card.") + this.addAbility(new DiesCreatureTriggeredAbility(new InvestigateEffect(), false, filter)); + + // Whenever you sacrifice a Clue, put a 1/1 white Human Soldier creature token onto the battlefield. + this.addAbility(new UlvenwaldMysteriesTriggeredAbility()); + } + + public UlvenwaldMysteries(final UlvenwaldMysteries card) { + super(card); + } + + @Override + public UlvenwaldMysteries copy() { + return new UlvenwaldMysteries(this); + } +} + +class UlvenwaldMysteriesTriggeredAbility extends TriggeredAbilityImpl { + + public UlvenwaldMysteriesTriggeredAbility() { + super(Zone.BATTLEFIELD, new CreateTokenEffect(new HumanSoldierToken())); + } + + public UlvenwaldMysteriesTriggeredAbility(final UlvenwaldMysteriesTriggeredAbility ability) { + super(ability); + } + + @Override + public UlvenwaldMysteriesTriggeredAbility copy() { + return new UlvenwaldMysteriesTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == EventType.SACRIFICED_PERMANENT; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + return event.getPlayerId().equals(this.getControllerId()) + && game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD).getSubtype().contains("Clue"); + } + + @Override + public String getRule() { + return "When you sacrifice a Clue, " + super.getRule(); + } +} diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index 7c14ba4576c..b14767e2fb0 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -56988,7 +56988,7 @@ Trail of Evidence|Shadows over Innistrad|93|U|{2}{U}|Enchantment|||Whenever you Welcome to the Fold|Shadows over Innistrad|96|R|{2}{U}{U}|Sorcery|||Madness {X}{U}{U} (If you discard this card, discard it into exile. When you do, cast it for its madness cost or put it into your graveyard.$Gain control of target creature if its toughness is 2 or less. If Welcome to the Fold's madness cost was paid, instead gain control of that creature if its toughness is X or less.| Asylum Visitor|Shadows over Innistrad|99|R|{1}{B}|Creature - Vampire Wizard|3|1|At the beginning of each player's upkeep, if that player has no cards in hand, you draw a card and you lose 1 life.$Madness {1}{B} (If you discard this card, discard it into exile. When you do, cast it for its madness cost or put it into your graveyard.)| Behold the Beyond|Shadows over Innistrad|101|M|{5}{B}{B}|Sorcery|||Discard your hand. Search your library for three cards and put those cards into your hand. Then shuffle your library.| -Call the Bloodline|Shadows over Innistrad|103|U|{1}{B}|Enchantment|||{1}, Discard a card: Put a 1/1 black Vampire Knight token with lifelink onto the battlefield. Activate this ability only once per turn.| +Call the Bloodline|Shadows over Innistrad|103|U|{1}{B}|Enchantment|||{1}, Discard a card: Put a 1/1 black Vampire Knight token with lifelink onto the battlefield. Activate this ability only once each turn.| Crow of Dark Tidings|Shadows over Innistrad|105|C|{2}{B}|Creature - Zombie Bird|2|2|Flying$When Crow of Dark Tidings enters the battlefield or dies, put the top two cards of your library into your graveyard.| Dead Weight|Shadows over Innistrad|106|C|{B}|Enchantment - Aura|||Enchant creature$Enchanted creature gets -2/-2.| Diregraf Colossus|Shadows over Innistrad|107|R|{2}{B}|Creature - Zombie Giant|2|2|Diregraf Colossus enters the battlefield with a +1/+1 counter on it for each Zombie card in your graveyard.$Whenever you cast a Zombie spell, put a 2/2 black Zombie creature token onto the battlefield tapped.| @@ -57079,7 +57079,7 @@ Fortified Village|Shadows over Innistrad|274|R||Land|||As Fortified Village ente Foul Orchard|Shadows over Innistrad|275|U||Land|||Foul Orchard enters the battlefield tapped.${T}: Add {B} or {G} to your mana pool.| Game Trail|Shadows over Innistrad|276|R||Land|||As Game Trail enters the battlefield, you may reveal a Mountain or Forest card from your hand. If you don't, Game Trail enters the battlefield tapped.${T}: Add {R} or {G} to your mana pool.| Highland Lake|Shadows over Innistrad|277|U||Land|||Highland Lake enters the battlefield tapped.${T}: Add {U} or {R} to your mana pool.| -Port Town|Shadows over Innistrad|278|R||Land|||As Port Town enters the battlefield, you may reveal a Plains or Island from your hand. If you don't, Port Town enters the battlefield tapped.${T}: Add {W} or {U} to your mana pool.| +Port Town|Shadows over Innistrad|278|R||Land|||As Port Town enters the battlefield, you may reveal a Plains or Island card from your hand. If you don't, Port Town enters the battlefield tapped.${T}: Add {W} or {U} to your mana pool.| Stone Quarry|Shadows over Innistrad|279|U||Land|||Stone Quarry enters the battlefield tapped.${T}: Add {R} or {W} to your mana pool.| Woodland Stream|Shadows over Innistrad|282|U||Land|||Woodland Stream enters the battlefield tapped.${T}: Add {G} or {U} to your mana pool.| Warped Landscape|Shadows over Innistrad|280|C||Land|||{T}: Add {C} to your mana pool.${2}, {T}, Sacrifice Warped Landscape: Search your library for a basic land card and put it onto the battlefield tapped. Then shuffle your library.|