From cb99dbd330626eea9c37a9f367b6a7dea2aefa7a Mon Sep 17 00:00:00 2001 From: mkalender Date: Tue, 23 Jun 2015 13:56:31 -0400 Subject: [PATCH 001/105] set filter on restriction effect --- Mage.Sets/src/mage/sets/timeshifted/TeferisMoat.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Mage.Sets/src/mage/sets/timeshifted/TeferisMoat.java b/Mage.Sets/src/mage/sets/timeshifted/TeferisMoat.java index 4ae362d68d6..e614bae19e1 100644 --- a/Mage.Sets/src/mage/sets/timeshifted/TeferisMoat.java +++ b/Mage.Sets/src/mage/sets/timeshifted/TeferisMoat.java @@ -41,6 +41,9 @@ import mage.constants.Duration; import mage.constants.Outcome; import mage.constants.Rarity; import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.AbilityPredicate; import mage.game.Game; import mage.game.permanent.Permanent; @@ -73,6 +76,11 @@ public class TeferisMoat extends CardImpl { class TeferisMoatRestrictionEffect extends RestrictionEffect { + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Creatures without flying"); + static { + filter.add(Predicates.not(new AbilityPredicate(FlyingAbility.class))); + } + TeferisMoatRestrictionEffect(){ super(Duration.WhileOnBattlefield, Outcome.Benefit); staticText = "Creatures of the chosen color without flying can't attack you"; From 8357514142d72659344115642ed71f4ad98c1e26 Mon Sep 17 00:00:00 2001 From: mkalender Date: Tue, 23 Jun 2015 17:45:36 -0400 Subject: [PATCH 002/105] Revert "set filter on restriction effect" This reverts commit cb99dbd330626eea9c37a9f367b6a7dea2aefa7a. --- Mage.Sets/src/mage/sets/timeshifted/TeferisMoat.java | 8 -------- 1 file changed, 8 deletions(-) diff --git a/Mage.Sets/src/mage/sets/timeshifted/TeferisMoat.java b/Mage.Sets/src/mage/sets/timeshifted/TeferisMoat.java index e614bae19e1..4ae362d68d6 100644 --- a/Mage.Sets/src/mage/sets/timeshifted/TeferisMoat.java +++ b/Mage.Sets/src/mage/sets/timeshifted/TeferisMoat.java @@ -41,9 +41,6 @@ import mage.constants.Duration; import mage.constants.Outcome; import mage.constants.Rarity; import mage.constants.Zone; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.Predicates; -import mage.filter.predicate.mageobject.AbilityPredicate; import mage.game.Game; import mage.game.permanent.Permanent; @@ -76,11 +73,6 @@ public class TeferisMoat extends CardImpl { class TeferisMoatRestrictionEffect extends RestrictionEffect { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Creatures without flying"); - static { - filter.add(Predicates.not(new AbilityPredicate(FlyingAbility.class))); - } - TeferisMoatRestrictionEffect(){ super(Duration.WhileOnBattlefield, Outcome.Benefit); staticText = "Creatures of the chosen color without flying can't attack you"; From 0b60b3750619ff4e8a0896ac3f5e7929605b59d7 Mon Sep 17 00:00:00 2001 From: mkalender Date: Tue, 23 Jun 2015 17:46:14 -0400 Subject: [PATCH 003/105] new card Mwonvulia Acid Moss --- .../sets/timespiral/MwonvuliAcidMoss.java | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/timespiral/MwonvuliAcidMoss.java diff --git a/Mage.Sets/src/mage/sets/timespiral/MwonvuliAcidMoss.java b/Mage.Sets/src/mage/sets/timespiral/MwonvuliAcidMoss.java new file mode 100644 index 00000000000..a3902e1aa77 --- /dev/null +++ b/Mage.Sets/src/mage/sets/timespiral/MwonvuliAcidMoss.java @@ -0,0 +1,75 @@ +/* + * 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.timespiral; + +import java.util.UUID; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.FilterCard; +import mage.filter.FilterPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.target.TargetPermanent; +import mage.target.common.TargetCardInLibrary; + +/** + * + * @author anonymous + */ +public class MwonvuliAcidMoss extends CardImpl { + + public MwonvuliAcidMoss(UUID ownerId) { + super(ownerId, 207, "Mwonvuli Acid-Moss", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{2}{G}{G}"); + this.expansionSetCode = "TSP"; + + FilterPermanent filter = new FilterPermanent("land"); + filter.add(Predicates.and(new CardTypePredicate(CardType.LAND))); + + FilterCard filterForest = new FilterCard("a Forest card"); + filterForest.add(new SubtypePredicate("Forest")); + + // Destroy target land. Search your library for a Forest card and put that card onto the battlefield tapped. Then shuffle your library. + this.getSpellAbility().addEffect(new DestroyTargetEffect(true)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); + this.getSpellAbility().addEffect(new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(filterForest), false, true)); + } + + public MwonvuliAcidMoss(final MwonvuliAcidMoss card) { + super(card); + } + + @Override + public MwonvuliAcidMoss copy() { + return new MwonvuliAcidMoss(this); + } +} + From d231ace13075e240c8d2cb689508394905c0c65d Mon Sep 17 00:00:00 2001 From: mkalender Date: Tue, 23 Jun 2015 13:56:31 -0400 Subject: [PATCH 004/105] set filter on restriction effect --- Mage.Sets/src/mage/sets/timeshifted/TeferisMoat.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Mage.Sets/src/mage/sets/timeshifted/TeferisMoat.java b/Mage.Sets/src/mage/sets/timeshifted/TeferisMoat.java index e1edcb283c4..4fc0cf8e35c 100644 --- a/Mage.Sets/src/mage/sets/timeshifted/TeferisMoat.java +++ b/Mage.Sets/src/mage/sets/timeshifted/TeferisMoat.java @@ -41,6 +41,9 @@ import mage.constants.Duration; import mage.constants.Outcome; import mage.constants.Rarity; import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.AbilityPredicate; import mage.game.Game; import mage.game.permanent.Permanent; @@ -73,6 +76,11 @@ public class TeferisMoat extends CardImpl { class TeferisMoatRestrictionEffect extends RestrictionEffect { + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Creatures without flying"); + static { + filter.add(Predicates.not(new AbilityPredicate(FlyingAbility.class))); + } + TeferisMoatRestrictionEffect(){ super(Duration.WhileOnBattlefield, Outcome.Benefit); staticText = "Creatures of the chosen color without flying can't attack you"; @@ -100,4 +108,4 @@ class TeferisMoatRestrictionEffect extends RestrictionEffect { public TeferisMoatRestrictionEffect copy() { return new TeferisMoatRestrictionEffect(this); } -} \ No newline at end of file +} From 9bb10eb8c9c603a4fbce70262419f7be37805778 Mon Sep 17 00:00:00 2001 From: mkalender Date: Tue, 23 Jun 2015 17:45:36 -0400 Subject: [PATCH 005/105] Revert "set filter on restriction effect" This reverts commit cb99dbd330626eea9c37a9f367b6a7dea2aefa7a. --- Mage.Sets/src/mage/sets/timeshifted/TeferisMoat.java | 8 -------- 1 file changed, 8 deletions(-) diff --git a/Mage.Sets/src/mage/sets/timeshifted/TeferisMoat.java b/Mage.Sets/src/mage/sets/timeshifted/TeferisMoat.java index 4fc0cf8e35c..6348e83d0dd 100644 --- a/Mage.Sets/src/mage/sets/timeshifted/TeferisMoat.java +++ b/Mage.Sets/src/mage/sets/timeshifted/TeferisMoat.java @@ -41,9 +41,6 @@ import mage.constants.Duration; import mage.constants.Outcome; import mage.constants.Rarity; import mage.constants.Zone; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.Predicates; -import mage.filter.predicate.mageobject.AbilityPredicate; import mage.game.Game; import mage.game.permanent.Permanent; @@ -76,11 +73,6 @@ public class TeferisMoat extends CardImpl { class TeferisMoatRestrictionEffect extends RestrictionEffect { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Creatures without flying"); - static { - filter.add(Predicates.not(new AbilityPredicate(FlyingAbility.class))); - } - TeferisMoatRestrictionEffect(){ super(Duration.WhileOnBattlefield, Outcome.Benefit); staticText = "Creatures of the chosen color without flying can't attack you"; From 271957a1a179faf69bb9981021e8f5c562f44f68 Mon Sep 17 00:00:00 2001 From: mkalender Date: Tue, 23 Jun 2015 17:46:14 -0400 Subject: [PATCH 006/105] new card Mwonvulia Acid Moss --- .../sets/timespiral/MwonvuliAcidMoss.java | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/timespiral/MwonvuliAcidMoss.java diff --git a/Mage.Sets/src/mage/sets/timespiral/MwonvuliAcidMoss.java b/Mage.Sets/src/mage/sets/timespiral/MwonvuliAcidMoss.java new file mode 100644 index 00000000000..a3902e1aa77 --- /dev/null +++ b/Mage.Sets/src/mage/sets/timespiral/MwonvuliAcidMoss.java @@ -0,0 +1,75 @@ +/* + * 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.timespiral; + +import java.util.UUID; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.FilterCard; +import mage.filter.FilterPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.target.TargetPermanent; +import mage.target.common.TargetCardInLibrary; + +/** + * + * @author anonymous + */ +public class MwonvuliAcidMoss extends CardImpl { + + public MwonvuliAcidMoss(UUID ownerId) { + super(ownerId, 207, "Mwonvuli Acid-Moss", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{2}{G}{G}"); + this.expansionSetCode = "TSP"; + + FilterPermanent filter = new FilterPermanent("land"); + filter.add(Predicates.and(new CardTypePredicate(CardType.LAND))); + + FilterCard filterForest = new FilterCard("a Forest card"); + filterForest.add(new SubtypePredicate("Forest")); + + // Destroy target land. Search your library for a Forest card and put that card onto the battlefield tapped. Then shuffle your library. + this.getSpellAbility().addEffect(new DestroyTargetEffect(true)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); + this.getSpellAbility().addEffect(new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(filterForest), false, true)); + } + + public MwonvuliAcidMoss(final MwonvuliAcidMoss card) { + super(card); + } + + @Override + public MwonvuliAcidMoss copy() { + return new MwonvuliAcidMoss(this); + } +} + From 9294bac4c2e0ac5a991356461226637bde5e05e0 Mon Sep 17 00:00:00 2001 From: Mark Date: Wed, 24 Jun 2015 11:15:22 -0400 Subject: [PATCH 007/105] Harvest Wurm implementation --- .../mage/sets/weatherlight/HarvestWurm.java | 66 ++++++++++++++ .../common/ReturnToHandFromGraveyardCost.java | 86 +++++++++++++++++++ 2 files changed, 152 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/weatherlight/HarvestWurm.java create mode 100644 Mage/src/mage/abilities/costs/common/ReturnToHandFromGraveyardCost.java diff --git a/Mage.Sets/src/mage/sets/weatherlight/HarvestWurm.java b/Mage.Sets/src/mage/sets/weatherlight/HarvestWurm.java new file mode 100644 index 00000000000..7b2c3be0442 --- /dev/null +++ b/Mage.Sets/src/mage/sets/weatherlight/HarvestWurm.java @@ -0,0 +1,66 @@ +/* + * 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.weatherlight; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.costs.common.ReturnToHandFromGraveyardCost; +import mage.abilities.effects.common.SacrificeSourceUnlessPaysEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.common.FilterBasicLandCard; +import mage.target.common.TargetCardInYourGraveyard; + +/** + * + * @author anonymous + */ +public class HarvestWurm extends CardImpl { + + public HarvestWurm(UUID ownerId) { + super(ownerId, 72, "Harvest Wurm", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{1}{G}"); + this.expansionSetCode = "WTH"; + this.subtype.add("Wurm"); + this.power = new MageInt(3); + this.toughness = new MageInt(2); + + // When Harvest Wurm enters the battlefield, sacrifice it unless you return a basic land card from your graveyard to your hand. + this.addAbility(new EntersBattlefieldTriggeredAbility(new SacrificeSourceUnlessPaysEffect(new ReturnToHandFromGraveyardCost(new TargetCardInYourGraveyard(new FilterBasicLandCard()))))); + } + + public HarvestWurm(final HarvestWurm card) { + super(card); + } + + @Override + public HarvestWurm copy() { + return new HarvestWurm(this); + } +} diff --git a/Mage/src/mage/abilities/costs/common/ReturnToHandFromGraveyardCost.java b/Mage/src/mage/abilities/costs/common/ReturnToHandFromGraveyardCost.java new file mode 100644 index 00000000000..f73578adf39 --- /dev/null +++ b/Mage/src/mage/abilities/costs/common/ReturnToHandFromGraveyardCost.java @@ -0,0 +1,86 @@ +/* + * 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.abilities.costs.common; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.costs.CostImpl; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.game.Game; +import mage.players.Player; +import mage.target.TargetCard; +import mage.target.common.TargetCardInYourGraveyard; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class ReturnToHandFromGraveyardCost extends CostImpl { + + public ReturnToHandFromGraveyardCost(TargetCardInYourGraveyard target) { + this.addTarget(target); + if (target.getMaxNumberOfTargets() > 1 && target.getMaxNumberOfTargets() == target.getNumberOfTargets()) { + this.text = new StringBuilder("return ").append(target.getMaxNumberOfTargets()).append(" ").append(target.getTargetName()).append(" from graveyard to it's owner's hand").toString(); + } else { + this.text = new StringBuilder("return ").append(target.getTargetName()).append(" from graveyard to it's owner's hand").toString(); + } + } + public ReturnToHandFromGraveyardCost(ReturnToHandFromGraveyardCost cost) { + super(cost); + } + + @Override + public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) { + Player controller = game.getPlayer(controllerId); + if (controller != null) { + if (targets.choose(Outcome.ReturnToHand, controllerId, sourceId, game)) { + for (UUID targetId: targets.get(0).getTargets()) { + mage.cards.Card targetCard = game.getCard(targetId); + if (targetCard == null) { + return false; + } + paid |= controller.moveCardToHandWithInfo(targetCard, sourceId, game, Zone.HAND); + } + } + } + return paid; + } + + @Override + public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) { + return targets.canChoose(controllerId, game); + } + + @Override + public ReturnToHandFromGraveyardCost copy() { + return new ReturnToHandFromGraveyardCost(this); + } + +} From e35a7b2f364ddb1c9fc013f3631f03f4d2a7acb5 Mon Sep 17 00:00:00 2001 From: Mark Date: Thu, 25 Jun 2015 21:05:39 -0400 Subject: [PATCH 008/105] new cards Barbed Shocker ,Cabal Slaver, Shoker added new DiscardHandAndDrawEffect --- .../mage/sets/conspiracy/BarbedShocker.java | 70 +++++++++++++++ .../src/mage/sets/onslaught/CabalSlaver.java | 66 ++++++++++++++ Mage.Sets/src/mage/sets/tempest/Shocker.java | 64 +++++++++++++ .../mage/sets/timespiral/BarbedShocker.java | 52 +++++++++++ .../discard/DiscardHandAndDrawEffect.java | 89 +++++++++++++++++++ 5 files changed, 341 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/conspiracy/BarbedShocker.java create mode 100644 Mage.Sets/src/mage/sets/onslaught/CabalSlaver.java create mode 100644 Mage.Sets/src/mage/sets/tempest/Shocker.java create mode 100644 Mage.Sets/src/mage/sets/timespiral/BarbedShocker.java create mode 100644 Mage/src/mage/abilities/effects/common/discard/DiscardHandAndDrawEffect.java diff --git a/Mage.Sets/src/mage/sets/conspiracy/BarbedShocker.java b/Mage.Sets/src/mage/sets/conspiracy/BarbedShocker.java new file mode 100644 index 00000000000..bc47168738b --- /dev/null +++ b/Mage.Sets/src/mage/sets/conspiracy/BarbedShocker.java @@ -0,0 +1,70 @@ +/* + * 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.conspiracy; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.DealsDamageToAPlayerTriggeredAbility; +import mage.abilities.effects.common.discard.DiscardHandAndDrawEffect; +import mage.abilities.keyword.TrampleAbility; +import mage.abilities.keyword.HasteAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.TargetController; + +/** + * + * @author anonymous + */ +public class BarbedShocker extends CardImpl { + + public BarbedShocker(UUID ownerId) { + super(ownerId, 136, "Barbed Shocker", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{3}{R}"); + this.expansionSetCode = "CNS"; + this.subtype.add("Insect"); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Trample + this.addAbility(TrampleAbility.getInstance()); + // Haste + this.addAbility(HasteAbility.getInstance()); + // Whenever Barbed Shocker deals damage to a player, that player discards all the cards in his or her hand, then draws that many cards. + this.addAbility(new DealsDamageToAPlayerTriggeredAbility(new DiscardHandAndDrawEffect(TargetController.OPPONENT), false, true)); + } + + public BarbedShocker(final BarbedShocker card) { + super(card); + } + + @Override + public BarbedShocker copy() { + return new BarbedShocker(this); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/onslaught/CabalSlaver.java b/Mage.Sets/src/mage/sets/onslaught/CabalSlaver.java new file mode 100644 index 00000000000..9b3ee5a8b82 --- /dev/null +++ b/Mage.Sets/src/mage/sets/onslaught/CabalSlaver.java @@ -0,0 +1,66 @@ +/* + * 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.onslaught; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.DealsDamageToAPlayerTriggeredAbility; +import mage.abilities.effects.common.discard.DiscardHandAndDrawEffect; +import mage.abilities.effects.common.discard.DiscardTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.TargetController; + +/** + * + * @author anonymous + */ +public class CabalSlaver extends CardImpl { + + public CabalSlaver(UUID ownerId) { + super(ownerId, 131, "Cabal Slaver", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{2}{B}"); + this.expansionSetCode = "ONS"; + this.subtype.add("Human"); + this.subtype.add("Cleric"); + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + // Whenever a Goblin deals combat damage to a player, that player discards a card. + this.addAbility(new DealsDamageToAPlayerTriggeredAbility(new DiscardTargetEffect(1), false, true)); + } + + public CabalSlaver(final CabalSlaver card) { + super(card); + } + + @Override + public CabalSlaver copy() { + return new CabalSlaver(this); + } +} diff --git a/Mage.Sets/src/mage/sets/tempest/Shocker.java b/Mage.Sets/src/mage/sets/tempest/Shocker.java new file mode 100644 index 00000000000..fe32c73bab3 --- /dev/null +++ b/Mage.Sets/src/mage/sets/tempest/Shocker.java @@ -0,0 +1,64 @@ +/* + * 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.tempest; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.DealsDamageToAPlayerTriggeredAbility; +import mage.abilities.effects.common.discard.DiscardHandAndDrawEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.TargetController; + +/** + * + * @author anonymous + */ +public class Shocker extends CardImpl { + + public Shocker(UUID ownerId) { + super(ownerId, 204, "Shocker", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{1}{R}"); + this.expansionSetCode = "TMP"; + this.subtype.add("Insect"); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Whenever Shocker deals damage to a player, that player discards all the cards in his or her hand, then draws that many cards. + this.addAbility(new DealsDamageToAPlayerTriggeredAbility(new DiscardHandAndDrawEffect(TargetController.OPPONENT), false, true)); + } + + public Shocker(final Shocker card) { + super(card); + } + + @Override + public Shocker copy() { + return new Shocker(this); + } +} diff --git a/Mage.Sets/src/mage/sets/timespiral/BarbedShocker.java b/Mage.Sets/src/mage/sets/timespiral/BarbedShocker.java new file mode 100644 index 00000000000..fe57ec4b632 --- /dev/null +++ b/Mage.Sets/src/mage/sets/timespiral/BarbedShocker.java @@ -0,0 +1,52 @@ +/* + * 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.timespiral; + +import java.util.UUID; + +/** + * + * @author anonymous + */ +public class BarbedShocker extends mage.sets.conspiracy.BarbedShocker { + + public BarbedShocker(UUID ownerId) { + super(ownerId); + this.cardNumber = 144; + this.expansionSetCode = "TSP"; + } + + public BarbedShocker(final BarbedShocker card) { + super(card); + } + + @Override + public BarbedShocker copy() { + return new BarbedShocker(this); + } +} diff --git a/Mage/src/mage/abilities/effects/common/discard/DiscardHandAndDrawEffect.java b/Mage/src/mage/abilities/effects/common/discard/DiscardHandAndDrawEffect.java new file mode 100644 index 00000000000..322d613dcc7 --- /dev/null +++ b/Mage/src/mage/abilities/effects/common/discard/DiscardHandAndDrawEffect.java @@ -0,0 +1,89 @@ +/* + * 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.abilities.effects.common.discard; + +import java.util.Set; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.cards.Card; +import mage.constants.Outcome; +import mage.constants.TargetController; +import mage.game.Game; +import mage.players.Player; + +/** + * @author mluds + */ +public class DiscardHandAndDrawEffect extends OneShotEffect { + + private int CardDrawOffset = 0; + public DiscardHandAndDrawEffect(TargetController targetController) { + this(targetController,0); + } + public DiscardHandAndDrawEffect(TargetController targetController, int cardDrawOffset) { + super(Outcome.Discard); + String PostText = ""; + if (cardDrawOffset >0){ + PostText = " plus " + cardDrawOffset; + }else if(cardDrawOffset < 0){ + PostText = " minus " + cardDrawOffset; + } + this.CardDrawOffset = cardDrawOffset; + switch(targetController) { + case OPPONENT: + this.staticText = "Opponent discards his hand then draws that many cards" + PostText; + break; + case YOU: + this.staticText = "Discard your hand then draws that many cards" + PostText; + break; + } + } + + public DiscardHandAndDrawEffect(final DiscardHandAndDrawEffect effect) { + super(effect); + } + + @Override + public DiscardHandAndDrawEffect copy() { + return new DiscardHandAndDrawEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(targetPointer.getFirst(game, source)); + if (player != null) { + Set cards = player.getHand().getCards(game); + int count = cards.size(); + for (Card card : cards) { + player.discard(card, source, game); + } + player.drawCards(count + this.CardDrawOffset, game); + } + return true; + } +} From f3f48496381199283d1752d3b3cc5f42fd14c8c7 Mon Sep 17 00:00:00 2001 From: Mark Date: Thu, 2 Jul 2015 15:14:45 -0400 Subject: [PATCH 009/105] fixed Barbed Shocker ,Cabal Slaver, Shoker removed DiscardHandAndDrawEffect added author name --- .../mage/sets/conspiracy/BarbedShocker.java | 42 ++++++++- .../src/mage/sets/onslaught/CabalSlaver.java | 16 ++-- Mage.Sets/src/mage/sets/tempest/Shocker.java | 41 ++++++++- .../mage/sets/timespiral/BarbedShocker.java | 2 +- .../sets/timespiral/MwonvuliAcidMoss.java | 16 ++-- .../mage/sets/weatherlight/HarvestWurm.java | 2 +- .../common/ReturnToHandFromGraveyardCost.java | 2 +- .../discard/DiscardHandAndDrawEffect.java | 89 ------------------- 8 files changed, 97 insertions(+), 113 deletions(-) delete mode 100644 Mage/src/mage/abilities/effects/common/discard/DiscardHandAndDrawEffect.java diff --git a/Mage.Sets/src/mage/sets/conspiracy/BarbedShocker.java b/Mage.Sets/src/mage/sets/conspiracy/BarbedShocker.java index bc47168738b..0fb985c6562 100644 --- a/Mage.Sets/src/mage/sets/conspiracy/BarbedShocker.java +++ b/Mage.Sets/src/mage/sets/conspiracy/BarbedShocker.java @@ -27,20 +27,26 @@ */ package mage.sets.conspiracy; +import java.util.Set; import java.util.UUID; import mage.MageInt; +import mage.abilities.Ability; import mage.abilities.common.DealsDamageToAPlayerTriggeredAbility; -import mage.abilities.effects.common.discard.DiscardHandAndDrawEffect; +import mage.abilities.effects.OneShotEffect; import mage.abilities.keyword.TrampleAbility; import mage.abilities.keyword.HasteAbility; +import mage.cards.Card; import mage.cards.CardImpl; import mage.constants.CardType; +import mage.constants.Outcome; import mage.constants.Rarity; import mage.constants.TargetController; +import mage.game.Game; +import mage.players.Player; /** * - * @author anonymous + * @author markedagain */ public class BarbedShocker extends CardImpl { @@ -56,7 +62,7 @@ public class BarbedShocker extends CardImpl { // Haste this.addAbility(HasteAbility.getInstance()); // Whenever Barbed Shocker deals damage to a player, that player discards all the cards in his or her hand, then draws that many cards. - this.addAbility(new DealsDamageToAPlayerTriggeredAbility(new DiscardHandAndDrawEffect(TargetController.OPPONENT), false, true)); + this.addAbility(new DealsDamageToAPlayerTriggeredAbility(new BarbedShockerEffect(), false, true)); } public BarbedShocker(final BarbedShocker card) { @@ -67,4 +73,34 @@ public class BarbedShocker extends CardImpl { public BarbedShocker copy() { return new BarbedShocker(this); } +} +class BarbedShockerEffect extends OneShotEffect { + + public BarbedShockerEffect() { + super(Outcome.Discard); + this.staticText = " that player discards all the cards in his or her hand, then draws that many cards"; + } + + public BarbedShockerEffect(final BarbedShockerEffect effect) { + super(effect); + } + + @Override + public BarbedShockerEffect copy() { + return new BarbedShockerEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player targetPlayer = game.getPlayer(targetPointer.getFirst(game, source)); + if (targetPlayer != null) { + int count = targetPlayer.getHand().size(); + for (Card card : targetPlayer.getHand().getCards(game)) { + targetPlayer.discard(card, source, game); + } + targetPlayer.drawCards(count, game); + return false; + } + return true; + } } \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/onslaught/CabalSlaver.java b/Mage.Sets/src/mage/sets/onslaught/CabalSlaver.java index 9b3ee5a8b82..ac9da8f9eae 100644 --- a/Mage.Sets/src/mage/sets/onslaught/CabalSlaver.java +++ b/Mage.Sets/src/mage/sets/onslaught/CabalSlaver.java @@ -29,19 +29,25 @@ package mage.sets.onslaught; import java.util.UUID; import mage.MageInt; -import mage.abilities.common.DealsDamageToAPlayerTriggeredAbility; -import mage.abilities.effects.common.discard.DiscardHandAndDrawEffect; +import mage.abilities.common.DealsDamageToAPlayerAllTriggeredAbility; import mage.abilities.effects.common.discard.DiscardTargetEffect; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Rarity; -import mage.constants.TargetController; +import mage.constants.SetTargetPointer; +import mage.filter.FilterPermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; /** * - * @author anonymous + * @author markedagain */ public class CabalSlaver extends CardImpl { + private static final FilterPermanent filter = new FilterPermanent("Goblin"); + + static { + filter.add(new SubtypePredicate("Goblin")); + } public CabalSlaver(UUID ownerId) { super(ownerId, 131, "Cabal Slaver", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{2}{B}"); @@ -52,7 +58,7 @@ public class CabalSlaver extends CardImpl { this.toughness = new MageInt(1); // Whenever a Goblin deals combat damage to a player, that player discards a card. - this.addAbility(new DealsDamageToAPlayerTriggeredAbility(new DiscardTargetEffect(1), false, true)); + this.addAbility(new DealsDamageToAPlayerAllTriggeredAbility(new DiscardTargetEffect(1),filter, false, SetTargetPointer.NONE, true)); } public CabalSlaver(final CabalSlaver card) { diff --git a/Mage.Sets/src/mage/sets/tempest/Shocker.java b/Mage.Sets/src/mage/sets/tempest/Shocker.java index fe32c73bab3..4ed38a71f35 100644 --- a/Mage.Sets/src/mage/sets/tempest/Shocker.java +++ b/Mage.Sets/src/mage/sets/tempest/Shocker.java @@ -29,16 +29,21 @@ package mage.sets.tempest; import java.util.UUID; import mage.MageInt; +import mage.abilities.Ability; import mage.abilities.common.DealsDamageToAPlayerTriggeredAbility; -import mage.abilities.effects.common.discard.DiscardHandAndDrawEffect; +import mage.abilities.effects.OneShotEffect; +import mage.cards.Card; import mage.cards.CardImpl; import mage.constants.CardType; +import mage.constants.Outcome; import mage.constants.Rarity; import mage.constants.TargetController; +import mage.game.Game; +import mage.players.Player; /** * - * @author anonymous + * @author markedagain */ public class Shocker extends CardImpl { @@ -50,7 +55,7 @@ public class Shocker extends CardImpl { this.toughness = new MageInt(1); // Whenever Shocker deals damage to a player, that player discards all the cards in his or her hand, then draws that many cards. - this.addAbility(new DealsDamageToAPlayerTriggeredAbility(new DiscardHandAndDrawEffect(TargetController.OPPONENT), false, true)); + this.addAbility(new DealsDamageToAPlayerTriggeredAbility(new ShockerEffect(), false, true)); } public Shocker(final Shocker card) { @@ -62,3 +67,33 @@ public class Shocker extends CardImpl { return new Shocker(this); } } +class ShockerEffect extends OneShotEffect { + + public ShockerEffect() { + super(Outcome.Discard); + this.staticText = " that player discards all the cards in his or her hand, then draws that many cards"; + } + + public ShockerEffect(final ShockerEffect effect) { + super(effect); + } + + @Override + public ShockerEffect copy() { + return new ShockerEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player targetPlayer = game.getPlayer(targetPointer.getFirst(game, source)); + if (targetPlayer != null) { + int count = targetPlayer.getHand().size(); + for (Card card : targetPlayer.getHand().getCards(game)) { + targetPlayer.discard(card, source, game); + } + targetPlayer.drawCards(count, game); + return false; + } + return true; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/timespiral/BarbedShocker.java b/Mage.Sets/src/mage/sets/timespiral/BarbedShocker.java index fe57ec4b632..28587af3873 100644 --- a/Mage.Sets/src/mage/sets/timespiral/BarbedShocker.java +++ b/Mage.Sets/src/mage/sets/timespiral/BarbedShocker.java @@ -31,7 +31,7 @@ import java.util.UUID; /** * - * @author anonymous + * @author markedagain */ public class BarbedShocker extends mage.sets.conspiracy.BarbedShocker { diff --git a/Mage.Sets/src/mage/sets/timespiral/MwonvuliAcidMoss.java b/Mage.Sets/src/mage/sets/timespiral/MwonvuliAcidMoss.java index a3902e1aa77..7bb54c0dd5b 100644 --- a/Mage.Sets/src/mage/sets/timespiral/MwonvuliAcidMoss.java +++ b/Mage.Sets/src/mage/sets/timespiral/MwonvuliAcidMoss.java @@ -33,33 +33,29 @@ import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Rarity; -import mage.filter.FilterCard; -import mage.filter.FilterPermanent; -import mage.filter.predicate.Predicates; -import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.common.FilterBasicLandCard; +import mage.filter.common.FilterLandCard; +import mage.filter.common.FilterLandPermanent; import mage.filter.predicate.mageobject.SubtypePredicate; import mage.target.TargetPermanent; import mage.target.common.TargetCardInLibrary; /** * - * @author anonymous + * @author markedagain */ public class MwonvuliAcidMoss extends CardImpl { public MwonvuliAcidMoss(UUID ownerId) { super(ownerId, 207, "Mwonvuli Acid-Moss", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{2}{G}{G}"); this.expansionSetCode = "TSP"; - - FilterPermanent filter = new FilterPermanent("land"); - filter.add(Predicates.and(new CardTypePredicate(CardType.LAND))); - FilterCard filterForest = new FilterCard("a Forest card"); + FilterLandCard filterForest = new FilterLandCard(); filterForest.add(new SubtypePredicate("Forest")); // Destroy target land. Search your library for a Forest card and put that card onto the battlefield tapped. Then shuffle your library. this.getSpellAbility().addEffect(new DestroyTargetEffect(true)); - this.getSpellAbility().addTarget(new TargetPermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(new FilterLandPermanent())); this.getSpellAbility().addEffect(new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(filterForest), false, true)); } diff --git a/Mage.Sets/src/mage/sets/weatherlight/HarvestWurm.java b/Mage.Sets/src/mage/sets/weatherlight/HarvestWurm.java index 7b2c3be0442..075ebcb48e0 100644 --- a/Mage.Sets/src/mage/sets/weatherlight/HarvestWurm.java +++ b/Mage.Sets/src/mage/sets/weatherlight/HarvestWurm.java @@ -40,7 +40,7 @@ import mage.target.common.TargetCardInYourGraveyard; /** * - * @author anonymous + * @author markedagain */ public class HarvestWurm extends CardImpl { diff --git a/Mage/src/mage/abilities/costs/common/ReturnToHandFromGraveyardCost.java b/Mage/src/mage/abilities/costs/common/ReturnToHandFromGraveyardCost.java index f73578adf39..91b85072c9a 100644 --- a/Mage/src/mage/abilities/costs/common/ReturnToHandFromGraveyardCost.java +++ b/Mage/src/mage/abilities/costs/common/ReturnToHandFromGraveyardCost.java @@ -40,7 +40,7 @@ import mage.target.common.TargetCardInYourGraveyard; /** * - * @author BetaSteward_at_googlemail.com + * @author markedagain */ public class ReturnToHandFromGraveyardCost extends CostImpl { diff --git a/Mage/src/mage/abilities/effects/common/discard/DiscardHandAndDrawEffect.java b/Mage/src/mage/abilities/effects/common/discard/DiscardHandAndDrawEffect.java deleted file mode 100644 index 322d613dcc7..00000000000 --- a/Mage/src/mage/abilities/effects/common/discard/DiscardHandAndDrawEffect.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * 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.abilities.effects.common.discard; - -import java.util.Set; -import mage.abilities.Ability; -import mage.abilities.effects.OneShotEffect; -import mage.cards.Card; -import mage.constants.Outcome; -import mage.constants.TargetController; -import mage.game.Game; -import mage.players.Player; - -/** - * @author mluds - */ -public class DiscardHandAndDrawEffect extends OneShotEffect { - - private int CardDrawOffset = 0; - public DiscardHandAndDrawEffect(TargetController targetController) { - this(targetController,0); - } - public DiscardHandAndDrawEffect(TargetController targetController, int cardDrawOffset) { - super(Outcome.Discard); - String PostText = ""; - if (cardDrawOffset >0){ - PostText = " plus " + cardDrawOffset; - }else if(cardDrawOffset < 0){ - PostText = " minus " + cardDrawOffset; - } - this.CardDrawOffset = cardDrawOffset; - switch(targetController) { - case OPPONENT: - this.staticText = "Opponent discards his hand then draws that many cards" + PostText; - break; - case YOU: - this.staticText = "Discard your hand then draws that many cards" + PostText; - break; - } - } - - public DiscardHandAndDrawEffect(final DiscardHandAndDrawEffect effect) { - super(effect); - } - - @Override - public DiscardHandAndDrawEffect copy() { - return new DiscardHandAndDrawEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(targetPointer.getFirst(game, source)); - if (player != null) { - Set cards = player.getHand().getCards(game); - int count = cards.size(); - for (Card card : cards) { - player.discard(card, source, game); - } - player.drawCards(count + this.CardDrawOffset, game); - } - return true; - } -} From 042efb9c22419f1c9d08bb09bfb312c7934b6204 Mon Sep 17 00:00:00 2001 From: LoneFox Date: Fri, 3 Jul 2015 15:38:15 +0300 Subject: [PATCH 010/105] Implement cards: Doomsday Specter, Marsh Crocodile, Natural Emergence, Razing Snidd, and Sparkcaster --- .../mage/sets/planeshift/DoomsdaySpecter.java | 81 ++++++++++++++++ .../mage/sets/planeshift/MarshCrocodile.java | 77 +++++++++++++++ .../sets/planeshift/NaturalEmergence.java | 94 +++++++++++++++++++ .../src/mage/sets/planeshift/RazingSnidd.java | 78 +++++++++++++++ .../src/mage/sets/planeshift/Sparkcaster.java | 81 ++++++++++++++++ .../DiscardCardYouChooseTargetEffect.java | 32 +++---- 6 files changed, 427 insertions(+), 16 deletions(-) create mode 100644 Mage.Sets/src/mage/sets/planeshift/DoomsdaySpecter.java create mode 100644 Mage.Sets/src/mage/sets/planeshift/MarshCrocodile.java create mode 100644 Mage.Sets/src/mage/sets/planeshift/NaturalEmergence.java create mode 100644 Mage.Sets/src/mage/sets/planeshift/RazingSnidd.java create mode 100644 Mage.Sets/src/mage/sets/planeshift/Sparkcaster.java diff --git a/Mage.Sets/src/mage/sets/planeshift/DoomsdaySpecter.java b/Mage.Sets/src/mage/sets/planeshift/DoomsdaySpecter.java new file mode 100644 index 00000000000..0581059b7e8 --- /dev/null +++ b/Mage.Sets/src/mage/sets/planeshift/DoomsdaySpecter.java @@ -0,0 +1,81 @@ +/* + * 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.planeshift; + +import java.util.UUID; +import mage.MageInt; +import mage.ObjectColor; +import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.ReturnToHandChosenControlledPermanentEffect; +import mage.abilities.effects.common.discard.DiscardCardYouChooseTargetEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.ColorPredicate; + +/** + * + * @author LoneFox + + */ +public class DoomsdaySpecter extends CardImpl { + + static final private FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("blue or black creature you control"); + + static { + filter.add(Predicates.or(new ColorPredicate(ObjectColor.BLUE), new ColorPredicate(ObjectColor.BLACK))); + } + + public DoomsdaySpecter(UUID ownerId) { + super(ownerId, 103, "Doomsday Specter", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{2}{U}{B}"); + this.expansionSetCode = "PLS"; + this.subtype.add("Specter"); + this.power = new MageInt(2); + this.toughness = new MageInt(3); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + // When Doomsday Specter enters the battlefield, return a blue or black creature you control to its owner's hand. + this.addAbility(new EntersBattlefieldTriggeredAbility(new ReturnToHandChosenControlledPermanentEffect(filter), false)); + // Whenever Doomsday Specter deals combat damage to a player, look at that player's hand and choose a card from it. The player discards that card. + this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new DiscardCardYouChooseTargetEffect(), false, true)); + } + + public DoomsdaySpecter(final DoomsdaySpecter card) { + super(card); + } + + @Override + public DoomsdaySpecter copy() { + return new DoomsdaySpecter(this); + } +} diff --git a/Mage.Sets/src/mage/sets/planeshift/MarshCrocodile.java b/Mage.Sets/src/mage/sets/planeshift/MarshCrocodile.java new file mode 100644 index 00000000000..29e4f0752c8 --- /dev/null +++ b/Mage.Sets/src/mage/sets/planeshift/MarshCrocodile.java @@ -0,0 +1,77 @@ +/* + * 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.planeshift; + +import java.util.UUID; +import mage.MageInt; +import mage.ObjectColor; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.ReturnToHandChosenControlledPermanentEffect; +import mage.abilities.effects.common.discard.DiscardEachPlayerEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.ColorPredicate; + +/** + * + * @author LoneFox + + */ +public class MarshCrocodile extends CardImpl { + + static final private FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("blue or black creature you control"); + + static { + filter.add(Predicates.or(new ColorPredicate(ObjectColor.BLUE), new ColorPredicate(ObjectColor.BLACK))); + } + + public MarshCrocodile(UUID ownerId) { + super(ownerId, 115, "Marsh Crocodile", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{2}{U}{B}"); + this.expansionSetCode = "PLS"; + this.subtype.add("Crocodile"); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // When Marsh Crocodile enters the battlefield, return a blue or black creature you control to its owner's hand. + this.addAbility(new EntersBattlefieldTriggeredAbility(new ReturnToHandChosenControlledPermanentEffect(filter), false)); + // When Marsh Crocodile enters the battlefield, each player discards a card. + this.addAbility(new EntersBattlefieldTriggeredAbility(new DiscardEachPlayerEffect(), false)); + } + + public MarshCrocodile(final MarshCrocodile card) { + super(card); + } + + @Override + public MarshCrocodile copy() { + return new MarshCrocodile(this); + } +} diff --git a/Mage.Sets/src/mage/sets/planeshift/NaturalEmergence.java b/Mage.Sets/src/mage/sets/planeshift/NaturalEmergence.java new file mode 100644 index 00000000000..45e816753dc --- /dev/null +++ b/Mage.Sets/src/mage/sets/planeshift/NaturalEmergence.java @@ -0,0 +1,94 @@ +/* + * 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.planeshift; + +import java.util.UUID; +import mage.MageInt; +import mage.ObjectColor; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.ReturnToHandChosenControlledPermanentEffect; +import mage.abilities.effects.common.continuous.BecomesCreatureAllEffect; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterControlledEnchantmentPermanent; +import mage.filter.common.FilterControlledLandPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.ColorPredicate; +import mage.game.permanent.token.Token; + +/** + * + * @author LoneFox + + */ +public class NaturalEmergence extends CardImpl { + + static final private FilterControlledEnchantmentPermanent filter = new FilterControlledEnchantmentPermanent("red or green creature you control"); + + static { + filter.add(Predicates.or(new ColorPredicate(ObjectColor.RED), new ColorPredicate(ObjectColor.GREEN))); + } + + public NaturalEmergence(UUID ownerId) { + super(ownerId, 117, "Natural Emergence", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}{G}"); + this.expansionSetCode = "PLS"; + + // When Natural Emergence enters the battlefield, return a red or green enchantment you control to its owner's hand. + Effect effect = new ReturnToHandChosenControlledPermanentEffect(filter); + effect.setText("return a red or green enchantment you control to its owner's hand"); + this.addAbility(new EntersBattlefieldTriggeredAbility(effect, false)); + // Lands you control are 2/2 creatures with first strike. They're still lands. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BecomesCreatureAllEffect(new NaturalEmergenceToken(), + "lands", new FilterControlledLandPermanent("lands you control"), Duration.WhileOnBattlefield))); + } + + public NaturalEmergence(final NaturalEmergence card) { + super(card); + } + + @Override + public NaturalEmergence copy() { + return new NaturalEmergence(this); + } +} + +class NaturalEmergenceToken extends Token { + public NaturalEmergenceToken() { + super("Land", "2/2 creature with first strike"); + cardType.add(CardType.CREATURE); + power = new MageInt(2); + toughness = new MageInt(2); + this.addAbility(FirstStrikeAbility.getInstance()); + } +} diff --git a/Mage.Sets/src/mage/sets/planeshift/RazingSnidd.java b/Mage.Sets/src/mage/sets/planeshift/RazingSnidd.java new file mode 100644 index 00000000000..3567ba17d8d --- /dev/null +++ b/Mage.Sets/src/mage/sets/planeshift/RazingSnidd.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.planeshift; + +import java.util.UUID; +import mage.MageInt; +import mage.ObjectColor; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.ReturnToHandChosenControlledPermanentEffect; +import mage.abilities.effects.common.SacrificeAllEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.common.FilterControlledLandPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.ColorPredicate; + +/** + * + * @author LoneFox + + */ +public class RazingSnidd extends CardImpl { + + static final private FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("black or red creature you control"); + + static { + filter.add(Predicates.or(new ColorPredicate(ObjectColor.BLACK), new ColorPredicate(ObjectColor.RED))); + } + + public RazingSnidd(UUID ownerId) { + super(ownerId, 121, "Razing Snidd", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{4}{B}{R}"); + this.expansionSetCode = "PLS"; + this.subtype.add("Beast"); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // When Razing Snidd enters the battlefield, return a black or red creature you control to its owner's hand. + this.addAbility(new EntersBattlefieldTriggeredAbility(new ReturnToHandChosenControlledPermanentEffect(filter), false)); + // When Razing Snidd enters the battlefield, each player sacrifices a land. + this.addAbility(new EntersBattlefieldTriggeredAbility(new SacrificeAllEffect(1, new FilterControlledLandPermanent("a land")), false)); + } + + public RazingSnidd(final RazingSnidd card) { + super(card); + } + + @Override + public RazingSnidd copy() { + return new RazingSnidd(this); + } +} diff --git a/Mage.Sets/src/mage/sets/planeshift/Sparkcaster.java b/Mage.Sets/src/mage/sets/planeshift/Sparkcaster.java new file mode 100644 index 00000000000..47ee3f189a9 --- /dev/null +++ b/Mage.Sets/src/mage/sets/planeshift/Sparkcaster.java @@ -0,0 +1,81 @@ +/* + * 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.planeshift; + +import java.util.UUID; +import mage.MageInt; +import mage.ObjectColor; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.ReturnToHandChosenControlledPermanentEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPlayer; + +/** + * + * @author LoneFox + + */ +public class Sparkcaster extends CardImpl { + + static final private FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("red or green creature you control"); + + static { + filter.add(Predicates.or(new ColorPredicate(ObjectColor.RED), new ColorPredicate(ObjectColor.GREEN))); + } + + public Sparkcaster(UUID ownerId) { + super(ownerId, 126, "Sparkcaster", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{2}{R}{G}"); + this.expansionSetCode = "PLS"; + this.subtype.add("Kavu"); + this.power = new MageInt(5); + this.toughness = new MageInt(3); + + // When Sparkcaster enters the battlefield, return a red or green creature you control to its owner's hand. + this.addAbility(new EntersBattlefieldTriggeredAbility(new ReturnToHandChosenControlledPermanentEffect(filter), false)); + // When Sparkcaster enters the battlefield, it deals 1 damage to target player. + Ability ability = new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(1), false); + ability.addTarget(new TargetPlayer()); + this.addAbility(ability); + } + + public Sparkcaster(final Sparkcaster card) { + super(card); + } + + @Override + public Sparkcaster copy() { + return new Sparkcaster(this); + } +} diff --git a/Mage/src/mage/abilities/effects/common/discard/DiscardCardYouChooseTargetEffect.java b/Mage/src/mage/abilities/effects/common/discard/DiscardCardYouChooseTargetEffect.java index e88dd52e0b4..76462b5b011 100644 --- a/Mage/src/mage/abilities/effects/common/discard/DiscardCardYouChooseTargetEffect.java +++ b/Mage/src/mage/abilities/effects/common/discard/DiscardCardYouChooseTargetEffect.java @@ -73,9 +73,9 @@ public class DiscardCardYouChooseTargetEffect extends OneShotEffect { public DiscardCardYouChooseTargetEffect(FilterCard filter) { this(filter, TargetController.OPPONENT); } - + public DiscardCardYouChooseTargetEffect(TargetController targetController, int numberCardsToReveal) { - this(new FilterCard("one card"), targetController, + this(new FilterCard("one card"), targetController, new StaticValue(numberCardsToReveal, new StringBuilder(CardUtil.numberToText(numberCardsToReveal)).append(" cards").toString())); } @@ -87,28 +87,28 @@ public class DiscardCardYouChooseTargetEffect extends OneShotEffect { super(Outcome.Discard); this.targetController = targetController; this.filter = filter; - + this.revealAllCards = false; this.numberCardsToReveal = numberCardsToReveal; this.numberCardsToDiscard = new StaticValue(1); - - staticText = this.setText(); + + staticText = this.setText(); } - + public DiscardCardYouChooseTargetEffect(FilterCard filter, TargetController targetController) { this(new StaticValue(1), filter, targetController); } - + public DiscardCardYouChooseTargetEffect(DynamicValue numberCardsToDiscard, FilterCard filter, TargetController targetController) { super(Outcome.Discard); this.targetController = targetController; this.filter = filter; - + this.numberCardsToDiscard = numberCardsToDiscard; this.numberCardsToReveal = null; this.revealAllCards = true; - - staticText = this.setText(); + + staticText = this.setText(); } public DiscardCardYouChooseTargetEffect(final DiscardCardYouChooseTargetEffect effect) { @@ -117,12 +117,12 @@ public class DiscardCardYouChooseTargetEffect extends OneShotEffect { this.targetController = effect.targetController; this.numberCardsToDiscard = effect.numberCardsToDiscard; this.numberCardsToReveal = effect.numberCardsToReveal; - this.revealAllCards = effect.revealAllCards; + this.revealAllCards = effect.revealAllCards; } @Override public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getFirstTarget()); + Player player = game.getPlayer(targetPointer.getFirst(game, source)); Player controller = game.getPlayer(source.getControllerId()); Card sourceCard = game.getCard(source.getSourceId()); if (player != null && controller != null) { @@ -131,7 +131,7 @@ public class DiscardCardYouChooseTargetEffect extends OneShotEffect { } int numberToReveal = this.numberCardsToReveal.calculate(game, source, this); if (numberToReveal > 0) { - Cards revealedCards = new CardsImpl(Zone.HAND); + Cards revealedCards = new CardsImpl(Zone.HAND); numberToReveal = Math.min(player.getHand().size(), numberToReveal); if (player.getHand().size() > numberToReveal) { TargetCardInHand chosenCards = new TargetCardInHand(numberToReveal, numberToReveal, new FilterCard("card in "+ player.getLogName() +"'s hand")); @@ -149,10 +149,10 @@ public class DiscardCardYouChooseTargetEffect extends OneShotEffect { } } else { revealedCards.addAll(player.getHand()); - } + } player.revealCards(sourceCard != null ? sourceCard.getName() :"Discard", revealedCards, game); - + boolean result = true; int filteredCardsCount = revealedCards.count(filter, source.getSourceId(), source.getControllerId(), game); int numberToDiscard = Math.min(this.numberCardsToDiscard.calculate(game, source, this), filteredCardsCount); @@ -220,7 +220,7 @@ public class DiscardCardYouChooseTargetEffect extends OneShotEffect { } else { sb.append(" of them."); } - + sb.append(" That player discards ").append(discardMultipleCards ? "those cards" : "that card").toString(); return sb.toString(); } From 83bb48981fb98a13e7ab8359cc09d0f9f654dd05 Mon Sep 17 00:00:00 2001 From: LoneFox Date: Fri, 3 Jul 2015 16:42:02 +0300 Subject: [PATCH 011/105] Implement cards: Crypt Angel, Reckless Assault, Smoldering Tar, and Stalking Assassin --- .../src/mage/sets/invasion/CryptAngel.java | 87 +++++++++++++++++++ .../mage/sets/invasion/RecklessAssault.java | 68 +++++++++++++++ .../src/mage/sets/invasion/SmolderingTar.java | 75 ++++++++++++++++ .../mage/sets/invasion/StalkingAssassin.java | 84 ++++++++++++++++++ 4 files changed, 314 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/invasion/CryptAngel.java create mode 100644 Mage.Sets/src/mage/sets/invasion/RecklessAssault.java create mode 100644 Mage.Sets/src/mage/sets/invasion/SmolderingTar.java create mode 100644 Mage.Sets/src/mage/sets/invasion/StalkingAssassin.java diff --git a/Mage.Sets/src/mage/sets/invasion/CryptAngel.java b/Mage.Sets/src/mage/sets/invasion/CryptAngel.java new file mode 100644 index 00000000000..da30d56b63d --- /dev/null +++ b/Mage.Sets/src/mage/sets/invasion/CryptAngel.java @@ -0,0 +1,87 @@ +/* + * 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.invasion; + +import java.util.UUID; +import mage.MageInt; +import mage.ObjectColor; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.ReturnToHandTargetEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.ProtectionAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.FilterCard; +import mage.filter.common.FilterCreatureCard; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.common.TargetCardInYourGraveyard; + +/** + * + * @author LoneFox + + */ +public class CryptAngel extends CardImpl { + + private static final FilterCard filter = new FilterCard("white"); + private static final FilterCreatureCard filter2 = new FilterCreatureCard("blue or red creature card from your graveyard"); + + static { + filter.add(new ColorPredicate(ObjectColor.WHITE)); + filter2.add(Predicates.or(new ColorPredicate(ObjectColor.RED), new ColorPredicate(ObjectColor.BLUE))); + } + + public CryptAngel(UUID ownerId) { + super(ownerId, 97, "Crypt Angel", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{4}{B}"); + this.expansionSetCode = "INV"; + this.subtype.add("Angel"); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + // protection from white + this.addAbility(new ProtectionAbility(filter)); + // When Crypt Angel enters the battlefield, return target blue or red creature card from your graveyard to your hand. + Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect(), false); + ability.addTarget(new TargetCardInYourGraveyard(filter2)); + this.addAbility(ability); + } + + public CryptAngel(final CryptAngel card) { + super(card); + } + + @Override + public CryptAngel copy() { + return new CryptAngel(this); + } +} diff --git a/Mage.Sets/src/mage/sets/invasion/RecklessAssault.java b/Mage.Sets/src/mage/sets/invasion/RecklessAssault.java new file mode 100644 index 00000000000..ec7a63d2631 --- /dev/null +++ b/Mage.Sets/src/mage/sets/invasion/RecklessAssault.java @@ -0,0 +1,68 @@ +/* + * 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.invasion; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.PayLifeCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.target.common.TargetCreatureOrPlayer; + +/** + * + * @author LoneFox + + */ +public class RecklessAssault extends CardImpl { + + public RecklessAssault(UUID ownerId) { + super(ownerId, 263, "Reckless Assault", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{2}{B}{R}"); + this.expansionSetCode = "INV"; + + // {1}, Pay 2 life: Reckless Assault deals 1 damage to target creature or player. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(1), new ManaCostsImpl("{1}")); + ability.addCost(new PayLifeCost(2)); + ability.addTarget(new TargetCreatureOrPlayer()); + this.addAbility(ability); + } + + public RecklessAssault(final RecklessAssault card) { + super(card); + } + + @Override + public RecklessAssault copy() { + return new RecklessAssault(this); + } +} diff --git a/Mage.Sets/src/mage/sets/invasion/SmolderingTar.java b/Mage.Sets/src/mage/sets/invasion/SmolderingTar.java new file mode 100644 index 00000000000..7effc424ebf --- /dev/null +++ b/Mage.Sets/src/mage/sets/invasion/SmolderingTar.java @@ -0,0 +1,75 @@ +/* + * 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.invasion; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.ActivateAsSorceryActivatedAbility; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.LoseLifeTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.target.TargetPlayer; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LoneFox + + */ +public class SmolderingTar extends CardImpl { + + public SmolderingTar(UUID ownerId) { + super(ownerId, 275, "Smoldering Tar", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT}, "{2}{B}{R}"); + this.expansionSetCode = "INV"; + + // At the beginning of your upkeep, target player loses 1 life. + Ability ability = new BeginningOfUpkeepTriggeredAbility(new LoseLifeTargetEffect(1), TargetController.YOU, false); + ability.addTarget(new TargetPlayer()); + this.addAbility(ability); + // Sacrifice Smoldering Tar: Smoldering Tar deals 4 damage to target creature. Activate this ability only any time you could cast a sorcery. + ability = new ActivateAsSorceryActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(4), new SacrificeSourceCost()); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + public SmolderingTar(final SmolderingTar card) { + super(card); + } + + @Override + public SmolderingTar copy() { + return new SmolderingTar(this); + } +} diff --git a/Mage.Sets/src/mage/sets/invasion/StalkingAssassin.java b/Mage.Sets/src/mage/sets/invasion/StalkingAssassin.java new file mode 100644 index 00000000000..559f5943d46 --- /dev/null +++ b/Mage.Sets/src/mage/sets/invasion/StalkingAssassin.java @@ -0,0 +1,84 @@ +/* + * 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.invasion; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.effects.common.TapTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.TappedPredicate; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LoneFox + + */ +public class StalkingAssassin extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("tapped creature"); + + static { + filter.add(new TappedPredicate()); + } + + public StalkingAssassin(UUID ownerId) { + super(ownerId, 277, "Stalking Assassin", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{1}{U}{B}"); + this.expansionSetCode = "INV"; + this.subtype.add("Human"); + this.subtype.add("Assassin"); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // {3}{U}, {T}: Tap target creature. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TapTargetEffect(), new ManaCostsImpl("{3}{U}")); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + // {3}{B}, {T}: Destroy target tapped creature. + ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DestroyTargetEffect(), new ManaCostsImpl("{3}{B}")); + ability.addTarget(new TargetCreaturePermanent(filter)); + this.addAbility(ability); + } + + public StalkingAssassin(final StalkingAssassin card) { + super(card); + } + + @Override + public StalkingAssassin copy() { + return new StalkingAssassin(this); + } +} From 2b4829377ae8dc9066177b64f3696ccc8d1eed7d Mon Sep 17 00:00:00 2001 From: LoneFox Date: Fri, 3 Jul 2015 19:02:47 +0300 Subject: [PATCH 012/105] Stalking Assassin's abilities require tapping the Assassin --- Mage.Sets/src/mage/sets/invasion/StalkingAssassin.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Mage.Sets/src/mage/sets/invasion/StalkingAssassin.java b/Mage.Sets/src/mage/sets/invasion/StalkingAssassin.java index 559f5943d46..e89edd61256 100644 --- a/Mage.Sets/src/mage/sets/invasion/StalkingAssassin.java +++ b/Mage.Sets/src/mage/sets/invasion/StalkingAssassin.java @@ -31,6 +31,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.TapTargetEffect; @@ -65,10 +66,12 @@ public class StalkingAssassin extends CardImpl { // {3}{U}, {T}: Tap target creature. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TapTargetEffect(), new ManaCostsImpl("{3}{U}")); + ability.addCost(new TapSourceCost()); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); // {3}{B}, {T}: Destroy target tapped creature. ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DestroyTargetEffect(), new ManaCostsImpl("{3}{B}")); + ability.addCost(new TapSourceCost()); ability.addTarget(new TargetCreaturePermanent(filter)); this.addAbility(ability); } From 7e776fc8dd47c3b49d6b3aebc8389b8fdc23b7d9 Mon Sep 17 00:00:00 2001 From: LoneFox Date: Fri, 3 Jul 2015 19:17:44 +0300 Subject: [PATCH 013/105] Implement cards: Plague Spitter, Plague Spores, Stronghold Taskmaster, and Urborg Shambler --- .../src/mage/sets/invasion/PlagueSpitter.java | 68 ++++++++++++++++ .../src/mage/sets/invasion/PlagueSpores.java | 76 ++++++++++++++++++ .../mage/sets/invasion/UrborgShambler.java | 76 ++++++++++++++++++ .../sets/stronghold/StrongholdTaskmaster.java | 77 +++++++++++++++++++ 4 files changed, 297 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/invasion/PlagueSpitter.java create mode 100644 Mage.Sets/src/mage/sets/invasion/PlagueSpores.java create mode 100644 Mage.Sets/src/mage/sets/invasion/UrborgShambler.java create mode 100644 Mage.Sets/src/mage/sets/stronghold/StrongholdTaskmaster.java diff --git a/Mage.Sets/src/mage/sets/invasion/PlagueSpitter.java b/Mage.Sets/src/mage/sets/invasion/PlagueSpitter.java new file mode 100644 index 00000000000..cc9c600a78c --- /dev/null +++ b/Mage.Sets/src/mage/sets/invasion/PlagueSpitter.java @@ -0,0 +1,68 @@ +/* + * 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.invasion; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.DiesTriggeredAbility; +import mage.abilities.effects.common.DamageEverythingEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.TargetController; + +/** + * + * @author LoneFox + + */ +public class PlagueSpitter extends CardImpl { + + public PlagueSpitter(UUID ownerId) { + super(ownerId, 119, "Plague Spitter", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{2}{B}"); + this.expansionSetCode = "INV"; + this.subtype.add("Horror"); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // At the beginning of your upkeep, Plague Spitter deals 1 damage to each creature and each player. + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new DamageEverythingEffect(1), TargetController.YOU, false)); + // When Plague Spitter dies, Plague Spitter deals 1 damage to each creature and each player. + this.addAbility(new DiesTriggeredAbility(new DamageEverythingEffect(1), false)); + } + + public PlagueSpitter(final PlagueSpitter card) { + super(card); + } + + @Override + public PlagueSpitter copy() { + return new PlagueSpitter(this); + } +} diff --git a/Mage.Sets/src/mage/sets/invasion/PlagueSpores.java b/Mage.Sets/src/mage/sets/invasion/PlagueSpores.java new file mode 100644 index 00000000000..db32455cf27 --- /dev/null +++ b/Mage.Sets/src/mage/sets/invasion/PlagueSpores.java @@ -0,0 +1,76 @@ +/* + * 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.invasion; + +import java.util.UUID; +import mage.ObjectColor; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.common.TargetCreaturePermanent; +import mage.target.common.TargetLandPermanent; + +/** + * + * @author LoneFox + + */ +public class PlagueSpores extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nonblack creature"); + + static { + filter.add(Predicates.not(new ColorPredicate(ObjectColor.BLACK))); + } + + public PlagueSpores(UUID ownerId) { + super(ownerId, 260, "Plague Spores", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{4}{B}{R}"); + this.expansionSetCode = "INV"; + + // Destroy target nonblack creature and target land. They can't be regenerated. + Effect effect = new DestroyTargetEffect(true); + effect.setText("Destroy target nonblack creature and target land. They can't be regenerated."); + this.getSpellAbility().addEffect(effect); + this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetLandPermanent()); + } + + public PlagueSpores(final PlagueSpores card) { + super(card); + } + + @Override + public PlagueSpores copy() { + return new PlagueSpores(this); + } +} diff --git a/Mage.Sets/src/mage/sets/invasion/UrborgShambler.java b/Mage.Sets/src/mage/sets/invasion/UrborgShambler.java new file mode 100644 index 00000000000..e587ab087b4 --- /dev/null +++ b/Mage.Sets/src/mage/sets/invasion/UrborgShambler.java @@ -0,0 +1,76 @@ +/* + * 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.invasion; + +import java.util.UUID; +import mage.MageInt; +import mage.ObjectColor; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.continuous.BoostAllEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.ColorPredicate; + +/** + * + * @author LoneFox + + */ +public class UrborgShambler extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("black creatures"); + + static { + filter.add(new ColorPredicate(ObjectColor.BLACK)); + } + + public UrborgShambler(UUID ownerId) { + super(ownerId, 133, "Urborg Shambler", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{2}{B}{B}"); + this.expansionSetCode = "INV"; + this.subtype.add("Horror"); + this.power = new MageInt(4); + this.toughness = new MageInt(3); + + // Other black creatures get -1/-1. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostAllEffect(-1, -1, + Duration.WhileOnBattlefield, filter, true))); + } + + public UrborgShambler(final UrborgShambler card) { + super(card); + } + + @Override + public UrborgShambler copy() { + return new UrborgShambler(this); + } +} diff --git a/Mage.Sets/src/mage/sets/stronghold/StrongholdTaskmaster.java b/Mage.Sets/src/mage/sets/stronghold/StrongholdTaskmaster.java new file mode 100644 index 00000000000..b195202367a --- /dev/null +++ b/Mage.Sets/src/mage/sets/stronghold/StrongholdTaskmaster.java @@ -0,0 +1,77 @@ +/* + * 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.stronghold; + +import java.util.UUID; +import mage.MageInt; +import mage.ObjectColor; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.continuous.BoostAllEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.ColorPredicate; + +/** + * + * @author LoneFox + + */ +public class StrongholdTaskmaster extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("black creatures"); + + static { + filter.add(new ColorPredicate(ObjectColor.BLACK)); + } + + public StrongholdTaskmaster(UUID ownerId) { + super(ownerId, 22, "Stronghold Taskmaster", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{2}{B}{B}"); + this.expansionSetCode = "STH"; + this.subtype.add("Giant"); + this.subtype.add("Minion"); + this.power = new MageInt(4); + this.toughness = new MageInt(3); + + // Other black creatures get -1/-1. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostAllEffect(-1, -1, + Duration.WhileOnBattlefield, filter, true))); + } + + public StrongholdTaskmaster(final StrongholdTaskmaster card) { + super(card); + } + + @Override + public StrongholdTaskmaster copy() { + return new StrongholdTaskmaster(this); + } +} From aa237cd27eeebc0aa41ea5bb1cdd9cef01db7f25 Mon Sep 17 00:00:00 2001 From: LoneFox Date: Fri, 3 Jul 2015 21:24:45 +0300 Subject: [PATCH 014/105] Combine several card-specific implementations of TapAllTargetPlayerControlsEffect to a public class. Implement another card that uses it: Tectonic Instability --- .../sets/fatereforged/TorrentElemental.java | 35 ++------ .../sets/invasion/TectonicInstability.java | 65 ++++++++++++++ .../src/mage/sets/limitedalpha/ManaShort.java | 26 ++---- .../src/mage/sets/lorwyn/MistbindClique.java | 46 ++-------- .../riseoftheeldrazi/DawnglareInvoker.java | 48 ++--------- .../mage/sets/shardsofalara/NayaCharm.java | 47 +--------- .../TapAllTargetPlayerControlsEffect.java | 86 +++++++++++++++++++ 7 files changed, 178 insertions(+), 175 deletions(-) create mode 100644 Mage.Sets/src/mage/sets/invasion/TectonicInstability.java create mode 100644 Mage/src/mage/abilities/effects/common/TapAllTargetPlayerControlsEffect.java diff --git a/Mage.Sets/src/mage/sets/fatereforged/TorrentElemental.java b/Mage.Sets/src/mage/sets/fatereforged/TorrentElemental.java index a4bbe3f58f3..d9590de8ffa 100644 --- a/Mage.Sets/src/mage/sets/fatereforged/TorrentElemental.java +++ b/Mage.Sets/src/mage/sets/fatereforged/TorrentElemental.java @@ -33,7 +33,9 @@ import mage.abilities.Ability; import mage.abilities.common.ActivateAsSorceryActivatedAbility; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.TapAllTargetPlayerControlsEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.Card; import mage.cards.CardImpl; @@ -44,7 +46,6 @@ import mage.constants.SetTargetPointer; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; -import mage.game.permanent.Permanent; import mage.players.Player; /** @@ -63,8 +64,9 @@ public class TorrentElemental extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); // Whenever Torrent Elemental attacks, tap all creatures defending player controls. - this.addAbility(new AttacksTriggeredAbility(new TorrentElementalEffect(), false, null, SetTargetPointer.PLAYER)); - + Effect effect = new TapAllTargetPlayerControlsEffect(new FilterCreaturePermanent()); + effect.setText("tap all creatures defending player controls."); + this.addAbility(new AttacksTriggeredAbility(effect, false, null, SetTargetPointer.PLAYER)); // {3}{B/G}{B/G}: Put Torrent Elemental from exile onto the battlefield tapped. Activate this ability only any time you could cast a sorcery. Ability ability = new ActivateAsSorceryActivatedAbility(Zone.EXILED, new ReturnSourceFromExileToBattlefieldEffect(true), new ManaCostsImpl("{3}{B/G}{B/G}")); this.addAbility(ability); @@ -81,31 +83,6 @@ public class TorrentElemental extends CardImpl { } } -class TorrentElementalEffect extends OneShotEffect { - - public TorrentElementalEffect() { - super(Outcome.Tap); - this.staticText = "tap all creatures defending player controls"; - } - - public TorrentElementalEffect(final TorrentElementalEffect effect) { - super(effect); - } - - @Override - public TorrentElementalEffect copy() { - return new TorrentElementalEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - for (Permanent permanent : game.getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), getTargetPointer().getFirst(game, source), game)) { - permanent.tap(game); - } - return true; - } -} - class ReturnSourceFromExileToBattlefieldEffect extends OneShotEffect { private boolean tapped; @@ -172,4 +149,4 @@ class ReturnSourceFromExileToBattlefieldEffect extends OneShotEffect { staticText = sb.toString(); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/sets/invasion/TectonicInstability.java b/Mage.Sets/src/mage/sets/invasion/TectonicInstability.java new file mode 100644 index 00000000000..5cbdd9b6bed --- /dev/null +++ b/Mage.Sets/src/mage/sets/invasion/TectonicInstability.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.invasion; + +import java.util.UUID; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; +import mage.abilities.effects.common.TapAllTargetPlayerControlsEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.SetTargetPointer; +import mage.constants.Zone; +import mage.filter.common.FilterLandPermanent; + +/** + * + * @author LoneFox + + */ +public class TectonicInstability extends CardImpl { + + public TectonicInstability(UUID ownerId) { + super(ownerId, 173, "Tectonic Instability", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}"); + this.expansionSetCode = "INV"; + + // Whenever a land enters the battlefield, tap all lands its controller controls. + this.addAbility(new EntersBattlefieldAllTriggeredAbility(Zone.BATTLEFIELD, + new TapAllTargetPlayerControlsEffect(new FilterLandPermanent()), new FilterLandPermanent(), + false, SetTargetPointer.PLAYER, "Whenever a land enters the battlefield, tap all lands its controller controls.")); + } + + public TectonicInstability(final TectonicInstability card) { + super(card); + } + + @Override + public TectonicInstability copy() { + return new TectonicInstability(this); + } +} diff --git a/Mage.Sets/src/mage/sets/limitedalpha/ManaShort.java b/Mage.Sets/src/mage/sets/limitedalpha/ManaShort.java index 68a31f8db1c..9a1f38eec6e 100644 --- a/Mage.Sets/src/mage/sets/limitedalpha/ManaShort.java +++ b/Mage.Sets/src/mage/sets/limitedalpha/ManaShort.java @@ -27,16 +27,14 @@ */ package mage.sets.limitedalpha; -import java.util.List; import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.TapAllTargetPlayerControlsEffect; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.Rarity; import mage.filter.common.FilterLandPermanent; -import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; @@ -52,7 +50,6 @@ public class ManaShort extends CardImpl { super(ownerId, 66, "Mana Short", Rarity.RARE, new CardType[]{CardType.INSTANT}, "{2}{U}"); this.expansionSetCode = "LEA"; - // Tap all lands target player controls and empty his or her mana pool. this.getSpellAbility().addEffect(new ManaShortEffect()); this.getSpellAbility().addTarget(new TargetPlayer()); @@ -68,13 +65,13 @@ public class ManaShort extends CardImpl { } } -class ManaShortEffect extends OneShotEffect { +class ManaShortEffect extends TapAllTargetPlayerControlsEffect { public ManaShortEffect() { - super(Outcome.Detriment); + super(new FilterLandPermanent("lands")); staticText = "Tap all lands target player controls and empty his or her mana pool"; } - + public ManaShortEffect(final ManaShortEffect effect) { super(effect); } @@ -83,24 +80,15 @@ class ManaShortEffect extends OneShotEffect { public ManaShortEffect copy() { return new ManaShortEffect(this); } - + @Override public boolean apply(Game game, Ability source) { Player targetPlayer = game.getPlayer(source.getFirstTarget()); - if (targetPlayer != null) { - FilterLandPermanent filter = new FilterLandPermanent(); - filter.add(new ControllerIdPredicate(targetPlayer.getId())); - - List lands = game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game); - for (Permanent land : lands) { - land.tap(game); - } - + if(targetPlayer != null) { + super.apply(game, source); targetPlayer.getManaPool().emptyPool(game); - return true; } return false; } - } diff --git a/Mage.Sets/src/mage/sets/lorwyn/MistbindClique.java b/Mage.Sets/src/mage/sets/lorwyn/MistbindClique.java index 5eaf9d8f525..3809f1350bc 100644 --- a/Mage.Sets/src/mage/sets/lorwyn/MistbindClique.java +++ b/Mage.Sets/src/mage/sets/lorwyn/MistbindClique.java @@ -27,14 +27,13 @@ */ package mage.sets.lorwyn; -import java.util.List; import java.util.UUID; import mage.MageInt; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.ZoneChangeTriggeredAbility; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.TapAllTargetPlayerControlsEffect; import mage.abilities.keyword.ChampionAbility; import mage.abilities.keyword.FlashAbility; import mage.abilities.keyword.FlyingAbility; @@ -44,11 +43,9 @@ import mage.constants.Outcome; import mage.constants.Rarity; import mage.constants.Zone; import mage.filter.common.FilterLandPermanent; -import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.ZoneChangeEvent; -import mage.game.permanent.Permanent; import mage.target.TargetPlayer; /** @@ -92,14 +89,14 @@ class MistbindCliqueAbility extends ZoneChangeTriggeredAbility { public MistbindCliqueAbility() { // ability has to trigger independant where the source object is now - super(Zone.ALL, Zone.BATTLEFIELD, Zone.EXILED, new MistbindCliqueTapEffect(), "When a Faerie is championed with {this}, ", false); + super(Zone.ALL, Zone.BATTLEFIELD, Zone.EXILED, new TapAllTargetPlayerControlsEffect(new FilterLandPermanent("lands")), "When a Faerie is championed with {this}, ", false); this.addTarget(new TargetPlayer()); } public MistbindCliqueAbility(MistbindCliqueAbility ability) { super(ability); } - + @Override public MistbindCliqueAbility copy() { return new MistbindCliqueAbility(this); @@ -113,44 +110,11 @@ class MistbindCliqueAbility extends ZoneChangeTriggeredAbility { @Override public boolean checkTrigger(GameEvent event, Game game) { if (event.getSourceId() != null && event.getSourceId().equals(getSourceId())) { - ZoneChangeEvent zEvent = (ZoneChangeEvent)event; + ZoneChangeEvent zEvent = (ZoneChangeEvent)event; if (zEvent.getTarget() != null && zEvent.getTarget().hasSubtype("Faerie")) { return true; - } + } } return false; } } - -class MistbindCliqueTapEffect extends OneShotEffect { - - public MistbindCliqueTapEffect() { - super(Outcome.Tap); - staticText = "tap all lands target player controls"; - } - - public MistbindCliqueTapEffect(final MistbindCliqueTapEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - if (source.getFirstTarget() == null) { - return false; - } - - FilterLandPermanent filter = new FilterLandPermanent(); - filter.add(new ControllerIdPredicate(source.getFirstTarget())); - - List lands = game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game); - for (Permanent land : lands) { - land.tap(game); - } - return true; - } - - @Override - public MistbindCliqueTapEffect copy() { - return new MistbindCliqueTapEffect(this); - } -} diff --git a/Mage.Sets/src/mage/sets/riseoftheeldrazi/DawnglareInvoker.java b/Mage.Sets/src/mage/sets/riseoftheeldrazi/DawnglareInvoker.java index 0a6ed85ffc3..70999f3afea 100644 --- a/Mage.Sets/src/mage/sets/riseoftheeldrazi/DawnglareInvoker.java +++ b/Mage.Sets/src/mage/sets/riseoftheeldrazi/DawnglareInvoker.java @@ -27,23 +27,18 @@ */ package mage.sets.riseoftheeldrazi; -import java.util.List; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.Rarity; -import mage.constants.Zone; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.TapAllTargetPlayerControlsEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.permanent.ControllerIdPredicate; -import mage.game.Game; -import mage.game.permanent.Permanent; import mage.target.TargetPlayer; /** @@ -63,7 +58,7 @@ public class DawnglareInvoker extends CardImpl { this.addAbility(FlyingAbility.getInstance()); SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, - new DawnglareInvokerEffect(), + new TapAllTargetPlayerControlsEffect(new FilterCreaturePermanent("creatures")), new ManaCostsImpl("{8}")); ability.addTarget(new TargetPlayer()); this.addAbility(ability); @@ -78,36 +73,3 @@ public class DawnglareInvoker extends CardImpl { return new DawnglareInvoker(this); } } - -class DawnglareInvokerEffect extends OneShotEffect { - - public DawnglareInvokerEffect() { - super(Outcome.Tap); - staticText = "Tap all creatures target player controls"; - } - - public DawnglareInvokerEffect(final DawnglareInvokerEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - if (source.getFirstTarget() == null) { - return false; - } - - FilterCreaturePermanent filter = new FilterCreaturePermanent(); - filter.add(new ControllerIdPredicate(source.getFirstTarget())); - - List creatures = game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game); - for (Permanent creature : creatures) { - creature.tap(game); - } - return true; - } - - @Override - public DawnglareInvokerEffect copy() { - return new DawnglareInvokerEffect(this); - } -} diff --git a/Mage.Sets/src/mage/sets/shardsofalara/NayaCharm.java b/Mage.Sets/src/mage/sets/shardsofalara/NayaCharm.java index ecca5d6752a..cc48836bb53 100644 --- a/Mage.Sets/src/mage/sets/shardsofalara/NayaCharm.java +++ b/Mage.Sets/src/mage/sets/shardsofalara/NayaCharm.java @@ -29,19 +29,14 @@ package mage.sets.shardsofalara; import java.util.List; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.Rarity; -import mage.abilities.Ability; import mage.abilities.Mode; -import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.ReturnToHandTargetEffect; +import mage.abilities.effects.common.TapAllTargetPlayerControlsEffect; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.permanent.ControllerIdPredicate; -import mage.game.Game; -import mage.game.permanent.Permanent; import mage.target.TargetPlayer; import mage.target.common.TargetCardInGraveyard; import mage.target.common.TargetCreaturePermanent; @@ -56,7 +51,6 @@ public class NayaCharm extends CardImpl { super(ownerId, 180, "Naya Charm", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{R}{G}{W}"); this.expansionSetCode = "ALA"; - // Choose one - Naya Charm deals 3 damage to target creature; this.getSpellAbility().addEffect(new DamageTargetEffect(3)); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); @@ -67,7 +61,7 @@ public class NayaCharm extends CardImpl { this.getSpellAbility().addMode(mode); // or tap all creatures target player controls. mode = new Mode(); - mode.getEffects().add(new NayaCharmEffect()); + mode.getEffects().add(new TapAllTargetPlayerControlsEffect(new FilterCreaturePermanent("creatures"))); mode.getTargets().add(new TargetPlayer()); this.getSpellAbility().addMode(mode); } @@ -81,36 +75,3 @@ public class NayaCharm extends CardImpl { return new NayaCharm(this); } } - -class NayaCharmEffect extends OneShotEffect { - - public NayaCharmEffect() { - super(Outcome.Tap); - staticText = "Tap all creatures target player controls"; - } - - public NayaCharmEffect(final NayaCharmEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - if (source.getFirstTarget() == null) { - return false; - } - - FilterCreaturePermanent filter = new FilterCreaturePermanent(); - filter.add(new ControllerIdPredicate(source.getFirstTarget())); - - List creatures = game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game); - for (Permanent creature : creatures) { - creature.tap(game); - } - return true; - } - - @Override - public NayaCharmEffect copy() { - return new NayaCharmEffect(this); - } -} diff --git a/Mage/src/mage/abilities/effects/common/TapAllTargetPlayerControlsEffect.java b/Mage/src/mage/abilities/effects/common/TapAllTargetPlayerControlsEffect.java new file mode 100644 index 00000000000..0ad564a7211 --- /dev/null +++ b/Mage/src/mage/abilities/effects/common/TapAllTargetPlayerControlsEffect.java @@ -0,0 +1,86 @@ +/* + * 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.abilities.effects.common; + +import java.util.List; +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.effects.OneShotEffect; +import mage.constants.Outcome; +import mage.filter.FilterPermanent; +import mage.filter.predicate.permanent.ControllerIdPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; + +/** + * + * @author LoneFox + */ +public class TapAllTargetPlayerControlsEffect extends OneShotEffect { + + private FilterPermanent filter; + + public TapAllTargetPlayerControlsEffect(FilterPermanent filter) { + super(Outcome.Tap); + this.filter = filter; + } + + public TapAllTargetPlayerControlsEffect(final TapAllTargetPlayerControlsEffect effect) { + super(effect); + filter = effect.filter.copy(); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(targetPointer.getFirst(game, source)); + if(player != null) { + filter.add(new ControllerIdPredicate(player.getId())); + List permanents = game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game); + for(Permanent p : permanents) { + p.tap(game); + } + return true; + } + return false; + } + + @Override + public TapAllTargetPlayerControlsEffect copy() { + return new TapAllTargetPlayerControlsEffect(this); + } + + @Override + public String getText(Mode mode) { + if(staticText != null && !staticText.isEmpty()) { + return staticText; + } + return "tap all " + filter.getMessage() + " target player controls"; + } +} From 3a4740ce710e8142bfe2e3c2efb4c474a1de229f Mon Sep 17 00:00:00 2001 From: LoneFox Date: Sat, 4 Jul 2015 11:11:44 +0300 Subject: [PATCH 015/105] Implement cards: Daring Leap, Disciple of Kangee, March of Souls, and Stratadon --- .../src/mage/sets/planeshift/DaringLeap.java | 73 ++++++++++++ .../sets/planeshift/DiscipleOfKangee.java | 82 ++++++++++++++ .../mage/sets/planeshift/MarchOfSouls.java | 98 ++++++++++++++++ .../src/mage/sets/planeshift/Stratadon.java | 105 ++++++++++++++++++ 4 files changed, 358 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/planeshift/DaringLeap.java create mode 100644 Mage.Sets/src/mage/sets/planeshift/DiscipleOfKangee.java create mode 100644 Mage.Sets/src/mage/sets/planeshift/MarchOfSouls.java create mode 100644 Mage.Sets/src/mage/sets/planeshift/Stratadon.java diff --git a/Mage.Sets/src/mage/sets/planeshift/DaringLeap.java b/Mage.Sets/src/mage/sets/planeshift/DaringLeap.java new file mode 100644 index 00000000000..b8d9105ca69 --- /dev/null +++ b/Mage.Sets/src/mage/sets/planeshift/DaringLeap.java @@ -0,0 +1,73 @@ +/* + * 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.planeshift; + +import java.util.UUID; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LoneFox + */ +public class DaringLeap extends CardImpl { + + public DaringLeap(UUID ownerId) { + super(ownerId, 101, "Daring Leap", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{1}{W}{U}"); + this.expansionSetCode = "PLS"; + + // Target creature gets +1/+1 and gains flying and first strike until end of turn. + Effect effect = new BoostTargetEffect(1, 1, Duration.EndOfTurn); + effect.setText("Target creature gets +1/+1"); + this.getSpellAbility().addEffect(effect); + effect = new GainAbilityTargetEffect(FlyingAbility.getInstance(), Duration.EndOfTurn); + effect.setText("and gains flying"); + this.getSpellAbility().addEffect(effect); + effect = new GainAbilityTargetEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn); + effect.setText("and first strike until end of turn."); + this.getSpellAbility().addEffect(effect); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + } + + public DaringLeap(final DaringLeap card) { + super(card); + } + + @Override + public DaringLeap copy() { + return new DaringLeap(this); + } +} diff --git a/Mage.Sets/src/mage/sets/planeshift/DiscipleOfKangee.java b/Mage.Sets/src/mage/sets/planeshift/DiscipleOfKangee.java new file mode 100644 index 00000000000..2080755673c --- /dev/null +++ b/Mage.Sets/src/mage/sets/planeshift/DiscipleOfKangee.java @@ -0,0 +1,82 @@ +/* + * 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.planeshift; + +import java.util.UUID; +import mage.MageInt; +import mage.ObjectColor; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.continuous.BecomesColorTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LoneFox + */ +public class DiscipleOfKangee extends CardImpl { + + public DiscipleOfKangee(UUID ownerId) { + super(ownerId, 3, "Disciple of Kangee", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{2}{W}"); + this.expansionSetCode = "PLS"; + this.subtype.add("Human"); + this.subtype.add("Wizard"); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // {U}, {T}: Target creature gains flying and becomes blue until end of turn. + Effect effect = new GainAbilityTargetEffect(FlyingAbility.getInstance(), Duration.EndOfTurn); + effect.setText("Target creature gains flying"); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{U}")); + effect = new BecomesColorTargetEffect(ObjectColor.BLUE, Duration.EndOfTurn); + effect.setText("and becomes blue until end of turn."); + ability.addEffect(effect); + ability.addCost(new TapSourceCost()); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + public DiscipleOfKangee(final DiscipleOfKangee card) { + super(card); + } + + @Override + public DiscipleOfKangee copy() { + return new DiscipleOfKangee(this); + } +} diff --git a/Mage.Sets/src/mage/sets/planeshift/MarchOfSouls.java b/Mage.Sets/src/mage/sets/planeshift/MarchOfSouls.java new file mode 100644 index 00000000000..d1d0d83b4ea --- /dev/null +++ b/Mage.Sets/src/mage/sets/planeshift/MarchOfSouls.java @@ -0,0 +1,98 @@ +/* + * 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.planeshift; + +import java.util.List; +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.filter.common.FilterCreaturePermanent; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.game.permanent.token.SpiritWhiteToken; + +/** + * + * @author LoneFox + + */ +public class MarchOfSouls extends CardImpl { + + public MarchOfSouls(UUID ownerId) { + super(ownerId, 10, "March of Souls", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{4}{W}"); + this.expansionSetCode = "PLS"; + + // Destroy all creatures. They can't be regenerated. For each creature destroyed this way, its controller puts a 1/1 white Spirit creature token with flying onto the battlefield. + this.getSpellAbility().addEffect(new MarchOfSoulsEffect()); + } + + public MarchOfSouls(final MarchOfSouls card) { + super(card); + } + + @Override + public MarchOfSouls copy() { + return new MarchOfSouls(this); + } +} + +class MarchOfSoulsEffect extends OneShotEffect { + + public MarchOfSoulsEffect() { + super(Outcome.Benefit); + staticText = "Destroy all creatures. They can't be regenerated. For each creature destroyed this way, its controller puts a 1/1 white Spirit creature token with flying onto the battlefield."; + } + + public MarchOfSoulsEffect(final MarchOfSoulsEffect effect) { + super(effect); + } + + @Override + public MarchOfSoulsEffect copy() { + return new MarchOfSoulsEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + List creatures = game.getBattlefield().getActivePermanents(new FilterCreaturePermanent(), + source.getControllerId(), source.getSourceId(), game); + for(Permanent p : creatures) { + UUID controllerId = p.getControllerId(); + if(p.destroy(source.getSourceId(), game, true)) { + SpiritWhiteToken token = new SpiritWhiteToken(); + token.putOntoBattlefield(1, game, source.getSourceId(), controllerId); + } + } + return true; + } + +} diff --git a/Mage.Sets/src/mage/sets/planeshift/Stratadon.java b/Mage.Sets/src/mage/sets/planeshift/Stratadon.java new file mode 100644 index 00000000000..fd2a3be8f89 --- /dev/null +++ b/Mage.Sets/src/mage/sets/planeshift/Stratadon.java @@ -0,0 +1,105 @@ +/* + * 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.planeshift; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.SpellAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.dynamicvalue.common.DomainValue; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.Game; +import mage.util.CardUtil; + +/** + * + * @author LoneFox + */ +public class Stratadon extends CardImpl { + + public Stratadon(UUID ownerId) { + super(ownerId, 135, "Stratadon", Rarity.UNCOMMON, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{10}"); + this.expansionSetCode = "PLS"; + this.subtype.add("Beast"); + this.power = new MageInt(5); + this.toughness = new MageInt(5); + + // Domain - Stratadon costs {1} less to cast for each basic land type among lands you control. + this.addAbility(new SimpleStaticAbility(Zone.STACK, new StratadonCostReductionEffect())); + // Trample + this.addAbility(TrampleAbility.getInstance()); + } + + @Override + public void adjustCosts(Ability ability, Game game) { + super.adjustCosts(ability, game); + CardUtil.adjustCost((SpellAbility)ability, new DomainValue().calculate(game, ability, null)); + } + + + public Stratadon(final Stratadon card) { + super(card); + } + + @Override + public Stratadon copy() { + return new Stratadon(this); + } +} + +// Dummy to get the text on the card. +class StratadonCostReductionEffect extends OneShotEffect { + private static final String effectText = "Domain - {this} costs {1} less to cast for each basic land type among lands you control."; + + StratadonCostReductionEffect() { + super(Outcome.Benefit); + this.staticText = effectText; + } + + StratadonCostReductionEffect(StratadonCostReductionEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + return false; + } + + @Override + public StratadonCostReductionEffect copy() { + return new StratadonCostReductionEffect(this); + } + +} From fe332ac3ef3c37c57d4c743a43579f71a8ee3ec7 Mon Sep 17 00:00:00 2001 From: Wehk Date: Sat, 4 Jul 2015 13:00:32 +0200 Subject: [PATCH 016/105] Added card: Boggart Forager --- .../src/mage/sets/lorwyn/BoggartForager.java | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/lorwyn/BoggartForager.java diff --git a/Mage.Sets/src/mage/sets/lorwyn/BoggartForager.java b/Mage.Sets/src/mage/sets/lorwyn/BoggartForager.java new file mode 100644 index 00000000000..864de5601ca --- /dev/null +++ b/Mage.Sets/src/mage/sets/lorwyn/BoggartForager.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.sets.lorwyn; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.ShuffleLibraryTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.target.TargetPlayer; + +/** + * + * @author Wehk + */ +public class BoggartForager extends CardImpl { + + public BoggartForager(UUID ownerId) { + super(ownerId, 154, "Boggart Forager", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{R}"); + this.expansionSetCode = "LRW"; + this.subtype.add("Goblin"); + this.subtype.add("Rogue"); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // {R}, Sacrifice Boggart Forager: Target player shuffles his or her library. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ShuffleLibraryTargetEffect(), new SacrificeSourceCost()); + ability.addManaCost(new ManaCostsImpl("{R}")); + ability.addTarget(new TargetPlayer()); + this.addAbility(ability); + } + + public BoggartForager(final BoggartForager card) { + super(card); + } + + @Override + public BoggartForager copy() { + return new BoggartForager(this); + } +} From ccecc930b037ba03f75d7534f225ac8905402f84 Mon Sep 17 00:00:00 2001 From: Wehk Date: Sat, 4 Jul 2015 13:02:30 +0200 Subject: [PATCH 017/105] Added card: Exiled Boggart --- .../src/mage/sets/lorwyn/ExiledBoggart.java | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/lorwyn/ExiledBoggart.java diff --git a/Mage.Sets/src/mage/sets/lorwyn/ExiledBoggart.java b/Mage.Sets/src/mage/sets/lorwyn/ExiledBoggart.java new file mode 100644 index 00000000000..6503fffe837 --- /dev/null +++ b/Mage.Sets/src/mage/sets/lorwyn/ExiledBoggart.java @@ -0,0 +1,64 @@ +/* + * 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.lorwyn; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.DiesTriggeredAbility; +import mage.abilities.effects.common.discard.DiscardControllerEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; + +/** + * + * @author Wehk + */ +public class ExiledBoggart extends CardImpl { + + public ExiledBoggart(UUID ownerId) { + super(ownerId, 109, "Exiled Boggart", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{1}{B}"); + this.expansionSetCode = "LRW"; + this.subtype.add("Goblin"); + this.subtype.add("Rogue"); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // When Exiled Boggart dies, discard a card. + this.addAbility(new DiesTriggeredAbility(new DiscardControllerEffect(1), false)); + } + + public ExiledBoggart(final ExiledBoggart card) { + super(card); + } + + @Override + public ExiledBoggart copy() { + return new ExiledBoggart(this); + } +} From 629f17cefb8b536b6660caf03cd7f800d27c5cf1 Mon Sep 17 00:00:00 2001 From: Wehk Date: Sat, 4 Jul 2015 13:03:09 +0200 Subject: [PATCH 018/105] Added card: Goldmeadow Dodger --- .../mage/sets/lorwyn/GoldmeadowDodger.java | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/lorwyn/GoldmeadowDodger.java diff --git a/Mage.Sets/src/mage/sets/lorwyn/GoldmeadowDodger.java b/Mage.Sets/src/mage/sets/lorwyn/GoldmeadowDodger.java new file mode 100644 index 00000000000..a957e34130f --- /dev/null +++ b/Mage.Sets/src/mage/sets/lorwyn/GoldmeadowDodger.java @@ -0,0 +1,75 @@ +/* + * 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.lorwyn; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesSourceEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.Filter; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.PowerPredicate; + +/** + * + * @author Wehk + */ +public class GoldmeadowDodger extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures with power 4 or greater"); + + static { + filter.add(new PowerPredicate(Filter.ComparisonType.GreaterThan, 3)); + } + + public GoldmeadowDodger(UUID ownerId) { + super(ownerId, 16, "Goldmeadow Dodger", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{W}"); + this.expansionSetCode = "LRW"; + this.subtype.add("Kithkin"); + this.subtype.add("Rogue"); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Goldmeadow Dodger can't be blocked by creatures with power 4 or greater. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantBeBlockedByCreaturesSourceEffect(filter, Duration.WhileOnBattlefield))); + } + + public GoldmeadowDodger(final GoldmeadowDodger card) { + super(card); + } + + @Override + public GoldmeadowDodger copy() { + return new GoldmeadowDodger(this); + } +} From 502bd3e6fd475ad58435b7d4011118e5b5950c24 Mon Sep 17 00:00:00 2001 From: Wehk Date: Sat, 4 Jul 2015 13:04:28 +0200 Subject: [PATCH 019/105] Added card: Rootgrapple --- .../src/mage/sets/lorwyn/Rootgrapple.java | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/lorwyn/Rootgrapple.java diff --git a/Mage.Sets/src/mage/sets/lorwyn/Rootgrapple.java b/Mage.Sets/src/mage/sets/lorwyn/Rootgrapple.java new file mode 100644 index 00000000000..bf4fcc4c962 --- /dev/null +++ b/Mage.Sets/src/mage/sets/lorwyn/Rootgrapple.java @@ -0,0 +1,83 @@ +/* + * 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.lorwyn; + +import java.util.UUID; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.FilterPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.target.TargetPermanent; + +/** + * + * @author Wehk + */ +public class Rootgrapple extends CardImpl { + + private static final FilterPermanent filterNoncreature = new FilterPermanent("noncreature permanent"); + private static final FilterPermanent filterTreefolk = new FilterPermanent("If you control a Treefolk,"); + + static { + filterNoncreature.add(Predicates.not(new CardTypePredicate(CardType.CREATURE))); + } + static { + filterTreefolk.add(new SubtypePredicate("Treefolk")); + } + + public Rootgrapple(UUID ownerId) { + super(ownerId, 234, "Rootgrapple", Rarity.COMMON, new CardType[]{CardType.TRIBAL, CardType.INSTANT}, "{4}{G}"); + this.expansionSetCode = "LRW"; + this.subtype.add("Treefolk"); + + // Destroy target noncreature permanent. + this.getSpellAbility().addTarget(new TargetPermanent(filterNoncreature)); + this.getSpellAbility().addEffect(new DestroyTargetEffect()); + + // If you control a Treefolk, draw a card. + this.getSpellAbility().addEffect(new ConditionalOneShotEffect(new DrawCardSourceControllerEffect(1), + new PermanentsOnTheBattlefieldCondition(filterTreefolk, PermanentsOnTheBattlefieldCondition.CountType.MORE_THAN, 0), + "If you control a Treefolk, draw a card")); + } + + public Rootgrapple(final Rootgrapple card) { + super(card); + } + + @Override + public Rootgrapple copy() { + return new Rootgrapple(this); + } +} From d280a015f4ac96ce1b1dd958df60e03bb6dcde16 Mon Sep 17 00:00:00 2001 From: Wehk Date: Sat, 4 Jul 2015 13:05:13 +0200 Subject: [PATCH 020/105] Added card: Ribbons of Night --- .../src/mage/sets/ravnica/RibbonsOfNight.java | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/ravnica/RibbonsOfNight.java diff --git a/Mage.Sets/src/mage/sets/ravnica/RibbonsOfNight.java b/Mage.Sets/src/mage/sets/ravnica/RibbonsOfNight.java new file mode 100644 index 00000000000..b43344bdc6e --- /dev/null +++ b/Mage.Sets/src/mage/sets/ravnica/RibbonsOfNight.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.ravnica; + +import java.util.UUID; +import mage.abilities.condition.common.ManaWasSpentCondition; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.GainLifeEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.ColoredManaSymbol; +import mage.constants.Rarity; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author Wehk + */ +public class RibbonsOfNight extends CardImpl { + + public RibbonsOfNight(UUID ownerId) { + super(ownerId, 101, "Ribbons of Night", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{4}{B}"); + this.expansionSetCode = "RAV"; + + // Ribbons of Night deals 4 damage to target creature + Effect effect = new DamageTargetEffect(4); + effect.setText("{this} deals 4 damage to target creature"); + this.getSpellAbility().addEffect(effect); + + // and you gain 4 life. + effect = new GainLifeEffect(4); + effect.setText("and you gain 4 life"); + this.getSpellAbility().addEffect(effect); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + + //If {U} was spent to cast Ribbons of Night, draw a card. + this.getSpellAbility().addEffect(new ConditionalOneShotEffect( + new DrawCardSourceControllerEffect(1), + new ManaWasSpentCondition(ColoredManaSymbol.U), "If {U} was spent to cast {this}, draw a card")); + } + + public RibbonsOfNight(final RibbonsOfNight card) { + super(card); + } + + @Override + public RibbonsOfNight copy() { + return new RibbonsOfNight(this); + } +} From eddd451f80327b6b10cc658daefb159a5fee323e Mon Sep 17 00:00:00 2001 From: Wehk Date: Sat, 4 Jul 2015 13:05:36 +0200 Subject: [PATCH 021/105] Added card: Sewerdreg --- .../src/mage/sets/ravnica/Sewerdreg.java | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/ravnica/Sewerdreg.java diff --git a/Mage.Sets/src/mage/sets/ravnica/Sewerdreg.java b/Mage.Sets/src/mage/sets/ravnica/Sewerdreg.java new file mode 100644 index 00000000000..14d8fe08607 --- /dev/null +++ b/Mage.Sets/src/mage/sets/ravnica/Sewerdreg.java @@ -0,0 +1,73 @@ +/* + * 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.ravnica; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.effects.common.ExileTargetEffect; +import mage.abilities.keyword.SwampwalkAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.target.common.TargetCardInGraveyard; + +/** + * + * @author Wehk + */ +public class Sewerdreg extends CardImpl { + + public Sewerdreg(UUID ownerId) { + super(ownerId, 104, "Sewerdreg", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{3}{B}{B}"); + this.expansionSetCode = "RAV"; + this.subtype.add("Spirit"); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Swampwalk + this.addAbility(new SwampwalkAbility()); + + // Sacrifice Sewerdreg: Exile target card from a graveyard. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ExileTargetEffect(), new SacrificeSourceCost()); + ability.addTarget(new TargetCardInGraveyard()); + this.addAbility(ability); + } + + public Sewerdreg(final Sewerdreg card) { + super(card); + } + + @Override + public Sewerdreg copy() { + return new Sewerdreg(this); + } +} From 24e5d4010893a13c39e4fdbbbe2b41707661e082 Mon Sep 17 00:00:00 2001 From: Wehk Date: Sat, 4 Jul 2015 13:06:21 +0200 Subject: [PATCH 022/105] Added card: Vindictive Mob --- .../src/mage/sets/ravnica/VindictiveMob.java | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/ravnica/VindictiveMob.java diff --git a/Mage.Sets/src/mage/sets/ravnica/VindictiveMob.java b/Mage.Sets/src/mage/sets/ravnica/VindictiveMob.java new file mode 100644 index 00000000000..cbbc0ab2a3e --- /dev/null +++ b/Mage.Sets/src/mage/sets/ravnica/VindictiveMob.java @@ -0,0 +1,79 @@ +/* + * 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.ravnica; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.SacrificeControllerEffect; +import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesSourceEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; + +/** + * + * @author Wehk + */ +public class VindictiveMob extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("can't be blocked by Saporlings"); + + static { + filter.add(new SubtypePredicate("Saporling")); + } + + public VindictiveMob(UUID ownerId) { + super(ownerId, 112, "Vindictive Mob", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{4}{B}{B}"); + this.expansionSetCode = "RAV"; + this.subtype.add("Human"); + this.subtype.add("Berserker"); + this.power = new MageInt(5); + this.toughness = new MageInt(5); + + // When Vindictive Mob enters the battlefield, sacrifice a creature. + this.addAbility(new EntersBattlefieldTriggeredAbility(new SacrificeControllerEffect(new FilterCreaturePermanent(), 1, null))); + + // Vindictive Mob can't be blocked by Saprolings. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantBeBlockedByCreaturesSourceEffect(filter, Duration.WhileOnBattlefield))); + } + + public VindictiveMob(final VindictiveMob card) { + super(card); + } + + @Override + public VindictiveMob copy() { + return new VindictiveMob(this); + } +} From 4f8de2d6a9991896c9ec0e0f2c2a25f891591096 Mon Sep 17 00:00:00 2001 From: Wehk Date: Sat, 4 Jul 2015 13:16:35 +0200 Subject: [PATCH 023/105] Corrected Kytheon's Irregulars' Creature Type Changed creature type to "Soldier" from "Solder". --- Mage.Sets/src/mage/sets/magicorigins/KytheonsIrregulars.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mage.Sets/src/mage/sets/magicorigins/KytheonsIrregulars.java b/Mage.Sets/src/mage/sets/magicorigins/KytheonsIrregulars.java index cb9133fa199..7a33f22e3cd 100644 --- a/Mage.Sets/src/mage/sets/magicorigins/KytheonsIrregulars.java +++ b/Mage.Sets/src/mage/sets/magicorigins/KytheonsIrregulars.java @@ -50,7 +50,7 @@ public class KytheonsIrregulars extends CardImpl { super(ownerId, 24, "Kytheon's Irregulars", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{2}{W}{W}"); this.expansionSetCode = "ORI"; this.subtype.add("Human"); - this.subtype.add("Solder"); + this.subtype.add("Soldier"); this.power = new MageInt(4); this.toughness = new MageInt(3); From 13f0a90258fd796392205f4a380b87083e9b5f53 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sat, 4 Jul 2015 15:37:22 +0200 Subject: [PATCH 024/105] Fixed build bug of Server Console project. --- Mage.Server.Console/pom.xml | 47 ------------------------------------- 1 file changed, 47 deletions(-) diff --git a/Mage.Server.Console/pom.xml b/Mage.Server.Console/pom.xml index 01aa84df340..839ee4bfd6f 100644 --- a/Mage.Server.Console/pom.xml +++ b/Mage.Server.Console/pom.xml @@ -31,51 +31,4 @@ test - - - - - org.apache.maven.plugins - maven-compiler-plugin - - - org.apache.maven.plugins - maven-install-plugin - 2.5.2 - - - maven-resources-plugin - - UTF-8 - - - - maven-jar-plugin - - - ${manifest.file} - - true - mage.server.console.ConsoleFrame - - - - - - maven-assembly-plugin - - false - - src/main/assembly/distribution.xml - - - - - - mage-console - - - - src/main/resources/META-INF/MANIFEST.MF - From b481b2623f57ccf789dffa5e9f422bbd8d6b2288 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sat, 4 Jul 2015 15:42:53 +0200 Subject: [PATCH 025/105] * Erebos's Titan - Fixed that the ability triggers from graveyard instead from battlefield. --- Mage.Sets/src/mage/sets/magicorigins/ErebossTitan.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mage.Sets/src/mage/sets/magicorigins/ErebossTitan.java b/Mage.Sets/src/mage/sets/magicorigins/ErebossTitan.java index 6d4d632fc99..cb87647fbf0 100644 --- a/Mage.Sets/src/mage/sets/magicorigins/ErebossTitan.java +++ b/Mage.Sets/src/mage/sets/magicorigins/ErebossTitan.java @@ -95,7 +95,7 @@ public class ErebossTitan extends CardImpl { class ErebossTitanTriggeredAbility extends TriggeredAbilityImpl { public ErebossTitanTriggeredAbility() { - super(Zone.BATTLEFIELD, new DoIfCostPaid(new ReturnSourceFromGraveyardToHandEffect(), new DiscardCardCost())); + super(Zone.GRAVEYARD, new DoIfCostPaid(new ReturnSourceFromGraveyardToHandEffect(), new DiscardCardCost())); } public ErebossTitanTriggeredAbility(final ErebossTitanTriggeredAbility ability) { From 06a2fe68a8a640c774613e262615e72a9f0ef8ea Mon Sep 17 00:00:00 2001 From: Wehk Date: Sat, 4 Jul 2015 15:55:09 +0200 Subject: [PATCH 026/105] Merged static blocks --- Mage.Sets/src/mage/sets/lorwyn/Rootgrapple.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/Mage.Sets/src/mage/sets/lorwyn/Rootgrapple.java b/Mage.Sets/src/mage/sets/lorwyn/Rootgrapple.java index bf4fcc4c962..03d45de6570 100644 --- a/Mage.Sets/src/mage/sets/lorwyn/Rootgrapple.java +++ b/Mage.Sets/src/mage/sets/lorwyn/Rootgrapple.java @@ -52,8 +52,6 @@ public class Rootgrapple extends CardImpl { static { filterNoncreature.add(Predicates.not(new CardTypePredicate(CardType.CREATURE))); - } - static { filterTreefolk.add(new SubtypePredicate("Treefolk")); } From 6b9af161c4b3953da9d38afae97e6d7501dd9fd4 Mon Sep 17 00:00:00 2001 From: Wehk Date: Sat, 4 Jul 2015 15:57:39 +0200 Subject: [PATCH 027/105] Omitted superfluous setText --- Mage.Sets/src/mage/sets/ravnica/RibbonsOfNight.java | 1 - 1 file changed, 1 deletion(-) diff --git a/Mage.Sets/src/mage/sets/ravnica/RibbonsOfNight.java b/Mage.Sets/src/mage/sets/ravnica/RibbonsOfNight.java index b43344bdc6e..a1c03587689 100644 --- a/Mage.Sets/src/mage/sets/ravnica/RibbonsOfNight.java +++ b/Mage.Sets/src/mage/sets/ravnica/RibbonsOfNight.java @@ -52,7 +52,6 @@ public class RibbonsOfNight extends CardImpl { // Ribbons of Night deals 4 damage to target creature Effect effect = new DamageTargetEffect(4); - effect.setText("{this} deals 4 damage to target creature"); this.getSpellAbility().addEffect(effect); // and you gain 4 life. From 8de4987b80d75df421184cb7aab662a69ed17514 Mon Sep 17 00:00:00 2001 From: Wehk Date: Sat, 4 Jul 2015 16:02:28 +0200 Subject: [PATCH 028/105] Fixed saprolings typo --- Mage.Sets/src/mage/sets/ravnica/VindictiveMob.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Mage.Sets/src/mage/sets/ravnica/VindictiveMob.java b/Mage.Sets/src/mage/sets/ravnica/VindictiveMob.java index cbbc0ab2a3e..f2b57af28e7 100644 --- a/Mage.Sets/src/mage/sets/ravnica/VindictiveMob.java +++ b/Mage.Sets/src/mage/sets/ravnica/VindictiveMob.java @@ -47,10 +47,10 @@ import mage.filter.predicate.mageobject.SubtypePredicate; */ public class VindictiveMob extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("can't be blocked by Saporlings"); + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("can't be blocked by Saprolings"); static { - filter.add(new SubtypePredicate("Saporling")); + filter.add(new SubtypePredicate("Saproling")); } public VindictiveMob(UUID ownerId) { From 40421cb54f2a316c61d0246c100512bdd19143d3 Mon Sep 17 00:00:00 2001 From: Wehk Date: Sat, 4 Jul 2015 16:07:02 +0200 Subject: [PATCH 029/105] Swapped cost order --- Mage.Sets/src/mage/sets/lorwyn/BoggartForager.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Mage.Sets/src/mage/sets/lorwyn/BoggartForager.java b/Mage.Sets/src/mage/sets/lorwyn/BoggartForager.java index 864de5601ca..022a18d0646 100644 --- a/Mage.Sets/src/mage/sets/lorwyn/BoggartForager.java +++ b/Mage.Sets/src/mage/sets/lorwyn/BoggartForager.java @@ -55,8 +55,8 @@ public class BoggartForager extends CardImpl { this.toughness = new MageInt(1); // {R}, Sacrifice Boggart Forager: Target player shuffles his or her library. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ShuffleLibraryTargetEffect(), new SacrificeSourceCost()); - ability.addManaCost(new ManaCostsImpl("{R}")); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ShuffleLibraryTargetEffect(), new ManaCostsImpl("{R}")); + ability.addCost(new SacrificeSourceCost()); ability.addTarget(new TargetPlayer()); this.addAbility(ability); } From 53e36c728c518476b764f9885cd2a26d2755f614 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sat, 4 Jul 2015 16:44:36 +0200 Subject: [PATCH 030/105] * Some minor fixed, error handling. --- .../java/mage/player/ai/ComputerPlayer.java | 3 +- .../abilities/effects/ContinuousEffects.java | 32 +++++++++++-------- Mage/src/mage/players/PlayerImpl.java | 2 -- 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java index 7b8b96edaeb..57c42140b9b 100644 --- a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java +++ b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java @@ -173,12 +173,11 @@ public class ComputerPlayer extends PlayerImpl implements Player { public ComputerPlayer(String name, RangeOfInfluence range) { super(name, range); - flagName = "computer"; human = false; userData = UserData.getDefaultUserDataView(); userData.setAvatarId(64); userData.setGroupId(UserGroup.COMPUTER.getGroupId()); - userData.setFlagName("Computer.png"); + userData.setFlagName("computer.png"); pickedCards = new ArrayList<>(); } diff --git a/Mage/src/mage/abilities/effects/ContinuousEffects.java b/Mage/src/mage/abilities/effects/ContinuousEffects.java index 9f8f39211e3..a6030dc051b 100644 --- a/Mage/src/mage/abilities/effects/ContinuousEffects.java +++ b/Mage/src/mage/abilities/effects/ContinuousEffects.java @@ -214,12 +214,16 @@ public class ContinuousEffects implements Serializable { case WhileOnStack: case WhileInGraveyard: HashSet abilities = layeredEffects.getAbility(effect.getId()); - for (Ability ability : abilities) { - // If e.g. triggerd abilities (non static) created the effect, the ability must not be in usable zone (e.g. Unearth giving Haste effect) - if (!(ability instanceof StaticAbility) || ability.isInUseableZone(game, null, null)) { - layerEffects.add(effect); - break; + if (abilities != null) { + for (Ability ability : abilities) { + // If e.g. triggerd abilities (non static) created the effect, the ability must not be in usable zone (e.g. Unearth giving Haste effect) + if (!(ability instanceof StaticAbility) || ability.isInUseableZone(game, null, null)) { + layerEffects.add(effect); + break; + } } + } else { + logger.error("No abilities for continuous effect: " + effect.toString()); } break; default: @@ -1058,14 +1062,16 @@ public class ContinuousEffects implements Serializable { private void setControllerForEffect(ContinuousEffectsList effects, UUID cardId, UUID controllerId) { for (Effect effect : effects) { HashSet abilities = effects.getAbility(effect.getId()); - for (Ability ability : abilities) { - if (ability.getSourceId() != null) { - if (ability.getSourceId().equals(cardId)) { - ability.setControllerId(controllerId); - } - } else { - if (!ability.getZone().equals(Zone.COMMAND)) { - logger.fatal(new StringBuilder("No sourceId Ability: ").append(ability)); + if (abilities != null) { + for (Ability ability : abilities) { + if (ability.getSourceId() != null) { + if (ability.getSourceId().equals(cardId)) { + ability.setControllerId(controllerId); + } + } else { + if (!ability.getZone().equals(Zone.COMMAND)) { + logger.fatal(new StringBuilder("No sourceId Ability: ").append(ability)); + } } } } diff --git a/Mage/src/mage/players/PlayerImpl.java b/Mage/src/mage/players/PlayerImpl.java index 9f04992fc8e..228cbb7de95 100644 --- a/Mage/src/mage/players/PlayerImpl.java +++ b/Mage/src/mage/players/PlayerImpl.java @@ -227,8 +227,6 @@ public abstract class PlayerImpl implements Player, Serializable { protected UserData userData; protected MatchPlayer matchPlayer; - protected String flagName; - /** * During some steps we can't play anything */ From 930f155d1090f8cc1c8bcabb1f0e09100aca0465 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sat, 4 Jul 2015 16:45:11 +0200 Subject: [PATCH 031/105] [ORI] Volcanic Rambler - Fixed wrong tap activation cost. --- Mage.Sets/src/mage/sets/magicorigins/VolcanicRambler.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Mage.Sets/src/mage/sets/magicorigins/VolcanicRambler.java b/Mage.Sets/src/mage/sets/magicorigins/VolcanicRambler.java index 17361c9fc80..76c7e7a90cb 100644 --- a/Mage.Sets/src/mage/sets/magicorigins/VolcanicRambler.java +++ b/Mage.Sets/src/mage/sets/magicorigins/VolcanicRambler.java @@ -31,7 +31,6 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; -import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.common.DamageTargetEffect; import mage.cards.CardImpl; @@ -55,9 +54,8 @@ public class VolcanicRambler extends CardImpl { // {2}{R}: Volcanic Rambler deals 1 damage to target player. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(1), new ManaCostsImpl("{2}{R}")); - ability.addCost(new TapSourceCost()); ability.addTarget(new TargetPlayer()); - this.addAbility(ability); + this.addAbility(ability); } public VolcanicRambler(final VolcanicRambler card) { From aaef4b7cafaae129ee03ff51aac0bbb6992f739d Mon Sep 17 00:00:00 2001 From: LoneFox Date: Sat, 4 Jul 2015 17:49:28 +0300 Subject: [PATCH 032/105] Implement cards: Alchemist's Vial, Guardian Automaton, Ramroller, and War Horn --- .../sets/magicorigins/AlchemistsVial.java | 75 +++++++++++++++++ .../sets/magicorigins/GuardianAutomaton.java | 64 ++++++++++++++ .../src/mage/sets/magicorigins/Ramroller.java | 84 +++++++++++++++++++ .../src/mage/sets/magicorigins/WarHorn.java | 64 ++++++++++++++ 4 files changed, 287 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/magicorigins/AlchemistsVial.java create mode 100644 Mage.Sets/src/mage/sets/magicorigins/GuardianAutomaton.java create mode 100644 Mage.Sets/src/mage/sets/magicorigins/Ramroller.java create mode 100644 Mage.Sets/src/mage/sets/magicorigins/WarHorn.java diff --git a/Mage.Sets/src/mage/sets/magicorigins/AlchemistsVial.java b/Mage.Sets/src/mage/sets/magicorigins/AlchemistsVial.java new file mode 100644 index 00000000000..84867bbeef7 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/AlchemistsVial.java @@ -0,0 +1,75 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.combat.CantAttackBlockTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LoneFox + + */ +public class AlchemistsVial extends CardImpl { + + public AlchemistsVial(UUID ownerId) { + super(ownerId, 220, "Alchemist's Vial", Rarity.COMMON, new CardType[]{CardType.ARTIFACT}, "{2}"); + this.expansionSetCode = "ORI"; + + // When Alchemist's Vial enters the battlefield, draw a card. + this.addAbility(new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1))); + // {1}, {T}: Sacrifice Alchemist's Vial: Target creature can't attack or block this turn. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CantAttackBlockTargetEffect(Duration.EndOfTurn), new ManaCostsImpl("{1}")); + ability.addCost(new TapSourceCost()); + ability.addCost(new SacrificeSourceCost()); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + public AlchemistsVial(final AlchemistsVial card) { + super(card); + } + + @Override + public AlchemistsVial copy() { + return new AlchemistsVial(this); + } +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/GuardianAutomaton.java b/Mage.Sets/src/mage/sets/magicorigins/GuardianAutomaton.java new file mode 100644 index 00000000000..3e66bafc19f --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/GuardianAutomaton.java @@ -0,0 +1,64 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.MageInt; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.abilities.common.DiesTriggeredAbility; +import mage.abilities.effects.common.GainLifeEffect; + +/** + * + * @author LoneFox + + */ +public class GuardianAutomaton extends CardImpl { + + public GuardianAutomaton(UUID ownerId) { + super(ownerId, 227, "Guardian Automaton", Rarity.COMMON, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{4}"); + this.expansionSetCode = "ORI"; + this.subtype.add("Construct"); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // When Guardian Automaton dies, you gain 3 life. + this.addAbility(new DiesTriggeredAbility(new GainLifeEffect(3))); + } + + public GuardianAutomaton(final GuardianAutomaton card) { + super(card); + } + + @Override + public GuardianAutomaton copy() { + return new GuardianAutomaton(this); + } +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/Ramroller.java b/Mage.Sets/src/mage/sets/magicorigins/Ramroller.java new file mode 100644 index 00000000000..2a7c2083899 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/Ramroller.java @@ -0,0 +1,84 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.AttacksEachTurnStaticAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition.CountType; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterControlledArtifactPermanent; +import mage.filter.predicate.permanent.AnotherPredicate; + +/** + * + * @author LoneFox + + */ +public class Ramroller extends CardImpl { + + private static final FilterControlledArtifactPermanent filter = new FilterControlledArtifactPermanent(); + + static { + filter.add(new AnotherPredicate()); + } + + public Ramroller(UUID ownerId) { + super(ownerId, 237, "Ramroller", Rarity.UNCOMMON, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{3}"); + this.expansionSetCode = "ORI"; + this.subtype.add("Juggernaut"); + this.power = new MageInt(2); + this.toughness = new MageInt(3); + + // Ramroller attacks each turn if able. + this.addAbility(new AttacksEachTurnStaticAbility()); + // Ramroller gets +2/+0 as long as you control another artifact. + Condition condition = new PermanentsOnTheBattlefieldCondition(filter, CountType.MORE_THAN, 0); + ConditionalContinuousEffect effect = new ConditionalContinuousEffect(new BoostSourceEffect(2, 0, + Duration.WhileOnBattlefield), condition, "{this} gets +2/+0 as long as you control another artifact."); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); + } + + public Ramroller(final Ramroller card) { + super(card); + } + + @Override + public Ramroller copy() { + return new Ramroller(this); + } +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/WarHorn.java b/Mage.Sets/src/mage/sets/magicorigins/WarHorn.java new file mode 100644 index 00000000000..cf29b99c74b --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/WarHorn.java @@ -0,0 +1,64 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterAttackingCreature; + +/** + * + * @author LoneFox + + */ +public class WarHorn extends CardImpl { + + public WarHorn(UUID ownerId) { + super(ownerId, 243, "War Horn", Rarity.UNCOMMON, new CardType[]{CardType.ARTIFACT}, "{3}"); + this.expansionSetCode = "ORI"; + + // Attacking creatures you control get +1/+0. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostControlledEffect(1, 0, + Duration.WhileOnBattlefield, new FilterAttackingCreature(), false))); + } + + public WarHorn(final WarHorn card) { + super(card); + } + + @Override + public WarHorn copy() { + return new WarHorn(this); + } +} From a027a4d190051d2962107c0e119659f00b89119a Mon Sep 17 00:00:00 2001 From: LoneFox Date: Sat, 4 Jul 2015 18:52:28 +0300 Subject: [PATCH 033/105] Fix the card number of Relic Seeker --- Mage.Sets/src/mage/sets/magicorigins/RelicSeeker.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Mage.Sets/src/mage/sets/magicorigins/RelicSeeker.java b/Mage.Sets/src/mage/sets/magicorigins/RelicSeeker.java index 612b08ceacb..c23c289ab6b 100644 --- a/Mage.Sets/src/mage/sets/magicorigins/RelicSeeker.java +++ b/Mage.Sets/src/mage/sets/magicorigins/RelicSeeker.java @@ -45,16 +45,16 @@ import mage.target.common.TargetCardInLibrary; * @author LevelX2 */ public class RelicSeeker extends CardImpl { - + private static final FilterCard filter = new FilterCard("an Equipment card"); static { filter.add(new CardTypePredicate(CardType.ARTIFACT)); filter.add(new SubtypePredicate("Equipment")); } - + public RelicSeeker(UUID ownerId) { - super(ownerId, 107, "Relic Seeker", Rarity.SPECIAL, new CardType[]{CardType.CREATURE}, "{1}{W}"); + super(ownerId, 29, "Relic Seeker", Rarity.SPECIAL, new CardType[]{CardType.CREATURE}, "{1}{W}"); this.expansionSetCode = "ORI"; this.subtype.add("Human"); this.subtype.add("Soldier"); @@ -63,7 +63,7 @@ public class RelicSeeker extends CardImpl { // Renown 1 this.addAbility(new RenownAbility(1)); - + // When Relic Seeker becomes renowned, you may search your library for an Equipment card, reveal it, put it into your hand, then shuffle your library. TargetCardInLibrary target = new TargetCardInLibrary(1, 1, filter); this.addAbility(new BecomesRenownSourceTriggeredAbility(new SearchLibraryPutInHandEffect(target, true, true), true)); From e8230dd51e16a185f45c767e763609dd70bfbf6f Mon Sep 17 00:00:00 2001 From: LoneFox Date: Sat, 4 Jul 2015 18:52:55 +0300 Subject: [PATCH 034/105] Implement cards: Consecrated by Blood, Eyeblight Massacre, Fetid Imp, and Macabre Waltz --- .../mage/sets/dissension/MacabreWaltz.java | 53 ++++++++++ .../sets/magicorigins/ConsecratedByBlood.java | 99 +++++++++++++++++++ .../sets/magicorigins/EyeblightMassacre.java | 69 +++++++++++++ .../src/mage/sets/magicorigins/FetidImp.java | 71 +++++++++++++ .../mage/sets/magicorigins/MacabreWaltz.java | 65 ++++++++++++ 5 files changed, 357 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/dissension/MacabreWaltz.java create mode 100644 Mage.Sets/src/mage/sets/magicorigins/ConsecratedByBlood.java create mode 100644 Mage.Sets/src/mage/sets/magicorigins/EyeblightMassacre.java create mode 100644 Mage.Sets/src/mage/sets/magicorigins/FetidImp.java create mode 100644 Mage.Sets/src/mage/sets/magicorigins/MacabreWaltz.java diff --git a/Mage.Sets/src/mage/sets/dissension/MacabreWaltz.java b/Mage.Sets/src/mage/sets/dissension/MacabreWaltz.java new file mode 100644 index 00000000000..90b164516d8 --- /dev/null +++ b/Mage.Sets/src/mage/sets/dissension/MacabreWaltz.java @@ -0,0 +1,53 @@ +/* + * 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.dissension; + +import java.util.UUID; + +/** + * + * @author LoneFox + + */ +public class MacabreWaltz extends mage.sets.magicorigins.MacabreWaltz { + + public MacabreWaltz(UUID ownerId) { + super(ownerId); + this.cardNumber = 47; + this.expansionSetCode = "DIS"; + } + + public MacabreWaltz(final MacabreWaltz card) { + super(card); + } + + @Override + public MacabreWaltz copy() { + return new MacabreWaltz(this); + } +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/ConsecratedByBlood.java b/Mage.Sets/src/mage/sets/magicorigins/ConsecratedByBlood.java new file mode 100644 index 00000000000..db3331a17ff --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/ConsecratedByBlood.java @@ -0,0 +1,99 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.RegenerateSourceEffect; +import mage.abilities.effects.common.continuous.BoostEnchantedEffect; +import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.constants.AttachmentType; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.permanent.AnotherPredicate; +import mage.target.TargetPermanent; +import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LoneFox + + */ +public class ConsecratedByBlood extends CardImpl { + + private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("two other creatures"); + + static { + filter.add(new AnotherPredicate()); + } + + public ConsecratedByBlood(UUID ownerId) { + super(ownerId, 87, "Consecrated By Blood", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT}, "{2}{B}{B}"); + this.expansionSetCode = "ORI"; + this.subtype.add("Aura"); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.Benefit)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + // Enchanted creature gets +2/+2 and has flying and "Sacrifice two other creatures: Regenerate this creature." + ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEnchantedEffect(2, 2, Duration.WhileOnBattlefield)); + Effect effect = new GainAbilityAttachedEffect(FlyingAbility.getInstance(), AttachmentType.AURA); + effect.setText("and has flying"); + ability.addEffect(effect); + effect = new GainAbilityAttachedEffect(new SimpleActivatedAbility(Zone.BATTLEFIELD, new RegenerateSourceEffect(), + new SacrificeTargetCost(new TargetControlledCreaturePermanent(2, 2, filter, true))), AttachmentType.AURA); + effect.setText("and \"Sacrifice two other creatures: Regenerate this creature.\""); + ability.addEffect(effect); + this.addAbility(ability); + } + + public ConsecratedByBlood(final ConsecratedByBlood card) { + super(card); + } + + @Override + public ConsecratedByBlood copy() { + return new ConsecratedByBlood(this); + } +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/EyeblightMassacre.java b/Mage.Sets/src/mage/sets/magicorigins/EyeblightMassacre.java new file mode 100644 index 00000000000..66e10dee682 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/EyeblightMassacre.java @@ -0,0 +1,69 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.abilities.effects.common.continuous.BoostAllEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.SubtypePredicate; + +/** + * + * @author LoneFox + + */ +public class EyeblightMassacre extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Non-Elf creatures"); + + static { + filter.add(Predicates.not(new SubtypePredicate("Elf"))); + } + + public EyeblightMassacre(UUID ownerId) { + super(ownerId, 96, "Eyeblight Massacre", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{2}{B}{B}"); + this.expansionSetCode = "ORI"; + + // Non-Elf creatures get -2/-2 until end of turn. + this.getSpellAbility().addEffect(new BoostAllEffect(-2, -2, Duration.EndOfTurn, filter, false)); + } + + public EyeblightMassacre(final EyeblightMassacre card) { + super(card); + } + + @Override + public EyeblightMassacre copy() { + return new EyeblightMassacre(this); + } +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/FetidImp.java b/Mage.Sets/src/mage/sets/magicorigins/FetidImp.java new file mode 100644 index 00000000000..8e7701c598d --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/FetidImp.java @@ -0,0 +1,71 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.keyword.DeathtouchAbility; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; + +/** + * + * @author LoneFox + + */ +public class FetidImp extends CardImpl { + + public FetidImp(UUID ownerId) { + super(ownerId, 97, "Fetid Imp", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{1}{B}"); + this.expansionSetCode = "ORI"; + this.subtype.add("Imp"); + this.power = new MageInt(1); + this.toughness = new MageInt(2); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + // {B}: Fetid Imp gains deathtouch until end of turn. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new GainAbilitySourceEffect(DeathtouchAbility.getInstance(), Duration.EndOfTurn), new ManaCostsImpl("{B}"))); + } + + public FetidImp(final FetidImp card) { + super(card); + } + + @Override + public FetidImp copy() { + return new FetidImp(this); + } +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/MacabreWaltz.java b/Mage.Sets/src/mage/sets/magicorigins/MacabreWaltz.java new file mode 100644 index 00000000000..5030b5290a8 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/MacabreWaltz.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.magicorigins; + + +import java.util.UUID; +import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect; +import mage.abilities.effects.common.discard.DiscardControllerEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.common.FilterCreatureCard; +import mage.target.common.TargetCardInYourGraveyard; + +/** + * + * @author LoneFox + + */ +public class MacabreWaltz extends CardImpl { + + public MacabreWaltz(UUID ownerId) { + super(ownerId, 107, "Macabre Waltz", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{1}{B}"); + this.expansionSetCode = "ORI"; + + // Return up to two target creature cards from your graveyard to your hand, then discard a card. + this.getSpellAbility().addEffect(new ReturnFromGraveyardToHandTargetEffect()); + this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(0, 2, new FilterCreatureCard("creature cards from your graveyard"))); + this.getSpellAbility().addEffect(new DiscardControllerEffect(1)); + } + + public MacabreWaltz(final MacabreWaltz card) { + super(card); + } + + @Override + public MacabreWaltz copy() { + return new MacabreWaltz(this); + } +} From d33f85d04aa465e964355c18b6c5f51544f0d62b Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sat, 4 Jul 2015 19:26:48 +0200 Subject: [PATCH 035/105] Fixed wrong name for download of Kothophed, Soul Hoarder image. --- .../dl/sources/MythicspoilerComSource.java | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MythicspoilerComSource.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MythicspoilerComSource.java index 007e208be20..0728084c111 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MythicspoilerComSource.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MythicspoilerComSource.java @@ -80,6 +80,7 @@ public class MythicspoilerComSource implements CardImageSource { cardNameAliases.put("THS-purphorosemissary", "purphorossemissary"); cardNameAliases.put("THS-soldierofpantheon", "soldierofthepantheon"); cardNameAliases.put("THS-vulpinegolaith", "vulpinegoliath"); + cardNameAliases.put("ORI-kothopedhoarderofsouls", "kothophedsoulhoarder"); } private Map getSetLinks(String cardSet) { @@ -130,17 +131,17 @@ public class MythicspoilerComSource implements CardImageSource { if (cardNameAliases.containsKey(cardSet + "-" + cardName)) { cardName = cardNameAliases.get(cardSet + "-" + cardName); } - if (cardName.endsWith("1") || cardName.endsWith("2") || cardName.endsWith("3")|| cardName.endsWith("4")|| cardName.endsWith("5")) { - if (!cardName.startsWith("forest") && - !cardName.startsWith("swamp") && - !cardName.startsWith("mountain") && - !cardName.startsWith("island") && - !cardName.startsWith("plains")) { + if (cardName.endsWith("1") || cardName.endsWith("2") || cardName.endsWith("3") || cardName.endsWith("4") || cardName.endsWith("5")) { + if (!cardName.startsWith("forest") + && !cardName.startsWith("swamp") + && !cardName.startsWith("mountain") + && !cardName.startsWith("island") + && !cardName.startsWith("plains")) { cardName = cardName.substring(0, cardName.length() - 1); - } + } } setLinks.put(cardName, baseUrl + cardLink); - } + } } } @@ -149,7 +150,7 @@ public class MythicspoilerComSource implements CardImageSource { System.out.println("Exception when parsing the mythicspoiler page: " + ex.getMessage()); } return setLinks; - } + } @Override public String generateURL(CardDownloadData card) throws Exception { From 1782832d82e8532249ea864de755c2a39d828dea Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sat, 4 Jul 2015 19:27:08 +0200 Subject: [PATCH 036/105] Fixed rule text generation of Renown. --- .../mage/abilities/keyword/RenownAbility.java | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/Mage/src/mage/abilities/keyword/RenownAbility.java b/Mage/src/mage/abilities/keyword/RenownAbility.java index b6920d6d946..f6f3f778257 100644 --- a/Mage/src/mage/abilities/keyword/RenownAbility.java +++ b/Mage/src/mage/abilities/keyword/RenownAbility.java @@ -22,12 +22,10 @@ import mage.util.CardUtil; * * @author LevelX2 */ - - public class RenownAbility extends TriggeredAbilityImpl { private int renownValue; - + public RenownAbility(int renownValue) { super(Zone.BATTLEFIELD, new BecomeRenownSourceEffect(renownValue), false); this.renownValue = renownValue; @@ -50,7 +48,7 @@ public class RenownAbility extends TriggeredAbilityImpl { @Override public boolean checkInterveningIfClause(Game game) { - return getSourceObject(game) != null && !((Permanent)getSourceObject(game)).isRenown(); + return getSourceObject(game) != null && !((Permanent) getSourceObject(game)).isRenown(); } @Override @@ -59,11 +57,6 @@ public class RenownAbility extends TriggeredAbilityImpl { && ((DamagedPlayerEvent) event).isCombatDamage(); } - @Override - public String getRule() { - return "Whenever {this} deals combat damage to a player, " + super.getRule(); - } - public int getRenownValue() { return renownValue; } @@ -95,7 +88,7 @@ class BecomeRenownSourceEffect extends OneShotEffect { if (renownValue == Integer.MAX_VALUE) { renownValue = source.getManaCostsToPay().getX(); } - new AddCountersSourceEffect(CounterType.P1P1.createInstance(renownValue),true).apply(game, source); + new AddCountersSourceEffect(CounterType.P1P1.createInstance(renownValue), true).apply(game, source); permanent.setRenown(true); game.fireEvent(GameEvent.getEvent(GameEvent.EventType.BECOMES_RENOWN, source.getSourceId(), source.getSourceId(), source.getControllerId(), renownValue)); return true; @@ -106,9 +99,9 @@ class BecomeRenownSourceEffect extends OneShotEffect { private String setText(int renownValue) { // Renown 1 (When this creature deals combat damage to a player, if it isn't renowned, put a +1/+1 counter on it and it becomes renowned.) StringBuilder sb = new StringBuilder("Renown "); - sb.append(renownValue == Integer.MAX_VALUE ? "X":renownValue) + sb.append(renownValue == Integer.MAX_VALUE ? "X" : renownValue) .append(". (When this creature deals combat damage to a player, if it isn't renowned, put ") - .append(renownValue == Integer.MAX_VALUE ? "X":CardUtil.numberToText(renownValue, "a")) + .append(renownValue == Integer.MAX_VALUE ? "X" : CardUtil.numberToText(renownValue, "a")) .append(" +1/+1 counter on it and it becomes renowned.)").toString(); return sb.toString(); } From 9ff08d979b67bb3d9ed2aa5693af87e43305e379 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sat, 4 Jul 2015 19:27:24 +0200 Subject: [PATCH 037/105] Some minor changes. --- .../betrayersofkamigawa/PatronOfTheMoon.java | 15 ++--- .../sets/scarsofmirrodin/GenesisWave.java | 31 +++++----- .../mage/sets/shardsofalara/BantPanorama.java | 11 ++-- .../src/mage/sets/zendikar/SummoningTrap.java | 57 +++++-------------- .../filter/common/FilterBasicLandCard.java | 17 +++--- 5 files changed, 55 insertions(+), 76 deletions(-) diff --git a/Mage.Sets/src/mage/sets/betrayersofkamigawa/PatronOfTheMoon.java b/Mage.Sets/src/mage/sets/betrayersofkamigawa/PatronOfTheMoon.java index 6dcb76e201c..826408a71be 100644 --- a/Mage.Sets/src/mage/sets/betrayersofkamigawa/PatronOfTheMoon.java +++ b/Mage.Sets/src/mage/sets/betrayersofkamigawa/PatronOfTheMoon.java @@ -28,9 +28,6 @@ package mage.sets.betrayersofkamigawa; import java.util.UUID; - -import mage.constants.CardType; -import mage.constants.Rarity; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; @@ -40,14 +37,16 @@ import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.OfferingAbility; import mage.cards.Card; import mage.cards.CardImpl; +import mage.constants.CardType; import mage.constants.Outcome; +import mage.constants.Rarity; import mage.constants.Zone; import mage.filter.common.FilterLandCard; import mage.game.Game; import mage.players.Player; +import mage.target.TargetCard; import mage.target.common.TargetCardInHand; - /** * @author LevelX2 */ @@ -70,7 +69,6 @@ public class PatronOfTheMoon extends CardImpl { // {1}: Put up to two land cards from your hand onto the battlefield tapped. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new PatronOfTheMoonEffect(), new ManaCostsImpl("{1}")); - ability.addTarget(new TargetCardInHand(0,2, new FilterLandCard())); this.addAbility(ability); } @@ -86,6 +84,7 @@ public class PatronOfTheMoon extends CardImpl { } class PatronOfTheMoonEffect extends OneShotEffect { + PatronOfTheMoonEffect() { super(Outcome.PutLandInPlay); staticText = "Put up to two land cards from your hand onto the battlefield tapped"; @@ -99,7 +98,9 @@ class PatronOfTheMoonEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { - for (UUID cardId : targetPointer.getTargets(game, source)) { + TargetCard target = new TargetCardInHand(0, 2, new FilterLandCard("up to two land cards to put onto the battlefield tapped")); + controller.chooseTarget(outcome, controller.getHand(), target, source, game); + for (UUID cardId : target.getTargets()) { Card card = game.getCard(cardId); if (card != null) { controller.putOntoBattlefieldWithInfo(card, game, Zone.HAND, source.getSourceId(), true); @@ -115,4 +116,4 @@ class PatronOfTheMoonEffect extends OneShotEffect { return new PatronOfTheMoonEffect(this); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/sets/scarsofmirrodin/GenesisWave.java b/Mage.Sets/src/mage/sets/scarsofmirrodin/GenesisWave.java index 1d54c0cce94..b20a7cfe247 100644 --- a/Mage.Sets/src/mage/sets/scarsofmirrodin/GenesisWave.java +++ b/Mage.Sets/src/mage/sets/scarsofmirrodin/GenesisWave.java @@ -1,16 +1,16 @@ /* * Copyright 2011 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 @@ -20,7 +20,7 @@ * 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. @@ -29,16 +29,16 @@ package mage.sets.scarsofmirrodin; import java.util.UUID; import mage.MageObject; -import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.Rarity; -import mage.constants.Zone; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; 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.Zone; import mage.filter.Filter.ComparisonType; import mage.filter.FilterCard; import mage.filter.predicate.Predicates; @@ -58,7 +58,6 @@ public class GenesisWave extends CardImpl { super(ownerId, 122, "Genesis Wave", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{X}{G}{G}{G}"); this.expansionSetCode = "SOM"; - // Reveal the top X cards of your library. You may put any number of permanent cards with converted mana // cost X or less from among them onto the battlefield. Then put all cards revealed this way that weren't // put onto the battlefield into your graveyard. @@ -102,21 +101,21 @@ class GenesisWaveEffect extends OneShotEffect { cards.add(card); } if (cards.size() > 0) { - controller.revealCards(sourceObject.getName(), cards, game); + controller.revealCards(sourceObject.getIdName(), cards, game); FilterCard filter = new FilterCard("cards with converted mana cost " + xValue + " or less to put onto the battlefield"); filter.add(new ConvertedManaCostPredicate(ComparisonType.LessThan, xValue + 1)); filter.add( Predicates.or(new CardTypePredicate(CardType.ARTIFACT), - new CardTypePredicate(CardType.CREATURE), - new CardTypePredicate(CardType.ENCHANTMENT), - new CardTypePredicate(CardType.LAND), - new CardTypePredicate(CardType.PLANESWALKER) + new CardTypePredicate(CardType.CREATURE), + new CardTypePredicate(CardType.ENCHANTMENT), + new CardTypePredicate(CardType.LAND), + new CardTypePredicate(CardType.PLANESWALKER) )); TargetCard target1 = new TargetCard(0, Integer.MAX_VALUE, Zone.LIBRARY, filter); target1.setRequired(false); controller.choose(Outcome.PutCardInPlay, cards, target1, game); - for (UUID cardId: target1.getTargets()) { + for (UUID cardId : target1.getTargets()) { Card card = cards.get(cardId, game); if (card != null) { cards.remove(card); diff --git a/Mage.Sets/src/mage/sets/shardsofalara/BantPanorama.java b/Mage.Sets/src/mage/sets/shardsofalara/BantPanorama.java index 99e9f76453b..d93ffc176f5 100644 --- a/Mage.Sets/src/mage/sets/shardsofalara/BantPanorama.java +++ b/Mage.Sets/src/mage/sets/shardsofalara/BantPanorama.java @@ -28,10 +28,6 @@ package mage.sets.shardsofalara; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.Rarity; -import mage.constants.Zone; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.SacrificeSourceCost; @@ -40,6 +36,10 @@ import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect; import mage.abilities.mana.ColorlessManaAbility; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; import mage.filter.FilterCard; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.CardTypePredicate; @@ -68,7 +68,10 @@ public class BantPanorama extends CardImpl { super(ownerId, 221, "Bant Panorama", Rarity.COMMON, new CardType[]{CardType.LAND}, ""); this.expansionSetCode = "ALA"; + // {T}: Add {1} to your mana pool. this.addAbility(new ColorlessManaAbility()); + + // {1}, {T}, Sacrifice Bant Panorama: Search your library for a basic Forest, Plains, or Island card and put it onto the battlefield tapped. Then shuffle your library. TargetCardInLibrary target = new TargetCardInLibrary(filter); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new SearchLibraryPutInPlayEffect(target, true, Outcome.PutLandInPlay), new GenericManaCost(1)); ability.addCost(new TapSourceCost()); diff --git a/Mage.Sets/src/mage/sets/zendikar/SummoningTrap.java b/Mage.Sets/src/mage/sets/zendikar/SummoningTrap.java index 6766cf3467c..e2fd1b88a42 100644 --- a/Mage.Sets/src/mage/sets/zendikar/SummoningTrap.java +++ b/Mage.Sets/src/mage/sets/zendikar/SummoningTrap.java @@ -43,7 +43,6 @@ import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.Cards; import mage.cards.CardsImpl; -import mage.filter.FilterCard; import mage.filter.common.FilterCreatureCard; import mage.game.Game; import mage.game.events.GameEvent; @@ -54,7 +53,7 @@ import mage.target.TargetCard; import mage.watchers.Watcher; /** - * + * * @author Rafbill */ public class SummoningTrap extends CardImpl { @@ -65,7 +64,6 @@ public class SummoningTrap extends CardImpl { this.expansionSetCode = "ZEN"; this.subtype.add("Trap"); - // If a creature spell you cast this turn was countered by a spell or // ability an opponent controlled, you may pay {0} rather than pay // Summoning Trap's mana cost. @@ -117,7 +115,7 @@ class SummoningTrapWatcher extends Watcher { if (counterObject == null) { counterObject = (StackObject) game.getLastKnownInformation(event.getSourceId(), Zone.STACK); } - if (stackObject != null && counterObject != null + if (stackObject != null && counterObject != null && stackObject.getCardType().contains(CardType.CREATURE) && game.getOpponents(controllerId).contains(counterObject.getControllerId())) { condition = true; @@ -145,10 +143,7 @@ class SummoningTrapAlternativeCost extends AlternativeCostImpl { @Override public boolean isAvailable(Game game, Ability source) { Watcher watcher = game.getState().getWatchers().get("CreatureSpellCountered", source.getControllerId()); - if (watcher != null && watcher.conditionMet()) { - return true; - } - return false; + return watcher != null && watcher.conditionMet(); } @Override @@ -170,54 +165,32 @@ class SummoningTrapEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - - Cards cards = new CardsImpl(Zone.PICK); - int count = Math.min(player.getLibrary().size(), 7); - for (int i = 0; i < count; i++) { - Card card = player.getLibrary().removeFromTop(game); - if (card != null) { - cards.add(card); - } + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; } - + Cards cards = new CardsImpl(Zone.LIBRARY); + cards.addAll(controller.getLibrary().getTopCards(game, 7)); if (!cards.isEmpty()) { - TargetCard target = new TargetCard(Zone.PICK, + TargetCard target = new TargetCard(Zone.LIBRARY, new FilterCreatureCard( - "creature card to put on the battlefield")); - if (player.choose(Outcome.PutCreatureInPlay, cards, target, game)) { + "creature card to put on the battlefield")); + if (controller.choose(Outcome.PutCreatureInPlay, cards, target, game)) { Card card = cards.get(target.getFirstTarget(), game); if (card != null) { cards.remove(card); - card.putOntoBattlefield(game, Zone.PICK, - source.getSourceId(), source.getControllerId()); + controller.putOntoBattlefieldWithInfo(card, game, Zone.LIBRARY, source.getSourceId()); } } if (cards.size() > 0) { - TargetCard target2 = new TargetCard(Zone.PICK, - new FilterCard( - "card to put on the bottom of your library")); - while (player.isInGame() && cards.size() > 1) { - player.choose(Outcome.Benefit, cards, target2, - game); - Card card = cards.get(target2.getFirstTarget(), game); - if (card != null) { - cards.remove(card); - player.getLibrary().putOnBottom(card, game); - } - target2.clearChosen(); - } - Card card = cards.get(cards.iterator().next(), game); - cards.remove(card); - player.getLibrary().putOnBottom(card, game); + controller.putCardsOnBottomOfLibrary(cards, game, source, true); } } - - return false; + return true; } @Override public SummoningTrapEffect copy() { return new SummoningTrapEffect(this); } -} \ No newline at end of file +} diff --git a/Mage/src/mage/filter/common/FilterBasicLandCard.java b/Mage/src/mage/filter/common/FilterBasicLandCard.java index 87ed9fcf95e..9c4a4dc52c0 100644 --- a/Mage/src/mage/filter/common/FilterBasicLandCard.java +++ b/Mage/src/mage/filter/common/FilterBasicLandCard.java @@ -1,16 +1,16 @@ /* * 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 @@ -20,12 +20,11 @@ * 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.filter.common; import mage.constants.CardType; @@ -40,7 +39,11 @@ import mage.filter.predicate.mageobject.SupertypePredicate; public class FilterBasicLandCard extends FilterCard { public FilterBasicLandCard() { - super("basic land card"); + this("basic land card"); + } + + public FilterBasicLandCard(String name) { + super(name); this.add(new CardTypePredicate(CardType.LAND)); this.add(new SupertypePredicate("Basic")); } From be8d016327ff0bbf850b561a5c043f6d7c18c671 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sat, 4 Jul 2015 19:27:48 +0200 Subject: [PATCH 038/105] [ORI] 13 green cards. --- .../mage/sets/magicorigins/AerialVolley.java | 73 +++++++++ .../sets/magicorigins/AnimistsAwakening.java | 125 ++++++++++++++ .../sets/magicorigins/CausticCaterpillar.java | 81 ++++++++++ .../mage/sets/magicorigins/GatherThePack.java | 119 ++++++++++++++ .../sets/magicorigins/JoragaInvocation.java | 102 ++++++++++++ .../sets/magicorigins/NissasPilgrimage.java | 125 ++++++++++++++ .../sets/magicorigins/NissasRevelation.java | 107 ++++++++++++ .../sets/magicorigins/TheGreatAurora.java | 152 ++++++++++++++++++ .../sets/magicorigins/UndercityTroll.java | 68 ++++++++ .../sets/magicorigins/ValeronWardens.java | 105 ++++++++++++ .../src/mage/sets/magicorigins/VineSnare.java | 68 ++++++++ .../mage/sets/magicorigins/WildInstincts.java | 77 +++++++++ .../mage/sets/magicorigins/ZendikarsRoil.java | 78 +++++++++ 13 files changed, 1280 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/magicorigins/AerialVolley.java create mode 100644 Mage.Sets/src/mage/sets/magicorigins/AnimistsAwakening.java create mode 100644 Mage.Sets/src/mage/sets/magicorigins/CausticCaterpillar.java create mode 100644 Mage.Sets/src/mage/sets/magicorigins/GatherThePack.java create mode 100644 Mage.Sets/src/mage/sets/magicorigins/JoragaInvocation.java create mode 100644 Mage.Sets/src/mage/sets/magicorigins/NissasPilgrimage.java create mode 100644 Mage.Sets/src/mage/sets/magicorigins/NissasRevelation.java create mode 100644 Mage.Sets/src/mage/sets/magicorigins/TheGreatAurora.java create mode 100644 Mage.Sets/src/mage/sets/magicorigins/UndercityTroll.java create mode 100644 Mage.Sets/src/mage/sets/magicorigins/ValeronWardens.java create mode 100644 Mage.Sets/src/mage/sets/magicorigins/VineSnare.java create mode 100644 Mage.Sets/src/mage/sets/magicorigins/WildInstincts.java create mode 100644 Mage.Sets/src/mage/sets/magicorigins/ZendikarsRoil.java diff --git a/Mage.Sets/src/mage/sets/magicorigins/AerialVolley.java b/Mage.Sets/src/mage/sets/magicorigins/AerialVolley.java new file mode 100644 index 00000000000..daecbc102c9 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/AerialVolley.java @@ -0,0 +1,73 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.DamageMultiEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.common.TargetCreaturePermanentAmount; + +/** + * + * @author LevelX2 + */ +public class AerialVolley extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures with flying"); + + static { + filter.add(new AbilityPredicate(FlyingAbility.class)); + } + + public AerialVolley(UUID ownerId) { + super(ownerId, 168, "Aerial Volley", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{G}"); + this.expansionSetCode = "ORI"; + + // Aerial Volley deals 3 damage divided as you choose among one, two, or three target creatures with flying. + Effect effect = new DamageMultiEffect(3); + effect.setText("A{this} deals 3 damage divided as you choose among one, two, or three target creatures with flying"); + this.getSpellAbility().addEffect(effect); + this.getSpellAbility().addTarget(new TargetCreaturePermanentAmount(3, filter)); + + } + + public AerialVolley(final AerialVolley card) { + super(card); + } + + @Override + public AerialVolley copy() { + return new AerialVolley(this); + } +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/AnimistsAwakening.java b/Mage.Sets/src/mage/sets/magicorigins/AnimistsAwakening.java new file mode 100644 index 00000000000..4cbe0168fc4 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/AnimistsAwakening.java @@ -0,0 +1,125 @@ +/* + * 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.magicorigins; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.condition.common.SpellMasteryCondition; +import mage.abilities.effects.OneShotEffect; +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.Zone; +import mage.filter.common.FilterLandCard; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; + +/** + * + * @author LevelX2 + */ +public class AnimistsAwakening extends CardImpl { + + public AnimistsAwakening(UUID ownerId) { + super(ownerId, 169, "Animist's Awakening", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{X}{G}"); + this.expansionSetCode = "ORI"; + + // Reveal the top X cards of your library. Put all land cards from among them onto the battlefield tapped and the rest on the bottom of your library in any order. + // Spell mastery — If there are two or more instant and/or sorcery cards in your graveyard, untap those lands. + this.getSpellAbility().addEffect(new AnimistsAwakeningEffect()); + } + + public AnimistsAwakening(final AnimistsAwakening card) { + super(card); + } + + @Override + public AnimistsAwakening copy() { + return new AnimistsAwakening(this); + } +} + +class AnimistsAwakeningEffect extends OneShotEffect { + + public AnimistsAwakeningEffect() { + super(Outcome.PutCardInPlay); + staticText = "Reveal the top X cards of your library. Put all land cards from among them onto the battlefield tapped and the rest on the bottom of your library in any order." + + "
Spell mastery — If there are two or more instant and/or sorcery cards in your graveyard, untap those lands"; + } + + public AnimistsAwakeningEffect(final AnimistsAwakeningEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + MageObject sourceObject = game.getObject(source.getSourceId()); + if (controller == null || sourceObject == null) { + return false; + } + Cards cards = new CardsImpl(Zone.LIBRARY); + int xValue = source.getManaCostsToPay().getX(); + cards.addAll(controller.getLibrary().getTopCards(game, xValue)); + List lands = new ArrayList<>(); + if (cards.size() > 0) { + controller.revealCards(sourceObject.getIdName(), cards, game); + for (Card card : cards.getCards(new FilterLandCard(), source.getSourceId(), source.getControllerId(), game)) { + cards.remove(card); + controller.putOntoBattlefieldWithInfo(card, game, Zone.LIBRARY, source.getSourceId(), true); + Permanent land = game.getPermanent(card.getId()); + if (land != null) { + lands.add(land); + } + + } + controller.putCardsOnBottomOfLibrary(cards, game, source, true); + + if (SpellMasteryCondition.getInstance().apply(game, source)) { + for (Permanent land : lands) { + land.untap(game); + } + } + } + return true; + } + + @Override + public AnimistsAwakeningEffect copy() { + return new AnimistsAwakeningEffect(this); + } + +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/CausticCaterpillar.java b/Mage.Sets/src/mage/sets/magicorigins/CausticCaterpillar.java new file mode 100644 index 00000000000..ad57d8f949c --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/CausticCaterpillar.java @@ -0,0 +1,81 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.FilterPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.target.TargetPermanent; + +/** + * + * @author LevelX2 + */ +public class CausticCaterpillar extends CardImpl { + + private static final FilterPermanent filter = new FilterPermanent("artifact or enchantment"); + + static { + filter.add(Predicates.or(new CardTypePredicate(CardType.ARTIFACT), + new CardTypePredicate(CardType.ENCHANTMENT))); + } + + public CausticCaterpillar(UUID ownerId) { + super(ownerId, 170, "Caustic Caterpillar", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{G}"); + this.expansionSetCode = "ORI"; + this.subtype.add("Insect"); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // {1}{G}, Sacrifice Caustic Caterpillar: Destroy target artifact or enchantment. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DestroyTargetEffect(), new ManaCostsImpl("{1}{G}")); + ability.addCost(new SacrificeSourceCost()); + ability.addTarget(new TargetPermanent(filter)); + this.addAbility(ability); + } + + public CausticCaterpillar(final CausticCaterpillar card) { + super(card); + } + + @Override + public CausticCaterpillar copy() { + return new CausticCaterpillar(this); + } +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/GatherThePack.java b/Mage.Sets/src/mage/sets/magicorigins/GatherThePack.java new file mode 100644 index 00000000000..31888fd17a7 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/GatherThePack.java @@ -0,0 +1,119 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.condition.common.SpellMasteryCondition; +import mage.abilities.effects.OneShotEffect; +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.Zone; +import mage.filter.common.FilterCreatureCard; +import mage.game.Game; +import mage.players.Player; +import mage.target.TargetCard; + +/** + * + * @author LevelX2 + */ +public class GatherThePack extends CardImpl { + + public GatherThePack(UUID ownerId) { + super(ownerId, 178, "Gather the Pack", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{1}{G}"); + this.expansionSetCode = "ORI"; + + // Reveal the top five cards of your library. You may put a creature card from among them into your hand. Put the rest into your graveyard. + // Spell mastery — If there are two or more instant and/or sorcery cards in your graveyard, put up to two creature cards from among the revealed cards into your hand instead of one. + this.getSpellAbility().addEffect(new GatherThePackEffect()); + } + + public GatherThePack(final GatherThePack card) { + super(card); + } + + @Override + public GatherThePack copy() { + return new GatherThePack(this); + } +} + +class GatherThePackEffect extends OneShotEffect { + + public GatherThePackEffect(final GatherThePackEffect effect) { + super(effect); + } + + public GatherThePackEffect() { + super(Outcome.PutCreatureInPlay); + this.staticText = "Reveal the top five cards of your library. You may put a creature card from among them into your hand. Put the rest into your graveyard." + + "
Spell mastery — If there are two or more instant and/or sorcery cards in your graveyard, put up to two creature cards from among the revealed cards into your hand instead of one"; + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } + Cards cards = new CardsImpl(Zone.LIBRARY); + cards.addAll(controller.getLibrary().getTopCards(game, 5)); + if (!cards.isEmpty()) { + int creatures = cards.count(new FilterCreatureCard(), source.getSourceId(), source.getControllerId(), game); + if (creatures > 0) { + int max = 1; + if (SpellMasteryCondition.getInstance().apply(game, source) && creatures > 1) { + max++; + } + TargetCard target = new TargetCard(0, max, Zone.LIBRARY, new FilterCreatureCard("creature card" + (max > 1 ? "s" : "") + " to put into your hand")); + if (controller.choose(Outcome.PutCreatureInPlay, cards, target, game)) { + Card card = cards.get(target.getFirstTarget(), game); + if (card != null) { + cards.remove(card); + controller.moveCards(card, Zone.LIBRARY, Zone.HAND, source, game); + } + } + } + if (cards.size() > 0) { + controller.moveCards(cards, Zone.LIBRARY, Zone.GRAVEYARD, source, game); + } + } + return true; + } + + @Override + public GatherThePackEffect copy() { + return new GatherThePackEffect(this); + } +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/JoragaInvocation.java b/Mage.Sets/src/mage/sets/magicorigins/JoragaInvocation.java new file mode 100644 index 00000000000..b5277621db7 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/JoragaInvocation.java @@ -0,0 +1,102 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.combat.MustBeBlockedByAtLeastOneTargetEffect; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.filter.common.FilterCreaturePermanent; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author LevelX2 + */ +public class JoragaInvocation extends CardImpl { + + public JoragaInvocation(UUID ownerId) { + super(ownerId, 183, "Joraga Invocation", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{4}{G}{G}"); + this.expansionSetCode = "ORI"; + + // Each creature you control gets +3/+3 until end of turn and must be blocked this turn if able. + this.getSpellAbility().addEffect(new BoostControlledEffect(3, 3, Duration.EndOfTurn)); + this.getSpellAbility().addEffect(new JoragaInvocationEffect()); + + } + + public JoragaInvocation(final JoragaInvocation card) { + super(card); + } + + @Override + public JoragaInvocation copy() { + return new JoragaInvocation(this); + } +} + +class JoragaInvocationEffect extends OneShotEffect { + + public JoragaInvocationEffect() { + super(Outcome.Detriment); + this.staticText = "and must be blocked this turn if able"; + } + + public JoragaInvocationEffect(final JoragaInvocationEffect effect) { + super(effect); + } + + @Override + public JoragaInvocationEffect copy() { + return new JoragaInvocationEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + for (Permanent permanent : game.getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), game)) { + ContinuousEffect effect = new MustBeBlockedByAtLeastOneTargetEffect(); + effect.setTargetPointer(new FixedTarget(permanent.getId())); + game.addEffect(effect, source); + } + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/NissasPilgrimage.java b/Mage.Sets/src/mage/sets/magicorigins/NissasPilgrimage.java new file mode 100644 index 00000000000..f9599cb6418 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/NissasPilgrimage.java @@ -0,0 +1,125 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.condition.common.SpellMasteryCondition; +import mage.abilities.effects.OneShotEffect; +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.Zone; +import mage.filter.FilterCard; +import mage.filter.common.FilterBasicLandCard; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetCardInLibrary; + +/** + * + * @author LevelX2 + */ +public class NissasPilgrimage extends CardImpl { + + public NissasPilgrimage(UUID ownerId) { + super(ownerId, 190, "Nissa's Pilgrimage", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{2}{G}"); + this.expansionSetCode = "ORI"; + + // Search your library for up to two basic Forest cards, reveal those cards, and put one onto the battlefield tapped and the rest into your hand. Then shuffle your library. + // Spell Mastery — If there are two or more instant and/or sorcery cards in your graveyard, search your library for up to three basic Forest cards instead of two. + this.getSpellAbility().addEffect(new NissasPilgrimageEffect()); + } + + public NissasPilgrimage(final NissasPilgrimage card) { + super(card); + } + + @Override + public NissasPilgrimage copy() { + return new NissasPilgrimage(this); + } +} + +class NissasPilgrimageEffect extends OneShotEffect { + + private static final FilterCard filter = new FilterBasicLandCard("basic Forest"); + + static { + filter.add(new SubtypePredicate("Forest")); + } + + public NissasPilgrimageEffect() { + super(Outcome.Benefit); + this.staticText = "Search your library for up to two basic Forest cards, reveal those cards, and put one onto the battlefield tapped and the rest into your hand. Then shuffle your library." + + "
Spell Mastery — If there are two or more instant and/or sorcery cards in your graveyard, search your library for up to three basic Forest cards instead of two."; + } + + public NissasPilgrimageEffect(final NissasPilgrimageEffect effect) { + super(effect); + } + + @Override + public NissasPilgrimageEffect copy() { + return new NissasPilgrimageEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + MageObject sourceObject = source.getSourceObject(game); + if (controller != null && sourceObject != null) { + int number = 2; + if (SpellMasteryCondition.getInstance().apply(game, source)) { + number++; + } + TargetCardInLibrary target = new TargetCardInLibrary(0, number, filter); + controller.chooseTarget(outcome, target, source, game); + if (!target.getTargets().isEmpty()) { + Cards cards = new CardsImpl(target.getTargets()); + controller.revealCards(sourceObject.getIdName(), cards, game); + if (!cards.isEmpty()) { + Card card = cards.getRandom(game); + if (card != null) { + cards.remove(card); + controller.putOntoBattlefieldWithInfo(card, game, Zone.LIBRARY, source.getSourceId(), true); + controller.moveCards(cards, Zone.LIBRARY, Zone.HAND, source, game); + } + } + } + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/NissasRevelation.java b/Mage.Sets/src/mage/sets/magicorigins/NissasRevelation.java new file mode 100644 index 00000000000..975e1d8fbd8 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/NissasRevelation.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.magicorigins; + +import java.util.UUID; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.keyword.ScryEffect; +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.game.Game; +import mage.players.Player; + +/** + * + * @author LevelX2 + */ +public class NissasRevelation extends CardImpl { + + public NissasRevelation(UUID ownerId) { + super(ownerId, 191, "Nissa's Revelation", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{5}{G}{G}"); + this.expansionSetCode = "ORI"; + + // Scry 5, then reveal the top card of your library. If it's a creature card, you draw cards equal to its power and you gain life equal to its toughness. + this.getSpellAbility().addEffect(new ScryEffect(5)); + this.getSpellAbility().addEffect(new NissasRevelationEffect()); + + } + + public NissasRevelation(final NissasRevelation card) { + super(card); + } + + @Override + public NissasRevelation copy() { + return new NissasRevelation(this); + } +} + +class NissasRevelationEffect extends OneShotEffect { + + public NissasRevelationEffect() { + super(Outcome.DrawCard); + this.staticText = ", then reveal the top card of your library. If it's a creature card, you draw cards equal to its power and you gain life equal to its toughness"; + } + + public NissasRevelationEffect(final NissasRevelationEffect effect) { + super(effect); + } + + @Override + public NissasRevelationEffect copy() { + return new NissasRevelationEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + MageObject sourceObject = source.getSourceObject(game); + if (controller != null && sourceObject != null) { + Cards cards = new CardsImpl(); + Card card = controller.getLibrary().getFromTop(game); + + if (card != null) { + cards.add(card); + controller.revealCards(sourceObject.getIdName(), cards, game); + if (card.getCardType().contains(CardType.CREATURE)) { + controller.drawCards(card.getPower().getValue(), game); + controller.gainLife(card.getToughness().getValue(), game); + } + } + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/TheGreatAurora.java b/Mage.Sets/src/mage/sets/magicorigins/TheGreatAurora.java new file mode 100644 index 00000000000..4b9654bfcf8 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/TheGreatAurora.java @@ -0,0 +1,152 @@ +/* + * 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.magicorigins; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ExileSpellEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterLandCard; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.TargetCard; +import mage.target.common.TargetCardInHand; + +/** + * + * @author LevelX2 + */ +public class TheGreatAurora extends CardImpl { + + public TheGreatAurora(UUID ownerId) { + super(ownerId, 179, "The Great Aurora", Rarity.MYTHIC, new CardType[]{CardType.SORCERY}, "{6}{G}{G}{G}"); + this.expansionSetCode = "ORI"; + + // Each player shuffles all cards from his or her hand and all permanents he or she owns into his or her library, then draws that many cards. Each player may put any number of land cards from his or her hand onto the battlefield. Exile The Great Aurora. + this.getSpellAbility().addEffect(new TheGreatAuroraEffect()); + this.getSpellAbility().addEffect(ExileSpellEffect.getInstance()); + } + + public TheGreatAurora(final TheGreatAurora card) { + super(card); + } + + @Override + public TheGreatAurora copy() { + return new TheGreatAurora(this); + } +} + +class TheGreatAuroraEffect extends OneShotEffect { + + public TheGreatAuroraEffect() { + super(Outcome.Benefit); + this.staticText = "Each player shuffles all cards from his or her hand and all permanents he or she owns into his or her library, then draws that many cards. Each player may put any number of land cards from his or her hand onto the battlefield"; + } + + public TheGreatAuroraEffect(final TheGreatAuroraEffect effect) { + super(effect); + } + + @Override + public TheGreatAuroraEffect copy() { + return new TheGreatAuroraEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + + Map> permanentsOwned = new HashMap<>(); + Collection permanents = game.getBattlefield().getAllPermanents(); + for (Permanent permanent : permanents) { + List list = permanentsOwned.get(permanent.getOwnerId()); + if (list == null) { + list = new ArrayList<>(); + } + list.add(permanent); + permanentsOwned.put(permanent.getOwnerId(), list); + } + + // shuffle permanents and hand cards into owner's library + Map permanentsCount = new HashMap<>(); + + for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) { + Player player = game.getPlayer(playerId); + if (player != null) { + int handCards = player.getHand().size(); + player.moveCards(player.getHand(), Zone.HAND, Zone.LIBRARY, source, game); + List list = permanentsOwned.remove(player.getId()); + permanentsCount.put(playerId, handCards + (list != null ? list.size() : 0)); + for (Permanent permanent : list) { + permanent.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true); + } + player.getLibrary().shuffle(); + } + } + + // Draw cards + for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) { + Player player = game.getPlayer(playerId); + if (player != null) { + int count = permanentsCount.get(playerId); + if (count > 0) { + player.drawCards(count, game); + } + } + } + + // put lands onto the battlefield + for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) { + Player player = game.getPlayer(playerId); + if (player != null) { + TargetCard target = new TargetCardInHand(0, Integer.MAX_VALUE, new FilterLandCard("put any number of land cards from your hand onto the battlefield")); + player.chooseTarget(Outcome.PutLandInPlay, player.getHand(), target, source, game); + for (UUID cardId : target.getTargets()) { + Card card = game.getCard(cardId); + if (card != null) { + player.putOntoBattlefieldWithInfo(card, game, Zone.HAND, source.getSourceId(), true); + } + } + + } + } + return true; + } +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/UndercityTroll.java b/Mage.Sets/src/mage/sets/magicorigins/UndercityTroll.java new file mode 100644 index 00000000000..2a7cb637bbf --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/UndercityTroll.java @@ -0,0 +1,68 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.RegenerateSourceEffect; +import mage.abilities.keyword.RenownAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; + +/** + * + * @author LevelX2 + */ +public class UndercityTroll extends CardImpl { + + public UndercityTroll(UUID ownerId) { + super(ownerId, 202, "Undercity Troll", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{1}{G}"); + this.expansionSetCode = "ORI"; + this.subtype.add("Troll"); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Renown 1 + this.addAbility(new RenownAbility(1)); + // {2}{G}: Regenerate Undercity Troll. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new RegenerateSourceEffect(), new ManaCostsImpl<>("{2}{G}"))); + } + + public UndercityTroll(final UndercityTroll card) { + super(card); + } + + @Override + public UndercityTroll copy() { + return new UndercityTroll(this); + } +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/ValeronWardens.java b/Mage.Sets/src/mage/sets/magicorigins/ValeronWardens.java new file mode 100644 index 00000000000..2237ba37683 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/ValeronWardens.java @@ -0,0 +1,105 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.keyword.RenownAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; +import mage.game.permanent.Permanent; + +/** + * + * @author LevelX2 + */ +public class ValeronWardens extends CardImpl { + + public ValeronWardens(UUID ownerId) { + super(ownerId, 203, "Valeron Wardens", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{2}{G}"); + this.expansionSetCode = "ORI"; + this.subtype.add("Human"); + this.subtype.add("Monk"); + this.power = new MageInt(1); + this.toughness = new MageInt(3); + + // Renown 2 + this.addAbility(new RenownAbility(2)); + + // Whenever a creature you control becomes renowned, draw a card. + this.addAbility(new ValeronWardensTriggeredAbility()); + } + + public ValeronWardens(final ValeronWardens card) { + super(card); + } + + @Override + public ValeronWardens copy() { + return new ValeronWardens(this); + } +} + +class ValeronWardensTriggeredAbility extends TriggeredAbilityImpl { + + public ValeronWardensTriggeredAbility() { + super(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), false); + } + + public ValeronWardensTriggeredAbility(final ValeronWardensTriggeredAbility ability) { + super(ability); + } + + @Override + public ValeronWardensTriggeredAbility copy() { + return new ValeronWardensTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType().equals(EventType.BECOMES_RENOWN); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + Permanent permanent = game.getPermanentOrLKIBattlefield(event.getTargetId()); + return permanent != null && permanent.getControllerId().equals(getControllerId()); + } + + @Override + public String getRule() { + return "Whenever a creature you control becomes renowned, draw a card."; + } +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/VineSnare.java b/Mage.Sets/src/mage/sets/magicorigins/VineSnare.java new file mode 100644 index 00000000000..9890fb2ba0e --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/VineSnare.java @@ -0,0 +1,68 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.abilities.effects.common.PreventAllDamageByAllEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.filter.Filter; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.PowerPredicate; + +/** + * + * @author LevelX2 + */ +public class VineSnare extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures with power 4 or less"); + + static { + filter.add(new PowerPredicate(Filter.ComparisonType.LessThan, 5)); + } + + public VineSnare(UUID ownerId) { + super(ownerId, 205, "Vine Snare", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{2}{G}"); + this.expansionSetCode = "ORI"; + + // Prevent all combat damage that would be dealt this turn by creatures with power 4 or less. + this.getSpellAbility().addEffect(new PreventAllDamageByAllEffect(filter, Duration.EndOfTurn, true)); + } + + public VineSnare(final VineSnare card) { + super(card); + } + + @Override + public VineSnare copy() { + return new VineSnare(this); + } +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/WildInstincts.java b/Mage.Sets/src/mage/sets/magicorigins/WildInstincts.java new file mode 100644 index 00000000000..0f2d1595c4b --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/WildInstincts.java @@ -0,0 +1,77 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.FightTargetsEffect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LevelX2 + */ +public class WildInstincts extends CardImpl { + + private final static FilterCreaturePermanent filter = new FilterCreaturePermanent("creature an opponent controls"); + + static { + filter.add(new ControllerPredicate(TargetController.OPPONENT)); + } + + public WildInstincts(UUID ownerId) { + super(ownerId, 206, "Wild Instincts", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{3}{G}"); + this.expansionSetCode = "ORI"; + + // Target creature you control gets +2/+2 until end of turn. It fights target creature an opponent controls. + getSpellAbility().addEffect(new BoostTargetEffect(2, 2, Duration.EndOfTurn)); + getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); + Effect effect = new FightTargetsEffect(); + effect.setText("It fights target creature an opponent controls (Each deals damage equal to its power to each other)"); + getSpellAbility().addEffect(effect); + getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + } + + public WildInstincts(final WildInstincts card) { + super(card); + } + + @Override + public WildInstincts copy() { + return new WildInstincts(this); + } +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/ZendikarsRoil.java b/Mage.Sets/src/mage/sets/magicorigins/ZendikarsRoil.java new file mode 100644 index 00000000000..5f9940335bc --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/ZendikarsRoil.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.magicorigins; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.common.FilterLandPermanent; +import mage.game.permanent.token.Token; + +/** + * + * @author LevelX2 + */ +public class ZendikarsRoil extends CardImpl { + + public ZendikarsRoil(UUID ownerId) { + super(ownerId, 209, "Zendikar's Roil", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT}, "{3}{G}{G}"); + this.expansionSetCode = "ORI"; + + // Whenever a land enters the battlefield under your control, put a 2/2 green Elemental creature token onto the battlefield. + Effect effect = new CreateTokenEffect(new ZendikarsRoilElementalToken()); + this.addAbility(new EntersBattlefieldControlledTriggeredAbility(effect, new FilterLandPermanent("a land"))); + } + + public ZendikarsRoil(final ZendikarsRoil card) { + super(card); + } + + @Override + public ZendikarsRoil copy() { + return new ZendikarsRoil(this); + } +} + +class ZendikarsRoilElementalToken extends Token { + + public ZendikarsRoilElementalToken() { + super("Elemental", "2/2 green Elemental creature token"); + cardType.add(CardType.CREATURE); + setOriginalExpansionSetCode("ORI"); + subtype.add("Elemental"); + color.setGreen(true); + power = new MageInt(2); + toughness = new MageInt(2); + } + +} From f0efc17f49dd004dae3a4c668c899ed976794f22 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sat, 4 Jul 2015 19:50:33 +0200 Subject: [PATCH 039/105] XMage 1.4.2v1 --- Mage.Common/src/mage/utils/MageVersion.java | 2 +- Mage/src/mage/cards/repository/CardRepository.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Mage.Common/src/mage/utils/MageVersion.java b/Mage.Common/src/mage/utils/MageVersion.java index 8ea13bc3cad..05b90a6e01d 100644 --- a/Mage.Common/src/mage/utils/MageVersion.java +++ b/Mage.Common/src/mage/utils/MageVersion.java @@ -41,7 +41,7 @@ public class MageVersion implements Serializable, Comparable { public final static int MAGE_VERSION_MAJOR = 1; public final static int MAGE_VERSION_MINOR = 4; public final static int MAGE_VERSION_PATCH = 2; - public final static String MAGE_VERSION_MINOR_PATCH = "v0"; + public final static String MAGE_VERSION_MINOR_PATCH = "v1"; public final static String MAGE_VERSION_INFO = ""; private final int major; diff --git a/Mage/src/mage/cards/repository/CardRepository.java b/Mage/src/mage/cards/repository/CardRepository.java index ebddaf05ab8..d4364e3275a 100644 --- a/Mage/src/mage/cards/repository/CardRepository.java +++ b/Mage/src/mage/cards/repository/CardRepository.java @@ -60,7 +60,7 @@ public enum CardRepository { // raise this if db structure was changed private static final long CARD_DB_VERSION = 39; // raise this if new cards were added to the server - private static final long CARD_CONTENT_VERSION = 21; + private static final long CARD_CONTENT_VERSION = 22; private final Random random = new Random(); private Dao cardDao; From aaf0ae847bab36b369d061adcfa6f5c0f886fde2 Mon Sep 17 00:00:00 2001 From: Wehk Date: Sat, 4 Jul 2015 20:26:55 +0200 Subject: [PATCH 040/105] Added card: Acolyte of the Inferno --- .../sets/magicorigins/AcolyteOfTheInferno | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/magicorigins/AcolyteOfTheInferno diff --git a/Mage.Sets/src/mage/sets/magicorigins/AcolyteOfTheInferno b/Mage.Sets/src/mage/sets/magicorigins/AcolyteOfTheInferno new file mode 100644 index 00000000000..fb8642d959f --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/AcolyteOfTheInferno @@ -0,0 +1,68 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.BecomesBlockedByCreatureTriggeredAbility; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.keyword.RenownAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; + +/** + * + * @author Wehk + */ +public class AcolyteOfTheInferno extends CardImpl { + + public AcolyteOfTheInferno(UUID ownerId) { + super(ownerId, 128, "Acolyte of the Inferno", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{2}{R}"); + this.expansionSetCode = "ORI"; + this.subtype.add("Human"); + this.subtype.add("Monk"); + this.power = new MageInt(3); + this.toughness = new MageInt(1); + + // Renown 1 + this.addAbility(new RenownAbility(1)); + + // Whenever Acolyte of the Inferno becomes blocked by a creature, it deals 2 damage to that creature + this.addAbility(new BecomesBlockedByCreatureTriggeredAbility(new DamageTargetEffect(2, true, "that creature"), false)); + } + + public AcolyteOfTheInferno(final AcolyteOfTheInferno card) { + super(card); + } + + @Override + public AcolyteOfTheInferno copy() { + return new AcolyteOfTheInferno(this); + } +} From ae5a77a8d52a8ac9f1a0d9bc1ceae30cbf294dd8 Mon Sep 17 00:00:00 2001 From: Wehk Date: Sat, 4 Jul 2015 20:27:58 +0200 Subject: [PATCH 041/105] Added card: Ghirapur AEther Grid --- .../mage/sets/magicorigins/GhirapurAEtherGrid | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/magicorigins/GhirapurAEtherGrid diff --git a/Mage.Sets/src/mage/sets/magicorigins/GhirapurAEtherGrid b/Mage.Sets/src/mage/sets/magicorigins/GhirapurAEtherGrid new file mode 100644 index 00000000000..95138ec2cc1 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/GhirapurAEtherGrid @@ -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.magicorigins; + +import java.util.UUID; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapTargetCost; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.predicate.permanent.TappedPredicate; +import mage.target.common.TargetCreatureOrPlayer; +import mage.target.common.TargetControlledPermanent; + +/** + * + * @author Wehk + */ +public class GhirapurAEtherGrid extends CardImpl { + + private static final FilterControlledPermanent filter = new FilterControlledPermanent("untapped artifacts you control"); + + static { + filter.add(new CardTypePredicate(CardType.ARTIFACT)); + filter.add(Predicates.not(new TappedPredicate())); + } + + public GhirapurAEtherGrid(UUID ownerId) { + super(ownerId, 148, "Ghirapur AEther Grid", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}"); + this.expansionSetCode = "ORI"; + + // Tap two untaped artifacts you control: Ghirapur Aether Grid deals 1 damage to target creature or player + SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, + new DamageTargetEffect(1), + new TapTargetCost(new TargetControlledPermanent(2, 2, filter, true))); + ability.addTarget(new TargetCreatureOrPlayer()); + this.addAbility(ability); + } + + public GhirapurAEtherGrid(final GhirapurAEtherGrid card) { + super(card); + } + + @Override + public GhirapurAEtherGrid copy() { + return new GhirapurAEtherGrid(this); + } +} From 93ed7ce0088a278b566db68893c231084fea5bd4 Mon Sep 17 00:00:00 2001 From: Wehk Date: Sat, 4 Jul 2015 20:28:39 +0200 Subject: [PATCH 042/105] Added card: Mage-Ring Bully --- .../mage/sets/magicorigins/MageRingBully.java | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/magicorigins/MageRingBully.java diff --git a/Mage.Sets/src/mage/sets/magicorigins/MageRingBully.java b/Mage.Sets/src/mage/sets/magicorigins/MageRingBully.java new file mode 100644 index 00000000000..98d8baf3898 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/MageRingBully.java @@ -0,0 +1,67 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.AttacksEachTurnStaticAbility; +import mage.abilities.keyword.ProwessAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; + +/** + * + * @author Wehk + */ +public class MageRingBully extends CardImpl { + + public MageRingBully(UUID ownerId) { + super(ownerId, 154, "Mage-Ring Bully", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{1}{R}"); + this.expansionSetCode = "ORI"; + this.subtype.add("Human"); + this.subtype.add("Warrior"); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Prowess + this.addAbility(new ProwessAbility()); + + // Mage-Ring Bully attacks each turn if able. + this.addAbility(new AttacksEachTurnStaticAbility()); + } + + public MageRingBully(final MageRingBully card) { + super(card); + } + + @Override + public MageRingBully copy() { + return new MageRingBully(this); + } +} From 227ac56f522319143ecbac9294977f435c57fe52 Mon Sep 17 00:00:00 2001 From: Wehk Date: Sat, 4 Jul 2015 20:29:46 +0200 Subject: [PATCH 043/105] Added .java file type --- .../magicorigins/{GhirapurAEtherGrid => GhirapurAEtherGrid.java} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Mage.Sets/src/mage/sets/magicorigins/{GhirapurAEtherGrid => GhirapurAEtherGrid.java} (100%) diff --git a/Mage.Sets/src/mage/sets/magicorigins/GhirapurAEtherGrid b/Mage.Sets/src/mage/sets/magicorigins/GhirapurAEtherGrid.java similarity index 100% rename from Mage.Sets/src/mage/sets/magicorigins/GhirapurAEtherGrid rename to Mage.Sets/src/mage/sets/magicorigins/GhirapurAEtherGrid.java From c716f2057471ed01e7ae540864913fb1d449b15a Mon Sep 17 00:00:00 2001 From: Wehk Date: Sat, 4 Jul 2015 20:30:07 +0200 Subject: [PATCH 044/105] Added .java file type --- .../{AcolyteOfTheInferno => AcolyteOfTheInferno.java} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Mage.Sets/src/mage/sets/magicorigins/{AcolyteOfTheInferno => AcolyteOfTheInferno.java} (100%) diff --git a/Mage.Sets/src/mage/sets/magicorigins/AcolyteOfTheInferno b/Mage.Sets/src/mage/sets/magicorigins/AcolyteOfTheInferno.java similarity index 100% rename from Mage.Sets/src/mage/sets/magicorigins/AcolyteOfTheInferno rename to Mage.Sets/src/mage/sets/magicorigins/AcolyteOfTheInferno.java From d212310a2162bccbd73676a673e7c2f2ab4f72bf Mon Sep 17 00:00:00 2001 From: Wehk Date: Sat, 4 Jul 2015 20:31:01 +0200 Subject: [PATCH 045/105] Added card: Prickleboar --- .../mage/sets/magicorigins/Prickleboar.java | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/magicorigins/Prickleboar.java diff --git a/Mage.Sets/src/mage/sets/magicorigins/Prickleboar.java b/Mage.Sets/src/mage/sets/magicorigins/Prickleboar.java new file mode 100644 index 00000000000..768e6f465d4 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/Prickleboar.java @@ -0,0 +1,82 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.MyTurnCondition; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; + +/** + * + * @author Wehk + */ +public class Prickleboar extends CardImpl { + + public Prickleboar(UUID ownerId) { + super(ownerId, 158, "Prickleboar", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{4}{R}"); + this.expansionSetCode = "ORI"; + this.subtype.add("Boar"); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + /// As long as it's your turn, Prickleboar gets +2/+0 + Effect boostEffect = new ConditionalContinuousEffect( + new BoostSourceEffect(2, 0, Duration.WhileOnBattlefield), + MyTurnCondition.getInstance(), + "As long as it's your turn, {this} gets +2/+0"); + // and has first strike. + Effect gainAbilityEffect = new ConditionalContinuousEffect( + new GainAbilitySourceEffect(FirstStrikeAbility.getInstance(), Duration.WhileOnBattlefield), + MyTurnCondition.getInstance(), + "and has first strike"); + Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, boostEffect); + ability.addEffect(gainAbilityEffect); + this.addAbility(ability); + } + + public Prickleboar(final Prickleboar card) { + super(card); + } + + @Override + public Prickleboar copy() { + return new Prickleboar(this); + } +} From de4ab7c026a4cc9c43359db4df26643fdee39600 Mon Sep 17 00:00:00 2001 From: Wehk Date: Sat, 4 Jul 2015 20:32:05 +0200 Subject: [PATCH 046/105] Added card: Thopter Engineer --- .../sets/magicorigins/ThopterEngineer.java | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/magicorigins/ThopterEngineer.java diff --git a/Mage.Sets/src/mage/sets/magicorigins/ThopterEngineer.java b/Mage.Sets/src/mage/sets/magicorigins/ThopterEngineer.java new file mode 100644 index 00000000000..a3bd1c6f0b8 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/ThopterEngineer.java @@ -0,0 +1,94 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.continuous.GainAbilityAllEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.HasteAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.game.permanent.token.Token; + +/** + * + * @author Wehk + */ +public class ThopterEngineer extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Artifact creatures"); + + static { + filter.add(new CardTypePredicate(CardType.ARTIFACT)); + } + + public ThopterEngineer(UUID ownerId) { + super(ownerId, 165, "Thopter Engineer", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{2}{R}"); + this.expansionSetCode = "ORI"; + this.subtype.add("Human"); + this.subtype.add("Artificer"); + this.power = new MageInt(1); + this.toughness = new MageInt(3); + + // When Thopter Engineer enters the battlefield, put a 1/1 colorless Thopter artifact creature token with flying onto the battlefield. + this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new ThopterEngineerThopterToken(), 1))); + + // Artifact creatures you control have haste. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAllEffect(HasteAbility.getInstance(), Duration.WhileOnBattlefield, filter, false))); + } + + public ThopterEngineer(final ThopterEngineer card) { + super(card); + } + + @Override + public ThopterEngineer copy() { + return new ThopterEngineer(this); + } +} + +class ThopterEngineerThopterToken extends Token { + ThopterEngineerThopterToken() { + super("Thopter", "a 1/1 colorless Thopter artifact creature token with flying"); + cardType.add(CardType.CREATURE); + cardType.add(CardType.ARTIFACT); + subtype.add("Thopter"); + power = new MageInt(1); + toughness = new MageInt(1); + this.addAbility(FlyingAbility.getInstance()); + } +} From ca2bff02adac18c32594a7ff154402b1ec56d590 Mon Sep 17 00:00:00 2001 From: Wehk Date: Sat, 4 Jul 2015 20:54:04 +0200 Subject: [PATCH 047/105] Thopter Engineer's haste effect fix Limited the effect to only controlled creatures, as opposed to all creatures. --- Mage.Sets/src/mage/sets/magicorigins/ThopterEngineer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Mage.Sets/src/mage/sets/magicorigins/ThopterEngineer.java b/Mage.Sets/src/mage/sets/magicorigins/ThopterEngineer.java index a3bd1c6f0b8..dd0a4a1c202 100644 --- a/Mage.Sets/src/mage/sets/magicorigins/ThopterEngineer.java +++ b/Mage.Sets/src/mage/sets/magicorigins/ThopterEngineer.java @@ -40,7 +40,7 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Rarity; import mage.constants.Zone; -import mage.filter.common.FilterCreaturePermanent; +import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.mageobject.CardTypePredicate; import mage.game.permanent.token.Token; @@ -50,7 +50,7 @@ import mage.game.permanent.token.Token; */ public class ThopterEngineer extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Artifact creatures"); + private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("Artifact creatures"); static { filter.add(new CardTypePredicate(CardType.ARTIFACT)); From 04840d10aaa91e4cdd2189ffbfc42a1619882925 Mon Sep 17 00:00:00 2001 From: Wehk Date: Sat, 4 Jul 2015 21:47:45 +0200 Subject: [PATCH 048/105] Added card: Ampryn Tactician --- .../sets/magicorigins/AmprynTactician.java | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/magicorigins/AmprynTactician.java diff --git a/Mage.Sets/src/mage/sets/magicorigins/AmprynTactician.java b/Mage.Sets/src/mage/sets/magicorigins/AmprynTactician.java new file mode 100644 index 00000000000..3229076d44a --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/AmprynTactician.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.magicorigins; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; + +/** + * + * @author Wehk + */ +public class AmprynTactician extends CardImpl { + + public AmprynTactician(UUID ownerId) { + super(ownerId, 2, "Ampryn Tactician", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{2}{W}{W}"); + this.expansionSetCode = "ORI"; + this.subtype.add("Human"); + this.subtype.add("Soldier"); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // When Ampryn Tactician enters the battlefield, creatures you control get +1/+1 until end of turn. + this.addAbility(new EntersBattlefieldTriggeredAbility(new BoostControlledEffect(1, 1, Duration.EndOfTurn))); + } + + public AmprynTactician(final AmprynTactician card) { + super(card); + } + + @Override + public AmprynTactician copy() { + return new AmprynTactician(this); + } +} From 5c4451a09481f0d825b1cb5a07493c41a39b9c95 Mon Sep 17 00:00:00 2001 From: Wehk Date: Sat, 4 Jul 2015 21:48:17 +0200 Subject: [PATCH 049/105] Added Card: Aven Battle Priest --- .../sets/magicorigins/AvenBattlePriest.java | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/magicorigins/AvenBattlePriest.java diff --git a/Mage.Sets/src/mage/sets/magicorigins/AvenBattlePriest.java b/Mage.Sets/src/mage/sets/magicorigins/AvenBattlePriest.java new file mode 100644 index 00000000000..b46ed44fc46 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/AvenBattlePriest.java @@ -0,0 +1,68 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; + +/** + * + * @author Wehk + */ +public class AvenBattlePriest extends CardImpl { + + public AvenBattlePriest(UUID ownerId) { + super(ownerId, 6, "Aven Battle Priest", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{5}{W}"); + this.expansionSetCode = "ORI"; + this.subtype.add("Bird"); + this.subtype.add("Cleric"); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // When Aven battle Priest enters the battlefield, you gain 3 life. + this.addAbility(new EntersBattlefieldTriggeredAbility(new GainLifeEffect(3))); + } + + public AvenBattlePriest(final AvenBattlePriest card) { + super(card); + } + + @Override + public AvenBattlePriest copy() { + return new AvenBattlePriest(this); + } +} From b062b3f99c5acd40cc0babaaa62975fe355da4cc Mon Sep 17 00:00:00 2001 From: Wehk Date: Sat, 4 Jul 2015 21:48:48 +0200 Subject: [PATCH 050/105] Added card: Enlightened Ascetic --- .../sets/magicorigins/EnlightenedAscetic.java | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/magicorigins/EnlightenedAscetic.java diff --git a/Mage.Sets/src/mage/sets/magicorigins/EnlightenedAscetic.java b/Mage.Sets/src/mage/sets/magicorigins/EnlightenedAscetic.java new file mode 100644 index 00000000000..a2e31a2e755 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/EnlightenedAscetic.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.magicorigins; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.FilterPermanent; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.target.Target; +import mage.target.TargetPermanent; + +/** + * + * @author Wehk + */ +public class EnlightenedAscetic extends CardImpl { + + private static final FilterPermanent filter = new FilterPermanent("enchantment"); + + static { + filter.add(new CardTypePredicate(CardType.ENCHANTMENT)); + } + + public EnlightenedAscetic(UUID ownerId) { + super(ownerId, 12, "Enlightened Ascetic", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{1}{W}"); + this.expansionSetCode = "ORI"; + this.subtype.add("Cat"); + this.subtype.add("Monk"); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // When Enlightened Ascetic enters the battlefield, you may destroy target enchantment. + Ability ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect(), true); + Target target = new TargetPermanent(filter); + ability.addTarget(target); + this.addAbility(ability); + } + + public EnlightenedAscetic(final EnlightenedAscetic card) { + super(card); + } + + @Override + public EnlightenedAscetic copy() { + return new EnlightenedAscetic(this); + } +} From e1c6281e01edc1802d470922bd40958464aa7da8 Mon Sep 17 00:00:00 2001 From: Wehk Date: Sat, 4 Jul 2015 21:49:59 +0200 Subject: [PATCH 051/105] Added card: Healing Hands --- .../mage/sets/magicorigins/HealingHands.java | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/magicorigins/HealingHands.java diff --git a/Mage.Sets/src/mage/sets/magicorigins/HealingHands.java b/Mage.Sets/src/mage/sets/magicorigins/HealingHands.java new file mode 100644 index 00000000000..6fb1d99ddf5 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/HealingHands.java @@ -0,0 +1,63 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.GainLifeTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.target.TargetPlayer; + +/** + * + * @author Wehk + */ +public class HealingHands extends CardImpl { + + public HealingHands(UUID ownerId) { + super(ownerId, 17, "Healing Hands", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{2}{W}"); + this.expansionSetCode = "ORI"; + + // Target player gains 4 life. + this.getSpellAbility().addEffect(new GainLifeTargetEffect(4)); + this.getSpellAbility().addTarget(new TargetPlayer()); + // Draw a card. + this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1)); + } + + public HealingHands(final HealingHands card) { + super(card); + } + + @Override + public HealingHands copy() { + return new HealingHands(this); + } +} From 87e953f6bab8e4d91b07e0d03147b21d929e9149 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sat, 4 Jul 2015 22:16:45 +0200 Subject: [PATCH 052/105] Reworked Stratadon. --- .../src/mage/sets/planeshift/Stratadon.java | 35 +++++++++---------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/Mage.Sets/src/mage/sets/planeshift/Stratadon.java b/Mage.Sets/src/mage/sets/planeshift/Stratadon.java index fd2a3be8f89..1d7c4638b9a 100644 --- a/Mage.Sets/src/mage/sets/planeshift/Stratadon.java +++ b/Mage.Sets/src/mage/sets/planeshift/Stratadon.java @@ -30,13 +30,14 @@ package mage.sets.planeshift; import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.dynamicvalue.common.DomainValue; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.cost.CostModificationEffectImpl; import mage.abilities.keyword.TrampleAbility; import mage.cards.CardImpl; import mage.constants.CardType; +import mage.constants.CostModificationType; +import mage.constants.Duration; import mage.constants.Outcome; import mage.constants.Rarity; import mage.constants.Zone; @@ -62,13 +63,6 @@ public class Stratadon extends CardImpl { this.addAbility(TrampleAbility.getInstance()); } - @Override - public void adjustCosts(Ability ability, Game game) { - super.adjustCosts(ability, game); - CardUtil.adjustCost((SpellAbility)ability, new DomainValue().calculate(game, ability, null)); - } - - public Stratadon(final Stratadon card) { super(card); } @@ -79,27 +73,30 @@ public class Stratadon extends CardImpl { } } -// Dummy to get the text on the card. -class StratadonCostReductionEffect extends OneShotEffect { - private static final String effectText = "Domain - {this} costs {1} less to cast for each basic land type among lands you control."; +class StratadonCostReductionEffect extends CostModificationEffectImpl { - StratadonCostReductionEffect() { - super(Outcome.Benefit); - this.staticText = effectText; + public StratadonCostReductionEffect() { + super(Duration.WhileOnStack, Outcome.Benefit, CostModificationType.REDUCE_COST); + staticText = "Domain - {this} costs {1} less to cast for each basic land type among lands you control."; } - StratadonCostReductionEffect(StratadonCostReductionEffect effect) { + protected StratadonCostReductionEffect(final StratadonCostReductionEffect effect) { super(effect); } @Override - public boolean apply(Game game, Ability source) { - return false; + public boolean apply(Game game, Ability source, Ability abilityToModify) { + CardUtil.reduceCost(abilityToModify, new DomainValue().calculate(game, source, this)); + return true; + } + + @Override + public boolean applies(Ability abilityToModify, Ability source, Game game) { + return abilityToModify.getSourceId().equals(source.getSourceId()); } @Override public StratadonCostReductionEffect copy() { return new StratadonCostReductionEffect(this); } - } From 1c9e7d653d4d569c65bf24eae9538ad0aae7e89f Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sat, 4 Jul 2015 22:16:56 +0200 Subject: [PATCH 053/105] Minor change. --- .../cost/SpellCostReductionSourceEffect.java | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/Mage/src/mage/abilities/effects/common/cost/SpellCostReductionSourceEffect.java b/Mage/src/mage/abilities/effects/common/cost/SpellCostReductionSourceEffect.java index c617a4cf249..775b4cdb745 100644 --- a/Mage/src/mage/abilities/effects/common/cost/SpellCostReductionSourceEffect.java +++ b/Mage/src/mage/abilities/effects/common/cost/SpellCostReductionSourceEffect.java @@ -25,7 +25,6 @@ * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package mage.abilities.effects.common.cost; import mage.abilities.Ability; @@ -39,19 +38,17 @@ import mage.constants.Outcome; import mage.game.Game; import mage.util.CardUtil; - /** * * @author LevelX2 */ - public class SpellCostReductionSourceEffect extends CostModificationEffectImpl { private final int amount; private ManaCosts manaCostsToReduce = null; private final Condition condition; - public SpellCostReductionSourceEffect(ManaCosts manaCostsToReduce, Condition condition) { + public SpellCostReductionSourceEffect(ManaCosts manaCostsToReduce, Condition condition) { super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.REDUCE_COST); this.amount = 0; this.manaCostsToReduce = manaCostsToReduce; @@ -59,14 +56,13 @@ public class SpellCostReductionSourceEffect extends CostModificationEffectImpl { StringBuilder sb = new StringBuilder(); sb.append("{this} costs "); - for (String manaSymbol :manaCostsToReduce.getSymbols()) { + for (String manaSymbol : manaCostsToReduce.getSymbols()) { sb.append(manaSymbol); } sb.append(" less to if ").append(this.condition.toString()); this.staticText = sb.toString(); } - public SpellCostReductionSourceEffect(int amount, Condition condition) { super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.REDUCE_COST); this.amount = amount; @@ -76,7 +72,7 @@ public class SpellCostReductionSourceEffect extends CostModificationEffectImpl { this.staticText = sb.toString(); } - protected SpellCostReductionSourceEffect(SpellCostReductionSourceEffect effect) { + protected SpellCostReductionSourceEffect(final SpellCostReductionSourceEffect effect) { super(effect); this.amount = effect.amount; this.manaCostsToReduce = effect.manaCostsToReduce; @@ -85,7 +81,7 @@ public class SpellCostReductionSourceEffect extends CostModificationEffectImpl { @Override public boolean apply(Game game, Ability source, Ability abilityToModify) { - if (manaCostsToReduce != null){ + if (manaCostsToReduce != null) { CardUtil.adjustCost((SpellAbility) abilityToModify, manaCostsToReduce, false); } else { CardUtil.reduceCost(abilityToModify, this.amount); @@ -95,7 +91,7 @@ public class SpellCostReductionSourceEffect extends CostModificationEffectImpl { @Override public boolean applies(Ability abilityToModify, Ability source, Game game) { - if (abilityToModify.getSourceId().equals(source.getSourceId()) && (abilityToModify instanceof SpellAbility)) { + if (abilityToModify.getSourceId().equals(source.getSourceId()) && (abilityToModify instanceof SpellAbility)) { return condition.apply(game, source); } return false; From 9e5ffde0da9723e6e8bfe6b036c76cd43c05ef21 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sat, 4 Jul 2015 22:58:42 +0200 Subject: [PATCH 054/105] [ORI] Two multicolor cards. --- .../sets/avacynrestored/FavorableWinds.java | 8 +- .../sets/magicorigins/PossessedSkaab.java | 135 ++++++++++++++++++ .../sets/magicorigins/ThunderclapWyvern.java | 85 +++++++++++ 3 files changed, 223 insertions(+), 5 deletions(-) create mode 100644 Mage.Sets/src/mage/sets/magicorigins/PossessedSkaab.java create mode 100644 Mage.Sets/src/mage/sets/magicorigins/ThunderclapWyvern.java diff --git a/Mage.Sets/src/mage/sets/avacynrestored/FavorableWinds.java b/Mage.Sets/src/mage/sets/avacynrestored/FavorableWinds.java index 2efe567a05a..f7a00271332 100644 --- a/Mage.Sets/src/mage/sets/avacynrestored/FavorableWinds.java +++ b/Mage.Sets/src/mage/sets/avacynrestored/FavorableWinds.java @@ -27,19 +27,18 @@ */ package mage.sets.avacynrestored; -import mage.constants.CardType; -import mage.constants.Rarity; +import java.util.UUID; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.continuous.BoostControlledEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; +import mage.constants.CardType; import mage.constants.Duration; +import mage.constants.Rarity; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; -import java.util.UUID; - /** * * @author noxx @@ -56,7 +55,6 @@ public class FavorableWinds extends CardImpl { super(ownerId, 51, "Favorable Winds", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT}, "{1}{U}"); this.expansionSetCode = "AVR"; - // Creatures you control with flying get +1/+1. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostControlledEffect(1, 1, Duration.WhileOnBattlefield, filter, false))); } diff --git a/Mage.Sets/src/mage/sets/magicorigins/PossessedSkaab.java b/Mage.Sets/src/mage/sets/magicorigins/PossessedSkaab.java new file mode 100644 index 00000000000..0bfd93d22f8 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/PossessedSkaab.java @@ -0,0 +1,135 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.effects.common.ReturnToHandTargetEffect; +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.FilterCard; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; +import mage.game.events.ZoneChangeEvent; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCardInYourGraveyard; + +/** + * + * @author LevelX2 + */ +public class PossessedSkaab extends CardImpl { + + private static final FilterCard filter = new FilterCard("instant, sorcery, or creature card from your graveyard"); + + static { + filter.add(Predicates.or( + new CardTypePredicate(CardType.INSTANT), + new CardTypePredicate(CardType.SORCERY), + new CardTypePredicate(CardType.CREATURE))); + } + + public PossessedSkaab(UUID ownerId) { + super(ownerId, 215, "Possessed Skaab", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{3}{U}{B}"); + this.expansionSetCode = "ORI"; + this.subtype.add("Zombie"); + this.power = new MageInt(3); + this.toughness = new MageInt(2); + + // When Possessed Skaab enters the battlefield, return target instant, sorcery, or creature card from your graveyard to your hand. + EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect(), false); + ability.addTarget(new TargetCardInYourGraveyard(filter)); + this.addAbility(ability); + + // If Possessed Skaab would die, exile it instead. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new PossessedSkaabDiesEffect())); + } + + public PossessedSkaab(final PossessedSkaab card) { + super(card); + } + + @Override + public PossessedSkaab copy() { + return new PossessedSkaab(this); + } +} + +class PossessedSkaabDiesEffect extends ReplacementEffectImpl { + + public PossessedSkaabDiesEffect() { + super(Duration.WhileOnBattlefield, Outcome.Exile); + staticText = "If {this} would die, exile it instead"; + } + + public PossessedSkaabDiesEffect(final PossessedSkaabDiesEffect effect) { + super(effect); + } + + @Override + public PossessedSkaabDiesEffect copy() { + return new PossessedSkaabDiesEffect(this); + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + Permanent permanent = ((ZoneChangeEvent) event).getTarget(); + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null && permanent != null) { + return controller.moveCardToExileWithInfo(permanent, null, null, source.getSourceId(), game, Zone.BATTLEFIELD, true); + } + return false; + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.ZONE_CHANGE; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (event.getTargetId().equals(source.getSourceId())) { + ZoneChangeEvent zce = (ZoneChangeEvent) event; + return zce.isDiesEvent(); + } + return false; + } + +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/ThunderclapWyvern.java b/Mage.Sets/src/mage/sets/magicorigins/ThunderclapWyvern.java new file mode 100644 index 00000000000..9b2d7dff977 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/ThunderclapWyvern.java @@ -0,0 +1,85 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.abilities.keyword.FlashAbility; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.AbilityPredicate; + +/** + * + * @author LevelX2 + */ +public class ThunderclapWyvern extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures you control with flying"); + + static { + filter.add(new AbilityPredicate(FlyingAbility.class)); + } + + public ThunderclapWyvern(UUID ownerId) { + super(ownerId, 218, "Thunderclap Wyvern", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{2}{W}{U}"); + this.expansionSetCode = "ORI"; + this.subtype.add("Drake"); + this.power = new MageInt(2); + this.toughness = new MageInt(3); + + // Flash + this.addAbility(FlashAbility.getInstance()); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Other creatures you control with flying get +1/+1. + Effect effect = new BoostControlledEffect(1, 1, Duration.WhileOnBattlefield, filter, true); + effect.setText("Other creatures you control with flying get +1/+1"); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); + + } + + public ThunderclapWyvern(final ThunderclapWyvern card) { + super(card); + } + + @Override + public ThunderclapWyvern copy() { + return new ThunderclapWyvern(this); + } +} From ebd6e478484710d9e170fea90b5acc768d7fa2ca Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sun, 5 Jul 2015 02:03:59 +0200 Subject: [PATCH 055/105] Fixed that Menace was a singleton class, what causes a lot of bugs on the public server and it shouldn't be a singleton anyway. --- .../mage/abilities/keyword/MenaceAbility.java | 21 +++++-------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/Mage/src/mage/abilities/keyword/MenaceAbility.java b/Mage/src/mage/abilities/keyword/MenaceAbility.java index 0ae88b54d06..8735b17d3ff 100644 --- a/Mage/src/mage/abilities/keyword/MenaceAbility.java +++ b/Mage/src/mage/abilities/keyword/MenaceAbility.java @@ -5,7 +5,6 @@ */ package mage.abilities.keyword; -import java.io.ObjectStreamException; import mage.abilities.Ability; import mage.abilities.StaticAbility; import mage.abilities.effects.common.combat.CantBeBlockedByOneEffect; @@ -16,33 +15,23 @@ import mage.constants.Zone; * @author LevelX2 */ public class MenaceAbility extends StaticAbility { - - private static final MenaceAbility fINSTANCE = new MenaceAbility(); public MenaceAbility() { super(Zone.BATTLEFIELD, new CantBeBlockedByOneEffect(2)); } - public MenaceAbility(MenaceAbility ability) { + public MenaceAbility(final MenaceAbility ability) { super(ability); } - - private Object readResolve() throws ObjectStreamException { - return fINSTANCE; - } - public static MenaceAbility getInstance() { - return fINSTANCE; - } - @Override public Ability copy() { - return fINSTANCE; - } + return new MenaceAbility(this); + } @Override public String getRule() { return "Menace (This creature can't be blocked except by two or more creatures.)"; - } - + } + } From 72b724e28ac3ebac0a07c5d79f29febe2349ad9e Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sun, 5 Jul 2015 02:04:40 +0200 Subject: [PATCH 056/105] Minor formatting issues. --- .../dragonsmaze/CouncilOfTheAbsolute.java | 8 +- .../sets/magicorigins/GoblinGloryChaser.java | 6 +- Mage/src/mage/game/stack/Spell.java | 166 +++++++++--------- Mage/src/mage/game/stack/SpellStack.java | 80 ++++----- Utils/mtg-cards-data.txt | 2 +- 5 files changed, 128 insertions(+), 134 deletions(-) diff --git a/Mage.Sets/src/mage/sets/dragonsmaze/CouncilOfTheAbsolute.java b/Mage.Sets/src/mage/sets/dragonsmaze/CouncilOfTheAbsolute.java index 7d49f8ada0d..a0569cfff99 100644 --- a/Mage.Sets/src/mage/sets/dragonsmaze/CouncilOfTheAbsolute.java +++ b/Mage.Sets/src/mage/sets/dragonsmaze/CouncilOfTheAbsolute.java @@ -25,7 +25,6 @@ * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package mage.sets.dragonsmaze; import java.util.UUID; @@ -56,17 +55,14 @@ import mage.util.CardUtil; * * @author LevelX2 */ - - public class CouncilOfTheAbsolute extends CardImpl { - public CouncilOfTheAbsolute (UUID ownerId) { + public CouncilOfTheAbsolute(UUID ownerId) { super(ownerId, 62, "Council of the Absolute", Rarity.MYTHIC, new CardType[]{CardType.CREATURE}, "{2}{W}{U}"); this.expansionSetCode = "DGM"; this.subtype.add("Human"); this.subtype.add("Advisor"); - this.power = new MageInt(2); this.toughness = new MageInt(4); @@ -79,7 +75,7 @@ public class CouncilOfTheAbsolute extends CardImpl { } - public CouncilOfTheAbsolute (final CouncilOfTheAbsolute card) { + public CouncilOfTheAbsolute(final CouncilOfTheAbsolute card) { super(card); } diff --git a/Mage.Sets/src/mage/sets/magicorigins/GoblinGloryChaser.java b/Mage.Sets/src/mage/sets/magicorigins/GoblinGloryChaser.java index b05ba2784c5..09faa522915 100644 --- a/Mage.Sets/src/mage/sets/magicorigins/GoblinGloryChaser.java +++ b/Mage.Sets/src/mage/sets/magicorigins/GoblinGloryChaser.java @@ -59,14 +59,14 @@ public class GoblinGloryChaser extends CardImpl { // Renown 1 this.addAbility(new RenownAbility(1)); - + // As long as Goblin Glory Chaser is renowned, it has menace. Effect effect = new ConditionalContinuousEffect( - new GainAbilitySourceEffect(MenaceAbility.getInstance(), Duration.WhileOnBattlefield), + new GainAbilitySourceEffect(new MenaceAbility(), Duration.WhileOnBattlefield), RenownCondition.getInstance(), "As long as {this} is renowned, it has menace"); Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, effect); - this.addAbility(ability); + this.addAbility(ability); } public GoblinGloryChaser(final GoblinGloryChaser card) { diff --git a/Mage/src/mage/game/stack/Spell.java b/Mage/src/mage/game/stack/Spell.java index 6674065cafc..2adc38b5e2c 100644 --- a/Mage/src/mage/game/stack/Spell.java +++ b/Mage/src/mage/game/stack/Spell.java @@ -1,31 +1,30 @@ /* -* 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. -*/ - + * 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.game.stack; import java.util.ArrayList; @@ -101,10 +100,10 @@ public class Spell extends StackObjImpl implements Card { public Spell(final Spell spell) { this.id = spell.id; - for (SpellAbility spellAbility: spell.spellAbilities) { + for (SpellAbility spellAbility : spell.spellAbilities) { this.spellAbilities.add(spellAbility.copy()); } - for (Card spellCard: spell.spellCards) { + for (Card spellCard : spell.spellCards) { this.spellCards.add(spellCard.copy()); } if (spell.spellAbilities.get(0).equals(spell.ability)) { @@ -124,7 +123,6 @@ public class Spell extends StackObjImpl implements Card { this.color = spell.color.copy(); } - public boolean activate(Game game, boolean noMana) { if (!spellAbilities.get(0).activate(game, noMana)) { return false; @@ -132,7 +130,7 @@ public class Spell extends StackObjImpl implements Card { // if there are more abilities (fused split spell) or first ability added new abilities (splice), activate the additional abilities boolean ignoreAbility = true; boolean payNoMana = noMana; - for (SpellAbility spellAbility: spellAbilities) { + for (SpellAbility spellAbility : spellAbilities) { // costs for spliced abilities were added to main spellAbility, so pay no mana for spliced abilities payNoMana |= spellAbility.getSpellAbilityType().equals(SpellAbilityType.SPLICE); if (ignoreAbility) { @@ -174,19 +172,19 @@ public class Spell extends StackObjImpl implements Card { result = false; boolean legalParts = false; // check for legal parts - for(SpellAbility spellAbility: this.spellAbilities) { - // if muliple modes are selected, and there are modes with targets, then at least one mode has to have a legal target or - // When resolving a fused split spell with multiple targets, treat it as you would any spell with multiple targets. - // If all targets are illegal when the spell tries to resolve, the spell is countered and none of its effects happen. + for (SpellAbility spellAbility : this.spellAbilities) { + // if muliple modes are selected, and there are modes with targets, then at least one mode has to have a legal target or + // When resolving a fused split spell with multiple targets, treat it as you would any spell with multiple targets. + // If all targets are illegal when the spell tries to resolve, the spell is countered and none of its effects happen. // If at least one target is still legal at that time, the spell resolves, but an illegal target can't perform any actions - // or have any actions performed on it. + // or have any actions performed on it. legalParts |= spellAbilityHasLegalParts(spellAbility, game); } // resolve if legal parts if (legalParts) { - for(SpellAbility spellAbility: this.spellAbilities) { + for (SpellAbility spellAbility : this.spellAbilities) { if (spellAbilityHasLegalParts(spellAbility, game)) { - for (UUID modeId :spellAbility.getModes().getSelectedModes()) { + for (UUID modeId : spellAbility.getModes().getSelectedModes()) { spellAbility.getModes().setActiveMode(modeId); if (spellAbility.getTargets().stillLegal(spellAbility, game)) { if (!spellAbility.getSpellAbilityType().equals(SpellAbilityType.SPLICE)) { @@ -216,14 +214,14 @@ public class Spell extends StackObjImpl implements Card { if (ability.getTargets().stillLegal(ability, game)) { updateOptionalCosts(0); boolean bestow = this.getSpellAbility() instanceof BestowAbility; - if (bestow) { + if (bestow) { // Must be removed first time, after that will be removed by continous effect // Otherwise effects like evolve trigger from creature comes into play event card.getCardType().remove(CardType.CREATURE); - card.getSubtype().add("Aura"); + card.getSubtype().add("Aura"); } if (card.putOntoBattlefield(game, fromZone, ability.getSourceId(), controllerId)) { - if (bestow) { + if (bestow) { // card will be copied during putOntoBattlefield, so the card of CardPermanent has to be changed // TODO: Find a better way to prevent bestow creatures from being effected by creature affecting abilities Permanent permanent = game.getPermanent(card.getId()); @@ -234,16 +232,16 @@ public class Spell extends StackObjImpl implements Card { } card.getCardType().add(CardType.CREATURE); card.getSubtype().remove("Aura"); - } + } return ability.resolve(game); } - if (bestow) { + if (bestow) { card.getCardType().add(CardType.CREATURE); - } + } return false; } // Aura has no legal target and its a bestow enchantment -> Add it to battlefield as creature - if (this.getSpellAbility() instanceof BestowAbility) { + if (this.getSpellAbility() instanceof BestowAbility) { updateOptionalCosts(0); result = card.putOntoBattlefield(game, fromZone, ability.getSourceId(), controllerId); return result; @@ -263,17 +261,17 @@ public class Spell extends StackObjImpl implements Card { } private boolean spellAbilityHasLegalParts(SpellAbility spellAbility, Game game) { - if (spellAbility.getModes().getSelectedModes().size() > 1) { + if (spellAbility.getModes().getSelectedModes().size() > 1) { boolean targetedMode = false; boolean legalTargetedMode = false; - for (UUID modeId :spellAbility.getModes().getSelectedModes()) { + for (UUID modeId : spellAbility.getModes().getSelectedModes()) { spellAbility.getModes().setActiveMode(modeId); if (spellAbility.getTargets().size() > 0) { targetedMode = true; if (spellAbility.getTargets().stillLegal(spellAbility, game)) { legalTargetedMode = true; - } - } + } + } } if (targetedMode) { return legalTargetedMode; @@ -283,11 +281,11 @@ public class Spell extends StackObjImpl implements Card { return spellAbility.getTargets().stillLegal(spellAbility, game); } } - + /** - * As we have ability in the stack, we need to update optional costs in original card. - * This information will be used later by effects, e.g. to determine whether card was kicked or not. - * E.g. Desolation Angel + * As we have ability in the stack, we need to update optional costs in + * original card. This information will be used later by effects, e.g. to + * determine whether card was kicked or not. E.g. Desolation Angel */ private void updateOptionalCosts(int index) { Ability abilityOrig = spellCards.get(index).getAbilities().get(spellAbilities.get(index).getId()); @@ -307,9 +305,7 @@ public class Spell extends StackObjImpl implements Card { } } } - - @Override public void counter(UUID sourceId, Game game) { this.countered = true; @@ -319,10 +315,10 @@ public class Spell extends StackObjImpl implements Card { Ability counteringAbility = null; MageObject counteringObject = game.getObject(sourceId); if (counteringObject instanceof StackObject) { - counteringAbility = ((StackObject)counteringObject).getStackAbility(); + counteringAbility = ((StackObject) counteringObject).getStackAbility(); } player.moveCards(card, Zone.STACK, Zone.GRAVEYARD, counteringAbility, game); - } + } } } @@ -340,18 +336,18 @@ public class Spell extends StackObjImpl implements Card { public String getName() { return card.getName(); } - + @Override public String getIdName() { String idName; if (card != null) { - idName = card.getId().toString().substring(0,3); + idName = card.getId().toString().substring(0, 3); } else { - idName = getId().toString().substring(0,3); + idName = getId().toString().substring(0, 3); } - return getName() + " ["+idName+"]"; + return getName() + " [" + idName + "]"; } - + @Override public String getLogName() { return GameLog.getColoredObjectIdName(card); @@ -363,7 +359,8 @@ public class Spell extends StackObjImpl implements Card { } @Override - public void setName(String name) {} + public void setName(String name) { + } @Override public Rarity getRarity() { @@ -415,7 +412,6 @@ public class Spell extends StackObjImpl implements Card { return card.getSupertype(); } - public List getSpellAbilities() { return spellAbilities; } @@ -429,7 +425,7 @@ public class Spell extends StackObjImpl implements Card { public Abilities getAbilities(Game game) { return card.getAbilities(game); } - + @Override public boolean hasAbility(UUID abilityId, Game game) { return card.hasAbility(abilityId, game); @@ -446,9 +442,11 @@ public class Spell extends StackObjImpl implements Card { } /** - * 202.3b When calculating the converted mana cost of an object with an {X} in its - * mana cost, X is treated as 0 while the object is not on the stack, and X is - * treated as the number chosen for it while the object is on the stack. + * 202.3b When calculating the converted mana cost of an object with an {X} + * in its mana cost, X is treated as 0 while the object is not on the stack, + * and X is treated as the number chosen for it while the object is on the + * stack. + * * @return */ @Override @@ -457,9 +455,9 @@ public class Spell extends StackObjImpl implements Card { if (faceDown) { return 0; } - for (Ability spellAbility: spellAbilities) { + for (Ability spellAbility : spellAbilities) { int xMultiplier = 0; - for (String symbolString :spellAbility.getManaCosts().getSymbols()) { + for (String symbolString : spellAbility.getManaCosts().getSymbols()) { int index = symbolString.indexOf("{X}"); while (index != -1) { xMultiplier++; @@ -471,14 +469,14 @@ public class Spell extends StackObjImpl implements Card { cmc += spellAbility.getManaCostsToPay().getX() * xMultiplier; } else { cmc += spellAbility.getManaCosts().convertedManaCost() + spellAbility.getManaCostsToPay().getX() * xMultiplier; - } + } } if (this.getSpellAbility().getSpellAbilityType().equals(SpellAbilityType.BASE_ALTERNATE)) { cmc += getCard().getManaCost().convertedManaCost(); } return cmc; } - + @Override public MageInt getPower() { return card.getPower(); @@ -503,7 +501,8 @@ public class Spell extends StackObjImpl implements Card { spellAbilities.add(spellAbility); } - public void addAbility(Ability ability) {} + public void addAbility(Ability ability) { + } @Override public SpellAbility getSpellAbility() { @@ -512,14 +511,15 @@ public class Spell extends StackObjImpl implements Card { public void setControllerId(UUID controllerId) { this.ability.setControllerId(controllerId); - for (SpellAbility spellAbility: spellAbilities) { + for (SpellAbility spellAbility : spellAbilities) { spellAbility.setControllerId(controllerId); } this.controllerId = controllerId; } @Override - public void setOwnerId(UUID controllerId) {} + public void setOwnerId(UUID controllerId) { + } @Override public List getRules() { @@ -608,7 +608,7 @@ public class Spell extends StackObjImpl implements Card { card.adjustChoices(ability, game); } } - + @Override public void adjustCosts(Ability ability, Game game) { if (card != null) { @@ -623,7 +623,6 @@ public class Spell extends StackObjImpl implements Card { } } - @Override public boolean moveToZone(Zone zone, UUID sourceId, Game game, boolean flag) { return moveToZone(zone, sourceId, game, flag, null); @@ -635,7 +634,7 @@ public class Spell extends StackObjImpl implements Card { // If a copy of a card is in any zone other than the stack or the battlefield, it ceases to exist. // These are state-based actions. See rule 704. if (this.isCopiedSpell() && !zone.equals(Zone.STACK)) { - return true; + return true; } throw new UnsupportedOperationException("Unsupported operation"); } @@ -646,7 +645,7 @@ public class Spell extends StackObjImpl implements Card { } @Override - public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game, ArrayList appliedEffects) { + public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game, ArrayList appliedEffects) { ZoneChangeEvent event = new ZoneChangeEvent(this.getId(), sourceId, this.getOwnerId(), Zone.STACK, Zone.EXILED, appliedEffects); if (!game.replaceEvent(event)) { game.getStack().remove(this); @@ -667,8 +666,6 @@ public class Spell extends StackObjImpl implements Card { return false; } - - @Override public boolean putOntoBattlefield(Game game, Zone fromZone, UUID sourceId, UUID controllerId) { throw new UnsupportedOperationException("Unsupported operation"); @@ -711,7 +708,7 @@ public class Spell extends StackObjImpl implements Card { @Override public void updateZoneChangeCounter(Game game) { - throw new UnsupportedOperationException("Unsupported operation"); + throw new UnsupportedOperationException("Unsupported operation"); } @Override @@ -762,7 +759,8 @@ public class Spell extends StackObjImpl implements Card { } @Override - public void build() {} + public void build() { + } @Override public Counters getCounters(Game game) { @@ -815,7 +813,7 @@ public class Spell extends StackObjImpl implements Card { @Override public void setSpellAbility(SpellAbility ability) { - throw new UnsupportedOperationException("Not supported."); + throw new UnsupportedOperationException("Not supported."); } public boolean isCountered() { diff --git a/Mage/src/mage/game/stack/SpellStack.java b/Mage/src/mage/game/stack/SpellStack.java index 174ac51cb32..62ea3bb72ca 100644 --- a/Mage/src/mage/game/stack/SpellStack.java +++ b/Mage/src/mage/game/stack/SpellStack.java @@ -1,31 +1,30 @@ /* -* 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. -*/ - + * 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.game.stack; import java.util.ArrayDeque; @@ -44,11 +43,12 @@ public class SpellStack extends ArrayDeque { protected Date dateLastAdded; - public SpellStack () {} + public SpellStack() { + } public SpellStack(final SpellStack stack) { - - for (StackObject spell: stack) { + + for (StackObject spell : stack) { this.addLast(spell.copy()); } } @@ -67,7 +67,7 @@ public class SpellStack extends ArrayDeque { } public void remove(StackObject object) { - for (StackObject spell: this) { + for (StackObject spell : this) { if (spell.getId().equals(object.getId())) { super.remove(spell); return; @@ -77,7 +77,7 @@ public class SpellStack extends ArrayDeque { public boolean counter(UUID objectId, UUID sourceId, Game game) { // the counter logic is copied by some spells to handle replacement effects of the countered spell - // so if logic is changed here check those spells for needed changes too + // so if logic is changed here check those spells for needed changes too // Concerned cards to check: Hinder, Spell Crumple StackObject stackObject = getStackObject(objectId); MageObject sourceObject = game.getObject(sourceId); @@ -87,7 +87,7 @@ public class SpellStack extends ArrayDeque { if (targetSourceObject == null) { targetSourceName = "[Object not found]"; } else { - targetSourceName = game.getObject(stackObject.getSourceId()).getName(); + targetSourceName = game.getObject(stackObject.getSourceId()).getLogName(); } if (stackObject instanceof Spell) { counteredObjectName = targetSourceName; @@ -95,12 +95,12 @@ public class SpellStack extends ArrayDeque { counteredObjectName = "Ability (" + stackObject.getStackAbility().getRule(targetSourceName) + ") of " + targetSourceName; } if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.COUNTER, objectId, sourceId, stackObject.getControllerId()))) { - if ( stackObject instanceof Spell ) { - game.rememberLKI(objectId, Zone.STACK, (Spell)stackObject); + if (stackObject instanceof Spell) { + game.rememberLKI(objectId, Zone.STACK, (Spell) stackObject); } else { - this.remove(stackObject); + this.remove(stackObject); } - stackObject.counter(sourceId, game); + stackObject.counter(sourceId, game); if (!game.isSimulation()) { game.informPlayers(counteredObjectName + " is countered by " + sourceObject.getLogName()); } @@ -114,7 +114,7 @@ public class SpellStack extends ArrayDeque { } public StackObject getStackObject(UUID id) { - for (StackObject stackObject: this) { + for (StackObject stackObject : this) { UUID objectId = stackObject.getId(); if (objectId.equals(id)) { return stackObject; @@ -128,10 +128,10 @@ public class SpellStack extends ArrayDeque { } public Spell getSpell(UUID id) { - for (StackObject stackObject: this) { + for (StackObject stackObject : this) { if (stackObject instanceof Spell) { if (stackObject.getId().equals(id) || stackObject.getSourceId().equals(id)) { - return (Spell)stackObject; + return (Spell) stackObject; } } } diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index c0e8ba5b3d5..4535fb23d1f 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -26130,7 +26130,7 @@ Valor in Akros|Magic Origins|39|U|{3}{W}|Enchantment|||Whenever a creature enter Vryn Wingmare|Magic Origins|40|R|{2}{W}|Creature - Pegasus|2|1|Flying$Noncreature spells cost {1} more to cast.| War Oracle|Magic Origins|41|U|{2}{W}{W}|Creature - Human Cleric|3|3|Lifelink$Renown 1 (When this creature deals combat damage to a player, if it isn't renowned, put a +1/+1 counter on it and it becomes renowned)| Yoked Ox|Magic Origins|42|C|{W}|Creature - Ox|0|4|| -Alhammarret, High Arbiter|Magic Origins|43|R|{5}{U}{U}|Legendary Creature - Sphinx|5|5|Flying$As Alhammarret, High Arbiter enters the battlefield, each opponent reveals his or her hand. You choose the name of a nonland card revealed this way.$Your opponent can't cast spells with the chosen name (as long as this creature is on the battlefield).| +Alhammarret, High Arbiter|Magic Origins|43|R|{5}{U}{U}|Legendary Creature - Sphinx|5|5|Flying$As Alhammarret, High Arbiter enters the battlefield, each opponent reveals his or her hand. You choose the name of a nonland card revealed this way.$Your opponents can't cast spells with the chosen name (as long as this creature is on the battlefield).| Anchor to the AEther|Magic Origins|44|U|{2}{U}|Sorcery|||Put target creature on top of its owner's library. Scry 1.| Artificer's Epiphany|Magic Origins|45|C|{2}{U}|Instant|||Draw two cards. If you control no artifacts, discard a card.| Aspiring Aeronaut|Magic Origins|46|C|{3}{U}|Creature - Human Artificer|1|2|Flying$When Aspiring Aeronaut enters the battlefield, put a 1/1 colorless Thopter artifact creature token with flying onto the battlefield.| From a126942a038c090449b967e5724983f95871e323 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sun, 5 Jul 2015 02:05:03 +0200 Subject: [PATCH 057/105] [ORI] 7 blue cards. --- .../magicorigins/AlhammarretHighArbiter.java | 189 ++++++++++++++++++ .../sets/magicorigins/AnchorToTheAEther.java | 63 ++++++ .../magicorigins/CalculatedDismissal.java | 67 +++++++ .../mage/sets/magicorigins/DeepSeaTerror.java | 74 +++++++ .../magicorigins/HarbingerOfTheTides.java | 85 ++++++++ .../mage/sets/magicorigins/NivixBarrier.java | 75 +++++++ .../sets/magicorigins/PsychicRebuttal.java | 157 +++++++++++++++ ...yMoreToCastAsThoughtItHadFlashAbility.java | 52 +++++ 8 files changed, 762 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/magicorigins/AlhammarretHighArbiter.java create mode 100644 Mage.Sets/src/mage/sets/magicorigins/AnchorToTheAEther.java create mode 100644 Mage.Sets/src/mage/sets/magicorigins/CalculatedDismissal.java create mode 100644 Mage.Sets/src/mage/sets/magicorigins/DeepSeaTerror.java create mode 100644 Mage.Sets/src/mage/sets/magicorigins/HarbingerOfTheTides.java create mode 100644 Mage.Sets/src/mage/sets/magicorigins/NivixBarrier.java create mode 100644 Mage.Sets/src/mage/sets/magicorigins/PsychicRebuttal.java create mode 100644 Mage/src/mage/abilities/common/PayMoreToCastAsThoughtItHadFlashAbility.java diff --git a/Mage.Sets/src/mage/sets/magicorigins/AlhammarretHighArbiter.java b/Mage.Sets/src/mage/sets/magicorigins/AlhammarretHighArbiter.java new file mode 100644 index 00000000000..a3ffd5c8fb0 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/AlhammarretHighArbiter.java @@ -0,0 +1,189 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.MageInt; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; +import mage.abilities.effects.EntersBattlefieldEffect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.Cards; +import mage.cards.CardsImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterNonlandCard; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.TargetCard; +import mage.util.CardUtil; +import mage.util.GameLog; + +/** + * + * @author LevelX2 + */ +public class AlhammarretHighArbiter extends CardImpl { + + public AlhammarretHighArbiter(UUID ownerId) { + super(ownerId, 43, "Alhammarret, High Arbiter", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{5}{U}{U}"); + this.expansionSetCode = "ORI"; + this.supertype.add("Legendary"); + this.subtype.add("Sphinx"); + this.power = new MageInt(5); + this.toughness = new MageInt(5); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + // As Alhammarret, High Arbiter enters the battlefield, each opponent reveals his or her hand. You choose the name of a nonland card revealed this way. + // Your opponents can't cast spells with the chosen name. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new EntersBattlefieldEffect(new AlhammarretHighArbiterEffect(), ""))); + } + + public AlhammarretHighArbiter(final AlhammarretHighArbiter card) { + super(card); + } + + @Override + public AlhammarretHighArbiter copy() { + return new AlhammarretHighArbiter(this); + } +} + +class AlhammarretHighArbiterEffect extends OneShotEffect { + + public AlhammarretHighArbiterEffect() { + super(Outcome.Benefit); + this.staticText = "As {this} enters the battlefield, each opponent reveals his or her hand. You choose the name of a nonland card revealed this way." + + "
Your opponents can't cast spells with the chosen name"; + } + + public AlhammarretHighArbiterEffect(final AlhammarretHighArbiterEffect effect) { + super(effect); + } + + @Override + public AlhammarretHighArbiterEffect copy() { + return new AlhammarretHighArbiterEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + Cards revealedCards = new CardsImpl(Zone.PICK); + for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { + if (playerId != controller.getId()) { + Player opponent = game.getPlayer(playerId); + if (opponent != null) { + Cards cards = new CardsImpl(opponent.getHand()); + opponent.revealCards(opponent.getName() + "'s hand", cards, game); + revealedCards.addAll(cards); + } + } + } + TargetCard target = new TargetCard(Zone.HAND, new FilterNonlandCard("nonland card from an opponents hand")); + controller.chooseTarget(Outcome.Benefit, revealedCards, target, source, game); + Card card = game.getCard(target.getFirstTarget()); + if (card != null) { + game.informPlayers("The choosen card name is [" + GameLog.getColoredObjectName(card) + "]"); + Permanent sourcePermanent = game.getPermanent(source.getSourceId()); + if (sourcePermanent != null) { + sourcePermanent.addInfo("chosen card name", CardUtil.addToolTipMarkTags("Chosen card name: " + card.getName()), game); + } + game.addEffect(new AlhammarretHighArbiterCantCastEffect(card.getName()), source); + } + return true; + + } + return false; + } +} + +class AlhammarretHighArbiterCantCastEffect extends ContinuousRuleModifyingEffectImpl { + + String cardName; + + public AlhammarretHighArbiterCantCastEffect(String cardName) { + super(Duration.Custom, Outcome.Benefit); + this.cardName = cardName; + staticText = "Your opponents can't cast spells with the chosen name"; + } + + public AlhammarretHighArbiterCantCastEffect(final AlhammarretHighArbiterCantCastEffect effect) { + super(effect); + this.cardName = effect.cardName; + } + + @Override + public AlhammarretHighArbiterCantCastEffect copy() { + return new AlhammarretHighArbiterCantCastEffect(this); + } + + @Override + public boolean isInactive(Ability source, Game game) { + Permanent sourceObject = game.getPermanent(source.getSourceId()); + return sourceObject == null || sourceObject.getZoneChangeCounter(game) != source.getSourceObjectZoneChangeCounter(); + } + + @Override + public String getInfoMessage(Ability source, GameEvent event, Game game) { + MageObject mageObject = game.getObject(source.getSourceId()); + if (mageObject != null) { + return "You may not cast a card named " + cardName + " (" + mageObject.getLogName() + ")."; + } + return null; + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.CAST_SPELL; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (game.getOpponents(source.getControllerId()).contains(event.getPlayerId())) { + MageObject object = game.getObject(event.getSourceId()); + if (object != null && object.getName().equals(cardName)) { + return true; + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/AnchorToTheAEther.java b/Mage.Sets/src/mage/sets/magicorigins/AnchorToTheAEther.java new file mode 100644 index 00000000000..c7992654e2d --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/AnchorToTheAEther.java @@ -0,0 +1,63 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.abilities.effects.common.PutOnLibraryTargetEffect; +import mage.abilities.effects.keyword.ScryEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LevelX2 + */ +public class AnchorToTheAEther extends CardImpl { + + public AnchorToTheAEther(UUID ownerId) { + super(ownerId, 44, "Anchor to the AEther", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{2}{U}"); + this.expansionSetCode = "ORI"; + + // Put target creature on top of its owner's library. Scry 1. + this.getSpellAbility().addEffect(new PutOnLibraryTargetEffect(true)); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + this.getSpellAbility().addEffect(new ScryEffect(1)); + + } + + public AnchorToTheAEther(final AnchorToTheAEther card) { + super(card); + } + + @Override + public AnchorToTheAEther copy() { + return new AnchorToTheAEther(this); + } +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/CalculatedDismissal.java b/Mage.Sets/src/mage/sets/magicorigins/CalculatedDismissal.java new file mode 100644 index 00000000000..5a8856b34b0 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/CalculatedDismissal.java @@ -0,0 +1,67 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.abilities.condition.common.SpellMasteryCondition; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.common.CounterUnlessPaysEffect; +import mage.abilities.effects.keyword.ScryEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.target.TargetSpell; + +/** + * + * @author LevelX2 + */ +public class CalculatedDismissal extends CardImpl { + + public CalculatedDismissal(UUID ownerId) { + super(ownerId, 48, "Calculated Dismissal", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{2}{U}"); + this.expansionSetCode = "ORI"; + + // Counter target spell unless its controller pays {3}. + this.getSpellAbility().addTarget(new TargetSpell()); + this.getSpellAbility().addEffect(new CounterUnlessPaysEffect(new GenericManaCost(3))); + // Spell mastery — If there are two or more instant and/or sorcery cards in your graveyard, scry 2. + this.getSpellAbility().addEffect(new ConditionalOneShotEffect(new ScryEffect(2), SpellMasteryCondition.getInstance(), + "
Spell mastery — If there are two or more instant and/or sorcery cards in your graveyard, scry 2")); + } + + public CalculatedDismissal(final CalculatedDismissal card) { + super(card); + } + + @Override + public CalculatedDismissal copy() { + return new CalculatedDismissal(this); + } +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/DeepSeaTerror.java b/Mage.Sets/src/mage/sets/magicorigins/DeepSeaTerror.java new file mode 100644 index 00000000000..de8288f3431 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/DeepSeaTerror.java @@ -0,0 +1,74 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.InvertCondition; +import mage.abilities.condition.common.CardsInControllerGraveCondition; +import mage.abilities.decorator.ConditionalRestrictionEffect; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.combat.CantAttackAnyPlayerSourceEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; + +/** + * + * @author LevelX2 + */ +public class DeepSeaTerror extends CardImpl { + + public DeepSeaTerror(UUID ownerId) { + super(ownerId, 52, "Deep-Sea Terror", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{4}{U}{U}"); + this.expansionSetCode = "ORI"; + this.subtype.add("Serpent"); + this.power = new MageInt(6); + this.toughness = new MageInt(6); + + // Deep-Sea Terror can't attack unless there are seven or more cards in your graveyard. + Effect effect = new ConditionalRestrictionEffect( + new CantAttackAnyPlayerSourceEffect(Duration.WhileOnBattlefield), + new InvertCondition(new CardsInControllerGraveCondition(7))); + effect.setText("{this} can't attack unless there are seven or more cards in your graveyard"); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); + + } + + public DeepSeaTerror(final DeepSeaTerror card) { + super(card); + } + + @Override + public DeepSeaTerror copy() { + return new DeepSeaTerror(this); + } +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/HarbingerOfTheTides.java b/Mage.Sets/src/mage/sets/magicorigins/HarbingerOfTheTides.java new file mode 100644 index 00000000000..54048591d95 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/HarbingerOfTheTides.java @@ -0,0 +1,85 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.PayMoreToCastAsThoughtItHadFlashAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.ReturnToHandTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.filter.predicate.permanent.TappedPredicate; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LevelX2 + */ +public class HarbingerOfTheTides extends CardImpl { + + private final static FilterCreaturePermanent filter = new FilterCreaturePermanent("tapped creature an opponent controls"); + + static { + filter.add(new TappedPredicate()); + filter.add(new ControllerPredicate(TargetController.OPPONENT)); + } + + public HarbingerOfTheTides(UUID ownerId) { + super(ownerId, 58, "Harbinger of the Tides", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{U}{U}"); + this.expansionSetCode = "ORI"; + this.subtype.add("Merfolk"); + this.subtype.add("Wizard"); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // You may cast Harbinger of the Tides as though it had flash if you pay {2} more to cast it. + this.addAbility(new PayMoreToCastAsThoughtItHadFlashAbility(this, new ManaCostsImpl<>("{2}"))); + + // When Harbinger of the Tides enters the battlefield, you may return target tapped creature an opponent controls to its owner's hand. + Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect(), true); + ability.addTarget(new TargetCreaturePermanent(filter)); + this.addAbility(ability); + + } + + public HarbingerOfTheTides(final HarbingerOfTheTides card) { + super(card); + } + + @Override + public HarbingerOfTheTides copy() { + return new HarbingerOfTheTides(this); + } +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/NivixBarrier.java b/Mage.Sets/src/mage/sets/magicorigins/NivixBarrier.java new file mode 100644 index 00000000000..7a3487f855b --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/NivixBarrier.java @@ -0,0 +1,75 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.abilities.keyword.DefenderAbility; +import mage.abilities.keyword.FlashAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.target.common.TargetAttackingCreature; + +/** + * + * @author LevelX2 + */ +public class NivixBarrier extends CardImpl { + + public NivixBarrier(UUID ownerId) { + super(ownerId, 66, "Nivix Barrier", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{3}{U}"); + this.expansionSetCode = "ORI"; + this.subtype.add("Illusion"); + this.subtype.add("Wall"); + this.power = new MageInt(0); + this.toughness = new MageInt(4); + + // Flash + this.addAbility(FlashAbility.getInstance()); + // Defender + this.addAbility(DefenderAbility.getInstance()); + // When Nivix Barrier enters the battlefield, target attacking creature gets -4/-0 until end of turn. + Ability ability = new EntersBattlefieldTriggeredAbility(new BoostTargetEffect(-4, 0, Duration.EndOfTurn), false); + ability.addTarget(new TargetAttackingCreature()); + this.addAbility(ability); + } + + public NivixBarrier(final NivixBarrier card) { + super(card); + } + + @Override + public NivixBarrier copy() { + return new NivixBarrier(this); + } +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/PsychicRebuttal.java b/Mage.Sets/src/mage/sets/magicorigins/PsychicRebuttal.java new file mode 100644 index 00000000000..cdc1ecbfb18 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/PsychicRebuttal.java @@ -0,0 +1,157 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.condition.common.SpellMasteryCondition; +import mage.abilities.effects.OneShotEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.filter.FilterSpell; +import mage.filter.predicate.ObjectPlayer; +import mage.filter.predicate.ObjectPlayerPredicate; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.game.Game; +import mage.game.stack.Spell; +import mage.game.stack.StackObject; +import mage.players.Player; +import mage.target.Target; +import mage.target.TargetSpell; + +/** + * + * @author LevelX2 + */ +public class PsychicRebuttal extends CardImpl { + + private static final FilterSpell filter = new FilterSpell("instant or sorcery spell that targets you"); + + static { + filter.add(Predicates.or(new CardTypePredicate(CardType.INSTANT), new CardTypePredicate(CardType.SORCERY))); + filter.add(new PsychicRebuttalPredicate()); + } + + public PsychicRebuttal(UUID ownerId) { + super(ownerId, 67, "Psychic Rebuttal", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{1}{U}"); + this.expansionSetCode = "ORI"; + + // Counter target instant or sorcery spell that targets you. + this.getSpellAbility().addEffect(new PsychicRebuttalEffect()); + this.getSpellAbility().addTarget(new TargetSpell(filter)); + // Spell mastery — If there are two or more instant and/or sorcery cards in your graveyard, you may copy the spell countered this way. You may choose new targets for the copy. + } + + public PsychicRebuttal(final PsychicRebuttal card) { + super(card); + } + + @Override + public PsychicRebuttal copy() { + return new PsychicRebuttal(this); + } +} + +class PsychicRebuttalEffect extends OneShotEffect { + + public PsychicRebuttalEffect() { + super(Outcome.Benefit); + this.staticText = "Counter target instant or sorcery spell that targets you." + + "
Spell mastery — If there are two or more instant and/or sorcery cards in your graveyard, you may copy the spell countered this way. You may choose new targets for the copy"; + } + + public PsychicRebuttalEffect(final PsychicRebuttalEffect effect) { + super(effect); + } + + @Override + public PsychicRebuttalEffect copy() { + return new PsychicRebuttalEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } + StackObject stackObject = game.getState().getStack().getStackObject(getTargetPointer().getFirst(game, source)); + if (stackObject != null) { + game.getStack().counter(stackObject.getId(), source.getSourceId(), game); + + if (SpellMasteryCondition.getInstance().apply(game, source) + && controller.chooseUse(Outcome.PlayForFree, "Copy " + stackObject.getName() + " (you may choose new targets for the copy)?", source, game)) { + + Spell copy = ((Spell) stackObject).copySpell(); + copy.setControllerId(source.getControllerId()); + copy.setCopiedSpell(true); + game.getStack().push(copy); + copy.chooseNewTargets(game, source.getControllerId()); + Player player = game.getPlayer(source.getControllerId()); + String activateMessage = copy.getActivatedMessage(game); + if (activateMessage.startsWith(" casts ")) { + activateMessage = activateMessage.substring(6); + } + game.informPlayers(player.getLogName() + activateMessage); + } + + return true; + } + return false; + } +} + +class PsychicRebuttalPredicate implements ObjectPlayerPredicate> { + + @Override + public boolean apply(ObjectPlayer input, Game game) { + UUID controllerId = input.getPlayerId(); + if (controllerId == null) { + return false; + } + for (UUID modeId : input.getObject().getStackAbility().getModes().getSelectedModes()) { + input.getObject().getStackAbility().getModes().setActiveMode(modeId); + for (Target target : input.getObject().getStackAbility().getTargets()) { + for (UUID targetId : target.getTargets()) { + if (controllerId.equals(targetId)) { + return true; + } + } + } + } + return false; + } + + @Override + public String toString() { + return "spell that targets you"; + } +} diff --git a/Mage/src/mage/abilities/common/PayMoreToCastAsThoughtItHadFlashAbility.java b/Mage/src/mage/abilities/common/PayMoreToCastAsThoughtItHadFlashAbility.java new file mode 100644 index 00000000000..7045c08433b --- /dev/null +++ b/Mage/src/mage/abilities/common/PayMoreToCastAsThoughtItHadFlashAbility.java @@ -0,0 +1,52 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package mage.abilities.common; + +import mage.abilities.SpellAbility; +import mage.abilities.costs.mana.ManaCosts; +import mage.cards.Card; +import mage.constants.SpellAbilityType; +import mage.constants.TimingRule; +import mage.constants.Zone; +import mage.util.CardUtil; + +/** + * + * @author LevelX2 + */ +public class PayMoreToCastAsThoughtItHadFlashAbility extends SpellAbility { + + private final ManaCosts costsToAdd; + + public PayMoreToCastAsThoughtItHadFlashAbility(Card card, ManaCosts costsToAdd) { + super(card.getSpellAbility().getManaCosts().copy(), card.getName() + " as though it had flash", Zone.HAND, SpellAbilityType.BASE_ALTERNATE); + this.costsToAdd = costsToAdd; + this.timing = TimingRule.INSTANT; + + CardUtil.increaseCost(this, costsToAdd); + } + + public PayMoreToCastAsThoughtItHadFlashAbility(final PayMoreToCastAsThoughtItHadFlashAbility ability) { + super(ability); + this.costsToAdd = ability.costsToAdd; + } + + @Override + public PayMoreToCastAsThoughtItHadFlashAbility copy() { + return new PayMoreToCastAsThoughtItHadFlashAbility(this); + } + + @Override + public String getRule(boolean all) { + return getRule(); + } + + @Override + public String getRule() { + return "You may cast {this} as though it had flash if you pay " + costsToAdd.getText() + " more to cast it. (You may cast it any time you could cast an instant)"; + } + +} From 863df0606968f06c55c8d0670f84d2754d29f925 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sun, 5 Jul 2015 02:44:11 +0200 Subject: [PATCH 058/105] [ORI] 3 white cards. --- .../sets/magicorigins/SuppressionBonds.java | 77 ++++++++ .../sets/magicorigins/SwiftReckoning.java | 80 +++++++++ .../sets/magicorigins/TragicArrogance.java | 170 ++++++++++++++++++ 3 files changed, 327 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/magicorigins/SuppressionBonds.java create mode 100644 Mage.Sets/src/mage/sets/magicorigins/SwiftReckoning.java create mode 100644 Mage.Sets/src/mage/sets/magicorigins/TragicArrogance.java diff --git a/Mage.Sets/src/mage/sets/magicorigins/SuppressionBonds.java b/Mage.Sets/src/mage/sets/magicorigins/SuppressionBonds.java new file mode 100644 index 00000000000..db0b6fc7325 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/SuppressionBonds.java @@ -0,0 +1,77 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.combat.CantBlockAttackActivateAttachedEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.target.TargetPermanent; +import mage.target.common.TargetNonlandPermanent; + +/** + * + * @author LevelX2 + */ +public class SuppressionBonds extends CardImpl { + + public SuppressionBonds(UUID ownerId) { + super(ownerId, 34, "Suppression Bonds", Rarity.COMMON, new CardType[]{CardType.ENCHANTMENT}, "{3}{W}"); + this.expansionSetCode = "ORI"; + this.subtype.add("Aura"); + + // Enchant nonland permanent + TargetPermanent auraTarget = new TargetNonlandPermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.Detriment)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + + // Enchanted permanent can't attack or block, and its activated abilities can't be actiated. + Effect effect = new CantBlockAttackActivateAttachedEffect(); + effect.setText("Enchanted permanent can't attack or block, and its activated abilities can't be actiated"); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantBlockAttackActivateAttachedEffect())); + } + + public SuppressionBonds(final SuppressionBonds card) { + super(card); + } + + @Override + public SuppressionBonds copy() { + return new SuppressionBonds(this); + } +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/SwiftReckoning.java b/Mage.Sets/src/mage/sets/magicorigins/SwiftReckoning.java new file mode 100644 index 00000000000..2d34a1fe360 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/SwiftReckoning.java @@ -0,0 +1,80 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.SpellMasteryCondition; +import mage.abilities.decorator.ConditionalAsThoughEffect; +import mage.abilities.effects.AsThoughEffect; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.effects.common.continuous.CastAsThoughItHadFlashSourceEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.TappedPredicate; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LevelX2 + */ +public class SwiftReckoning extends CardImpl { + + private final static FilterCreaturePermanent filter = new FilterCreaturePermanent("tapped creature"); + + static { + filter.add(new TappedPredicate()); + } + + public SwiftReckoning(UUID ownerId) { + super(ownerId, 35, "Swift Reckoning", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{1}{W}"); + this.expansionSetCode = "ORI"; + + // Spell mastery — If there are two or more instant and/or sorcery cards in your graveyard, you may cast Swift Reckoning as though it had flash. + AsThoughEffect effect = new CastAsThoughItHadFlashSourceEffect(Duration.EndOfGame); + effect.setText("Spell mastery — If there are two or more instant and/or sorcery cards in your graveyard, you may cast {this} as though it had flash"); + this.addAbility(new SimpleStaticAbility(Zone.ALL, new ConditionalAsThoughEffect(effect, + SpellMasteryCondition.getInstance()))); + // Destroy target tapped creature. + this.getSpellAbility().addEffect(new DestroyTargetEffect()); + this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + } + + public SwiftReckoning(final SwiftReckoning card) { + super(card); + } + + @Override + public SwiftReckoning copy() { + return new SwiftReckoning(this); + } +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/TragicArrogance.java b/Mage.Sets/src/mage/sets/magicorigins/TragicArrogance.java new file mode 100644 index 00000000000..4cd7dfe7661 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/TragicArrogance.java @@ -0,0 +1,170 @@ +/* + * 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.magicorigins; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.filter.common.FilterArtifactPermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.common.FilterEnchantmentPermanent; +import mage.filter.common.FilterNonlandPermanent; +import mage.filter.common.FilterPlaneswalkerPermanent; +import mage.filter.predicate.permanent.ControllerIdPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.Target; +import mage.target.TargetPermanent; +import mage.target.common.TargetArtifactPermanent; + +/** + * + * @author LevelX2 + */ +public class TragicArrogance extends CardImpl { + + public TragicArrogance(UUID ownerId) { + super(ownerId, 38, "Tragic Arrogance", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{3}{W}{W}"); + this.expansionSetCode = "ORI"; + + // For each player, you choose from among the permanents that player controls an artifact, a creature, an enchantment, and a planeswalker. Then each player sacrifices all other nonland permanents he or she controls. + this.getSpellAbility().addEffect(new TragicArroganceffect()); + } + + public TragicArrogance(final TragicArrogance card) { + super(card); + } + + @Override + public TragicArrogance copy() { + return new TragicArrogance(this); + } +} + +class TragicArroganceffect extends OneShotEffect { + + public TragicArroganceffect() { + super(Outcome.Benefit); + this.staticText = "For each player, you choose from among the permanents that player controls an artifact, a creature, an enchantment, and a planeswalker. Then each player sacrifices all other nonland permanents he or she controls"; + } + + public TragicArroganceffect(final TragicArroganceffect effect) { + super(effect); + } + + @Override + public TragicArroganceffect copy() { + return new TragicArroganceffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + Set choosenPermanent = new HashSet<>(); + for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { + Player player = game.getPlayer(playerId); + if (player != null) { + FilterArtifactPermanent filterArtifactPermanent = new FilterArtifactPermanent("an artifact of " + player.getName()); + filterArtifactPermanent.add(new ControllerIdPredicate(playerId)); + Target target1 = new TargetArtifactPermanent(1, 1, filterArtifactPermanent, true); + + FilterCreaturePermanent filterCreaturePermanent = new FilterCreaturePermanent("a creature of " + player.getName()); + filterCreaturePermanent.add(new ControllerIdPredicate(playerId)); + Target target2 = new TargetPermanent(1, 1, new FilterCreaturePermanent(), true); + + FilterEnchantmentPermanent filterEnchantmentPermanent = new FilterEnchantmentPermanent("an enchantment of " + player.getName()); + filterEnchantmentPermanent.add(new ControllerIdPredicate(playerId)); + Target target3 = new TargetPermanent(1, 1, new FilterEnchantmentPermanent(), true); + + FilterPlaneswalkerPermanent filterPlaneswalkerPermanent = new FilterPlaneswalkerPermanent("a planeswalker of " + player.getName()); + filterPlaneswalkerPermanent.add(new ControllerIdPredicate(playerId)); + Target target4 = new TargetPermanent(1, 1, new FilterPlaneswalkerPermanent(), true); + + if (target1.canChoose(controller.getId(), game)) { + controller.chooseTarget(Outcome.Benefit, target1, source, game); + Permanent artifact = game.getPermanent(target1.getFirstTarget()); + if (artifact != null) { + choosenPermanent.add(artifact); + } + target1.clearChosen(); + } + + if (target2.canChoose(player.getId(), game)) { + controller.chooseTarget(Outcome.Benefit, target2, source, game); + Permanent creature = game.getPermanent(target2.getFirstTarget()); + if (creature != null) { + choosenPermanent.add(creature); + } + target2.clearChosen(); + } + + if (target3.canChoose(player.getId(), game)) { + controller.chooseTarget(Outcome.Benefit, target3, source, game); + Permanent enchantment = game.getPermanent(target3.getFirstTarget()); + if (enchantment != null) { + choosenPermanent.add(enchantment); + } + target3.clearChosen(); + } + + if (target4.canChoose(player.getId(), game)) { + controller.chooseTarget(Outcome.Benefit, target4, source, game); + Permanent planeswalker = game.getPermanent(target4.getFirstTarget()); + if (planeswalker != null) { + choosenPermanent.add(planeswalker); + } + target4.clearChosen(); + } + } + } + // Then each player sacrifices all other nonland permanents he or she controls + for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { + Player player = game.getPlayer(playerId); + if (player != null) { + for (Permanent permanent : game.getBattlefield().getAllActivePermanents(new FilterNonlandPermanent(), game)) { + if (!choosenPermanent.contains(permanent)) { + permanent.sacrifice(playerId, game); + } + } + } + } + + return true; + } + + return false; + } +} From 211bc20093e93a16d0d259d1d5b7ca14addbb498 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sun, 5 Jul 2015 02:48:39 +0200 Subject: [PATCH 059/105] [ORI] Fixed Wild Instincts not applying the boost before the fight. --- Mage.Sets/src/mage/sets/magicorigins/WildInstincts.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Mage.Sets/src/mage/sets/magicorigins/WildInstincts.java b/Mage.Sets/src/mage/sets/magicorigins/WildInstincts.java index 0f2d1595c4b..6c676643bcb 100644 --- a/Mage.Sets/src/mage/sets/magicorigins/WildInstincts.java +++ b/Mage.Sets/src/mage/sets/magicorigins/WildInstincts.java @@ -58,9 +58,11 @@ public class WildInstincts extends CardImpl { this.expansionSetCode = "ORI"; // Target creature you control gets +2/+2 until end of turn. It fights target creature an opponent controls. - getSpellAbility().addEffect(new BoostTargetEffect(2, 2, Duration.EndOfTurn)); + Effect effect = new BoostTargetEffect(2, 2, Duration.EndOfTurn); + effect.setApplyEffectsAfter(); + getSpellAbility().addEffect(effect); getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); - Effect effect = new FightTargetsEffect(); + effect = new FightTargetsEffect(); effect.setText("It fights target creature an opponent controls (Each deals damage equal to its power to each other)"); getSpellAbility().addEffect(effect); getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); From bb2a7a25b26212006d82c43e0da701fcf05ac1f7 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sun, 5 Jul 2015 08:57:24 +0200 Subject: [PATCH 060/105] [ORI] Topan Freeblade added missing Vigilance. --- Mage.Sets/src/mage/sets/magicorigins/TopanFreeblade.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Mage.Sets/src/mage/sets/magicorigins/TopanFreeblade.java b/Mage.Sets/src/mage/sets/magicorigins/TopanFreeblade.java index 9d3e7d6f923..813f44a0719 100644 --- a/Mage.Sets/src/mage/sets/magicorigins/TopanFreeblade.java +++ b/Mage.Sets/src/mage/sets/magicorigins/TopanFreeblade.java @@ -30,6 +30,7 @@ package mage.sets.magicorigins; import java.util.UUID; import mage.MageInt; import mage.abilities.keyword.RenownAbility; +import mage.abilities.keyword.VigilanceAbility; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Rarity; @@ -49,6 +50,8 @@ public class TopanFreeblade extends CardImpl { this.toughness = new MageInt(2); // Vigilance (Attacking doesn't cause this creature to tap.) + this.addAbility(VigilanceAbility.getInstance()); + // Renown 1 this.addAbility(new RenownAbility(1)); } From 9c53e7f984aed74c0f45d3a6944fc07403fcd1b8 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sun, 5 Jul 2015 08:58:19 +0200 Subject: [PATCH 061/105] [ORI] Renown - Fixed that renown was not applied again after creature left and returned to battlefield. --- .../cards/abilities/keywords/RenownTest.java | 102 +++++++++++++++--- .../mage/abilities/keyword/RenownAbility.java | 3 +- 2 files changed, 89 insertions(+), 16 deletions(-) diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/RenownTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/RenownTest.java index 7db71b19598..45dd3fad21e 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/RenownTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/RenownTest.java @@ -27,9 +27,12 @@ */ package org.mage.test.cards.abilities.keywords; +import mage.abilities.keyword.MenaceAbility; import mage.abilities.keyword.VigilanceAbility; import mage.constants.PhaseStep; import mage.constants.Zone; +import mage.game.permanent.Permanent; +import org.junit.Assert; import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBase; @@ -50,17 +53,17 @@ public class RenownTest extends CardTestPlayerBase { attack(3, playerA, "Knight of the Pilgrim's Road"); // 3 damage attack(5, playerA, "Knight of the Pilgrim's Road"); // 4 damage attack(7, playerA, "Knight of the Pilgrim's Road"); // 4 damage - + setStopAt(7, PhaseStep.POSTCOMBAT_MAIN); execute(); assertPowerToughness(playerA, "Knight of the Pilgrim's Road", 4, 3); - + assertLife(playerA, 20); assertLife(playerB, 9); } - + /** * Test renown trigger */ @@ -76,19 +79,19 @@ public class RenownTest extends CardTestPlayerBase { attack(3, playerA, "Relic Seeker"); // 2 damage attack(5, playerA, "Relic Seeker"); // 3 damage - + setStopAt(5, PhaseStep.POSTCOMBAT_MAIN); execute(); assertPowerToughness(playerA, "Relic Seeker", 3, 3); assertHandCount(playerA, "Veteran's Sidearm", 1); - + assertLife(playerA, 20); assertLife(playerB, 15); - } - - /** + } + + /** * Test renown state */ @Test @@ -102,18 +105,19 @@ public class RenownTest extends CardTestPlayerBase { attack(3, playerA, "Honored Hierarch"); // 1 damage attack(5, playerA, "Honored Hierarch"); // 2 damage - + setStopAt(5, PhaseStep.POSTCOMBAT_MAIN); execute(); assertPowerToughness(playerA, "Honored Hierarch", 2, 2); assertTapped("Honored Hierarch", false); assertAbility(playerA, "Honored Hierarch", VigilanceAbility.getInstance(), true); - + assertLife(playerA, 20); assertLife(playerB, 17); - } + } + /** * Test renown > 1 */ @@ -121,7 +125,7 @@ public class RenownTest extends CardTestPlayerBase { public void testRhoxMaulers() { addCard(Zone.BATTLEFIELD, playerA, "Forest", 5); // Trample - // Renown 2 + // Renown 2 addCard(Zone.HAND, playerA, "Rhox Maulers"); // 4/4 castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Rhox Maulers"); @@ -129,14 +133,82 @@ public class RenownTest extends CardTestPlayerBase { attack(3, playerA, "Rhox Maulers"); // 4 damage attack(5, playerA, "Rhox Maulers"); // 6 damage attack(7, playerA, "Rhox Maulers"); // 6 damage - + setStopAt(7, PhaseStep.POSTCOMBAT_MAIN); execute(); assertPowerToughness(playerA, "Rhox Maulers", 6, 6); - + assertLife(playerA, 20); assertLife(playerB, 4); - } + } + + /** + * Test renown is gone after zone change + * + * /** + * Test renown is gone after zone change + */ + @Test + public void testRenownGoneAfterZoneChange() { + addCard(Zone.BATTLEFIELD, playerA, "Forest", 1); + addCard(Zone.BATTLEFIELD, playerA, "Plains", 6); + // Trample + // Renown 2 + addCard(Zone.HAND, playerA, "Rhox Maulers"); // 4/4 + addCard(Zone.HAND, playerA, "Cloudshift"); // 4/4 + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Rhox Maulers"); + castSpell(5, PhaseStep.POSTCOMBAT_MAIN, playerA, "Cloudshift", "Rhox Maulers"); + + attack(3, playerA, "Rhox Maulers"); // 4 damage + attack(5, playerA, "Rhox Maulers"); // 6 damage + attack(7, playerA, "Rhox Maulers"); // 4 damage + + setStopAt(7, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertLife(playerA, 20); + assertLife(playerB, 6); + + assertPowerToughness(playerA, "Rhox Maulers", 4, 4); + Permanent rhoxMaulers = getPermanent("Rhox Maulers", playerA); + Assert.assertEquals("may not be renown", false, rhoxMaulers.isRenown()); + + } + + /* + Test renown can be gained again after zone change + */ + @Test + public void testRenownGainedGainAfterZoneChange() { + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1); + addCard(Zone.BATTLEFIELD, playerA, "Plains", 2); + // Renown 1 + // As long as Goblin Glory Chaser is renowned, it has menace. + addCard(Zone.HAND, playerA, "Goblin Glory Chaser"); // 1/1 {R} + addCard(Zone.HAND, playerA, "Cloudshift"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Goblin Glory Chaser"); + castSpell(5, PhaseStep.POSTCOMBAT_MAIN, playerA, "Cloudshift", "Goblin Glory Chaser"); + + attack(3, playerA, "Goblin Glory Chaser"); // 1 damage + attack(5, playerA, "Goblin Glory Chaser"); // 2 damage + attack(7, playerA, "Goblin Glory Chaser"); // 1 damage + attack(9, playerA, "Goblin Glory Chaser"); // 2 damage + + setStopAt(9, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + Permanent goblin = getPermanent("Goblin Glory Chaser", playerA); + Assert.assertEquals("has has renown", true, goblin.isRenown()); + assertAbility(playerA, "Goblin Glory Chaser", new MenaceAbility(), true); + assertPowerToughness(playerA, "Goblin Glory Chaser", 2, 2); + + assertLife(playerA, 20); + assertLife(playerB, 14); + + } + } diff --git a/Mage/src/mage/abilities/keyword/RenownAbility.java b/Mage/src/mage/abilities/keyword/RenownAbility.java index f6f3f778257..96a8b1e8e75 100644 --- a/Mage/src/mage/abilities/keyword/RenownAbility.java +++ b/Mage/src/mage/abilities/keyword/RenownAbility.java @@ -48,7 +48,8 @@ public class RenownAbility extends TriggeredAbilityImpl { @Override public boolean checkInterveningIfClause(Game game) { - return getSourceObject(game) != null && !((Permanent) getSourceObject(game)).isRenown(); + Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(getSourceId()); + return sourcePermanent != null && !sourcePermanent.isRenown(); } @Override From 3a69959e46bbcd282e6f55a74516c36ef2e8ee8b Mon Sep 17 00:00:00 2001 From: LoneFox Date: Sun, 5 Jul 2015 10:07:44 +0300 Subject: [PATCH 062/105] Implement cards: Foundry of the Consuls, Grab the Reins, and Mage-Ring Network --- .../magicorigins/FoundryOfTheConsuls.java | 73 +++++++++ .../sets/magicorigins/MageRingNetwork.java | 80 ++++++++++ .../src/mage/sets/mirrodin/GrabTheReins.java | 149 ++++++++++++++++++ 3 files changed, 302 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/magicorigins/FoundryOfTheConsuls.java create mode 100644 Mage.Sets/src/mage/sets/magicorigins/MageRingNetwork.java create mode 100644 Mage.Sets/src/mage/sets/mirrodin/GrabTheReins.java diff --git a/Mage.Sets/src/mage/sets/magicorigins/FoundryOfTheConsuls.java b/Mage.Sets/src/mage/sets/magicorigins/FoundryOfTheConsuls.java new file mode 100644 index 00000000000..954e9edf44c --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/FoundryOfTheConsuls.java @@ -0,0 +1,73 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.mana.ColorlessManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.permanent.token.ThopterColorlessToken; + +/** + * + * @author LoneFox + + */ +public class FoundryOfTheConsuls extends CardImpl { + + public FoundryOfTheConsuls(UUID ownerId) { + super(ownerId, 247, "Foundry of the Consuls", Rarity.UNCOMMON, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "ORI"; + + // {T}: Add {1} to your mana pool. + this.addAbility(new ColorlessManaAbility()); + // {5}, {T}, Sacrifice Foundry of the Consuls: Put two 1/1 colorless Thopter artifact creature tokens with flying onto the battlefield. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new ThopterColorlessToken("ORI"), 2), + new ManaCostsImpl("{5}")); + ability.addCost(new TapSourceCost()); + ability.addCost(new SacrificeSourceCost()); + this.addAbility(ability); + } + + public FoundryOfTheConsuls(final FoundryOfTheConsuls card) { + super(card); + } + + @Override + public FoundryOfTheConsuls copy() { + return new FoundryOfTheConsuls(this); + } +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/MageRingNetwork.java b/Mage.Sets/src/mage/sets/magicorigins/MageRingNetwork.java new file mode 100644 index 00000000000..6ee273ea26e --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/MageRingNetwork.java @@ -0,0 +1,80 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.RemoveVariableCountersSourceCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.dynamicvalue.common.RemovedCountersForCostValue; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.mana.ColorlessManaAbility; +import mage.abilities.mana.DynamicManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.counters.CounterType; + +/** + * + * @author LoneFox + + */ +public class MageRingNetwork extends CardImpl { + + public MageRingNetwork(UUID ownerId) { + super(ownerId, 249, "Mage-Ring Network", Rarity.UNCOMMON, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "ORI"; + + // {t}: Add {1} to your mana pool. + this.addAbility(new ColorlessManaAbility()); + // {1}, {t}: Put a storage counter on Mage-Ring Network. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.STORAGE.createInstance()), + new ManaCostsImpl("{1}")); + ability.addCost(new TapSourceCost()); + this.addAbility(ability); + // {t}, Remove X storage counters from Mage-Ring Network: Add {x} to your mana pool. + ability = new DynamicManaAbility(Mana.ColorlessMana, new RemovedCountersForCostValue(), "Add {X} to your mana pool"); + ability.addCost(new RemoveVariableCountersSourceCost(CounterType.STORAGE.createInstance(), + "Remove X storage counters from {this}")); + this.addAbility(ability); + } + + public MageRingNetwork(final MageRingNetwork card) { + super(card); + } + + @Override + public MageRingNetwork copy() { + return new MageRingNetwork(this); + } +} diff --git a/Mage.Sets/src/mage/sets/mirrodin/GrabTheReins.java b/Mage.Sets/src/mage/sets/mirrodin/GrabTheReins.java new file mode 100644 index 00000000000..905ef340f27 --- /dev/null +++ b/Mage.Sets/src/mage/sets/mirrodin/GrabTheReins.java @@ -0,0 +1,149 @@ +/* + * 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.mirrodin; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.effects.common.continuous.GainControlTargetEffect; +import mage.abilities.keyword.EntwineAbility; +import mage.abilities.keyword.HasteAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.Target; +import mage.target.common.TargetCreatureOrPlayer; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LoneFox + + */ +public class GrabTheReins extends CardImpl { + + public GrabTheReins(UUID ownerId) { + super(ownerId, 95, "Grab the Reins", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{3}{R}"); + this.expansionSetCode = "MRD"; + + // Choose one - + this.getSpellAbility().getModes().setMinModes(1); + this.getSpellAbility().getModes().setMaxModes(1); + // Until end of turn, you gain control of target creature and it gains haste; + Effect effect = new GainControlTargetEffect(Duration.EndOfTurn); + effect.setText("Until end of turn, you gain control of target creature"); + effect.setApplyEffectsAfter(); + this.getSpellAbility().addEffect(effect); + effect = new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn); + effect.setText("and it gains haste"); + this.getSpellAbility().addEffect(effect); + TargetCreaturePermanent target = new TargetCreaturePermanent(); + target.setTargetName("a creature to take control of"); + this.getSpellAbility().addTarget(target); + // or sacrifice a creature, then Grab the Reins deals damage equal to that creature's power to target creature or player. + Mode mode = new Mode(); + mode.getEffects().add(new GrabTheReinsEffect()); + TargetCreatureOrPlayer target2 = new TargetCreatureOrPlayer(); + target2.setTargetName("a creature or player to damage"); + mode.getTargets().add(target2); + this.getSpellAbility().getModes().addMode(mode); + + // Entwine {2}{R} + this.addAbility(new EntwineAbility("{2}{R}")); + } + + public GrabTheReins(final GrabTheReins card) { + super(card); + } + + @Override + public GrabTheReins copy() { + return new GrabTheReins(this); + } +} + +class GrabTheReinsEffect extends OneShotEffect { + + public GrabTheReinsEffect() { + super(Outcome.Damage); + staticText = "sacrifice a creature. {this} deals damage equal to the sacrificed creature's power to target creature or player"; + } + + public GrabTheReinsEffect(final GrabTheReinsEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + UUID controllerId = source.getControllerId(); + Target target = new TargetCreaturePermanent(); + target.setNotTarget(true); + target.setTargetName("a creature to sacrifice"); + if(!target.canChoose(source.getSourceId(), controllerId, game)) { + return false; + } + Player player = game.getPlayer(controllerId); + if(player != null) { + player.chooseTarget(Outcome.Sacrifice, target, source, game); + Permanent creatureToSacrifice = game.getPermanent(target.getTargets().get(0)); + int amount = creatureToSacrifice.getPower().getValue(); + if(!creatureToSacrifice.sacrifice(creatureToSacrifice.getId(), game)) { + return false; + } + if (amount > 0) { + Permanent permanent = game.getPermanent(source.getFirstTarget()); + if (permanent != null) { + permanent.damage(amount, source.getSourceId(), game, false, true); + return true; + } + player = game.getPlayer(source.getFirstTarget()); + if (player != null) { + player.damage(amount, source.getSourceId(), game, false, true); + return true; + } + } + else { + return true; + } + } + return false; + } + + @Override + public GrabTheReinsEffect copy() { + return new GrabTheReinsEffect(this); + } +} From 3dd101e63f31934c2da83a492772e0687f56626b Mon Sep 17 00:00:00 2001 From: LoneFox Date: Sun, 5 Jul 2015 12:24:59 +0300 Subject: [PATCH 063/105] Implement cards: Call of the Full Moon, Embermaw Hellion, Sword of the Animist, and Throwing Knife --- .../sets/magicorigins/CallOfTheFullMoon.java | 94 +++++++++++++ .../sets/magicorigins/EmbermawHellion.java | 125 ++++++++++++++++++ .../sets/magicorigins/SwordOfTheAnimist.java | 75 +++++++++++ .../mage/sets/magicorigins/ThrowingKnife.java | 80 +++++++++++ 4 files changed, 374 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/magicorigins/CallOfTheFullMoon.java create mode 100644 Mage.Sets/src/mage/sets/magicorigins/EmbermawHellion.java create mode 100644 Mage.Sets/src/mage/sets/magicorigins/SwordOfTheAnimist.java create mode 100644 Mage.Sets/src/mage/sets/magicorigins/ThrowingKnife.java diff --git a/Mage.Sets/src/mage/sets/magicorigins/CallOfTheFullMoon.java b/Mage.Sets/src/mage/sets/magicorigins/CallOfTheFullMoon.java new file mode 100644 index 00000000000..cb0b34f8d31 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/CallOfTheFullMoon.java @@ -0,0 +1,94 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbility; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.TwoOrMoreSpellsWereCastLastTurnCondition; +import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.SacrificeSourceEffect; +import mage.abilities.effects.common.continuous.BoostEnchantedEffect; +import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.constants.AttachmentType; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LoneFox + + */ +public class CallOfTheFullMoon extends CardImpl { + + public CallOfTheFullMoon(UUID ownerId) { + super(ownerId, 134, "Call of the Full Moon", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT}, "{1}{R}"); + this.expansionSetCode = "ORI"; + this.subtype.add("Aura"); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.Benefit)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + // Enchanted creature gets +3/+2 and has trample. + ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEnchantedEffect(3, 2, Duration.WhileOnBattlefield)); + Effect effect = new GainAbilityAttachedEffect(TrampleAbility.getInstance(), AttachmentType.AURA); + effect.setText("and has trample."); + ability.addEffect(effect); + this.addAbility(ability); + + // At the beginning of each upkeep, if a player cast two or more spells last turn, sacrifice Call of the Full Moon. + TriggeredAbility ability2 = new BeginningOfUpkeepTriggeredAbility(new SacrificeSourceEffect(), TargetController.ANY, false); + this.addAbility(new ConditionalTriggeredAbility(ability2, TwoOrMoreSpellsWereCastLastTurnCondition.getInstance(), + "At the beginning of each upkeep, if a player cast two or more spells last turn, sacrifice {this}.")); + } + + public CallOfTheFullMoon(final CallOfTheFullMoon card) { + super(card); + } + + @Override + public CallOfTheFullMoon copy() { + return new CallOfTheFullMoon(this); + } +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/EmbermawHellion.java b/Mage.Sets/src/mage/sets/magicorigins/EmbermawHellion.java new file mode 100644 index 00000000000..5632b9cfcf4 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/EmbermawHellion.java @@ -0,0 +1,125 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.keyword.TrampleAbility; +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.game.Game; +import mage.game.events.DamagedPlayerEvent; +import mage.game.events.GameEvent.EventType; +import mage.game.events.GameEvent; + +/** + * + * @author LoneFox + + */ +public class EmbermawHellion extends CardImpl { + + public EmbermawHellion(UUID ownerId) { + super(ownerId, 141, "Embermaw Hellion", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{3}{R}{R}"); + this.expansionSetCode = "ORI"; + this.subtype.add("Hellion"); + this.power = new MageInt(4); + this.toughness = new MageInt(5); + + // Trample + this.addAbility(TrampleAbility.getInstance()); + // If another red source you control would deal damage to a permanent or player, it deals that much damage plus 1 to that permanent or player instead. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new EmbermawHellionEffect())); + } + + public EmbermawHellion(final EmbermawHellion card) { + super(card); + } + + @Override + public EmbermawHellion copy() { + return new EmbermawHellion(this); + } +} + +class EmbermawHellionEffect extends ReplacementEffectImpl { + + EmbermawHellionEffect() { + super(Duration.WhileOnBattlefield, Outcome.Benefit); + staticText = "If another red source you control would deal damage to a permanent or player, it deals that much damage plus 1 to that permanent or player instead."; + } + + EmbermawHellionEffect(final EmbermawHellionEffect effect) { + super(effect); + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + switch(event.getType()) { + case DAMAGE_CREATURE: + case DAMAGE_PLANESWALKER: + case DAMAGE_PLAYER: + return true; + default: + return false; + } + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if(source.getControllerId().equals(game.getControllerId(event.getSourceId()))) { + Card card = game.getCard(event.getSourceId()); + return card != null && card.getColor(game).isRed() && !card.getId().equals(source.getSourceId()); + } + return false; + } + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + event.setAmount(event.getAmount() + 1); + return false; + } + + @Override + public EmbermawHellionEffect copy() { + return new EmbermawHellionEffect(this); + } + +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/SwordOfTheAnimist.java b/Mage.Sets/src/mage/sets/magicorigins/SwordOfTheAnimist.java new file mode 100644 index 00000000000..b58fb4be486 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/SwordOfTheAnimist.java @@ -0,0 +1,75 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.abilities.common.AttacksAttachedTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.continuous.BoostEquippedEffect; +import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect; +import mage.abilities.keyword.EquipAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterBasicLandCard; +import mage.target.common.TargetCardInLibrary; + +/** + * + * @author LoneFox + + */ +public class SwordOfTheAnimist extends CardImpl { + + public SwordOfTheAnimist(UUID ownerId) { + super(ownerId, 240, "Sword of the Animist", Rarity.RARE, new CardType[]{CardType.ARTIFACT}, "{2}"); + this.expansionSetCode = "ORI"; + this.supertype.add("Legendary"); + this.subtype.add("Equipment"); + + // Equipped creature gets +1/+1. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(1, 1))); + // Whenever equipped creature attacks, you may search your library for a basic land card, put it onto the battlefield tapped, then shuffle your library. + TargetCardInLibrary target = new TargetCardInLibrary(new FilterBasicLandCard()); + this.addAbility(new AttacksAttachedTriggeredAbility(new SearchLibraryPutInPlayEffect(target, true), true)); + // Equip {2} + this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(2))); + } + + public SwordOfTheAnimist(final SwordOfTheAnimist card) { + super(card); + } + + @Override + public SwordOfTheAnimist copy() { + return new SwordOfTheAnimist(this); + } +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/ThrowingKnife.java b/Mage.Sets/src/mage/sets/magicorigins/ThrowingKnife.java new file mode 100644 index 00000000000..fa810899d79 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/ThrowingKnife.java @@ -0,0 +1,80 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.AttacksAttachedTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.SacrificeSourceEffect; +import mage.abilities.effects.common.continuous.BoostEquippedEffect; +import mage.abilities.keyword.EquipAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.target.common.TargetCreatureOrPlayer; + +/** + * + * @author LoneFox + + */ +public class ThrowingKnife extends CardImpl { + + public ThrowingKnife(UUID ownerId) { + super(ownerId, 241, "Throwing Knife", Rarity.UNCOMMON, new CardType[]{CardType.ARTIFACT}, "{2}"); + this.expansionSetCode = "ORI"; + this.subtype.add("Equipment"); + + // Equipped creature gets +2/+0. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(2, 0))); + // Whenever equipped creature attacks, you may sacrifice Throwing Knife. If you do, Throwing Knife deals 2 damage to target creature or player. + Effect effect = new SacrificeSourceEffect(); + effect.setText("you may sacrifice {this}. If you do, "); + Ability ability = new AttacksAttachedTriggeredAbility(new SacrificeSourceEffect(), true); + ability.addEffect(new DamageTargetEffect(2)); + ability.addTarget(new TargetCreatureOrPlayer()); + this.addAbility(ability); + // Equip {2} + this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(2))); + } + + public ThrowingKnife(final ThrowingKnife card) { + super(card); + } + + @Override + public ThrowingKnife copy() { + return new ThrowingKnife(this); + } +} From b2ed48da874ebc6475b7c4d2aaebb0357efbcdce Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sun, 5 Jul 2015 11:48:19 +0200 Subject: [PATCH 064/105] Fixed a bug about must be blocked requirement forcing the blocker to block multiple attackers locking the game. --- .../requirement/BlockRequirementTest.java | 36 ++++++ .../mage/cards/repository/CardRepository.java | 2 +- Mage/src/mage/game/combat/Combat.java | 110 +++++++++++------- 3 files changed, 103 insertions(+), 45 deletions(-) diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/requirement/BlockRequirementTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/requirement/BlockRequirementTest.java index cbd8ba96d6c..6797cdc95a5 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/requirement/BlockRequirementTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/requirement/BlockRequirementTest.java @@ -76,4 +76,40 @@ public class BlockRequirementTest extends CardTestPlayerBase { assertPermanentCount(playerA, "Silvercoat Lion", 1); assertPermanentCount(playerB, "Prized Unicorn", 1); } + + /** + * Joraga Invocation is bugged big time. He cast it with 2 creatures out. I + * only had one untapped creature. Blocked one of his, hit Done, error + * message popped up saying the other one needed to be blocked in an + * infinite loop. Had to shut down the program via Task Manager. + */ + @Test + public void testJoragaInvocationTest() { + addCard(Zone.BATTLEFIELD, playerB, "Forest", 6); + // Each creature you control gets +3/+3 until end of turn and must be blocked this turn if able. + addCard(Zone.HAND, playerB, "Joraga Invocation"); + addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion"); // 2/2 + addCard(Zone.BATTLEFIELD, playerB, "Pillarfield Ox"); // 2/4 + + // Swampwalk + addCard(Zone.BATTLEFIELD, playerA, "Bog Wraith"); // 3/3 + + castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Joraga Invocation"); + + // Silvercoat Lion has not to block because it has to pay {3} to block + attack(2, playerB, "Silvercoat Lion"); + attack(2, playerB, "Pillarfield Ox"); + block(2, playerA, "Bog Wraith", "Pillarfield Ox"); + + setStopAt(2, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertLife(playerA, 15); + + assertGraveyardCount(playerB, "Joraga Invocation", 1); + assertPowerToughness(playerB, "Silvercoat Lion", 5, 5); + assertPowerToughness(playerB, "Pillarfield Ox", 5, 7); + assertGraveyardCount(playerA, "Bog Wraith", 1); + } + } diff --git a/Mage/src/mage/cards/repository/CardRepository.java b/Mage/src/mage/cards/repository/CardRepository.java index d4364e3275a..970c5670c3d 100644 --- a/Mage/src/mage/cards/repository/CardRepository.java +++ b/Mage/src/mage/cards/repository/CardRepository.java @@ -60,7 +60,7 @@ public enum CardRepository { // raise this if db structure was changed private static final long CARD_DB_VERSION = 39; // raise this if new cards were added to the server - private static final long CARD_CONTENT_VERSION = 22; + private static final long CARD_CONTENT_VERSION = 23; private final Random random = new Random(); private Dao cardDao; diff --git a/Mage/src/mage/game/combat/Combat.java b/Mage/src/mage/game/combat/Combat.java index 5c8a5154da7..5ba13a273a3 100644 --- a/Mage/src/mage/game/combat/Combat.java +++ b/Mage/src/mage/game/combat/Combat.java @@ -665,7 +665,7 @@ public class Combat implements Serializable, Copyable { } - // check attacking creature mustBeBlockedByAtLeastOne + // check if for attacking creatures with mustBeBlockedByAtLeastOne requirements are fulfilled for (UUID toBeBlockedCreatureId : mustBeBlockedByAtLeastOne.keySet()) { for (CombatGroup combatGroup : game.getCombat().getGroups()) { if (combatGroup.getBlockers().isEmpty() && combatGroup.getAttackers().contains(toBeBlockedCreatureId)) { @@ -675,56 +675,27 @@ public class Combat implements Serializable, Copyable { if (toBeBlockedCreature != null) { // check if all possible blocker block other creatures they are forced to block // read through all possible blockers - boolean possibleBlockerAvailable = false; for (UUID possibleBlockerId : mustBeBlockedByAtLeastOne.get(toBeBlockedCreatureId)) { - Set forcingAttackers = creatureMustBlockAttackers.get(possibleBlockerId); - if (forcingAttackers == null) { - // no other creature forces the blocker to block -> it's available - possibleBlockerAvailable = true; - break; + String blockRequiredMessage = isCreatureDoingARequiredBlock(possibleBlockerId, mustBeBlockedByAtLeastOne, game); + if (blockRequiredMessage != null) { // message means not required + game.informPlayer(controller, blockRequiredMessage + "It's a requirement to block " + toBeBlockedCreature.getIdName()); + return false; } - // get the attackers he blocks - List blockedAttackers = null; - for (CombatGroup combatGroupToCheck : game.getCombat().getGroups()) { - if (combatGroupToCheck.getBlockers().contains(possibleBlockerId)) { - blockedAttackers = combatGroupToCheck.getAttackers(); - break; - } - } - if (blockedAttackers == null) { - // he blocks no other creature -> it's available - possibleBlockerAvailable = true; - break; - } - - // get attackers forcing the possible blocker to block - possibleBlockerAvailable = true; - for (UUID blockedAttackerId : blockedAttackers) { - if (creatureMustBlockAttackers.get(possibleBlockerId).contains(blockedAttackerId)) { - possibleBlockerAvailable = false; - break; - } - } - if (possibleBlockerAvailable) { - break; - } - } - if (possibleBlockerAvailable) { - if (!game.isSimulation()) { - game.informPlayer(controller, new StringBuilder(toBeBlockedCreature.getLogName()).append(" has to be blocked by at least one creature.").toString()); - } - return false; } } } else { // take the first potential blocker from the set to block for the AI - UUID blockingCreatureId = mustBeBlockedByAtLeastOne.get(toBeBlockedCreatureId).iterator().next(); - Permanent blockingCreature = game.getPermanent(blockingCreatureId); - if (blockingCreature != null) { - Player defender = game.getPlayer(blockingCreature.getControllerId()); - if (defender != null) { - defender.declareBlocker(defender.getId(), blockingCreatureId, toBeBlockedCreatureId, game); + for (UUID possibleBlockerId : mustBeBlockedByAtLeastOne.get(toBeBlockedCreatureId)) { + String blockRequiredMessage = isCreatureDoingARequiredBlock(possibleBlockerId, mustBeBlockedByAtLeastOne, game); + if (blockRequiredMessage != null) { + // set the block + Permanent possibleBlocker = game.getPermanent(possibleBlockerId); + Player defender = game.getPlayer(possibleBlocker.getControllerId()); + if (defender != null) { + defender.declareBlocker(defender.getId(), possibleBlockerId, toBeBlockedCreatureId, game); + } + break; } } } @@ -800,6 +771,48 @@ public class Combat implements Serializable, Copyable { return true; } + /** + * Checks if a possible creature for a block is already doing another + * required block + * + * @param possibleBlockerId + * @param mustBeBlockedByAtLeastOne + * @param game + * @return null block is required otherwise message with reason why not + */ + protected String isCreatureDoingARequiredBlock(UUID possibleBlockerId, Map> mustBeBlockedByAtLeastOne, Game game) { + Permanent possibleBlocker = game.getPermanent(possibleBlockerId); + if (possibleBlocker != null) { + if (possibleBlocker.getBlocking() == 0) { + return possibleBlocker.getIdName() + " does not block, but could block creatures with requirement to be blocked."; + } + Set forcingAttackers = creatureMustBlockAttackers.get(possibleBlockerId); + if (forcingAttackers == null) { + // no other creature forces the blocker to block -> it's available + // check now, if it already blocks a creature that mustBeBlockedByAtLeastOne + if (possibleBlocker.getBlocking() > 0) { + CombatGroup combatGroupOfPossibleBlocker = findGroupOfBlocker(possibleBlockerId); + for (UUID blockedAttackerId : combatGroupOfPossibleBlocker.getAttackers()) { + if (mustBeBlockedByAtLeastOne.containsKey(blockedAttackerId)) { + // blocks a creature that has to be blocked by at least one + if (combatGroupOfPossibleBlocker.getBlockers().size() == 1) { + // the creature blocks alone already a creature that has to be blocked by at least one, + // so this is ok + return null; + } + // TODO: Check if the attacker is already blocked by another creature + // and despite there is need that this attacker blocks this attacker also + // I don't know why + Permanent blockedAttacker = game.getPermanent(blockedAttackerId); + return possibleBlocker.getIdName() + " blocks with other creatures " + blockedAttacker.getIdName() + ", which has to be blocked by only one creature. "; + } + } + } + } + } + return null; + } + /** * Checks the canBeBlockedCheckAfter RestrictionEffect Is the block still * valid after all block decisions are done @@ -1037,6 +1050,15 @@ public class Combat implements Serializable, Copyable { return null; } + public CombatGroup findGroupOfBlocker(UUID blockerId) { + for (CombatGroup group : groups) { + if (group.getBlockers().contains(blockerId)) { + return group; + } + } + return null; + } + // public int totalUnblockedDamage(Game game) { // int total = 0; // for (CombatGroup group : groups) { From a4f76a1fb81963fe8c50e3aceded888c2f5a9783 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sun, 5 Jul 2015 11:51:51 +0200 Subject: [PATCH 065/105] Fixed another bug of renown. --- .../org/mage/test/cards/abilities/keywords/RenownTest.java | 4 ++-- Mage/src/mage/game/permanent/PermanentImpl.java | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/RenownTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/RenownTest.java index 45dd3fad21e..533c50b39b4 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/RenownTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/RenownTest.java @@ -172,9 +172,9 @@ public class RenownTest extends CardTestPlayerBase { assertLife(playerA, 20); assertLife(playerB, 6); - assertPowerToughness(playerA, "Rhox Maulers", 4, 4); + assertPowerToughness(playerA, "Rhox Maulers", 6, 6); // renown again in turn 7 after the attack Permanent rhoxMaulers = getPermanent("Rhox Maulers", playerA); - Assert.assertEquals("may not be renown", false, rhoxMaulers.isRenown()); + Assert.assertEquals("may not be renown", true, rhoxMaulers.isRenown()); } diff --git a/Mage/src/mage/game/permanent/PermanentImpl.java b/Mage/src/mage/game/permanent/PermanentImpl.java index c44b666bff4..b71c09a9a31 100644 --- a/Mage/src/mage/game/permanent/PermanentImpl.java +++ b/Mage/src/mage/game/permanent/PermanentImpl.java @@ -176,6 +176,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent { this.maxBlockedBy = permanent.maxBlockedBy; this.transformed = permanent.transformed; this.monstrous = permanent.monstrous; + this.renown = permanent.renown; this.pairedCard = permanent.pairedCard; this.timesLoyaltyUsed = permanent.timesLoyaltyUsed; From 6fa2d146a90e0be75524902c8c6ef0f21c9cd19c Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sun, 5 Jul 2015 12:03:54 +0200 Subject: [PATCH 066/105] * Nissa's Pilgrimage - Fixed a bug that the search library dialog was not shown. --- Mage.Sets/src/mage/sets/magicorigins/NissasPilgrimage.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mage.Sets/src/mage/sets/magicorigins/NissasPilgrimage.java b/Mage.Sets/src/mage/sets/magicorigins/NissasPilgrimage.java index f9599cb6418..7fd632cb301 100644 --- a/Mage.Sets/src/mage/sets/magicorigins/NissasPilgrimage.java +++ b/Mage.Sets/src/mage/sets/magicorigins/NissasPilgrimage.java @@ -105,7 +105,7 @@ class NissasPilgrimageEffect extends OneShotEffect { number++; } TargetCardInLibrary target = new TargetCardInLibrary(0, number, filter); - controller.chooseTarget(outcome, target, source, game); + controller.searchLibrary(target, game); if (!target.getTargets().isEmpty()) { Cards cards = new CardsImpl(target.getTargets()); controller.revealCards(sourceObject.getIdName(), cards, game); From ab6345e7cf05bc1dbd801d12472751aa91db88f3 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sun, 5 Jul 2015 12:49:36 +0200 Subject: [PATCH 067/105] [ORI] Added Touch of Moonglove and Thornbow Archer. --- .../sets/magicorigins/ThornbowArcher.java | 110 ++++++++++++ .../sets/magicorigins/TouchOfMoonglove.java | 167 ++++++++++++++++++ .../mage/sets/urzassaga/VampiricEmbrace.java | 23 ++- 3 files changed, 288 insertions(+), 12 deletions(-) create mode 100644 Mage.Sets/src/mage/sets/magicorigins/ThornbowArcher.java create mode 100644 Mage.Sets/src/mage/sets/magicorigins/TouchOfMoonglove.java diff --git a/Mage.Sets/src/mage/sets/magicorigins/ThornbowArcher.java b/Mage.Sets/src/mage/sets/magicorigins/ThornbowArcher.java new file mode 100644 index 00000000000..e1ae93705b1 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/ThornbowArcher.java @@ -0,0 +1,110 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.game.Game; +import mage.players.Player; + +/** + * + * @author LevelX2 + */ +public class ThornbowArcher extends CardImpl { + + public ThornbowArcher(UUID ownerId) { + super(ownerId, 121, "Thornbow Archer", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{B}"); + this.expansionSetCode = "ORI"; + this.subtype.add("Elf"); + this.subtype.add("Archer"); + this.power = new MageInt(1); + this.toughness = new MageInt(2); + + // Whenever Thornbow Archer attacks, each opponent who doesn't control an Elf loses 1 life. + this.addAbility(new AttacksTriggeredAbility(new ThornbowArcherEffect(), false)); + } + + public ThornbowArcher(final ThornbowArcher card) { + super(card); + } + + @Override + public ThornbowArcher copy() { + return new ThornbowArcher(this); + } +} + +class ThornbowArcherEffect extends OneShotEffect { + + private final static FilterCreaturePermanent filter = new FilterCreaturePermanent(); + + static { + filter.add(new SubtypePredicate("Elf")); + } + + public ThornbowArcherEffect() { + super(Outcome.LoseLife); + this.staticText = "each opponent who doesn't control an Elf loses 1 life"; + } + + public ThornbowArcherEffect(final ThornbowArcherEffect effect) { + super(effect); + } + + @Override + public ThornbowArcherEffect copy() { + return new ThornbowArcherEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + for (UUID opponentId : game.getOpponents(controller.getId())) { + Player opponent = game.getPlayer(opponentId); + if (opponent != null) { + if (game.getBattlefield().countAll(filter, opponentId, game) == 0) { + opponent.loseLife(1, game); + } + } + } + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/TouchOfMoonglove.java b/Mage.Sets/src/mage/sets/magicorigins/TouchOfMoonglove.java new file mode 100644 index 00000000000..b5faf222d09 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/TouchOfMoonglove.java @@ -0,0 +1,167 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.MageObjectReference; +import mage.abilities.Ability; +import mage.abilities.DelayedTriggeredAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.DeathtouchAbility; +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.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; +import mage.game.events.ZoneChangeEvent; +import mage.game.permanent.Permanent; +import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author LevelX2 + */ +public class TouchOfMoonglove extends CardImpl { + + public TouchOfMoonglove(UUID ownerId) { + super(ownerId, 123, "Touch of Moonglove", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{B}"); + this.expansionSetCode = "ORI"; + + // Target creature you control gets +1/+0 and gains deathtouch until end of turn. + Effect effect = new BoostTargetEffect(1, 0, Duration.EndOfTurn); + effect.setText("Target creature you control gets +1/+0"); + this.getSpellAbility().addEffect(effect); + this.getSpellAbility().addEffect(new GainAbilityTargetEffect( + DeathtouchAbility.getInstance(), Duration.EndOfTurn, "and gains deathtouch until end of turn")); + this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); + // Whenever a creature dealt damage by that creature this turn dies, its controller loses 2 life. + // this.getSpellAbility().addEffect(new CreateDelayedTriggeredAbilityEffect(null)); + this.getSpellAbility().addEffect(new TouchOfMoongloveAddTriggerEffect()); + + } + + public TouchOfMoonglove(final TouchOfMoonglove card) { + super(card); + } + + @Override + public TouchOfMoonglove copy() { + return new TouchOfMoonglove(this); + } +} + +class TouchOfMoongloveAddTriggerEffect extends OneShotEffect { + + public TouchOfMoongloveAddTriggerEffect() { + super(Outcome.Damage); + this.staticText = "Whenever a creature dealt damage by that creature this turn dies, its controller loses 2 life"; + } + + public TouchOfMoongloveAddTriggerEffect(final TouchOfMoongloveAddTriggerEffect effect) { + super(effect); + } + + @Override + public TouchOfMoongloveAddTriggerEffect copy() { + return new TouchOfMoongloveAddTriggerEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanentOrLKIBattlefield(getTargetPointer().getFirst(game, source)); + if (permanent != null) { + DelayedTriggeredAbility delayedAbility = new TouchOfMoongloveDelayedTriggeredAbility(new MageObjectReference(permanent, game)); + delayedAbility.setSourceId(source.getSourceId()); + delayedAbility.setControllerId(source.getControllerId()); + delayedAbility.setSourceObject(source.getSourceObject(game), game); + game.addDelayedTriggeredAbility(delayedAbility); + } + return true; + } +} + +class TouchOfMoongloveDelayedTriggeredAbility extends DelayedTriggeredAbility { + + private final MageObjectReference creatureToCheck; + + public TouchOfMoongloveDelayedTriggeredAbility(MageObjectReference creatureToCheck) { + super(new DamageTargetEffect(2), Duration.EndOfTurn); + this.creatureToCheck = creatureToCheck; + } + + public TouchOfMoongloveDelayedTriggeredAbility(TouchOfMoongloveDelayedTriggeredAbility ability) { + super(ability); + this.creatureToCheck = ability.creatureToCheck; + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == EventType.ZONE_CHANGE; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + ZoneChangeEvent zEvent = (ZoneChangeEvent) event; + if (zEvent.getFromZone() == Zone.BATTLEFIELD && zEvent.getToZone() == Zone.GRAVEYARD + && zEvent.getTarget().getCardType().contains(CardType.CREATURE)) { + boolean damageDealt = false; + for (MageObjectReference mor : zEvent.getTarget().getDealtDamageByThisTurn()) { + if (mor.equals(creatureToCheck)) { + damageDealt = true; + break; + } + } + if (damageDealt) { + for (Effect effect : getEffects()) { + effect.setTargetPointer(new FixedTarget(zEvent.getTarget().getControllerId())); + } + return true; + } + } + return false; + } + + @Override + public TouchOfMoongloveDelayedTriggeredAbility copy() { + return new TouchOfMoongloveDelayedTriggeredAbility(this); + } + + @Override + public String getRule() { + return "Whenever a creature dealt damage by that creature this turn dies, its controller loses 2 life."; + } +} diff --git a/Mage.Sets/src/mage/sets/urzassaga/VampiricEmbrace.java b/Mage.Sets/src/mage/sets/urzassaga/VampiricEmbrace.java index 6aebd11671e..e8157d73dcb 100644 --- a/Mage.Sets/src/mage/sets/urzassaga/VampiricEmbrace.java +++ b/Mage.Sets/src/mage/sets/urzassaga/VampiricEmbrace.java @@ -28,12 +28,6 @@ package mage.sets.urzassaga; import java.util.UUID; -import mage.constants.AttachmentType; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Outcome; -import mage.constants.Rarity; -import mage.constants.Zone; import mage.abilities.Ability; import mage.abilities.common.DiesAndDealtDamageThisTurnTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; @@ -44,6 +38,12 @@ import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.keyword.EnchantAbility; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; +import mage.constants.AttachmentType; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; import mage.counters.CounterType; import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; @@ -59,19 +59,18 @@ public class VampiricEmbrace extends CardImpl { this.expansionSetCode = "USG"; this.subtype.add("Aura"); - // Enchant creature - TargetPermanent auraTarget = new TargetCreaturePermanent(); + TargetPermanent auraTarget = new TargetCreaturePermanent(); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); Ability ability = new EnchantAbility(auraTarget.getTargetName()); this.addAbility(ability); - - // Enchanted creature gets +2/+2 and has flying. + + // Enchanted creature gets +2/+2 and has flying. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEnchantedEffect(2, 2, Duration.WhileOnBattlefield))); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(FlyingAbility.getInstance(), AttachmentType.AURA))); - - // Whenever a creature dealt damage by enchanted creature this turn dies, put a +1/+1 counter on that creature. + + // Whenever a creature dealt damage by enchanted creature this turn dies, put a +1/+1 counter on that creature. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(new DiesAndDealtDamageThisTurnTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance()), false), AttachmentType.AURA))); } From 39f292537625d827c2579cf12522e73a1528005b Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sun, 5 Jul 2015 19:09:43 +0200 Subject: [PATCH 068/105] [ORI] Relic Seeker - Fixed wrong rarity. --- Mage.Sets/src/mage/sets/magicorigins/RelicSeeker.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Mage.Sets/src/mage/sets/magicorigins/RelicSeeker.java b/Mage.Sets/src/mage/sets/magicorigins/RelicSeeker.java index c23c289ab6b..c4411ca92a7 100644 --- a/Mage.Sets/src/mage/sets/magicorigins/RelicSeeker.java +++ b/Mage.Sets/src/mage/sets/magicorigins/RelicSeeker.java @@ -44,7 +44,7 @@ import mage.target.common.TargetCardInLibrary; * * @author LevelX2 */ -public class RelicSeeker extends CardImpl { +public class RelicSeeker extends CardImpl { private static final FilterCard filter = new FilterCard("an Equipment card"); @@ -54,7 +54,7 @@ public class RelicSeeker extends CardImpl { } public RelicSeeker(UUID ownerId) { - super(ownerId, 29, "Relic Seeker", Rarity.SPECIAL, new CardType[]{CardType.CREATURE}, "{1}{W}"); + super(ownerId, 29, "Relic Seeker", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{1}{W}"); this.expansionSetCode = "ORI"; this.subtype.add("Human"); this.subtype.add("Soldier"); From a61dd323e65d04c3baaeeed221a8f9ac90f0f1db Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sun, 5 Jul 2015 19:10:18 +0200 Subject: [PATCH 069/105] [ORI] Added Shadows of the Past, Nightsnare and Dark Dabbling. --- .../mage/sets/magicorigins/DarkDabbling.java | 98 ++++++++++++++ .../mage/sets/magicorigins/Nightsnare.java | 121 ++++++++++++++++++ .../sets/magicorigins/ShadowsOfThePast.java | 76 +++++++++++ .../CardsInControllerGraveCondition.java | 14 +- 4 files changed, 308 insertions(+), 1 deletion(-) create mode 100644 Mage.Sets/src/mage/sets/magicorigins/DarkDabbling.java create mode 100644 Mage.Sets/src/mage/sets/magicorigins/Nightsnare.java create mode 100644 Mage.Sets/src/mage/sets/magicorigins/ShadowsOfThePast.java diff --git a/Mage.Sets/src/mage/sets/magicorigins/DarkDabbling.java b/Mage.Sets/src/mage/sets/magicorigins/DarkDabbling.java new file mode 100644 index 00000000000..f8b734832f8 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/DarkDabbling.java @@ -0,0 +1,98 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.condition.common.SpellMasteryCondition; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.RegenerateTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.filter.common.FilterCreaturePermanent; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LevelX2 + */ +public class DarkDabbling extends CardImpl { + + public DarkDabbling(UUID ownerId) { + super(ownerId, 89, "Dark Dabbling", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{2}{B}"); + this.expansionSetCode = "ORI"; + + // Regenerate target creature. Draw a card. + this.getSpellAbility().addEffect(new RegenerateTargetEffect()); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + // Spell mastery — If there are two or more instant and/or sorcery cards in your graveyard, also regenerate each other creature you control. + this.getSpellAbility().addEffect(new DarkDabblingEffect()); + } + + public DarkDabbling(final DarkDabbling card) { + super(card); + } + + @Override + public DarkDabbling copy() { + return new DarkDabbling(this); + } +} + +class DarkDabblingEffect extends OneShotEffect { + + public DarkDabblingEffect() { + super(Outcome.Benefit); + this.staticText = "Spell mastery — If there are two or more instant and/or sorcery cards in your graveyard, also regenerate each other creature you control"; + } + + public DarkDabblingEffect(final DarkDabblingEffect effect) { + super(effect); + } + + @Override + public DarkDabblingEffect copy() { + return new DarkDabblingEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + if (SpellMasteryCondition.getInstance().apply(game, source)) { + for (Permanent permanent : game.getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), source.getControllerId(), game)) { + if (!permanent.getId().equals(getTargetPointer().getFirst(game, source))) { + permanent.regenerate(source.getSourceId(), game); + } + } + } + return true; + } +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/Nightsnare.java b/Mage.Sets/src/mage/sets/magicorigins/Nightsnare.java new file mode 100644 index 00000000000..6c728ad2ad6 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/Nightsnare.java @@ -0,0 +1,121 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +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.Zone; +import mage.filter.common.FilterNonlandCard; +import mage.game.Game; +import mage.players.Player; +import mage.target.TargetCard; +import mage.target.common.TargetOpponent; + +/** + * + * @author LevelX2 + */ +public class Nightsnare extends CardImpl { + + public Nightsnare(UUID ownerId) { + super(ownerId, 111, "Nightsnare", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{3}{B}"); + this.expansionSetCode = "ORI"; + + // Target opponent reveals his or her hand. You may choose a nonland card from it. If you do, that player discards that card. If you don't, that player discards two cards. + this.getSpellAbility().addTarget(new TargetOpponent()); + this.getSpellAbility().addEffect(new NightsnareDiscardEffect()); + } + + public Nightsnare(final Nightsnare card) { + super(card); + } + + @Override + public Nightsnare copy() { + return new Nightsnare(this); + } +} + +class NightsnareDiscardEffect extends OneShotEffect { + + public NightsnareDiscardEffect() { + super(Outcome.Discard); + staticText = "Target opponent reveals his or her hand. You may choose a nonland card from it. If you do, that player discards that card. If you don't, that player discards two cards"; + } + + public NightsnareDiscardEffect(final NightsnareDiscardEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(targetPointer.getFirst(game, source)); + Player controller = game.getPlayer(source.getControllerId()); + Card sourceCard = game.getCard(source.getSourceId()); + if (player != null && controller != null) { + if (!player.getHand().isEmpty()) { + Cards revealedCards = new CardsImpl(Zone.HAND); + revealedCards.addAll(player.getHand()); + player.revealCards(sourceCard != null ? sourceCard.getIdName() : "Discard", revealedCards, game); + // You may choose a nonland card from it. + if (controller.chooseUse(outcome, "Choose a a card to discard? (Otherwise " + player.getLogName() + " has to discard 2 cards).", source, game)) { + TargetCard target = new TargetCard(1, Zone.HAND, new FilterNonlandCard()); + if (controller.choose(Outcome.Benefit, revealedCards, target, game)) { + for (Object targetId : target.getTargets()) { + Card card = revealedCards.get((UUID) targetId, game); + if (card != null) { + player.discard(card, source, game); + } + } + } + + } else { + player.discard(2, false, source, game); + } + } + return true; + + } + return false; + + } + + @Override + public NightsnareDiscardEffect copy() { + return new NightsnareDiscardEffect(this); + } + +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/ShadowsOfThePast.java b/Mage.Sets/src/mage/sets/magicorigins/ShadowsOfThePast.java new file mode 100644 index 00000000000..0c70c600fbb --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/ShadowsOfThePast.java @@ -0,0 +1,76 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.DiesCreatureTriggeredAbility; +import mage.abilities.condition.common.CardsInControllerGraveCondition; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.effects.common.LoseLifeOpponentsEffect; +import mage.abilities.effects.keyword.ScryEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterCreatureCard; + +/** + * + * @author LevelX2 + */ +public class ShadowsOfThePast extends CardImpl { + + public ShadowsOfThePast(UUID ownerId) { + super(ownerId, 118, "Shadows of the Past", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT}, "{1}{B}"); + this.expansionSetCode = "ORI"; + + // Whenever a creature dies, scry 1. + this.addAbility(new DiesCreatureTriggeredAbility(new ScryEffect(1), false)); + + // {4}{B}: Each opponent loses 2 life and you gain 2 life. Activate this ability only if there are four or more creature cards in your graveyard. + Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, + new LoseLifeOpponentsEffect(2), new ManaCostsImpl<>("{4}{B}"), new CardsInControllerGraveCondition(4, new FilterCreatureCard())); + Effect effect = new GainLifeEffect(2); + effect.setText("and you gain 2 life"); + ability.addEffect(effect); + this.addAbility(ability); + } + + public ShadowsOfThePast(final ShadowsOfThePast card) { + super(card); + } + + @Override + public ShadowsOfThePast copy() { + return new ShadowsOfThePast(this); + } +} diff --git a/Mage/src/mage/abilities/condition/common/CardsInControllerGraveCondition.java b/Mage/src/mage/abilities/condition/common/CardsInControllerGraveCondition.java index d36c9c96870..2cd6cef755e 100644 --- a/Mage/src/mage/abilities/condition/common/CardsInControllerGraveCondition.java +++ b/Mage/src/mage/abilities/condition/common/CardsInControllerGraveCondition.java @@ -2,6 +2,7 @@ package mage.abilities.condition.common; import mage.abilities.Ability; import mage.abilities.condition.Condition; +import mage.filter.FilterCard; import mage.game.Game; import mage.players.Player; import mage.util.CardUtil; @@ -14,20 +15,31 @@ import mage.util.CardUtil; public class CardsInControllerGraveCondition implements Condition { private final int value; + private final FilterCard filter; public CardsInControllerGraveCondition(int value) { + this(value, null); + } + + public CardsInControllerGraveCondition(int value, FilterCard filter) { this.value = value; + this.filter = filter; } @Override public boolean apply(Game game, Ability source) { Player player = game.getPlayer(source.getControllerId()); + if (filter != null) { + return player != null && player.getGraveyard().count(filter, source.getSourceId(), source.getControllerId(), game) >= value; + } return player != null && player.getGraveyard().size() >= value; } @Override public String toString() { - return "there are " + CardUtil.numberToText(value, "one") + " or more cards in your graveyard"; + return "there are " + CardUtil.numberToText(value, "one") + " or more " + + (filter == null ? "cards" : filter.getMessage()) + + " in your graveyard"; } } From d7f9e07386b0a840d46cd750859a25a47f140c7c Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sun, 5 Jul 2015 20:32:36 +0200 Subject: [PATCH 070/105] [ORI] Added Sigil of Valor and Pyromancer's Goggles. --- .../sets/magicorigins/PyromancersGoggles.java | 129 ++++++++++ .../mage/sets/magicorigins/SigilOfValor.java | 154 ++++++++++++ .../effects/common/CopyTargetSpellEffect.java | 61 ++--- .../abilities/keyword/ExaltedAbility.java | 62 +++-- Mage/src/mage/game/events/GameEvent.java | 224 ++++++++---------- 5 files changed, 447 insertions(+), 183 deletions(-) create mode 100644 Mage.Sets/src/mage/sets/magicorigins/PyromancersGoggles.java create mode 100644 Mage.Sets/src/mage/sets/magicorigins/SigilOfValor.java diff --git a/Mage.Sets/src/mage/sets/magicorigins/PyromancersGoggles.java b/Mage.Sets/src/mage/sets/magicorigins/PyromancersGoggles.java new file mode 100644 index 00000000000..f9729a180dd --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/PyromancersGoggles.java @@ -0,0 +1,129 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.ObjectColor; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.CopyTargetSpellEffect; +import mage.abilities.mana.RedManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterInstantOrSorcerySpell; +import mage.filter.predicate.mageobject.ColorPredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; +import mage.game.stack.Spell; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author LevelX2 + */ +public class PyromancersGoggles extends CardImpl { + + public PyromancersGoggles(UUID ownerId) { + super(ownerId, 236, "Pyromancer's Goggles", Rarity.MYTHIC, new CardType[]{CardType.ARTIFACT}, "{5}"); + this.expansionSetCode = "ORI"; + this.supertype.add("Legendary"); + + // {T}: Add {R} to your mana pool. + Ability ability = new RedManaAbility(); + this.addAbility(ability); + + // When that mana is used to cast a red instant or sorcery spell, copy that spell and you may choose new targets for the copy. + Effect effect = new CopyTargetSpellEffect(); + effect.setText("copy that spell and you may choose new targets for the copy"); + this.addAbility(new PyromancersGogglesTriggeredAbility(ability.getOriginalId(), effect)); + + } + + public PyromancersGoggles(final PyromancersGoggles card) { + super(card); + } + + @Override + public PyromancersGoggles copy() { + return new PyromancersGoggles(this); + } +} + +class PyromancersGogglesTriggeredAbility extends TriggeredAbilityImpl { + + private final static FilterInstantOrSorcerySpell filter = new FilterInstantOrSorcerySpell(); + + static { + filter.add(new ColorPredicate(ObjectColor.RED)); + } + + String abilityOriginalId; + + public PyromancersGogglesTriggeredAbility(UUID abilityOriginalId, Effect effect) { + super(Zone.ALL, effect, true); + this.abilityOriginalId = abilityOriginalId.toString(); + } + + public PyromancersGogglesTriggeredAbility(final PyromancersGogglesTriggeredAbility ability) { + super(ability); + this.abilityOriginalId = ability.abilityOriginalId; + } + + @Override + public PyromancersGogglesTriggeredAbility copy() { + return new PyromancersGogglesTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType().equals(EventType.MANA_PAYED); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getData().equals(abilityOriginalId)) { + Spell spell = game.getStack().getSpell(event.getTargetId()); + if (spell != null && filter.match(spell, getControllerId(), game)) { + for (Effect effect : getEffects()) { + effect.setTargetPointer(new FixedTarget(event.getTargetId())); + } + return true; + } + } + return false; + } + + @Override + public String getRule() { + return "When that mana is used to cast a red instant or sorcery spell, " + super.getRule(); + } +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/SigilOfValor.java b/Mage.Sets/src/mage/sets/magicorigins/SigilOfValor.java new file mode 100644 index 00000000000..4dc297988ff --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/SigilOfValor.java @@ -0,0 +1,154 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.abilities.keyword.EquipAbility; +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.FilterPermanent; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardIdPredicate; +import static mage.filter.predicate.permanent.ControllerControlsIslandPredicate.filter; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author LevelX2 + */ +public class SigilOfValor extends CardImpl { + + public SigilOfValor(UUID ownerId) { + super(ownerId, 239, "Sigil of Valor", Rarity.UNCOMMON, new CardType[]{CardType.ARTIFACT}, "{2}"); + this.expansionSetCode = "ORI"; + this.subtype.add("Equipment"); + + // Whenever equipped creature attacks alone, it gets +1/+1 until end of turn for each other creature you control. + this.addAbility(new SigilOfValorTriggeredAbility(new SigilOfValorCount())); + + // Equip {1} + this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(1))); + } + + public SigilOfValor(final SigilOfValor card) { + super(card); + } + + @Override + public SigilOfValor copy() { + return new SigilOfValor(this); + } +} + +class SigilOfValorTriggeredAbility extends TriggeredAbilityImpl { + + public SigilOfValorTriggeredAbility(DynamicValue boostValue) { + super(Zone.BATTLEFIELD, new BoostTargetEffect(boostValue, boostValue, Duration.EndOfTurn)); + } + + public SigilOfValorTriggeredAbility(final SigilOfValorTriggeredAbility ability) { + super(ability); + } + + @Override + public SigilOfValorTriggeredAbility copy() { + return new SigilOfValorTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DECLARED_ATTACKERS; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (game.getActivePlayerId().equals(this.controllerId)) { + if (game.getCombat().attacksAlone()) { + this.getEffects().get(0).setTargetPointer(new FixedTarget(game.getCombat().getAttackers().get(0))); + return true; + } + } + return false; + } + + @Override + public String getRule() { + return "Whenever equipped creature attacks alone, it gets +1/+1 until end of turn for each other creature you control."; + } + +} + +class SigilOfValorCount implements DynamicValue { + + public SigilOfValorCount() { + } + + public SigilOfValorCount(final SigilOfValorCount dynamicValue) { + super(); + } + + @Override + public int calculate(Game game, Ability sourceAbility, Effect effect) { + Permanent equipment = game.getPermanent(sourceAbility.getSourceId()); + if (equipment != null && equipment.getAttachedTo() != null) { + FilterPermanent filterPermanent = new FilterControlledCreaturePermanent(); + filterPermanent.add(Predicates.not(new CardIdPredicate(equipment.getAttachedTo()))); + return game.getBattlefield().count(filterPermanent, sourceAbility.getSourceId(), sourceAbility.getControllerId(), game); + } + return 0; + } + + @Override + public DynamicValue copy() { + return new SigilOfValorCount(this); + } + + @Override + public String toString() { + return "X"; + } + + @Override + public String getMessage() { + return filter.getMessage(); + } +} diff --git a/Mage/src/mage/abilities/effects/common/CopyTargetSpellEffect.java b/Mage/src/mage/abilities/effects/common/CopyTargetSpellEffect.java index 6d02c2cb8e0..fcec4c594c6 100644 --- a/Mage/src/mage/abilities/effects/common/CopyTargetSpellEffect.java +++ b/Mage/src/mage/abilities/effects/common/CopyTargetSpellEffect.java @@ -1,38 +1,36 @@ /* -* 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. -*/ - - + * 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.abilities.effects.common; -import mage.constants.Outcome; import mage.abilities.Ability; import mage.abilities.Mode; import mage.abilities.effects.OneShotEffect; +import mage.constants.Outcome; import mage.constants.Zone; import mage.game.Game; import mage.game.stack.Spell; @@ -82,8 +80,11 @@ public class CopyTargetSpellEffect extends OneShotEffect { return new CopyTargetSpellEffect(this); } - @Override + @Override public String getText(Mode mode) { + if (staticText != null && !staticText.isEmpty()) { + return staticText; + } StringBuilder sb = new StringBuilder(); sb.append("copy target ").append(mode.getTargets().get(0).getTargetName()).append(". You may choose new targets for the copy"); return sb.toString(); diff --git a/Mage/src/mage/abilities/keyword/ExaltedAbility.java b/Mage/src/mage/abilities/keyword/ExaltedAbility.java index d35381cda91..bc0bd895a89 100644 --- a/Mage/src/mage/abilities/keyword/ExaltedAbility.java +++ b/Mage/src/mage/abilities/keyword/ExaltedAbility.java @@ -1,40 +1,38 @@ /* -* 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. -*/ - + * 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.abilities.keyword; -import mage.constants.Duration; -import mage.constants.Zone; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.constants.Duration; +import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; -import mage.game.events.GameEvent.EventType; import mage.target.targetpointer.FixedTarget; /** @@ -63,7 +61,7 @@ public class ExaltedAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - if (game.getActivePlayerId().equals(this.controllerId) ) { + if (game.getActivePlayerId().equals(this.controllerId)) { if (game.getCombat().attacksAlone()) { this.getEffects().get(0).setTargetPointer(new FixedTarget(game.getCombat().getAttackers().get(0))); return true; @@ -74,7 +72,7 @@ public class ExaltedAbility extends TriggeredAbilityImpl { @Override public String getRule() { - return "Exalted"; + return "Exalted (Whenever a creature you control attacks alone, that creature gets +1/+1 until end of turn.)"; } } diff --git a/Mage/src/mage/game/events/GameEvent.java b/Mage/src/mage/game/events/GameEvent.java index 4b0c5223b67..10ccca9d241 100644 --- a/Mage/src/mage/game/events/GameEvent.java +++ b/Mage/src/mage/game/events/GameEvent.java @@ -1,31 +1,30 @@ /* -* 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. -*/ - + * 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.game.events; import java.io.Serializable; @@ -54,7 +53,6 @@ public class GameEvent implements Serializable { //Game events BEGINNING, PREVENT_DAMAGE, PREVENTED_DAMAGE, - //Turn-based events PLAY_TURN, EXTRA_TURN, CHANGE_PHASE, PHASE_CHANGED, @@ -78,15 +76,14 @@ public class GameEvent implements Serializable { CLEANUP_STEP_PRE, CLEANUP_STEP, CLEANUP_STEP_POST, EMPTY_MANA_POOL, AT_END_OF_TURN, - //player events /* ZONE_CHANGE - targetId id of the zone changing object - sourceId sourceId of the ability with the object moving effect - playerId controller of the moved object - amount not used for this event - flag not used for this event - */ + targetId id of the zone changing object + sourceId sourceId of the ability with the object moving effect + playerId controller of the moved object + amount not used for this event + flag not used for this event + */ ZONE_CHANGE, ZONE_CHANGE_GROUP, EMPTY_DRAW, @@ -96,77 +93,69 @@ public class GameEvent implements Serializable { DISCARDED_CARD, CYCLE_CARD, CYCLED_CARD, CLASH, CLASHED, - DAMAGE_PLAYER, - + DAMAGE_PLAYER, /* DAMAGED_PLAYER - targetId the id of the damged player - sourceId sourceId of the ability which caused the damage - playerId the id of the damged player - amount amount of damage - flag true = comabat damage - other damage = false - */ + targetId the id of the damged player + sourceId sourceId of the ability which caused the damage + playerId the id of the damged player + amount amount of damage + flag true = comabat damage - other damage = false + */ DAMAGED_PLAYER, - DAMAGE_CAUSES_LIFE_LOSS, PLAYER_LIFE_CHANGE, GAIN_LIFE, GAINED_LIFE, LOSE_LIFE, LOST_LIFE, PLAY_LAND, LAND_PLAYED, - CAST_SPELL, - + CAST_SPELL, /* SPELL_CAST - targetId id of the spell that's cast - sourceId sourceId of the spell that's cast - playerId player that casts the spell - amount not used for this event - flag not used for this event - zone zone the spell is cast from - */ + targetId id of the spell that's cast + sourceId sourceId of the spell that's cast + playerId player that casts the spell + amount not used for this event + flag not used for this event + zone zone the spell is cast from + */ SPELL_CAST, - ACTIVATE_ABILITY, ACTIVATED_ABILITY, - ADD_MANA, MANA_ADDED, - + ADD_MANA, MANA_ADDED, /* MANA_PAYED - targetId id if the ability the mana was paid for (not the sourceId) - sourceId sourceId of the mana source - playerId controller of the ability the mana was paid for - amount not used for this event - flag indicates a special condition - */ - MANA_PAYED, - + targetId id if the ability the mana was paid for (not the sourceId) + sourceId sourceId of the mana source + playerId controller of the ability the mana was paid for + amount not used for this event + flag indicates a special condition + data originalId of the mana producing ability + */ + MANA_PAYED, LOSES, LOST, WINS, TARGET, TARGETED, - /* COUNTER - targetId id of the spell or id of stack ability - sourceId sourceId of the ability countering the spell or stack ability - playerId controller of the countered spell or stack ability - amount not used for this event - flag not used for this event - */ + targetId id of the spell or id of stack ability + sourceId sourceId of the ability countering the spell or stack ability + playerId controller of the countered spell or stack ability + amount not used for this event + flag not used for this event + */ COUNTER, COUNTERED, DECLARING_ATTACKERS, DECLARED_ATTACKERS, DECLARE_ATTACKER, - /* ATTACKER_DECLARED - targetId id of the defending player or planeswalker attacked - sourceId id of the attacking creature - playerId player defining the attacking creatures - amount not used for this event - flag not used for this event - */ + targetId id of the defending player or planeswalker attacked + sourceId id of the attacking creature + playerId player defining the attacking creatures + amount not used for this event + flag not used for this event + */ ATTACKER_DECLARED, - /* DECLARING_BLOCKERS - targetId attackerId - sourceId not used for this event - playerId attackerId - amount not used for this event - flag not used for this event - */ + targetId attackerId + sourceId not used for this event + playerId attackerId + amount not used for this event + flag not used for this event + */ DECLARING_BLOCKERS, DECLARED_BLOCKERS, DECLARE_BLOCKER, BLOCKER_DECLARED, @@ -176,7 +165,6 @@ public class GameEvent implements Serializable { ENCHANT_PLAYER, ENCHANTED_PLAYER, CAN_TAKE_MULLIGAN, FLIP_COIN, COIN_FLIPPED, SCRY, FATESEAL, - //permanent events ENTERS_THE_BATTLEFIELD, TAP, TAPPED, TAPPED_FOR_MANA, @@ -192,17 +180,15 @@ public class GameEvent implements Serializable { TURNFACEDOWN, TURNEDFACEDOWN, DAMAGE_CREATURE, DAMAGED_CREATURE, DAMAGE_PLANESWALKER, DAMAGED_PLANESWALKER, - DESTROY_PERMANENT, - + DESTROY_PERMANENT, /* DESTROYED_PERMANENT - targetId id of the destroyed creature - sourceId sourceId of the ability with the destroy effect - playerId controller of the creature - amount not used for this event - flag true if no regeneration is allowed - */ + targetId id of the destroyed creature + sourceId sourceId of the ability with the destroy effect + playerId controller of the creature + amount not used for this event + flag true if no regeneration is allowed + */ DESTROYED_PERMANENT, - SACRIFICE_PERMANENT, SACRIFICED_PERMANENT, FIGHTED_PERMANENT, EXPLOITED_CREATURE, @@ -211,31 +197,27 @@ public class GameEvent implements Serializable { ADD_COUNTER, COUNTER_ADDED, ADD_COUNTERS, COUNTERS_ADDED, COUNTER_REMOVED, - LOSE_CONTROL, - + LOSE_CONTROL, /* LOST_CONTROL - targetId id of the creature that lost control - sourceId id of the creature that lost control - playerId player that controlles the creature before - amount not used for this event - flag not used for this event - */ + targetId id of the creature that lost control + sourceId id of the creature that lost control + playerId player that controlles the creature before + amount not used for this event + flag not used for this event + */ LOST_CONTROL, GAIN_CONTROL, GAINED_CONTROL, CREATE_TOKEN, - /* REGENERATE - targetId id of the creature to regenerate - sourceId sourceId of the effect doing the regeneration - playerId controller of the creature - amount not used for this event - flag not used for this event - */ + targetId id of the creature to regenerate + sourceId sourceId of the effect doing the regeneration + playerId controller of the creature + amount not used for this event + flag not used for this event + */ REGENERATE, - REGENERATED, CHANGE_COLOR, COLOR_CHANGED, - //combat events COMBAT_DAMAGE_APPLIED, SELECTED_ATTACKER, SELECTED_BLOCKER; @@ -268,7 +250,7 @@ public class GameEvent implements Serializable { } public static GameEvent getEvent(EventType type, UUID targetId, UUID playerId, String data, int amount) { - GameEvent event = getEvent(type, targetId,playerId); + GameEvent event = getEvent(type, targetId, playerId); event.setAmount(amount); event.setData(data); return event; @@ -310,7 +292,6 @@ public class GameEvent implements Serializable { this.flag = flag; } - public String getData() { return data; } @@ -326,17 +307,18 @@ public class GameEvent implements Serializable { public void setZone(Zone zone) { this.zone = zone; } + /** * used to store which replacement effects were already applied to an event * or or any modified events that may replace it * - * 614.5. A replacement effect doesn't invoke itself repeatedly; it gets only one - * opportunity to affect an event or any modified events that may replace it. - * Example: A player controls two permanents, each with an ability that reads - * "If a creature you control would deal damage to a creature or player, it - * deals double that damage to that creature or player instead." A creature - * that normally deals 2 damage will deal 8 damage--not just 4, and not an - * infinite amount. + * 614.5. A replacement effect doesn't invoke itself repeatedly; it gets + * only one opportunity to affect an event or any modified events that may + * replace it. Example: A player controls two permanents, each with an + * ability that reads "If a creature you control would deal damage to a + * creature or player, it deals double that damage to that creature or + * player instead." A creature that normally deals 2 damage will deal 8 + * damage--not just 4, and not an infinite amount. * * @return */ From 98993b593ea37b278d20539f134bc1d4d8801ffa Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sun, 5 Jul 2015 22:20:36 +0200 Subject: [PATCH 071/105] [ORI] Added Prism Ring and Orbs of Warding. --- .../mage/sets/magicorigins/OrbsOfWarding.java | 103 +++++++++++++++++ .../src/mage/sets/magicorigins/PrismRing.java | 108 ++++++++++++++++++ .../src/mage/sets/urzassaga/UrzasArmor.java | 32 ++---- 3 files changed, 220 insertions(+), 23 deletions(-) create mode 100644 Mage.Sets/src/mage/sets/magicorigins/OrbsOfWarding.java create mode 100644 Mage.Sets/src/mage/sets/magicorigins/PrismRing.java diff --git a/Mage.Sets/src/mage/sets/magicorigins/OrbsOfWarding.java b/Mage.Sets/src/mage/sets/magicorigins/OrbsOfWarding.java new file mode 100644 index 00000000000..a244007d356 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/OrbsOfWarding.java @@ -0,0 +1,103 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.PreventionEffectImpl; +import mage.abilities.effects.common.continuous.GainAbilityControllerEffect; +import mage.abilities.keyword.HexproofAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; + +/** + * + * @author LevelX2 + */ +public class OrbsOfWarding extends CardImpl { + + public OrbsOfWarding(UUID ownerId) { + super(ownerId, 234, "Orbs of Warding", Rarity.RARE, new CardType[]{CardType.ARTIFACT}, "{5}"); + this.expansionSetCode = "ORI"; + + // You have hexproof. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityControllerEffect(HexproofAbility.getInstance(), Duration.WhileOnBattlefield))); + + // If a creature would deal damage to you, prevent 1 of that damage. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new OrbsOfWardingEffect())); + } + + public OrbsOfWarding(final OrbsOfWarding card) { + super(card); + } + + @Override + public OrbsOfWarding copy() { + return new OrbsOfWarding(this); + } +} + +class OrbsOfWardingEffect extends PreventionEffectImpl { + + public OrbsOfWardingEffect() { + super(Duration.WhileOnBattlefield, 1, false, false); + this.staticText = "If a creature would deal damage to you, prevent 1 of that damage"; + } + + public OrbsOfWardingEffect(OrbsOfWardingEffect effect) { + super(effect); + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType().equals(GameEvent.EventType.DAMAGE_PLAYER); + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (event.getTargetId().equals(source.getControllerId())) { + Permanent permanent = game.getPermanentOrLKIBattlefield(event.getSourceId()); + if (permanent.getCardType().contains(CardType.CREATURE)) { + return super.applies(event, source, game); + } + } + return false; + } + + @Override + public OrbsOfWardingEffect copy() { + return new OrbsOfWardingEffect(this); + } +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/PrismRing.java b/Mage.Sets/src/mage/sets/magicorigins/PrismRing.java new file mode 100644 index 00000000000..6433612fe56 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/PrismRing.java @@ -0,0 +1,108 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.ObjectColor; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.effects.common.ChooseColorEffect; +import mage.abilities.effects.common.GainLifeEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.stack.Spell; + +/** + * + * @author LevelX2 + */ +public class PrismRing extends CardImpl { + + public PrismRing(UUID ownerId) { + super(ownerId, 235, "Prism Ring", Rarity.UNCOMMON, new CardType[]{CardType.ARTIFACT}, "{1}"); + this.expansionSetCode = "ORI"; + + // As Prism Ring enters the battlefield, choose a color. + this.addAbility(new EntersBattlefieldAbility(new ChooseColorEffect(Outcome.Neutral))); + + // Whenever you cast a spell of the chosen color, you gain 1 life. + this.addAbility(new PrismRingTriggeredAbility()); + } + + public PrismRing(final PrismRing card) { + super(card); + } + + @Override + public PrismRing copy() { + return new PrismRing(this); + } +} + +class PrismRingTriggeredAbility extends TriggeredAbilityImpl { + + public PrismRingTriggeredAbility() { + super(Zone.BATTLEFIELD, new GainLifeEffect(1), false); + } + + public PrismRingTriggeredAbility(final PrismRingTriggeredAbility ability) { + super(ability); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.SPELL_CAST; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getPlayerId().equals(this.getControllerId())) { + Spell spell = game.getStack().getSpell(event.getTargetId()); + ObjectColor color = (ObjectColor) game.getState().getValue(getSourceId() + "_color"); + if (spell != null && color != null && spell.getColor(game).shares(color)) { + return true; + } + } + return false; + } + + @Override + public String getRule() { + return "Whenever you cast a spell of the chosen color, you gain 1 life."; + } + + @Override + public PrismRingTriggeredAbility copy() { + return new PrismRingTriggeredAbility(this); + } +} diff --git a/Mage.Sets/src/mage/sets/urzassaga/UrzasArmor.java b/Mage.Sets/src/mage/sets/urzassaga/UrzasArmor.java index 7fa3650a39f..0953ec58d9e 100644 --- a/Mage.Sets/src/mage/sets/urzassaga/UrzasArmor.java +++ b/Mage.Sets/src/mage/sets/urzassaga/UrzasArmor.java @@ -28,14 +28,14 @@ package mage.sets.urzassaga; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Rarity; -import mage.constants.Zone; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.PreventionEffectImpl; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; @@ -66,7 +66,7 @@ public class UrzasArmor extends CardImpl { class UrzasArmorEffect extends PreventionEffectImpl { public UrzasArmorEffect() { - super(Duration.WhileOnBattlefield); + super(Duration.WhileOnBattlefield, 1, false, false); this.staticText = "If a source would deal damage to you, prevent 1 of that damage"; } @@ -75,28 +75,14 @@ class UrzasArmorEffect extends PreventionEffectImpl { } @Override - public boolean replaceEvent(GameEvent event, Ability source, Game game) { - GameEvent preventEvent = new GameEvent(GameEvent.EventType.PREVENT_DAMAGE, source.getFirstTarget(), source.getSourceId(), source.getControllerId(), 1, false); - if (!game.replaceEvent(preventEvent)) { - int damage = event.getAmount(); - if (damage > 0) { - event.setAmount(damage - 1); - game.informPlayers("1 damage has been prevented."); - } - game.fireEvent(GameEvent.getEvent(GameEvent.EventType.PREVENTED_DAMAGE, source.getFirstTarget(), source.getSourceId(), source.getControllerId(), 1)); - } - return false; - } - - @Override - public boolean apply(Game game, Ability source) { - return true; + public boolean checksEventType(GameEvent event, Game game) { + return event.getType().equals(GameEvent.EventType.DAMAGE_PLAYER); } @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType().equals(GameEvent.EventType.DAMAGE_PLAYER) && event.getTargetId().equals(source.getControllerId())) { - return super.applies(event, source, game); + if (event.getTargetId().equals(source.getControllerId())) { + return super.applies(event, source, game); } return false; } From 22dd2ffeccfb6fdb5b8e7fdc20918ccc78665623 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sun, 5 Jul 2015 23:24:03 +0200 Subject: [PATCH 072/105] [ORI] Cruel Revival - Fixed wrong rarity. --- Mage.Sets/src/mage/sets/magicorigins/CruelRevival.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Mage.Sets/src/mage/sets/magicorigins/CruelRevival.java b/Mage.Sets/src/mage/sets/magicorigins/CruelRevival.java index 92d0760bf83..3c800688d73 100644 --- a/Mage.Sets/src/mage/sets/magicorigins/CruelRevival.java +++ b/Mage.Sets/src/mage/sets/magicorigins/CruelRevival.java @@ -28,6 +28,7 @@ package mage.sets.magicorigins; import java.util.UUID; +import mage.constants.Rarity; /** * @@ -37,6 +38,7 @@ public class CruelRevival extends mage.sets.onslaught.CruelRevival { public CruelRevival(UUID ownerId) { super(ownerId); + this.rarity = Rarity.UNCOMMON; this.cardNumber = 88; this.expansionSetCode = "ORI"; } From 12f8dc31b85a05112c43f2335a1a8717a29f5ee9 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Mon, 6 Jul 2015 00:36:10 +0200 Subject: [PATCH 073/105] [ORI] Added last 4 white cards. --- .../sets/commander2014/ContainmentPriest.java | 76 +--------- .../sets/magicorigins/ArchangelOfTithes.java | 131 +++++++++++++++++ .../sets/magicorigins/ConsulsLieutenant.java | 78 ++++++++++ .../sets/magicorigins/HallowedMoonlight.java | 136 ++++++++++++++++++ .../sets/magicorigins/KytheonsTactics.java | 67 +++++++++ .../CantAttackYouUnlessPayManaAllEffect.java | 28 +++- .../CantBlockUnlessPayManaAllEffect.java | 88 ++++++++++++ .../common/CreatureWasCastWatcher.java | 93 ++++++++++++ 8 files changed, 625 insertions(+), 72 deletions(-) create mode 100644 Mage.Sets/src/mage/sets/magicorigins/ArchangelOfTithes.java create mode 100644 Mage.Sets/src/mage/sets/magicorigins/ConsulsLieutenant.java create mode 100644 Mage.Sets/src/mage/sets/magicorigins/HallowedMoonlight.java create mode 100644 Mage.Sets/src/mage/sets/magicorigins/KytheonsTactics.java create mode 100644 Mage/src/mage/abilities/effects/common/combat/CantBlockUnlessPayManaAllEffect.java create mode 100644 Mage/src/mage/watchers/common/CreatureWasCastWatcher.java diff --git a/Mage.Sets/src/mage/sets/commander2014/ContainmentPriest.java b/Mage.Sets/src/mage/sets/commander2014/ContainmentPriest.java index caff08b7404..12728e17d97 100644 --- a/Mage.Sets/src/mage/sets/commander2014/ContainmentPriest.java +++ b/Mage.Sets/src/mage/sets/commander2014/ContainmentPriest.java @@ -27,8 +27,6 @@ */ package mage.sets.commander2014; -import java.util.HashSet; -import java.util.Set; import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; @@ -41,17 +39,12 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Outcome; import mage.constants.Rarity; -import mage.constants.WatcherScope; import mage.constants.Zone; -import mage.filter.common.FilterCreatureCard; -import mage.filter.predicate.Predicates; -import mage.filter.predicate.permanent.TokenPredicate; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.ZoneChangeEvent; -import mage.game.stack.Spell; import mage.players.Player; -import mage.watchers.Watcher; +import mage.watchers.common.CreatureWasCastWatcher; /** * @@ -71,7 +64,7 @@ public class ContainmentPriest extends CardImpl { // Flash this.addAbility(FlashAbility.getInstance()); // If a nontoken creature would enter the battlefield and it wasn't cast, exile it instead. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ContainmentPriestReplacementEffect()), new CreatureCastWatcher()); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ContainmentPriestReplacementEffect()), new CreatureWasCastWatcher()); } public ContainmentPriest(final ContainmentPriest card) { @@ -86,14 +79,8 @@ public class ContainmentPriest extends CardImpl { class ContainmentPriestReplacementEffect extends ReplacementEffectImpl { - private static final FilterCreatureCard filter = new FilterCreatureCard(); - - static { - filter.add(Predicates.not(new TokenPredicate())); - } - public ContainmentPriestReplacementEffect() { - super(Duration.WhileOnBattlefield, Outcome.GainControl); + super(Duration.WhileOnBattlefield, Outcome.Exile); staticText = "If a nontoken creature would enter the battlefield and it wasn't cast, exile it instead"; } @@ -125,19 +112,18 @@ class ContainmentPriestReplacementEffect extends ReplacementEffectImpl { } return false; } - - @Override + + @Override public boolean checksEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.ZONE_CHANGE; + return event.getType() == GameEvent.EventType.ZONE_CHANGE; // Token create the create Token event } - @Override public boolean applies(GameEvent event, Ability source, Game game) { if (((ZoneChangeEvent) event).getToZone() == Zone.BATTLEFIELD) { Card card = game.getCard(event.getTargetId()); if (card.getCardType().contains(CardType.CREATURE)) { // TODO: Bestow Card cast as Enchantment probably not handled correctly - CreatureCastWatcher watcher = (CreatureCastWatcher) game.getState().getWatchers().get("CreatureWasCast"); + CreatureWasCastWatcher watcher = (CreatureWasCastWatcher) game.getState().getWatchers().get("CreatureWasCast"); if (watcher != null && !watcher.wasCreatureCastThisTurn(event.getTargetId())) { return true; } @@ -146,51 +132,3 @@ class ContainmentPriestReplacementEffect extends ReplacementEffectImpl { return false; } } - -class CreatureCastWatcher extends Watcher { - - private final Set creaturesCasted = new HashSet<>(); - - public CreatureCastWatcher() { - super("CreatureWasCast", WatcherScope.GAME); - } - - public CreatureCastWatcher(final CreatureCastWatcher watcher) { - super(watcher); - } - - @Override - public void watch(GameEvent event, Game game) { - if (event.getType() == GameEvent.EventType.SPELL_CAST) { - Spell spell = (Spell) game.getObject(event.getTargetId()); - if (spell != null) { - Card card = game.getCard(spell.getSourceId()); - if (card != null && card.getCardType().contains(CardType.CREATURE)) { - creaturesCasted.add(card.getId()); - } - } - } - if (event.getType() == GameEvent.EventType.ZONE_CHANGE - && ((ZoneChangeEvent) event).getFromZone() == Zone.BATTLEFIELD) { - Card card = game.getCard(event.getTargetId()); - if (card != null && card.getCardType().contains(CardType.CREATURE)) { - creaturesCasted.remove(card.getId()); - } - } - } - - public boolean wasCreatureCastThisTurn(UUID creatureSourceId) { - return creaturesCasted.contains(creatureSourceId); - } - - @Override - public void reset() { - super.reset(); - creaturesCasted.clear(); - } - - @Override - public CreatureCastWatcher copy() { - return new CreatureCastWatcher(this); - } -} diff --git a/Mage.Sets/src/mage/sets/magicorigins/ArchangelOfTithes.java b/Mage.Sets/src/mage/sets/magicorigins/ArchangelOfTithes.java new file mode 100644 index 00000000000..f58a35af3a9 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/ArchangelOfTithes.java @@ -0,0 +1,131 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.combat.CantAttackYouUnlessPayManaAllEffect; +import mage.abilities.effects.common.combat.CantBlockUnlessPayManaAllEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; + +/** + * + * @author LevelX2 + */ +public class ArchangelOfTithes extends CardImpl { + + public ArchangelOfTithes(UUID ownerId) { + super(ownerId, 4, "Archangel of Tithes", Rarity.MYTHIC, new CardType[]{CardType.CREATURE}, "{1}{W}{W}{W}"); + this.expansionSetCode = "ORI"; + this.subtype.add("Angel"); + this.power = new MageInt(3); + this.toughness = new MageInt(5); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // As long as Archangel of Tithes is untapped, creatures can't attack you or a planeswalker you control unless their controller pays {1} for each of those creatures. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ArchangelOfTithesPayManaToAttackAllEffect())); + + // As long as Archangel of Tithes is attacking, creatures can't block unless their controller pays {1} for each of those creatures. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ArchangelOfTithesPayManaToBlockAllEffect())); + } + + public ArchangelOfTithes(final ArchangelOfTithes card) { + super(card); + } + + @Override + public ArchangelOfTithes copy() { + return new ArchangelOfTithes(this); + } +} + +class ArchangelOfTithesPayManaToAttackAllEffect extends CantAttackYouUnlessPayManaAllEffect { + + ArchangelOfTithesPayManaToAttackAllEffect() { + super(new ManaCostsImpl<>("{1}"), true); + staticText = "As long as {this} is untapped, creatures can't attack you or a planeswalker you control unless their controller pays {1} for each of those creatures."; + } + + ArchangelOfTithesPayManaToAttackAllEffect(ArchangelOfTithesPayManaToAttackAllEffect effect) { + super(effect); + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent.isTapped()) { + return false; + } + return super.applies(event, source, game); + } + + @Override + public ArchangelOfTithesPayManaToAttackAllEffect copy() { + return new ArchangelOfTithesPayManaToAttackAllEffect(this); + } + +} + +class ArchangelOfTithesPayManaToBlockAllEffect extends CantBlockUnlessPayManaAllEffect { + + ArchangelOfTithesPayManaToBlockAllEffect() { + super(new ManaCostsImpl<>("{1}"), true); + staticText = "As long as {this} is attacking, creatures can't block unless their controller pays {1} for each of those creatures."; + } + + ArchangelOfTithesPayManaToBlockAllEffect(ArchangelOfTithesPayManaToBlockAllEffect effect) { + super(effect); + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + Permanent permanent = game.getPermanent(source.getSourceId()); + if (!permanent.isAttacking()) { + return false; + } + return super.applies(event, source, game); + } + + @Override + public ArchangelOfTithesPayManaToBlockAllEffect copy() { + return new ArchangelOfTithesPayManaToBlockAllEffect(this); + } + +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/ConsulsLieutenant.java b/Mage.Sets/src/mage/sets/magicorigins/ConsulsLieutenant.java new file mode 100644 index 00000000000..26befe1d8f4 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/ConsulsLieutenant.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.magicorigins; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.condition.common.RenownCondition; +import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.abilities.keyword.RenownAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.filter.common.FilterAttackingCreature; + +/** + * + * @author LevelX2 + */ +public class ConsulsLieutenant extends CardImpl { + + public ConsulsLieutenant(UUID ownerId) { + super(ownerId, 11, "Consul's Lieutenant", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{W}{W}"); + this.expansionSetCode = "ORI"; + this.subtype.add("Human"); + this.subtype.add("Soldier"); + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + // First strike + this.addAbility(FirstStrikeAbility.getInstance()); + // Renown 1 + this.addAbility(new RenownAbility(1)); + // Whenever Consul's Lieutenant attacks, if it's renowned, other attacking creatures you control get +1/+1 until end of turn. + this.addAbility(new ConditionalTriggeredAbility(new AttacksTriggeredAbility( + new BoostControlledEffect(1, 1, Duration.EndOfTurn, new FilterAttackingCreature("other attacking creatures you control"), true), false), + RenownCondition.getInstance(), + "Whenever Consul's Lieutenant attacks, if it's renowned, other attacking creatures you control get +1/+1 until end of turn.")); + + } + + public ConsulsLieutenant(final ConsulsLieutenant card) { + super(card); + } + + @Override + public ConsulsLieutenant copy() { + return new ConsulsLieutenant(this); + } +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/HallowedMoonlight.java b/Mage.Sets/src/mage/sets/magicorigins/HallowedMoonlight.java new file mode 100644 index 00000000000..1c2589ac464 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/HallowedMoonlight.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.magicorigins; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +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.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.ZoneChangeEvent; +import mage.players.Player; +import mage.watchers.common.CreatureWasCastWatcher; + +/** + * + * @author LevelX2 + */ +public class HallowedMoonlight extends CardImpl { + + public HallowedMoonlight(UUID ownerId) { + super(ownerId, 16, "Hallowed Moonlight", Rarity.RARE, new CardType[]{CardType.INSTANT}, "{1}{W}"); + this.expansionSetCode = "ORI"; + + // Until end of turn, if a creature would enter the battlefield and it wasn't cast, exile it instead. + this.getSpellAbility().addEffect(new HallowedMoonlightEffect()); + this.getSpellAbility().addWatcher(new CreatureWasCastWatcher()); + // Draw a card. + this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1)); + } + + public HallowedMoonlight(final HallowedMoonlight card) { + super(card); + } + + @Override + public HallowedMoonlight copy() { + return new HallowedMoonlight(this); + } +} + +class HallowedMoonlightEffect extends ReplacementEffectImpl { + + public HallowedMoonlightEffect() { + super(Duration.EndOfTurn, Outcome.Exile); + staticText = "Until end of turn, if a creature would enter the battlefield and it wasn't cast, exile it instead"; + } + + public HallowedMoonlightEffect(final HallowedMoonlightEffect effect) { + super(effect); + } + + @Override + public HallowedMoonlightEffect copy() { + return new HallowedMoonlightEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + Player controller = game.getPlayer(source.getControllerId()); + ZoneChangeEvent zEvent = (ZoneChangeEvent) event; + if (controller != null) { + Card card = game.getCard(event.getTargetId()); + if (card != null) { + controller.moveCardToExileWithInfo(card, null, "", source.getSourceId(), game, zEvent.getFromZone(), true); + } + return true; + + } + return false; + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.ZONE_CHANGE || event.getType() == GameEvent.EventType.CREATE_TOKEN; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (event.getType() == GameEvent.EventType.CREATE_TOKEN) { + // TODO: not clear how to check for creature type + // Tokens: Even though you’re probably casting a spell that makes tokens (Lingering Souls, Raise the Alarm, etc), + // the tokens themselves are not cast. As such, Hallowed Moonlight will stop ANY kind of creature tokens + // from entering the battlefield. + return true; + } + if (((ZoneChangeEvent) event).getToZone() == Zone.BATTLEFIELD) { + Card card = game.getCard(event.getTargetId()); + if (card != null && card.getCardType().contains(CardType.CREATURE)) { + // TODO: Bestow Card cast as Enchantment probably not handled correctly + CreatureWasCastWatcher watcher = (CreatureWasCastWatcher) game.getState().getWatchers().get("CreatureWasCast"); + if (watcher != null && !watcher.wasCreatureCastThisTurn(event.getTargetId())) { + return true; + } + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/KytheonsTactics.java b/Mage.Sets/src/mage/sets/magicorigins/KytheonsTactics.java new file mode 100644 index 00000000000..2bf1dbe507a --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/KytheonsTactics.java @@ -0,0 +1,67 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.abilities.condition.common.SpellMasteryCondition; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.abilities.keyword.VigilanceAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; + +/** + * + * @author LevelX2 + */ +public class KytheonsTactics extends CardImpl { + + public KytheonsTactics(UUID ownerId) { + super(ownerId, 25, "Kytheon's Tactics", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{1}{W}{W}"); + this.expansionSetCode = "ORI"; + + // Creatures you control get +2/+1 until end of turn. + this.getSpellAbility().addEffect(new BoostControlledEffect(2, 1, Duration.EndOfTurn)); + // Spell mastery — If there are two or more instant and/or sorcery cards in your graveyard, those creatures also gain vigilance until end of turn. + this.getSpellAbility().addEffect(new ConditionalContinuousEffect(new GainAbilityControlledEffect(VigilanceAbility.getInstance(), Duration.EndOfTurn), + SpellMasteryCondition.getInstance(), + "
Spell mastery — If there are two or more instant and/or sorcery cards in your graveyard, those creatures also gain vigilance until end of turn")); + } + + public KytheonsTactics(final KytheonsTactics card) { + super(card); + } + + @Override + public KytheonsTactics copy() { + return new KytheonsTactics(this); + } +} diff --git a/Mage/src/mage/abilities/effects/common/combat/CantAttackYouUnlessPayManaAllEffect.java b/Mage/src/mage/abilities/effects/common/combat/CantAttackYouUnlessPayManaAllEffect.java index 18463843955..4c359b4aa37 100644 --- a/Mage/src/mage/abilities/effects/common/combat/CantAttackYouUnlessPayManaAllEffect.java +++ b/Mage/src/mage/abilities/effects/common/combat/CantAttackYouUnlessPayManaAllEffect.java @@ -1,7 +1,29 @@ /* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. + * 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.abilities.effects.common.combat; diff --git a/Mage/src/mage/abilities/effects/common/combat/CantBlockUnlessPayManaAllEffect.java b/Mage/src/mage/abilities/effects/common/combat/CantBlockUnlessPayManaAllEffect.java new file mode 100644 index 00000000000..f8d42a4c4b9 --- /dev/null +++ b/Mage/src/mage/abilities/effects/common/combat/CantBlockUnlessPayManaAllEffect.java @@ -0,0 +1,88 @@ +/* + * 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.abilities.effects.common.combat; + +import mage.abilities.Ability; +import mage.abilities.costs.mana.ManaCosts; +import mage.abilities.effects.PayCostToAttackBlockEffectImpl; +import mage.abilities.effects.PayCostToAttackBlockEffectImpl.RestrictType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.filter.common.FilterCreaturePermanent; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; + +/** + * + * @author LevelX2 + */ +public class CantBlockUnlessPayManaAllEffect extends PayCostToAttackBlockEffectImpl { + + private final FilterCreaturePermanent filterCreaturePermanent; + + public CantBlockUnlessPayManaAllEffect(ManaCosts manaCosts) { + this(manaCosts, false); + } + + public CantBlockUnlessPayManaAllEffect(ManaCosts manaCosts, boolean payAlsoForAttackingPlaneswalker) { + this(manaCosts, payAlsoForAttackingPlaneswalker, null); + } + + public CantBlockUnlessPayManaAllEffect(ManaCosts manaCosts, boolean payAlsoForAttackingPlaneswalker, FilterCreaturePermanent filter) { + super(Duration.WhileOnBattlefield, Outcome.Detriment, RestrictType.BLOCK, manaCosts); + this.filterCreaturePermanent = filter; + staticText = (filterCreaturePermanent == null ? "Creatures" : filterCreaturePermanent.getMessage()) + + " can't block " + + "unless their controller pays " + + (manaCosts == null ? "" : manaCosts.getText()) + + " for each blocking creature he or she controls"; + } + + public CantBlockUnlessPayManaAllEffect(CantBlockUnlessPayManaAllEffect effect) { + super(effect); + this.filterCreaturePermanent = effect.filterCreaturePermanent; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + // check if blocking creature fullfills filter criteria + if (filterCreaturePermanent != null) { + Permanent permanent = game.getPermanent(event.getSourceId()); + if (!filterCreaturePermanent.match(permanent, source.getSourceId(), source.getControllerId(), game)) { + return false; + } + } + return true; + } + + @Override + public CantBlockUnlessPayManaAllEffect copy() { + return new CantBlockUnlessPayManaAllEffect(this); + } +} diff --git a/Mage/src/mage/watchers/common/CreatureWasCastWatcher.java b/Mage/src/mage/watchers/common/CreatureWasCastWatcher.java new file mode 100644 index 00000000000..e693a010556 --- /dev/null +++ b/Mage/src/mage/watchers/common/CreatureWasCastWatcher.java @@ -0,0 +1,93 @@ +/* + * 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.watchers.common; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; +import mage.cards.Card; +import mage.constants.CardType; +import mage.constants.WatcherScope; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.ZoneChangeEvent; +import mage.game.stack.Spell; +import mage.watchers.Watcher; + +/** + * + * @author LevelX2 + */ +public class CreatureWasCastWatcher extends Watcher { + + private final Set creaturesCasted = new HashSet<>(); + + public CreatureWasCastWatcher() { + super("CreatureWasCast", WatcherScope.GAME); + } + + public CreatureWasCastWatcher(final CreatureWasCastWatcher watcher) { + super(watcher); + } + + @Override + public void watch(GameEvent event, Game game) { + if (event.getType() == GameEvent.EventType.SPELL_CAST) { + Spell spell = (Spell) game.getObject(event.getTargetId()); + if (spell != null) { + Card card = game.getCard(spell.getSourceId()); + if (card != null && card.getCardType().contains(CardType.CREATURE)) { + creaturesCasted.add(card.getId()); + } + } + } + if (event.getType() == GameEvent.EventType.ZONE_CHANGE + && ((ZoneChangeEvent) event).getFromZone() == Zone.BATTLEFIELD) { + Card card = game.getCard(event.getTargetId()); + if (card != null && card.getCardType().contains(CardType.CREATURE)) { + creaturesCasted.remove(card.getId()); + } + } + } + + public boolean wasCreatureCastThisTurn(UUID creatureSourceId) { + return creaturesCasted.contains(creatureSourceId); + } + + @Override + public void reset() { + super.reset(); + creaturesCasted.clear(); + } + + @Override + public CreatureWasCastWatcher copy() { + return new CreatureWasCastWatcher(this); + } +} From 0b26aaff6ec033a538179bf607b1c7a7736aedb2 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Mon, 6 Jul 2015 00:57:53 +0200 Subject: [PATCH 074/105] Fixed Ensoul Artifact not giving P/T to the target artifact. --- Mage.Sets/src/mage/sets/MagicOrigins.java | 10 +-- .../cards/continuous/EnsoulArtifactTest.java | 62 +++++++++++++++++++ .../BecomesCreatureAttachedEffect.java | 11 +--- 3 files changed, 70 insertions(+), 13 deletions(-) create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/continuous/EnsoulArtifactTest.java diff --git a/Mage.Sets/src/mage/sets/MagicOrigins.java b/Mage.Sets/src/mage/sets/MagicOrigins.java index cc4c9524148..d9d75e78dd0 100644 --- a/Mage.Sets/src/mage/sets/MagicOrigins.java +++ b/Mage.Sets/src/mage/sets/MagicOrigins.java @@ -51,11 +51,11 @@ public class MagicOrigins extends ExpansionSet { this.numBoosterUncommon = 3; this.numBoosterRare = 1; this.ratioBoosterMythic = 8; - /* There are 15 additional cards, numbered 270–284, that don't appear in Magic - 2015 booster packs. These are reprints from earlier sets that are present in - some supplemental products, including sample decks and the Deck Builder's Toolkit. - These additional cards have a Magic 2015 expansion symbol and are legal in all - formats in which Magic 2015 is legal. */ + /* There are additional cards, numbered 273–288, that don't appear in Magic + Origin booster packs. These are reprints from earlier sets that are present in + some supplemental products, including sample decks and the Deck Builder's Toolkit. + These additional cards have a Magic Origin expansion symbol and are legal in all + formats in which Magic Origins is legal. */ this.maxCardNumberInBooster = 272; } } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/continuous/EnsoulArtifactTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/continuous/EnsoulArtifactTest.java new file mode 100644 index 00000000000..666bc718b50 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/continuous/EnsoulArtifactTest.java @@ -0,0 +1,62 @@ +/* + * 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 org.mage.test.cards.continuous; + +import mage.abilities.keyword.IndestructibleAbility; +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ +public class EnsoulArtifactTest extends CardTestPlayerBase { + + /** + * Tests boost disappeared after creature died + */ + @Test + public void testBoostWithUndying() { + addCard(Zone.BATTLEFIELD, playerA, "Darksteel Citadel", 1); + addCard(Zone.BATTLEFIELD, playerA, "Island", 2); + + // Enchanted artifact is a creature with base power and toughness 5/5 in addition to its other types. + addCard(Zone.HAND, playerA, "Ensoul Artifact"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Ensoul Artifact", "Darksteel Citadel"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertAbility(playerA, "Darksteel Citadel", IndestructibleAbility.getInstance(), true); + assertPowerToughness(playerA, "Darksteel Citadel", 5, 5); + } + +} diff --git a/Mage/src/mage/abilities/effects/common/continuous/BecomesCreatureAttachedEffect.java b/Mage/src/mage/abilities/effects/common/continuous/BecomesCreatureAttachedEffect.java index cf5a907365e..1658b00fc80 100644 --- a/Mage/src/mage/abilities/effects/common/continuous/BecomesCreatureAttachedEffect.java +++ b/Mage/src/mage/abilities/effects/common/continuous/BecomesCreatureAttachedEffect.java @@ -155,14 +155,9 @@ public class BecomesCreatureAttachedEffect extends ContinuousEffectImpl { break; case PTChangingEffects_7: if (sublayer == SubLayer.SetPT_7b) { - switch (loseType) { - case ALL: - case ALL_BUT_COLOR: - case ABILITIES_AND_PT: - permanent.getPower().setValue(token.getPower().getValue()); - permanent.getToughness().setValue(token.getToughness().getValue()); - break; - } + permanent.getPower().setValue(token.getPower().getValue()); + permanent.getToughness().setValue(token.getToughness().getValue()); + break; } } } From 98d3f3193c053c11c22a51fd91fe8686bff27ff4 Mon Sep 17 00:00:00 2001 From: LoneFox Date: Mon, 6 Jul 2015 09:07:59 +0300 Subject: [PATCH 075/105] Implement cards: Armored Guardian, Blind Seer, Blinding Light, and Samite Archer --- .../mage/sets/invasion/ArmoredGuardian.java | 79 +++++++++++++++++++ .../src/mage/sets/invasion/BlindSeer.java | 74 +++++++++++++++++ .../src/mage/sets/invasion/BlindingLight.java | 53 +++++++++++++ .../src/mage/sets/invasion/SamiteArcher.java | 79 +++++++++++++++++++ .../src/mage/sets/mirage/BlindingLight.java | 69 ++++++++++++++++ .../src/mage/sets/portal/BlindingLight.java | 55 +++++++++++++ .../mage/sets/starter1999/BlindingLight.java | 55 +++++++++++++ 7 files changed, 464 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/invasion/ArmoredGuardian.java create mode 100644 Mage.Sets/src/mage/sets/invasion/BlindSeer.java create mode 100644 Mage.Sets/src/mage/sets/invasion/BlindingLight.java create mode 100644 Mage.Sets/src/mage/sets/invasion/SamiteArcher.java create mode 100644 Mage.Sets/src/mage/sets/mirage/BlindingLight.java create mode 100644 Mage.Sets/src/mage/sets/portal/BlindingLight.java create mode 100644 Mage.Sets/src/mage/sets/starter1999/BlindingLight.java diff --git a/Mage.Sets/src/mage/sets/invasion/ArmoredGuardian.java b/Mage.Sets/src/mage/sets/invasion/ArmoredGuardian.java new file mode 100644 index 00000000000..875c459a54e --- /dev/null +++ b/Mage.Sets/src/mage/sets/invasion/ArmoredGuardian.java @@ -0,0 +1,79 @@ +/* + * 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.invasion; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.effects.common.continuous.GainProtectionFromColorTargetEffect; +import mage.abilities.keyword.ProtectionAbility; +import mage.abilities.keyword.ShroudAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.target.common.TargetControlledCreaturePermanent; + +/** + * + * @author LoneFox + + */ +public class ArmoredGuardian extends CardImpl { + + public ArmoredGuardian(UUID ownerId) { + super(ownerId, 230, "Armored Guardian", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{3}{W}{U}"); + this.expansionSetCode = "INV"; + this.subtype.add("Cat"); + this.subtype.add("Soldier"); + this.power = new MageInt(2); + this.toughness = new MageInt(5); + + // {1}{W}{W}: Target creature you control gains protection from the color of your choice until end of turn. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new GainProtectionFromColorTargetEffect(Duration.EndOfTurn), + new ManaCostsImpl("{1}{W}{W}")); + ability.addTarget(new TargetControlledCreaturePermanent()); + this.addAbility(ability); + // {1}{U}{U}: Armored Guardian gains shroud until end of turn. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new GainAbilitySourceEffect(ShroudAbility.getInstance(), Duration.EndOfTurn), + new ManaCostsImpl("{1}{U}{U}"))); + } + + public ArmoredGuardian(final ArmoredGuardian card) { + super(card); + } + + @Override + public ArmoredGuardian copy() { + return new ArmoredGuardian(this); + } +} diff --git a/Mage.Sets/src/mage/sets/invasion/BlindSeer.java b/Mage.Sets/src/mage/sets/invasion/BlindSeer.java new file mode 100644 index 00000000000..aa9a60a6383 --- /dev/null +++ b/Mage.Sets/src/mage/sets/invasion/BlindSeer.java @@ -0,0 +1,74 @@ +/* + * 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.invasion; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.continuous.BecomesColorTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.target.common.TargetSpellOrPermanent; + +/** + * + * @author LoneFox + + */ +public class BlindSeer extends CardImpl { + + public BlindSeer(UUID ownerId) { + super(ownerId, 47, "Blind Seer", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{2}{U}{U}"); + this.expansionSetCode = "INV"; + this.supertype.add("Legendary"); + this.subtype.add("Human"); + this.subtype.add("Wizard"); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // {1}{U}: Target spell or permanent becomes the color of your choice until end of turn. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BecomesColorTargetEffect(Duration.EndOfTurn), + new ManaCostsImpl("{1}{U}")); + ability.addTarget(new TargetSpellOrPermanent()); + this.addAbility(ability); + } + + public BlindSeer(final BlindSeer card) { + super(card); + } + + @Override + public BlindSeer copy() { + return new BlindSeer(this); + } +} diff --git a/Mage.Sets/src/mage/sets/invasion/BlindingLight.java b/Mage.Sets/src/mage/sets/invasion/BlindingLight.java new file mode 100644 index 00000000000..65a593b5788 --- /dev/null +++ b/Mage.Sets/src/mage/sets/invasion/BlindingLight.java @@ -0,0 +1,53 @@ +/* + * 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.invasion; + +import java.util.UUID; + +/** + * + * @author LoneFox + + */ +public class BlindingLight extends mage.sets.mirage.BlindingLight { + + public BlindingLight(UUID ownerId) { + super(ownerId); + this.cardNumber = 9; + this.expansionSetCode = "INV"; + } + + public BlindingLight(final BlindingLight card) { + super(card); + } + + @Override + public BlindingLight copy() { + return new BlindingLight(this); + } +} diff --git a/Mage.Sets/src/mage/sets/invasion/SamiteArcher.java b/Mage.Sets/src/mage/sets/invasion/SamiteArcher.java new file mode 100644 index 00000000000..ee23bb2bb9b --- /dev/null +++ b/Mage.Sets/src/mage/sets/invasion/SamiteArcher.java @@ -0,0 +1,79 @@ +/* + * 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.invasion; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.PreventDamageToTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.target.common.TargetCreatureOrPlayer; + +/** + * + * @author LoneFox + + */ +public class SamiteArcher extends CardImpl { + + public SamiteArcher(UUID ownerId) { + super(ownerId, 269, "Samite Archer", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{1}{W}{U}"); + this.expansionSetCode = "INV"; + this.subtype.add("Human"); + this.subtype.add("Cleric"); + this.subtype.add("Archer"); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // {T}: Prevent the next 1 damage that would be dealt to target creature or player this turn. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new PreventDamageToTargetEffect(Duration.EndOfTurn, 1), + new TapSourceCost()); + ability.addTarget(new TargetCreatureOrPlayer()); + this.addAbility(ability); + // {T}: Samite Archer deals 1 damage to target creature or player. + ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(1), new TapSourceCost()); + ability.addTarget(new TargetCreatureOrPlayer()); + this.addAbility(ability); + } + + public SamiteArcher(final SamiteArcher card) { + super(card); + } + + @Override + public SamiteArcher copy() { + return new SamiteArcher(this); + } +} diff --git a/Mage.Sets/src/mage/sets/mirage/BlindingLight.java b/Mage.Sets/src/mage/sets/mirage/BlindingLight.java new file mode 100644 index 00000000000..afb96c8c33d --- /dev/null +++ b/Mage.Sets/src/mage/sets/mirage/BlindingLight.java @@ -0,0 +1,69 @@ +/* + * 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.mirage; + +import java.util.UUID; +import mage.ObjectColor; +import mage.abilities.effects.common.TapAllEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.ColorPredicate; + +/** + * + * @author LoneFox + + */ +public class BlindingLight extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nonwhite creatures"); + + static { + filter.add(Predicates.not(new ColorPredicate(ObjectColor.WHITE))); + } + + public BlindingLight(UUID ownerId) { + super(ownerId, 209, "Blinding Light", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{2}{W}"); + this.expansionSetCode = "MIR"; + + // Tap all nonwhite creatures. + this.getSpellAbility().addEffect(new TapAllEffect(filter)); + } + + public BlindingLight(final BlindingLight card) { + super(card); + } + + @Override + public BlindingLight copy() { + return new BlindingLight(this); + } +} diff --git a/Mage.Sets/src/mage/sets/portal/BlindingLight.java b/Mage.Sets/src/mage/sets/portal/BlindingLight.java new file mode 100644 index 00000000000..615d884a504 --- /dev/null +++ b/Mage.Sets/src/mage/sets/portal/BlindingLight.java @@ -0,0 +1,55 @@ +/* + * 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.portal; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author LoneFox + + */ +public class BlindingLight extends mage.sets.mirage.BlindingLight { + + public BlindingLight(UUID ownerId) { + super(ownerId); + this.cardNumber = 170; + this.expansionSetCode = "POR"; + this.rarity = Rarity.RARE; + } + + public BlindingLight(final BlindingLight card) { + super(card); + } + + @Override + public BlindingLight copy() { + return new BlindingLight(this); + } +} diff --git a/Mage.Sets/src/mage/sets/starter1999/BlindingLight.java b/Mage.Sets/src/mage/sets/starter1999/BlindingLight.java new file mode 100644 index 00000000000..2d56300260e --- /dev/null +++ b/Mage.Sets/src/mage/sets/starter1999/BlindingLight.java @@ -0,0 +1,55 @@ +/* + * 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.starter1999; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author LoneFox + + */ +public class BlindingLight extends mage.sets.mirage.BlindingLight { + + public BlindingLight(UUID ownerId) { + super(ownerId); + this.cardNumber = 8; + this.expansionSetCode = "S99"; + this.rarity = Rarity.RARE; + } + + public BlindingLight(final BlindingLight card) { + super(card); + } + + @Override + public BlindingLight copy() { + return new BlindingLight(this); + } +} From 9be613beb9e82892d6b438f1bd3949e069f7ea3b Mon Sep 17 00:00:00 2001 From: Nidhoegger Date: Mon, 6 Jul 2015 10:51:06 +0200 Subject: [PATCH 076/105] Fixed Issue #1054. Buttons in Feedback panel will only get focused, if the MageFrame has the focus thus preventing focus theft from other programs. --- .../src/main/java/mage/client/game/FeedbackPanel.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Mage.Client/src/main/java/mage/client/game/FeedbackPanel.java b/Mage.Client/src/main/java/mage/client/game/FeedbackPanel.java index 778c6ae58c2..0190ec139bc 100644 --- a/Mage.Client/src/main/java/mage/client/game/FeedbackPanel.java +++ b/Mage.Client/src/main/java/mage/client/game/FeedbackPanel.java @@ -201,9 +201,12 @@ public class FeedbackPanel extends javax.swing.JPanel { } // Issue 256: Chat+Feedback panel: request focus prevents players from chatting - private void requestFocusIfPossible() { + // Issue #1054: XMage steals window focus whenever the screen updates + private void requestFocusIfPossible() { boolean requestFocusAllowed = true; - if (connectedChatPanel != null && connectedChatPanel.getTxtMessageInputComponent() != null) { + if (MageFrame.getInstance().getFocusOwner() == null) { + requestFocusAllowed = false; + } else if (connectedChatPanel != null && connectedChatPanel.getTxtMessageInputComponent() != null) { if (connectedChatPanel.getTxtMessageInputComponent().hasFocus()) { requestFocusAllowed = false; } From c942592c3b72ce4ec6e4eceead03192e19762fdf Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Mon, 6 Jul 2015 13:36:23 +0200 Subject: [PATCH 077/105] * Dash - Fixed that the creature was returned to hand from dash also if it left battlefield before. --- .../sets/returntoravnica/AngelOfSerenity.java | 11 ++-- .../sets/returntoravnica/UltimatePrice.java | 2 - .../cards/abilities/keywords/DashTest.java | 62 +++++++++++++------ .../cards/abilities/keywords/RenownTest.java | 27 ++++++++ .../mage/abilities/keyword/DashAbility.java | 44 ++++++++++--- 5 files changed, 112 insertions(+), 34 deletions(-) diff --git a/Mage.Sets/src/mage/sets/returntoravnica/AngelOfSerenity.java b/Mage.Sets/src/mage/sets/returntoravnica/AngelOfSerenity.java index e59ab2b006f..06879b41d58 100644 --- a/Mage.Sets/src/mage/sets/returntoravnica/AngelOfSerenity.java +++ b/Mage.Sets/src/mage/sets/returntoravnica/AngelOfSerenity.java @@ -67,7 +67,6 @@ public class AngelOfSerenity extends CardImpl { this.power = new MageInt(5); this.toughness = new MageInt(6); - // Flying this.addAbility(FlyingAbility.getInstance()); @@ -75,7 +74,7 @@ public class AngelOfSerenity extends CardImpl { this.addAbility(new AngelOfSerenityTriggeredAbility()); // When Angel of Serenity leaves the battlefield, return the exiled cards to their owners' hands. - this.addAbility(new LeavesBattlefieldTriggeredAbility(new AngelOfSerenityLeaveEffect(), false )); + this.addAbility(new LeavesBattlefieldTriggeredAbility(new AngelOfSerenityLeaveEffect(), false)); } public AngelOfSerenity(final AngelOfSerenity card) { @@ -104,7 +103,7 @@ class AngelOfSerenityTriggeredAbility extends ZoneChangeTriggeredAbility { getTargets().clear(); FilterCreaturePermanent filter = new FilterCreaturePermanent("up to three other target creatures"); filter.add(new AnotherPredicate()); - TargetCreaturePermanent target1 = new TargetCreaturePermanent(0,3, filter, false); + TargetCreaturePermanent target1 = new TargetCreaturePermanent(0, 3, filter, false); game.getPlayer(getControllerId()).chooseTarget(Outcome.Exile, target1, this, game); if (target1.getTargets().size() > 0) { getTargets().add(target1); @@ -112,8 +111,8 @@ class AngelOfSerenityTriggeredAbility extends ZoneChangeTriggeredAbility { } int leftTargets = 3 - target1.getTargets().size(); if (leftTargets > 0) { - FilterCard filter2 = new FilterCreatureCard("up to " + leftTargets + " target creature card" + (leftTargets > 1?"s":"") +" from graveyards"); - TargetCardInGraveyard target2 = new TargetCardInGraveyard(0,leftTargets, filter2); + FilterCard filter2 = new FilterCreatureCard("up to " + leftTargets + " target creature card" + (leftTargets > 1 ? "s" : "") + " from graveyards"); + TargetCardInGraveyard target2 = new TargetCardInGraveyard(0, leftTargets, filter2); game.getPlayer(getControllerId()).chooseTarget(Outcome.Exile, target2, this, game); if (target2.getTargets().size() > 0) { getTargets().add(target2); @@ -160,7 +159,7 @@ class AngelOfSerenityEnterEffect extends OneShotEffect { } } - } else if (target instanceof TargetCardInGraveyard){ + } else if (target instanceof TargetCardInGraveyard) { for (UUID cardId : target.getTargets()) { Card card = game.getCard(cardId); if (card != null) { diff --git a/Mage.Sets/src/mage/sets/returntoravnica/UltimatePrice.java b/Mage.Sets/src/mage/sets/returntoravnica/UltimatePrice.java index 168ad1e8f70..2c2e3a4af0e 100644 --- a/Mage.Sets/src/mage/sets/returntoravnica/UltimatePrice.java +++ b/Mage.Sets/src/mage/sets/returntoravnica/UltimatePrice.java @@ -34,7 +34,6 @@ import mage.abilities.effects.common.DestroyTargetEffect; import mage.cards.CardImpl; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.MonocoloredPredicate; -import mage.target.Target; import mage.target.common.TargetCreaturePermanent; /** @@ -53,7 +52,6 @@ public class UltimatePrice extends CardImpl { super(ownerId, 82, "Ultimate Price", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{1}{B}"); this.expansionSetCode = "RTR"; - // Destroy target monocolored creature. this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); this.getSpellAbility().addEffect(new DestroyTargetEffect()); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/DashTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/DashTest.java index 5305854a07a..e5f3b6f0167 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/DashTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/DashTest.java @@ -25,7 +25,6 @@ * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package org.mage.test.cards.abilities.keywords; import mage.constants.PhaseStep; @@ -40,26 +39,25 @@ import org.mage.test.serverside.base.CardTestPlayerBase; public class DashTest extends CardTestPlayerBase { /** - * 702.108. Dash - * 702.108a Dash represents three abilities: two static abilities that function while the card with dash is - * on the stack, one of which may create a delayed triggered ability, and a static ability that - * functions while the object with dash is on the battlefield. “Dash [cost]” means “You may cast - * this card by paying [cost] rather that its mana cost,” “If this spell’s dash cost was paid, return the - * permanent this spell becomes to its owner’s hand at the beginning of the next end step,” and “As - * long as this permanent’s dash cost was paid, it has haste.” Paying a card’s dash cost follows the - * rules for paying alternative costs in rules 601.2b and 601.2e–g. - * - */ - - /** - * Screamreach Brawler - * Creature — Orc Berserker 2/3, 2R (3) - * Dash {1}{R} (You may cast this spell for its dash cost. If you do, it - * gains haste, and it's returned from the battlefield to its owner's hand - * at the beginning of the next end step.) + * 702.108. Dash 702.108a Dash represents three abilities: two static + * abilities that function while the card with dash is on the stack, one of + * which may create a delayed triggered ability, and a static ability that + * functions while the object with dash is on the battlefield. “Dash [cost]” + * means “You may cast this card by paying [cost] rather that its mana + * cost,” “If this spell’s dash cost was paid, return the permanent this + * spell becomes to its owner’s hand at the beginning of the next end step,” + * and “As long as this permanent’s dash cost was paid, it has haste.” + * Paying a card’s dash cost follows the rules for paying alternative costs + * in rules 601.2b and 601.2e–g. + * + */ + /** + * Screamreach Brawler Creature — Orc Berserker 2/3, 2R (3) Dash {1}{R} (You + * may cast this spell for its dash cost. If you do, it gains haste, and + * it's returned from the battlefield to its owner's hand at the beginning + * of the next end step.) * */ - @Test public void testDash() { addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2); @@ -96,4 +94,30 @@ public class DashTest extends CardTestPlayerBase { } + /** + * Also dash returns creatures to your hand at end of turn even if they died + * that turn. + */ + @Test + public void testDashedCreatureDiesInCombat() { + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2); + addCard(Zone.HAND, playerA, "Screamreach Brawler"); // 2/3 + + addCard(Zone.BATTLEFIELD, playerB, "Geist of the Moors", 1); // 3/1 + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Screamreach Brawler"); + setChoice(playerA, "Yes"); + attack(1, playerA, "Screamreach Brawler"); + block(1, playerB, "Geist of the Moors", "Screamreach Brawler"); + + setStopAt(2, PhaseStep.UNTAP); + execute(); + + assertLife(playerB, 20); + assertPermanentCount(playerA, "Screamreach Brawler", 0); + assertHandCount(playerA, "Screamreach Brawler", 0); + assertGraveyardCount(playerA, "Screamreach Brawler", 1); + assertGraveyardCount(playerB, "Geist of the Moors", 1); + + } } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/RenownTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/RenownTest.java index 533c50b39b4..16637cc14cd 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/RenownTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/RenownTest.java @@ -211,4 +211,31 @@ public class RenownTest extends CardTestPlayerBase { } + /** + * Ability doesn't trigger when renowned. ("Whenever an opponent casts a + * noncreature spell, if ~ is renowned, ~ deals 2 damage to that player.") + */ + @Test + public void testScabClanBerserker() { + // Renown 1 + // Whenever an opponent casts a noncreature spell, if Scab-Clan Berserker is renowned, Scab-Clan Berserker deals 2 damage to that player. + addCard(Zone.BATTLEFIELD, playerA, "Scab-Clan Berserker"); // 2/2 {1}{R}{R} + + addCard(Zone.BATTLEFIELD, playerB, "Mountain", 1); + addCard(Zone.HAND, playerB, "Lightning Bolt"); + + attack(3, playerA, "Scab-Clan Berserker"); // 1 damage + castSpell(3, PhaseStep.POSTCOMBAT_MAIN, playerB, "Lightning Bolt", playerA); + + setStopAt(3, PhaseStep.END_TURN); + execute(); + + Permanent berserker = getPermanent("Scab-Clan Berserker", playerA); + Assert.assertEquals("has has renown", true, berserker.isRenown()); + assertPowerToughness(playerA, "Scab-Clan Berserker", 3, 3); + + assertLife(playerA, 17); // Lightning Bolt + assertLife(playerB, 16); // 2 from attack 2 from triggered ability + + } } diff --git a/Mage/src/mage/abilities/keyword/DashAbility.java b/Mage/src/mage/abilities/keyword/DashAbility.java index 4072e1a8563..4a2d96170f0 100644 --- a/Mage/src/mage/abilities/keyword/DashAbility.java +++ b/Mage/src/mage/abilities/keyword/DashAbility.java @@ -31,6 +31,7 @@ import java.util.Iterator; import java.util.LinkedList; import java.util.List; import mage.abilities.Ability; +import mage.abilities.DelayedTriggeredAbility; import mage.abilities.SpellAbility; import mage.abilities.StaticAbility; import mage.abilities.common.EntersBattlefieldAbility; @@ -44,7 +45,7 @@ import mage.abilities.costs.Costs; import mage.abilities.costs.CostsImpl; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.Effect; -import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; +import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.ReturnToHandTargetEffect; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.cards.Card; @@ -76,12 +77,9 @@ public class DashAbility extends StaticAbility implements AlternativeSourceCosts Ability ability = new EntersBattlefieldAbility( new GainAbilitySourceEffect(HasteAbility.getInstance(), Duration.Custom, false), DashedCondition.getInstance(), false, "", ""); - Effect effect = new ReturnToHandTargetEffect(); - effect.setText("return the dashed creature from the battlefield to its owner's hand"); - effect.setTargetPointer(new FixedTarget(card.getId())); - ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(effect), false)); + ability.addEffect(new DashAddDelayedTriggeredAbilityEffect()); addSubAbility(ability); - + } public DashAbility(final DashAbility ability) { @@ -134,7 +132,7 @@ public class DashAbility extends StaticAbility implements AlternativeSourceCosts this.resetDash(); for (AlternativeCost2 dashCost : alternativeSourceCosts) { if (dashCost.canPay(ability, sourceId, controllerId, game) - && player.chooseUse(Outcome.Benefit, new StringBuilder(KEYWORD).append(" the creature for ").append(dashCost.getText(true)).append(" ?").toString(), ability, game)) { + && player.chooseUse(Outcome.Benefit, KEYWORD + " the creature for " + dashCost.getText(true) + " ?", ability, game)) { activateDash(dashCost, game); ability.getManaCostsToPay().clear(); ability.getCosts().clear(); @@ -209,3 +207,35 @@ public class DashAbility extends StaticAbility implements AlternativeSourceCosts return alterCosts; } } + +class DashAddDelayedTriggeredAbilityEffect extends OneShotEffect { + + public DashAddDelayedTriggeredAbilityEffect() { + super(Outcome.Benefit); + this.staticText = "return the dashed creature from the battlefield to its owner's hand"; + } + + public DashAddDelayedTriggeredAbilityEffect(final DashAddDelayedTriggeredAbilityEffect effect) { + super(effect); + } + + @Override + public DashAddDelayedTriggeredAbilityEffect copy() { + return new DashAddDelayedTriggeredAbilityEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Effect effect = new ReturnToHandTargetEffect(); + effect.setText("return the dashed creature from the battlefield to its owner's hand"); + effect.setTargetPointer(new FixedTarget(source.getSourceId())); + // init target pointer now because the dashed creature will only be returned from current zone + effect.getTargetPointer().init(game, source); + DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(effect); + delayedAbility.setSourceId(source.getSourceId()); + delayedAbility.setControllerId(source.getControllerId()); + delayedAbility.setSourceObject(source.getSourceObject(game), game); + game.addDelayedTriggeredAbility(delayedAbility); + return false; + } +} From b45cdb9a556b59cc78b4969ab33bd53ed346c898 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Mon, 6 Jul 2015 13:51:55 +0200 Subject: [PATCH 078/105] * Mistmeadow Witch - Fixed the unexpected tap source cost. --- Mage.Sets/src/mage/sets/shadowmoor/MistmeadowWitch.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/Mage.Sets/src/mage/sets/shadowmoor/MistmeadowWitch.java b/Mage.Sets/src/mage/sets/shadowmoor/MistmeadowWitch.java index 0b85cca6af5..f5acde0684e 100644 --- a/Mage.Sets/src/mage/sets/shadowmoor/MistmeadowWitch.java +++ b/Mage.Sets/src/mage/sets/shadowmoor/MistmeadowWitch.java @@ -36,7 +36,6 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; -import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.ReturnFromExileEffect; @@ -62,7 +61,6 @@ public class MistmeadowWitch extends CardImpl { // {2}{W}{U}: Exile target creature. Return that card to the battlefield under its owner's control at the beginning of the next end step. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new MistmeadowWitchEffect(), new ManaCostsImpl("{2}{W}{U}")); - ability.addCost(new TapSourceCost()); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); } From 1ee75e3e94b30b126791c6c02294200f71765b4b Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Mon, 6 Jul 2015 15:22:16 +0200 Subject: [PATCH 079/105] * Angel of Serenity - Fixed that the exiled cards did not return when the Angel left the battlefield (fixes #1083). --- .../sets/returntoravnica/AngelOfSerenity.java | 46 ++------- .../EnterLeaveBattlefieldExileTargetTest.java | 99 +++++++++++++++++++ ...ereTest.java => JourneyToNowhereTest.java} | 2 +- .../ReturnFromExileForSourceEffect.java | 98 +++++++++--------- Mage/src/mage/players/PlayerImpl.java | 6 ++ Utils/release/getting_implemented_cards.txt | 3 + 6 files changed, 168 insertions(+), 86 deletions(-) create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/triggers/EnterLeaveBattlefieldExileTargetTest.java rename Mage.Tests/src/test/java/org/mage/test/cards/triggers/{JournexToNowhereTest.java => JourneyToNowhereTest.java} (96%) diff --git a/Mage.Sets/src/mage/sets/returntoravnica/AngelOfSerenity.java b/Mage.Sets/src/mage/sets/returntoravnica/AngelOfSerenity.java index 06879b41d58..d71d7c49ce0 100644 --- a/Mage.Sets/src/mage/sets/returntoravnica/AngelOfSerenity.java +++ b/Mage.Sets/src/mage/sets/returntoravnica/AngelOfSerenity.java @@ -29,10 +29,12 @@ package mage.sets.returntoravnica; import java.util.UUID; import mage.MageInt; +import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.LeavesBattlefieldTriggeredAbility; import mage.abilities.common.ZoneChangeTriggeredAbility; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ReturnFromExileForSourceEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.Card; import mage.cards.CardImpl; @@ -44,10 +46,10 @@ import mage.filter.FilterCard; import mage.filter.common.FilterCreatureCard; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.AnotherPredicate; -import mage.game.ExileZone; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; +import mage.players.Player; import mage.target.Target; import mage.target.common.TargetCardInGraveyard; import mage.target.common.TargetCreaturePermanent; @@ -74,7 +76,7 @@ public class AngelOfSerenity extends CardImpl { this.addAbility(new AngelOfSerenityTriggeredAbility()); // When Angel of Serenity leaves the battlefield, return the exiled cards to their owners' hands. - this.addAbility(new LeavesBattlefieldTriggeredAbility(new AngelOfSerenityLeaveEffect(), false)); + this.addAbility(new LeavesBattlefieldTriggeredAbility(new ReturnFromExileForSourceEffect(Zone.HAND, false, true), false)); } public AngelOfSerenity(final AngelOfSerenity card) { @@ -149,13 +151,16 @@ class AngelOfSerenityEnterEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { boolean result = true; - if (source.getTargets().size() > 0) { + Player controller = game.getPlayer(source.getControllerId()); + MageObject sourceObject = game.getObject(source.getSourceId()); + if (controller != null && sourceObject != null && source.getTargets().size() > 0) { + UUID exileZoneId = CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter()); for (Target target : source.getTargets()) { if (target instanceof TargetCreaturePermanent) { for (UUID permanentId : target.getTargets()) { Permanent permanent = game.getPermanent(permanentId); if (permanent != null) { - result |= permanent.moveToExile(CardUtil.getCardExileZoneId(game, source), "Angel of Serenity", source.getSourceId(), game); + result |= controller.moveCardToExileWithInfo(permanent, exileZoneId, sourceObject.getIdName(), source.getSourceId(), game, Zone.BATTLEFIELD, true); } } @@ -163,7 +168,7 @@ class AngelOfSerenityEnterEffect extends OneShotEffect { for (UUID cardId : target.getTargets()) { Card card = game.getCard(cardId); if (card != null) { - result |= card.moveToExile(CardUtil.getCardExileZoneId(game, source), "Angel of Serenity", source.getSourceId(), game); + result |= controller.moveCardToExileWithInfo(card, exileZoneId, sourceObject.getIdName(), source.getSourceId(), game, Zone.GRAVEYARD, true); } } } @@ -172,34 +177,3 @@ class AngelOfSerenityEnterEffect extends OneShotEffect { return result; } } - -class AngelOfSerenityLeaveEffect extends OneShotEffect { - - public AngelOfSerenityLeaveEffect() { - super(Outcome.ReturnToHand); - this.staticText = "return the exiled cards to their owners' hands"; - } - - public AngelOfSerenityLeaveEffect(final AngelOfSerenityLeaveEffect effect) { - super(effect); - } - - @Override - public AngelOfSerenityLeaveEffect copy() { - return new AngelOfSerenityLeaveEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - ExileZone exZone = game.getExile().getExileZone(CardUtil.getCardExileZoneId(game, source)); - if (exZone != null) { - for (Card card : exZone.getCards(game)) { - if (card != null) { - card.moveToZone(Zone.HAND, source.getSourceId(), game, false); - } - } - return true; - } - return false; - } -} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/EnterLeaveBattlefieldExileTargetTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/EnterLeaveBattlefieldExileTargetTest.java new file mode 100644 index 00000000000..a8088969696 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/EnterLeaveBattlefieldExileTargetTest.java @@ -0,0 +1,99 @@ +/* + * 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 org.mage.test.cards.triggers; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ +public class EnterLeaveBattlefieldExileTargetTest extends CardTestPlayerBase { + + @Test + public void testAngelOfSerenityExile() { + // Flying + // When Angel of Serenity enters the battlefield, you may exile up to three other target creatures from the battlefield and/or creature cards from graveyards. + // When Angel of Serenity leaves the battlefield, return the exiled cards to their owners' hands. + addCard(Zone.HAND, playerA, "Angel of Serenity"); + addCard(Zone.BATTLEFIELD, playerA, "Plains", 7); + + addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion", 1); + addCard(Zone.BATTLEFIELD, playerB, "Pillarfield Ox", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Angel of Serenity"); + addTarget(playerA, "Silvercoat Lion^Pillarfield Ox"); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertPermanentCount(playerA, "Angel of Serenity", 1); + assertExileCount("Silvercoat Lion", 1); + assertExileCount("Pillarfield Ox", 1); + + } + + /** + * When Angel of Serenity entered the battlefield on my opponent's main + * phase it exiled 3 of my creatures (as it should), I cast Ultimate Price + * (destroy monocolored creature) on my next main phase and destroyed the + * Angel of Serenity. The log said the exiled cards were returned to my hand + * but they remained in exile indefinitely. + */ + @Test + public void testAngelOfSerenityExileReturn() { + // Flying + // When Angel of Serenity enters the battlefield, you may exile up to three other target creatures from the battlefield and/or creature cards from graveyards. + // When Angel of Serenity leaves the battlefield, return the exiled cards to their owners' hands. + addCard(Zone.HAND, playerA, "Angel of Serenity"); + addCard(Zone.BATTLEFIELD, playerA, "Plains", 7); + + addCard(Zone.BATTLEFIELD, playerB, "Swamp", 2); + addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion", 1); + addCard(Zone.BATTLEFIELD, playerB, "Pillarfield Ox", 1); + addCard(Zone.HAND, playerB, "Ultimate Price", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Angel of Serenity"); + addTarget(playerA, "Silvercoat Lion^Pillarfield Ox"); + + castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Ultimate Price", "Angel of Serenity"); + + setStopAt(2, PhaseStep.BEGIN_COMBAT); + execute(); + + assertGraveyardCount(playerB, "Ultimate Price", 1); + assertGraveyardCount(playerA, "Angel of Serenity", 1); + assertHandCount(playerB, "Silvercoat Lion", 1); + assertHandCount(playerB, "Pillarfield Ox", 1); + assertExileCount(playerB, 0); + + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/JournexToNowhereTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/JourneyToNowhereTest.java similarity index 96% rename from Mage.Tests/src/test/java/org/mage/test/cards/triggers/JournexToNowhereTest.java rename to Mage.Tests/src/test/java/org/mage/test/cards/triggers/JourneyToNowhereTest.java index 9199ba892e2..8cef82f8998 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/JournexToNowhereTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/JourneyToNowhereTest.java @@ -37,7 +37,7 @@ import org.mage.test.serverside.base.CardTestPlayerBase; * @author LeveX2 */ -public class JournexToNowhereTest extends CardTestPlayerBase { +public class JourneyToNowhereTest extends CardTestPlayerBase { /* Journey to Nowhere Enchantment {1}{W} diff --git a/Mage/src/mage/abilities/effects/common/ReturnFromExileForSourceEffect.java b/Mage/src/mage/abilities/effects/common/ReturnFromExileForSourceEffect.java index f1e23475651..181bb35f94c 100644 --- a/Mage/src/mage/abilities/effects/common/ReturnFromExileForSourceEffect.java +++ b/Mage/src/mage/abilities/effects/common/ReturnFromExileForSourceEffect.java @@ -1,35 +1,32 @@ /* -* 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. -*/ - + * 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.abilities.effects.common; -import java.util.LinkedList; -import java.util.UUID; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; @@ -41,6 +38,7 @@ import static mage.constants.Zone.GRAVEYARD; import static mage.constants.Zone.HAND; import mage.game.ExileZone; import mage.game.Game; +import mage.game.permanent.PermanentToken; import mage.players.Player; import mage.util.CardUtil; @@ -55,7 +53,7 @@ public class ReturnFromExileForSourceEffect extends OneShotEffect { private boolean previousZone; /** - * + * * @param zone Zone the card should return to */ public ReturnFromExileForSourceEffect(Zone zone) { @@ -65,12 +63,13 @@ public class ReturnFromExileForSourceEffect extends OneShotEffect { public ReturnFromExileForSourceEffect(Zone zone, boolean tapped) { this(zone, tapped, true); } - + /** - * + * * @param zone * @param tapped - * @param previousZone if this is used from a dies leave battlefield or destroyed trigger, the exile zone is based on previous zone of the object + * @param previousZone if this is used from a dies leave battlefield or + * destroyed trigger, the exile zone is based on previous zone of the object */ public ReturnFromExileForSourceEffect(Zone zone, boolean tapped, boolean previousZone) { super(Outcome.PutCardInPlay); @@ -94,24 +93,25 @@ public class ReturnFromExileForSourceEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - int zoneChangeCounter = source.getSourceObjectZoneChangeCounter() - (previousZone ? 1:0); - UUID exileId = CardUtil.getExileZoneId(game, source.getSourceId(), zoneChangeCounter); - ExileZone exile = game.getExile().getExileZone(exileId); + Player controller = game.getPlayer(source.getControllerId()); + MageObject sourceObject = source.getSourceObject(game); + if (sourceObject != null && controller != null) { + int zoneChangeCounter = source.getSourceObjectZoneChangeCounter(); + if (zoneChangeCounter > 0 && previousZone && !(sourceObject instanceof PermanentToken)) { + zoneChangeCounter--; + } + ExileZone exile = game.getExile().getExileZone(CardUtil.getExileZoneId(game, source.getSourceId(), zoneChangeCounter)); if (exile != null) { // null is valid if source left battlefield before enters the battlefield effect resolved - LinkedList cards = new LinkedList<>(exile); - for (UUID cardId: cards) { - Card card = game.getCard(cardId); - if (card == null) { - return false; + if (returnToZone.equals(Zone.BATTLEFIELD)) { + for (Card card : exile.getCards(game)) { + Player owner = game.getPlayer(card.getOwnerId()); + if (owner != null) { + owner.putOntoBattlefieldWithInfo(card, game, Zone.EXILED, source.getSourceId()); + } } - if (!game.isSimulation()) { - game.informPlayers(controller.getLogName() + " moves " + card.getLogName() + " from exile to " + returnToZone.toString().toLowerCase()); - } - card.moveToZone(returnToZone, source.getSourceId(), game, tapped); + } else { + controller.moveCards(exile, Zone.EXILED, returnToZone, source, game); } - exile.clear(); } return true; } @@ -121,7 +121,7 @@ public class ReturnFromExileForSourceEffect extends OneShotEffect { private void setText() { StringBuilder sb = new StringBuilder(); sb.append("return the exiled cards "); - switch(returnToZone) { + switch (returnToZone) { case BATTLEFIELD: sb.append("to the battlefield under its owner's control"); if (tapped) { diff --git a/Mage/src/mage/players/PlayerImpl.java b/Mage/src/mage/players/PlayerImpl.java index 228cbb7de95..052ab43222f 100644 --- a/Mage/src/mage/players/PlayerImpl.java +++ b/Mage/src/mage/players/PlayerImpl.java @@ -2914,6 +2914,12 @@ public abstract class PlayerImpl implements Player, Serializable { result |= moveCardToHandWithInfo(card, source == null ? null : source.getSourceId(), game, fromZone); } return result; + case BATTLEFIELD: + result = false; + for (Card card : cards) { + result |= putOntoBattlefieldWithInfo(card, game, fromZone, source == null ? null : source.getSourceId()); + } + return result; default: throw new UnsupportedOperationException("to Zone not supported yet"); } diff --git a/Utils/release/getting_implemented_cards.txt b/Utils/release/getting_implemented_cards.txt index 9fd9eceae25..9efee636722 100644 --- a/Utils/release/getting_implemented_cards.txt +++ b/Utils/release/getting_implemented_cards.txt @@ -146,6 +146,9 @@ git log 757b9ea99ec1f0ce46bb533f9f86f3473d122a60..HEAD --diff-filter=A --name-st since 1.4.2.v0 git log cd0cba6ec7d8799bb85247b7b4f5d545e170b093..HEAD --diff-filter=A --name-status | sed -ne "s/^A[^u]Mage.Sets\/src\/mage\/sets\///p" | sort > added_cards.txt +since 1.4.2.v1 +git log 0b26aaff6ec033a538179bf607b1c7a7736aedb2..HEAD --diff-filter=A --name-status | sed -ne "s/^A[^u]Mage.Sets\/src\/mage\/sets\///p" | sort > added_cards.txt + 3. Copy added_cards.txt to trunk\Utils folder 4. Run script: > perl extract_in_wiki_format.perl From 8a43a6710946971cd644370c26cf7c41ab2a5377 Mon Sep 17 00:00:00 2001 From: LoneFox Date: Mon, 6 Jul 2015 16:47:18 +0300 Subject: [PATCH 080/105] Implement cards: Callous Giant, Tek, Voracious Cobra, and Wallop --- .../src/mage/sets/invasion/CallousGiant.java | 107 ++++++++++++++++++ Mage.Sets/src/mage/sets/invasion/Tek.java | 100 ++++++++++++++++ .../mage/sets/invasion/VoraciousCobra.java | 67 +++++++++++ Mage.Sets/src/mage/sets/invasion/Wallop.java | 74 ++++++++++++ 4 files changed, 348 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/invasion/CallousGiant.java create mode 100644 Mage.Sets/src/mage/sets/invasion/Tek.java create mode 100644 Mage.Sets/src/mage/sets/invasion/VoraciousCobra.java create mode 100644 Mage.Sets/src/mage/sets/invasion/Wallop.java diff --git a/Mage.Sets/src/mage/sets/invasion/CallousGiant.java b/Mage.Sets/src/mage/sets/invasion/CallousGiant.java new file mode 100644 index 00000000000..f7304cfad28 --- /dev/null +++ b/Mage.Sets/src/mage/sets/invasion/CallousGiant.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.invasion; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.PreventionEffectImpl; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; + +/** + * + * @author LoneFox + + */ +public class CallousGiant extends CardImpl { + + public CallousGiant(UUID ownerId) { + super(ownerId, 139, "Callous Giant", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{4}{R}{R}"); + this.expansionSetCode = "INV"; + this.subtype.add("Giant"); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // If a source would deal 3 or less damage to Callous Giant, prevent that damage. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CallousGiantEffect())); + } + + public CallousGiant(final CallousGiant card) { + super(card); + } + + @Override + public CallousGiant copy() { + return new CallousGiant(this); + } +} + +class CallousGiantEffect extends PreventionEffectImpl { + + public CallousGiantEffect() { + super(Duration.WhileOnBattlefield); + staticText = "If a source would deal 3 or less damage to {this}, prevent that damage."; + } + + public CallousGiantEffect(final CallousGiantEffect effect) { + super(effect); + } + + @Override + public CallousGiantEffect copy() { + return new CallousGiantEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + if(event.getAmount() <= 3) + { + preventDamageAction(event, source, game); + return true; + } + return false; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + return super.applies(event, source, game) && event.getTargetId().equals(source.getSourceId()); + } + +} diff --git a/Mage.Sets/src/mage/sets/invasion/Tek.java b/Mage.Sets/src/mage/sets/invasion/Tek.java new file mode 100644 index 00000000000..e4457c07a41 --- /dev/null +++ b/Mage.Sets/src/mage/sets/invasion/Tek.java @@ -0,0 +1,100 @@ +/* + * 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.invasion; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; + +/** + * + * @author LoneFox + + */ +public class Tek extends CardImpl { + + private static final FilterControlledPermanent filterPlains = new FilterControlledPermanent("Plains"); + private static final FilterControlledPermanent filterIsland = new FilterControlledPermanent("Island"); + private static final FilterControlledPermanent filterSwamp = new FilterControlledPermanent("Swamp"); + private static final FilterControlledPermanent filterMountain = new FilterControlledPermanent("Mountain"); + private static final FilterControlledPermanent filterForest = new FilterControlledPermanent("Forest"); + + static { + filterPlains.add(new SubtypePredicate("Plains")); + filterIsland.add(new SubtypePredicate("Island")); + filterSwamp.add(new SubtypePredicate("Swamp")); + filterMountain.add(new SubtypePredicate("Mountain")); + filterForest.add(new SubtypePredicate("Forest")); + } + + + public Tek(UUID ownerId) { + super(ownerId, 313, "Tek", Rarity.RARE, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{5}"); + this.expansionSetCode = "INV"; + this.subtype.add("Dragon"); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Tek gets +0/+2 as long as you control a Plains, has flying as long as you control an Island, gets +2/+0 as long as you control a Swamp, has first strike as long as you control a Mountain, and has trample as long as you control a Forest. + Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(new BoostSourceEffect(0, 2, Duration.WhileOnBattlefield), + new PermanentsOnTheBattlefieldCondition(filterPlains), "{this} gets +0/+2 as long as you control a Plains")); + ability.addEffect(new ConditionalContinuousEffect(new GainAbilitySourceEffect(FlyingAbility.getInstance(), Duration.WhileOnBattlefield), + new PermanentsOnTheBattlefieldCondition(filterIsland), ", has flying as long as you control an Island")); + ability.addEffect(new ConditionalContinuousEffect(new BoostSourceEffect(2, 0, Duration.WhileOnBattlefield), + new PermanentsOnTheBattlefieldCondition(filterSwamp), ", gets +2/+0 as long as you control a Swamp")); + ability.addEffect(new ConditionalContinuousEffect(new GainAbilitySourceEffect(FirstStrikeAbility.getInstance(), Duration.WhileOnBattlefield), + new PermanentsOnTheBattlefieldCondition(filterMountain), ", has first strike as long as you control a Mountain")); + ability.addEffect(new ConditionalContinuousEffect(new GainAbilitySourceEffect(TrampleAbility.getInstance(), Duration.WhileOnBattlefield), + new PermanentsOnTheBattlefieldCondition(filterForest), ", and has trample as long as you control a Forest.")); + this.addAbility(ability); + } + + public Tek(final Tek card) { + super(card); + } + + @Override + public Tek copy() { + return new Tek(this); + } +} diff --git a/Mage.Sets/src/mage/sets/invasion/VoraciousCobra.java b/Mage.Sets/src/mage/sets/invasion/VoraciousCobra.java new file mode 100644 index 00000000000..9bdc35bf630 --- /dev/null +++ b/Mage.Sets/src/mage/sets/invasion/VoraciousCobra.java @@ -0,0 +1,67 @@ +/* + * 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.invasion; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.DealsDamageToACreatureTriggeredAbility; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; + +/** + * + * @author LoneFox + + */ +public class VoraciousCobra extends CardImpl { + + public VoraciousCobra(UUID ownerId) { + super(ownerId, 288, "Voracious Cobra", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{2}{R}{G}"); + this.expansionSetCode = "INV"; + this.subtype.add("Snake"); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // First strike + this.addAbility(FirstStrikeAbility.getInstance()); + // Whenever Voracious Cobra deals combat damage to a creature, destroy that creature. + this.addAbility(new DealsDamageToACreatureTriggeredAbility(new DestroyTargetEffect(), true, false, true)); + } + + public VoraciousCobra(final VoraciousCobra card) { + super(card); + } + + @Override + public VoraciousCobra copy() { + return new VoraciousCobra(this); + } +} diff --git a/Mage.Sets/src/mage/sets/invasion/Wallop.java b/Mage.Sets/src/mage/sets/invasion/Wallop.java new file mode 100644 index 00000000000..d4b1b93cdea --- /dev/null +++ b/Mage.Sets/src/mage/sets/invasion/Wallop.java @@ -0,0 +1,74 @@ +/* + * 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.invasion; + +import java.util.UUID; +import mage.ObjectColor; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LoneFox + + */ +public class Wallop extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("blue or black creature with flying"); + + static { + filter.add(Predicates.or(new ColorPredicate(ObjectColor.BLUE), new ColorPredicate(ObjectColor.BLACK))); + filter.add(new AbilityPredicate(FlyingAbility.class)); + } + + public Wallop(UUID ownerId) { + super(ownerId, 223, "Wallop", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{1}{G}"); + this.expansionSetCode = "INV"; + + // Destroy target blue or black creature with flying. + this.getSpellAbility().addEffect(new DestroyTargetEffect()); + this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + } + + public Wallop(final Wallop card) { + super(card); + } + + @Override + public Wallop copy() { + return new Wallop(this); + } +} From d38910b81b7b9268148775f6845859a9b7bbef34 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Mon, 6 Jul 2015 16:49:24 +0200 Subject: [PATCH 081/105] * Liliana, Heretical Healer - Fixed that the Zombie token was not created if Liliana was exiled by her effect. --- .../magicorigins/LilianaHereticalHealer.java | 5 ++- .../abilities/keywords/TransformTest.java | 3 ++ ...ExileAndReturnTransformedSourceEffect.java | 43 ++++++++++++++----- 3 files changed, 40 insertions(+), 11 deletions(-) diff --git a/Mage.Sets/src/mage/sets/magicorigins/LilianaHereticalHealer.java b/Mage.Sets/src/mage/sets/magicorigins/LilianaHereticalHealer.java index 7d7a1ee93f1..a3a6bc156b0 100644 --- a/Mage.Sets/src/mage/sets/magicorigins/LilianaHereticalHealer.java +++ b/Mage.Sets/src/mage/sets/magicorigins/LilianaHereticalHealer.java @@ -30,6 +30,7 @@ package mage.sets.magicorigins; import java.util.UUID; import mage.MageInt; import mage.abilities.common.DiesCreatureTriggeredAbility; +import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.ExileAndReturnTransformedSourceEffect; import mage.abilities.keyword.LifelinkAbility; import mage.abilities.keyword.TransformAbility; @@ -42,6 +43,7 @@ import mage.filter.predicate.Predicates; import mage.filter.predicate.permanent.AnotherPredicate; import mage.filter.predicate.permanent.ControllerPredicate; import mage.filter.predicate.permanent.TokenPredicate; +import mage.game.permanent.token.ZombieToken; /** * @@ -74,7 +76,8 @@ public class LilianaHereticalHealer extends CardImpl { this.addAbility(LifelinkAbility.getInstance()); // Whenever another nontoken creature you control dies, exile Liliana Heretical Healer, then return her to the battlefield transformed under her owner's control. If you do, put a 2/2 black Zombie creature token onto the battlefield. - this.addAbility(new DiesCreatureTriggeredAbility(new ExileAndReturnTransformedSourceEffect(ExileAndReturnTransformedSourceEffect.Gender.FEMAL), false, filter)); + this.addAbility(new DiesCreatureTriggeredAbility(new ExileAndReturnTransformedSourceEffect(ExileAndReturnTransformedSourceEffect.Gender.FEMAL, + new CreateTokenEffect(new ZombieToken(expansionSetCode))), false, filter)); } public LilianaHereticalHealer(final LilianaHereticalHealer card) { diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/TransformTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/TransformTest.java index 8ed4b751656..eb3cf1762dc 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/TransformTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/TransformTest.java @@ -87,6 +87,9 @@ public class TransformTest extends CardTestPlayerBase { assertPermanentCount(playerA, "Liliana, Heretical Healer", 0); assertPermanentCount(playerA, "Liliana, Defiant Necromancer", 1); assertCounterCount("Liliana, Defiant Necromancer", CounterType.LOYALTY, 3); + + assertPermanentCount(playerA, "Zombie", 1); + } } diff --git a/Mage/src/mage/abilities/effects/common/ExileAndReturnTransformedSourceEffect.java b/Mage/src/mage/abilities/effects/common/ExileAndReturnTransformedSourceEffect.java index 3e6bd508bb4..7e328a9b8b1 100644 --- a/Mage/src/mage/abilities/effects/common/ExileAndReturnTransformedSourceEffect.java +++ b/Mage/src/mage/abilities/effects/common/ExileAndReturnTransformedSourceEffect.java @@ -7,6 +7,8 @@ package mage.abilities.effects.common; import mage.MageObject; import mage.abilities.Ability; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.abilities.keyword.TransformAbility; import mage.cards.Card; @@ -19,26 +21,40 @@ import mage.players.Player; * * @author LevelX2 */ - public class ExileAndReturnTransformedSourceEffect extends OneShotEffect { - - public static enum Gender { MALE, FEMAL }; - + + public static enum Gender { + + MALE, FEMAL + }; + + protected Effect additionalEffect; + public ExileAndReturnTransformedSourceEffect(Gender gender) { - super(Outcome.Benefit); - this.staticText = "exile {this}, then return " + (gender.equals(Gender.MALE) ? "him":"her") - + " to the battlefield transformed under" + (gender.equals(Gender.MALE) ? "his":"her")+ " owner's control"; + this(gender, null); } - + + /** + * @param gender + * @param additionalEffect that effect is applies as source is exiled + */ + public ExileAndReturnTransformedSourceEffect(Gender gender, Effect additionalEffect) { + super(Outcome.Benefit); + this.additionalEffect = additionalEffect; + this.staticText = "exile {this}, then return " + (gender.equals(Gender.MALE) ? "him" : "her") + + " to the battlefield transformed under" + (gender.equals(Gender.MALE) ? "his" : "her") + " owner's control"; + } + public ExileAndReturnTransformedSourceEffect(final ExileAndReturnTransformedSourceEffect effect) { super(effect); + this.additionalEffect = effect.additionalEffect; } - + @Override public ExileAndReturnTransformedSourceEffect copy() { return new ExileAndReturnTransformedSourceEffect(this); } - + @Override public boolean apply(Game game, Ability source) { MageObject sourceObject = source.getSourceObjectIfItStillExists(game); @@ -48,6 +64,13 @@ public class ExileAndReturnTransformedSourceEffect extends OneShotEffect { if (controller.moveCards(card, Zone.BATTLEFIELD, Zone.EXILED, source, game)) { game.getState().setValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + source.getSourceId(), Boolean.TRUE); controller.putOntoBattlefieldWithInfo(card, game, Zone.EXILED, source.getSourceId()); + if (additionalEffect != null) { + if (additionalEffect instanceof ContinuousEffect) { + game.addEffect((ContinuousEffect) additionalEffect, source); + } else { + additionalEffect.apply(game, source); + } + } } } return true; From 7bb93fbb25adaa1e5cae4c558305ff83697873ba Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Mon, 6 Jul 2015 17:23:47 +0200 Subject: [PATCH 082/105] * Willbreaker - Fixed that it didn't trigger when targeted by abilities. --- .../mage/sets/magicorigins/Willbreaker.java | 4 +- .../sets/newphyrexia/BlindingSouleater.java | 9 +-- .../cards/triggers/BecomesTheTargetTest.java | 71 +++++++++++++++++++ 3 files changed, 77 insertions(+), 7 deletions(-) create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/triggers/BecomesTheTargetTest.java diff --git a/Mage.Sets/src/mage/sets/magicorigins/Willbreaker.java b/Mage.Sets/src/mage/sets/magicorigins/Willbreaker.java index c6dcbe34c62..0480e397f3e 100644 --- a/Mage.Sets/src/mage/sets/magicorigins/Willbreaker.java +++ b/Mage.Sets/src/mage/sets/magicorigins/Willbreaker.java @@ -43,7 +43,6 @@ import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; import mage.game.permanent.Permanent; -import mage.game.stack.StackObject; import mage.players.Player; import mage.target.targetpointer.FixedTarget; @@ -96,8 +95,7 @@ class WillbreakerTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { if (getControllerId().equals(event.getPlayerId())) { Permanent permanent = game.getPermanent(event.getTargetId()); - if (permanent != null && permanent.getCardType().contains(CardType.CREATURE) - && StackObject.class.isInstance(game.getObject(event.getSourceId()))) { + if (permanent != null && permanent.getCardType().contains(CardType.CREATURE)) { Player controller = game.getPlayer(getControllerId()); if (controller != null && controller.hasOpponent(permanent.getControllerId(), game)) { getEffects().get(0).setTargetPointer(new FixedTarget(event.getTargetId())); diff --git a/Mage.Sets/src/mage/sets/newphyrexia/BlindingSouleater.java b/Mage.Sets/src/mage/sets/newphyrexia/BlindingSouleater.java index 34cd7866f8d..97edb201897 100644 --- a/Mage.Sets/src/mage/sets/newphyrexia/BlindingSouleater.java +++ b/Mage.Sets/src/mage/sets/newphyrexia/BlindingSouleater.java @@ -28,16 +28,16 @@ package mage.sets.newphyrexia; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.ColoredManaSymbol; -import mage.constants.Rarity; -import mage.constants.Zone; import mage.MageInt; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.PhyrexianManaCost; import mage.abilities.effects.common.TapTargetEffect; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.ColoredManaSymbol; +import mage.constants.Rarity; +import mage.constants.Zone; import mage.target.common.TargetCreaturePermanent; /** @@ -54,6 +54,7 @@ public class BlindingSouleater extends CardImpl { this.power = new MageInt(1); this.toughness = new MageInt(3); + // {WP},{T}: Tap target creature. ( can be paid with either or 2 life.) SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TapTargetEffect(), new PhyrexianManaCost(ColoredManaSymbol.W)); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/BecomesTheTargetTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/BecomesTheTargetTest.java new file mode 100644 index 00000000000..a6bb72f4050 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/BecomesTheTargetTest.java @@ -0,0 +1,71 @@ +/* + * 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 org.mage.test.cards.triggers; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ +public class BecomesTheTargetTest extends CardTestPlayerBase { + + /** + * Willbreaker is not working when an ability is targeting the opponet's + * creature. Only spells. + * + */ + @Test + public void testWillbreakerAbility() { + // Whenever a creature an opponent controls becomes the target of a spell or ability you control, gain control of that creature for as long as you control Willbreaker. + addCard(Zone.BATTLEFIELD, playerB, "Willbreaker", 1); + addCard(Zone.BATTLEFIELD, playerB, "Blinding Souleater", 1); + addCard(Zone.BATTLEFIELD, playerB, "Plains", 1); + + addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion", 1); + + activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerB, "{WP},{T}: Tap target creature", "Silvercoat Lion"); + + setStopAt(2, PhaseStep.BEGIN_COMBAT); + execute(); + + assertLife(playerA, 20); + assertLife(playerB, 20); + + assertPermanentCount(playerA, "Silvercoat Lion", 0); + assertTapped("Silvercoat Lion", true); + + assertPermanentCount(playerB, "Silvercoat Lion", 1); + assertPermanentCount(playerB, "Willbreaker", 1); + assertPermanentCount(playerB, "Blinding Souleater", 1); + + } +} From a834f9242c024287672871d99f24b55bc8f735ce Mon Sep 17 00:00:00 2001 From: fireshoes Date: Mon, 6 Jul 2015 12:30:39 -0500 Subject: [PATCH 083/105] [ORI] Fixed that Necromantic Summons only targeted the controller's graveyard. --- .../magicorigins/ChandraRoaringFlame.java | 289 +++++++++--------- .../sets/magicorigins/NecromanticSummons.java | 4 +- 2 files changed, 146 insertions(+), 147 deletions(-) diff --git a/Mage.Sets/src/mage/sets/magicorigins/ChandraRoaringFlame.java b/Mage.Sets/src/mage/sets/magicorigins/ChandraRoaringFlame.java index a12cfc19dd7..45882a2ddcf 100644 --- a/Mage.Sets/src/mage/sets/magicorigins/ChandraRoaringFlame.java +++ b/Mage.Sets/src/mage/sets/magicorigins/ChandraRoaringFlame.java @@ -1,146 +1,145 @@ -/* - * 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.magicorigins; - -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; -import mage.abilities.Ability; -import mage.abilities.LoyaltyAbility; -import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; -import mage.abilities.common.EntersBattlefieldAbility; -import mage.abilities.effects.Effect; -import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.DamageSelfEffect; -import mage.abilities.effects.common.DamageTargetEffect; -import mage.abilities.effects.common.counter.AddCountersSourceEffect; -import mage.cards.CardImpl; -import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.Rarity; -import mage.constants.TargetController; -import mage.constants.Zone; -import mage.counters.CounterType; -import mage.game.Game; -import mage.game.command.Emblem; -import mage.players.Player; -import mage.target.TargetPlayer; -import mage.target.common.TargetCreaturePermanent; - -/** - * - * @author LevelX2 - */ -public class ChandraRoaringFlame extends CardImpl { - - public ChandraRoaringFlame(UUID ownerId) { - super(ownerId, 135, "Chandra, Roaring Flame", Rarity.MYTHIC, new CardType[]{CardType.PLANESWALKER}, ""); - this.expansionSetCode = "ORI"; - this.subtype.add("Chandra"); - this.color.setRed(true); - - this.nightCard = true; - this.canTransform = true; - - this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.LOYALTY.createInstance(4)), false)); - - // +1: Chandra, Roaring Flame deals 2 damage to target player. - LoyaltyAbility loyaltyAbility = new LoyaltyAbility(new DamageTargetEffect(2), 1); - loyaltyAbility.addTarget(new TargetPlayer()); - this.addAbility(loyaltyAbility); - - //-2: Chandra, Roaring Flame deals 2 damage to target creature. - loyaltyAbility = new LoyaltyAbility(new DamageTargetEffect(2), -2); - loyaltyAbility.addTarget(new TargetCreaturePermanent()); - this.addAbility(loyaltyAbility); - - //-7: Chandra, Roaring Flame deals 6 damage to each opponent. Each player dealt damage this way gets an emblem with "At the beginning of your upkeep, this emblem deals 3 damage to you." - this.addAbility(new LoyaltyAbility(new ChandraRoaringFlameEmblemEffect(), -7)); - - - } - - public ChandraRoaringFlame(final ChandraRoaringFlame card) { - super(card); - } - - @Override - public ChandraRoaringFlame copy() { - return new ChandraRoaringFlame(this); - } -} - -class ChandraRoaringFlameEmblemEffect extends OneShotEffect { - - public ChandraRoaringFlameEmblemEffect() { - super(Outcome.Damage); - this.staticText = "{this} deals 6 damage to each opponent. Each player dealt damage this way gets an emblem with \"At the beginning of your upkeep, this emblem deals 3 damage to you.\""; - } - - public ChandraRoaringFlameEmblemEffect(final ChandraRoaringFlameEmblemEffect effect) { - super(effect); - } - - @Override - public ChandraRoaringFlameEmblemEffect copy() { - return new ChandraRoaringFlameEmblemEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - List opponentsEmblem = new ArrayList<>(); - for(UUID playerId: game.getOpponents(controller.getId())) { - Player opponent = game.getPlayer(playerId); - if (opponent != null) { - if (opponent.damage(6, source.getSourceId(), game, false, true) > 0) { - opponentsEmblem.add(opponent); - } - } - } - for (Player opponent : opponentsEmblem) { - game.addEmblem(new ChandraRoaringFlameEmblem(), source, opponent.getId()); - } - } - return false; - } -} - -/** - * Emblem with "At the beginning of your upkeep, this emblem deals 3 damage to you." - */ -class ChandraRoaringFlameEmblem extends Emblem { - - public ChandraRoaringFlameEmblem() { - setName("EMBLEM: Chandra, Roaring Flame"); - Effect effect = new DamageTargetEffect(3); - effect.setText("this emblem deals 3 damage to you"); - this.getAbilities().add(new BeginningOfUpkeepTriggeredAbility(Zone.COMMAND, effect, TargetController.YOU, false, true)); - } +/* + * 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.magicorigins; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.LoyaltyAbility; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.game.Game; +import mage.game.command.Emblem; +import mage.players.Player; +import mage.target.TargetPlayer; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LevelX2 + */ +public class ChandraRoaringFlame extends CardImpl { + + public ChandraRoaringFlame(UUID ownerId) { + super(ownerId, 135, "Chandra, Roaring Flame", Rarity.MYTHIC, new CardType[]{CardType.PLANESWALKER}, ""); + this.expansionSetCode = "ORI"; + this.subtype.add("Chandra"); + this.color.setRed(true); + + this.nightCard = true; + this.canTransform = true; + + this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.LOYALTY.createInstance(4)), false)); + + // +1: Chandra, Roaring Flame deals 2 damage to target player. + LoyaltyAbility loyaltyAbility = new LoyaltyAbility(new DamageTargetEffect(2), 1); + loyaltyAbility.addTarget(new TargetPlayer()); + this.addAbility(loyaltyAbility); + + //-2: Chandra, Roaring Flame deals 2 damage to target creature. + loyaltyAbility = new LoyaltyAbility(new DamageTargetEffect(2), -2); + loyaltyAbility.addTarget(new TargetCreaturePermanent()); + this.addAbility(loyaltyAbility); + + //-7: Chandra, Roaring Flame deals 6 damage to each opponent. Each player dealt damage this way gets an emblem with "At the beginning of your upkeep, this emblem deals 3 damage to you." + this.addAbility(new LoyaltyAbility(new ChandraRoaringFlameEmblemEffect(), -7)); + + + } + + public ChandraRoaringFlame(final ChandraRoaringFlame card) { + super(card); + } + + @Override + public ChandraRoaringFlame copy() { + return new ChandraRoaringFlame(this); + } +} + +class ChandraRoaringFlameEmblemEffect extends OneShotEffect { + + public ChandraRoaringFlameEmblemEffect() { + super(Outcome.Damage); + this.staticText = "{this} deals 6 damage to each opponent. Each player dealt damage this way gets an emblem with \"At the beginning of your upkeep, this emblem deals 3 damage to you.\""; + } + + public ChandraRoaringFlameEmblemEffect(final ChandraRoaringFlameEmblemEffect effect) { + super(effect); + } + + @Override + public ChandraRoaringFlameEmblemEffect copy() { + return new ChandraRoaringFlameEmblemEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + List opponentsEmblem = new ArrayList<>(); + for(UUID playerId: game.getOpponents(controller.getId())) { + Player opponent = game.getPlayer(playerId); + if (opponent != null) { + if (opponent.damage(6, source.getSourceId(), game, false, true) > 0) { + opponentsEmblem.add(opponent); + } + } + } + for (Player opponent : opponentsEmblem) { + game.addEmblem(new ChandraRoaringFlameEmblem(), source, opponent.getId()); + } + } + return false; + } +} + +/** + * Emblem with "At the beginning of your upkeep, this emblem deals 3 damage to you." + */ +class ChandraRoaringFlameEmblem extends Emblem { + + public ChandraRoaringFlameEmblem() { + setName("EMBLEM: Chandra, Roaring Flame"); + Effect effect = new DamageTargetEffect(3); + effect.setText("this emblem deals 3 damage to you"); + this.getAbilities().add(new BeginningOfUpkeepTriggeredAbility(Zone.COMMAND, effect, TargetController.YOU, false, true)); + } } \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/magicorigins/NecromanticSummons.java b/Mage.Sets/src/mage/sets/magicorigins/NecromanticSummons.java index 1028d2e87a3..b8bcb491aa1 100644 --- a/Mage.Sets/src/mage/sets/magicorigins/NecromanticSummons.java +++ b/Mage.Sets/src/mage/sets/magicorigins/NecromanticSummons.java @@ -42,7 +42,7 @@ import mage.counters.CounterType; import mage.filter.common.FilterCreatureCard; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.target.common.TargetCardInYourGraveyard; +import mage.target.common.TargetCardInGraveyard; /** * @@ -56,7 +56,7 @@ public class NecromanticSummons extends CardImpl { // Put target creature card from a graveyard onto the battlefield under your control. this.getSpellAbility().addEffect(new ReturnFromGraveyardToBattlefieldTargetEffect()); - this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(new FilterCreatureCard("creature card from your graveyard"))); + this.getSpellAbility().addTarget(new TargetCardInGraveyard(new FilterCreatureCard("creature card from a graveyard"))); // Spell mastery - If there are two or more instant and/or sorcery cards in your graveyard, that creature enters the battlefield with two additional +1/+1 counters on it. Effect effect = new ConditionalOneShotEffect(new NecromanticSummoningEffect(), From 7146b0b02759f8ed553a58dd1ffafadf2393b1e1 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Mon, 6 Jul 2015 19:49:13 +0200 Subject: [PATCH 084/105] * Fixed wrong text for becomes renown triggered effect. --- .../common/BecomesRenownSourceTriggeredAbility.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Mage/src/mage/abilities/common/BecomesRenownSourceTriggeredAbility.java b/Mage/src/mage/abilities/common/BecomesRenownSourceTriggeredAbility.java index 0864328cee7..44ae09a0f2b 100644 --- a/Mage/src/mage/abilities/common/BecomesRenownSourceTriggeredAbility.java +++ b/Mage/src/mage/abilities/common/BecomesRenownSourceTriggeredAbility.java @@ -15,7 +15,6 @@ import mage.game.events.GameEvent; * * @author LevelX2 */ - public class BecomesRenownSourceTriggeredAbility extends TriggeredAbilityImpl { private int renownValue; @@ -54,6 +53,6 @@ public class BecomesRenownSourceTriggeredAbility extends TriggeredAbilityImpl { @Override public String getRule() { - return "When {this} becomes monstrous, " + super.getRule(); + return "When {this} becomes renown, " + super.getRule(); } -} \ No newline at end of file +} From 6e5acee2dc1aca53d0985effeaa620349207c983 Mon Sep 17 00:00:00 2001 From: Wehk Date: Mon, 6 Jul 2015 21:53:22 +0200 Subject: [PATCH 085/105] Avatar test Testing access to a "normal" avatar that is not added to "available_avatars". Can't test name cases in local build. --- Mage.Server/src/main/java/mage/server/Session.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Mage.Server/src/main/java/mage/server/Session.java b/Mage.Server/src/main/java/mage/server/Session.java index 4d6368fae2e..c705ffd740a 100644 --- a/Mage.Server/src/main/java/mage/server/Session.java +++ b/Mage.Server/src/main/java/mage/server/Session.java @@ -181,6 +181,8 @@ public class Session { return 1018; case "Bandit": return 1020; + case "Wehk": + return 66; } return 51; } From 512ea669c2e7c707889feae8e2c89ecd3febc9e6 Mon Sep 17 00:00:00 2001 From: Wehk Date: Mon, 6 Jul 2015 23:24:50 +0200 Subject: [PATCH 086/105] Added card: Dryad's Caress --- .../src/mage/sets/ravnica/DryadsCaress.java | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/ravnica/DryadsCaress.java diff --git a/Mage.Sets/src/mage/sets/ravnica/DryadsCaress.java b/Mage.Sets/src/mage/sets/ravnica/DryadsCaress.java new file mode 100644 index 00000000000..0e7052ceda0 --- /dev/null +++ b/Mage.Sets/src/mage/sets/ravnica/DryadsCaress.java @@ -0,0 +1,74 @@ +/* + * 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.ravnica; + +import java.util.UUID; +import mage.abilities.condition.common.ManaWasSpentCondition; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.effects.common.UntapAllControllerEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.ColoredManaSymbol; +import mage.constants.Rarity; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.common.FilterCreaturePermanent; + +/** + * + * @author Wehk + */ +public class DryadsCaress extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature on the battlefield"); + private static final String rule = "untap all creatures you control"; + + public DryadsCaress(UUID ownerId) { + super(ownerId, 160, "Dryad's Caress", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{4}{G}{G}"); + this.expansionSetCode = "RAV"; + + // You gain 1 life for each creature on the battlefield. + + this.getSpellAbility().addEffect(new GainLifeEffect(new PermanentsOnBattlefieldCount(filter))); + + //If {W} was spent to cast Dryad's Caress, untap all creatures you control. + this.getSpellAbility().addEffect(new ConditionalOneShotEffect( + new UntapAllControllerEffect(new FilterControlledCreaturePermanent(), rule), + new ManaWasSpentCondition(ColoredManaSymbol.W), "If {W} was spent to cast {this}, untap all creatures you control")); + } + + public DryadsCaress(final DryadsCaress card) { + super(card); + } + + @Override + public DryadsCaress copy() { + return new DryadsCaress(this); + } +} From 5c3deaa13a4e0ee0ebf4d747fdab0916462b16c2 Mon Sep 17 00:00:00 2001 From: Wehk Date: Mon, 6 Jul 2015 23:25:16 +0200 Subject: [PATCH 087/105] Added card: Golgari Germination --- .../mage/sets/ravnica/GolgariGermination.java | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/ravnica/GolgariGermination.java diff --git a/Mage.Sets/src/mage/sets/ravnica/GolgariGermination.java b/Mage.Sets/src/mage/sets/ravnica/GolgariGermination.java new file mode 100644 index 00000000000..c4c3cde7ba2 --- /dev/null +++ b/Mage.Sets/src/mage/sets/ravnica/GolgariGermination.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.sets.ravnica; + +import java.util.UUID; +import mage.abilities.common.DiesCreatureTriggeredAbility; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.TargetController; +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.permanent.token.SaprolingToken; + +/** + * + * @author Wehk + */ +public class GolgariGermination 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 GolgariGermination(UUID ownerId) { + super(ownerId, 209, "Golgari Germination", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT}, "{1}{B}{G}"); + this.expansionSetCode = "RAV"; + + // Whenever a nontoken creature you control dies, put a 1/1 green Saproling creature token onto the battlefield. + this.addAbility(new DiesCreatureTriggeredAbility(new CreateTokenEffect(new SaprolingToken()), false, filter)); + } + + public GolgariGermination(final GolgariGermination card) { + super(card); + } + + @Override + public GolgariGermination copy() { + return new GolgariGermination(this); + } +} From 35b470d370c966fda0f6ed41273527d8202678ad Mon Sep 17 00:00:00 2001 From: Wehk Date: Mon, 6 Jul 2015 23:25:47 +0200 Subject: [PATCH 088/105] Added card: Stone-Seeder Hierophant --- .../sets/ravnica/StoneSeederHierophant.java | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/ravnica/StoneSeederHierophant.java diff --git a/Mage.Sets/src/mage/sets/ravnica/StoneSeederHierophant.java b/Mage.Sets/src/mage/sets/ravnica/StoneSeederHierophant.java new file mode 100644 index 00000000000..b6aeee6f40c --- /dev/null +++ b/Mage.Sets/src/mage/sets/ravnica/StoneSeederHierophant.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.ravnica; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.common.UntapSourceEffect; +import mage.abilities.effects.common.UntapTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterLandPermanent; +import mage.target.Target; +import mage.target.common.TargetLandPermanent; + +/** + * + * @author Wehk + */ +public class StoneSeederHierophant extends CardImpl { + + public StoneSeederHierophant(UUID ownerId) { + super(ownerId, 184, "Stone-Seeder Hierophant", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{2}{G}{G}"); + this.expansionSetCode = "RAV"; + this.subtype.add("Human"); + this.subtype.add("Druid"); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Whenever a land enters the battlefield under your control, untap Stone-Seeder Hierophant. + this.addAbility(new EntersBattlefieldAllTriggeredAbility(Zone.BATTLEFIELD, new UntapSourceEffect(), new FilterLandPermanent("a land"), false)); + + // {tap}: Untap target land. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new UntapTargetEffect(), new TapSourceCost()); + Target target = new TargetLandPermanent(); + ability.addTarget(target); + this.addAbility(ability); + } + + public StoneSeederHierophant(final StoneSeederHierophant card) { + super(card); + } + + @Override + public StoneSeederHierophant copy() { + return new StoneSeederHierophant(this); + } +} From 0173325a984d4a7a5b12bbf4742980c62c0be17c Mon Sep 17 00:00:00 2001 From: Wehk Date: Mon, 6 Jul 2015 23:26:11 +0200 Subject: [PATCH 089/105] Added card: Seed Spark --- .../src/mage/sets/ravnica/SeedSpark.java | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/ravnica/SeedSpark.java diff --git a/Mage.Sets/src/mage/sets/ravnica/SeedSpark.java b/Mage.Sets/src/mage/sets/ravnica/SeedSpark.java new file mode 100644 index 00000000000..0818865d24d --- /dev/null +++ b/Mage.Sets/src/mage/sets/ravnica/SeedSpark.java @@ -0,0 +1,71 @@ +/* + * 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.ravnica; + +import java.util.UUID; +import mage.abilities.condition.common.ManaWasSpentCondition; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.ColoredManaSymbol; +import mage.constants.Rarity; +import mage.filter.common.FilterArtifactOrEnchantmentPermanent; +import mage.game.permanent.token.SaprolingToken; +import mage.target.TargetPermanent; +import mage.abilities.effects.common.CreateTokenEffect; + +/** + * + * @author Wehk + */ +public class SeedSpark extends CardImpl { + + public SeedSpark(UUID ownerId) { + super(ownerId, 30, "Seed Spark", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{3}{W}"); + this.expansionSetCode = "RAV"; + + // Destroy target artifact or enchantment. + this.getSpellAbility().addTarget(new TargetPermanent(new FilterArtifactOrEnchantmentPermanent())); + this.getSpellAbility().addEffect(new DestroyTargetEffect()); + + //If {G} was spent to cast Seed Spark, put two 1/1 green Saproling creature tokens onto the battlefield. + this.getSpellAbility().addEffect(new ConditionalOneShotEffect( + new CreateTokenEffect(new SaprolingToken(), 2), + new ManaWasSpentCondition(ColoredManaSymbol.G), "If {G} was spent to cast {this}, put two 1/1 green Saproling creature tokens onto the battlefield")); + } + + public SeedSpark(final SeedSpark card) { + super(card); + } + + @Override + public SeedSpark copy() { + return new SeedSpark(this); + } +} From aca92886307b0b7e5c2284e034ca22160d284612 Mon Sep 17 00:00:00 2001 From: Wehk Date: Mon, 6 Jul 2015 23:26:47 +0200 Subject: [PATCH 090/105] Added card: Hour Of Reckoning --- .../mage/sets/ravnica/HourOfReckoning.java | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/ravnica/HourOfReckoning.java diff --git a/Mage.Sets/src/mage/sets/ravnica/HourOfReckoning.java b/Mage.Sets/src/mage/sets/ravnica/HourOfReckoning.java new file mode 100644 index 00000000000..523d5581683 --- /dev/null +++ b/Mage.Sets/src/mage/sets/ravnica/HourOfReckoning.java @@ -0,0 +1,73 @@ +/* + * 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.ravnica; + +import java.util.UUID; +import mage.ObjectColor; +import mage.abilities.effects.common.DestroyAllEffect; +import mage.abilities.keyword.ConvokeAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.ColorPredicate; +import mage.filter.predicate.permanent.TokenPredicate; + +/** + * + * @author Wehk + */ +public class HourOfReckoning extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nontoken creature"); + + static { + filter.add(Predicates.not(new TokenPredicate())); + } + + public HourOfReckoning(UUID ownerId) { + super(ownerId, 21, "Hour of Reckoning", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{4}{W}{W}{W}"); + this.expansionSetCode = "RAV"; + + // Convoke + this.addAbility(new ConvokeAbility()); + + // Destroy all nontoken creatures. + this.getSpellAbility().addEffect(new DestroyAllEffect(filter)); + } + + public HourOfReckoning(final HourOfReckoning card) { + super(card); + } + + @Override + public HourOfReckoning copy() { + return new HourOfReckoning(this); + } +} From 134809ea5ad9e8077fbdbc7e8dee8bbc9000b360 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Tue, 7 Jul 2015 00:29:56 +0200 Subject: [PATCH 091/105] * Dark Dabbling - Fixed the missing card draw effect. --- Mage.Sets/src/mage/sets/magicorigins/DarkDabbling.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Mage.Sets/src/mage/sets/magicorigins/DarkDabbling.java b/Mage.Sets/src/mage/sets/magicorigins/DarkDabbling.java index f8b734832f8..43b0d5783e5 100644 --- a/Mage.Sets/src/mage/sets/magicorigins/DarkDabbling.java +++ b/Mage.Sets/src/mage/sets/magicorigins/DarkDabbling.java @@ -31,6 +31,7 @@ import java.util.UUID; import mage.abilities.Ability; import mage.abilities.condition.common.SpellMasteryCondition; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.RegenerateTargetEffect; import mage.cards.CardImpl; import mage.constants.CardType; @@ -53,6 +54,7 @@ public class DarkDabbling extends CardImpl { // Regenerate target creature. Draw a card. this.getSpellAbility().addEffect(new RegenerateTargetEffect()); + this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1)); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); // Spell mastery — If there are two or more instant and/or sorcery cards in your graveyard, also regenerate each other creature you control. this.getSpellAbility().addEffect(new DarkDabblingEffect()); From 31c225373e34c51f302168343ecb0ef7ef66d4b0 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Tue, 7 Jul 2015 00:31:34 +0200 Subject: [PATCH 092/105] * Infectious Bloodlust - Fixed handling of attack requirement. --- .../mage/sets/magicorigins/InfectiousBloodlust.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Mage.Sets/src/mage/sets/magicorigins/InfectiousBloodlust.java b/Mage.Sets/src/mage/sets/magicorigins/InfectiousBloodlust.java index 56631e05d85..219311c74be 100644 --- a/Mage.Sets/src/mage/sets/magicorigins/InfectiousBloodlust.java +++ b/Mage.Sets/src/mage/sets/magicorigins/InfectiousBloodlust.java @@ -29,11 +29,11 @@ package mage.sets.magicorigins; import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.common.AttacksEachTurnStaticAbility; import mage.abilities.common.DiesAttachedTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.combat.AttacksIfAbleAttachedEffect; import mage.abilities.effects.common.continuous.BoostEnchantedEffect; import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect; @@ -42,6 +42,7 @@ import mage.abilities.keyword.HasteAbility; import mage.cards.CardImpl; import mage.constants.AttachmentType; import mage.constants.CardType; +import mage.constants.Duration; import mage.constants.Outcome; import mage.constants.Rarity; import mage.constants.Zone; @@ -56,7 +57,7 @@ import mage.target.common.TargetCreaturePermanent; * @author fireshoes */ public class InfectiousBloodlust extends CardImpl { - + private static final FilterCard filter = new FilterCard("card named Infectious Bloodlust"); static { @@ -74,7 +75,7 @@ public class InfectiousBloodlust extends CardImpl { this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); Ability ability = new EnchantAbility(auraTarget.getTargetName()); this.addAbility(ability); - + // Enchanted creature gets +2/+1, has haste, and attacks each turn if able. Effect effect = new BoostEnchantedEffect(2, 1); effect.setText("Enchanted creature gets +2/+1"); @@ -82,11 +83,12 @@ public class InfectiousBloodlust extends CardImpl { effect = new GainAbilityAttachedEffect(HasteAbility.getInstance(), AttachmentType.AURA); effect.setText("has haste"); ability.addEffect(effect); - effect = new GainAbilityAttachedEffect(new AttacksEachTurnStaticAbility(), AttachmentType.AURA); + ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEnchantedEffect(2, 2, Duration.WhileOnBattlefield)); + effect = new AttacksIfAbleAttachedEffect(Duration.WhileOnBattlefield, AttachmentType.AURA); effect.setText("and attacks each turn if able"); ability.addEffect(effect); this.addAbility(ability); - + // When enchanted creature dies, you may search your library for a card named Infectious Bloodlust, reveal it, put it into your hand, then shuffle your library. TargetCardInLibrary target = new TargetCardInLibrary(0, 1, filter); this.addAbility(new DiesAttachedTriggeredAbility(new SearchLibraryPutInHandEffect(target, true, true), "enchanted creature", true)); From 018478b3fbbd05372d6f9d323802c698f4ea4db4 Mon Sep 17 00:00:00 2001 From: fireshoes Date: Mon, 6 Jul 2015 18:59:40 -0500 Subject: [PATCH 093/105] [ORI] Fixed tooltip text for Undead Servant --- Mage.Sets/src/mage/sets/magicorigins/UndeadServant.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Mage.Sets/src/mage/sets/magicorigins/UndeadServant.java b/Mage.Sets/src/mage/sets/magicorigins/UndeadServant.java index d5cd57a2d0c..c550be4f66a 100644 --- a/Mage.Sets/src/mage/sets/magicorigins/UndeadServant.java +++ b/Mage.Sets/src/mage/sets/magicorigins/UndeadServant.java @@ -45,7 +45,8 @@ import mage.game.permanent.token.ZombieToken; */ public class UndeadServant extends CardImpl { - private static final FilterCard filter = new FilterCard(); + private static final FilterCard filter = new FilterCard(" card named Undead Servant"); + static { filter.add(new NamePredicate("Undead Servant")); } From 6e2b4793f86b6a5663d691b91ab746a246effd0c Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Tue, 7 Jul 2015 07:55:16 +0200 Subject: [PATCH 094/105] Fixed wrong type name in config.xml --- Mage.Server/release/config/config.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mage.Server/release/config/config.xml b/Mage.Server/release/config/config.xml index 37d72390fb8..c18cbdeb3af 100644 --- a/Mage.Server/release/config/config.xml +++ b/Mage.Server/release/config/config.xml @@ -37,7 +37,7 @@ - + From 381603666de92266ad9a7eb3b88d46ddc7e5c6e6 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Tue, 7 Jul 2015 07:55:31 +0200 Subject: [PATCH 095/105] Added test. --- .../test/combat/RemoveFromCombatTest.java | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 Mage.Tests/src/test/java/org/mage/test/combat/RemoveFromCombatTest.java diff --git a/Mage.Tests/src/test/java/org/mage/test/combat/RemoveFromCombatTest.java b/Mage.Tests/src/test/java/org/mage/test/combat/RemoveFromCombatTest.java new file mode 100644 index 00000000000..e77aa7428d7 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/combat/RemoveFromCombatTest.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 org.mage.test.combat; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ +public class RemoveFromCombatTest extends CardTestPlayerBase { + + /** + * In a test game against the AI, it attacked me with a Stomping Ground + * animated by an Ambush Commander and boosted it with the Commander's + * second ability. I killed the Commander. The now non-creature land + * continued attacking and dealt 3 damage to me. + */ + @Test + public void testLeavesCombatIfNoLongerACreature() { + addCard(Zone.BATTLEFIELD, playerA, "Mountain"); + addCard(Zone.HAND, playerB, "Lightning Bolt", 1); + + // Forests you control are 1/1 green Elf creatures that are still lands. + // {1}{G}, Sacrifice an Elf: Target creature gets +3/+3 until end of turn. + addCard(Zone.BATTLEFIELD, playerB, "Ambush Commander", 1); + addCard(Zone.BATTLEFIELD, playerB, "Stomping Ground"); + + attack(2, playerB, "Stomping Ground"); + castSpell(2, PhaseStep.DECLARE_BLOCKERS, playerA, "Lightning Bolt", "Ambush Commander"); + setStopAt(2, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertLife(playerA, 20); + assertLife(playerB, 20); + + assertGraveyardCount(playerA, "Lightning Bolt", 1); + assertGraveyardCount(playerB, "Ambush Commander", 1); + + assertPowerToughness(playerB, "Stomping Ground", 0, 0); + + } + +} From 1e5a8e2a571fb2e0b74b68039409f42a41b641bc Mon Sep 17 00:00:00 2001 From: LoneFox Date: Tue, 7 Jul 2015 12:04:03 +0300 Subject: [PATCH 096/105] Implement cards: Bog Down, Falling Timber, Magma Burst, and Pollen Remedy --- .../src/mage/sets/planeshift/BogDown.java | 71 +++++++++++++++ .../mage/sets/planeshift/FallingTimber.java | 84 ++++++++++++++++++ .../src/mage/sets/planeshift/MagmaBurst.java | 83 ++++++++++++++++++ .../mage/sets/planeshift/PollenRemedy.java | 86 +++++++++++++++++++ 4 files changed, 324 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/planeshift/BogDown.java create mode 100644 Mage.Sets/src/mage/sets/planeshift/FallingTimber.java create mode 100644 Mage.Sets/src/mage/sets/planeshift/MagmaBurst.java create mode 100644 Mage.Sets/src/mage/sets/planeshift/PollenRemedy.java diff --git a/Mage.Sets/src/mage/sets/planeshift/BogDown.java b/Mage.Sets/src/mage/sets/planeshift/BogDown.java new file mode 100644 index 00000000000..28601d9c185 --- /dev/null +++ b/Mage.Sets/src/mage/sets/planeshift/BogDown.java @@ -0,0 +1,71 @@ +/* + * 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.planeshift; + +import java.util.UUID; +import mage.abilities.condition.common.KickedCondition; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.common.discard.DiscardTargetEffect; +import mage.abilities.keyword.KickerAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.common.FilterControlledLandPermanent; +import mage.target.TargetPlayer; +import mage.target.common.TargetControlledPermanent; + +/** + * + * @author LoneFox + + */ +public class BogDown extends CardImpl { + + public BogDown(UUID ownerId) { + super(ownerId, 39, "Bog Down", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{2}{B}"); + this.expansionSetCode = "PLS"; + + // Kicker-Sacrifice two lands. + this.addAbility(new KickerAbility(new SacrificeTargetCost(new TargetControlledPermanent(2, 2, new FilterControlledLandPermanent("two lands"), true)))); + // Target player discards two cards. If Bog Down was kicked, that player discards three cards instead. + this.getSpellAbility().addEffect(new ConditionalOneShotEffect(new DiscardTargetEffect(3), + new DiscardTargetEffect(2), KickedCondition.getInstance(), + "Target player discards two cards. If {this} was kicked, that player discards three cards instead.")); + this.getSpellAbility().addTarget(new TargetPlayer()); + } + + public BogDown(final BogDown card) { + super(card); + } + + @Override + public BogDown copy() { + return new BogDown(this); + } +} diff --git a/Mage.Sets/src/mage/sets/planeshift/FallingTimber.java b/Mage.Sets/src/mage/sets/planeshift/FallingTimber.java new file mode 100644 index 00000000000..d20cf266577 --- /dev/null +++ b/Mage.Sets/src/mage/sets/planeshift/FallingTimber.java @@ -0,0 +1,84 @@ +/* + * 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.planeshift; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.condition.common.KickedCondition; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.PreventDamageByTargetEffect; +import mage.abilities.keyword.KickerAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.filter.common.FilterControlledLandPermanent; +import mage.game.Game; +import mage.target.common.TargetControlledPermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LoneFox + + */ +public class FallingTimber extends CardImpl { + + private final UUID originalId; + + public FallingTimber(UUID ownerId) { + super(ownerId, 79, "Falling Timber", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{2}{G}"); + this.expansionSetCode = "PLS"; + + // Kicker-Sacrifice a land. + this.addAbility(new KickerAbility(new SacrificeTargetCost(new TargetControlledPermanent(1, 1, new FilterControlledLandPermanent("a land"), true)))); + // Prevent all combat damage target creature would deal this turn. If Falling Timber was kicked, prevent all combat damage another target creature would deal this turn. + Effect effect = new PreventDamageByTargetEffect(Duration.EndOfTurn, true); + effect.setText("Prevent all combat damage target creature would deal this turn. If {this} was kicked, prevent all combat damage another target creature would deal this turn."); + this.getSpellAbility().addEffect(effect); + originalId = this.getSpellAbility().getOriginalId(); + } + + @Override + public void adjustTargets(Ability ability, Game game) { + if(ability.getOriginalId().equals(originalId)) { + ability.addTarget(new TargetCreaturePermanent(KickedCondition.getInstance().apply(game, ability) ? 2 : 1)); + } + } + + public FallingTimber(final FallingTimber card) { + super(card); + this.originalId = card.originalId; + } + + @Override + public FallingTimber copy() { + return new FallingTimber(this); + } +} diff --git a/Mage.Sets/src/mage/sets/planeshift/MagmaBurst.java b/Mage.Sets/src/mage/sets/planeshift/MagmaBurst.java new file mode 100644 index 00000000000..868c160b9d8 --- /dev/null +++ b/Mage.Sets/src/mage/sets/planeshift/MagmaBurst.java @@ -0,0 +1,83 @@ +/* + * 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.planeshift; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.condition.common.KickedCondition; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.keyword.KickerAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.common.FilterControlledLandPermanent; +import mage.game.Game; +import mage.target.common.TargetControlledPermanent; +import mage.target.common.TargetCreatureOrPlayer; + +/** + * + * @author LoneFox + + */ +public class MagmaBurst extends CardImpl { + + private final UUID originalId; + + public MagmaBurst(UUID ownerId) { + super(ownerId, 66, "Magma Burst", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{3}{R}"); + this.expansionSetCode = "PLS"; + + // Kicker-Sacrifice two lands. + this.addAbility(new KickerAbility(new SacrificeTargetCost(new TargetControlledPermanent(2, 2, new FilterControlledLandPermanent("two lands"), true)))); + // Magma Burst deals 3 damage to target creature or player. If Magma Burst was kicked, it deals 3 damage to another target creature or player. + Effect effect = new DamageTargetEffect(3); + effect.setText("{this} deals 3 damage to target creature or player. If {this} was kicked, it deals 3 damage to another target creature or player."); + this.getSpellAbility().addEffect(effect); + originalId = this.getSpellAbility().getOriginalId(); + } + + @Override + public void adjustTargets(Ability ability, Game game) { + if(ability.getOriginalId().equals(originalId)) { + ability.addTarget(new TargetCreatureOrPlayer(KickedCondition.getInstance().apply(game, ability) ? 2 : 1)); + } + } + + public MagmaBurst(final MagmaBurst card) { + super(card); + this.originalId = card.originalId; + } + + @Override + public MagmaBurst copy() { + return new MagmaBurst(this); + } +} diff --git a/Mage.Sets/src/mage/sets/planeshift/PollenRemedy.java b/Mage.Sets/src/mage/sets/planeshift/PollenRemedy.java new file mode 100644 index 00000000000..7e3d7d8b1b7 --- /dev/null +++ b/Mage.Sets/src/mage/sets/planeshift/PollenRemedy.java @@ -0,0 +1,86 @@ +/* + * 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.planeshift; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.condition.common.KickedCondition; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.decorator.ConditionalReplacementEffect; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.PreventDamageToTargetMultiAmountEffect; +import mage.abilities.keyword.KickerAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.filter.common.FilterControlledLandPermanent; +import mage.game.Game; +import mage.target.common.TargetCreatureOrPlayerAmount; +import mage.target.common.TargetControlledPermanent; + +/** + * + * @author LoneFox + + */ +public class PollenRemedy extends CardImpl { + + private final UUID originalId; + + public PollenRemedy(UUID ownerId) { + super(ownerId, 13, "Pollen Remedy", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{W}"); + this.expansionSetCode = "PLS"; + + // Kicker-Sacrifice a land. + this.addAbility(new KickerAbility(new SacrificeTargetCost(new TargetControlledPermanent(1, 1, new FilterControlledLandPermanent("a land"), true)))); + // Prevent the next 3 damage that would be dealt this turn to any number of target creatures and/or players, divided as you choose. If Pollen Remedy was kicked, prevent the next 6 damage this way instead. + Effect effect = new ConditionalReplacementEffect(new PreventDamageToTargetMultiAmountEffect(Duration.EndOfTurn, 6), + KickedCondition.getInstance(), new PreventDamageToTargetMultiAmountEffect(Duration.EndOfTurn, 3)); + effect.setText("Prevent the next 3 damage that would be dealt this turn to any number of target creatures and/or players, divided as you choose. If {this} was kicked, prevent the next 6 damage this way instead."); + this.getSpellAbility().addEffect(effect); + originalId = this.getSpellAbility().getOriginalId(); + } + + @Override + public void adjustTargets(Ability ability, Game game) { + if(ability.getOriginalId().equals(originalId)) { + ability.addTarget(new TargetCreatureOrPlayerAmount(KickedCondition.getInstance().apply(game, ability) ? 6 : 3)); + } + } + + public PollenRemedy(final PollenRemedy card) { + super(card); + this.originalId = card.originalId; + } + + @Override + public PollenRemedy copy() { + return new PollenRemedy(this); + } +} From 859bfd9bf376d91fd9c01ff697c51e609f23c007 Mon Sep 17 00:00:00 2001 From: LoneFox Date: Tue, 7 Jul 2015 12:34:50 +0300 Subject: [PATCH 097/105] Fix wrong source of damage for Chandra's Ignition --- .../src/mage/sets/magicorigins/ChandrasIgnition.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Mage.Sets/src/mage/sets/magicorigins/ChandrasIgnition.java b/Mage.Sets/src/mage/sets/magicorigins/ChandrasIgnition.java index b6c28101735..8fc0e942883 100644 --- a/Mage.Sets/src/mage/sets/magicorigins/ChandrasIgnition.java +++ b/Mage.Sets/src/mage/sets/magicorigins/ChandrasIgnition.java @@ -66,34 +66,34 @@ public class ChandrasIgnition extends CardImpl { } class ChandrasIgnitionEffect extends OneShotEffect { - + public ChandrasIgnitionEffect() { super(Outcome.Benefit); this.staticText = "Target creature you control deals damage equal to its power to each other creature and each opponent"; } - + public ChandrasIgnitionEffect(final ChandrasIgnitionEffect effect) { super(effect); } - + @Override public ChandrasIgnitionEffect copy() { return new ChandrasIgnitionEffect(this); } - + @Override public boolean apply(Game game, Ability source) { Permanent targetCreature = game.getPermanent(getTargetPointer().getFirst(game, source)); if (targetCreature != null && targetCreature.getPower().getValue() > 0) { for (Permanent creature : game.getState().getBattlefield().getActivePermanents(new FilterCreaturePermanent(), source.getControllerId(), source.getSourceId(), game)) { if (!creature.getId().equals(targetCreature.getId())) { - creature.damage(targetCreature.getPower().getValue(), source.getSourceId(), game, false, true); + creature.damage(targetCreature.getPower().getValue(), targetCreature.getId(), game, false, true); } } for(UUID opponentId : game.getOpponents(source.getControllerId())) { Player opponent = game.getPlayer(opponentId); if (opponent != null) { - opponent.damage(targetCreature.getPower().getValue(), source.getSourceId(), game, false, true); + opponent.damage(targetCreature.getPower().getValue(), targetCreature.getId(), game, false, true); } } } From d7eed8934eb141af4f9c164b65f6d08dc022fc2e Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Tue, 7 Jul 2015 11:58:31 +0200 Subject: [PATCH 098/105] * Dark Dabbling - Fixed wrong regenerate handling. --- Mage.Sets/src/mage/sets/magicorigins/DarkDabbling.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Mage.Sets/src/mage/sets/magicorigins/DarkDabbling.java b/Mage.Sets/src/mage/sets/magicorigins/DarkDabbling.java index 43b0d5783e5..26e92e1593a 100644 --- a/Mage.Sets/src/mage/sets/magicorigins/DarkDabbling.java +++ b/Mage.Sets/src/mage/sets/magicorigins/DarkDabbling.java @@ -41,6 +41,7 @@ import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetpointer.FixedTarget; /** * @@ -91,7 +92,9 @@ class DarkDabblingEffect extends OneShotEffect { if (SpellMasteryCondition.getInstance().apply(game, source)) { for (Permanent permanent : game.getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), source.getControllerId(), game)) { if (!permanent.getId().equals(getTargetPointer().getFirst(game, source))) { - permanent.regenerate(source.getSourceId(), game); + RegenerateTargetEffect regenEffect = new RegenerateTargetEffect(); + regenEffect.setTargetPointer(new FixedTarget(permanent.getId())); + game.addEffect(regenEffect, source); } } } From c1afa574851559c1e191f96fd672af24e43fc75c Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Tue, 7 Jul 2015 12:08:20 +0200 Subject: [PATCH 099/105] * Renown - Fixed name of active status to be renowned. --- .../src/mage/sets/magicorigins/RelicSeeker.java | 4 ++-- .../src/mage/sets/magicorigins/ValeronWardens.java | 2 +- ... => BecomesRenownedSourceTriggeredAbility.java} | 14 +++++++------- .../effects/common/RegenerateAllEffect.java | 8 +++----- Mage/src/mage/abilities/keyword/RenownAbility.java | 2 +- Mage/src/mage/game/events/GameEvent.java | 3 ++- 6 files changed, 16 insertions(+), 17 deletions(-) rename Mage/src/mage/abilities/common/{BecomesRenownSourceTriggeredAbility.java => BecomesRenownedSourceTriggeredAbility.java} (68%) diff --git a/Mage.Sets/src/mage/sets/magicorigins/RelicSeeker.java b/Mage.Sets/src/mage/sets/magicorigins/RelicSeeker.java index c4411ca92a7..cfb3c63e723 100644 --- a/Mage.Sets/src/mage/sets/magicorigins/RelicSeeker.java +++ b/Mage.Sets/src/mage/sets/magicorigins/RelicSeeker.java @@ -29,7 +29,7 @@ package mage.sets.magicorigins; import java.util.UUID; import mage.MageInt; -import mage.abilities.common.BecomesRenownSourceTriggeredAbility; +import mage.abilities.common.BecomesRenownedSourceTriggeredAbility; import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect; import mage.abilities.keyword.RenownAbility; import mage.cards.CardImpl; @@ -66,7 +66,7 @@ public class RelicSeeker extends CardImpl { // When Relic Seeker becomes renowned, you may search your library for an Equipment card, reveal it, put it into your hand, then shuffle your library. TargetCardInLibrary target = new TargetCardInLibrary(1, 1, filter); - this.addAbility(new BecomesRenownSourceTriggeredAbility(new SearchLibraryPutInHandEffect(target, true, true), true)); + this.addAbility(new BecomesRenownedSourceTriggeredAbility(new SearchLibraryPutInHandEffect(target, true, true), true)); } diff --git a/Mage.Sets/src/mage/sets/magicorigins/ValeronWardens.java b/Mage.Sets/src/mage/sets/magicorigins/ValeronWardens.java index 2237ba37683..4a180fd386c 100644 --- a/Mage.Sets/src/mage/sets/magicorigins/ValeronWardens.java +++ b/Mage.Sets/src/mage/sets/magicorigins/ValeronWardens.java @@ -89,7 +89,7 @@ class ValeronWardensTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkEventType(GameEvent event, Game game) { - return event.getType().equals(EventType.BECOMES_RENOWN); + return event.getType().equals(EventType.BECOMES_RENOWNED); } @Override diff --git a/Mage/src/mage/abilities/common/BecomesRenownSourceTriggeredAbility.java b/Mage/src/mage/abilities/common/BecomesRenownedSourceTriggeredAbility.java similarity index 68% rename from Mage/src/mage/abilities/common/BecomesRenownSourceTriggeredAbility.java rename to Mage/src/mage/abilities/common/BecomesRenownedSourceTriggeredAbility.java index 44ae09a0f2b..290215f9239 100644 --- a/Mage/src/mage/abilities/common/BecomesRenownSourceTriggeredAbility.java +++ b/Mage/src/mage/abilities/common/BecomesRenownedSourceTriggeredAbility.java @@ -15,27 +15,27 @@ import mage.game.events.GameEvent; * * @author LevelX2 */ -public class BecomesRenownSourceTriggeredAbility extends TriggeredAbilityImpl { +public class BecomesRenownedSourceTriggeredAbility extends TriggeredAbilityImpl { private int renownValue; - public BecomesRenownSourceTriggeredAbility(Effect effect, boolean optional) { + public BecomesRenownedSourceTriggeredAbility(Effect effect, boolean optional) { super(Zone.BATTLEFIELD, effect, optional); } - public BecomesRenownSourceTriggeredAbility(final BecomesRenownSourceTriggeredAbility ability) { + public BecomesRenownedSourceTriggeredAbility(final BecomesRenownedSourceTriggeredAbility ability) { super(ability); this.renownValue = ability.renownValue; } @Override - public BecomesRenownSourceTriggeredAbility copy() { - return new BecomesRenownSourceTriggeredAbility(this); + public BecomesRenownedSourceTriggeredAbility copy() { + return new BecomesRenownedSourceTriggeredAbility(this); } @Override public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.BECOMES_RENOWN; + return event.getType() == GameEvent.EventType.BECOMES_RENOWNED; } @Override @@ -53,6 +53,6 @@ public class BecomesRenownSourceTriggeredAbility extends TriggeredAbilityImpl { @Override public String getRule() { - return "When {this} becomes renown, " + super.getRule(); + return "When {this} becomes renowned, " + super.getRule(); } } diff --git a/Mage/src/mage/abilities/effects/common/RegenerateAllEffect.java b/Mage/src/mage/abilities/effects/common/RegenerateAllEffect.java index fd53bae45be..c23b072fbf3 100644 --- a/Mage/src/mage/abilities/effects/common/RegenerateAllEffect.java +++ b/Mage/src/mage/abilities/effects/common/RegenerateAllEffect.java @@ -25,12 +25,11 @@ * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package mage.abilities.effects.common; -import mage.constants.Outcome; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; +import mage.constants.Outcome; import mage.filter.FilterPermanent; import mage.game.Game; import mage.game.permanent.Permanent; @@ -40,10 +39,9 @@ import mage.target.targetpointer.FixedTarget; * * @author LevelX2 */ +public class RegenerateAllEffect extends OneShotEffect { - public class RegenerateAllEffect extends OneShotEffect { - - private FilterPermanent filter; + private final FilterPermanent filter; public RegenerateAllEffect(FilterPermanent filter) { super(Outcome.DestroyPermanent); diff --git a/Mage/src/mage/abilities/keyword/RenownAbility.java b/Mage/src/mage/abilities/keyword/RenownAbility.java index 96a8b1e8e75..f136de8ca96 100644 --- a/Mage/src/mage/abilities/keyword/RenownAbility.java +++ b/Mage/src/mage/abilities/keyword/RenownAbility.java @@ -91,7 +91,7 @@ class BecomeRenownSourceEffect extends OneShotEffect { } new AddCountersSourceEffect(CounterType.P1P1.createInstance(renownValue), true).apply(game, source); permanent.setRenown(true); - game.fireEvent(GameEvent.getEvent(GameEvent.EventType.BECOMES_RENOWN, source.getSourceId(), source.getSourceId(), source.getControllerId(), renownValue)); + game.fireEvent(GameEvent.getEvent(GameEvent.EventType.BECOMES_RENOWNED, source.getSourceId(), source.getSourceId(), source.getControllerId(), renownValue)); return true; } return false; diff --git a/Mage/src/mage/game/events/GameEvent.java b/Mage/src/mage/game/events/GameEvent.java index 10ccca9d241..433ad158c39 100644 --- a/Mage/src/mage/game/events/GameEvent.java +++ b/Mage/src/mage/game/events/GameEvent.java @@ -51,6 +51,7 @@ public class GameEvent implements Serializable { public enum EventType { //Game events +//Game events BEGINNING, PREVENT_DAMAGE, PREVENTED_DAMAGE, //Turn-based events @@ -173,7 +174,7 @@ public class GameEvent implements Serializable { UNFLIP, UNFLIPPED, TRANSFORM, TRANSFORMED, BECOMES_MONSTROUS, - BECOMES_RENOWN, + BECOMES_RENOWNED, PHASE_OUT, PHASED_OUT, PHASE_IN, PHASED_IN, TURNFACEUP, TURNEDFACEUP, From 11d6d5afb7b6c880be05a65960cff04e9e6d354c Mon Sep 17 00:00:00 2001 From: LoneFox Date: Tue, 7 Jul 2015 13:08:20 +0300 Subject: [PATCH 100/105] Fix the indestructibility condition of Erebos's Titan --- Mage.Sets/src/mage/sets/magicorigins/ErebossTitan.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mage.Sets/src/mage/sets/magicorigins/ErebossTitan.java b/Mage.Sets/src/mage/sets/magicorigins/ErebossTitan.java index cb87647fbf0..a8b4940e0af 100644 --- a/Mage.Sets/src/mage/sets/magicorigins/ErebossTitan.java +++ b/Mage.Sets/src/mage/sets/magicorigins/ErebossTitan.java @@ -74,7 +74,7 @@ public class ErebossTitan extends CardImpl { // Erebos's Titan has indestructible as long as no opponent controls a creature. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(new GainAbilitySourceEffect(IndestructibleAbility.getInstance(), Duration.WhileOnBattlefield), - new PermanentsOnTheBattlefieldCondition(filter, PermanentsOnTheBattlefieldCondition.CountType.MORE_THAN, 0), + new PermanentsOnTheBattlefieldCondition(filter, PermanentsOnTheBattlefieldCondition.CountType.EQUAL_TO, 0, false), "As long as your opponents control no creatures, {this} has indestructible"))); // Whenever a creature leaves an opponent's graveyard, you may discard a card. If you do, return Erebos's Titan from your graveyard to your hand. From 6f9317246bf7c8b698ea9ef346f259e501aab9bd Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Tue, 7 Jul 2015 12:10:02 +0200 Subject: [PATCH 101/105] * Renown - Fixed name of active status to be renowned. --- Mage/src/mage/abilities/keyword/RenownAbility.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mage/src/mage/abilities/keyword/RenownAbility.java b/Mage/src/mage/abilities/keyword/RenownAbility.java index f136de8ca96..81fac74c52f 100644 --- a/Mage/src/mage/abilities/keyword/RenownAbility.java +++ b/Mage/src/mage/abilities/keyword/RenownAbility.java @@ -83,7 +83,7 @@ class BecomeRenownSourceEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent != null && source instanceof RenownAbility) { - game.informPlayers(permanent.getLogName() + " is now renown"); + game.informPlayers(permanent.getLogName() + " is now renowned"); int renownValue = ((RenownAbility) source).getRenownValue(); // handle renown = X if (renownValue == Integer.MAX_VALUE) { From de47259a4996838770cb6b2b95df8941bc23afbe Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Tue, 7 Jul 2015 15:55:37 +0200 Subject: [PATCH 102/105] * Fixed that end turn effects (e.g. Day's Undoing) did not remove triggered abilities waiting to go onto the stack. --- .../mage/sets/magicorigins/UndeadServant.java | 6 +- .../abilities/other/EndTurnEffectTest.java | 74 ++++++++++ .../effects/common/EndTurnEffect.java | 7 +- Mage/src/mage/game/GameState.java | 7 + Mage/src/mage/game/turn/Turn.java | 130 +++++++++--------- 5 files changed, 151 insertions(+), 73 deletions(-) create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/EndTurnEffectTest.java diff --git a/Mage.Sets/src/mage/sets/magicorigins/UndeadServant.java b/Mage.Sets/src/mage/sets/magicorigins/UndeadServant.java index c550be4f66a..de8bbce4967 100644 --- a/Mage.Sets/src/mage/sets/magicorigins/UndeadServant.java +++ b/Mage.Sets/src/mage/sets/magicorigins/UndeadServant.java @@ -44,9 +44,9 @@ import mage.game.permanent.token.ZombieToken; * @author fireshoes */ public class UndeadServant extends CardImpl { - - private static final FilterCard filter = new FilterCard(" card named Undead Servant"); - + + private static final FilterCard filter = new FilterCard("card named Undead Servant"); + static { filter.add(new NamePredicate("Undead Servant")); } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/EndTurnEffectTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/EndTurnEffectTest.java new file mode 100644 index 00000000000..6f6eca531c9 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/EndTurnEffectTest.java @@ -0,0 +1,74 @@ +/* + * 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 org.mage.test.cards.abilities.other; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ +public class EndTurnEffectTest extends CardTestPlayerBase { + + /** + * Additional bug: Days Undoing and Sphinx's Tutelage are broken. You + * shouldn't get triggers off of Tutelage, since the turn ends, but it has + * you resolve them in your cleanup step. + * + * http://tabakrules.tumblr.com/post/122350751009/days-undoing-has-been-officially-spoiled-on + * + */ + @Test + public void testSpellsAffinity() { + addCard(Zone.BATTLEFIELD, playerA, "Island", 3); + + // Whenever you draw a card, target opponent puts the top two cards of his or her library into his or her graveyard. If they're both nonland cards that share a color, repeat this process. + // {5}{U}: Draw a card, then discard a card. + addCard(Zone.BATTLEFIELD, playerA, "Sphinx's Tutelage"); + + // Each player shuffles his or her hand and graveyard into his or her library, then draws seven cards. If it's your turn, end the turn. + addCard(Zone.HAND, playerA, "Day's Undoing"); //Sorcery {2}{U} + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Day's Undoing"); + + setStopAt(2, PhaseStep.UPKEEP); + execute(); + + assertExileCount("Day's Undoing", 1); + + assertHandCount(playerA, 7); + assertHandCount(playerB, 7); + + assertGraveyardCount(playerB, 0); // because the trigegrs of Sphinx's Tutelage cease to exist + + } + +} diff --git a/Mage/src/mage/abilities/effects/common/EndTurnEffect.java b/Mage/src/mage/abilities/effects/common/EndTurnEffect.java index 287e6b6b4e4..2a5608c0f73 100644 --- a/Mage/src/mage/abilities/effects/common/EndTurnEffect.java +++ b/Mage/src/mage/abilities/effects/common/EndTurnEffect.java @@ -25,12 +25,11 @@ * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package mage.abilities.effects.common; -import mage.constants.Outcome; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; +import mage.constants.Outcome; import mage.game.Game; public class EndTurnEffect extends OneShotEffect { @@ -46,8 +45,9 @@ public class EndTurnEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - if (!game.isSimulation()) + if (!game.isSimulation()) { game.informPlayers("The current turn ends"); + } return game.endTurn(); } @@ -56,4 +56,3 @@ public class EndTurnEffect extends OneShotEffect { return new EndTurnEffect(this); } } - diff --git a/Mage/src/mage/game/GameState.java b/Mage/src/mage/game/GameState.java index cdfdd6ccc90..d33aac385a0 100644 --- a/Mage/src/mage/game/GameState.java +++ b/Mage/src/mage/game/GameState.java @@ -757,6 +757,13 @@ public class GameState implements Serializable, Copyable { } } + /** + * Removes all waiting triggers (needed for turn end effects) + */ + public void clearTriggeredAbilities() { + this.triggered.clear(); + } + public void addTriggeredAbility(TriggeredAbility ability) { this.triggered.add(ability); } diff --git a/Mage/src/mage/game/turn/Turn.java b/Mage/src/mage/game/turn/Turn.java index c781a711d2d..ec5d2f81ca1 100644 --- a/Mage/src/mage/game/turn/Turn.java +++ b/Mage/src/mage/game/turn/Turn.java @@ -1,31 +1,30 @@ /* -* 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. -*/ - + * 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.game.turn; import java.io.Serializable; @@ -56,7 +55,7 @@ public class Turn implements Serializable { private final List phases = new ArrayList<>(); private boolean declareAttackersStepStarted = false; private boolean endTurn; // indicates that an end turn effect has resolved. - + public Turn() { endTurn = false; phases.add(new BeginningPhase()); @@ -71,7 +70,7 @@ public class Turn implements Serializable { this.currentPhase = turn.currentPhase.copy(); } this.activePlayerId = turn.activePlayerId; - for (Phase phase: turn.phases) { + for (Phase phase : turn.phases) { this.phases.add(phase.copy()); } this.declareAttackersStepStarted = turn.declareAttackersStepStarted; @@ -91,7 +90,7 @@ public class Turn implements Serializable { } public Phase getPhase(TurnPhase turnPhase) { - for (Phase phase: phases) { + for (Phase phase : phases) { if (phase.getType() == turnPhase) { return phase; } @@ -133,7 +132,7 @@ public class Turn implements Serializable { this.activePlayerId = activePlayer.getId(); resetCounts(); game.getPlayer(activePlayer.getId()).beginTurn(game); - for (Phase phase: phases) { + for (Phase phase : phases) { if (game.isPaused() || game.gameOver(null)) { return; } @@ -142,11 +141,11 @@ public class Turn implements Serializable { game.fireEvent(new GameEvent(GameEvent.EventType.PHASE_CHANGED, activePlayer.getId(), null, activePlayer.getId())); if (!game.getState().getTurnMods().skipPhase(activePlayer.getId(), currentPhase.getType())) { if (phase.play(game, activePlayer.getId())) { - if(game.executingRollback()) { + if (game.executingRollback()) { return; } //20091005 - 500.4/703.4n - game.emptyManaPools(); + game.emptyManaPools(); game.saveState(false); //20091005 - 500.8 @@ -208,7 +207,7 @@ public class Turn implements Serializable { } private void resetCounts() { - for (Phase phase: phases) { + for (Phase phase : phases) { phase.resetCount(); } } @@ -223,7 +222,7 @@ public class Turn implements Serializable { return false; } Phase phase; - switch(extraPhase) { + switch (extraPhase) { case BEGINNING: phase = new BeginningPhase(); break; @@ -251,52 +250,51 @@ public class Turn implements Serializable { } /*protected void playExtraTurns(Game game) { - while (game.getState().getTurnMods().extraTurn(activePlayerId)) { - this.play(game, activePlayerId); - } - }*/ -/** - * Used for some spells with end turn effect (e.g. Time Stop). - * - * @param game - * @param activePlayerId - */ + while (game.getState().getTurnMods().extraTurn(activePlayerId)) { + this.play(game, activePlayerId); + } + }*/ + /** + * Used for some spells with end turn effect (e.g. Time Stop). + * + * @param game + * @param activePlayerId + */ public void endTurn(Game game, UUID activePlayerId) { - // Ending the turn this way (Time Stop) means the following things happen in order: - + // Ending the turn this way (Time Stop) means the following things happen in order: + setEndTurnRequested(true); - - // 1) All spells and abilities on the stack are exiled. This includes Time Stop, though it will continue to resolve. - // It also includes spells and abilities that can't be countered. + + // 1) All spells and abilities on the stack are exiled. This includes Time Stop, though it will continue to resolve. + // It also includes spells and abilities that can't be countered. while (!game.getStack().isEmpty()) { StackObject stackObject = game.getStack().removeLast(); if (stackObject instanceof Spell) { ((Spell) stackObject).moveToExile(null, "", null, game); } } - // 2) All attacking and blocking creatures are removed from combat. - for (UUID attackerId: game.getCombat().getAttackers()) { + // 2) All attacking and blocking creatures are removed from combat. + for (UUID attackerId : game.getCombat().getAttackers()) { Permanent permanent = game.getPermanent(attackerId); if (permanent != null) { permanent.removeFromCombat(game); } game.getCombat().removeAttacker(attackerId, game); } - for (UUID blockerId: game.getCombat().getBlockers()) { + for (UUID blockerId : game.getCombat().getBlockers()) { Permanent permanent = game.getPermanent(blockerId); if (permanent != null) { permanent.removeFromCombat(game); } } - - // 3) State-based actions are checked. No player gets priority, and no triggered abilities are put onto the stack. - + // 3) State-based actions are checked. No player gets priority, and no triggered abilities are put onto the stack. + // seems like trigger events have to be removed: http://tabakrules.tumblr.com/post/122350751009/days-undoing-has-been-officially-spoiled-on + game.getState().clearTriggeredAbilities(); game.checkStateAndTriggered(); // triggered effects don't go to stack because check of endTurnRequested - - // 4) The current phase and/or step ends. + + // 4) The current phase and/or step ends. // The game skips straight to the cleanup step. The cleanup step happens in its entirety. // this is caused by the endTurnRequest state - } public boolean isDeclareAttackersStepStarted() { @@ -310,23 +308,23 @@ public class Turn implements Serializable { public void setEndTurnRequested(boolean endTurn) { this.endTurn = endTurn; } - + public boolean isEndTurnRequested() { return endTurn; } - + public Turn copy() { return new Turn(this); } - + public String getValue(int turnNum) { StringBuilder sb = threadLocalBuilder.get(); sb.append("[").append(turnNum) - .append(":").append(currentPhase.getType()) - .append(":").append(currentPhase.getStep().getType()) - .append("]"); + .append(":").append(currentPhase.getType()) + .append(":").append(currentPhase.getStep().getType()) + .append("]"); return sb.toString(); } - + } From ee738786b989229744d195226deca0d19fd866cb Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Tue, 7 Jul 2015 16:23:12 +0200 Subject: [PATCH 103/105] * Liliana, Heretical Healer - Fixed that she was exiled and transformed even if no longer on the battlefield as the effect resolved. --- .../abilities/keywords/TransformTest.java | 32 +++++++++++++++++++ ...ExileAndReturnTransformedSourceEffect.java | 5 +-- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/TransformTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/TransformTest.java index eb3cf1762dc..14e6c0db6a3 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/TransformTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/TransformTest.java @@ -92,4 +92,36 @@ public class TransformTest extends CardTestPlayerBase { } + /** + * The creature-Liliana and another creature was out, Languish is cast + * killing both, Liliana comes back transformed and no zombie. I'm fairly + * certain she's not supposed to come back due to her exile trigger + * shouldn't be able to exile her cos she's dead. + */ + @Test + public void LilianaHereticalHealer2() { + addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion", 1); + + // Lifelink + // Whenever another nontoken creature you control dies, exile Liliana Heretical Healer, then return her to the battlefield transformed under her owner's control. If you do, put a 2/2 black Zombie creature token onto the battlefield. + addCard(Zone.BATTLEFIELD, playerA, "Liliana, Heretical Healer"); + + // All creatures get -4/-4 until end of turn. + addCard(Zone.HAND, playerB, "Languish"); + addCard(Zone.BATTLEFIELD, playerB, "Swamp", 4); + + castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Languish"); + + setStopAt(2, PhaseStep.BEGIN_COMBAT); + execute(); + + assertGraveyardCount(playerB, "Languish", 1); + assertPermanentCount(playerA, "Liliana, Defiant Necromancer", 0); + assertPermanentCount(playerA, "Zombie", 0); + + assertGraveyardCount(playerA, "Silvercoat Lion", 1); + assertGraveyardCount(playerA, "Liliana, Heretical Healer", 1); + + } + } diff --git a/Mage/src/mage/abilities/effects/common/ExileAndReturnTransformedSourceEffect.java b/Mage/src/mage/abilities/effects/common/ExileAndReturnTransformedSourceEffect.java index 7e328a9b8b1..6b57e657d3c 100644 --- a/Mage/src/mage/abilities/effects/common/ExileAndReturnTransformedSourceEffect.java +++ b/Mage/src/mage/abilities/effects/common/ExileAndReturnTransformedSourceEffect.java @@ -5,7 +5,6 @@ */ package mage.abilities.effects.common; -import mage.MageObject; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.Effect; @@ -15,6 +14,7 @@ import mage.cards.Card; import mage.constants.Outcome; import mage.constants.Zone; import mage.game.Game; +import mage.game.permanent.Permanent; import mage.players.Player; /** @@ -57,7 +57,8 @@ public class ExileAndReturnTransformedSourceEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - MageObject sourceObject = source.getSourceObjectIfItStillExists(game); + // Creature has to be on the battlefield to get exiled and be able to return transformed + Permanent sourceObject = game.getPermanent(source.getSourceId()); Player controller = game.getPlayer(source.getControllerId()); if (sourceObject != null && controller != null) { Card card = (Card) sourceObject; From 322d2dd0e5a805966a286814e7092c2bec8b8eea Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Tue, 7 Jul 2015 16:47:19 +0200 Subject: [PATCH 104/105] * Moltensteel Dragon - Fixed missing flying ability. --- .../mage/sets/newphyrexia/MoltensteelDragon.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/Mage.Sets/src/mage/sets/newphyrexia/MoltensteelDragon.java b/Mage.Sets/src/mage/sets/newphyrexia/MoltensteelDragon.java index 7a7199cf973..61c0f707e93 100644 --- a/Mage.Sets/src/mage/sets/newphyrexia/MoltensteelDragon.java +++ b/Mage.Sets/src/mage/sets/newphyrexia/MoltensteelDragon.java @@ -28,16 +28,17 @@ package mage.sets.newphyrexia; import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.PhyrexianManaCost; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.ColoredManaSymbol; import mage.constants.Duration; import mage.constants.Rarity; import mage.constants.Zone; -import mage.MageInt; -import mage.abilities.common.SimpleActivatedAbility; -import mage.abilities.costs.mana.PhyrexianManaCost; -import mage.abilities.effects.common.continuous.BoostSourceEffect; -import mage.cards.CardImpl; /** * @@ -53,6 +54,9 @@ public class MoltensteelDragon extends CardImpl { this.power = new MageInt(4); this.toughness = new MageInt(4); + // Flying + this.addAbility(FlyingAbility.getInstance()); + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostSourceEffect(1, 0, Duration.EndOfTurn), new PhyrexianManaCost(ColoredManaSymbol.R))); From 51c6a89753ea3dc22194009826e5263f4e25444b Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Tue, 7 Jul 2015 17:09:52 +0200 Subject: [PATCH 105/105] * Enshrouding Mist - Fixed that the target creature was not untapped if renowned. --- .../sets/magicorigins/ConsulsLieutenant.java | 4 +- .../sets/magicorigins/EnshroudingMist.java | 11 ++- .../sets/magicorigins/GoblinGloryChaser.java | 4 +- .../sets/magicorigins/HonoredHierarch.java | 6 +- .../sets/magicorigins/ScabClanBerserker.java | 4 +- .../cards/abilities/keywords/RenownTest.java | 35 +++++++++- ...tion.java => RenownedSourceCondition.java} | 12 ++-- .../common/RenownedTargetCondition.java | 67 +++++++++++++++++++ .../mage/abilities/keyword/RenownAbility.java | 16 ++--- Mage/src/mage/game/permanent/Permanent.java | 4 +- .../mage/game/permanent/PermanentImpl.java | 12 ++-- 11 files changed, 135 insertions(+), 40 deletions(-) rename Mage/src/mage/abilities/condition/common/{RenownCondition.java => RenownedSourceCondition.java} (69%) create mode 100644 Mage/src/mage/abilities/condition/common/RenownedTargetCondition.java diff --git a/Mage.Sets/src/mage/sets/magicorigins/ConsulsLieutenant.java b/Mage.Sets/src/mage/sets/magicorigins/ConsulsLieutenant.java index 26befe1d8f4..0359438bf99 100644 --- a/Mage.Sets/src/mage/sets/magicorigins/ConsulsLieutenant.java +++ b/Mage.Sets/src/mage/sets/magicorigins/ConsulsLieutenant.java @@ -30,7 +30,7 @@ package mage.sets.magicorigins; import java.util.UUID; import mage.MageInt; import mage.abilities.common.AttacksTriggeredAbility; -import mage.abilities.condition.common.RenownCondition; +import mage.abilities.condition.common.RenownedSourceCondition; import mage.abilities.decorator.ConditionalTriggeredAbility; import mage.abilities.effects.common.continuous.BoostControlledEffect; import mage.abilities.keyword.FirstStrikeAbility; @@ -62,7 +62,7 @@ public class ConsulsLieutenant extends CardImpl { // Whenever Consul's Lieutenant attacks, if it's renowned, other attacking creatures you control get +1/+1 until end of turn. this.addAbility(new ConditionalTriggeredAbility(new AttacksTriggeredAbility( new BoostControlledEffect(1, 1, Duration.EndOfTurn, new FilterAttackingCreature("other attacking creatures you control"), true), false), - RenownCondition.getInstance(), + RenownedSourceCondition.getInstance(), "Whenever Consul's Lieutenant attacks, if it's renowned, other attacking creatures you control get +1/+1 until end of turn.")); } diff --git a/Mage.Sets/src/mage/sets/magicorigins/EnshroudingMist.java b/Mage.Sets/src/mage/sets/magicorigins/EnshroudingMist.java index 9c81ff6e17d..f85197d29d8 100644 --- a/Mage.Sets/src/mage/sets/magicorigins/EnshroudingMist.java +++ b/Mage.Sets/src/mage/sets/magicorigins/EnshroudingMist.java @@ -28,12 +28,12 @@ package mage.sets.magicorigins; import java.util.UUID; -import mage.abilities.condition.common.RenownCondition; +import mage.abilities.condition.common.RenownedTargetCondition; import mage.abilities.decorator.ConditionalOneShotEffect; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.PreventDamageToTargetEffect; -import mage.abilities.effects.common.UntapSourceEffect; +import mage.abilities.effects.common.UntapTargetEffect; import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.cards.CardImpl; import mage.constants.CardType; @@ -56,12 +56,11 @@ public class EnshroudingMist extends CardImpl { Effect effect = new PreventDamageToTargetEffect(Duration.EndOfTurn, Integer.MAX_VALUE); effect.setText("Prevent all damage that would dealt to it this turn"); this.getSpellAbility().addEffect(effect); - OneShotEffect effect2 = new UntapSourceEffect(); + OneShotEffect effect2 = new UntapTargetEffect(); effect2.setText("untap it"); - this.getSpellAbility().addEffect(new ConditionalOneShotEffect(effect2, RenownCondition.getInstance())); + this.getSpellAbility().addEffect(new ConditionalOneShotEffect(effect2, RenownedTargetCondition.getInstance())); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); - - + } public EnshroudingMist(final EnshroudingMist card) { diff --git a/Mage.Sets/src/mage/sets/magicorigins/GoblinGloryChaser.java b/Mage.Sets/src/mage/sets/magicorigins/GoblinGloryChaser.java index 09faa522915..c5a5ae8e4ce 100644 --- a/Mage.Sets/src/mage/sets/magicorigins/GoblinGloryChaser.java +++ b/Mage.Sets/src/mage/sets/magicorigins/GoblinGloryChaser.java @@ -31,7 +31,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.condition.common.RenownCondition; +import mage.abilities.condition.common.RenownedSourceCondition; import mage.abilities.decorator.ConditionalContinuousEffect; import mage.abilities.effects.Effect; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; @@ -63,7 +63,7 @@ public class GoblinGloryChaser extends CardImpl { // As long as Goblin Glory Chaser is renowned, it has menace. Effect effect = new ConditionalContinuousEffect( new GainAbilitySourceEffect(new MenaceAbility(), Duration.WhileOnBattlefield), - RenownCondition.getInstance(), + RenownedSourceCondition.getInstance(), "As long as {this} is renowned, it has menace"); Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, effect); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/sets/magicorigins/HonoredHierarch.java b/Mage.Sets/src/mage/sets/magicorigins/HonoredHierarch.java index d09a2fb9e63..0661baef1d0 100644 --- a/Mage.Sets/src/mage/sets/magicorigins/HonoredHierarch.java +++ b/Mage.Sets/src/mage/sets/magicorigins/HonoredHierarch.java @@ -31,7 +31,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.condition.common.RenownCondition; +import mage.abilities.condition.common.RenownedSourceCondition; import mage.abilities.decorator.ConditionalContinuousEffect; import mage.abilities.effects.Effect; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; @@ -64,12 +64,12 @@ public class HonoredHierarch extends CardImpl { // As long as Honored Hierarch is renowned, it has vigilance and "{T}: Add one mana of any color to your mana pool." Effect effect = new ConditionalContinuousEffect( new GainAbilitySourceEffect(VigilanceAbility.getInstance(), Duration.WhileOnBattlefield), - RenownCondition.getInstance(), + RenownedSourceCondition.getInstance(), "As long as {this} is renown, it has vigilance"); Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, effect); effect = new ConditionalContinuousEffect( new GainAbilitySourceEffect(new AnyColorManaAbility(), Duration.WhileOnBattlefield), - RenownCondition.getInstance(), + RenownedSourceCondition.getInstance(), "and \"{T}: Add one mana of any color to your mana pool.\""); ability.addEffect(effect); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/sets/magicorigins/ScabClanBerserker.java b/Mage.Sets/src/mage/sets/magicorigins/ScabClanBerserker.java index d325fe9e592..35c7bd9d9e3 100644 --- a/Mage.Sets/src/mage/sets/magicorigins/ScabClanBerserker.java +++ b/Mage.Sets/src/mage/sets/magicorigins/ScabClanBerserker.java @@ -30,7 +30,7 @@ package mage.sets.magicorigins; import java.util.UUID; import mage.MageInt; import mage.abilities.TriggeredAbilityImpl; -import mage.abilities.condition.common.RenownCondition; +import mage.abilities.condition.common.RenownedSourceCondition; import mage.abilities.decorator.ConditionalTriggeredAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.common.DamageTargetEffect; @@ -68,7 +68,7 @@ public class ScabClanBerserker extends CardImpl { // Whenever an opponent casts a noncreature spell, if Scab-Clan Berserker is renowned, Scab-Clan Berserker deals 2 damage to that player. this.addAbility(new ConditionalTriggeredAbility( new ScabClanBerserkerTriggeredAbility(), - RenownCondition.getInstance(), + RenownedSourceCondition.getInstance(), "Whenever an opponent casts a noncreature spell, if Scab-Clan Berserker is renowned, Scab-Clan Berserker deals 2 damage to that player")); } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/RenownTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/RenownTest.java index 16637cc14cd..60e740bb1b3 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/RenownTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/RenownTest.java @@ -174,7 +174,7 @@ public class RenownTest extends CardTestPlayerBase { assertPowerToughness(playerA, "Rhox Maulers", 6, 6); // renown again in turn 7 after the attack Permanent rhoxMaulers = getPermanent("Rhox Maulers", playerA); - Assert.assertEquals("may not be renown", true, rhoxMaulers.isRenown()); + Assert.assertEquals("may not be renown", true, rhoxMaulers.isRenowned()); } @@ -202,7 +202,7 @@ public class RenownTest extends CardTestPlayerBase { execute(); Permanent goblin = getPermanent("Goblin Glory Chaser", playerA); - Assert.assertEquals("has has renown", true, goblin.isRenown()); + Assert.assertEquals("has has renown", true, goblin.isRenowned()); assertAbility(playerA, "Goblin Glory Chaser", new MenaceAbility(), true); assertPowerToughness(playerA, "Goblin Glory Chaser", 2, 2); @@ -231,11 +231,40 @@ public class RenownTest extends CardTestPlayerBase { execute(); Permanent berserker = getPermanent("Scab-Clan Berserker", playerA); - Assert.assertEquals("has has renown", true, berserker.isRenown()); + Assert.assertEquals("has has renown", true, berserker.isRenowned()); assertPowerToughness(playerA, "Scab-Clan Berserker", 3, 3); assertLife(playerA, 17); // Lightning Bolt assertLife(playerB, 16); // 2 from attack 2 from triggered ability } + + /** + * Enshrouding Mist (new card from ORI) isn't untapping renowned creatures. + */ + @Test + public void testEnshroudingMist() { + // Renown 1 + // Whenever an opponent casts a noncreature spell, if Scab-Clan Berserker is renowned, Scab-Clan Berserker deals 2 damage to that player. + addCard(Zone.BATTLEFIELD, playerB, "Scab-Clan Berserker"); // 2/2 {1}{R}{R} + + addCard(Zone.BATTLEFIELD, playerB, "Plains", 1); + // Target creature gets +1/+1 until end of turn. Prevent all damage that would dealt to it this turn. If it's renowned, untap it. + addCard(Zone.HAND, playerB, "Enshrouding Mist"); + + attack(2, playerB, "Scab-Clan Berserker"); // 1 damage + castSpell(2, PhaseStep.POSTCOMBAT_MAIN, playerB, "Enshrouding Mist", "Scab-Clan Berserker"); + + setStopAt(2, PhaseStep.END_TURN); + execute(); + + Permanent berserker = getPermanent("Scab-Clan Berserker", playerB); + Assert.assertEquals("has has renown", true, berserker.isRenowned()); + assertPowerToughness(playerB, "Scab-Clan Berserker", 4, 4); // +1 from renowned + 1 from Enshrouding Mist + assertTapped("Scab-Clan Berserker", false); + + assertLife(playerA, 18); // Lightning Bolt + assertLife(playerB, 20); + + } } diff --git a/Mage/src/mage/abilities/condition/common/RenownCondition.java b/Mage/src/mage/abilities/condition/common/RenownedSourceCondition.java similarity index 69% rename from Mage/src/mage/abilities/condition/common/RenownCondition.java rename to Mage/src/mage/abilities/condition/common/RenownedSourceCondition.java index 1e00bba4426..edd058a64b2 100644 --- a/Mage/src/mage/abilities/condition/common/RenownCondition.java +++ b/Mage/src/mage/abilities/condition/common/RenownedSourceCondition.java @@ -16,15 +16,15 @@ import mage.game.permanent.Permanent; * @author LevelX2 */ -public class RenownCondition implements Condition { +public class RenownedSourceCondition implements Condition { - private static RenownCondition fInstance = null; + private static RenownedSourceCondition fInstance = null; - private RenownCondition() {} + private RenownedSourceCondition() {} - public static RenownCondition getInstance() { + public static RenownedSourceCondition getInstance() { if (fInstance == null) { - fInstance = new RenownCondition(); + fInstance = new RenownedSourceCondition(); } return fInstance; } @@ -33,7 +33,7 @@ public class RenownCondition implements Condition { public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent != null) { - return permanent.isRenown(); + return permanent.isRenowned(); } return false; } diff --git a/Mage/src/mage/abilities/condition/common/RenownedTargetCondition.java b/Mage/src/mage/abilities/condition/common/RenownedTargetCondition.java new file mode 100644 index 00000000000..0d822b288d5 --- /dev/null +++ b/Mage/src/mage/abilities/condition/common/RenownedTargetCondition.java @@ -0,0 +1,67 @@ +/* + * 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.abilities.condition.common; + +import mage.abilities.Ability; +import mage.abilities.condition.Condition; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * + * @author LevelX2 + */ +public class RenownedTargetCondition implements Condition { + + private static RenownedTargetCondition fInstance = null; + + private RenownedTargetCondition() { + } + + public static RenownedTargetCondition getInstance() { + if (fInstance == null) { + fInstance = new RenownedTargetCondition(); + } + return fInstance; + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(source.getTargets().getFirstTarget()); + if (permanent != null) { + return permanent.isRenowned(); + } + return false; + } + + @Override + public String toString() { + return "it's renowned"; + } + +} diff --git a/Mage/src/mage/abilities/keyword/RenownAbility.java b/Mage/src/mage/abilities/keyword/RenownAbility.java index 81fac74c52f..878a7659768 100644 --- a/Mage/src/mage/abilities/keyword/RenownAbility.java +++ b/Mage/src/mage/abilities/keyword/RenownAbility.java @@ -27,7 +27,7 @@ public class RenownAbility extends TriggeredAbilityImpl { private int renownValue; public RenownAbility(int renownValue) { - super(Zone.BATTLEFIELD, new BecomeRenownSourceEffect(renownValue), false); + super(Zone.BATTLEFIELD, new BecomesRenownedSourceEffect(renownValue), false); this.renownValue = renownValue; } @@ -49,7 +49,7 @@ public class RenownAbility extends TriggeredAbilityImpl { @Override public boolean checkInterveningIfClause(Game game) { Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(getSourceId()); - return sourcePermanent != null && !sourcePermanent.isRenown(); + return sourcePermanent != null && !sourcePermanent.isRenowned(); } @Override @@ -63,20 +63,20 @@ public class RenownAbility extends TriggeredAbilityImpl { } } -class BecomeRenownSourceEffect extends OneShotEffect { +class BecomesRenownedSourceEffect extends OneShotEffect { - public BecomeRenownSourceEffect(int renownValue) { + public BecomesRenownedSourceEffect(int renownValue) { super(Outcome.BoostCreature); this.staticText = setText(renownValue); } - public BecomeRenownSourceEffect(final BecomeRenownSourceEffect effect) { + public BecomesRenownedSourceEffect(final BecomesRenownedSourceEffect effect) { super(effect); } @Override - public BecomeRenownSourceEffect copy() { - return new BecomeRenownSourceEffect(this); + public BecomesRenownedSourceEffect copy() { + return new BecomesRenownedSourceEffect(this); } @Override @@ -90,7 +90,7 @@ class BecomeRenownSourceEffect extends OneShotEffect { renownValue = source.getManaCostsToPay().getX(); } new AddCountersSourceEffect(CounterType.P1P1.createInstance(renownValue), true).apply(game, source); - permanent.setRenown(true); + permanent.setRenowned(true); game.fireEvent(GameEvent.getEvent(GameEvent.EventType.BECOMES_RENOWNED, source.getSourceId(), source.getSourceId(), source.getControllerId(), renownValue)); return true; } diff --git a/Mage/src/mage/game/permanent/Permanent.java b/Mage/src/mage/game/permanent/Permanent.java index 22e6319590d..33221ea2fb7 100644 --- a/Mage/src/mage/game/permanent/Permanent.java +++ b/Mage/src/mage/game/permanent/Permanent.java @@ -75,8 +75,8 @@ public interface Permanent extends Card, Controllable { boolean isMonstrous(); void setMonstrous(boolean value); - boolean isRenown(); - void setRenown(boolean value); + boolean isRenowned(); + void setRenowned(boolean value); void setCardNumber(int cid); void setExpansionSetCode(String expansionSetCode); diff --git a/Mage/src/mage/game/permanent/PermanentImpl.java b/Mage/src/mage/game/permanent/PermanentImpl.java index b71c09a9a31..5ba200bae69 100644 --- a/Mage/src/mage/game/permanent/PermanentImpl.java +++ b/Mage/src/mage/game/permanent/PermanentImpl.java @@ -90,7 +90,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent { protected boolean flipped; protected boolean transformed; protected boolean monstrous; - protected boolean renown; + protected boolean renowned; protected boolean manifested = false; protected boolean morphed = false; protected UUID originalControllerId; @@ -176,7 +176,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent { this.maxBlockedBy = permanent.maxBlockedBy; this.transformed = permanent.transformed; this.monstrous = permanent.monstrous; - this.renown = permanent.renown; + this.renowned = permanent.renowned; this.pairedCard = permanent.pairedCard; this.timesLoyaltyUsed = permanent.timesLoyaltyUsed; @@ -1268,13 +1268,13 @@ public abstract class PermanentImpl extends CardImpl implements Permanent { } @Override - public boolean isRenown() { - return this.renown; + public boolean isRenowned() { + return this.renowned; } @Override - public void setRenown(boolean value) { - this.renown = value; + public void setRenowned(boolean value) { + this.renowned = value; } @Override