From 2979d7189d107a36fc761e8eae93d3b036375d8d Mon Sep 17 00:00:00 2001 From: Luna Skyrise Date: Sun, 10 May 2015 22:54:16 -0300 Subject: [PATCH 01/37] Change Tenth Edition set name to "tenthedition" The corresponding package is mage.sets.tenthedition, not mage.sets.tenth --- Utils/known-sets.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Utils/known-sets.txt b/Utils/known-sets.txt index 80bae39e68..dccc840c67 100644 --- a/Utils/known-sets.txt +++ b/Utils/known-sets.txt @@ -116,7 +116,7 @@ Starter 2000|starter2000| Stronghold|stronghold| Tempest|tempest| Tempest Remastered|tempestremastered| -Tenth Edition|tenth| +Tenth Edition|tenthedition| The Dark|thedark| Theros|theros| Time Spiral "Timeshifted"|timeshifted| From fb989cd2f2ae74731b2a16e60b91f6a553e292cd Mon Sep 17 00:00:00 2001 From: Luna Skyrise Date: Sun, 10 May 2015 23:00:51 -0300 Subject: [PATCH 02/37] [5ED, ICE] Add Chub Toad --- .../src/mage/sets/fifthedition/ChubToad.java | 52 ++++++++++++++ Mage.Sets/src/mage/sets/iceage/ChubToad.java | 69 +++++++++++++++++++ .../mage/sets/mastersedition/ChubToad.java | 52 ++++++++++++++ 3 files changed, 173 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/fifthedition/ChubToad.java create mode 100644 Mage.Sets/src/mage/sets/iceage/ChubToad.java create mode 100644 Mage.Sets/src/mage/sets/mastersedition/ChubToad.java diff --git a/Mage.Sets/src/mage/sets/fifthedition/ChubToad.java b/Mage.Sets/src/mage/sets/fifthedition/ChubToad.java new file mode 100644 index 0000000000..a3448378e3 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fifthedition/ChubToad.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.fifthedition; + +import java.util.UUID; + +/** + * + * @author anonymous + */ +public class ChubToad extends mage.sets.iceage.ChubToad { + + public ChubToad(UUID ownerId) { + super(ownerId); + this.cardNumber = 145; + this.expansionSetCode = "5ED"; + } + + public ChubToad(final ChubToad card) { + super(card); + } + + @Override + public ChubToad copy() { + return new ChubToad(this); + } +} diff --git a/Mage.Sets/src/mage/sets/iceage/ChubToad.java b/Mage.Sets/src/mage/sets/iceage/ChubToad.java new file mode 100644 index 0000000000..5b7cbdb052 --- /dev/null +++ b/Mage.Sets/src/mage/sets/iceage/ChubToad.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.iceage; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.BlocksOrBecomesBlockedTriggeredAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; + +/** + * + * @author anonymous + */ +public class ChubToad extends CardImpl { + + public ChubToad(UUID ownerId) { + super(ownerId, 117, "Chub Toad", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{2}{G}"); + this.expansionSetCode = "ICE"; + this.subtype.add("Frog"); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Whenever Chub Toad blocks or becomes blocked, it gets +2/+2 until end of turn. + Effect effect = new BoostSourceEffect(+1, +1, Duration.EndOfTurn); + effect.setText("it gets +2/+2 until end of turn"); + Ability ability = new BlocksOrBecomesBlockedTriggeredAbility(effect, false); + this.addAbility(ability); + } + + public ChubToad(final ChubToad card) { + super(card); + } + + @Override + public ChubToad copy() { + return new ChubToad(this); + } +} diff --git a/Mage.Sets/src/mage/sets/mastersedition/ChubToad.java b/Mage.Sets/src/mage/sets/mastersedition/ChubToad.java new file mode 100644 index 0000000000..d780f6d7e7 --- /dev/null +++ b/Mage.Sets/src/mage/sets/mastersedition/ChubToad.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.mastersedition; + +import java.util.UUID; + +/** + * + * @author anonymous + */ +public class ChubToad extends mage.sets.iceage.ChubToad { + + public ChubToad(UUID ownerId) { + super(ownerId); + this.cardNumber = 116; + this.expansionSetCode = "MED"; + } + + public ChubToad(final ChubToad card) { + super(card); + } + + @Override + public ChubToad copy() { + return new ChubToad(this); + } +} From d26cd70a3a3a6bde9f89317988b28e8a5bec27e4 Mon Sep 17 00:00:00 2001 From: Luna Skyrise Date: Sun, 10 May 2015 23:01:29 -0300 Subject: [PATCH 03/37] [10E] Add Sylvan Basilisk --- .../sets/portalsecondage/SylvanBasilisk.java | 63 +++++++++++++++++++ .../mage/sets/starter1999/SylvanBasilisk.java | 52 +++++++++++++++ .../sets/tenthedition/SylvanBasilisk.java | 54 ++++++++++++++++ 3 files changed, 169 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/portalsecondage/SylvanBasilisk.java create mode 100644 Mage.Sets/src/mage/sets/starter1999/SylvanBasilisk.java create mode 100644 Mage.Sets/src/mage/sets/tenthedition/SylvanBasilisk.java diff --git a/Mage.Sets/src/mage/sets/portalsecondage/SylvanBasilisk.java b/Mage.Sets/src/mage/sets/portalsecondage/SylvanBasilisk.java new file mode 100644 index 0000000000..981f43296e --- /dev/null +++ b/Mage.Sets/src/mage/sets/portalsecondage/SylvanBasilisk.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.portalsecondage; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.BecomesBlockedByCreatureTriggeredAbility; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; + +/** + * + * @author anonymous + */ +public class SylvanBasilisk extends CardImpl { + + public SylvanBasilisk(UUID ownerId) { + super(ownerId, 86, "Sylvan Basilisk", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{3}{G}{G}"); + this.expansionSetCode = "PO2"; + this.subtype.add("Basilisk"); + this.power = new MageInt(2); + this.toughness = new MageInt(4); + + // Whenever Sylvan Basilisk becomes blocked by a creature, destroy that creature. + this.addAbility(new BecomesBlockedByCreatureTriggeredAbility(new DestroyTargetEffect(), false)); + } + + public SylvanBasilisk(final SylvanBasilisk card) { + super(card); + } + + @Override + public SylvanBasilisk copy() { + return new SylvanBasilisk(this); + } +} diff --git a/Mage.Sets/src/mage/sets/starter1999/SylvanBasilisk.java b/Mage.Sets/src/mage/sets/starter1999/SylvanBasilisk.java new file mode 100644 index 0000000000..44c25f6d4b --- /dev/null +++ b/Mage.Sets/src/mage/sets/starter1999/SylvanBasilisk.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.starter1999; + +import java.util.UUID; + +/** + * + * @author anonymous + */ +public class SylvanBasilisk extends mage.sets.portalsecondage.SylvanBasilisk { + + public SylvanBasilisk(UUID ownerId) { + super(ownerId); + this.cardNumber = 145; + this.expansionSetCode = "S99"; + } + + public SylvanBasilisk(final SylvanBasilisk card) { + super(card); + } + + @Override + public SylvanBasilisk copy() { + return new SylvanBasilisk(this); + } +} diff --git a/Mage.Sets/src/mage/sets/tenthedition/SylvanBasilisk.java b/Mage.Sets/src/mage/sets/tenthedition/SylvanBasilisk.java new file mode 100644 index 0000000000..b09865278d --- /dev/null +++ b/Mage.Sets/src/mage/sets/tenthedition/SylvanBasilisk.java @@ -0,0 +1,54 @@ +/* + * 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.tenthedition; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author anonymous + */ +public class SylvanBasilisk extends mage.sets.portalsecondage.SylvanBasilisk { + + public SylvanBasilisk(UUID ownerId) { + super(ownerId); + this.cardNumber = 301; + this.expansionSetCode = "10E"; + this.rarity = Rarity.UNCOMMON; + } + + public SylvanBasilisk(final SylvanBasilisk card) { + super(card); + } + + @Override + public SylvanBasilisk copy() { + return new SylvanBasilisk(this); + } +} From be41a64975d528c984f241e6276bb4f36e618058 Mon Sep 17 00:00:00 2001 From: Luna Skyrise Date: Sun, 10 May 2015 23:02:23 -0300 Subject: [PATCH 04/37] [9ED, 8ED, UDS] Add Emperor Crocodile --- .../sets/eighthedition/EmperorCrocodile.java | 52 ++++++++++ .../sets/ninthedition/EmperorCrocodile.java | 99 +++++++++++++++++++ .../sets/urzasdestiny/EmperorCrocodile.java | 52 ++++++++++ 3 files changed, 203 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/eighthedition/EmperorCrocodile.java create mode 100644 Mage.Sets/src/mage/sets/ninthedition/EmperorCrocodile.java create mode 100644 Mage.Sets/src/mage/sets/urzasdestiny/EmperorCrocodile.java diff --git a/Mage.Sets/src/mage/sets/eighthedition/EmperorCrocodile.java b/Mage.Sets/src/mage/sets/eighthedition/EmperorCrocodile.java new file mode 100644 index 0000000000..4b5e3572ec --- /dev/null +++ b/Mage.Sets/src/mage/sets/eighthedition/EmperorCrocodile.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.eighthedition; + +import java.util.UUID; + +/** + * + * @author anonymous + */ +public class EmperorCrocodile extends mage.sets.ninthedition.EmperorCrocodile { + + public EmperorCrocodile(UUID ownerId) { + super(ownerId); + this.cardNumber = 246; + this.expansionSetCode = "8ED"; + } + + public EmperorCrocodile(final EmperorCrocodile card) { + super(card); + } + + @Override + public EmperorCrocodile copy() { + return new EmperorCrocodile(this); + } +} diff --git a/Mage.Sets/src/mage/sets/ninthedition/EmperorCrocodile.java b/Mage.Sets/src/mage/sets/ninthedition/EmperorCrocodile.java new file mode 100644 index 0000000000..ceb3252bc3 --- /dev/null +++ b/Mage.Sets/src/mage/sets/ninthedition/EmperorCrocodile.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.ninthedition; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.StateTriggeredAbility; +import mage.abilities.effects.common.SacrificeSourceEffect; +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 anonymous + */ +public class EmperorCrocodile extends CardImpl { + + public EmperorCrocodile(UUID ownerId) { + super(ownerId, 241, "Emperor Crocodile", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{3}{G}"); + this.expansionSetCode = "9ED"; + this.subtype.add("Crocodile"); + this.power = new MageInt(5); + this.toughness = new MageInt(5); + + // When you control no other creatures, sacrifice Emperor Crocodile. + // 704.1 + this.addAbility(new EmperorCrocodileStateTriggeredAbility()); + } + + public EmperorCrocodile(final EmperorCrocodile card) { + super(card); + } + + @Override + public EmperorCrocodile copy() { + return new EmperorCrocodile(this); + } +} + +class EmperorCrocodileStateTriggeredAbility extends StateTriggeredAbility { + + public EmperorCrocodileStateTriggeredAbility() { + super(Zone.BATTLEFIELD, new SacrificeSourceEffect()); + } + + public EmperorCrocodileStateTriggeredAbility(final EmperorCrocodileStateTriggeredAbility ability) { + super(ability); + } + + @Override + public EmperorCrocodileStateTriggeredAbility copy() { + return new EmperorCrocodileStateTriggeredAbility(this); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + for (Permanent perm : game.getBattlefield().getAllActivePermanents(controllerId)) { + if (!perm.getId().equals(this.getSourceId()) && perm.getCardType().contains(CardType.CREATURE)) { + return false; + } + } + return true; + } + + @Override + public String getRule() { + return "When you control no other creatures, sacrifice {this}."; + } +} diff --git a/Mage.Sets/src/mage/sets/urzasdestiny/EmperorCrocodile.java b/Mage.Sets/src/mage/sets/urzasdestiny/EmperorCrocodile.java new file mode 100644 index 0000000000..4536677945 --- /dev/null +++ b/Mage.Sets/src/mage/sets/urzasdestiny/EmperorCrocodile.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.urzasdestiny; + +import java.util.UUID; + +/** + * + * @author anonymous + */ +public class EmperorCrocodile extends mage.sets.ninthedition.EmperorCrocodile { + + public EmperorCrocodile(UUID ownerId) { + super(ownerId); + this.cardNumber = 105; + this.expansionSetCode = "UDS"; + } + + public EmperorCrocodile(final EmperorCrocodile card) { + super(card); + } + + @Override + public EmperorCrocodile copy() { + return new EmperorCrocodile(this); + } +} From c48d381b245ffbf5d7f6207f6d5301648631f988 Mon Sep 17 00:00:00 2001 From: Luna Skyrise Date: Sun, 10 May 2015 23:03:25 -0300 Subject: [PATCH 05/37] [TMP] Add Flailing Drake Includes test. --- .../src/mage/sets/tempest/FlailingDrake.java | 72 +++++++++++++++++++ .../test/cards/single/FlailingDrakeTest.java | 58 +++++++++++++++ 2 files changed, 130 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/tempest/FlailingDrake.java create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/single/FlailingDrakeTest.java diff --git a/Mage.Sets/src/mage/sets/tempest/FlailingDrake.java b/Mage.Sets/src/mage/sets/tempest/FlailingDrake.java new file mode 100644 index 0000000000..27c4a83cb5 --- /dev/null +++ b/Mage.Sets/src/mage/sets/tempest/FlailingDrake.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.tempest; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.BlocksOrBecomesBlockedByCreatureTriggeredAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; + +/** + * + * @author anonymous + */ +public class FlailingDrake extends CardImpl { + + public FlailingDrake(UUID ownerId) { + super(ownerId, 121, "Flailing Drake", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{3}{G}"); + this.expansionSetCode = "TMP"; + this.subtype.add("Drake"); + this.power = new MageInt(2); + this.toughness = new MageInt(3); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + // Whenever Flailing Drake blocks or becomes blocked by a creature, that creature gets +1/+1 until end of turn. + Effect effect = new BoostTargetEffect(+1, +1, Duration.EndOfTurn); + effect.setText("that creature gets +1/+1 until end of turn"); + Ability ability = new BlocksOrBecomesBlockedByCreatureTriggeredAbility(effect, false); + this.addAbility(ability); + } + + public FlailingDrake(final FlailingDrake card) { + super(card); + } + + @Override + public FlailingDrake copy() { + return new FlailingDrake(this); + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/FlailingDrakeTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/FlailingDrakeTest.java new file mode 100644 index 0000000000..a51c58a2c1 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/FlailingDrakeTest.java @@ -0,0 +1,58 @@ +package org.mage.test.cards.single; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author anonymous + * + * Whenever Flailing Drake blocks or becomes blocked by a creature, that creature gets +1/+1 until end of turn. + */ +public class FlailingDrakeTest extends CardTestPlayerBase { + + @Test + public void testIncreaseBlocker() { + addCard(Zone.BATTLEFIELD, playerA, "Forest", 3); + addCard(Zone.BATTLEFIELD, playerA, "Island", 1); + addCard(Zone.BATTLEFIELD, playerA, "Flailing Drake", 1); + + addCard(Zone.BATTLEFIELD, playerB, "Forest", 3); + addCard(Zone.BATTLEFIELD, playerB, "Island", 3); + addCard(Zone.BATTLEFIELD, playerB, "Snapping Drake", 1); + + attack(3, playerA, "Flailing Drake"); + block(3, playerB, "Snapping Drake", "Flailing Drake"); + + setStopAt(3, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertGraveyardCount(playerA, "Flailing Drake", 1); + //Snapping Drake 4/3 + assertPowerToughness(playerB, "Snapping Drake", 4, 3); + } + + @Test + public void testIncreaseBlocked() { + addCard(Zone.BATTLEFIELD, playerA, "Forest", 3); + addCard(Zone.BATTLEFIELD, playerA, "Island", 1); + addCard(Zone.BATTLEFIELD, playerA, "Flailing Drake", 1); + + addCard(Zone.BATTLEFIELD, playerB, "Forest", 3); + addCard(Zone.BATTLEFIELD, playerB, "Island", 3); + addCard(Zone.BATTLEFIELD, playerB, "Snapping Drake", 1); + + attack(4, playerB, "Snapping Drake"); + block(4, playerA, "Flailing Drake", "Snapping Drake"); + + setStopAt(4, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertGraveyardCount(playerA, "Flailing Drake", 1); + //Snapping Drake 4/3 + assertPowerToughness(playerB, "Snapping Drake", 4, 3); + } + +} From 791522805fe648fa8df942b08dfd4a39c45e8e72 Mon Sep 17 00:00:00 2001 From: Luna Skyrise Date: Sun, 10 May 2015 23:09:29 -0300 Subject: [PATCH 06/37] [CLD] Add Blizzard Specter --- .../mage/sets/coldsnap/BlizzardSpecter.java | 128 ++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/coldsnap/BlizzardSpecter.java diff --git a/Mage.Sets/src/mage/sets/coldsnap/BlizzardSpecter.java b/Mage.Sets/src/mage/sets/coldsnap/BlizzardSpecter.java new file mode 100644 index 0000000000..b451efa5ee --- /dev/null +++ b/Mage.Sets/src/mage/sets/coldsnap/BlizzardSpecter.java @@ -0,0 +1,128 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.coldsnap; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; +import mage.abilities.costs.common.DiscardTargetCost; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.discard.DiscardTargetEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.common.FilterControlledPermanent; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.Target; +import mage.target.common.TargetControlledPermanent; + +/** + * + * @author anonymous + */ +public class BlizzardSpecter extends CardImpl { + + public BlizzardSpecter(UUID ownerId) { + super(ownerId, 126, "Blizzard Specter", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{2}{U}{B}"); + this.expansionSetCode = "CSP"; + this.supertype.add("Snow"); + this.subtype.add("Specter"); + this.power = new MageInt(2); + this.toughness = new MageInt(3); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + // Whenever Blizzard Specter deals combat damage to a player, choose one - That player returns a permanent he or she controls to its owner's hand; or that player discards a card. + Ability ability2 = new DealsCombatDamageToAPlayerTriggeredAbility(new ReturnToHandEffect(), false); + + Mode mode2 = new Mode(); + mode2.getEffects().add(new DiscardTargetEffect(1, false)); + ability2.addMode(mode2); + + this.addAbility(ability2); + } + + public BlizzardSpecter(final BlizzardSpecter card) { + super(card); + } + + @Override + public BlizzardSpecter copy() { + return new BlizzardSpecter(this); + } +} + +class ReturnToHandEffect extends OneShotEffect { + + public ReturnToHandEffect() { + super(Outcome.ReturnToHand); + staticText = "That player returns a permanent he or she controls to its owner's hand"; + } + + public ReturnToHandEffect(final ReturnToHandEffect effect) { + super(effect); + } + + @Override + public ReturnToHandEffect copy() { + return new ReturnToHandEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + boolean result = false; + + Player player = game.getPlayer(targetPointer.getFirst(game, source)); + if (player == null) { + return false; + } + + Target target = new TargetControlledPermanent(1, 1, new FilterControlledPermanent(), true); + if (target.canChoose(player.getId(), game)) { + while (player.isInGame() && !target.isChosen() && target.canChoose(player.getId(), game)) { + player.chooseTarget(Outcome.ReturnToHand, target, source, game); + } + + for (UUID targetId: target.getTargets()) { + Permanent permanent = game.getPermanent(targetId); + if (permanent != null) { + result |= permanent.moveToZone(Zone.HAND, source.getSourceId(), game, false); + } + } + } + return result; + } +} From a0824c5c07f0d85a38dfa5062fd7bdcca242af45 Mon Sep 17 00:00:00 2001 From: Luna Skyrise Date: Sun, 10 May 2015 23:10:18 -0300 Subject: [PATCH 07/37] [8ED, MMQ] Add Distorting Lens --- .../sets/eighthedition/DistortingLens.java | 109 ++++++++++++++++++ .../sets/mercadianmasques/DistortingLens.java | 52 +++++++++ 2 files changed, 161 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/eighthedition/DistortingLens.java create mode 100644 Mage.Sets/src/mage/sets/mercadianmasques/DistortingLens.java diff --git a/Mage.Sets/src/mage/sets/eighthedition/DistortingLens.java b/Mage.Sets/src/mage/sets/eighthedition/DistortingLens.java new file mode 100644 index 0000000000..f77ce78316 --- /dev/null +++ b/Mage.Sets/src/mage/sets/eighthedition/DistortingLens.java @@ -0,0 +1,109 @@ +/* + * 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.eighthedition; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.BecomesColorTargetEffect; +import mage.cards.CardImpl; +import mage.choices.ChoiceColor; +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.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCreaturePermanent; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author anonymous + */ +public class DistortingLens extends CardImpl { + + public DistortingLens(UUID ownerId) { + super(ownerId, 299, "Distorting Lens", Rarity.RARE, new CardType[]{CardType.ARTIFACT}, "{2}"); + this.expansionSetCode = "8ED"; + + // {tap}: Target permanent becomes the color of your choice until end of turn. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ChangeColorEffect(), new TapSourceCost()); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + public DistortingLens(final DistortingLens card) { + super(card); + } + + @Override + public DistortingLens copy() { + return new DistortingLens(this); + } +} + +class ChangeColorEffect extends OneShotEffect { + + public ChangeColorEffect() { + super(Outcome.Neutral); + staticText = "Target permanent becomes the color of your choice until end of turn"; + } + + public ChangeColorEffect(final ChangeColorEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + Permanent permanent = game.getPermanent(source.getSourceId()); + Permanent chosen = game.getPermanent(targetPointer.getFirst(game, source)); + if (player != null && permanent != null) { + ChoiceColor colorChoice = new ChoiceColor(); + if (player.choose(Outcome.Neutral, colorChoice, game)) { + game.informPlayers(permanent.getName() + ": " + player.getName() + " has chosen " + colorChoice.getChoice()); + ContinuousEffect effect = new BecomesColorTargetEffect(colorChoice.getColor(), Duration.EndOfTurn, "is " + colorChoice.getChoice()); + effect.setTargetPointer(new FixedTarget(chosen.getId())); + game.addEffect(effect, source); + return true; + } + } + return false; + } + + @Override + public ChangeColorEffect copy() { + return new ChangeColorEffect(this); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/mercadianmasques/DistortingLens.java b/Mage.Sets/src/mage/sets/mercadianmasques/DistortingLens.java new file mode 100644 index 0000000000..208a90d539 --- /dev/null +++ b/Mage.Sets/src/mage/sets/mercadianmasques/DistortingLens.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.mercadianmasques; + +import java.util.UUID; + +/** + * + * @author anonymous + */ +public class DistortingLens extends mage.sets.eighthedition.DistortingLens { + + public DistortingLens(UUID ownerId) { + super(ownerId); + this.cardNumber = 293; + this.expansionSetCode = "MMQ"; + } + + public DistortingLens(final DistortingLens card) { + super(card); + } + + @Override + public DistortingLens copy() { + return new DistortingLens(this); + } +} From 19c4fe1d2888f74508de167c7267557e4ae76a85 Mon Sep 17 00:00:00 2001 From: Luna Skyrise Date: Sun, 10 May 2015 23:42:22 -0300 Subject: [PATCH 08/37] [ME2, 5ED, ICE] Added Sea Spirit --- .../src/mage/sets/fifthedition/SeaSpirit.java | 52 ++++++++++++++ Mage.Sets/src/mage/sets/iceage/SeaSpirit.java | 52 ++++++++++++++ .../mage/sets/masterseditionii/SeaSpirit.java | 69 +++++++++++++++++++ 3 files changed, 173 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/fifthedition/SeaSpirit.java create mode 100644 Mage.Sets/src/mage/sets/iceage/SeaSpirit.java create mode 100644 Mage.Sets/src/mage/sets/masterseditionii/SeaSpirit.java diff --git a/Mage.Sets/src/mage/sets/fifthedition/SeaSpirit.java b/Mage.Sets/src/mage/sets/fifthedition/SeaSpirit.java new file mode 100644 index 0000000000..57d996beeb --- /dev/null +++ b/Mage.Sets/src/mage/sets/fifthedition/SeaSpirit.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.fifthedition; + +import java.util.UUID; + +/** + * + * @author anonymous + */ +public class SeaSpirit extends mage.sets.masterseditionii.SeaSpirit { + + public SeaSpirit(UUID ownerId) { + super(ownerId); + this.cardNumber = 119; + this.expansionSetCode = "5ED"; + } + + public SeaSpirit(final SeaSpirit card) { + super(card); + } + + @Override + public SeaSpirit copy() { + return new SeaSpirit(this); + } +} diff --git a/Mage.Sets/src/mage/sets/iceage/SeaSpirit.java b/Mage.Sets/src/mage/sets/iceage/SeaSpirit.java new file mode 100644 index 0000000000..1f205f420c --- /dev/null +++ b/Mage.Sets/src/mage/sets/iceage/SeaSpirit.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.iceage; + +import java.util.UUID; + +/** + * + * @author anonymous + */ +public class SeaSpirit extends mage.sets.masterseditionii.SeaSpirit { + + public SeaSpirit(UUID ownerId) { + super(ownerId); + this.cardNumber = 95; + this.expansionSetCode = "ICE"; + } + + public SeaSpirit(final SeaSpirit card) { + super(card); + } + + @Override + public SeaSpirit copy() { + return new SeaSpirit(this); + } +} diff --git a/Mage.Sets/src/mage/sets/masterseditionii/SeaSpirit.java b/Mage.Sets/src/mage/sets/masterseditionii/SeaSpirit.java new file mode 100644 index 0000000000..3d82ba4b47 --- /dev/null +++ b/Mage.Sets/src/mage/sets/masterseditionii/SeaSpirit.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.masterseditionii; + +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.BoostSourceEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; + +/** + * + * @author anonymous + */ +public class SeaSpirit extends CardImpl { + + public SeaSpirit(UUID ownerId) { + super(ownerId, 65, "Sea Spirit", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{4}{U}"); + this.expansionSetCode = "ME2"; + this.subtype.add("Elemental"); + this.subtype.add("Spirit"); + this.power = new MageInt(2); + this.toughness = new MageInt(3); + + // {U}: Sea Spirit gets +1/+0 until end of turn. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostSourceEffect(+1, +0, Duration.EndOfTurn), new ManaCostsImpl("{U}")); + this.addAbility(ability); + } + + public SeaSpirit(final SeaSpirit card) { + super(card); + } + + @Override + public SeaSpirit copy() { + return new SeaSpirit(this); + } +} From 65283b5ac44e13918b945a743c8efa148cb760da Mon Sep 17 00:00:00 2001 From: Luna Skyrise Date: Sun, 10 May 2015 23:47:22 -0300 Subject: [PATCH 09/37] [9ED, 8ED, ARN] Added Rukh Egg Notice that there has been no published bird token creature, so I used the card's first edition. --- .../src/mage/sets/arabiannights/RukhEgg.java | 92 +++++++++++++++++++ .../src/mage/sets/eighthedition/RukhEgg.java | 54 +++++++++++ .../src/mage/sets/ninthedition/RukhEgg.java | 54 +++++++++++ 3 files changed, 200 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/arabiannights/RukhEgg.java create mode 100644 Mage.Sets/src/mage/sets/eighthedition/RukhEgg.java create mode 100644 Mage.Sets/src/mage/sets/ninthedition/RukhEgg.java diff --git a/Mage.Sets/src/mage/sets/arabiannights/RukhEgg.java b/Mage.Sets/src/mage/sets/arabiannights/RukhEgg.java new file mode 100644 index 0000000000..393148c71c --- /dev/null +++ b/Mage.Sets/src/mage/sets/arabiannights/RukhEgg.java @@ -0,0 +1,92 @@ +/* + * 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.arabiannights; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.DiesTriggeredAbility; +import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.game.permanent.token.Token; + +/** + * + * @author anonymous + */ +public class RukhEgg extends CardImpl { + + public RukhEgg(UUID ownerId) { + super(ownerId, 52, "Rukh Egg", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{3}{R}"); + this.expansionSetCode = "ARN"; + this.subtype.add("Bird"); + this.power = new MageInt(0); + this.toughness = new MageInt(3); + + // When Rukh Egg dies, put a 4/4 red Bird creature token with flying onto the battlefield at the beginning of the next end step. + Effect effect = new CreateDelayedTriggeredAbilityEffect(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new CreateTokenEffect(new BirdToken()))); + effect.setText("put a 4/4 red Bird creature token with flying onto the battlefield at the beginning of the next end step"); + Ability ability = new DiesTriggeredAbility(effect); + this.addAbility(ability); + } + + public RukhEgg(final RukhEgg card) { + super(card); + } + + @Override + public RukhEgg copy() { + return new RukhEgg(this); + } +} + +class BirdToken extends Token { + + public BirdToken() { + this("ARN"); //there is no such token in either ARN, 8ED or 9ED + } + + public BirdToken(String setCode) { + super("Bird", "4/4 red Bird creature token with flying"); + this.setOriginalExpansionSetCode(setCode); + cardType.add(CardType.CREATURE); + color.setRed(true); + + subtype.add("Bird"); + power = new MageInt(4); + toughness = new MageInt(4); + addAbility(FlyingAbility.getInstance()); + + } +} diff --git a/Mage.Sets/src/mage/sets/eighthedition/RukhEgg.java b/Mage.Sets/src/mage/sets/eighthedition/RukhEgg.java new file mode 100644 index 0000000000..88bff7441d --- /dev/null +++ b/Mage.Sets/src/mage/sets/eighthedition/RukhEgg.java @@ -0,0 +1,54 @@ +/* + * 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.eighthedition; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author anonymous + */ +public class RukhEgg extends mage.sets.arabiannights.RukhEgg { + + public RukhEgg(UUID ownerId) { + super(ownerId); + this.cardNumber = 216; + this.expansionSetCode = "8ED"; + this.rarity = Rarity.RARE; + } + + public RukhEgg(final RukhEgg card) { + super(card); + } + + @Override + public RukhEgg copy() { + return new RukhEgg(this); + } +} diff --git a/Mage.Sets/src/mage/sets/ninthedition/RukhEgg.java b/Mage.Sets/src/mage/sets/ninthedition/RukhEgg.java new file mode 100644 index 0000000000..511c5a81db --- /dev/null +++ b/Mage.Sets/src/mage/sets/ninthedition/RukhEgg.java @@ -0,0 +1,54 @@ +/* + * 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.ninthedition; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author anonymous + */ +public class RukhEgg extends mage.sets.arabiannights.RukhEgg { + + public RukhEgg(UUID ownerId) { + super(ownerId); + this.cardNumber = 214; + this.expansionSetCode = "9ED"; + this.rarity = Rarity.RARE; + } + + public RukhEgg(final RukhEgg card) { + super(card); + } + + @Override + public RukhEgg copy() { + return new RukhEgg(this); + } +} From 6acfeadd2199119dc564a2819114f67b157dc009 Mon Sep 17 00:00:00 2001 From: Luna Skyrise Date: Sun, 10 May 2015 23:49:28 -0300 Subject: [PATCH 10/37] [FUT] Added Homing Sliver --- .../mage/sets/futuresight/HomingSliver.java | 112 ++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/futuresight/HomingSliver.java diff --git a/Mage.Sets/src/mage/sets/futuresight/HomingSliver.java b/Mage.Sets/src/mage/sets/futuresight/HomingSliver.java new file mode 100644 index 0000000000..c8e91fb4b5 --- /dev/null +++ b/Mage.Sets/src/mage/sets/futuresight/HomingSliver.java @@ -0,0 +1,112 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.futuresight; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.common.DiscardSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.continuous.GainAbilityAllEffect; +import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect; +import mage.abilities.keyword.CyclingAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.filter.FilterPermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.target.common.TargetCardInLibrary; + +/** + * + * @author anonymous + */ +public class HomingSliver extends CardImpl { + + private static final FilterCard filter = new FilterCard("Sliver card"); + + static { + filter.add(new SubtypePredicate("Sliver")); + } + + private static final FilterPermanent filter2 = new FilterPermanent("Sliver card"); + + static { + filter2.add(new SubtypePredicate("Sliver")); + } + + public HomingSliver(UUID ownerId) { + super(ownerId, 118, "Homing Sliver", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{2}{R}"); + this.expansionSetCode = "FUT"; + this.subtype.add("Sliver"); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Each Sliver card in each player's hand has slivercycling {3}. + Ability ability = new CyclingAbility(new ManaCostsImpl("{3}"), filter, "Slivercycling"); + ability.addCost(new DiscardSourceCost()); + this.addAbility(new SimpleStaticAbility(Zone.HAND, new GainAbilityAllEffect(ability, Duration.WhileOnBattlefield, filter2))); + // Slivercycling {3} + this.addAbility(ability); + /** + * 01/02/2009 Slivercycling is a form of cycling. Any ability that + * triggers on a card being cycled also triggers on Slivercycling this + * card. Any ability that stops a cycling ability from being activated + * also stops Plainscycling from being activated. + */ + + /** + * 01/02/2009 Slivercycling is an activated ability. Effects that + * interact with activated abilities (such as Stifle or Rings of + * Brighthearth) will interact with Slivercycling. Effects that interact + * with spells (such as Remove Soul or Faerie Tauntings) will not. + */ + + /** + * 01/02/2009 You can choose to find any card with the Sliver creature + * type, even if it isn't a creature card. This includes, for example, + * Tribal cards with the Changeling ability. You can also choose not to + * find a card, even if there is a Sliver card in your graveyard. + * + */ + } + + public HomingSliver(final HomingSliver card) { + super(card); + } + + @Override + public HomingSliver copy() { + return new HomingSliver(this); + } +} From dd32411e8398203eb8b20af70dd3f0b483d92820 Mon Sep 17 00:00:00 2001 From: Luna Skyrise Date: Sun, 10 May 2015 23:51:00 -0300 Subject: [PATCH 11/37] [8ED, FEM] Added Orcish Spy... ...and the revealing target player's library effect --- .../mage/sets/eighthedition/OrcishSpy.java | 52 +++++++++ .../mage/sets/fallenempires/OrcishSpy.java | 69 ++++++++++++ .../RevealTargetPlayerLibraryEffect.java | 100 ++++++++++++++++++ 3 files changed, 221 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/eighthedition/OrcishSpy.java create mode 100644 Mage.Sets/src/mage/sets/fallenempires/OrcishSpy.java create mode 100644 Mage/src/mage/abilities/effects/common/RevealTargetPlayerLibraryEffect.java diff --git a/Mage.Sets/src/mage/sets/eighthedition/OrcishSpy.java b/Mage.Sets/src/mage/sets/eighthedition/OrcishSpy.java new file mode 100644 index 0000000000..8dc7c9a562 --- /dev/null +++ b/Mage.Sets/src/mage/sets/eighthedition/OrcishSpy.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.eighthedition; + +import java.util.UUID; + +/** + * + * @author anonymous + */ +public class OrcishSpy extends mage.sets.fallenempires.OrcishSpy { + + public OrcishSpy(UUID ownerId) { + super(ownerId); + this.cardNumber = 208; + this.expansionSetCode = "8ED"; + } + + public OrcishSpy(final OrcishSpy card) { + super(card); + } + + @Override + public OrcishSpy copy() { + return new OrcishSpy(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fallenempires/OrcishSpy.java b/Mage.Sets/src/mage/sets/fallenempires/OrcishSpy.java new file mode 100644 index 0000000000..1df6be2d05 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fallenempires/OrcishSpy.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.fallenempires; + +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.RevealTargetPlayerLibraryEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; + +/** + * + * @author anonymous + */ +public class OrcishSpy extends CardImpl { + + public OrcishSpy(UUID ownerId) { + super(ownerId, 124, "Orcish Spy", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{R}"); + this.expansionSetCode = "FEM"; + this.subtype.add("Orc"); + this.subtype.add("Rogue"); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // {tap}: Look at the top three cards of target player's library. + Ability ability = new SimpleActivatedAbility(Zone.LIBRARY, new RevealTargetPlayerLibraryEffect(3), new TapSourceCost()); + this.addAbility(ability); + } + + public OrcishSpy(final OrcishSpy card) { + super(card); + } + + @Override + public OrcishSpy copy() { + return new OrcishSpy(this); + } +} + diff --git a/Mage/src/mage/abilities/effects/common/RevealTargetPlayerLibraryEffect.java b/Mage/src/mage/abilities/effects/common/RevealTargetPlayerLibraryEffect.java new file mode 100644 index 0000000000..c2a40e7970 --- /dev/null +++ b/Mage/src/mage/abilities/effects/common/RevealTargetPlayerLibraryEffect.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.abilities.effects.common; + +import mage.abilities.Ability; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.OneShotEffect; +import mage.cards.Card; +import mage.cards.Cards; +import mage.cards.CardsImpl; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.game.Game; +import mage.players.Player; +import mage.util.CardUtil; + +/** + * + * @author anonymous + */ + +public class RevealTargetPlayerLibraryEffect extends OneShotEffect { + + private DynamicValue amountCards; + + public RevealTargetPlayerLibraryEffect(int amountCards) { + this(new StaticValue(amountCards)); + } + + public RevealTargetPlayerLibraryEffect(DynamicValue amountCards) { + super(Outcome.Neutral); + this.amountCards = amountCards; + this.staticText = setText(); + } + + public RevealTargetPlayerLibraryEffect(final RevealTargetPlayerLibraryEffect effect) { + super(effect); + this.amountCards = effect.amountCards; + } + + @Override + public RevealTargetPlayerLibraryEffect copy() { + return new RevealTargetPlayerLibraryEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + Player targetPlayer = game.getPlayer(source.getFirstTarget()); + + if (player == null || targetPlayer == null) { + return false; + } + + Cards cards = new CardsImpl(Zone.LIBRARY); + int count = Math.min(targetPlayer.getLibrary().size(), amountCards.calculate(game, source, this)); + for (int i = 0; i < count; i++) { + Card card = targetPlayer.getLibrary().removeFromTop(game); + if (card != null) { + cards.add(card); + } + } + + player.lookAtCards("Top " + amountCards.toString() + "cards of " + targetPlayer.getName() + "\'s library", cards, game); + + return true; + } + + private String setText() { + StringBuilder sb = new StringBuilder("Reveal the top "); + sb.append(CardUtil.numberToText(amountCards.toString())).append(" cards of target player's library."); + return sb.toString(); + } +} From fce9f8a1a766cc3f26273679e4e704beff349cd0 Mon Sep 17 00:00:00 2001 From: Luna Skyrise Date: Sun, 10 May 2015 23:53:18 -0300 Subject: [PATCH 12/37] [ME4, 5ED, 4ED, 3ED, 2ED, LEB, LEA] Added Instill Energy --- .../mage/sets/fifthedition/InstillEnergy.java | 196 ++++++++++++++++++ .../sets/fourthedition/InstillEnergy.java | 52 +++++ .../mage/sets/limitedalpha/InstillEnergy.java | 52 +++++ .../mage/sets/limitedbeta/InstillEnergy.java | 52 +++++ .../sets/masterseditioniv/InstillEnergy.java | 52 +++++ .../sets/revisededition/InstillEnergy.java | 52 +++++ .../sets/unlimitededition/InstillEnergy.java | 52 +++++ 7 files changed, 508 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/fifthedition/InstillEnergy.java create mode 100644 Mage.Sets/src/mage/sets/fourthedition/InstillEnergy.java create mode 100644 Mage.Sets/src/mage/sets/limitedalpha/InstillEnergy.java create mode 100644 Mage.Sets/src/mage/sets/limitedbeta/InstillEnergy.java create mode 100644 Mage.Sets/src/mage/sets/masterseditioniv/InstillEnergy.java create mode 100644 Mage.Sets/src/mage/sets/revisededition/InstillEnergy.java create mode 100644 Mage.Sets/src/mage/sets/unlimitededition/InstillEnergy.java diff --git a/Mage.Sets/src/mage/sets/fifthedition/InstillEnergy.java b/Mage.Sets/src/mage/sets/fifthedition/InstillEnergy.java new file mode 100644 index 0000000000..69bf026c43 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fifthedition/InstillEnergy.java @@ -0,0 +1,196 @@ +/* + * 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.fifthedition; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.ActivateIfConditionActivatedAbility; +import mage.abilities.common.LimitedTimesPerTurnActivatedAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.common.SimpleTriggeredAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.MyTurnCondition; +import mage.abilities.costs.Cost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.UntapEnchantedEffect; +import mage.abilities.effects.common.UntapSourceEffect; +import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; +import mage.abilities.keyword.EnchantAbility; +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; +import mage.game.Game; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; +import mage.util.CardUtil; + +/** + * + * @author anonymous + */ +public class InstillEnergy extends CardImpl { + + public InstillEnergy(UUID ownerId) { + super(ownerId, 166, "Instill Energy", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT}, "{G}"); + this.expansionSetCode = "5ED"; + this.subtype.add("Aura"); + + // Enchant creature + 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 can attack as though it had haste. + Ability haste = new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(HasteAbility.getInstance(), AttachmentType.AURA, Duration.Custom, "Enchanted creature can attack as though it had haste.")); + this.addAbility(haste); + // {0}: Untap enchanted creature. Activate this ability only during your turn and only once each turn. + Ability gainedAbility = new LimitedTimesIfConditionActivatedAbility(Zone.BATTLEFIELD, new UntapEnchantedEffect(), new GenericManaCost(0), MyTurnCondition.getInstance(), 1); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(gainedAbility, AttachmentType.AURA, Duration.WhileOnBattlefield, "{0}: Untap enchanted creature. Activate this ability only during your turn and only once each turn."))); + } + + public InstillEnergy(final InstillEnergy card) { + super(card); + } + + @Override + public InstillEnergy copy() { + return new InstillEnergy(this); + } +} + +class LimitedTimesIfConditionActivatedAbility extends ActivateIfConditionActivatedAbility { + + class ActivationInfo { + + public int turnNum; + public int activationCounter; + + public ActivationInfo(int turnNum, int activationCounter) { + this.turnNum = turnNum; + this.activationCounter = activationCounter; + } + } + + private int maxActivationsPerTurn; + + public LimitedTimesIfConditionActivatedAbility(Zone zone, Effect effect, Cost cost, Condition condition) { + this(zone, effect, cost, condition, 1); + } + + public LimitedTimesIfConditionActivatedAbility(Zone zone, Effect effect, Cost cost, Condition condition, int maxActivationsPerTurn) { + super(zone, effect, cost, condition); + this.maxActivationsPerTurn = maxActivationsPerTurn; + } + + public LimitedTimesIfConditionActivatedAbility(LimitedTimesIfConditionActivatedAbility ability) { + super(ability); + this.maxActivationsPerTurn = ability.maxActivationsPerTurn; + } + + @Override + public boolean canActivate(UUID playerId, Game game) { + if (super.canActivate(playerId, game)) { + ActivationInfo activationInfo = getActivationInfo(game); + return activationInfo == null || activationInfo.turnNum != game.getTurnNum() || activationInfo.activationCounter < maxActivationsPerTurn; + } + return false; + } + + @Override + public boolean activate(Game game, boolean noMana) { + if (canActivate(this.controllerId, game)) { + if (super.activate(game, noMana)) { + ActivationInfo activationInfo = getActivationInfo(game); + if (activationInfo == null) { + activationInfo = new ActivationInfo(game.getTurnNum(), 1); + } else { + if (activationInfo.turnNum != game.getTurnNum()) { + activationInfo.turnNum = game.getTurnNum(); + activationInfo.activationCounter = 1; + } else { + activationInfo.activationCounter++; + } + } + setActivationInfo(activationInfo, game); + return true; + } + } + return false; + } + + @Override + public boolean resolve(Game game) { + return super.resolve(game); + } + + @Override + public String getRule() { + StringBuilder sb = new StringBuilder(super.getRule()); + sb.replace(sb.length()-1, sb.length() -1, " and "); //suppress super()'s final period + switch(maxActivationsPerTurn) { + case 1: + sb.append("only once"); + break; + case 2: + sb.append("no more than twice"); + break; + default: + sb.append("no more than ").append(CardUtil.numberToText(maxActivationsPerTurn)).append(" times"); + } + sb.append(" each turn."); + return sb.toString(); + } + + @Override + public LimitedTimesIfConditionActivatedAbility copy() { + return new LimitedTimesIfConditionActivatedAbility(this); + } + + private ActivationInfo getActivationInfo(Game game) { + Integer turnNum = (Integer) game.getState().getValue(CardUtil.getCardZoneString("activationsTurn", sourceId, game)); + Integer activationCount = (Integer) game.getState().getValue(CardUtil.getCardZoneString("activationsCount", sourceId, game)); + if (turnNum == null || activationCount == null) { + return null; + } + return new ActivationInfo(turnNum, activationCount); + } + + private void setActivationInfo(ActivationInfo activationInfo, Game game) { + game.getState().setValue(CardUtil.getCardZoneString("activationsTurn", sourceId, game), activationInfo.turnNum); + game.getState().setValue(CardUtil.getCardZoneString("activationsCount", sourceId, game), activationInfo.activationCounter); + } +} diff --git a/Mage.Sets/src/mage/sets/fourthedition/InstillEnergy.java b/Mage.Sets/src/mage/sets/fourthedition/InstillEnergy.java new file mode 100644 index 0000000000..da00f2a861 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fourthedition/InstillEnergy.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.fourthedition; + +import java.util.UUID; + +/** + * + * @author anonymous + */ +public class InstillEnergy extends mage.sets.fifthedition.InstillEnergy { + + public InstillEnergy(UUID ownerId) { + super(ownerId); + this.cardNumber = 136; + this.expansionSetCode = "4ED"; + } + + public InstillEnergy(final InstillEnergy card) { + super(card); + } + + @Override + public InstillEnergy copy() { + return new InstillEnergy(this); + } +} diff --git a/Mage.Sets/src/mage/sets/limitedalpha/InstillEnergy.java b/Mage.Sets/src/mage/sets/limitedalpha/InstillEnergy.java new file mode 100644 index 0000000000..8e897863c1 --- /dev/null +++ b/Mage.Sets/src/mage/sets/limitedalpha/InstillEnergy.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.limitedalpha; + +import java.util.UUID; + +/** + * + * @author anonymous + */ +public class InstillEnergy extends mage.sets.fifthedition.InstillEnergy { + + public InstillEnergy(UUID ownerId) { + super(ownerId); + this.cardNumber = 111; + this.expansionSetCode = "LEA"; + } + + public InstillEnergy(final InstillEnergy card) { + super(card); + } + + @Override + public InstillEnergy copy() { + return new InstillEnergy(this); + } +} diff --git a/Mage.Sets/src/mage/sets/limitedbeta/InstillEnergy.java b/Mage.Sets/src/mage/sets/limitedbeta/InstillEnergy.java new file mode 100644 index 0000000000..f5f3e6d886 --- /dev/null +++ b/Mage.Sets/src/mage/sets/limitedbeta/InstillEnergy.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.limitedbeta; + +import java.util.UUID; + +/** + * + * @author anonymous + */ +public class InstillEnergy extends mage.sets.fifthedition.InstillEnergy { + + public InstillEnergy(UUID ownerId) { + super(ownerId); + this.cardNumber = 111; + this.expansionSetCode = "LEB"; + } + + public InstillEnergy(final InstillEnergy card) { + super(card); + } + + @Override + public InstillEnergy copy() { + return new InstillEnergy(this); + } +} diff --git a/Mage.Sets/src/mage/sets/masterseditioniv/InstillEnergy.java b/Mage.Sets/src/mage/sets/masterseditioniv/InstillEnergy.java new file mode 100644 index 0000000000..c33c70f7b0 --- /dev/null +++ b/Mage.Sets/src/mage/sets/masterseditioniv/InstillEnergy.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.masterseditioniv; + +import java.util.UUID; + +/** + * + * @author anonymous + */ +public class InstillEnergy extends mage.sets.fifthedition.InstillEnergy { + + public InstillEnergy(UUID ownerId) { + super(ownerId); + this.cardNumber = 157; + this.expansionSetCode = "ME4"; + } + + public InstillEnergy(final InstillEnergy card) { + super(card); + } + + @Override + public InstillEnergy copy() { + return new InstillEnergy(this); + } +} diff --git a/Mage.Sets/src/mage/sets/revisededition/InstillEnergy.java b/Mage.Sets/src/mage/sets/revisededition/InstillEnergy.java new file mode 100644 index 0000000000..c961e331c3 --- /dev/null +++ b/Mage.Sets/src/mage/sets/revisededition/InstillEnergy.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.revisededition; + +import java.util.UUID; + +/** + * + * @author anonymous + */ +public class InstillEnergy extends mage.sets.fifthedition.InstillEnergy { + + public InstillEnergy(UUID ownerId) { + super(ownerId); + this.cardNumber = 110; + this.expansionSetCode = "3ED"; + } + + public InstillEnergy(final InstillEnergy card) { + super(card); + } + + @Override + public InstillEnergy copy() { + return new InstillEnergy(this); + } +} diff --git a/Mage.Sets/src/mage/sets/unlimitededition/InstillEnergy.java b/Mage.Sets/src/mage/sets/unlimitededition/InstillEnergy.java new file mode 100644 index 0000000000..bc4265aae0 --- /dev/null +++ b/Mage.Sets/src/mage/sets/unlimitededition/InstillEnergy.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.unlimitededition; + +import java.util.UUID; + +/** + * + * @author anonymous + */ +public class InstillEnergy extends mage.sets.fifthedition.InstillEnergy { + + public InstillEnergy(UUID ownerId) { + super(ownerId); + this.cardNumber = 111; + this.expansionSetCode = "2ED"; + } + + public InstillEnergy(final InstillEnergy card) { + super(card); + } + + @Override + public InstillEnergy copy() { + return new InstillEnergy(this); + } +} From ab773ab509739c15d6bb0e39a1e0684f0d6f1b0f Mon Sep 17 00:00:00 2001 From: Luna Skyrise Date: Sun, 10 May 2015 23:54:05 -0300 Subject: [PATCH 13/37] [10E, USG] Added No Rest for the Wicked and test --- .../sets/tenthedition/NoRestForTheWicked.java | 52 +++++++ .../sets/urzassaga/NoRestForTheWicked.java | 144 ++++++++++++++++++ .../cards/single/NoRestForTheWickedTest.java | 128 ++++++++++++++++ 3 files changed, 324 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/tenthedition/NoRestForTheWicked.java create mode 100644 Mage.Sets/src/mage/sets/urzassaga/NoRestForTheWicked.java create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/single/NoRestForTheWickedTest.java diff --git a/Mage.Sets/src/mage/sets/tenthedition/NoRestForTheWicked.java b/Mage.Sets/src/mage/sets/tenthedition/NoRestForTheWicked.java new file mode 100644 index 0000000000..0b266f3776 --- /dev/null +++ b/Mage.Sets/src/mage/sets/tenthedition/NoRestForTheWicked.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.tenthedition; + +import java.util.UUID; + +/** + * + * @author anonymous + */ +public class NoRestForTheWicked extends mage.sets.urzassaga.NoRestForTheWicked { + + public NoRestForTheWicked(UUID ownerId) { + super(ownerId); + this.cardNumber = 165; + this.expansionSetCode = "10E"; + } + + public NoRestForTheWicked(final NoRestForTheWicked card) { + super(card); + } + + @Override + public NoRestForTheWicked copy() { + return new NoRestForTheWicked(this); + } +} diff --git a/Mage.Sets/src/mage/sets/urzassaga/NoRestForTheWicked.java b/Mage.Sets/src/mage/sets/urzassaga/NoRestForTheWicked.java new file mode 100644 index 0000000000..887f9aa043 --- /dev/null +++ b/Mage.Sets/src/mage/sets/urzassaga/NoRestForTheWicked.java @@ -0,0 +1,144 @@ +/* + * 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.urzassaga; + +import java.util.ArrayList; +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +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.WatcherScope; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.ZoneChangeEvent; +import mage.watchers.Watcher; + +/** + * + * @author anonymous + */ +public class NoRestForTheWicked extends CardImpl { + + public NoRestForTheWicked(UUID ownerId) { + super(ownerId, 142, "No Rest for the Wicked", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT}, "{1}{B}"); + this.expansionSetCode = "USG"; + + // Sacrifice No Rest for the Wicked: Return to your hand all creature cards in your graveyard that were put there from the battlefield this turn. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new NoRestForTheWickedEffect(), new SacrificeSourceCost()); + Watcher watcher = new NoRestForTheWickedWatcher(); + addAbility(ability, watcher); + } + + public NoRestForTheWicked(final NoRestForTheWicked card) { + super(card); + } + + @Override + public NoRestForTheWicked copy() { + return new NoRestForTheWicked(this); + } +} + +class NoRestForTheWickedEffect extends OneShotEffect { + + NoRestForTheWickedEffect() { + super(Outcome.Sacrifice); + staticText = "Return to your hand all creature cards in your graveyard that were put there from the battlefield this turn"; + } + + NoRestForTheWickedEffect(final NoRestForTheWickedEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + NoRestForTheWickedWatcher watcher = (NoRestForTheWickedWatcher) game.getState().getWatchers().get("NoRestForTheWickedWatcher"); + if (watcher != null) { + for (UUID id : watcher.cards) { + Card c = game.getCard(id); + if (c != null) { + if (game.getState().getZone(id) == Zone.GRAVEYARD) { + if (c.getCardType().contains(CardType.CREATURE) && c.getOwnerId().equals(source.getControllerId())) { + //400.3 + c.moveToZone(Zone.HAND, source.getSourceId(), game, false); + } + } + } + } + return true; + } + return false; + } + + @Override + public NoRestForTheWickedEffect copy() { + return new NoRestForTheWickedEffect(this); + } +} + +class NoRestForTheWickedWatcher extends Watcher { + + ArrayList cards = new ArrayList(); + + public NoRestForTheWickedWatcher() { + super("NoRestForTheWickedWatcher", WatcherScope.GAME); + } + + public NoRestForTheWickedWatcher(final NoRestForTheWickedWatcher watcher) { + super(watcher); + this.cards.addAll(watcher.cards); + } + + @Override + public void watch(GameEvent event, Game game) { + if (event.getType() == GameEvent.EventType.ZONE_CHANGE + && ((ZoneChangeEvent) event).isDiesEvent() + && ((ZoneChangeEvent) event).getPlayerId().equals(this.getControllerId())) { + //400.3 Intercept only the controller's events + cards.add(event.getTargetId()); + } + } + + @Override + public NoRestForTheWickedWatcher copy() { + return new NoRestForTheWickedWatcher(this); + } + + @Override + public void reset() { + super.reset(); + cards.clear(); + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/NoRestForTheWickedTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/NoRestForTheWickedTest.java new file mode 100644 index 0000000000..d8373052e7 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/NoRestForTheWickedTest.java @@ -0,0 +1,128 @@ +/* + * 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 org.mage.test.cards.single; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * @author anonymous + */ +public class NoRestForTheWickedTest extends CardTestPlayerBase { + + /** + * Checks that all playerA creatures are back to playerA's hand + */ + //@Test + public void testSacrifice() { + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 4); + addCard(Zone.HAND, playerA, "No Rest for the Wicked"); + + addCard(Zone.BATTLEFIELD, playerA, "Memnite"); + addCard(Zone.BATTLEFIELD, playerA, "Royal Assassin"); + addCard(Zone.BATTLEFIELD, playerA, "Sengir Vampire"); + + addCard(Zone.BATTLEFIELD, playerB, "Island"); + addCard(Zone.BATTLEFIELD, playerB, "Flowering Lumberknot"); + addCard(Zone.BATTLEFIELD, playerB, "Moorland Inquisitor"); + + castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, "No Rest for the Wicked"); + + attack(3, playerA, "Memnite"); + attack(3, playerA, "Royal Assassin"); + attack(3, playerA, "Sengin Vampire"); + block(3, playerB, "Moorland Inquisitor", "Memnite"); + + activateAbility(3, PhaseStep.POSTCOMBAT_MAIN, playerA, "Sacrifice {this}: Return to your hand all creature cards in your graveyard that were put there from the battlefield this turn."); + + setStopAt(3, PhaseStep.END_TURN); + execute(); + + assertGraveyardCount(playerA, 1); //No Rest only + assertGraveyardCount(playerA, "No Rest for the Wicked", 1); + assertGraveyardCount(playerA, "Memnite", 0); + assertHandCount(playerA, "Memnite", 1); + } + + /** + * Checks that all playerA creatures sacrificed prior to playing + * No Rest for the Wicked are back to playerA's hand + */ + //@Test + public void testSacrificeAfterDying() { + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 4); + addCard(Zone.HAND, playerA, "No Rest for the Wicked"); + + addCard(Zone.BATTLEFIELD, playerA, "Memnite"); + addCard(Zone.BATTLEFIELD, playerA, "Royal Assassin"); + addCard(Zone.BATTLEFIELD, playerA, "Sengir Vampire"); + + addCard(Zone.BATTLEFIELD, playerB, "Island"); + addCard(Zone.BATTLEFIELD, playerB, "Flowering Lumberknot"); + addCard(Zone.BATTLEFIELD, playerB, "Moorland Inquisitor"); + + attack(3, playerA, "Memnite"); + attack(3, playerA, "Royal Assassin"); + attack(3, playerA, "Sengin Vampire"); + block(3, playerB, "Moorland Inquisitor", "Memnite"); + + castSpell(3, PhaseStep.POSTCOMBAT_MAIN, playerA, "No Rest for the Wicked"); + + activateAbility(3, PhaseStep.POSTCOMBAT_MAIN, playerA, "Sacrifice {this}: Return to your hand all creature cards in your graveyard that were put there from the battlefield this turn."); + + setStopAt(3, PhaseStep.END_TURN); + execute(); + + assertPermanentCount(playerA, "No Rest for the Wicked", 0); + assertGraveyardCount(playerA, 1); //No Rest only + assertGraveyardCount(playerA, "No Rest for the Wicked", 1); + assertGraveyardCount(playerA, "Memnite", 0); + assertHandCount(playerA, "Memnite", 1); + } + + /** + * Take ownership of a creature from playerB and destroy it. + * Checks that after sacrificing No Rest for the Wicked it is on playerB's + * graveyard, and that it's not on either player's hand. + * 400.3 + */ + @Test + public void testTakeControlThenSacrifice() { + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 7); + addCard(Zone.HAND, playerA, "No Rest for the Wicked"); + addCard(Zone.HAND, playerA, "Beacon of Unrest"); + + addCard(Zone.BATTLEFIELD, playerA, "Moorland Inquisitor"); + + addCard(Zone.BATTLEFIELD, playerB, "Moorland Inquisitor"); + addCard(Zone.BATTLEFIELD, playerB, "Memnite"); + + castSpell(3, PhaseStep.POSTCOMBAT_MAIN, playerA, "No Rest for the Wicked"); + + attack(4, playerB, "Memnite"); + block(4, playerA, "Moorland Inquisitor", "Memnite"); + + castSpell(5, PhaseStep.POSTCOMBAT_MAIN, playerA, "Beacon of Unrest", "Memnite"); + + attack(7, playerA, "Memnite"); + block(7, playerB, "Moorland Inquisitor", "Memnite"); + activateAbility(7, PhaseStep.POSTCOMBAT_MAIN, playerA, "Sacrifice {this}: Return to your hand all creature cards in your graveyard that were put there from the battlefield this turn."); + + setStopAt(7, PhaseStep.END_TURN); + execute(); + + assertGraveyardCount(playerB, "Memnite", 1); + assertHandCount(playerB, "Memnite", 0); + + assertPermanentCount(playerA, "No Rest for the Wicked", 0); + assertGraveyardCount(playerA, 1); //No Rest only + assertGraveyardCount(playerA, "No Rest for the Wicked", 1); + assertGraveyardCount(playerA, "Memnite", 0); + assertHandCount(playerA, "Memnite", 0); + } +} From ab6105d09e3f9d25fc011d2a75ab4640118d1dc3 Mon Sep 17 00:00:00 2001 From: Luna Skyrise Date: Sun, 10 May 2015 23:57:13 -0300 Subject: [PATCH 14/37] [TOR] Added Rancid Earth --- .../src/mage/sets/torment/RancidEarth.java | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/torment/RancidEarth.java diff --git a/Mage.Sets/src/mage/sets/torment/RancidEarth.java b/Mage.Sets/src/mage/sets/torment/RancidEarth.java new file mode 100644 index 0000000000..78afb2b783 --- /dev/null +++ b/Mage.Sets/src/mage/sets/torment/RancidEarth.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.torment; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.condition.common.CardsInControllerGraveCondition; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DamageEverythingEffect; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.game.Game; +import mage.target.common.TargetLandPermanent; + +/** + * + * @author anonymous + */ +public class RancidEarth extends CardImpl { + + public RancidEarth(UUID ownerId) { + super(ownerId, 78, "Rancid Earth", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{1}{B}{B}"); + this.expansionSetCode = "TOR"; + + // Destroy target land. + // Threshold - If seven or more cards are in your graveyard, instead destroy that land and Rancid Earth deals 1 damage to each creature and each player. + this.getSpellAbility().addEffect(new ConditionalOneShotEffect( + new RancidEarthEffect(), + new DestroyTargetEffect(), + new CardsInControllerGraveCondition(7), + "Destroy target land.

Threshold - If seven or more cards are in your graveyard, instead destroy that land and Rancid Earth deals 1 damage to each creature and each player")); + this.getSpellAbility().addTarget(new TargetLandPermanent()); + } + + public RancidEarth(final RancidEarth card) { + super(card); + } + + @Override + public RancidEarth copy() { + return new RancidEarth(this); + } +} + +class RancidEarthEffect extends OneShotEffect { + + public RancidEarthEffect() { + super(Outcome.DestroyPermanent); + this.staticText = "destroy that land and Rancid Earth deals 1 damage to each creature and each player"; + } + + public RancidEarthEffect(final RancidEarthEffect effect) { + super(effect); + } + + @Override + public RancidEarthEffect copy() { + return new RancidEarthEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Effect effect1 = new DestroyTargetEffect("destroy that land"); + if (effect1.apply(game, source)) { + return new DamageEverythingEffect(1).apply(game, source); + } + + return false; + } +} From 71fc740c042564f868c494945fe2dfbbff5be0c9 Mon Sep 17 00:00:00 2001 From: Luna Skyrise Date: Sun, 10 May 2015 23:57:49 -0300 Subject: [PATCH 15/37] [FUT] Added Lymph Sliver --- .../mage/sets/futuresight/LymphSliver.java | 117 ++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/futuresight/LymphSliver.java diff --git a/Mage.Sets/src/mage/sets/futuresight/LymphSliver.java b/Mage.Sets/src/mage/sets/futuresight/LymphSliver.java new file mode 100644 index 0000000000..528e97515a --- /dev/null +++ b/Mage.Sets/src/mage/sets/futuresight/LymphSliver.java @@ -0,0 +1,117 @@ +/* + * 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.futuresight; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.PreventionEffectImpl; +import mage.abilities.effects.common.continuous.GainAbilityAllEffect; +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.game.Game; +import mage.game.events.GameEvent; + +/** + * + * @author anonymous + */ +public class LymphSliver extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Sliver", "All Sliver creatures"); + + public LymphSliver(UUID ownerId) { + super(ownerId, 26, "Lymph Sliver", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{4}{W}"); + this.expansionSetCode = "FUT"; + this.subtype.add("Sliver"); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // All Sliver creatures have absorb 1. + Ability absorb = new SimpleStaticAbility(Zone.BATTLEFIELD, new SliverAbsorbEffect()); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAllEffect(absorb, Duration.WhileOnBattlefield, filter))); + } + + public LymphSliver(final LymphSliver card) { + super(card); + } + + @Override + public LymphSliver copy() { + return new LymphSliver(this); + } +} + +class SliverAbsorbEffect extends PreventionEffectImpl { + //From Urza's Armor + public SliverAbsorbEffect() { + super(Duration.WhileOnBattlefield); + this.staticText = "If a source would deal damage to a Sliver, prevent 1 of that damage"; + } + + public SliverAbsorbEffect(SliverAbsorbEffect effect) { + super(effect); + } + + @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; + } + + @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); + } + return false; + } + + @Override + public SliverAbsorbEffect copy() { + return new SliverAbsorbEffect(this); + } +} \ No newline at end of file From 0ec9f8869cb21878ef53c07864b583d94c2dd395 Mon Sep 17 00:00:00 2001 From: Luna Skyrise Date: Sun, 10 May 2015 23:58:55 -0300 Subject: [PATCH 16/37] [PLS, 8ED] Added Shifting Sky --- .../mage/sets/eighthedition/ShiftingSky.java | 54 ++++++++ .../src/mage/sets/planeshift/ShiftingSky.java | 126 ++++++++++++++++++ 2 files changed, 180 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/eighthedition/ShiftingSky.java create mode 100644 Mage.Sets/src/mage/sets/planeshift/ShiftingSky.java diff --git a/Mage.Sets/src/mage/sets/eighthedition/ShiftingSky.java b/Mage.Sets/src/mage/sets/eighthedition/ShiftingSky.java new file mode 100644 index 0000000000..5b94a6eadc --- /dev/null +++ b/Mage.Sets/src/mage/sets/eighthedition/ShiftingSky.java @@ -0,0 +1,54 @@ +/* + * 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.eighthedition; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author anonymous + */ +public class ShiftingSky extends mage.sets.planeshift.ShiftingSky { + + public ShiftingSky(UUID ownerId) { + super(ownerId); + this.cardNumber = 100; + this.expansionSetCode = "8ED"; + this.rarity = Rarity.RARE; + } + + public ShiftingSky(final ShiftingSky card) { + super(card); + } + + @Override + public ShiftingSky copy() { + return new ShiftingSky(this); + } +} diff --git a/Mage.Sets/src/mage/sets/planeshift/ShiftingSky.java b/Mage.Sets/src/mage/sets/planeshift/ShiftingSky.java new file mode 100644 index 0000000000..43677a3dca --- /dev/null +++ b/Mage.Sets/src/mage/sets/planeshift/ShiftingSky.java @@ -0,0 +1,126 @@ +/* + * 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.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.BecomesColorTargetEffect; +import mage.cards.CardImpl; +import mage.choices.ChoiceColor; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.filter.FilterPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author anonymous + */ +public class ShiftingSky extends CardImpl { + + public ShiftingSky(UUID ownerId) { + super(ownerId, 32, "Shifting Sky", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}"); + this.expansionSetCode = "PLS"; + + // As Shifting Sky enters the battlefield, choose a color. + Ability ability = new EntersBattlefieldTriggeredAbility(new ShiftingSkyEffect()); + // All nonland permanents are the chosen color. + this.addAbility(ability); + } + + public ShiftingSky(final ShiftingSky card) { + super(card); + } + + @Override + public ShiftingSky copy() { + return new ShiftingSky(this); + } +} + +class ShiftingSkyEffect extends OneShotEffect { + + public ShiftingSkyEffect() { + super(Outcome.Neutral); + staticText = "All nonland permanents are the chosen color"; + } + + public ShiftingSkyEffect(final ShiftingSkyEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + Permanent permanent = game.getPermanent(source.getSourceId()); + + FilterPermanent filter = new FilterPermanent("All nonland permanents"); + + filter.add( + Predicates.not( + new CardTypePredicate(CardType.LAND) + ) + ); + + if (player != null && permanent != null) { + ChoiceColor colorChoice = new ChoiceColor(); + if (player.choose(Outcome.Neutral, colorChoice, game)) { + game.informPlayers(permanent.getName() + ": " + player.getName() + " has chosen " + colorChoice.getChoice()); + ContinuousEffect effect; + + for (UUID playerId : player.getInRange()) { + Player p = game.getPlayer(playerId); + if (p != null) { + for (Permanent chosen : game.getBattlefield().getAllActivePermanents(filter, playerId, game)) { + effect = new BecomesColorTargetEffect(colorChoice.getColor(), Duration.EndOfTurn, "is " + colorChoice.getChoice()); + effect.setTargetPointer(new FixedTarget(chosen.getId())); + game.addEffect(effect, source); + } + } + } + return true; + } + } + return false; + } + + @Override + public ShiftingSkyEffect copy() { + return new ShiftingSkyEffect(this); + } +} From b0d37ab7a6493083f88bdc9a52372b7bdcb687df Mon Sep 17 00:00:00 2001 From: Luna Skyrise Date: Sun, 10 May 2015 23:59:12 -0300 Subject: [PATCH 17/37] [PLS, 8ED] Added Star Compass --- .../mage/sets/eighthedition/StarCompass.java | 236 ++++++++++++++++++ .../src/mage/sets/planeshift/StarCompass.java | 52 ++++ 2 files changed, 288 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/eighthedition/StarCompass.java create mode 100644 Mage.Sets/src/mage/sets/planeshift/StarCompass.java diff --git a/Mage.Sets/src/mage/sets/eighthedition/StarCompass.java b/Mage.Sets/src/mage/sets/eighthedition/StarCompass.java new file mode 100644 index 0000000000..dad4627b46 --- /dev/null +++ b/Mage.Sets/src/mage/sets/eighthedition/StarCompass.java @@ -0,0 +1,236 @@ +/* + * 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.eighthedition; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import mage.Mana; +import mage.abilities.Abilities; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTappedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.common.ManaEffect; +import mage.abilities.mana.ManaAbility; +import mage.cards.CardImpl; +import mage.choices.Choice; +import mage.choices.ChoiceImpl; +import mage.constants.CardType; +import mage.constants.ColoredManaSymbol; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterControlledLandPermanent; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.mageobject.SupertypePredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; + +/** + * + * @author anonymous + */ +public class StarCompass extends CardImpl { + + public StarCompass(UUID ownerId) { + super(ownerId, 315, "Star Compass", Rarity.UNCOMMON, new CardType[]{CardType.ARTIFACT}, "{2}"); + this.expansionSetCode = "8ED"; + + // Star Compass enters the battlefield tapped. + this.addAbility(new EntersBattlefieldTappedAbility()); + // {tap}: Add to your mana pool one mana of any color that a basic land you control could produce. + this.addAbility(new StarCompassManaAbility()); + } + + public StarCompass(final StarCompass card) { + super(card); + } + + @Override + public StarCompass copy() { + return new StarCompass(this); + } +} + +class StarCompassManaAbility extends ManaAbility { + + public StarCompassManaAbility() { + super(Zone.BATTLEFIELD, new StarCompassManaEffect(),new TapSourceCost()); + } + + public StarCompassManaAbility(final StarCompassManaAbility ability) { + super(ability); + } + + @Override + public StarCompassManaAbility copy() { + return new StarCompassManaAbility(this); + } + + @Override + public List getNetMana(Game game) { + return ((StarCompassManaEffect)getEffects().get(0)).getNetMana(game, this); + } +} + +class StarCompassManaEffect extends ManaEffect { + + private static final FilterControlledPermanent filter = new FilterControlledLandPermanent(); + + static { + filter.add(new SupertypePredicate("Basic")); + } + + public StarCompassManaEffect() { + super(); + staticText = "Add to your mana pool one mana of any type that a basic land you control could produce"; + } + + public StarCompassManaEffect(final StarCompassManaEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Mana types = getManaTypes(game, source); + Choice choice = new ChoiceImpl(false); + choice.setMessage("Pick a mana color"); + if (types.getBlack() > 0) { + choice.getChoices().add("Black"); + } + if (types.getRed() > 0) { + choice.getChoices().add("Red"); + } + if (types.getBlue() > 0) { + choice.getChoices().add("Blue"); + } + if (types.getGreen() > 0) { + choice.getChoices().add("Green"); + } + if (types.getWhite() > 0) { + choice.getChoices().add("White"); + } + if (types.getColorless() > 0) { + choice.getChoices().add("Colorless"); + } + if (types.getAny() > 0) { + choice.getChoices().add("Black"); + choice.getChoices().add("Red"); + choice.getChoices().add("Blue"); + choice.getChoices().add("Green"); + choice.getChoices().add("White"); + choice.getChoices().add("Colorless"); + } + if (choice.getChoices().size() > 0) { + Player player = game.getPlayer(source.getControllerId()); + if (choice.getChoices().size() == 1) { + choice.setChoice(choice.getChoices().iterator().next()); + } else { + player.choose(outcome, choice, game); + } + if (choice.getChoice() != null) { + Mana mana = new Mana(); + switch (choice.getChoice()) { + case "Black": + mana.setBlack(1); + break; + case "Blue": + mana.setBlue(1); + break; + case "Red": + mana.setRed(1); + break; + case "Green": + mana.setGreen(1); + break; + case "White": + mana.setWhite(1); + break; + case "Colorless": + mana.setColorless(1); + break; + } + checkToFirePossibleEvents(mana, game, source); + player.getManaPool().addMana(mana, game, source); + return true; + } + return false; + } + return true; + } + + public List getNetMana(Game game, Ability source) { + List netManas = new ArrayList<>(); + Mana types = getManaTypes(game, source); + if (types.getBlack() > 0) { + netManas.add(new Mana(ColoredManaSymbol.B)); + } + if (types.getRed() > 0) { + netManas.add(new Mana(ColoredManaSymbol.R)); + } + if (types.getBlue() > 0) { + netManas.add(new Mana(ColoredManaSymbol.U)); + } + if (types.getGreen() > 0) { + netManas.add(new Mana(ColoredManaSymbol.G)); + } + if (types.getWhite() > 0) { + netManas.add(new Mana(ColoredManaSymbol.W)); + } + if (types.getColorless() > 0) { + netManas.add(new Mana(0,0,0,0,0,1,0)); + } + return netManas; + } + + private Mana getManaTypes(Game game, Ability source) { + List lands = game.getBattlefield().getActivePermanents(filter, source.getControllerId(), game); + Mana types = new Mana(); + for (Permanent land : lands) { + Abilities manaAbilities = land.getAbilities().getManaAbilities(Zone.BATTLEFIELD); + for (ManaAbility ability : manaAbilities) { + if (!ability.equals(source) && ability.definesMana()) { + for (Mana netMana: ability.getNetMana(game)) { + types.add(netMana); + } + } + } + } + return types; + } + + @Override + public Mana getMana(Game game, Ability source) { + return null; + } + + @Override + public StarCompassManaEffect copy() { + return new StarCompassManaEffect(this); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/planeshift/StarCompass.java b/Mage.Sets/src/mage/sets/planeshift/StarCompass.java new file mode 100644 index 0000000000..6188c95b68 --- /dev/null +++ b/Mage.Sets/src/mage/sets/planeshift/StarCompass.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.planeshift; + +import java.util.UUID; + +/** + * + * @author anonymous + */ +public class StarCompass extends mage.sets.eighthedition.StarCompass { + + public StarCompass(UUID ownerId) { + super(ownerId); + this.cardNumber = 134; + this.expansionSetCode = "PLS"; + } + + public StarCompass(final StarCompass card) { + super(card); + } + + @Override + public StarCompass copy() { + return new StarCompass(this); + } +} From 919cc73e6c2ac9338123fd1f5a802f7d119d41a3 Mon Sep 17 00:00:00 2001 From: Luna Skyrise Date: Mon, 11 May 2015 00:00:09 -0300 Subject: [PATCH 18/37] [TSB, ICE] Added Enduring Renewal --- .../src/mage/sets/iceage/EnduringRenewal.java | 238 ++++++++++++++++++ .../sets/timeshifted/EnduringRenewal.java | 54 ++++ 2 files changed, 292 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/iceage/EnduringRenewal.java create mode 100644 Mage.Sets/src/mage/sets/timeshifted/EnduringRenewal.java diff --git a/Mage.Sets/src/mage/sets/iceage/EnduringRenewal.java b/Mage.Sets/src/mage/sets/iceage/EnduringRenewal.java new file mode 100644 index 0000000000..7309f2f400 --- /dev/null +++ b/Mage.Sets/src/mage/sets/iceage/EnduringRenewal.java @@ -0,0 +1,238 @@ +/* + * 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.iceage; + +import java.util.UUID; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.ReplacementEffectImpl; +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.Layer; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.SubLayer; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.ZoneChangeEvent; +import mage.game.permanent.Permanent; +import mage.players.Player; + +/** + * + * @author anonymous + */ +public class EnduringRenewal extends CardImpl { + + public EnduringRenewal(UUID ownerId) { + super(ownerId, 247, "Enduring Renewal", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}{W}"); + this.expansionSetCode = "ICE"; + + // Play with your hand revealed. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new PlayWithHandRevealedEffect())); + // If you would draw a card, reveal the top card of your library instead. If it's a creature card, put it into your graveyard. Otherwise, draw a card. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new EnduringRenewalReplacementEffect())); + // Whenever a creature is put into your graveyard from the battlefield, return it to your hand. + this.addAbility(new EnduringRenewalTriggeredAbility()); + } + + public EnduringRenewal(final EnduringRenewal card) { + super(card); + } + + @Override + public EnduringRenewal copy() { + return new EnduringRenewal(this); + } +} + +class EnduringRenewalReplacementEffect extends ReplacementEffectImpl { + + public EnduringRenewalReplacementEffect() { + super(Duration.WhileOnBattlefield, Outcome.Benefit); + staticText = "If you would draw a card, reveal the top card of your library instead. If it's a creature card, put it into your graveyard. Otherwise, draw a card"; + } + + public EnduringRenewalReplacementEffect(final EnduringRenewalReplacementEffect effect) { + super(effect); + } + + @Override + public EnduringRenewalReplacementEffect copy() { + return new EnduringRenewalReplacementEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + Player you = game.getPlayer(source.getControllerId()); + if (you == null) { + return false; + } else if (you.getLibrary().size() > 0){ + + Card top = you.getLibrary().removeFromTop(game); + + Cards cards = new CardsImpl(Zone.PICK); + + cards.add(top); + + you.revealCards("Top card of " + you.getName() + "'s library", cards, game); + + if (top.getCardType().contains(CardType.CREATURE)) { + top.moveToZone(Zone.GRAVEYARD, top.getId(), game, true); + } else { + top.moveToZone(Zone.HAND, top.getId(), game, false); + } + + cards.clear(); + + return true; + } + return false; + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DRAW_CARD; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + return event.getPlayerId().equals(source.getControllerId()); + } +} + +class PlayWithHandRevealedEffect extends ContinuousEffectImpl { + + public PlayWithHandRevealedEffect() { + super(Duration.WhileOnBattlefield, Layer.PlayerEffects, SubLayer.NA, Outcome.Detriment); + staticText = "Play with your hand revealed"; + } + + public PlayWithHandRevealedEffect(final PlayWithHandRevealedEffect 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) { + controller.revealCards(controller.getName(), controller.getHand(), game, false); + return true; + } + return false; + } + + @Override + public PlayWithHandRevealedEffect copy() { + return new PlayWithHandRevealedEffect(this); + } +} + +class EnduringRenewalEffect extends OneShotEffect { + + public EnduringRenewalEffect() { + super(Outcome.ReturnToHand); + staticText = "return it to your hand"; + } + + public EnduringRenewalEffect(final EnduringRenewalEffect effect) { + super(effect); + } + + @Override + public EnduringRenewalEffect copy() { + return new EnduringRenewalEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + UUID creatureId = (UUID) getValue("returningCreature"); + Permanent creature = game.getPermanent(creatureId); + if (creature != null) { + Player player = game.getPlayer(source.getControllerId()); + if (player != null) { + creature.moveToZone(Zone.HAND, source.getSourceId(), game, false); + } + return true; + } + return false; + } +} + +class EnduringRenewalTriggeredAbility extends TriggeredAbilityImpl { + + public EnduringRenewalTriggeredAbility() { + super(Zone.BATTLEFIELD, new EnduringRenewalEffect(), false); + } + + public EnduringRenewalTriggeredAbility(EnduringRenewalTriggeredAbility ability) { + super(ability); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getType() == GameEvent.EventType.ZONE_CHANGE + && ((ZoneChangeEvent) event).isDiesEvent() + && ((ZoneChangeEvent) event).getPlayerId().equals(this.getControllerId())) { + Permanent permanent = game.getPermanent(event.getTargetId()); + if (permanent.getCardType().contains(CardType.CREATURE) + && permanent.getControllerId().equals(this.controllerId)) { + Effect effect = this.getEffects().get(0); + effect.setValue("returningCreature", event.getTargetId()); + return true; + } + } + return false; + } + + @Override + public String getRule() { + return "Whenever a creature is put into your graveyard from the battlefield, " + super.getRule(); + } + + @Override + public EnduringRenewalTriggeredAbility copy() { + return new EnduringRenewalTriggeredAbility(this); + } +} diff --git a/Mage.Sets/src/mage/sets/timeshifted/EnduringRenewal.java b/Mage.Sets/src/mage/sets/timeshifted/EnduringRenewal.java new file mode 100644 index 0000000000..e73d30f633 --- /dev/null +++ b/Mage.Sets/src/mage/sets/timeshifted/EnduringRenewal.java @@ -0,0 +1,54 @@ +/* + * 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.timeshifted; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author anonymous + */ +public class EnduringRenewal extends mage.sets.iceage.EnduringRenewal { + + public EnduringRenewal(UUID ownerId) { + super(ownerId); + this.cardNumber = 7; + this.expansionSetCode = "TSB"; + this.rarity = Rarity.SPECIAL; + } + + public EnduringRenewal(final EnduringRenewal card) { + super(card); + } + + @Override + public EnduringRenewal copy() { + return new EnduringRenewal(this); + } +} From 38bfe70961e243f6204771eed495e96f79a3b07a Mon Sep 17 00:00:00 2001 From: Luna Skyrise Date: Mon, 11 May 2015 00:01:20 -0300 Subject: [PATCH 19/37] [SHM] Added Knollspine Invocation --- .../sets/shadowmoor/KnollspineInvocation.java | 166 ++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/shadowmoor/KnollspineInvocation.java diff --git a/Mage.Sets/src/mage/sets/shadowmoor/KnollspineInvocation.java b/Mage.Sets/src/mage/sets/shadowmoor/KnollspineInvocation.java new file mode 100644 index 0000000000..8295f04461 --- /dev/null +++ b/Mage.Sets/src/mage/sets/shadowmoor/KnollspineInvocation.java @@ -0,0 +1,166 @@ +/* + * 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.shadowmoor; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.DiscardCardCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.Filter; +import mage.filter.FilterCard; +import mage.filter.common.FilterOwnedCard; +import mage.filter.predicate.mageobject.ConvertedManaCostPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCreatureOrPlayer; + +/** + * + * @author anonymous + */ +public class KnollspineInvocation extends CardImpl { + + public KnollspineInvocation(UUID ownerId) { + super(ownerId, 99, "Knollspine Invocation", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{1}{R}{R}"); + this.expansionSetCode = "SHM"; + + // {X}, Discard a card with converted mana cost X: Knollspine Invocation deals X damage to target creature or player. + Ability ability = new KnollspineInvocationAbility(); + ability.addTarget(new TargetCreatureOrPlayer()); + this.addAbility(ability); + } + + public KnollspineInvocation(final KnollspineInvocation card) { + super(card); + } + + @Override + public KnollspineInvocation copy() { + return new KnollspineInvocation(this); + } +} + +class KnollspineInvocationAbility extends SimpleActivatedAbility { + public KnollspineInvocationAbility() { + super(Zone.BATTLEFIELD, new KnollspineInvocationEffect(), new ManaCostsImpl("{0}")); + //If cost gets added by ManaCostsImpl.add from ActivatedAbilityImpl constructor, this will destroy our custom mana cost + //Here comes the hack + //A less hacky solution would be to implement this as a ManaCost proper, + //using ManaCostImpl (but it would involve duplicating code from ManaCostsImpl + //and, of course, it would deny access to ManaCostsImpl's API) + this.manaCosts = new KnollspineInvocationAbilityCost("{X}"); + this.manaCostsToPay = this.manaCosts.copy(); + } +} + +class KnollspineInvocationEffect extends OneShotEffect { + //See DrainLife for this class' implementation + + public KnollspineInvocationEffect() { + super(Outcome.Damage); + staticText = "Knollspine Invocation deals X damage to target creature or player"; + } + + public KnollspineInvocationEffect(final KnollspineInvocationEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + int amount = source.getManaCostsToPay().getX(); + if (amount > 0) { + Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); + if (permanent != null ) { + permanent.damage(amount, source.getSourceId(), game, false, true); + } else { + Player player = game.getPlayer(getTargetPointer().getFirst(game, source)); + if (player != null) { + player.damage(amount, source.getSourceId(), game, false, true); + } else { + return false; + } + } + } + return true; + } + + @Override + public KnollspineInvocationEffect copy() { + return new KnollspineInvocationEffect(this); + } +} + +class KnollspineInvocationAbilityCost extends ManaCostsImpl { + protected DiscardCardCost additional; + + public KnollspineInvocationAbilityCost(final KnollspineInvocationAbilityCost cost) { + super(cost); + this.additional = cost.additional; + } + + public KnollspineInvocationAbilityCost (String s) { + super(s); + //we can only apply the additional discard cost AFTER we resolve this one! + FilterCard filter = new FilterOwnedCard("a card with converted mana cost " + super.getText()); + filter.add(new ConvertedManaCostPredicate(Filter.ComparisonType.Equal, super.getX())); + additional = new DiscardCardCost(filter); + } + + @Override + public KnollspineInvocationAbilityCost copy() { + return new KnollspineInvocationAbilityCost(this); + } + + @Override + public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) { + if (super.pay(ability, game, sourceId, controllerId, noMana)) { + //Now we get the real deal + FilterCard filter = new FilterOwnedCard("a card with converted mana cost " + this.getX()); + filter.add(new ConvertedManaCostPredicate(Filter.ComparisonType.Equal, this.getX())); + return new DiscardCardCost(filter).pay(ability, game, sourceId, controllerId, noMana); + } + return false; + } + + @Override + public String getText() { + StringBuilder sb = new StringBuilder(super.getText()); + sb.append(", "); + sb.append(additional.getText()); + System.out.println("Knollspine Invocation tooltip: " + sb.toString()); + return sb.toString(); + } +} \ No newline at end of file From 7338022dd1810b2c09e44d77688eeb192a312400 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Mon, 11 May 2015 12:18:07 +0200 Subject: [PATCH 20/37] * Fixed that cyle triggered abilities did not work. --- .../mage/sets/urzassaga/DiscipleOfGrace.java | 8 +- .../cards/abilities/keywords/CycleTest.java | 117 ++++++++++++++++++ .../common/CycleTriggeredAbility.java | 7 -- Mage/src/mage/players/PlayerImpl.java | 45 ++++--- 4 files changed, 150 insertions(+), 27 deletions(-) create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/CycleTest.java diff --git a/Mage.Sets/src/mage/sets/urzassaga/DiscipleOfGrace.java b/Mage.Sets/src/mage/sets/urzassaga/DiscipleOfGrace.java index d4a5894d25..b271ba2441 100644 --- a/Mage.Sets/src/mage/sets/urzassaga/DiscipleOfGrace.java +++ b/Mage.Sets/src/mage/sets/urzassaga/DiscipleOfGrace.java @@ -46,7 +46,7 @@ import java.util.UUID; */ public class DiscipleOfGrace extends CardImpl { - private static final FilterCard filter = new FilterCard("Black"); + private static final FilterCard filter = new FilterCard("black"); static { filter.add(new ColorPredicate(ObjectColor.BLACK)); @@ -57,10 +57,14 @@ public class DiscipleOfGrace extends CardImpl { this.expansionSetCode = "USG"; this.subtype.add("Human"); this.subtype.add("Cleric"); - this.color.setWhite(true); + this.power = new MageInt(1); this.toughness = new MageInt(2); + + // Protection from black this.addAbility(new ProtectionAbility(filter)); + + // Cycling {2} ({2}, Discard this card: Draw a card.) this.addAbility(new CyclingAbility(new ManaCostsImpl("{2}"))); } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/CycleTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/CycleTest.java new file mode 100644 index 0000000000..a0f1f8e8dd --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/CycleTest.java @@ -0,0 +1,117 @@ +/* + * 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.keywords; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ +public class CycleTest extends CardTestPlayerBase { + + /** + * 702.28. Cycling + * 702.28a Cycling is an activated ability that functions only while the card with cycling is in a player’s hand. + * “Cycling [cost]” means “[Cost], Discard this card: Draw a card.” + * 702.28b Although the cycling ability is playable only if the card is in a player’s hand, it continues to exist + * while the object is in play and in all other zones. Therefore objects with cycling will be affected by + * effects that depend on objects having one or more activated abilities. + * 702.28c Some cards with cycling have abilities that trigger when they’re cycled. “When you cycle [this card]” means + * “When you discard [this card] to pay a cycling cost.” These abilities trigger from whatever zone the card + * winds up in after it’s cycled. + * 702.28d Typecycling is a variant of the cycling ability. “[Type]cycling [cost]” means “[Cost], Discard this card: + * Search your library for a [type] card, reveal it, and put it into your hand. Then shuffle your library.” + * This type is usually a subtype (as in “mountaincycling”) but can be any card type, subtype, supertype, or + * combination thereof (as in “basic landcycling”). + * 702.28e Typecycling abilities are cycling abilities, and typecycling costs are cycling costs. Any cards that trigger + * when a player cycles a card will trigger when a card is discarded to pay a typecycling cost. Any effect that + * stops players from cycling cards will stop players from activating cards’ typecycling abilities. Any effect + * that increases or reduces a cycling cost will increase or reduce a typecycling cost. + */ + + @Test + public void CycleAndTriggerTest() { + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 5); + // Destroy all creatures. They can't be regenerated. Draw a card for each creature destroyed this way. + // Cycling {3}{B}{B} + // When you cycle Decree of Pain, all creatures get -2/-2 until end of turn. + addCard(Zone.HAND, playerA, "Decree of Pain"); + + addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion", 1); + addCard(Zone.BATTLEFIELD, playerB, "Pillarfield Ox", 1); + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cycling {3}{B}{B}"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertHandCount(playerA, 1); + + assertGraveyardCount(playerA, "Decree of Pain", 1); + assertPermanentCount(playerA, "Silvercoat Lion", 0); + + assertPermanentCount(playerB, "Pillarfield Ox", 1); + assertPowerToughness(playerB, "Pillarfield Ox", 0, 2); + + + } + + /** + * Cycle from graveyard or battlefield may not work + */ + @Test + public void CycleFromGraveyard() { + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 5); + // Destroy all creatures. They can't be regenerated. Draw a card for each creature destroyed this way. + // Cycling {3}{B}{B} + // When you cycle Decree of Pain, all creatures get -2/-2 until end of turn. + addCard(Zone.GRAVEYARD, playerA, "Decree of Pain"); + // Protection from black + // Cycling {2} ({2}, Discard this card: Draw a card.) + addCard(Zone.BATTLEFIELD, playerB, "Disciple Of Grace"); + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cycling {3}{B}{B}"); + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Cycling {2}"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertHandCount(playerA, 0); + assertHandCount(playerB, 0); + + assertGraveyardCount(playerA, "Decree of Pain", 1); + assertPermanentCount(playerB, "Disciple Of Grace", 1); + + } + +} diff --git a/Mage/src/mage/abilities/common/CycleTriggeredAbility.java b/Mage/src/mage/abilities/common/CycleTriggeredAbility.java index ea8351356e..537b75691d 100644 --- a/Mage/src/mage/abilities/common/CycleTriggeredAbility.java +++ b/Mage/src/mage/abilities/common/CycleTriggeredAbility.java @@ -28,13 +28,11 @@ package mage.abilities.common; -import mage.MageObject; import mage.abilities.effects.Effect; import mage.abilities.keyword.CyclingAbility; import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; -import mage.game.events.GameEvent.EventType; import mage.game.stack.StackObject; /** @@ -55,11 +53,6 @@ public class CycleTriggeredAbility extends ZoneChangeTriggeredAbility { super(ability); } - @Override - public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { - return game.getState().getZone(getSourceId()).equals(Zone.HAND) && hasSourceObjectAbility(game, source, event); - } - @Override public boolean checkEventType(GameEvent event, Game game) { return event.getType() == GameEvent.EventType.ACTIVATED_ABILITY; diff --git a/Mage/src/mage/players/PlayerImpl.java b/Mage/src/mage/players/PlayerImpl.java index 6c3b0d77d5..6a35a5da6d 100644 --- a/Mage/src/mage/players/PlayerImpl.java +++ b/Mage/src/mage/players/PlayerImpl.java @@ -639,8 +639,9 @@ public abstract class PlayerImpl implements Player, Serializable { @Override public void discardToMax(Game game) { if (hand.size() > this.maxHandSize) { - if (!game.isSimulation()) + if (!game.isSimulation()) { game.informPlayers(getLogName() + " discards down to " + this.maxHandSize + (this.maxHandSize == 1 ? " hand card" : " hand cards")); + } discard(hand.size() - this.maxHandSize, null, game); } } @@ -733,8 +734,9 @@ public abstract class PlayerImpl implements Player, Serializable { */ if (card != null) { // write info to game log first so game log infos from triggered or replacement effects follow in the game log - if (!game.isSimulation()) + if (!game.isSimulation()) { game.informPlayers(getLogName() + " discards " + card.getLogName()); + } /* If a card is discarded while Rest in Peace is on the battlefield, abilities that function * when a card is discarded (such as madness) still work, even though that card never reaches * a graveyard. In addition, spells or abilities that check the characteristics of a discarded @@ -1034,8 +1036,9 @@ public abstract class PlayerImpl implements Player, Serializable { game.getStack().push(new StackAbility(ability, playerId)); if (ability.activate(game, false)) { game.fireEvent(GameEvent.getEvent(GameEvent.EventType.ACTIVATED_ABILITY, ability.getId(), ability.getSourceId(), playerId)); - if (!game.isSimulation()) + if (!game.isSimulation()) { game.informPlayers(getLogName() + ability.getGameLogMessage(game)); + } game.removeBookmark(bookmark); resetStoredBookmark(game); return true; @@ -1061,8 +1064,9 @@ public abstract class PlayerImpl implements Player, Serializable { int bookmark = game.bookmarkState(); if (action.activate(game, false)) { game.fireEvent(GameEvent.getEvent(GameEvent.EventType.ACTIVATED_ABILITY, action.getSourceId(), action.getId(), playerId)); - if (!game.isSimulation()) + if (!game.isSimulation()) { game.informPlayers(getLogName() + action.getGameLogMessage(game)); + } if (action.resolve(game)) { game.removeBookmark(bookmark); resetStoredBookmark(game); @@ -1287,8 +1291,9 @@ public abstract class PlayerImpl implements Player, Serializable { public void shuffleLibrary(Game game) { if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.SHUFFLE_LIBRARY, playerId, playerId))) { this.library.shuffle(); - if (!game.isSimulation()) + if (!game.isSimulation()) { game.informPlayers(getLogName() + " shuffles his or her library."); + } game.fireEvent(GameEvent.getEvent(GameEvent.EventType.LIBRARY_SHUFFLED, playerId, playerId)); } } @@ -1585,8 +1590,9 @@ public abstract class PlayerImpl implements Player, Serializable { GameEvent event = new GameEvent(GameEvent.EventType.LOSE_LIFE, playerId, playerId, playerId, amount, false); if (!game.replaceEvent(event)) { this.life -= event.getAmount(); - if (!game.isSimulation()) + if (!game.isSimulation()) { game.informPlayers(this.getLogName() + " loses " + event.getAmount() + " life"); + } game.fireEvent(GameEvent.getEvent(GameEvent.EventType.LOST_LIFE, playerId, playerId, playerId, amount)); return amount; } @@ -2055,8 +2061,9 @@ public abstract class PlayerImpl implements Player, Serializable { } GameEvent event = GameEvent.getEvent(GameEvent.EventType.SEARCH_LIBRARY, targetPlayerId, playerId, playerId, Integer.MAX_VALUE); if (!game.replaceEvent(event)) { - if (!game.isSimulation()) + if (!game.isSimulation()) { game.informPlayers(searchInfo); + } TargetCardInLibrary newTarget = target.copy(); int count; int librarySearchLimit = event.getAmount(); @@ -2096,8 +2103,9 @@ public abstract class PlayerImpl implements Player, Serializable { @Override public boolean flipCoin(Game game, ArrayList appliedEffects) { boolean result = rnd.nextBoolean(); - if (!game.isSimulation()) + if (!game.isSimulation()) { game.informPlayers("[Flip a coin] " + getLogName() + (result ? " won (head)." : " lost (tail).")); + } GameEvent event = new GameEvent(GameEvent.EventType.FLIP_COIN, playerId, null, playerId, 0, result); event.setAppliedEffects(appliedEffects); game.replaceEvent(event); @@ -2287,12 +2295,12 @@ public abstract class PlayerImpl implements Player, Serializable { } // controller specific alternate spell costs - for (AlternativeSourceCosts alternativeSourceCosts: getAlternativeSourceCosts()) { - if (alternativeSourceCosts instanceof Ability) { - if (((AlternativeSourceCosts) alternativeSourceCosts).isAvailable(ability, game)) { - if (((Ability) alternativeSourceCosts).getCosts().canPay(ability, playerId, playerId, game)) { + for (AlternativeSourceCosts alternateSourceCosts: getAlternativeSourceCosts()) { + if (alternateSourceCosts instanceof Ability) { + if (alternateSourceCosts.isAvailable(ability, game)) { + if (((Ability) alternateSourceCosts).getCosts().canPay(ability, playerId, playerId, game)) { ManaCostsImpl manaCosts = new ManaCostsImpl(); - for (Cost cost : ((Ability) alternativeSourceCosts).getCosts()) { + for (Cost cost : ((Ability) alternateSourceCosts).getCosts()) { if (cost instanceof ManaCost) { manaCosts.add((ManaCost) cost); } @@ -2884,7 +2892,7 @@ public abstract class PlayerImpl implements Player, Serializable { } boolean chooseOrder = true; if (cards.size() > 2) { - chooseOrder = choosingPlayer.chooseUse(Outcome.Neutral, "Do you like to choose the order the cards go to graveyard?", game); + chooseOrder = choosingPlayer.chooseUse(Outcome.Neutral, "Would you like to choose the order the cards go to graveyard?", game); } if (chooseOrder) { while (choosingPlayer.isInGame() && cards.size() > 1) { @@ -2997,11 +3005,12 @@ public abstract class PlayerImpl implements Player, Serializable { public boolean putOntoBattlefieldWithInfo(Card card, Game game, Zone fromZone, UUID sourceId, boolean tapped, boolean facedown) { boolean result = false; if (card.putOntoBattlefield(game, fromZone, sourceId, this.getId(), tapped, facedown)) { - if (!game.isSimulation()) + if (!game.isSimulation()) { game.informPlayers(new StringBuilder(this.getLogName()) - .append(" puts ").append(facedown ? "a card face down ":card.getLogName()) - .append(" from ").append(fromZone.toString().toLowerCase(Locale.ENGLISH)).append(" ") - .append("onto the Battlefield").toString()); + .append(" puts ").append(facedown ? "a card face down ":card.getLogName()) + .append(" from ").append(fromZone.toString().toLowerCase(Locale.ENGLISH)).append(" ") + .append("onto the Battlefield").toString()); + } result = true; } return result; From d42901d0523d72820c3c2d69dfaf83c19b7d8ca9 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Mon, 11 May 2015 13:49:04 +0200 Subject: [PATCH 21/37] Some minor changes. --- .../PutIntoGraveFromBattlefieldAllTriggeredAbility.java | 9 ++++++++- .../mage/abilities/effects/common/ChooseColorEffect.java | 3 ++- .../common/continuous/BecomesColorTargetEffect.java | 3 ++- .../mage/watchers/common/CastSpellLastTurnWatcher.java | 1 - 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/Mage/src/mage/abilities/common/PutIntoGraveFromBattlefieldAllTriggeredAbility.java b/Mage/src/mage/abilities/common/PutIntoGraveFromBattlefieldAllTriggeredAbility.java index cf2e9f2727..be6495f8c9 100644 --- a/Mage/src/mage/abilities/common/PutIntoGraveFromBattlefieldAllTriggeredAbility.java +++ b/Mage/src/mage/abilities/common/PutIntoGraveFromBattlefieldAllTriggeredAbility.java @@ -45,15 +45,21 @@ public class PutIntoGraveFromBattlefieldAllTriggeredAbility extends TriggeredAbi private final FilterPermanent filter; private boolean setTargetPointer; + private boolean onlyToControllerGraveyard; public PutIntoGraveFromBattlefieldAllTriggeredAbility(Effect effect, boolean optional, FilterPermanent filter, boolean setTargetPointer) { + this(effect, optional, filter, setTargetPointer, false); + } + public PutIntoGraveFromBattlefieldAllTriggeredAbility(Effect effect, boolean optional, FilterPermanent filter, boolean setTargetPointer, boolean onlyToControllerGraveyard) { super(Zone.BATTLEFIELD, effect, optional); this.filter = filter; + this.onlyToControllerGraveyard = onlyToControllerGraveyard; } public PutIntoGraveFromBattlefieldAllTriggeredAbility(final PutIntoGraveFromBattlefieldAllTriggeredAbility ability) { super(ability); this.filter = ability.filter; + this.onlyToControllerGraveyard = ability.onlyToControllerGraveyard; } @Override @@ -80,7 +86,8 @@ public class PutIntoGraveFromBattlefieldAllTriggeredAbility extends TriggeredAbi @Override public String getRule() { - return new StringBuilder("Whenever ").append(filter.getMessage()).append(" is put into a graveyard from the battlefield, ").append(super.getRule()).toString(); + return "Whenever " + filter.getMessage() + " is put into " + (onlyToControllerGraveyard ? "your":"a") + + " graveyard from the battlefield, " + super.getRule(); } @Override diff --git a/Mage/src/mage/abilities/effects/common/ChooseColorEffect.java b/Mage/src/mage/abilities/effects/common/ChooseColorEffect.java index 21d0b75964..ff5d4cee3c 100644 --- a/Mage/src/mage/abilities/effects/common/ChooseColorEffect.java +++ b/Mage/src/mage/abilities/effects/common/ChooseColorEffect.java @@ -63,8 +63,9 @@ public class ChooseColorEffect extends OneShotEffect { return false; } } - if (!game.isSimulation()) + if (!game.isSimulation()) { game.informPlayers(new StringBuilder(permanent.getLogName()).append(": ").append(controller.getLogName()).append(" has chosen ").append(choice.getChoice()).toString()); + } game.getState().setValue(source.getSourceId() + "_color", choice.getColor()); permanent.addInfo("chosen color", "Chosen color: " + choice.getColor().getDescription() + "", game); return true; diff --git a/Mage/src/mage/abilities/effects/common/continuous/BecomesColorTargetEffect.java b/Mage/src/mage/abilities/effects/common/continuous/BecomesColorTargetEffect.java index c17456326f..6c74ef7e58 100644 --- a/Mage/src/mage/abilities/effects/common/continuous/BecomesColorTargetEffect.java +++ b/Mage/src/mage/abilities/effects/common/continuous/BecomesColorTargetEffect.java @@ -96,8 +96,9 @@ public class BecomesColorTargetEffect extends ContinuousEffectImpl { } else { return false; } - if (!game.isSimulation()) + if (!game.isSimulation()) { game.informPlayers(controller.getLogName() + " has chosen the color: " + objectColor.toString()); + } } else { objectColor = this.setColor; } diff --git a/Mage/src/mage/watchers/common/CastSpellLastTurnWatcher.java b/Mage/src/mage/watchers/common/CastSpellLastTurnWatcher.java index 6498530c68..1b22784e90 100644 --- a/Mage/src/mage/watchers/common/CastSpellLastTurnWatcher.java +++ b/Mage/src/mage/watchers/common/CastSpellLastTurnWatcher.java @@ -38,7 +38,6 @@ import mage.MageObjectReference; import mage.constants.WatcherScope; import mage.game.Game; import mage.game.events.GameEvent; -import mage.game.stack.Spell; import mage.watchers.Watcher; /** From ef1ee0adbf787650de5bfaad2ed9db504a8d28d2 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Mon, 11 May 2015 15:00:54 +0200 Subject: [PATCH 22/37] * Norn's Annex - Fixed that the effect did not work if a planeswalker of the controller was attacked. --- .../src/mage/sets/newphyrexia/NornsAnnex.java | 27 ++++++++----------- .../abilities/costs/mana/ManaCostsImpl.java | 6 ++--- Mage/src/mage/game/events/GameEvent.java | 11 +++++++- 3 files changed, 24 insertions(+), 20 deletions(-) diff --git a/Mage.Sets/src/mage/sets/newphyrexia/NornsAnnex.java b/Mage.Sets/src/mage/sets/newphyrexia/NornsAnnex.java index f3c673928c..095aa694b5 100644 --- a/Mage.Sets/src/mage/sets/newphyrexia/NornsAnnex.java +++ b/Mage.Sets/src/mage/sets/newphyrexia/NornsAnnex.java @@ -52,7 +52,9 @@ public class NornsAnnex extends CardImpl { public NornsAnnex(UUID ownerId) { super(ownerId, 17, "Norn's Annex", Rarity.RARE, new CardType[]{CardType.ARTIFACT}, "{3}{WP}{WP}"); this.expansionSetCode = "NPH"; - this.color.setWhite(true); + + // {WP} ({WP} can be paid with either or 2 life.) + // Creatures can't attack you or a planeswalker you control unless their controller pays for each of those creatures. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new NornsAnnexReplacementEffect())); } @@ -87,29 +89,24 @@ class NornsAnnexReplacementEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == GameEvent.EventType.DECLARE_ATTACKER) { - if (event.getTargetId().equals(source.getControllerId()) ) { - return true; - } - // planeswalker - Permanent permanent = game.getPermanent(event.getTargetId()); - if (permanent != null && permanent.getControllerId().equals(source.getControllerId()) - && permanent.getCardType().contains(CardType.PLANESWALKER)) { - return true; - } + if (event.getTargetId().equals(source.getControllerId()) ) { + return true; } - return false; + // planeswalker + Permanent permanent = game.getPermanent(event.getTargetId()); + return permanent != null && permanent.getControllerId().equals(source.getControllerId()) + && permanent.getCardType().contains(CardType.PLANESWALKER); } @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { Player player = game.getPlayer(event.getPlayerId()); - if (player != null && event.getTargetId().equals(source.getControllerId())) { + if (player != null) { ManaCostsImpl propagandaTax = new ManaCostsImpl("{WP}"); if (propagandaTax.canPay(source, source.getSourceId(), event.getPlayerId(), game) && player.chooseUse(Outcome.Benefit, "Pay {WP} to declare attacker?", game)) { - if (propagandaTax.payOrRollback(source, game, this.getId(), event.getPlayerId())) { + if (propagandaTax.payOrRollback(source, game, source.getSourceId(), event.getPlayerId())) { return false; } } @@ -125,5 +122,3 @@ class NornsAnnexReplacementEffect extends ReplacementEffectImpl { } } - - diff --git a/Mage/src/mage/abilities/costs/mana/ManaCostsImpl.java b/Mage/src/mage/abilities/costs/mana/ManaCostsImpl.java index bfefe86b77..aca1bd6b37 100644 --- a/Mage/src/mage/abilities/costs/mana/ManaCostsImpl.java +++ b/Mage/src/mage/abilities/costs/mana/ManaCostsImpl.java @@ -139,12 +139,12 @@ public class ManaCostsImpl extends ArrayList implements M * @param ability * @param game * @param sourceId - * @param controllerId + * @param payingPlayerId * @return true if the cost was paid */ - public boolean payOrRollback(Ability ability, Game game, UUID sourceId, UUID controllerId) { + public boolean payOrRollback(Ability ability, Game game, UUID sourceId, UUID payingPlayerId) { int bookmark = game.bookmarkState(); - if (pay(ability, game, sourceId, controllerId, false)) { + if (pay(ability, game, sourceId, payingPlayerId, false)) { game.removeBookmark(bookmark); return true; } diff --git a/Mage/src/mage/game/events/GameEvent.java b/Mage/src/mage/game/events/GameEvent.java index d93ee6f92f..7862334c56 100644 --- a/Mage/src/mage/game/events/GameEvent.java +++ b/Mage/src/mage/game/events/GameEvent.java @@ -148,7 +148,16 @@ public class GameEvent implements Serializable { COUNTER, COUNTERED, DECLARING_ATTACKERS, DECLARED_ATTACKERS, - DECLARE_ATTACKER, ATTACKER_DECLARED, + 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 + */ + ATTACKER_DECLARED, /* DECLARING_BLOCKERS targetId attackerId From 70f152feb1fdaa350cd3a248ff321cf82ed908a6 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Mon, 11 May 2015 15:33:22 +0200 Subject: [PATCH 23/37] * Fixed that some mana effects did not send all neded events (prevented that Contamination chnaged conditonal mana from Cavern of Souls to black mana). --- .../cards/single/avr/CavernOfSoulsTest.java | 27 +++++++++++++++++++ .../AddConditionalManaOfAnyColorEffect.java | 1 + .../common/AddContinuousEffectToGame.java | 2 +- .../common/AddManaOfAnyColorEffect.java | 2 +- .../AddManaOfAnyTypeProducedEffect.java | 3 ++- .../abilities/effects/common/ManaEffect.java | 2 +- 6 files changed, 33 insertions(+), 4 deletions(-) diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/avr/CavernOfSoulsTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/avr/CavernOfSoulsTest.java index 4b2fc04a51..eb69c8b1c4 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/single/avr/CavernOfSoulsTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/avr/CavernOfSoulsTest.java @@ -223,4 +223,31 @@ public class CavernOfSoulsTest extends CardTestPlayerBase { assertPermanentCount(playerA, "Silvercoat Lion", 0); } + + /** + * Cavern of Souls can produce any colour of mana with its second ability when Contamination is in play. + */ + @Test + public void testUseWithConversionInPlay() { + addCard(Zone.BATTLEFIELD, playerA, "Plains", 3); + addCard(Zone.HAND, playerA, "Cavern of Souls"); + // Creature - Drake {3}{R} + addCard(Zone.HAND, playerA, "Desert Drake"); + + addCard(Zone.BATTLEFIELD, playerB, "Contamination", 1); + + + + playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cavern of Souls"); + setChoice(playerA, "Drake"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Desert Drake"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPermanentCount(playerA, "Cavern of Souls", 1); + assertPermanentCount(playerA, "Desert Drake", 0); + + } + } diff --git a/Mage/src/mage/abilities/effects/common/AddConditionalManaOfAnyColorEffect.java b/Mage/src/mage/abilities/effects/common/AddConditionalManaOfAnyColorEffect.java index 946bbf9613..1b37d1e395 100644 --- a/Mage/src/mage/abilities/effects/common/AddConditionalManaOfAnyColorEffect.java +++ b/Mage/src/mage/abilities/effects/common/AddConditionalManaOfAnyColorEffect.java @@ -106,6 +106,7 @@ public class AddConditionalManaOfAnyColorEffect extends ManaEffect { } if (mana != null) { + checkToFirePossibleEvents(mana, game, source); controller.getManaPool().addMana(mana, game, source); result = true; } diff --git a/Mage/src/mage/abilities/effects/common/AddContinuousEffectToGame.java b/Mage/src/mage/abilities/effects/common/AddContinuousEffectToGame.java index 0ccc81a8dc..1cfcdae0e2 100644 --- a/Mage/src/mage/abilities/effects/common/AddContinuousEffectToGame.java +++ b/Mage/src/mage/abilities/effects/common/AddContinuousEffectToGame.java @@ -59,7 +59,7 @@ public class AddContinuousEffectToGame extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - ContinuousEffect effectToAdd = (ContinuousEffect) effect.copy(); + ContinuousEffect effectToAdd = effect.copy(); game.addEffect(effectToAdd, source); return true; } diff --git a/Mage/src/mage/abilities/effects/common/AddManaOfAnyColorEffect.java b/Mage/src/mage/abilities/effects/common/AddManaOfAnyColorEffect.java index b79149a846..ea14b2f875 100644 --- a/Mage/src/mage/abilities/effects/common/AddManaOfAnyColorEffect.java +++ b/Mage/src/mage/abilities/effects/common/AddManaOfAnyColorEffect.java @@ -88,8 +88,8 @@ public class AddManaOfAnyColorEffect extends BasicManaEffect { createdMana = Mana.WhiteMana(amount); } if (createdMana != null) { - controller.getManaPool().addMana(createdMana, game, source); checkToFirePossibleEvents(createdMana, game, source); + controller.getManaPool().addMana(createdMana, game, source); } return true; } diff --git a/Mage/src/mage/abilities/effects/common/AddManaOfAnyTypeProducedEffect.java b/Mage/src/mage/abilities/effects/common/AddManaOfAnyTypeProducedEffect.java index cd3f1b5b39..d07dd9f6f9 100644 --- a/Mage/src/mage/abilities/effects/common/AddManaOfAnyTypeProducedEffect.java +++ b/Mage/src/mage/abilities/effects/common/AddManaOfAnyTypeProducedEffect.java @@ -111,8 +111,9 @@ public class AddManaOfAnyTypeProducedEffect extends ManaEffect { newMana.setColorless(1); break; } - targetController.getManaPool().addMana(newMana, game, source); checkToFirePossibleEvents(newMana, game, source); + targetController.getManaPool().addMana(newMana, game, source); + } return true; } diff --git a/Mage/src/mage/abilities/effects/common/ManaEffect.java b/Mage/src/mage/abilities/effects/common/ManaEffect.java index c19e070a51..1541c53114 100644 --- a/Mage/src/mage/abilities/effects/common/ManaEffect.java +++ b/Mage/src/mage/abilities/effects/common/ManaEffect.java @@ -56,7 +56,7 @@ public abstract class ManaEffect extends OneShotEffect { public abstract Mana getMana(Game game, Ability source); /** - * Only used for mana effects that decide which mana is produced during resolution of the effect. + * Only used for mana effects that decide which kind of mana is produced during resolution of the effect. * * @param mana * @param game From 1067ba296b2606dff4c73ab68c8ca22596c5ff0e Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Mon, 11 May 2015 19:17:38 +0200 Subject: [PATCH 24/37] * Chief Engineer - Fixed that convoke did not work for Artifacts while Chief Engineer was on the battlefield. --- .../mage/sets/magic2015/ChiefEngineer.java | 92 ++++++++++--------- Mage/src/mage/abilities/AbilityImpl.java | 3 +- .../abilities/keyword/ConvokeAbility.java | 3 +- Mage/src/mage/util/ManaUtil.java | 5 +- 4 files changed, 58 insertions(+), 45 deletions(-) diff --git a/Mage.Sets/src/mage/sets/magic2015/ChiefEngineer.java b/Mage.Sets/src/mage/sets/magic2015/ChiefEngineer.java index c33b5da89d..c7c1aedaf6 100644 --- a/Mage.Sets/src/mage/sets/magic2015/ChiefEngineer.java +++ b/Mage.Sets/src/mage/sets/magic2015/ChiefEngineer.java @@ -27,41 +27,56 @@ */ package mage.sets.magic2015; +import java.util.Iterator; import java.util.UUID; import mage.MageInt; -import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.keyword.ConvokeAbility; import mage.cards.Card; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Duration; +import mage.constants.Layer; import mage.constants.Outcome; import mage.constants.Rarity; +import mage.constants.SubLayer; import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.filter.FilterSpell; +import mage.filter.predicate.mageobject.CardTypePredicate; import mage.game.Game; -import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.game.stack.Spell; +import mage.game.stack.StackObject; +import mage.players.Player; /** * * @author LevelX2 */ public class ChiefEngineer extends CardImpl { + + private static final FilterSpell filter = new FilterSpell("Artifact spells you cast"); + static { + filter.add(new CardTypePredicate(CardType.ARTIFACT)); + } + public ChiefEngineer(UUID ownerId) { super(ownerId, 47, "Chief Engineer", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{1}{U}"); this.expansionSetCode = "M15"; this.subtype.add("Vedalken"); this.subtype.add("Artificer"); - this.color.setBlue(true); this.power = new MageInt(1); this.toughness = new MageInt(3); // Artifact spells you cast have convoke. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ChiefEngineerEffect())); + this.addAbility(new SimpleStaticAbility( + Zone.BATTLEFIELD, new ChiefEngineerGainAbilitySpellsEffect(new ConvokeAbility(), filter))); + } public ChiefEngineer(final ChiefEngineer card) { @@ -74,54 +89,49 @@ public class ChiefEngineer extends CardImpl { } } -class ChiefEngineerEffect extends ReplacementEffectImpl { +class ChiefEngineerGainAbilitySpellsEffect extends ContinuousEffectImpl { - public ChiefEngineerEffect() { - super(Duration.WhileOnBattlefield, Outcome.Benefit); - staticText = "Artifact spells you cast have convoke"; + private final Ability ability; + private final FilterSpell filter; + + public ChiefEngineerGainAbilitySpellsEffect(Ability ability, FilterSpell filter) { + super(Duration.WhileOnBattlefield, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility); + this.ability = ability; + this.filter = filter; + staticText = filter.getMessage() + " have " + ability.getRule(); } - public ChiefEngineerEffect(final ChiefEngineerEffect effect) { + public ChiefEngineerGainAbilitySpellsEffect(final ChiefEngineerGainAbilitySpellsEffect effect) { super(effect); + this.ability = effect.ability; + this.filter = effect.filter; } @Override - public ChiefEngineerEffect copy() { - return new ChiefEngineerEffect(this); + public ChiefEngineerGainAbilitySpellsEffect copy() { + return new ChiefEngineerGainAbilitySpellsEffect(this); } @Override public boolean apply(Game game, Ability source) { - return true; - } - - @Override - public boolean replaceEvent(GameEvent event, Ability source, Game game) { - MageObject object = game.getObject(event.getSourceId()); - if (object != null) { - Card card = (Card) object; - Ability ability = new ConvokeAbility(); - game.getState().addOtherAbility(card, ability); - ability.setControllerId(source.getControllerId()); - ability.setSourceId(card.getId()); - game.getState().addAbility(ability, source.getSourceId(), card); - } - return false; - } - - @Override - public boolean checksEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.CAST_SPELL; - } - - @Override - public boolean applies(GameEvent event, Ability source, Game game) { - if ((event.getType() == GameEvent.EventType.CAST_SPELL) - && event.getPlayerId() == source.getControllerId()) { - MageObject spellObject = game.getObject(event.getSourceId()); - if (spellObject != null && spellObject.getCardType().contains(CardType.ARTIFACT)) { - return true; + Player player = game.getPlayer(source.getControllerId()); + Permanent permanent = game.getPermanent(source.getSourceId()); + if (player != null && permanent != null) { + for (Iterator iterator = game.getStack().iterator(); iterator.hasNext();) { + StackObject stackObject = iterator.next(); + // only cast spells, so no copies + if (!stackObject.isCopy() && stackObject.getControllerId().equals(source.getControllerId())) { + if (stackObject instanceof Spell) { + Spell spell = (Spell) stackObject; + if (filter.match(spell, game)) { + if (!spell.getAbilities().contains(ability)) { + game.getState().addOtherAbility(spell.getCard(), ability); + } + } + } + } } + return true; } return false; } diff --git a/Mage/src/mage/abilities/AbilityImpl.java b/Mage/src/mage/abilities/AbilityImpl.java index cc35790778..2e4a0f8e45 100644 --- a/Mage/src/mage/abilities/AbilityImpl.java +++ b/Mage/src/mage/abilities/AbilityImpl.java @@ -246,7 +246,8 @@ public abstract class AbilityImpl implements Ability { if (controller == null) { return false; } - + game.applyEffects(); + /* 20130201 - 601.2b * If the spell is modal the player announces the mode choice (see rule 700.2). */ diff --git a/Mage/src/mage/abilities/keyword/ConvokeAbility.java b/Mage/src/mage/abilities/keyword/ConvokeAbility.java index fef21bc10e..9449efcb45 100644 --- a/Mage/src/mage/abilities/keyword/ConvokeAbility.java +++ b/Mage/src/mage/abilities/keyword/ConvokeAbility.java @@ -251,8 +251,9 @@ class ConvokeEffect extends OneShotEffect { manaPool.unlockManaType(ManaType.COLORLESS); manaName = "colorless"; } - if (!game.isSimulation()) + if (!game.isSimulation()) { game.informPlayers("Convoke: " + controller.getLogName() + " taps " + perm.getLogName() + " to pay one " + manaName + " mana"); + } } } diff --git a/Mage/src/mage/util/ManaUtil.java b/Mage/src/mage/util/ManaUtil.java index 080efef553..7dd8627c7b 100644 --- a/Mage/src/mage/util/ManaUtil.java +++ b/Mage/src/mage/util/ManaUtil.java @@ -13,6 +13,7 @@ import java.util.UUID; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.costs.mana.AlternateManaPaymentAbility; +import mage.cards.Card; import mage.game.Game; /** @@ -351,8 +352,8 @@ public class ManaUtil { public static String addSpecialManaPayAbilities(Ability source, Game game, ManaCost unpaid) { // check for special mana payment possibilities MageObject mageObject = source.getSourceObject(game); - if (mageObject != null) { - for (Ability ability :mageObject.getAbilities()) { + if (mageObject instanceof Card) { + for (Ability ability :((Card)mageObject).getAbilities(game)) { if (ability instanceof AlternateManaPaymentAbility) { ((AlternateManaPaymentAbility) ability).addSpecialAction(source, game, unpaid); } From f203d799ec44b65c7cef2d751357c291af03cfc3 Mon Sep 17 00:00:00 2001 From: Luna Skyrise Date: Mon, 11 May 2015 14:01:52 -0300 Subject: [PATCH 25/37] Orcish Spy: look the top X cards instead of removing them Basis: LookLibraryTopCardPlayerEffect and Library.getTopCards(game, amount) --- .../mage/sets/fallenempires/OrcishSpy.java | 180 +++++++++++------- 1 file changed, 111 insertions(+), 69 deletions(-) diff --git a/Mage.Sets/src/mage/sets/fallenempires/OrcishSpy.java b/Mage.Sets/src/mage/sets/fallenempires/OrcishSpy.java index 1df6be2d05..1e9b5c2402 100644 --- a/Mage.Sets/src/mage/sets/fallenempires/OrcishSpy.java +++ b/Mage.Sets/src/mage/sets/fallenempires/OrcishSpy.java @@ -1,69 +1,111 @@ -/* - * 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.fallenempires; - -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.RevealTargetPlayerLibraryEffect; -import mage.cards.CardImpl; -import mage.constants.CardType; -import mage.constants.Rarity; -import mage.constants.Zone; - -/** - * - * @author anonymous - */ -public class OrcishSpy extends CardImpl { - - public OrcishSpy(UUID ownerId) { - super(ownerId, 124, "Orcish Spy", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{R}"); - this.expansionSetCode = "FEM"; - this.subtype.add("Orc"); - this.subtype.add("Rogue"); - this.power = new MageInt(1); - this.toughness = new MageInt(1); - - // {tap}: Look at the top three cards of target player's library. - Ability ability = new SimpleActivatedAbility(Zone.LIBRARY, new RevealTargetPlayerLibraryEffect(3), new TapSourceCost()); - this.addAbility(ability); - } - - public OrcishSpy(final OrcishSpy card) { - super(card); - } - - @Override - public OrcishSpy copy() { - return new OrcishSpy(this); - } -} - +/* + * 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.fallenempires; + +import java.util.List; +import java.util.UUID; +import mage.MageInt; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.LookLibraryTopCardTargetPlayerEffect; +import mage.abilities.effects.common.RevealTargetPlayerLibraryEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardsImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.Game; +import mage.players.Player; + +/** + * + * @author anonymous + */ +public class OrcishSpy extends CardImpl { + + public OrcishSpy(UUID ownerId) { + super(ownerId, 124, "Orcish Spy", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{R}"); + this.expansionSetCode = "FEM"; + this.subtype.add("Orc"); + this.subtype.add("Rogue"); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // {tap}: Look at the top three cards of target player's library. + Ability ability = new SimpleActivatedAbility(Zone.LIBRARY, new LookLibraryTopXCardsTargetPlayerEffect(3, "look at the top three cards of target player's library"), new TapSourceCost()); + this.addAbility(ability); + } + + public OrcishSpy(final OrcishSpy card) { + super(card); + } + + @Override + public OrcishSpy copy() { + return new OrcishSpy(this); + } +} + +class LookLibraryTopXCardsTargetPlayerEffect extends OneShotEffect { + + protected int number; + + public LookLibraryTopXCardsTargetPlayerEffect(int number, String text) { + super(Outcome.Benefit); + this.number = number; + this.staticText = text; + } + + public LookLibraryTopXCardsTargetPlayerEffect(final LookLibraryTopXCardsTargetPlayerEffect effect) { + super(effect); + } + + @Override + public LookLibraryTopXCardsTargetPlayerEffect copy() { + return new LookLibraryTopXCardsTargetPlayerEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + Player targetPlayer = game.getPlayer(source.getFirstTarget()); + MageObject sourceObject = game.getObject(source.getSourceId()); + if (player != null && targetPlayer != null && sourceObject != null) { + CardsImpl cards = new CardsImpl(); + cards.addAll(targetPlayer.getLibrary().getTopCards(game, number)); + player.lookAtCards(sourceObject.getName(), cards, game); + return true; + } + return false; + } +} From 8d0619b356a76899750a876e4a6971009812d8ed Mon Sep 17 00:00:00 2001 From: Luna Skyrise Date: Mon, 11 May 2015 14:41:47 -0300 Subject: [PATCH 26/37] Distorting Lens: various fixes by LevelX2 * TargetPermanent() instead of TargetCreaturePermanent() * BecomesColorTargetEffect with setColor = null * use permanent.getLogName() and player.getLogName() --- .../sets/eighthedition/DistortingLens.java | 213 +++++++++--------- 1 file changed, 104 insertions(+), 109 deletions(-) diff --git a/Mage.Sets/src/mage/sets/eighthedition/DistortingLens.java b/Mage.Sets/src/mage/sets/eighthedition/DistortingLens.java index f77ce78316..bcec9540c5 100644 --- a/Mage.Sets/src/mage/sets/eighthedition/DistortingLens.java +++ b/Mage.Sets/src/mage/sets/eighthedition/DistortingLens.java @@ -1,109 +1,104 @@ -/* - * 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.eighthedition; - -import java.util.UUID; -import mage.abilities.Ability; -import mage.abilities.common.SimpleActivatedAbility; -import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.effects.ContinuousEffect; -import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.continuous.BecomesColorTargetEffect; -import mage.cards.CardImpl; -import mage.choices.ChoiceColor; -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.permanent.Permanent; -import mage.players.Player; -import mage.target.common.TargetCreaturePermanent; -import mage.target.targetpointer.FixedTarget; - -/** - * - * @author anonymous - */ -public class DistortingLens extends CardImpl { - - public DistortingLens(UUID ownerId) { - super(ownerId, 299, "Distorting Lens", Rarity.RARE, new CardType[]{CardType.ARTIFACT}, "{2}"); - this.expansionSetCode = "8ED"; - - // {tap}: Target permanent becomes the color of your choice until end of turn. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ChangeColorEffect(), new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent()); - this.addAbility(ability); - } - - public DistortingLens(final DistortingLens card) { - super(card); - } - - @Override - public DistortingLens copy() { - return new DistortingLens(this); - } -} - -class ChangeColorEffect extends OneShotEffect { - - public ChangeColorEffect() { - super(Outcome.Neutral); - staticText = "Target permanent becomes the color of your choice until end of turn"; - } - - public ChangeColorEffect(final ChangeColorEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - Permanent permanent = game.getPermanent(source.getSourceId()); - Permanent chosen = game.getPermanent(targetPointer.getFirst(game, source)); - if (player != null && permanent != null) { - ChoiceColor colorChoice = new ChoiceColor(); - if (player.choose(Outcome.Neutral, colorChoice, game)) { - game.informPlayers(permanent.getName() + ": " + player.getName() + " has chosen " + colorChoice.getChoice()); - ContinuousEffect effect = new BecomesColorTargetEffect(colorChoice.getColor(), Duration.EndOfTurn, "is " + colorChoice.getChoice()); - effect.setTargetPointer(new FixedTarget(chosen.getId())); - game.addEffect(effect, source); - return true; - } - } - return false; - } - - @Override - public ChangeColorEffect copy() { - return new ChangeColorEffect(this); - } -} \ No newline at end of file +/* + * 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.eighthedition; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.BecomesColorTargetEffect; +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.permanent.Permanent; +import mage.players.Player; +import mage.target.TargetPermanent; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author anonymous + */ +public class DistortingLens extends CardImpl { + + public DistortingLens(UUID ownerId) { + super(ownerId, 299, "Distorting Lens", Rarity.RARE, new CardType[]{CardType.ARTIFACT}, "{2}"); + this.expansionSetCode = "8ED"; + + // {tap}: Target permanent becomes the color of your choice until end of turn. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ChangeColorEffect(), new TapSourceCost()); + ability.addTarget(new TargetPermanent()); + this.addAbility(ability); + } + + public DistortingLens(final DistortingLens card) { + super(card); + } + + @Override + public DistortingLens copy() { + return new DistortingLens(this); + } +} + +class ChangeColorEffect extends OneShotEffect { + + public ChangeColorEffect() { + super(Outcome.Neutral); + staticText = "Target permanent becomes the color of your choice until end of turn"; + } + + public ChangeColorEffect(final ChangeColorEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + Permanent permanent = game.getPermanent(source.getSourceId()); + Permanent chosen = game.getPermanent(targetPointer.getFirst(game, source)); + if (player != null && permanent != null) { + ContinuousEffect effect = new BecomesColorTargetEffect(null, Duration.EndOfTurn); + effect.setTargetPointer(new FixedTarget(chosen.getId())); + game.addEffect(effect, source); + return true; + } + return false; + } + + @Override + public ChangeColorEffect copy() { + return new ChangeColorEffect(this); + } +} From 548eae29b90be31de77121136503610418f31364 Mon Sep 17 00:00:00 2001 From: Luna Skyrise Date: Mon, 11 May 2015 15:54:36 -0300 Subject: [PATCH 27/37] Homing Sliver: apply ability to Slivers on players' hands Fix based on Past In Flames (Innistrad) --- .../mage/sets/futuresight/HomingSliver.java | 88 ++++++++++++++++--- 1 file changed, 77 insertions(+), 11 deletions(-) diff --git a/Mage.Sets/src/mage/sets/futuresight/HomingSliver.java b/Mage.Sets/src/mage/sets/futuresight/HomingSliver.java index c8e91fb4b5..46ebea4bda 100644 --- a/Mage.Sets/src/mage/sets/futuresight/HomingSliver.java +++ b/Mage.Sets/src/mage/sets/futuresight/HomingSliver.java @@ -29,23 +29,30 @@ package mage.sets.futuresight; import java.util.UUID; import mage.MageInt; +import mage.MageObjectReference; import mage.abilities.Ability; -import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.common.DiscardSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.common.continuous.GainAbilityAllEffect; -import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect; import mage.abilities.keyword.CyclingAbility; +import mage.abilities.keyword.FlashbackAbility; +import mage.cards.Card; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Duration; +import mage.constants.Layer; +import mage.constants.Outcome; import mage.constants.Rarity; +import mage.constants.SubLayer; +import mage.constants.TimingRule; import mage.constants.Zone; import mage.filter.FilterCard; import mage.filter.FilterPermanent; import mage.filter.predicate.mageobject.SubtypePredicate; -import mage.target.common.TargetCardInLibrary; +import mage.game.Game; +import mage.players.Player; /** * @@ -59,12 +66,6 @@ public class HomingSliver extends CardImpl { filter.add(new SubtypePredicate("Sliver")); } - private static final FilterPermanent filter2 = new FilterPermanent("Sliver card"); - - static { - filter2.add(new SubtypePredicate("Sliver")); - } - public HomingSliver(UUID ownerId) { super(ownerId, 118, "Homing Sliver", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{2}{R}"); this.expansionSetCode = "FUT"; @@ -75,7 +76,7 @@ public class HomingSliver extends CardImpl { // Each Sliver card in each player's hand has slivercycling {3}. Ability ability = new CyclingAbility(new ManaCostsImpl("{3}"), filter, "Slivercycling"); ability.addCost(new DiscardSourceCost()); - this.addAbility(new SimpleStaticAbility(Zone.HAND, new GainAbilityAllEffect(ability, Duration.WhileOnBattlefield, filter2))); + this.addAbility(new SimpleStaticAbility(Zone.HAND, new HomingSliverEffect())); // Slivercycling {3} this.addAbility(ability); /** @@ -91,7 +92,6 @@ public class HomingSliver extends CardImpl { * Brighthearth) will interact with Slivercycling. Effects that interact * with spells (such as Remove Soul or Faerie Tauntings) will not. */ - /** * 01/02/2009 You can choose to find any card with the Sliver creature * type, even if it isn't a creature card. This includes, for example, @@ -110,3 +110,69 @@ public class HomingSliver extends CardImpl { return new HomingSliver(this); } } + +class HomingSliverEffect extends ContinuousEffectImpl { + + private static final FilterCard filter2 = new FilterCard("Sliver card"); + + static { + filter2.add(new SubtypePredicate("Sliver")); + } + + public HomingSliverEffect() { + super(Duration.WhileOnBattlefield, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility); + this.staticText = "Each Sliver card in each player's hand has slivercycling {3}"; + } + + public HomingSliverEffect(final HomingSliverEffect effect) { + super(effect); + } + + @Override + public HomingSliverEffect copy() { + return new HomingSliverEffect(this); + } + + @Override + public void init(Ability source, Game game) { + super.init(source, game); + if (this.affectedObjectsSet) { + for (UUID p : game.getPlayerList()) { + Player player = game.getPlayer(p); + if (player != null) { + for (UUID cardId : player.getHand()) { + Card card = game.getCard(cardId); + if (card.getSubtype().contains("Sliver")) { + affectedObjectList.add(new MageObjectReference(card, game)); + } + } + } + } + } + } + + @Override + public boolean apply(Game game, Ability source) { + for (UUID p : game.getPlayerList()) { + Player player = game.getPlayer(p); + if (player != null) { + for (UUID cardId : player.getHand()) { + if (affectedObjectList.contains(new MageObjectReference(cardId, game))) { + Card card = game.getCard(cardId); + CyclingAbility ability = null; + if (card.getSubtype().contains("Sliver")) { + ability = new CyclingAbility(new ManaCostsImpl("{3}"), filter2, "Slivercycling"); + } + if (ability != null) { + ability.setSourceId(cardId); + ability.setControllerId(card.getOwnerId()); + game.getState().addOtherAbility(card, ability); + } + } + } + return true; + } + } + return false; + } +} From ff998698c8a8b44b3f2a427860a2295092b5c964 Mon Sep 17 00:00:00 2001 From: Luna Skyrise Date: Mon, 11 May 2015 16:36:11 -0300 Subject: [PATCH 28/37] Knollspine Invocation: fix by LevelX2 Instead of hacking ManaCostsImpl, adjust real damage via adjustCosts (see Necropolis Fiend) --- .../sets/shadowmoor/KnollspineInvocation.java | 125 ++++-------------- 1 file changed, 26 insertions(+), 99 deletions(-) diff --git a/Mage.Sets/src/mage/sets/shadowmoor/KnollspineInvocation.java b/Mage.Sets/src/mage/sets/shadowmoor/KnollspineInvocation.java index 8295f04461..372aa409e1 100644 --- a/Mage.Sets/src/mage/sets/shadowmoor/KnollspineInvocation.java +++ b/Mage.Sets/src/mage/sets/shadowmoor/KnollspineInvocation.java @@ -30,21 +30,20 @@ package mage.sets.shadowmoor; import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; -import mage.abilities.costs.common.DiscardCardCost; +import mage.abilities.costs.Cost; +import mage.abilities.costs.common.DiscardTargetCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.dynamicvalue.common.ManacostVariableValue; +import mage.abilities.effects.common.DamageTargetEffect; import mage.cards.CardImpl; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.Rarity; import mage.constants.Zone; import mage.filter.Filter; import mage.filter.FilterCard; -import mage.filter.common.FilterOwnedCard; import mage.filter.predicate.mageobject.ConvertedManaCostPredicate; import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.players.Player; +import mage.target.common.TargetCardInHand; import mage.target.common.TargetCreatureOrPlayer; /** @@ -53,16 +52,36 @@ import mage.target.common.TargetCreatureOrPlayer; */ public class KnollspineInvocation extends CardImpl { + private static final FilterCard filter = new FilterCard("a card with converted mana cost X"); + public KnollspineInvocation(UUID ownerId) { super(ownerId, 99, "Knollspine Invocation", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{1}{R}{R}"); this.expansionSetCode = "SHM"; // {X}, Discard a card with converted mana cost X: Knollspine Invocation deals X damage to target creature or player. - Ability ability = new KnollspineInvocationAbility(); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(new ManacostVariableValue(), true), new ManaCostsImpl<>("{X}")); + ability.addCost(new DiscardTargetCost(new TargetCardInHand(filter))); ability.addTarget(new TargetCreatureOrPlayer()); this.addAbility(ability); } + @Override + public void adjustCosts(Ability ability, Game game) { + if (ability instanceof SimpleActivatedAbility) { + int xValue = ability.getManaCostsToPay().getX(); + for (Cost cost : ability.getCosts()) { + if (cost instanceof DiscardTargetCost) { + DiscardTargetCost discardCost = (DiscardTargetCost) cost; + discardCost.getTargets().clear(); + FilterCard adjustedFilter = filter.copy(); // don't use it directly, it's static!!!! + adjustedFilter.add(new ConvertedManaCostPredicate(Filter.ComparisonType.Equal, xValue)); + discardCost.addTarget(new TargetCardInHand(adjustedFilter)); + return; + } + } + } + } + public KnollspineInvocation(final KnollspineInvocation card) { super(card); } @@ -72,95 +91,3 @@ public class KnollspineInvocation extends CardImpl { return new KnollspineInvocation(this); } } - -class KnollspineInvocationAbility extends SimpleActivatedAbility { - public KnollspineInvocationAbility() { - super(Zone.BATTLEFIELD, new KnollspineInvocationEffect(), new ManaCostsImpl("{0}")); - //If cost gets added by ManaCostsImpl.add from ActivatedAbilityImpl constructor, this will destroy our custom mana cost - //Here comes the hack - //A less hacky solution would be to implement this as a ManaCost proper, - //using ManaCostImpl (but it would involve duplicating code from ManaCostsImpl - //and, of course, it would deny access to ManaCostsImpl's API) - this.manaCosts = new KnollspineInvocationAbilityCost("{X}"); - this.manaCostsToPay = this.manaCosts.copy(); - } -} - -class KnollspineInvocationEffect extends OneShotEffect { - //See DrainLife for this class' implementation - - public KnollspineInvocationEffect() { - super(Outcome.Damage); - staticText = "Knollspine Invocation deals X damage to target creature or player"; - } - - public KnollspineInvocationEffect(final KnollspineInvocationEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - int amount = source.getManaCostsToPay().getX(); - if (amount > 0) { - Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); - if (permanent != null ) { - permanent.damage(amount, source.getSourceId(), game, false, true); - } else { - Player player = game.getPlayer(getTargetPointer().getFirst(game, source)); - if (player != null) { - player.damage(amount, source.getSourceId(), game, false, true); - } else { - return false; - } - } - } - return true; - } - - @Override - public KnollspineInvocationEffect copy() { - return new KnollspineInvocationEffect(this); - } -} - -class KnollspineInvocationAbilityCost extends ManaCostsImpl { - protected DiscardCardCost additional; - - public KnollspineInvocationAbilityCost(final KnollspineInvocationAbilityCost cost) { - super(cost); - this.additional = cost.additional; - } - - public KnollspineInvocationAbilityCost (String s) { - super(s); - //we can only apply the additional discard cost AFTER we resolve this one! - FilterCard filter = new FilterOwnedCard("a card with converted mana cost " + super.getText()); - filter.add(new ConvertedManaCostPredicate(Filter.ComparisonType.Equal, super.getX())); - additional = new DiscardCardCost(filter); - } - - @Override - public KnollspineInvocationAbilityCost copy() { - return new KnollspineInvocationAbilityCost(this); - } - - @Override - public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) { - if (super.pay(ability, game, sourceId, controllerId, noMana)) { - //Now we get the real deal - FilterCard filter = new FilterOwnedCard("a card with converted mana cost " + this.getX()); - filter.add(new ConvertedManaCostPredicate(Filter.ComparisonType.Equal, this.getX())); - return new DiscardCardCost(filter).pay(ability, game, sourceId, controllerId, noMana); - } - return false; - } - - @Override - public String getText() { - StringBuilder sb = new StringBuilder(super.getText()); - sb.append(", "); - sb.append(additional.getText()); - System.out.println("Knollspine Invocation tooltip: " + sb.toString()); - return sb.toString(); - } -} \ No newline at end of file From 4af01f7cf4000caa4add3f5de978146b66fc1086 Mon Sep 17 00:00:00 2001 From: Luna Skyrise Date: Mon, 11 May 2015 16:47:15 -0300 Subject: [PATCH 29/37] Enduring Renewal: various fixes by LevelX2 --- .../src/mage/sets/iceage/EnduringRenewal.java | 57 ++++--------------- 1 file changed, 12 insertions(+), 45 deletions(-) diff --git a/Mage.Sets/src/mage/sets/iceage/EnduringRenewal.java b/Mage.Sets/src/mage/sets/iceage/EnduringRenewal.java index 7309f2f400..3c518ba54d 100644 --- a/Mage.Sets/src/mage/sets/iceage/EnduringRenewal.java +++ b/Mage.Sets/src/mage/sets/iceage/EnduringRenewal.java @@ -31,11 +31,14 @@ import java.util.UUID; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.PutCardIntoGraveFromAnywhereAllTriggeredAbility; +import mage.abilities.common.PutIntoGraveFromBattlefieldAllTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.Cards; @@ -47,9 +50,10 @@ import mage.constants.Outcome; import mage.constants.Rarity; import mage.constants.SubLayer; import mage.constants.Zone; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.events.GameEvent; -import mage.game.events.ZoneChangeEvent; import mage.game.permanent.Permanent; import mage.players.Player; @@ -58,6 +62,8 @@ import mage.players.Player; * @author anonymous */ public class EnduringRenewal extends CardImpl { + + private static final FilterPermanent filter = new FilterCreaturePermanent("a creature"); public EnduringRenewal(UUID ownerId) { super(ownerId, 247, "Enduring Renewal", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}{W}"); @@ -68,7 +74,7 @@ public class EnduringRenewal extends CardImpl { // If you would draw a card, reveal the top card of your library instead. If it's a creature card, put it into your graveyard. Otherwise, draw a card. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new EnduringRenewalReplacementEffect())); // Whenever a creature is put into your graveyard from the battlefield, return it to your hand. - this.addAbility(new EnduringRenewalTriggeredAbility()); + this.addAbility(new PutIntoGraveFromBattlefieldAllTriggeredAbility(new ReturnFromGraveyardToHandTargetEffect(), false, filter, true, true)); } public EnduringRenewal(final EnduringRenewal card) { @@ -109,22 +115,20 @@ class EnduringRenewalReplacementEffect extends ReplacementEffectImpl { return false; } else if (you.getLibrary().size() > 0){ - Card top = you.getLibrary().removeFromTop(game); + Card top = you.getLibrary().getFromTop(game); - Cards cards = new CardsImpl(Zone.PICK); + Cards cards = new CardsImpl(); cards.add(top); you.revealCards("Top card of " + you.getName() + "'s library", cards, game); if (top.getCardType().contains(CardType.CREATURE)) { - top.moveToZone(Zone.GRAVEYARD, top.getId(), game, true); + you.moveCardToGraveyardWithInfo(top, source.getSourceId(), game, Zone.LIBRARY); } else { - top.moveToZone(Zone.HAND, top.getId(), game, false); + you.moveCardToHandWithInfo(top, source.getSourceId(), game, Zone.LIBRARY); } - cards.clear(); - return true; } return false; @@ -199,40 +203,3 @@ class EnduringRenewalEffect extends OneShotEffect { return false; } } - -class EnduringRenewalTriggeredAbility extends TriggeredAbilityImpl { - - public EnduringRenewalTriggeredAbility() { - super(Zone.BATTLEFIELD, new EnduringRenewalEffect(), false); - } - - public EnduringRenewalTriggeredAbility(EnduringRenewalTriggeredAbility ability) { - super(ability); - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (event.getType() == GameEvent.EventType.ZONE_CHANGE - && ((ZoneChangeEvent) event).isDiesEvent() - && ((ZoneChangeEvent) event).getPlayerId().equals(this.getControllerId())) { - Permanent permanent = game.getPermanent(event.getTargetId()); - if (permanent.getCardType().contains(CardType.CREATURE) - && permanent.getControllerId().equals(this.controllerId)) { - Effect effect = this.getEffects().get(0); - effect.setValue("returningCreature", event.getTargetId()); - return true; - } - } - return false; - } - - @Override - public String getRule() { - return "Whenever a creature is put into your graveyard from the battlefield, " + super.getRule(); - } - - @Override - public EnduringRenewalTriggeredAbility copy() { - return new EnduringRenewalTriggeredAbility(this); - } -} From 9149e66e713a49d8adcb8a6d8c55f2db493b3cb9 Mon Sep 17 00:00:00 2001 From: Luna Skyrise Date: Mon, 11 May 2015 16:58:09 -0300 Subject: [PATCH 30/37] No Rest for the Wicked: fixes by LevelX2 --- .../sets/urzassaga/NoRestForTheWicked.java | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/Mage.Sets/src/mage/sets/urzassaga/NoRestForTheWicked.java b/Mage.Sets/src/mage/sets/urzassaga/NoRestForTheWicked.java index 887f9aa043..13cb200e27 100644 --- a/Mage.Sets/src/mage/sets/urzassaga/NoRestForTheWicked.java +++ b/Mage.Sets/src/mage/sets/urzassaga/NoRestForTheWicked.java @@ -43,6 +43,7 @@ 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.Watcher; /** @@ -86,14 +87,18 @@ class NoRestForTheWickedEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { NoRestForTheWickedWatcher watcher = (NoRestForTheWickedWatcher) game.getState().getWatchers().get("NoRestForTheWickedWatcher"); if (watcher != null) { - for (UUID id : watcher.cards) { - Card c = game.getCard(id); + for (UUID cardId : watcher.cards) { + Card c = game.getCard(cardId); if (c != null) { - if (game.getState().getZone(id) == Zone.GRAVEYARD) { - if (c.getCardType().contains(CardType.CREATURE) && c.getOwnerId().equals(source.getControllerId())) { - //400.3 - c.moveToZone(Zone.HAND, source.getSourceId(), game, false); - } + if (game.getState().getZone(cardId) == Zone.GRAVEYARD + && c.getCardType().contains(CardType.CREATURE) + && c.getOwnerId().equals(source.getControllerId())) { + //400.3 + Player p = game.getPlayer(source.getControllerId()); + if (p != null) { + p.moveCardToHandWithInfo(c, source.getSourceId(), game, Zone.GRAVEYARD); + } + return false; } } } @@ -105,27 +110,29 @@ class NoRestForTheWickedEffect extends OneShotEffect { @Override public NoRestForTheWickedEffect copy() { return new NoRestForTheWickedEffect(this); + } } class NoRestForTheWickedWatcher extends Watcher { - ArrayList cards = new ArrayList(); + ArrayList cards; public NoRestForTheWickedWatcher() { super("NoRestForTheWickedWatcher", WatcherScope.GAME); + this.cards = new ArrayList(); } public NoRestForTheWickedWatcher(final NoRestForTheWickedWatcher watcher) { super(watcher); + this.cards = new ArrayList(); this.cards.addAll(watcher.cards); } @Override public void watch(GameEvent event, Game game) { if (event.getType() == GameEvent.EventType.ZONE_CHANGE - && ((ZoneChangeEvent) event).isDiesEvent() - && ((ZoneChangeEvent) event).getPlayerId().equals(this.getControllerId())) { + && ((ZoneChangeEvent) event).isDiesEvent()) { //400.3 Intercept only the controller's events cards.add(event.getTargetId()); } From a49d0828236d91da6bed9dbe1230262534f9417a Mon Sep 17 00:00:00 2001 From: Luna Skyrise Date: Mon, 11 May 2015 19:07:14 -0300 Subject: [PATCH 31/37] Orcish Spy: modify LookLibraryTopCardTargetPlayerEffect to admit multiple cards --- .../mage/sets/fallenempires/OrcishSpy.java | 45 +------------------ .../LookLibraryTopCardTargetPlayerEffect.java | 38 +++++++++++----- 2 files changed, 29 insertions(+), 54 deletions(-) diff --git a/Mage.Sets/src/mage/sets/fallenempires/OrcishSpy.java b/Mage.Sets/src/mage/sets/fallenempires/OrcishSpy.java index 1e9b5c2402..ffe94a579d 100644 --- a/Mage.Sets/src/mage/sets/fallenempires/OrcishSpy.java +++ b/Mage.Sets/src/mage/sets/fallenempires/OrcishSpy.java @@ -27,25 +27,16 @@ */ package mage.sets.fallenempires; -import java.util.List; import java.util.UUID; import mage.MageInt; -import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.LookLibraryTopCardTargetPlayerEffect; -import mage.abilities.effects.common.RevealTargetPlayerLibraryEffect; -import mage.cards.Card; import mage.cards.CardImpl; -import mage.cards.CardsImpl; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.Rarity; import mage.constants.Zone; -import mage.game.Game; -import mage.players.Player; /** * @@ -62,7 +53,7 @@ public class OrcishSpy extends CardImpl { this.toughness = new MageInt(1); // {tap}: Look at the top three cards of target player's library. - Ability ability = new SimpleActivatedAbility(Zone.LIBRARY, new LookLibraryTopXCardsTargetPlayerEffect(3, "look at the top three cards of target player's library"), new TapSourceCost()); + Ability ability = new SimpleActivatedAbility(Zone.LIBRARY, new LookLibraryTopCardTargetPlayerEffect(3), new TapSourceCost()); this.addAbility(ability); } @@ -75,37 +66,3 @@ public class OrcishSpy extends CardImpl { return new OrcishSpy(this); } } - -class LookLibraryTopXCardsTargetPlayerEffect extends OneShotEffect { - - protected int number; - - public LookLibraryTopXCardsTargetPlayerEffect(int number, String text) { - super(Outcome.Benefit); - this.number = number; - this.staticText = text; - } - - public LookLibraryTopXCardsTargetPlayerEffect(final LookLibraryTopXCardsTargetPlayerEffect effect) { - super(effect); - } - - @Override - public LookLibraryTopXCardsTargetPlayerEffect copy() { - return new LookLibraryTopXCardsTargetPlayerEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - Player targetPlayer = game.getPlayer(source.getFirstTarget()); - MageObject sourceObject = game.getObject(source.getSourceId()); - if (player != null && targetPlayer != null && sourceObject != null) { - CardsImpl cards = new CardsImpl(); - cards.addAll(targetPlayer.getLibrary().getTopCards(game, number)); - player.lookAtCards(sourceObject.getName(), cards, game); - return true; - } - return false; - } -} diff --git a/Mage/src/mage/abilities/effects/common/LookLibraryTopCardTargetPlayerEffect.java b/Mage/src/mage/abilities/effects/common/LookLibraryTopCardTargetPlayerEffect.java index e2994edc63..a6a991d38d 100644 --- a/Mage/src/mage/abilities/effects/common/LookLibraryTopCardTargetPlayerEffect.java +++ b/Mage/src/mage/abilities/effects/common/LookLibraryTopCardTargetPlayerEffect.java @@ -30,26 +30,34 @@ package mage.abilities.effects.common; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; -import mage.cards.Card; +import mage.cards.Cards; import mage.cards.CardsImpl; import mage.constants.Outcome; import mage.game.Game; import mage.players.Player; +import mage.util.CardUtil; /** * * @author LevelX2 */ - public class LookLibraryTopCardTargetPlayerEffect extends OneShotEffect { - public LookLibraryTopCardTargetPlayerEffect() { + protected int amount; + + public LookLibraryTopCardTargetPlayerEffect(int amount) { super(Outcome.Benefit); - this.staticText = "look at the top card of target player's library"; + this.amount = amount; + setText(); + } + + public LookLibraryTopCardTargetPlayerEffect() { + this(1); } public LookLibraryTopCardTargetPlayerEffect(final LookLibraryTopCardTargetPlayerEffect effect) { super(effect); + amount = effect.amount; } @Override @@ -63,14 +71,24 @@ public class LookLibraryTopCardTargetPlayerEffect extends OneShotEffect { Player targetPlayer = game.getPlayer(source.getFirstTarget()); MageObject sourceObject = game.getObject(source.getSourceId()); if (player != null && targetPlayer != null && sourceObject != null) { - Card card = targetPlayer.getLibrary().getFromTop(game); - if (card != null) { - CardsImpl cards = new CardsImpl(); - cards.add(card); - player.lookAtCards(sourceObject.getName(), cards, game); - } + Cards cards = new CardsImpl(); + cards.addAll(targetPlayer.getLibrary().getTopCards(game, amount)); + player.lookAtCards(sourceObject.getName(), cards, game); return true; } return false; } + + private void setText() { + StringBuilder sb = new StringBuilder("look at the top "); + if (amount > 1) { + sb.append(CardUtil.numberToText(amount)); + sb.append(" cards "); + } + else { + sb.append(" card "); + } + sb.append("of target player's library"); + this.staticText = sb.toString(); + } } From 0b712fc3e7898760b765f539ec72e764d5125259 Mon Sep 17 00:00:00 2001 From: Luna Skyrise Date: Mon, 11 May 2015 19:13:17 -0300 Subject: [PATCH 32/37] Instill Energy: fix the haste-like effect --- .../mage/sets/fifthedition/InstillEnergy.java | 62 +++++++++++++------ 1 file changed, 43 insertions(+), 19 deletions(-) diff --git a/Mage.Sets/src/mage/sets/fifthedition/InstillEnergy.java b/Mage.Sets/src/mage/sets/fifthedition/InstillEnergy.java index 69bf026c43..5c82efdeba 100644 --- a/Mage.Sets/src/mage/sets/fifthedition/InstillEnergy.java +++ b/Mage.Sets/src/mage/sets/fifthedition/InstillEnergy.java @@ -30,22 +30,19 @@ package mage.sets.fifthedition; import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; -import mage.abilities.common.LimitedTimesPerTurnActivatedAbility; -import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.common.SimpleTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.MyTurnCondition; import mage.abilities.costs.Cost; import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.AsThoughEffectImpl; import mage.abilities.effects.Effect; import mage.abilities.effects.common.AttachEffect; import mage.abilities.effects.common.UntapEnchantedEffect; -import mage.abilities.effects.common.UntapSourceEffect; import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; import mage.abilities.keyword.EnchantAbility; -import mage.abilities.keyword.HasteAbility; import mage.cards.CardImpl; +import mage.constants.AsThoughEffectType; import mage.constants.AttachmentType; import mage.constants.CardType; import mage.constants.Duration; @@ -53,6 +50,7 @@ import mage.constants.Outcome; import mage.constants.Rarity; import mage.constants.Zone; import mage.game.Game; +import mage.game.permanent.Permanent; import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.util.CardUtil; @@ -75,7 +73,8 @@ public class InstillEnergy extends CardImpl { Ability ability = new EnchantAbility(auraTarget.getTargetName()); this.addAbility(ability); // Enchanted creature can attack as though it had haste. - Ability haste = new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(HasteAbility.getInstance(), AttachmentType.AURA, Duration.Custom, "Enchanted creature can attack as though it had haste.")); + Ability asThough = new SimpleStaticAbility(Zone.BATTLEFIELD, new CanAttackAsThoughItHadHasteEnchantedEffect(Duration.WhileOnBattlefield)); + Ability haste = new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(asThough, AttachmentType.AURA, Duration.WhileOnBattlefield, "Enchanted creature can attack as though it had haste.")); this.addAbility(haste); // {0}: Untap enchanted creature. Activate this ability only during your turn and only once each turn. Ability gainedAbility = new LimitedTimesIfConditionActivatedAbility(Zone.BATTLEFIELD, new UntapEnchantedEffect(), new GenericManaCost(0), MyTurnCondition.getInstance(), 1); @@ -92,8 +91,35 @@ public class InstillEnergy extends CardImpl { } } -class LimitedTimesIfConditionActivatedAbility extends ActivateIfConditionActivatedAbility { - +class CanAttackAsThoughItHadHasteEnchantedEffect extends AsThoughEffectImpl { + public CanAttackAsThoughItHadHasteEnchantedEffect(Duration duration) { + super(AsThoughEffectType.ATTACK, duration, Outcome.Benefit); + staticText = "Enchanted creature can attack as though it had haste"; + } + + public CanAttackAsThoughItHadHasteEnchantedEffect(final CanAttackAsThoughItHadHasteEnchantedEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public CanAttackAsThoughItHadHasteEnchantedEffect copy() { + return new CanAttackAsThoughItHadHasteEnchantedEffect(this); + } + + @Override + public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { + Permanent enchantment = game.getPermanent(source.getSourceId()); + return enchantment != null && enchantment.getAttachedTo() != null && enchantment.getAttachedTo() == objectId; + } +} + +class LimitedTimesIfConditionActivatedAbility extends ActivateIfConditionActivatedAbility { + class ActivationInfo { public int turnNum; @@ -106,7 +132,7 @@ class LimitedTimesIfConditionActivatedAbility extends ActivateIfConditionActivat } private int maxActivationsPerTurn; - + public LimitedTimesIfConditionActivatedAbility(Zone zone, Effect effect, Cost cost, Condition condition) { this(zone, effect, cost, condition, 1); } @@ -137,13 +163,11 @@ class LimitedTimesIfConditionActivatedAbility extends ActivateIfConditionActivat ActivationInfo activationInfo = getActivationInfo(game); if (activationInfo == null) { activationInfo = new ActivationInfo(game.getTurnNum(), 1); + } else if (activationInfo.turnNum != game.getTurnNum()) { + activationInfo.turnNum = game.getTurnNum(); + activationInfo.activationCounter = 1; } else { - if (activationInfo.turnNum != game.getTurnNum()) { - activationInfo.turnNum = game.getTurnNum(); - activationInfo.activationCounter = 1; - } else { - activationInfo.activationCounter++; - } + activationInfo.activationCounter++; } setActivationInfo(activationInfo, game); return true; @@ -160,8 +184,8 @@ class LimitedTimesIfConditionActivatedAbility extends ActivateIfConditionActivat @Override public String getRule() { StringBuilder sb = new StringBuilder(super.getRule()); - sb.replace(sb.length()-1, sb.length() -1, " and "); //suppress super()'s final period - switch(maxActivationsPerTurn) { + sb.replace(sb.length() - 1, sb.length() - 1, " and "); //suppress super()'s final period + switch (maxActivationsPerTurn) { case 1: sb.append("only once"); break; @@ -179,7 +203,7 @@ class LimitedTimesIfConditionActivatedAbility extends ActivateIfConditionActivat public LimitedTimesIfConditionActivatedAbility copy() { return new LimitedTimesIfConditionActivatedAbility(this); } - + private ActivationInfo getActivationInfo(Game game) { Integer turnNum = (Integer) game.getState().getValue(CardUtil.getCardZoneString("activationsTurn", sourceId, game)); Integer activationCount = (Integer) game.getState().getValue(CardUtil.getCardZoneString("activationsCount", sourceId, game)); @@ -188,7 +212,7 @@ class LimitedTimesIfConditionActivatedAbility extends ActivateIfConditionActivat } return new ActivationInfo(turnNum, activationCount); } - + private void setActivationInfo(ActivationInfo activationInfo, Game game) { game.getState().setValue(CardUtil.getCardZoneString("activationsTurn", sourceId, game), activationInfo.turnNum); game.getState().setValue(CardUtil.getCardZoneString("activationsCount", sourceId, game), activationInfo.activationCounter); From ee8b5116e67aac7c578e96e861ffffd11b351c87 Mon Sep 17 00:00:00 2001 From: Luna Skyrise Date: Mon, 11 May 2015 19:18:22 -0300 Subject: [PATCH 33/37] Homing Sliver: use hasSubtype to check Sliver cards --- Mage.Sets/src/mage/sets/futuresight/HomingSliver.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mage.Sets/src/mage/sets/futuresight/HomingSliver.java b/Mage.Sets/src/mage/sets/futuresight/HomingSliver.java index 46ebea4bda..1ec2b43aa5 100644 --- a/Mage.Sets/src/mage/sets/futuresight/HomingSliver.java +++ b/Mage.Sets/src/mage/sets/futuresight/HomingSliver.java @@ -160,7 +160,7 @@ class HomingSliverEffect extends ContinuousEffectImpl { if (affectedObjectList.contains(new MageObjectReference(cardId, game))) { Card card = game.getCard(cardId); CyclingAbility ability = null; - if (card.getSubtype().contains("Sliver")) { + if (card.hasSubtype("Sliver")) { ability = new CyclingAbility(new ManaCostsImpl("{3}"), filter2, "Slivercycling"); } if (ability != null) { From 68a44caadde11bb63bf4d4c90ca4d82effa38377 Mon Sep 17 00:00:00 2001 From: Luna Skyrise Date: Mon, 11 May 2015 19:39:01 -0300 Subject: [PATCH 34/37] Shifting Sky: use ChooseColorEffect and a static ability... ...to change colors --- .../src/mage/sets/planeshift/ShiftingSky.java | 107 +++++++++++------- 1 file changed, 65 insertions(+), 42 deletions(-) diff --git a/Mage.Sets/src/mage/sets/planeshift/ShiftingSky.java b/Mage.Sets/src/mage/sets/planeshift/ShiftingSky.java index 43677a3dca..c856eb587a 100644 --- a/Mage.Sets/src/mage/sets/planeshift/ShiftingSky.java +++ b/Mage.Sets/src/mage/sets/planeshift/ShiftingSky.java @@ -28,45 +28,47 @@ package mage.sets.planeshift; import java.util.UUID; +import mage.MageObject; +import mage.ObjectColor; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.effects.ContinuousEffect; +import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.continuous.BecomesColorTargetEffect; +import mage.abilities.effects.common.ChooseColorEffect; import mage.cards.CardImpl; -import mage.choices.ChoiceColor; 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.predicate.Predicates; import mage.filter.predicate.mageobject.CardTypePredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; -import mage.target.targetpointer.FixedTarget; /** * * @author anonymous */ public class ShiftingSky extends CardImpl { - + public ShiftingSky(UUID ownerId) { super(ownerId, 32, "Shifting Sky", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}"); this.expansionSetCode = "PLS"; // As Shifting Sky enters the battlefield, choose a color. - Ability ability = new EntersBattlefieldTriggeredAbility(new ShiftingSkyEffect()); - // All nonland permanents are the chosen color. + Ability ability = new EntersBattlefieldTriggeredAbility(new ChooseColorEffect(Outcome.Benefit)); this.addAbility(ability); + // All nonland permanents are the chosen color. + Ability ability2 = new SimpleStaticAbility(Zone.BATTLEFIELD, new ShiftingSkyEffect()); + this.addAbility(ability2); } - + public ShiftingSky(final ShiftingSky card) { super(card); } - + @Override public ShiftingSky copy() { return new ShiftingSky(this); @@ -74,53 +76,74 @@ public class ShiftingSky extends CardImpl { } class ShiftingSkyEffect extends OneShotEffect { + private static final FilterPermanent filter = new FilterPermanent("All nonland permanents"); - public ShiftingSkyEffect() { - super(Outcome.Neutral); - staticText = "All nonland permanents are the chosen color"; - } - - public ShiftingSkyEffect(final ShiftingSkyEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - Permanent permanent = game.getPermanent(source.getSourceId()); - - FilterPermanent filter = new FilterPermanent("All nonland permanents"); - + static { filter.add( Predicates.not( new CardTypePredicate(CardType.LAND) ) ); - + } + + public ShiftingSkyEffect() { + super(Outcome.Benefit); + staticText = "All nonland permanents are the chosen color"; + } + + public ShiftingSkyEffect(final ShiftingSkyEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + Permanent permanent = game.getPermanent(source.getSourceId()); + if (player != null && permanent != null) { - ChoiceColor colorChoice = new ChoiceColor(); - if (player.choose(Outcome.Neutral, colorChoice, game)) { - game.informPlayers(permanent.getName() + ": " + player.getName() + " has chosen " + colorChoice.getChoice()); - ContinuousEffect effect; - - for (UUID playerId : player.getInRange()) { - Player p = game.getPlayer(playerId); - if (p != null) { - for (Permanent chosen : game.getBattlefield().getAllActivePermanents(filter, playerId, game)) { - effect = new BecomesColorTargetEffect(colorChoice.getColor(), Duration.EndOfTurn, "is " + colorChoice.getChoice()); - effect.setTargetPointer(new FixedTarget(chosen.getId())); - game.addEffect(effect, source); - } + ObjectColor color = (ObjectColor) game.getState().getValue(source.getSourceId() + "_color"); + + if (color == null) { + return false; + } + + String colorString = color.toString(); + + for (UUID playerId : player.getInRange()) { + Player p = game.getPlayer(playerId); + if (p != null) { + for (Permanent chosen : game.getBattlefield().getAllActivePermanents(filter, playerId, game)) { + setObject(chosen, colorString); } } - return true; } + return true; } return false; } - + @Override public ShiftingSkyEffect copy() { return new ShiftingSkyEffect(this); } + + private void setObject(Permanent chosen, String colorString) { + switch (colorString) { + case "W": + chosen.getColor().setWhite(true); + break; + case "B": + chosen.getColor().setBlack(true); + break; + case "U": + chosen.getColor().setBlue(true); + break; + case "G": + chosen.getColor().setGreen(true); + break; + case "R": + chosen.getColor().setRed(true); + break; + } + } } From 4219c4eeeda636cb421757de9de00787d2f6cee6 Mon Sep 17 00:00:00 2001 From: Luna Skyrise Date: Mon, 11 May 2015 19:44:42 -0300 Subject: [PATCH 35/37] Lymph Sliver: adjust tooltip text, fully use PreventionEffectImpl --- .../mage/sets/futuresight/LymphSliver.java | 34 ++----------------- 1 file changed, 2 insertions(+), 32 deletions(-) diff --git a/Mage.Sets/src/mage/sets/futuresight/LymphSliver.java b/Mage.Sets/src/mage/sets/futuresight/LymphSliver.java index 528e97515a..3d972d2eb3 100644 --- a/Mage.Sets/src/mage/sets/futuresight/LymphSliver.java +++ b/Mage.Sets/src/mage/sets/futuresight/LymphSliver.java @@ -39,8 +39,6 @@ import mage.constants.Duration; import mage.constants.Rarity; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; -import mage.game.Game; -import mage.game.events.GameEvent; /** * @@ -59,7 +57,7 @@ public class LymphSliver extends CardImpl { // All Sliver creatures have absorb 1. Ability absorb = new SimpleStaticAbility(Zone.BATTLEFIELD, new SliverAbsorbEffect()); - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAllEffect(absorb, Duration.WhileOnBattlefield, filter))); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAllEffect(absorb, Duration.WhileOnBattlefield, filter, "If a source would deal damage to a Sliver, prevent 1 of that damage"))); } public LymphSliver(final LymphSliver card) { @@ -73,9 +71,8 @@ public class LymphSliver extends CardImpl { } class SliverAbsorbEffect extends PreventionEffectImpl { - //From Urza's Armor public SliverAbsorbEffect() { - super(Duration.WhileOnBattlefield); + super(Duration.WhileOnBattlefield, 1, false, false); this.staticText = "If a source would deal damage to a Sliver, prevent 1 of that damage"; } @@ -83,33 +80,6 @@ class SliverAbsorbEffect extends PreventionEffectImpl { super(effect); } - @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; - } - - @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); - } - return false; - } - @Override public SliverAbsorbEffect copy() { return new SliverAbsorbEffect(this); From 0fbb341eac1b1356a35dd3d710e1e1563bb866fd Mon Sep 17 00:00:00 2001 From: Luna Skyrise Date: Mon, 11 May 2015 20:11:35 -0300 Subject: [PATCH 36/37] Rancid Earth: correct effect dependency --- Mage.Sets/src/mage/sets/torment/RancidEarth.java | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/Mage.Sets/src/mage/sets/torment/RancidEarth.java b/Mage.Sets/src/mage/sets/torment/RancidEarth.java index 78afb2b783..39308e07c5 100644 --- a/Mage.Sets/src/mage/sets/torment/RancidEarth.java +++ b/Mage.Sets/src/mage/sets/torment/RancidEarth.java @@ -58,7 +58,7 @@ public class RancidEarth extends CardImpl { new RancidEarthEffect(), new DestroyTargetEffect(), new CardsInControllerGraveCondition(7), - "Destroy target land.

Threshold - If seven or more cards are in your graveyard, instead destroy that land and Rancid Earth deals 1 damage to each creature and each player")); + "Destroy target land.

Threshold - If seven or more cards are in your graveyard, instead destroy that land and Rancid Earth deals 1 damage to each creature and each player.")); this.getSpellAbility().addTarget(new TargetLandPermanent()); } @@ -91,10 +91,7 @@ class RancidEarthEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Effect effect1 = new DestroyTargetEffect("destroy that land"); - if (effect1.apply(game, source)) { - return new DamageEverythingEffect(1).apply(game, source); - } - - return false; + effect1.apply(game, source); + return new DamageEverythingEffect(1).apply(game, source); } } From d1f8575b2ff28f7cbf8bd067ae136e1b837ff96e Mon Sep 17 00:00:00 2001 From: Luna Skyrise Date: Mon, 11 May 2015 20:16:05 -0300 Subject: [PATCH 37/37] Lymph Sliver: correct tooltip text (quote the Absorb explanation) --- Mage.Sets/src/mage/sets/futuresight/LymphSliver.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mage.Sets/src/mage/sets/futuresight/LymphSliver.java b/Mage.Sets/src/mage/sets/futuresight/LymphSliver.java index 3d972d2eb3..3d9afb08a2 100644 --- a/Mage.Sets/src/mage/sets/futuresight/LymphSliver.java +++ b/Mage.Sets/src/mage/sets/futuresight/LymphSliver.java @@ -57,7 +57,7 @@ public class LymphSliver extends CardImpl { // All Sliver creatures have absorb 1. Ability absorb = new SimpleStaticAbility(Zone.BATTLEFIELD, new SliverAbsorbEffect()); - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAllEffect(absorb, Duration.WhileOnBattlefield, filter, "If a source would deal damage to a Sliver, prevent 1 of that damage"))); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAllEffect(absorb, Duration.WhileOnBattlefield, filter, "absorb 1. (If a source would deal damage to a Sliver, prevent 1 of that damage.)"))); } public LymphSliver(final LymphSliver card) {