From a44c2c90b48889ad7964dea54e51659f1e962688 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Fri, 21 Jun 2013 00:37:13 +0200 Subject: [PATCH 01/22] [MMA] Added 3 cards. --- .../mage/sets/eventide/ColdEyedSelkie.java | 105 ++++++++++++++++ .../src/mage/sets/lorwyn/BlindSpotGiant.java | 52 ++++++++ .../mage/sets/lorwyn/DreamspoilerWitches.java | 52 ++++++++ .../sets/modernmasters/BlindSpotGiant.java | 119 ++++++++++++++++++ .../sets/modernmasters/ColdEyedSelkie.java | 52 ++++++++ .../modernmasters/DreamspoilerWitches.java | 107 ++++++++++++++++ 6 files changed, 487 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/eventide/ColdEyedSelkie.java create mode 100644 Mage.Sets/src/mage/sets/lorwyn/BlindSpotGiant.java create mode 100644 Mage.Sets/src/mage/sets/lorwyn/DreamspoilerWitches.java create mode 100644 Mage.Sets/src/mage/sets/modernmasters/BlindSpotGiant.java create mode 100644 Mage.Sets/src/mage/sets/modernmasters/ColdEyedSelkie.java create mode 100644 Mage.Sets/src/mage/sets/modernmasters/DreamspoilerWitches.java diff --git a/Mage.Sets/src/mage/sets/eventide/ColdEyedSelkie.java b/Mage.Sets/src/mage/sets/eventide/ColdEyedSelkie.java new file mode 100644 index 0000000000..8dbf6adb71 --- /dev/null +++ b/Mage.Sets/src/mage/sets/eventide/ColdEyedSelkie.java @@ -0,0 +1,105 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.eventide; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.IslandwalkAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.game.Game; +import mage.players.Player; + +/** + * + * @author LevelX2 + */ +public class ColdEyedSelkie extends CardImpl { + + public ColdEyedSelkie(UUID ownerId) { + super(ownerId, 149, "Cold-Eyed Selkie", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{1}{G/U}{G/U}"); + this.expansionSetCode = "EVE"; + this.subtype.add("Merfolk"); + this.subtype.add("Rogue"); + + this.color.setBlue(true); + this.color.setGreen(true); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Islandwalk + this.addAbility(new IslandwalkAbility()); + // Whenever Cold-Eyed Selkie deals combat damage to a player, you may draw that many cards. + this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new ColdEyeSelkieEffect(), true, true)); + + } + + public ColdEyedSelkie(final ColdEyedSelkie card) { + super(card); + } + + @Override + public ColdEyedSelkie copy() { + return new ColdEyedSelkie(this); + } +} + +class ColdEyeSelkieEffect extends OneShotEffect { + + public ColdEyeSelkieEffect() { + super(Outcome.DrawCard); + this.staticText = "draw that many cards"; + } + + public ColdEyeSelkieEffect(final ColdEyeSelkieEffect effect) { + super(effect); + } + + @Override + public ColdEyeSelkieEffect copy() { + return new ColdEyeSelkieEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + int amount = (Integer) getValue("damage"); + if (amount > 0) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + controller.drawCards(amount, game); + return true; + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/lorwyn/BlindSpotGiant.java b/Mage.Sets/src/mage/sets/lorwyn/BlindSpotGiant.java new file mode 100644 index 0000000000..10ca0055e4 --- /dev/null +++ b/Mage.Sets/src/mage/sets/lorwyn/BlindSpotGiant.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.lorwyn; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class BlindSpotGiant extends mage.sets.modernmasters.BlindSpotGiant { + + public BlindSpotGiant(UUID ownerId) { + super(ownerId); + this.cardNumber = 153; + this.expansionSetCode = "LRW"; + } + + public BlindSpotGiant(final BlindSpotGiant card) { + super(card); + } + + @Override + public BlindSpotGiant copy() { + return new BlindSpotGiant(this); + } +} diff --git a/Mage.Sets/src/mage/sets/lorwyn/DreamspoilerWitches.java b/Mage.Sets/src/mage/sets/lorwyn/DreamspoilerWitches.java new file mode 100644 index 0000000000..3911aff08d --- /dev/null +++ b/Mage.Sets/src/mage/sets/lorwyn/DreamspoilerWitches.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.lorwyn; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class DreamspoilerWitches extends mage.sets.modernmasters.DreamspoilerWitches { + + public DreamspoilerWitches(UUID ownerId) { + super(ownerId); + this.cardNumber = 108; + this.expansionSetCode = "LRW"; + } + + public DreamspoilerWitches(final DreamspoilerWitches card) { + super(card); + } + + @Override + public DreamspoilerWitches copy() { + return new DreamspoilerWitches(this); + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/BlindSpotGiant.java b/Mage.Sets/src/mage/sets/modernmasters/BlindSpotGiant.java new file mode 100644 index 0000000000..85656c2caa --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/BlindSpotGiant.java @@ -0,0 +1,119 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.modernmasters; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.RestrictionEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.filter.predicate.permanent.AnotherPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * + * @author LevelX2 + */ +public class BlindSpotGiant extends CardImpl { + + public BlindSpotGiant(UUID ownerId) { + super(ownerId, 105, "Blind-Spot Giant", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{2}{R}"); + this.expansionSetCode = "MMA"; + this.subtype.add("Giant"); + this.subtype.add("Warrior"); + + this.color.setRed(true); + this.power = new MageInt(4); + this.toughness = new MageInt(3); + + // Blind-Spot Giant can't attack or block unless you control another Giant. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BlindSpotGiantEffect())); + + } + + public BlindSpotGiant(final BlindSpotGiant card) { + super(card); + } + + @Override + public BlindSpotGiant copy() { + return new BlindSpotGiant(this); + } +} + +class BlindSpotGiantEffect extends RestrictionEffect { + + private static final FilterControlledPermanent filter = new FilterControlledPermanent("another Giant"); + static { + filter.add(new SubtypePredicate("Giant")); + filter.add(new AnotherPredicate()); + } + + public BlindSpotGiantEffect() { + super(Duration.WhileOnBattlefield); + staticText = "{this} can't attack or block unless you control another Giant"; + } + + public BlindSpotGiantEffect(final BlindSpotGiantEffect effect) { + super(effect); + } + + @Override + public BlindSpotGiantEffect copy() { + return new BlindSpotGiantEffect(this); + } + + @Override + public boolean canAttack(Game game) { + return false; + } + + @Override + public boolean canBlock(Permanent attacker, Permanent blocker, Ability source, Game game) { + return false; + } + + @Override + public boolean applies(Permanent permanent, Ability source, Game game) { + if (permanent.getId().equals(source.getSourceId())) { + if (game.getBattlefield().count(filter, source.getSourceId(), source.getControllerId(), game) > 0) { + return false; + } + return true; + } // do not apply to other creatures. + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/ColdEyedSelkie.java b/Mage.Sets/src/mage/sets/modernmasters/ColdEyedSelkie.java new file mode 100644 index 0000000000..6142ffb9c3 --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/ColdEyedSelkie.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.modernmasters; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class ColdEyedSelkie extends mage.sets.eventide.ColdEyedSelkie { + + public ColdEyedSelkie(UUID ownerId) { + super(ownerId); + this.cardNumber = 186; + this.expansionSetCode = "MMA"; + } + + public ColdEyedSelkie(final ColdEyedSelkie card) { + super(card); + } + + @Override + public ColdEyedSelkie copy() { + return new ColdEyedSelkie(this); + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/DreamspoilerWitches.java b/Mage.Sets/src/mage/sets/modernmasters/DreamspoilerWitches.java new file mode 100644 index 0000000000..10f588cdf7 --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/DreamspoilerWitches.java @@ -0,0 +1,107 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.modernmasters; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.common.continious.BoostTargetEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LevelX2 + */ +public class DreamspoilerWitches extends CardImpl { + + public DreamspoilerWitches(UUID ownerId) { + super(ownerId, 81, "Dreamspoiler Witches", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{3}{B}"); + this.expansionSetCode = "MMA"; + this.subtype.add("Faerie"); + this.subtype.add("Wizard"); + + this.color.setBlack(true); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + // Whenever you cast a spell during an opponent's turn, you may have target creature get -1/-1 until end of turn. + this.addAbility(new DreamspoilerWitchesTriggeredAbility()); + + } + + public DreamspoilerWitches(final DreamspoilerWitches card) { + super(card); + } + + @Override + public DreamspoilerWitches copy() { + return new DreamspoilerWitches(this); + } +} + +class DreamspoilerWitchesTriggeredAbility extends TriggeredAbilityImpl { + DreamspoilerWitchesTriggeredAbility() { + super(Zone.BATTLEFIELD, new BoostTargetEffect(-1,-1, Duration.EndOfTurn), true); + this.addTarget(new TargetCreaturePermanent(true)); + } + + DreamspoilerWitchesTriggeredAbility(final DreamspoilerWitchesTriggeredAbility ability) { + super(ability); + } + + @Override + public DreamspoilerWitchesTriggeredAbility copy() { + return new DreamspoilerWitchesTriggeredAbility(this); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getType() == GameEvent.EventType.SPELL_CAST + && event.getPlayerId().equals(this.controllerId) + && game.getOpponents(this.controllerId).contains(game.getActivePlayerId())) { + return true; + + } + return false; + } + + @Override + public String getRule() { + return "Whenever you cast a spell during an opponent's turn, " + super.getRule(); + } +} From 881792c36d097c1092223aad9d2f382732149fab Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Fri, 21 Jun 2013 15:42:29 +0200 Subject: [PATCH 02/22] Added Zone as parameter for SpellCastTriggeredAbility. --- .../mage/abilities/common/SpellCastTriggeredAbility.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Mage/src/mage/abilities/common/SpellCastTriggeredAbility.java b/Mage/src/mage/abilities/common/SpellCastTriggeredAbility.java index 77d4fbc309..f516c806f6 100644 --- a/Mage/src/mage/abilities/common/SpellCastTriggeredAbility.java +++ b/Mage/src/mage/abilities/common/SpellCastTriggeredAbility.java @@ -51,8 +51,7 @@ public class SpellCastTriggeredAbility extends TriggeredAbilityImpl Date: Fri, 21 Jun 2013 15:43:08 +0200 Subject: [PATCH 03/22] * Bala-Ged Thief - Fixed bug in inform players message text. --- Mage.Sets/src/mage/sets/zendikar/BalaGedThief.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mage.Sets/src/mage/sets/zendikar/BalaGedThief.java b/Mage.Sets/src/mage/sets/zendikar/BalaGedThief.java index 407148ade6..52815a1318 100644 --- a/Mage.Sets/src/mage/sets/zendikar/BalaGedThief.java +++ b/Mage.Sets/src/mage/sets/zendikar/BalaGedThief.java @@ -152,7 +152,7 @@ class BalaGedThiefEffect extends OneShotEffect { Card card = revealedCards.get(targetInHand.getFirstTarget(), game); if (card != null) { targetPlayer.discard(card, source, game); - game.informPlayers(targetPlayer + "discarded " + card.getName()); + game.informPlayers(new StringBuilder("Bala Ged Thief: ").append(targetPlayer.getName()).append(" discarded ").append(card.getName()).toString()); } } return true; From 231b7d0ac64a3644cc571994c47e032fff4126a2 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Fri, 21 Jun 2013 15:43:36 +0200 Subject: [PATCH 04/22] [MMA] Added 6 cards. --- .../src/mage/sets/lorwyn/CrushUnderfoot.java | 54 +++++++ .../src/mage/sets/lorwyn/MaskedAdmirers.java | 54 +++++++ .../src/mage/sets/lorwyn/ThievingSprite.java | 52 ++++++ .../mercadianmasques/SqueeGoblinNabob.java | 52 ++++++ .../sets/modernmasters/CrushUnderfoot.java | 119 ++++++++++++++ .../sets/modernmasters/MaskedAdmirers.java | 84 ++++++++++ .../sets/modernmasters/OonaQueenOfTheFae.java | 52 ++++++ .../sets/modernmasters/SqueeGoblinNabob.java | 52 ++++++ .../sets/modernmasters/ThievingSprite.java | 150 ++++++++++++++++++ .../sets/modernmasters/TrompTheDomains.java | 52 ++++++ .../sets/shadowmoor/OonaQueenOfTheFae.java | 145 +++++++++++++++++ .../src/mage/sets/tenth/SqueeGoblinNabob.java | 69 ++++++++ .../mage/sets/timespiral/TrompTheDomains.java | 75 +++++++++ 13 files changed, 1010 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/lorwyn/CrushUnderfoot.java create mode 100644 Mage.Sets/src/mage/sets/lorwyn/MaskedAdmirers.java create mode 100644 Mage.Sets/src/mage/sets/lorwyn/ThievingSprite.java create mode 100644 Mage.Sets/src/mage/sets/mercadianmasques/SqueeGoblinNabob.java create mode 100644 Mage.Sets/src/mage/sets/modernmasters/CrushUnderfoot.java create mode 100644 Mage.Sets/src/mage/sets/modernmasters/MaskedAdmirers.java create mode 100644 Mage.Sets/src/mage/sets/modernmasters/OonaQueenOfTheFae.java create mode 100644 Mage.Sets/src/mage/sets/modernmasters/SqueeGoblinNabob.java create mode 100644 Mage.Sets/src/mage/sets/modernmasters/ThievingSprite.java create mode 100644 Mage.Sets/src/mage/sets/modernmasters/TrompTheDomains.java create mode 100644 Mage.Sets/src/mage/sets/shadowmoor/OonaQueenOfTheFae.java create mode 100644 Mage.Sets/src/mage/sets/tenth/SqueeGoblinNabob.java create mode 100644 Mage.Sets/src/mage/sets/timespiral/TrompTheDomains.java diff --git a/Mage.Sets/src/mage/sets/lorwyn/CrushUnderfoot.java b/Mage.Sets/src/mage/sets/lorwyn/CrushUnderfoot.java new file mode 100644 index 0000000000..dffe1e600c --- /dev/null +++ b/Mage.Sets/src/mage/sets/lorwyn/CrushUnderfoot.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.lorwyn; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author LevelX2 + */ +public class CrushUnderfoot extends mage.sets.modernmasters.CrushUnderfoot { + + public CrushUnderfoot(UUID ownerId) { + super(ownerId); + this.cardNumber = 162; + this.expansionSetCode = "LRW"; + this.rarity = Rarity.UNCOMMON; + } + + public CrushUnderfoot(final CrushUnderfoot card) { + super(card); + } + + @Override + public CrushUnderfoot copy() { + return new CrushUnderfoot(this); + } +} diff --git a/Mage.Sets/src/mage/sets/lorwyn/MaskedAdmirers.java b/Mage.Sets/src/mage/sets/lorwyn/MaskedAdmirers.java new file mode 100644 index 0000000000..25ff88f6e9 --- /dev/null +++ b/Mage.Sets/src/mage/sets/lorwyn/MaskedAdmirers.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.lorwyn; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author LevelX2 + */ +public class MaskedAdmirers extends mage.sets.modernmasters.MaskedAdmirers { + + public MaskedAdmirers(UUID ownerId) { + super(ownerId); + this.cardNumber = 230; + this.expansionSetCode = "LRW"; + this.rarity = Rarity.RARE; + } + + public MaskedAdmirers(final MaskedAdmirers card) { + super(card); + } + + @Override + public MaskedAdmirers copy() { + return new MaskedAdmirers(this); + } +} diff --git a/Mage.Sets/src/mage/sets/lorwyn/ThievingSprite.java b/Mage.Sets/src/mage/sets/lorwyn/ThievingSprite.java new file mode 100644 index 0000000000..73323cfa51 --- /dev/null +++ b/Mage.Sets/src/mage/sets/lorwyn/ThievingSprite.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.lorwyn; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class ThievingSprite extends mage.sets.modernmasters.ThievingSprite { + + public ThievingSprite(UUID ownerId) { + super(ownerId); + this.cardNumber = 143; + this.expansionSetCode = "LRW"; + } + + public ThievingSprite(final ThievingSprite card) { + super(card); + } + + @Override + public ThievingSprite copy() { + return new ThievingSprite(this); + } +} diff --git a/Mage.Sets/src/mage/sets/mercadianmasques/SqueeGoblinNabob.java b/Mage.Sets/src/mage/sets/mercadianmasques/SqueeGoblinNabob.java new file mode 100644 index 0000000000..4a0cf763db --- /dev/null +++ b/Mage.Sets/src/mage/sets/mercadianmasques/SqueeGoblinNabob.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 LevelX2 + */ +public class SqueeGoblinNabob extends mage.sets.tenth.SqueeGoblinNabob { + + public SqueeGoblinNabob(UUID ownerId) { + super(ownerId); + this.cardNumber = 214; + this.expansionSetCode = "MMQ"; + } + + public SqueeGoblinNabob(final SqueeGoblinNabob card) { + super(card); + } + + @Override + public SqueeGoblinNabob copy() { + return new SqueeGoblinNabob(this); + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/CrushUnderfoot.java b/Mage.Sets/src/mage/sets/modernmasters/CrushUnderfoot.java new file mode 100644 index 0000000000..314f5b404b --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/CrushUnderfoot.java @@ -0,0 +1,119 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.modernmasters; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.Target; +import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LevelX2 + */ +public class CrushUnderfoot extends CardImpl { + + public CrushUnderfoot(UUID ownerId) { + super(ownerId, 109, "Crush Underfoot", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{1}{R}"); + this.expansionSetCode = "MMA"; + this.supertype.add("Tribal"); + this.subtype.add("Giant"); + + this.color.setRed(true); + + // Choose a Giant creature you control. It deals damage equal to its power to target creature. + this.getSpellAbility().addEffect(new CrushUnderfootEffect()); + this.getSpellAbility().addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature damage is dealt to"))); + + } + + public CrushUnderfoot(final CrushUnderfoot card) { + super(card); + } + + @Override + public CrushUnderfoot copy() { + return new CrushUnderfoot(this); + } +} + +class CrushUnderfootEffect extends OneShotEffect { + + private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("Giant you control"); + static { + filter.add(new SubtypePredicate("Giant")); + } + + public CrushUnderfootEffect() { + super(Outcome.Damage); + this.staticText = "Choose a Giant creature you control. It deals damage equal to its power to target creature"; + } + + public CrushUnderfootEffect(final CrushUnderfootEffect effect) { + super(effect); + } + + @Override + public CrushUnderfootEffect copy() { + return new CrushUnderfootEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + // Choose a Giant creature you control (not targeted, happens during effect resolving ) + Target target = new TargetControlledCreaturePermanent(1,1, filter,false); + if (target.canChoose(source.getSourceId(), controller.getId(), game) + && controller.chooseTarget(outcome, target, source, game)) { + Permanent giant = game.getPermanent(target.getFirstTarget()); + if (giant != null) { + game.informPlayers(new StringBuilder("Crush Underfoot: Choosen Giant is").append(giant.getName()).toString()); + Permanent targetCreature = game.getPermanent(this.getTargetPointer().getFirst(game, source)); + if (targetCreature != null) { + targetCreature.damage(giant.getPower().getValue(), source.getSourceId(), game, true, false); + return true; + } + } + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/MaskedAdmirers.java b/Mage.Sets/src/mage/sets/modernmasters/MaskedAdmirers.java new file mode 100644 index 0000000000..b57b228388 --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/MaskedAdmirers.java @@ -0,0 +1,84 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.modernmasters; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SpellCastTriggeredAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DoIfCostPaid; +import mage.abilities.effects.common.DrawCardControllerEffect; +import mage.abilities.effects.common.ReturnToHandSourceEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.FilterSpell; +import mage.filter.predicate.mageobject.CardTypePredicate; + +/** + * + * @author LevelX2 + */ +public class MaskedAdmirers extends CardImpl { + + private static final FilterSpell filter = new FilterSpell("a creature spell"); + static { + filter.add(new CardTypePredicate(CardType.CREATURE)); + } + + public MaskedAdmirers(UUID ownerId) { + super(ownerId, 154, "Masked Admirers", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{2}{G}{G}"); + this.expansionSetCode = "MMA"; + this.subtype.add("Elf"); + this.subtype.add("Shaman"); + + this.color.setGreen(true); + this.power = new MageInt(3); + this.toughness = new MageInt(2); + + // When Masked Admirers enters the battlefield, draw a card. + this.addAbility(new EntersBattlefieldTriggeredAbility(new DrawCardControllerEffect(1), false)); + // Whenever you cast a creature spell, you may pay {G}{G}. If you do, return Masked Admirers from your graveyard to your hand. + OneShotEffect effect = new ReturnToHandSourceEffect(); + effect.setText("return {this} from your graveyard to your hand"); + this.addAbility(new SpellCastTriggeredAbility( + Zone.GRAVEYARD, new DoIfCostPaid(effect, new ManaCostsImpl("{G}{G}")), filter, false, false)); + } + + public MaskedAdmirers(final MaskedAdmirers card) { + super(card); + } + + @Override + public MaskedAdmirers copy() { + return new MaskedAdmirers(this); + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/OonaQueenOfTheFae.java b/Mage.Sets/src/mage/sets/modernmasters/OonaQueenOfTheFae.java new file mode 100644 index 0000000000..a9e95fb502 --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/OonaQueenOfTheFae.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.modernmasters; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class OonaQueenOfTheFae extends mage.sets.shadowmoor.OonaQueenOfTheFae { + + public OonaQueenOfTheFae(UUID ownerId) { + super(ownerId); + this.cardNumber = 193; + this.expansionSetCode = "MMA"; + } + + public OonaQueenOfTheFae(final OonaQueenOfTheFae card) { + super(card); + } + + @Override + public OonaQueenOfTheFae copy() { + return new OonaQueenOfTheFae(this); + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/SqueeGoblinNabob.java b/Mage.Sets/src/mage/sets/modernmasters/SqueeGoblinNabob.java new file mode 100644 index 0000000000..6ba36633d8 --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/SqueeGoblinNabob.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.modernmasters; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class SqueeGoblinNabob extends mage.sets.tenth.SqueeGoblinNabob { + + public SqueeGoblinNabob(UUID ownerId) { + super(ownerId); + this.cardNumber = 130; + this.expansionSetCode = "MMA"; + } + + public SqueeGoblinNabob(final SqueeGoblinNabob card) { + super(card); + } + + @Override + public SqueeGoblinNabob copy() { + return new SqueeGoblinNabob(this); + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/ThievingSprite.java b/Mage.Sets/src/mage/sets/modernmasters/ThievingSprite.java new file mode 100644 index 0000000000..5a6d40d80d --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/ThievingSprite.java @@ -0,0 +1,150 @@ +/* + * 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.modernmasters; + +import java.util.List; +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.Cards; +import mage.cards.CardsImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.game.Game; +import mage.players.Player; +import mage.target.TargetCard; +import mage.target.TargetPlayer; + +/** + * + * @author LevelX2 + */ +public class ThievingSprite extends CardImpl { + + public ThievingSprite(UUID ownerId) { + super(ownerId, 101, "Thieving Sprite", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{2}{B}"); + this.expansionSetCode = "MMA"; + this.subtype.add("Faerie"); + this.subtype.add("Rogue"); + + this.color.setBlack(true); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + // When Thieving Sprite enters the battlefield, target player reveals X cards from his or her hand, where X is the number of Faeries you control. You choose one of those cards. That player discards that card. + Ability ability = new EntersBattlefieldTriggeredAbility(new ThievingSpriteEffect(), false); + TargetPlayer target = new TargetPlayer(); + target.setRequired(true); + ability.addTarget(target); + this.addAbility(ability); + + } + + public ThievingSprite(final ThievingSprite card) { + super(card); + } + + @Override + public ThievingSprite copy() { + return new ThievingSprite(this); + } +} + +class ThievingSpriteEffect extends OneShotEffect { + + public ThievingSpriteEffect() { + super(Outcome.Discard); + this.staticText = "target player reveals X cards from his or her hand, where X is the number of Faeries you control. You choose one of those cards. That player discards that card"; + } + + public ThievingSpriteEffect(final ThievingSpriteEffect effect) { + super(effect); + } + + @Override + public ThievingSpriteEffect copy() { + return new ThievingSpriteEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player targetPlayer = game.getPlayer(source.getFirstTarget()); + Player controller = game.getPlayer(source.getControllerId()); + if (targetPlayer == null || controller == null) { + return false; + } + + FilterControlledPermanent filter = new FilterControlledPermanent(); + filter.add(new SubtypePredicate("Faerie")); + int numberOfFaeries = game.getBattlefield().countAll(filter, controller.getId(), game); + + Cards cardsInHand = new CardsImpl(Zone.PICK); + cardsInHand.addAll(targetPlayer.getHand()); + int count = Math.min(cardsInHand.size(), numberOfFaeries); + + TargetCard target = new TargetCard(count, Zone.PICK, new FilterCard()); + target.setRequired(true); + Cards revealedCards = new CardsImpl(); + + if (targetPlayer.choose(Outcome.Discard, cardsInHand, target, game)) { + List targets = target.getTargets(); + for (UUID targetId : targets) { + Card card = game.getCard(targetId); + if (card != null) { + revealedCards.add(card); + } + } + } + + TargetCard targetInHand = new TargetCard(Zone.PICK, new FilterCard("card to discard")); + targetInHand.setRequired(true); + + if (!revealedCards.isEmpty()) { + targetPlayer.revealCards("Thieving Sprite", revealedCards, game); + controller.choose(Outcome.Discard, revealedCards, targetInHand, game); + Card card = revealedCards.get(targetInHand.getFirstTarget(), game); + if (card != null) { + targetPlayer.discard(card, source, game); + game.informPlayers(new StringBuilder("Thieving Sprite").append(targetPlayer.getName()).append("discarded ").append(card.getName()).toString()); + } + } + return true; + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/TrompTheDomains.java b/Mage.Sets/src/mage/sets/modernmasters/TrompTheDomains.java new file mode 100644 index 0000000000..8746082ff4 --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/TrompTheDomains.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.modernmasters; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class TrompTheDomains extends mage.sets.timespiral.TrompTheDomains { + + public TrompTheDomains(UUID ownerId) { + super(ownerId); + this.cardNumber = 171; + this.expansionSetCode = "MMA"; + } + + public TrompTheDomains(final TrompTheDomains card) { + super(card); + } + + @Override + public TrompTheDomains copy() { + return new TrompTheDomains(this); + } +} diff --git a/Mage.Sets/src/mage/sets/shadowmoor/OonaQueenOfTheFae.java b/Mage.Sets/src/mage/sets/shadowmoor/OonaQueenOfTheFae.java new file mode 100644 index 0000000000..99c85b34d5 --- /dev/null +++ b/Mage.Sets/src/mage/sets/shadowmoor/OonaQueenOfTheFae.java @@ -0,0 +1,145 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.shadowmoor; + +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.OneShotEffect; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.choices.ChoiceColor; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.permanent.token.Token; +import mage.players.Player; +import mage.target.common.TargetOpponent; + +/** + * + * @author LevelX2 + */ +public class OonaQueenOfTheFae extends CardImpl { + + public OonaQueenOfTheFae(UUID ownerId) { + super(ownerId, 172, "Oona, Queen of the Fae", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{3}{U/B}{U/B}{U/B}"); + this.expansionSetCode = "SHM"; + this.supertype.add("Legendary"); + this.subtype.add("Faerie"); + this.subtype.add("Wizard"); + + this.color.setBlue(true); + this.color.setBlack(true); + this.power = new MageInt(5); + this.toughness = new MageInt(5); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + // {X}{UB}: Choose a color. Target opponent exiles the top X cards of his or her library. For each card of the chosen color exiled this way, put a 1/1 blue and black Faerie Rogue creature token with flying onto the battlefield. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new OonaQueenOfTheFaeEffect(), new ManaCostsImpl("{X}{U/B}")); + ability.addTarget(new TargetOpponent(true)); + this.addAbility(ability); + } + + public OonaQueenOfTheFae(final OonaQueenOfTheFae card) { + super(card); + } + + @Override + public OonaQueenOfTheFae copy() { + return new OonaQueenOfTheFae(this); + } +} + +class OonaQueenOfTheFaeEffect extends OneShotEffect { + + public OonaQueenOfTheFaeEffect() { + super(Outcome.PutCreatureInPlay); + this.staticText = "Choose a color. Target opponent exiles the top X cards of his or her library. For each card of the chosen color exiled this way, put a 1/1 blue and black Faerie Rogue creature token with flying onto the battlefield"; + } + + public OonaQueenOfTheFaeEffect(final OonaQueenOfTheFaeEffect effect) { + super(effect); + } + + @Override + public OonaQueenOfTheFaeEffect copy() { + return new OonaQueenOfTheFaeEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Player opponent = game.getPlayer(getTargetPointer().getFirst(game, source)); + if (controller == null || opponent == null) { + return false; + } + ChoiceColor choice = new ChoiceColor(); + controller.choose(outcome, choice, game); + if (choice.getColor() != null) { + int cardsWithColor = 0; + int cardsToExile = Math.min(opponent.getLibrary().size(), source.getManaCostsToPay().getX()); + for(int i = 0; i < cardsToExile; i++) { + Card card = opponent.getLibrary().removeFromTop(game); + if (card != null) { + if (card.getColor().contains(choice.getColor())) { + cardsWithColor++; + } + card.moveToExile(null, null, source.getSourceId(), game); + } + } + if (cardsWithColor > 0) { + new CreateTokenEffect(new OonaQueenFaerieToken(), cardsWithColor).apply(game, source); + } + game.informPlayers(new StringBuilder("Oona: ").append(cardsWithColor).append(" Token").append(cardsWithColor != 1?"s":"").append(" created").toString()); + return true; + } + return false; + } +} + +class OonaQueenFaerieToken extends Token { + OonaQueenFaerieToken() { + super("Faerie Rogue", "1/1 blue and black Faerie Rogue creature token with flying"); + cardType.add(CardType.CREATURE); + color.setBlue(true); + color.setBlack(true); + subtype.add("Faerie"); + subtype.add("Rogue"); + power = new MageInt(1); + toughness = new MageInt(1); + this.addAbility(FlyingAbility.getInstance()); + } +} diff --git a/Mage.Sets/src/mage/sets/tenth/SqueeGoblinNabob.java b/Mage.Sets/src/mage/sets/tenth/SqueeGoblinNabob.java new file mode 100644 index 0000000000..69651d5dbf --- /dev/null +++ b/Mage.Sets/src/mage/sets/tenth/SqueeGoblinNabob.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.tenth; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.effects.common.ReturnToHandSourceEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.constants.Zone; + +/** + * + * @author LevelX2 + */ +public class SqueeGoblinNabob extends CardImpl { + + public SqueeGoblinNabob(UUID ownerId) { + super(ownerId, 239, "Squee, Goblin Nabob", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{2}{R}"); + this.expansionSetCode = "10E"; + this.supertype.add("Legendary"); + this.subtype.add("Goblin"); + + this.color.setRed(true); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // At the beginning of your upkeep, you may return Squee, Goblin Nabob from your graveyard to your hand. + this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.GRAVEYARD, new ReturnToHandSourceEffect(), TargetController.YOU, true)); + } + + public SqueeGoblinNabob(final SqueeGoblinNabob card) { + super(card); + } + + @Override + public SqueeGoblinNabob copy() { + return new SqueeGoblinNabob(this); + } +} diff --git a/Mage.Sets/src/mage/sets/timespiral/TrompTheDomains.java b/Mage.Sets/src/mage/sets/timespiral/TrompTheDomains.java new file mode 100644 index 0000000000..329d08a2d5 --- /dev/null +++ b/Mage.Sets/src/mage/sets/timespiral/TrompTheDomains.java @@ -0,0 +1,75 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.timespiral; + +import java.util.UUID; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.DomainValue; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.continious.BoostControlledEffect; +import mage.abilities.effects.common.continious.GainAbilityControlledEffect; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.common.FilterCreaturePermanent; + +/** + * + * @author LevelX2 + */ +public class TrompTheDomains extends CardImpl { + + public TrompTheDomains(UUID ownerId) { + super(ownerId, 230, "Tromp the Domains", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{5}{G}"); + this.expansionSetCode = "TSP"; + + this.color.setGreen(true); + + // Domain - Until end of turn, creatures you control gain trample and get +1/+1 for each basic land type among lands you control. + Effect effect = new GainAbilityControlledEffect(TrampleAbility.getInstance(), Duration.EndOfTurn); + effect.setText("Domain - Until end of turn, creatures you control gain Trample"); + this.getSpellAbility().addEffect(effect); + DynamicValue domain = new DomainValue(); + effect = new BoostControlledEffect(domain, domain, Duration.EndOfTurn, new FilterCreaturePermanent(), false); + effect.setText(" and get +1/+1 for each basic land type among lands you control"); + this.getSpellAbility().addEffect(effect); + + } + + public TrompTheDomains(final TrompTheDomains card) { + super(card); + } + + @Override + public TrompTheDomains copy() { + return new TrompTheDomains(this); + } +} From 250f860298187e61a1ea7fd9795a7530f8ac168c Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Fri, 21 Jun 2013 21:28:19 +0200 Subject: [PATCH 05/22] * Retrace Ability - Added Reminder text. --- Mage/src/mage/abilities/keyword/RetraceAbility.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Mage/src/mage/abilities/keyword/RetraceAbility.java b/Mage/src/mage/abilities/keyword/RetraceAbility.java index cb15ed7964..2347e17827 100644 --- a/Mage/src/mage/abilities/keyword/RetraceAbility.java +++ b/Mage/src/mage/abilities/keyword/RetraceAbility.java @@ -67,9 +67,7 @@ public class RetraceAbility extends ActivatedAbilityImpl { @Override public String getRule() { - StringBuilder sbRule = new StringBuilder("Retrace"); - - return sbRule.toString(); + return "Retrace (You may cast this card from your graveyard by discarding a land card in addition to paying its other costs.)"; } } class RetraceEffect extends OneShotEffect { From 514d21375ce6da46bc3e8b4a0849ecd80a6af5fe Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Fri, 21 Jun 2013 21:30:24 +0200 Subject: [PATCH 06/22] [minor] SunburstCount prevent exception. --- .../condition/common/SuspendedCondition.java | 10 ++--- .../dynamicvalue/common/SunburstCount.java | 37 ++++++++++--------- 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/Mage/src/mage/abilities/condition/common/SuspendedCondition.java b/Mage/src/mage/abilities/condition/common/SuspendedCondition.java index 361b45879f..3b2538b584 100644 --- a/Mage/src/mage/abilities/condition/common/SuspendedCondition.java +++ b/Mage/src/mage/abilities/condition/common/SuspendedCondition.java @@ -69,11 +69,11 @@ public class SuspendedCondition implements Condition { break; } } - } - if (found) { - if (game.getState().getZone(card.getId()) == Zone.EXILED && - card.getCounters().getCount(CounterType.TIME) > 0) { - return true; + if (found) { + if (game.getState().getZone(card.getId()) == Zone.EXILED && + card.getCounters().getCount(CounterType.TIME) > 0) { + return true; + } } } return false; diff --git a/Mage/src/mage/abilities/dynamicvalue/common/SunburstCount.java b/Mage/src/mage/abilities/dynamicvalue/common/SunburstCount.java index b3e76851de..74ec3946fa 100644 --- a/Mage/src/mage/abilities/dynamicvalue/common/SunburstCount.java +++ b/Mage/src/mage/abilities/dynamicvalue/common/SunburstCount.java @@ -49,24 +49,25 @@ public class SunburstCount implements DynamicValue{ @Override public int calculate(Game game, Ability source) { int count = 0; - - StackObject spell = game.getStack().getFirst(); - if (spell != null && spell instanceof Spell && ((Spell)spell).getSourceId().equals(source.getSourceId())) { - Mana mana = ((Spell)spell).getSpellAbility().getManaCostsToPay().getPayment(); - if(mana.getBlack() > 0) { - count++; - } - if(mana.getBlue() > 0) { - count++; - } - if(mana.getGreen() > 0) { - count++; - } - if(mana.getRed() > 0) { - count++; - } - if(mana.getWhite() > 0) { - count++; + if (!game.getStack().isEmpty()) { + StackObject spell = game.getStack().getFirst(); + if (spell != null && spell instanceof Spell && ((Spell)spell).getSourceId().equals(source.getSourceId())) { + Mana mana = ((Spell)spell).getSpellAbility().getManaCostsToPay().getPayment(); + if(mana.getBlack() > 0) { + count++; + } + if(mana.getBlue() > 0) { + count++; + } + if(mana.getGreen() > 0) { + count++; + } + if(mana.getRed() > 0) { + count++; + } + if(mana.getWhite() > 0) { + count++; + } } } return count; From a573d2c0266e778a334edd72fd35573b05f5dfbe Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Fri, 21 Jun 2013 21:30:56 +0200 Subject: [PATCH 07/22] [minor] Improved inform text of Death denied. --- Mage.Sets/src/mage/sets/saviorsofkamigawa/DeathDenied.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mage.Sets/src/mage/sets/saviorsofkamigawa/DeathDenied.java b/Mage.Sets/src/mage/sets/saviorsofkamigawa/DeathDenied.java index 13d82da31d..3a3a0b578d 100644 --- a/Mage.Sets/src/mage/sets/saviorsofkamigawa/DeathDenied.java +++ b/Mage.Sets/src/mage/sets/saviorsofkamigawa/DeathDenied.java @@ -66,7 +66,7 @@ public class DeathDenied extends CardImpl { if (ability instanceof SpellAbility) { ability.getTargets().clear(); int xValue = ability.getManaCostsToPay().getX(); - Target target = new TargetCardInYourGraveyard(xValue, new FilterCreatureCard(new StringBuilder(xValue).append(xValue != 1?" creatures":"creature").toString())); + Target target = new TargetCardInYourGraveyard(xValue, new FilterCreatureCard(new StringBuilder(xValue).append(xValue != 1?" creature cards":"creature card").append(" from your graveyard").toString())); ability.addTarget(target); } } From 738efcc47fef97d8209a688304611bca40d1f8db Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Fri, 21 Jun 2013 21:34:06 +0200 Subject: [PATCH 08/22] Added option to select time limit (also none) on match or tournament creation. --- .../mage/client/dialog/NewTableDialog.form | 82 +++++++----- .../mage/client/dialog/NewTableDialog.java | 99 +++++++++------ .../client/dialog/NewTournamentDialog.form | 120 +++++++++--------- .../client/dialog/NewTournamentDialog.java | 107 +++++++++------- .../mage/client/dialog/PreferencesDialog.java | 1 + .../main/java/mage/client/game/GamePanel.java | 4 +- .../java/mage/client/game/PlayAreaPanel.java | 8 +- .../java/mage/client/game/PlayerPanelExt.java | 57 +++++---- Mage.Common/src/mage/view/GameView.java | 8 ++ .../java/mage/server/game/GameController.java | 12 +- Mage/src/mage/constants/MatchTimeLimit.java | 37 ++++++ Mage/src/mage/game/Game.java | 2 + Mage/src/mage/game/GameImpl.java | 28 +++- Mage/src/mage/game/match/MatchImpl.java | 1 + Mage/src/mage/game/match/MatchOptions.java | 15 +++ 15 files changed, 367 insertions(+), 214 deletions(-) create mode 100644 Mage/src/mage/constants/MatchTimeLimit.java diff --git a/Mage.Client/src/main/java/mage/client/dialog/NewTableDialog.form b/Mage.Client/src/main/java/mage/client/dialog/NewTableDialog.form index 5dfc2743e9..cec7d3c43e 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/NewTableDialog.form +++ b/Mage.Client/src/main/java/mage/client/dialog/NewTableDialog.form @@ -25,41 +25,49 @@ - - - - - - - - - - + + - + + + + + + + + + + + + + + + + + - - - + + + + + - - - + - - + + @@ -88,6 +96,7 @@ + @@ -98,7 +107,7 @@ - + @@ -107,17 +116,19 @@ - - - - - - - + + + + + + + + + @@ -157,10 +168,12 @@ - + + + - + @@ -174,7 +187,7 @@ - + @@ -198,6 +211,13 @@ + + + + + + + @@ -281,6 +301,8 @@ + + diff --git a/Mage.Client/src/main/java/mage/client/dialog/NewTableDialog.java b/Mage.Client/src/main/java/mage/client/dialog/NewTableDialog.java index 655f289493..8f55740296 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/NewTableDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/NewTableDialog.java @@ -27,21 +27,23 @@ */ package mage.client.dialog; - import java.io.FileNotFoundException; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.UUID; -import javax.swing.*; -import mage.constants.MultiplayerAttackOption; -import mage.constants.RangeOfInfluence; +import javax.swing.DefaultComboBoxModel; +import javax.swing.JOptionPane; +import javax.swing.SpinnerNumberModel; import mage.cards.decks.importer.DeckImporterUtil; import mage.client.MageFrame; import mage.client.components.MageComponents; -import mage.client.table.*; +import mage.client.table.TablePlayerPanel; import mage.client.util.Event; import mage.client.util.Listener; +import mage.constants.MatchTimeLimit; +import mage.constants.MultiplayerAttackOption; +import mage.constants.RangeOfInfluence; import mage.game.match.MatchOptions; import mage.remote.Session; import mage.view.GameTypeView; @@ -85,6 +87,8 @@ public class NewTableDialog extends MageDialog { txtName = new javax.swing.JTextField(); lbDeckType = new javax.swing.JLabel(); cbDeckType = new javax.swing.JComboBox(); + lbTimeLimit = new javax.swing.JLabel(); + cbTimeLimit = new javax.swing.JComboBox(); lblGameType = new javax.swing.JLabel(); cbGameType = new javax.swing.JComboBox(); lblFreeMulligans = new javax.swing.JLabel(); @@ -114,6 +118,8 @@ public class NewTableDialog extends MageDialog { lbDeckType.setText("Deck Type:"); + lbTimeLimit.setText("Time Limit:"); + lblGameType.setText("Game Type:"); cbGameType.addActionListener(new java.awt.event.ActionListener() { @@ -177,33 +183,39 @@ public class NewTableDialog extends MageDialog { .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() - .addContainerGap() - .addComponent(jLabel1)) - .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() - .addContainerGap() - .addComponent(jLabel2)) - .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() .addGap(16, 16, 16) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addComponent(lbDeckType) .addComponent(lblGameType) - .addComponent(lblName)) + .addComponent(lblName))) + .addGroup(layout.createSequentialGroup() + .addGap(30, 30, 30) + .addComponent(lbDeckType))) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(cbGameType, javax.swing.GroupLayout.PREFERRED_SIZE, 398, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(lblFreeMulligans) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(spnFreeMulligans, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, Short.MAX_VALUE)) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addGap(0, 0, Short.MAX_VALUE) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) - .addComponent(cbDeckType, javax.swing.GroupLayout.Alignment.LEADING, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() - .addComponent(cbGameType, javax.swing.GroupLayout.PREFERRED_SIZE, 398, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(txtName, javax.swing.GroupLayout.PREFERRED_SIZE, 546, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGroup(layout.createSequentialGroup() + .addComponent(cbDeckType, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(lbTimeLimit) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(lblFreeMulligans) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(spnFreeMulligans, javax.swing.GroupLayout.DEFAULT_SIZE, 50, Short.MAX_VALUE)) - .addComponent(txtName)))) - .addGap(0, 0, Short.MAX_VALUE)) + .addComponent(cbTimeLimit, javax.swing.GroupLayout.PREFERRED_SIZE, 126, javax.swing.GroupLayout.PREFERRED_SIZE)))))) .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(jLabel1, javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabel2, javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addGap(0, 0, Short.MAX_VALUE) .addComponent(btnOK) @@ -233,27 +245,30 @@ public class NewTableDialog extends MageDialog { .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() - .addComponent(jSeparator3, javax.swing.GroupLayout.DEFAULT_SIZE, 625, Short.MAX_VALUE) + .addComponent(jSeparator3, javax.swing.GroupLayout.DEFAULT_SIZE, 633, Short.MAX_VALUE) .addContainerGap())) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addComponent(lblName) .addComponent(txtName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addComponent(lbDeckType) - .addComponent(cbDeckType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(cbGameType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lblGameType) + .addComponent(cbDeckType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(cbTimeLimit, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(lbDeckType) + .addComponent(lbTimeLimit)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(spnFreeMulligans, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lblFreeMulligans))) + .addComponent(lblFreeMulligans)) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(cbGameType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(lblGameType))) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) @@ -282,7 +297,7 @@ public class NewTableDialog extends MageDialog { .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(jLabel2) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(pnlOtherPlayers, javax.swing.GroupLayout.DEFAULT_SIZE, 140, Short.MAX_VALUE) + .addComponent(pnlOtherPlayers, javax.swing.GroupLayout.DEFAULT_SIZE, 144, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) @@ -294,7 +309,7 @@ public class NewTableDialog extends MageDialog { .addGroup(layout.createSequentialGroup() .addGap(201, 201, 201) .addComponent(jSeparator3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addContainerGap(240, Short.MAX_VALUE))) + .addContainerGap(244, Short.MAX_VALUE))) ); pack(); @@ -315,6 +330,7 @@ public class NewTableDialog extends MageDialog { } options.setDeckType((String) this.cbDeckType.getSelectedItem()); options.setLimited(false); + options.setMatchTimeLimit((MatchTimeLimit) this.cbTimeLimit.getSelectedItem()); options.setAttackOption((MultiplayerAttackOption) this.cbAttackOption.getSelectedItem()); options.setRange((RangeOfInfluence) this.cbRange.getSelectedItem()); options.setWinsNeeded((Integer)this.spnNumWins.getValue()); @@ -422,6 +438,7 @@ public class NewTableDialog extends MageDialog { cbGameType.setModel(new DefaultComboBoxModel(session.getGameTypes().toArray())); cbDeckType.setModel(new DefaultComboBoxModel(session.getDeckTypes())); selectLimitedByDefault(); + cbTimeLimit.setModel(new DefaultComboBoxModel(MatchTimeLimit.values())); cbRange.setModel(new DefaultComboBoxModel(RangeOfInfluence.values())); cbAttackOption.setModel(new DefaultComboBoxModel(MultiplayerAttackOption.values())); @@ -464,13 +481,19 @@ public class NewTableDialog extends MageDialog { break; } } + int timeLimit = Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TABLE_TIME_LIMIT, "0")); + for (MatchTimeLimit mtl :MatchTimeLimit.values()) { + if (mtl.getTimeLimit() == timeLimit) { + this.cbTimeLimit.setSelectedItem(mtl); + break; + } + } cbDeckType.setSelectedItem(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TABLE_DECK_TYPE, "Limited")); String deckFile = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TABLE_DECK_FILE, null); if (deckFile != null) { this.player1Panel.setDeckFile(deckFile); } this.spnNumWins.setValue(Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TABLE_NUMBER_OF_WINS, "2"))); - this.spnFreeMulligans.setValue(Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TABLE_NUMBER_OF_FREE_MULLIGANS, "0"))); this.spnNumPlayers.setValue(Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TABLE_NUMBER_PLAYERS, "2"))); int range = Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TABLE_RANGE, "1")); for (RangeOfInfluence roi :RangeOfInfluence.values()) { @@ -497,9 +520,9 @@ public class NewTableDialog extends MageDialog { private void saveGameSettingsToPrefs(MatchOptions options, String deckFile) { PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_NAME, options.getName()); PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_DECK_TYPE, options.getDeckType()); + PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_TIME_LIMIT, Integer.toString(options.getPriorityTime())); PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_GAME_TYPE, options.getGameType()); PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_NUMBER_OF_WINS, Integer.toString(options.getWinsNeeded())); - PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_NUMBER_OF_FREE_MULLIGANS, Integer.toString(options.getFreeMulligans())); PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_DECK_FILE, deckFile); PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_NUMBER_PLAYERS, spnNumPlayers.getValue().toString()); PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_RANGE, Integer.toString(options.getRange().getRange())); @@ -513,12 +536,14 @@ public class NewTableDialog extends MageDialog { private javax.swing.JComboBox cbDeckType; private javax.swing.JComboBox cbGameType; private javax.swing.JComboBox cbRange; + private javax.swing.JComboBox cbTimeLimit; private javax.swing.JLabel jLabel1; private javax.swing.JLabel jLabel2; private javax.swing.JSeparator jSeparator1; private javax.swing.JSeparator jSeparator2; private javax.swing.JSeparator jSeparator3; private javax.swing.JLabel lbDeckType; + private javax.swing.JLabel lbTimeLimit; private javax.swing.JLabel lblAttack; private javax.swing.JLabel lblFreeMulligans; private javax.swing.JLabel lblGameType; @@ -534,4 +559,4 @@ public class NewTableDialog extends MageDialog { private javax.swing.JTextField txtName; // End of variables declaration//GEN-END:variables -} \ No newline at end of file +} diff --git a/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.form b/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.form index a11795a921..d2b4221f2d 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.form +++ b/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.form @@ -27,36 +27,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -73,6 +43,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -85,39 +91,30 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - + - + @@ -140,6 +137,13 @@ + + + + + + + @@ -233,7 +237,7 @@ - + diff --git a/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java b/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java index 497513246e..04a623f5fd 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java @@ -41,12 +41,13 @@ import javax.swing.DefaultComboBoxModel; import javax.swing.JComboBox; import javax.swing.JOptionPane; import javax.swing.SpinnerNumberModel; -import mage.constants.MultiplayerAttackOption; -import mage.constants.RangeOfInfluence; import mage.cards.ExpansionSet; import mage.cards.Sets; import mage.client.MageFrame; import mage.client.table.TournamentPlayerPanel; +import mage.constants.MatchTimeLimit; +import mage.constants.MultiplayerAttackOption; +import mage.constants.RangeOfInfluence; import mage.game.draft.DraftOptions; import mage.game.draft.DraftOptions.TimingOption; import mage.game.tournament.LimitedOptions; @@ -86,6 +87,7 @@ public class NewTournamentDialog extends MageDialog { session = MageFrame.getSession(); this.txtPlayer1Name.setText(session.getUserName()); cbTournamentType.setModel(new DefaultComboBoxModel(session.getTournamentTypes().toArray())); + cbTimeLimit.setModel(new DefaultComboBoxModel(MatchTimeLimit.values())); cbDraftTiming.setModel(new DefaultComboBoxModel(DraftOptions.TimingOption.values())); this.setModal(true); setTournamentOptions(); @@ -104,6 +106,8 @@ public class NewTournamentDialog extends MageDialog { lblName = new javax.swing.JLabel(); txtName = new javax.swing.JTextField(); + lbTimeLimit = new javax.swing.JLabel(); + cbTimeLimit = new javax.swing.JComboBox(); lblConstructionTime = new javax.swing.JLabel(); spnConstructTime = new javax.swing.JSpinner(); jLabel1 = new javax.swing.JLabel(); @@ -131,6 +135,8 @@ public class NewTournamentDialog extends MageDialog { lblName.setText("Name:"); + lbTimeLimit.setText("Time Limit:"); + lblConstructionTime.setText("Construction Time (Minutes):"); jLabel1.setText("Tournament Type:"); @@ -198,7 +204,7 @@ public class NewTournamentDialog extends MageDialog { .addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanel1Layout.createSequentialGroup() .addComponent(jLabel4) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(txtPlayer1Name, javax.swing.GroupLayout.DEFAULT_SIZE, 638, Short.MAX_VALUE))) + .addComponent(txtPlayer1Name))) .addContainerGap()) ); jPanel1Layout.setVerticalGroup( @@ -247,29 +253,6 @@ public class NewTournamentDialog extends MageDialog { .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addComponent(jPanel1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(pnlPacks, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addComponent(lblName) - .addComponent(jLabel1)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) - .addComponent(txtName) - .addComponent(cbTournamentType, 0, 330, Short.MAX_VALUE)) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(lblFreeMulligans) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(spnFreeMulligans) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(lblNumWins)) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() - .addGap(19, 19, 19) - .addComponent(lblConstructionTime))) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) - .addComponent(spnConstructTime, javax.swing.GroupLayout.DEFAULT_SIZE, 48, Short.MAX_VALUE) - .addComponent(spnNumWins))) .addGroup(layout.createSequentialGroup() .addGap(0, 0, Short.MAX_VALUE) .addComponent(btnOk) @@ -283,7 +266,36 @@ public class NewTournamentDialog extends MageDialog { .addComponent(spnNumPlayers, javax.swing.GroupLayout.PREFERRED_SIZE, 45, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(pnlDraftOptions, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addComponent(jLabel5, javax.swing.GroupLayout.Alignment.LEADING)) + .addComponent(jLabel5, javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) + .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() + .addComponent(lblName) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(txtName, javax.swing.GroupLayout.PREFERRED_SIZE, 233, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(lbTimeLimit) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(cbTimeLimit, 0, 115, Short.MAX_VALUE)) + .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() + .addComponent(jLabel1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(cbTournamentType, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(lblFreeMulligans) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(spnFreeMulligans, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(lblNumWins) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(spnNumWins, javax.swing.GroupLayout.PREFERRED_SIZE, 41, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addGap(23, 23, 23) + .addComponent(lblConstructionTime) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(spnConstructTime, javax.swing.GroupLayout.PREFERRED_SIZE, 41, javax.swing.GroupLayout.PREFERRED_SIZE))))) .addGap(0, 0, Short.MAX_VALUE))) .addContainerGap()) ); @@ -291,32 +303,28 @@ public class NewTournamentDialog extends MageDialog { layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addGroup(layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(txtName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lblName)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(jLabel1) - .addComponent(cbTournamentType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))) - .addGroup(layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(lblConstructionTime) - .addComponent(spnConstructTime, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(spnNumWins, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lblNumWins) - .addComponent(spnFreeMulligans, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lblFreeMulligans)))) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(txtName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(lblName) + .addComponent(lbTimeLimit) + .addComponent(cbTimeLimit, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(lblConstructionTime) + .addComponent(spnConstructTime, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel1) + .addComponent(cbTournamentType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(lblFreeMulligans) + .addComponent(spnFreeMulligans, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(lblNumWins) + .addComponent(spnNumWins, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jLabel5) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(pnlPacks, javax.swing.GroupLayout.DEFAULT_SIZE, 65, Short.MAX_VALUE) + .addComponent(pnlPacks, javax.swing.GroupLayout.DEFAULT_SIZE, 60, Short.MAX_VALUE) .addGap(11, 11, 11) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(spnNumPlayers, javax.swing.GroupLayout.DEFAULT_SIZE, 28, Short.MAX_VALUE) + .addComponent(spnNumPlayers, javax.swing.GroupLayout.DEFAULT_SIZE, 23, Short.MAX_VALUE) .addComponent(pnlDraftOptions, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(jLabel2)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) @@ -357,6 +365,7 @@ public class NewTournamentDialog extends MageDialog { tOptions.getLimitedOptions().getSetCodes().add(((ExpansionSet) pack.getSelectedItem()).getCode()); } } + tOptions.getMatchOptions().setMatchTimeLimit((MatchTimeLimit) this.cbTimeLimit.getSelectedItem()); tOptions.getMatchOptions().setDeckType("Limited"); tOptions.getMatchOptions().setWinsNeeded((Integer)this.spnNumWins.getValue()); tOptions.getMatchOptions().setFreeMulligans((Integer)this.spnFreeMulligans.getValue()); @@ -512,6 +521,7 @@ public class NewTournamentDialog extends MageDialog { private javax.swing.JButton btnCancel; private javax.swing.JButton btnOk; private javax.swing.JComboBox cbDraftTiming; + private javax.swing.JComboBox cbTimeLimit; private javax.swing.JComboBox cbTournamentType; private javax.swing.JLabel jLabel1; private javax.swing.JLabel jLabel2; @@ -520,6 +530,7 @@ public class NewTournamentDialog extends MageDialog { private javax.swing.JLabel jLabel5; private javax.swing.JLabel jLabel6; private javax.swing.JPanel jPanel1; + private javax.swing.JLabel lbTimeLimit; private javax.swing.JLabel lblConstructionTime; private javax.swing.JLabel lblFreeMulligans; private javax.swing.JLabel lblName; diff --git a/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java b/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java index bef9caf4f9..46f230051d 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java @@ -92,6 +92,7 @@ public class PreferencesDialog extends javax.swing.JDialog { // default setting for new table dialog public static final String KEY_NEW_TABLE_NAME = "newTableName"; public static final String KEY_NEW_TABLE_DECK_TYPE = "newTableDeckType"; + public static final String KEY_NEW_TABLE_TIME_LIMIT = "newTableTimeLimit"; public static final String KEY_NEW_TABLE_GAME_TYPE = "newTableGameType"; public static final String KEY_NEW_TABLE_NUMBER_OF_WINS = "newTableNumberOfWins"; public static final String KEY_NEW_TABLE_NUMBER_OF_FREE_MULLIGANS = "newTableNumberOfFreeMulligans"; diff --git a/Mage.Client/src/main/java/mage/client/game/GamePanel.java b/Mage.Client/src/main/java/mage/client/game/GamePanel.java index d5e08a492e..fa4137f843 100644 --- a/Mage.Client/src/main/java/mage/client/game/GamePanel.java +++ b/Mage.Client/src/main/java/mage/client/game/GamePanel.java @@ -353,7 +353,7 @@ public final class GamePanel extends javax.swing.JPanel { } } PlayerView player = game.getPlayers().get(playerSeat); - PlayAreaPanel sessionPlayer = new PlayAreaPanel(player, bigCard, gameId, true); + PlayAreaPanel sessionPlayer = new PlayAreaPanel(player, bigCard, gameId, true, game.getPriorityTime()); players.put(player.getPlayerId(), sessionPlayer); GridBagConstraints c = new GridBagConstraints(); c.fill = GridBagConstraints.BOTH; @@ -385,7 +385,7 @@ public final class GamePanel extends javax.swing.JPanel { col = numColumns - 1; } player = game.getPlayers().get(playerNum); - PlayAreaPanel playerPanel = new PlayAreaPanel(player, bigCard, gameId, false); + PlayAreaPanel playerPanel = new PlayAreaPanel(player, bigCard, gameId, false, game.getPriorityTime()); players.put(player.getPlayerId(), playerPanel); c = new GridBagConstraints(); c.fill = GridBagConstraints.BOTH; diff --git a/Mage.Client/src/main/java/mage/client/game/PlayAreaPanel.java b/Mage.Client/src/main/java/mage/client/game/PlayAreaPanel.java index 5f763feb96..48a77a1ec3 100644 --- a/Mage.Client/src/main/java/mage/client/game/PlayAreaPanel.java +++ b/Mage.Client/src/main/java/mage/client/game/PlayAreaPanel.java @@ -64,9 +64,9 @@ public class PlayAreaPanel extends javax.swing.JPanel { addPopupMenu(); } - public PlayAreaPanel(PlayerView player, BigCard bigCard, UUID gameId, boolean me) { + public PlayAreaPanel(PlayerView player, BigCard bigCard, UUID gameId, boolean me, int priorityTime) { this(); - init(player, bigCard, gameId); + init(player, bigCard, gameId, priorityTime); update(player); } @@ -99,8 +99,8 @@ public class PlayAreaPanel extends javax.swing.JPanel { }); } - public final void init(PlayerView player, BigCard bigCard, UUID gameId) { - this.playerPanel.init(gameId, player.getPlayerId(), bigCard); + public final void init(PlayerView player, BigCard bigCard, UUID gameId, int priorityTime) { + this.playerPanel.init(gameId, player.getPlayerId(), bigCard, priorityTime); this.battlefieldPanel.init(gameId, bigCard); this.gameId = gameId; if (MageFrame.getSession().isTestMode()) { diff --git a/Mage.Client/src/main/java/mage/client/game/PlayerPanelExt.java b/Mage.Client/src/main/java/mage/client/game/PlayerPanelExt.java index 3a93ad629a..8209c85600 100644 --- a/Mage.Client/src/main/java/mage/client/game/PlayerPanelExt.java +++ b/Mage.Client/src/main/java/mage/client/game/PlayerPanelExt.java @@ -52,7 +52,6 @@ import mage.client.util.Command; import mage.client.util.ImageHelper; import mage.client.util.gui.BufferedImageBuilder; import mage.components.ImagePanel; -import mage.constants.Constants; import mage.remote.Session; import mage.utils.timer.PriorityTimer; import mage.view.CardView; @@ -112,7 +111,7 @@ public class PlayerPanelExt extends javax.swing.JPanel { initComponents(); } - public void init(UUID gameId, UUID playerId, BigCard bigCard) { + public void init(UUID gameId, UUID playerId, BigCard bigCard, int priorityTime) { this.gameId = gameId; this.playerId = playerId; this.bigCard = bigCard; @@ -120,24 +119,27 @@ public class PlayerPanelExt extends javax.swing.JPanel { cheat.setVisible(session.isTestMode()); cheat.setFocusable(false); - long delay = 1000L; - timer = new PriorityTimer(Constants.PRIORITY_TIME_SEC, delay, new mage.interfaces.Action() { - @Override - public void execute() throws MageException { - // do nothing - } - }); - final PriorityTimer pt = timer; - timer.setTaskOnTick(new mage.interfaces.Action() { - @Override - public void execute() throws MageException { - int priorityTimeValue = pt.getCount(); - String text = getPriorityTimeLeftString(priorityTimeValue); - PlayerPanelExt.this.avatar.setTopText(text); - PlayerPanelExt.this.avatar.repaint(); - } - }); - timer.init(); + if (priorityTime > 0) { + long delay = 1000L; + + timer = new PriorityTimer(priorityTime, delay, new mage.interfaces.Action() { + @Override + public void execute() throws MageException { + // do nothing + } + }); + final PriorityTimer pt = timer; + timer.setTaskOnTick(new mage.interfaces.Action() { + @Override + public void execute() throws MageException { + int priorityTimeValue = pt.getCount(); + String text = getPriorityTimeLeftString(priorityTimeValue); + PlayerPanelExt.this.avatar.setTopText(text); + PlayerPanelExt.this.avatar.repaint(); + } + }); + timer.init(); + } } public void update(PlayerView player) { @@ -206,11 +208,19 @@ public class PlayerPanelExt extends javax.swing.JPanel { } } this.avatar.setText(player.getName()); - if (player.getPriorityTimeLeft() != Integer.MAX_VALUE) { + if (this.timer != null) { + if (player.getPriorityTimeLeft() != Integer.MAX_VALUE) { String priorityTimeValue = getPriorityTimeLeftString(player); this.timer.setCount(player.getPriorityTimeLeft()); this.avatar.setTopText(priorityTimeValue); + } + if (player.hasPriority()) { + this.timer.resume(); + } else { + this.timer.pause(); + } } + this.btnPlayer.setText(player.getName()); if (player.isActive()) { this.avatar.setBorder(greenBorder); @@ -223,11 +233,6 @@ public class PlayerPanelExt extends javax.swing.JPanel { this.btnPlayer.setBorder(emptyBorder); } - if (player.hasPriority()) { - this.timer.resume(); - } else { - this.timer.pause(); - } synchronized (this) { if (player.getTopCard() != null) { diff --git a/Mage.Common/src/mage/view/GameView.java b/Mage.Common/src/mage/view/GameView.java index 3913b9f954..db5535cf49 100644 --- a/Mage.Common/src/mage/view/GameView.java +++ b/Mage.Common/src/mage/view/GameView.java @@ -59,6 +59,7 @@ import mage.players.Player; public class GameView implements Serializable { private static final long serialVersionUID = 1L; + private int priorityTime; private List players = new ArrayList(); private SimpleCardsView hand; private Map opponentHands; @@ -75,7 +76,9 @@ public class GameView implements Serializable { private int turn; private boolean special = false; + public GameView(GameState state, Game game) { + priorityTime = game.getPriorityTime(); for (Player player: state.getPlayers().values()) { players.add(new PlayerView(player, state, game)); } @@ -255,4 +258,9 @@ public class GameView implements Serializable { public boolean getSpecial() { return special; } + + public int getPriorityTime() { + return priorityTime; + } + } diff --git a/Mage.Server/src/main/java/mage/server/game/GameController.java b/Mage.Server/src/main/java/mage/server/game/GameController.java index fe29d7fb06..925539e12a 100644 --- a/Mage.Server/src/main/java/mage/server/game/GameController.java +++ b/Mage.Server/src/main/java/mage/server/game/GameController.java @@ -137,7 +137,7 @@ public class GameController implements GameCallback { throw new IllegalStateException("INIT_TIMER: playerId can't be null"); } long delay = 250L; // run each 250 ms - timer = new PriorityTimer(Constants.PRIORITY_TIME_SEC, delay, new Action() { + timer = new PriorityTimer(game.getPriorityTime(), delay, new Action() { @Override public void execute() throws MageException { game.concede(initPlayerId); @@ -433,10 +433,12 @@ public class GameController implements GameCallback { } private synchronized void updateGame() { - for (Player player: game.getState().getPlayers().values()) { - PriorityTimer timer = timers.get(player.getId()); - if (timer != null) { - player.setPriorityTimeLeft(timer.getCount()); + if (!timers.isEmpty()) { + for (Player player: game.getState().getPlayers().values()) { + PriorityTimer timer = timers.get(player.getId()); + if (timer != null) { + player.setPriorityTimeLeft(timer.getCount()); + } } } for (final GameSession gameSession: gameSessions.values()) { diff --git a/Mage/src/mage/constants/MatchTimeLimit.java b/Mage/src/mage/constants/MatchTimeLimit.java new file mode 100644 index 0000000000..6e48356edb --- /dev/null +++ b/Mage/src/mage/constants/MatchTimeLimit.java @@ -0,0 +1,37 @@ +package mage.constants; + +/** + * + * @author LevelX2 + */ +public enum MatchTimeLimit { + NONE(0,"None"), + MIN__20(1200, "20 Minutes"), + MIN__30(1800, "30 Minutes"), + MIN__40(2400, "40 Minutes"), + MIN__50(3000, "50 Minutes"), + MIN__60(3600, "60 Minutes"), + MIN__90(5400, "90 Minutes"), + MIN_120(7200, "120 Minutes"); + + private int matchSeconds; + private String name; + + MatchTimeLimit(int matchSeconds, String name) { + this.matchSeconds = matchSeconds; + this.name = name; + } + + public int getTimeLimit() { + return matchSeconds; + } + + public String getName() { + return name; + } + + @Override + public String toString() { + return name; + } +} diff --git a/Mage/src/mage/game/Game.java b/Mage/src/mage/game/Game.java index df3a256a24..5eedb6188c 100644 --- a/Mage/src/mage/game/Game.java +++ b/Mage/src/mage/game/Game.java @@ -230,4 +230,6 @@ public interface Game extends MageItem, Serializable { void initTimer(UUID playerId); void resumeTimer(UUID playerId); void pauseTimer(UUID playerId); + int getPriorityTime(); + void setPriorityTime(int priorityTime); } diff --git a/Mage/src/mage/game/GameImpl.java b/Mage/src/mage/game/GameImpl.java index 1212595fe4..2517430a29 100644 --- a/Mage/src/mage/game/GameImpl.java +++ b/Mage/src/mage/game/GameImpl.java @@ -155,6 +155,8 @@ public abstract class GameImpl> implements Game, Serializa // used to indicate that currently applied replacement effects have to check for scope relevance (614.12 13/01/18) private boolean scopeRelevant = false; + private int priorityTime; + @Override public abstract T copy(); @@ -198,6 +200,7 @@ public abstract class GameImpl> implements Game, Serializa this.stateCheckRequired = game.stateCheckRequired; this.scorePlayer = game.scorePlayer; this.scopeRelevant = game.scopeRelevant; + this.priorityTime = game.priorityTime; } @Override @@ -589,7 +592,9 @@ public abstract class GameImpl> implements Game, Serializa protected void init(UUID choosingPlayerId, GameOptions gameOptions) { for (Player player: state.getPlayers().values()) { player.beginTurn(this); - initTimer(player.getId()); + if (priorityTime > 0) { + initTimer(player.getId()); + } } if (startMessage == null || startMessage.isEmpty()) { startMessage = "Game has started"; @@ -1949,17 +1954,32 @@ public abstract class GameImpl> implements Game, Serializa @Override public void initTimer(UUID playerId) { - tableEventSource.fireTableEvent(EventType.INIT_TIMER, playerId, null, this); + if (priorityTime > 0) { + tableEventSource.fireTableEvent(EventType.INIT_TIMER, playerId, null, this); + } } @Override public void resumeTimer(UUID playerId) { - tableEventSource.fireTableEvent(EventType.RESUME_TIMER, playerId, null, this); + if (priorityTime > 0) { + tableEventSource.fireTableEvent(EventType.RESUME_TIMER, playerId, null, this); + } } @Override public void pauseTimer(UUID playerId) { - tableEventSource.fireTableEvent(EventType.PAUSE_TIMER, playerId, null, this); + if (priorityTime > 0) { + tableEventSource.fireTableEvent(EventType.PAUSE_TIMER, playerId, null, this); + } } + @Override + public int getPriorityTime() { + return priorityTime; + } + + @Override + public void setPriorityTime(int priorityTime) { + this.priorityTime = priorityTime; + } } diff --git a/Mage/src/mage/game/match/MatchImpl.java b/Mage/src/mage/game/match/MatchImpl.java index 4d11d3e349..5fcb9b018c 100644 --- a/Mage/src/mage/game/match/MatchImpl.java +++ b/Mage/src/mage/game/match/MatchImpl.java @@ -162,6 +162,7 @@ public abstract class MatchImpl implements Match { game.loadCards(matchPlayer.getDeck().getSideboard(), matchPlayer.getPlayer().getId()); game.addPlayer(matchPlayer.getPlayer(), matchPlayer.getDeck()); } + game.setPriorityTime(options.getPriorityTime()); } protected void shufflePlayers() { diff --git a/Mage/src/mage/game/match/MatchOptions.java b/Mage/src/mage/game/match/MatchOptions.java index 72aee136ee..ad6187f224 100644 --- a/Mage/src/mage/game/match/MatchOptions.java +++ b/Mage/src/mage/game/match/MatchOptions.java @@ -31,6 +31,7 @@ package mage.game.match; import java.io.Serializable; import java.util.ArrayList; import java.util.List; +import mage.constants.MatchTimeLimit; import mage.constants.MultiplayerAttackOption; import mage.constants.RangeOfInfluence; @@ -49,6 +50,10 @@ public class MatchOptions implements Serializable { protected String deckType; protected boolean limited; protected List playerTypes = new ArrayList(); + /** + * Time each player has during the game to play using his\her priority. + */ + protected MatchTimeLimit matchTimeLimit; // 0 = no priorityTime handling public MatchOptions(String name, String gameType) { this.name = name; @@ -90,6 +95,7 @@ public class MatchOptions implements Serializable { public void setFreeMulligans(int freeMulligans) { this.freeMulligans = freeMulligans; } + public String getGameType() { return gameType; } @@ -117,4 +123,13 @@ public class MatchOptions implements Serializable { public void setLimited(boolean limited) { this.limited = limited; } + + public int getPriorityTime() { + return matchTimeLimit.getTimeLimit(); + } + + public void setMatchTimeLimit(MatchTimeLimit matchTimeLimit) { + this.matchTimeLimit = matchTimeLimit; + } + } From 0ab055c0f8d06fdba09fccb65d87a318d36258cd Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sat, 22 Jun 2013 01:56:43 +0200 Subject: [PATCH 09/22] Added default value for priority time. --- Mage/src/mage/game/match/MatchOptions.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Mage/src/mage/game/match/MatchOptions.java b/Mage/src/mage/game/match/MatchOptions.java index ad6187f224..b54e3adabb 100644 --- a/Mage/src/mage/game/match/MatchOptions.java +++ b/Mage/src/mage/game/match/MatchOptions.java @@ -125,6 +125,9 @@ public class MatchOptions implements Serializable { } public int getPriorityTime() { + if (matchTimeLimit == null) { + return MatchTimeLimit.NONE.getTimeLimit(); + } return matchTimeLimit.getTimeLimit(); } From 3e1b0f5fce820e210b3154895b8cf3bf15278eef Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sat, 22 Jun 2013 01:57:21 +0200 Subject: [PATCH 10/22] Added a mode to allow TargetCardInExile in all exile zones. --- .../mage/target/common/TargetCardInExile.java | 49 +++++++++++++++++-- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/Mage/src/mage/target/common/TargetCardInExile.java b/Mage/src/mage/target/common/TargetCardInExile.java index 4322d0dd58..c6835dcb43 100644 --- a/Mage/src/mage/target/common/TargetCardInExile.java +++ b/Mage/src/mage/target/common/TargetCardInExile.java @@ -27,15 +27,17 @@ */ package mage.target.common; -import mage.constants.Zone; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; import mage.abilities.Ability; import mage.cards.Card; +import mage.constants.Zone; import mage.filter.FilterCard; import mage.game.ExileZone; import mage.game.Game; import mage.target.TargetCard; -import java.util.UUID; /** * @@ -44,26 +46,67 @@ import java.util.UUID; public class TargetCardInExile extends TargetCard { private UUID zoneId; + private boolean allExileZones; public TargetCardInExile(FilterCard filter, UUID zoneId) { this(1, 1, filter, zoneId); } public TargetCardInExile(int minNumTargets, int maxNumTargets, FilterCard filter, UUID zoneId) { + this(minNumTargets, maxNumTargets, filter, zoneId, false); + } + + public TargetCardInExile(int minNumTargets, int maxNumTargets, FilterCard filter, UUID zoneId, boolean allExileZones) { super(minNumTargets, maxNumTargets, Zone.EXILED, filter); this.zoneId = zoneId; + this.allExileZones = allExileZones; this.targetName = filter.getMessage(); } public TargetCardInExile(final TargetCardInExile target) { super(target); this.zoneId = target.zoneId; + this.allExileZones = target.allExileZones; } - @Override + @Override + public Set possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) { + if (allExileZones) { + Set possibleTargets = new HashSet(); + for (Card card : game.getExile().getAllCards(game)) { + if (filter.match(card, sourceControllerId, game)) { + possibleTargets.add(card.getId()); + } + } + return possibleTargets; + } else { + return super.possibleTargets(sourceId, sourceControllerId, game); + } + } + + @Override + public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) { + if (allExileZones) { + int numberTargets = 0; + for(ExileZone exileZone : game.getExile().getExileZones()) { + numberTargets += exileZone.count(filter, sourceId, sourceControllerId, game); + if (numberTargets >= this.minNumberOfTargets) { + return true; + } + } + return false; + } else { + return super.canChoose(sourceControllerId, game); + } + } + + @Override public boolean canTarget(UUID id, Ability source, Game game) { Card card = game.getCard(id); if (card != null && game.getState().getZone(card.getId()) == Zone.EXILED) { + if (allExileZones) { + return filter.match(card, source.getControllerId(), game); + } ExileZone exile; if (zoneId != null) { exile = game.getExile().getExileZone(zoneId); From 49ea20b1c80a44c33b0e2bb3e00cd01a6a9c3fd2 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sat, 22 Jun 2013 01:57:48 +0200 Subject: [PATCH 11/22] Added ActivateAsSorceryManaAbility. --- .../mana/ActivateAsSorceryManaAbility.java | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 Mage/src/mage/abilities/mana/ActivateAsSorceryManaAbility.java diff --git a/Mage/src/mage/abilities/mana/ActivateAsSorceryManaAbility.java b/Mage/src/mage/abilities/mana/ActivateAsSorceryManaAbility.java new file mode 100644 index 0000000000..634584f71b --- /dev/null +++ b/Mage/src/mage/abilities/mana/ActivateAsSorceryManaAbility.java @@ -0,0 +1,56 @@ +/* + * 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.mana; + +import mage.Mana; +import mage.abilities.costs.Cost; +import mage.constants.TimingRule; +import mage.constants.Zone; + +/** + * + * @author LevelX2 + */ + + +public class ActivateAsSorceryManaAbility extends SimpleManaAbility { + + public ActivateAsSorceryManaAbility(Zone zone, Mana mana, Cost cost) { + super(zone, mana, cost); + timing = TimingRule.SORCERY; + } + + public ActivateAsSorceryManaAbility(final ActivateAsSorceryManaAbility ability) { + super(ability); + } + + @Override + public ActivateAsSorceryManaAbility copy() { + return new ActivateAsSorceryManaAbility(this); + } +} From 462acf2b2f4ffd8c74521564dbaeac30e4c00760 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sat, 22 Jun 2013 01:58:03 +0200 Subject: [PATCH 12/22] [MMA] Added 3 cards. --- .../src/mage/sets/eventide/WormHarvest.java | 84 +++++++++++++ .../mage/sets/futuresight/GrinningIgnus.java | 54 ++++++++ .../mage/sets/futuresight/Riftsweeper.java | 52 ++++++++ .../sets/modernmasters/GrinningIgnus.java | 71 +++++++++++ .../mage/sets/modernmasters/Riftsweeper.java | 115 ++++++++++++++++++ .../mage/sets/modernmasters/WormHarvest.java | 54 ++++++++ 6 files changed, 430 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/eventide/WormHarvest.java create mode 100644 Mage.Sets/src/mage/sets/futuresight/GrinningIgnus.java create mode 100644 Mage.Sets/src/mage/sets/futuresight/Riftsweeper.java create mode 100644 Mage.Sets/src/mage/sets/modernmasters/GrinningIgnus.java create mode 100644 Mage.Sets/src/mage/sets/modernmasters/Riftsweeper.java create mode 100644 Mage.Sets/src/mage/sets/modernmasters/WormHarvest.java diff --git a/Mage.Sets/src/mage/sets/eventide/WormHarvest.java b/Mage.Sets/src/mage/sets/eventide/WormHarvest.java new file mode 100644 index 0000000000..53fdabcc2c --- /dev/null +++ b/Mage.Sets/src/mage/sets/eventide/WormHarvest.java @@ -0,0 +1,84 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.eventide; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.keyword.RetraceAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.TimingRule; +import mage.filter.common.FilterLandCard; +import mage.game.permanent.token.Token; + +/** + * + * @author LevelX2 + */ +public class WormHarvest extends CardImpl { + + public WormHarvest(UUID ownerId) { + super(ownerId, 131, "Worm Harvest", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{2}{B/G}{B/G}{B/G}"); + this.expansionSetCode = "EVE"; + + this.color.setGreen(true); + this.color.setBlack(true); + + // Put a 1/1 black and green Worm creature token onto the battlefield for each land card in your graveyard. + CardsInControllerGraveyardCount value = new CardsInControllerGraveyardCount(new FilterLandCard()); + this.getSpellAbility().addEffect(new CreateTokenEffect(new WormHarvestToken(), value)); + + // Retrace + this.addAbility(new RetraceAbility(new ManaCostsImpl("{2}{B/G}{B/G}{B/G}"), TimingRule.SORCERY)); + } + + public WormHarvest(final WormHarvest card) { + super(card); + } + + @Override + public WormHarvest copy() { + return new WormHarvest(this); + } +} + +class WormHarvestToken extends Token { + WormHarvestToken() { + super("Worm", "1/1 black and green Worm creature token"); + cardType.add(CardType.CREATURE); + color.setBlack(true); + color.setGreen(true); + subtype.add("Worm"); + power = new MageInt(1); + toughness = new MageInt(1); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/futuresight/GrinningIgnus.java b/Mage.Sets/src/mage/sets/futuresight/GrinningIgnus.java new file mode 100644 index 0000000000..2d8c4e2cad --- /dev/null +++ b/Mage.Sets/src/mage/sets/futuresight/GrinningIgnus.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.futuresight; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author LevelX2 + */ +public class GrinningIgnus extends mage.sets.modernmasters.GrinningIgnus { + + public GrinningIgnus(UUID ownerId) { + super(ownerId); + this.cardNumber = 116; + this.expansionSetCode = "FUT"; + this.rarity = Rarity.COMMON; + } + + public GrinningIgnus(final GrinningIgnus card) { + super(card); + } + + @Override + public GrinningIgnus copy() { + return new GrinningIgnus(this); + } +} diff --git a/Mage.Sets/src/mage/sets/futuresight/Riftsweeper.java b/Mage.Sets/src/mage/sets/futuresight/Riftsweeper.java new file mode 100644 index 0000000000..45a5ed4621 --- /dev/null +++ b/Mage.Sets/src/mage/sets/futuresight/Riftsweeper.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.futuresight; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class Riftsweeper extends mage.sets.modernmasters.Riftsweeper { + + public Riftsweeper(UUID ownerId) { + super(ownerId); + this.cardNumber = 136; + this.expansionSetCode = "FUT"; + } + + public Riftsweeper(final Riftsweeper card) { + super(card); + } + + @Override + public Riftsweeper copy() { + return new Riftsweeper(this); + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/GrinningIgnus.java b/Mage.Sets/src/mage/sets/modernmasters/GrinningIgnus.java new file mode 100644 index 0000000000..b4750ab5f6 --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/GrinningIgnus.java @@ -0,0 +1,71 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.modernmasters; + +import java.util.UUID; +import mage.MageInt; +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.costs.common.ReturnToHandSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.mana.ActivateAsSorceryManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; + +/** + * + * @author LevelX2 + */ +public class GrinningIgnus extends CardImpl { + + public GrinningIgnus(UUID ownerId) { + super(ownerId, 118, "Grinning Ignus", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{2}{R}"); + this.expansionSetCode = "MMA"; + this.subtype.add("Elemental"); + + this.color.setRed(true); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // {R}, Return Grinning Ignus to its owner's hand: Add {2}{R} to your mana pool. Activate this ability only any time you could cast a sorcery. + Ability ability = new ActivateAsSorceryManaAbility(Zone.BATTLEFIELD, new Mana(1, 0, 0, 0, 0, 2, 0), new ManaCostsImpl("{R}")); + ability.addCost(new ReturnToHandSourceCost()); + this.addAbility(ability); + } + + public GrinningIgnus(final GrinningIgnus card) { + super(card); + } + + @Override + public GrinningIgnus copy() { + return new GrinningIgnus(this); + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/Riftsweeper.java b/Mage.Sets/src/mage/sets/modernmasters/Riftsweeper.java new file mode 100644 index 0000000000..3f23cce82a --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/Riftsweeper.java @@ -0,0 +1,115 @@ +/* + * 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.modernmasters; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.HauntAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.other.FaceDownPredicate; +import mage.game.Game; +import mage.target.common.TargetCardInExile; + +/** + * + * @author LevelX2 + */ +public class Riftsweeper extends CardImpl { + + private static final FilterCard filter = new FilterCard("face-up exiled card"); + static { + filter.add(Predicates.not(new FaceDownPredicate())); + } + + public Riftsweeper(UUID ownerId) { + super(ownerId, 159, "Riftsweeper", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{1}{G}"); + this.expansionSetCode = "MMA"; + this.subtype.add("Elf"); + this.subtype.add("Shaman"); + + this.color.setGreen(true); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // When Riftsweeper enters the battlefield, choose target face-up exiled card. Its owner shuffles it into his or her library. + Ability ability = new EntersBattlefieldTriggeredAbility(new RiftsweeperEffect(), false); + ability.addTarget(new TargetCardInExile(1, 1, filter, null, true)); + this.addAbility(ability); + } + + public Riftsweeper(final Riftsweeper card) { + super(card); + } + + @Override + public Riftsweeper copy() { + return new Riftsweeper(this); + } +} + +class RiftsweeperEffect extends OneShotEffect { + + public RiftsweeperEffect() { + super(Outcome.Benefit); + this.staticText = "choose target face-up exiled card. Its owner shuffles it into his or her library"; + } + + public RiftsweeperEffect(final RiftsweeperEffect effect) { + super(effect); + } + + @Override + public RiftsweeperEffect copy() { + return new RiftsweeperEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Card card = game.getCard(targetPointer.getFirst(game, source)); + if (card != null) { + // remove exiting suspend counters + card.getCounters().clear(); + // move to exile + card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true); + game.getState().getPlayer(card.getOwnerId()).getLibrary().shuffle(); + game.informPlayers(new StringBuilder("Riftsweeper: Choosen card was ").append(card.getName()).toString()); + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/WormHarvest.java b/Mage.Sets/src/mage/sets/modernmasters/WormHarvest.java new file mode 100644 index 0000000000..e158a312d5 --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/WormHarvest.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.modernmasters; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author LevelX2 + */ +public class WormHarvest extends mage.sets.eventide.WormHarvest { + + public WormHarvest(UUID ownerId) { + super(ownerId); + this.cardNumber = 195; + this.expansionSetCode = "MMA"; + this.rarity = Rarity.UNCOMMON; + } + + public WormHarvest(final WormHarvest card) { + super(card); + } + + @Override + public WormHarvest copy() { + return new WormHarvest(this); + } +} From d520d63e2cd490684385279f8e989f0fbaffb585 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sat, 22 Jun 2013 02:20:26 +0200 Subject: [PATCH 13/22] * Quest for the Gemblades - Triggers now only if creatures of the controller of Gemblade made combat damage to other creatures. --- .../sets/zendikar/QuestForTheGemblades.java | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/Mage.Sets/src/mage/sets/zendikar/QuestForTheGemblades.java b/Mage.Sets/src/mage/sets/zendikar/QuestForTheGemblades.java index d3d4a6522b..9159cb8ba2 100644 --- a/Mage.Sets/src/mage/sets/zendikar/QuestForTheGemblades.java +++ b/Mage.Sets/src/mage/sets/zendikar/QuestForTheGemblades.java @@ -28,9 +28,6 @@ package mage.sets.zendikar; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.Rarity; -import mage.constants.Zone; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.RemoveCountersSourceCost; @@ -38,10 +35,14 @@ import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.effects.common.counter.AddCountersTargetEffect; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; import mage.counters.CounterType; import mage.game.Game; import mage.game.events.DamagedCreatureEvent; import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; import mage.target.common.TargetCreaturePermanent; /** @@ -94,9 +95,15 @@ class QuestForTheGembladesTriggeredAbility extends TriggeredAbilityImpl Date: Sat, 22 Jun 2013 19:35:22 +0200 Subject: [PATCH 14/22] Added support for casting modal spells or activating modal abilities with more than one mode to choose. --- Mage.Common/src/mage/view/CardView.java | 15 ++-- .../src/mage/view/StackAbilityView.java | 59 ++++++++----- .../java/mage/player/ai/ComputerPlayer.java | 8 +- .../src/mage/player/human/HumanPlayer.java | 25 +++--- Mage/src/mage/abilities/AbilityImpl.java | 65 +++++++------- .../mage/abilities/ActivatedAbilityImpl.java | 16 ++++ Mage/src/mage/abilities/Modes.java | 85 +++++++++++++++---- Mage/src/mage/game/stack/Spell.java | 18 ++-- 8 files changed, 201 insertions(+), 90 deletions(-) diff --git a/Mage.Common/src/mage/view/CardView.java b/Mage.Common/src/mage/view/CardView.java index 30da7ad0d4..d619065ea5 100644 --- a/Mage.Common/src/mage/view/CardView.java +++ b/Mage.Common/src/mage/view/CardView.java @@ -47,6 +47,7 @@ import java.util.ArrayList; import java.util.List; import java.util.UUID; import mage.abilities.Mode; +import mage.abilities.Modes; import mage.abilities.SpellAbility; import mage.abilities.costs.mana.ManaCosts; import mage.cards.SplitCard; @@ -184,15 +185,19 @@ public class CardView extends SimpleCardView { if (card instanceof Spell) { Spell spell = (Spell) card; for (SpellAbility spellAbility: spell.getSpellAbilities()) { - if (spellAbility.getTargets().size() > 0) { - setTargets(spellAbility.getTargets()); + for(UUID modeId : spellAbility.getModes().getSelectedModes()) { + spellAbility.getModes().setMode(spellAbility.getModes().get(modeId)); + if (spellAbility.getTargets().size() > 0) { + setTargets(spellAbility.getTargets()); + } } } // show for modal spell, which mode was choosen if (spell.getSpellAbility().isModal()) { - Mode activeMode = spell.getSpellAbility().getModes().getMode(); - if (activeMode != null) { - this.rules.add("Chosen mode: " + activeMode.getEffects().getText(activeMode)+""); + Modes modes = spell.getSpellAbility().getModes(); + for(UUID modeId : modes.getSelectedModes()) { + modes.setMode(modes.get(modeId)); + this.rules.add("Chosen mode: " + spell.getSpellAbility().getEffects().getText(modes.get(modeId))+""); } } } diff --git a/Mage.Common/src/mage/view/StackAbilityView.java b/Mage.Common/src/mage/view/StackAbilityView.java index 60d5534d37..1b4d35124f 100644 --- a/Mage.Common/src/mage/view/StackAbilityView.java +++ b/Mage.Common/src/mage/view/StackAbilityView.java @@ -28,17 +28,17 @@ package mage.view; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; import mage.MageObject; +import mage.abilities.Modes; import mage.abilities.effects.Effect; import mage.game.Game; import mage.game.stack.StackAbility; import mage.target.targetpointer.FixedTarget; import mage.target.targetpointer.TargetPointer; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; - /** * * @author BetaSteward_at_googlemail.com @@ -68,30 +68,43 @@ public class StackAbilityView extends CardView { } private void updateTargets(Game game, StackAbility ability) { - if (ability.getTargets().size() > 0) { - setTargets(ability.getTargets()); - } else { - List targetList = new ArrayList(); - for (Effect effect : ability.getEffects()) { - TargetPointer targetPointer = effect.getTargetPointer(); - if (targetPointer instanceof FixedTarget) { - targetList.add(((FixedTarget) targetPointer).getTarget()); - } - } - if (targetList.size() > 0) { - overrideTargets(targetList); - List names = new ArrayList(); - for (UUID uuid : targetList) { - MageObject mageObject = game.getObject(uuid); - if (mageObject != null) { - names.add(mageObject.getName()); + List names = new ArrayList(); + for(UUID modeId : ability.getModes().getSelectedModes()) { + ability.getModes().setMode(ability.getModes().get(modeId)); + if (ability.getTargets().size() > 0) { + setTargets(ability.getTargets()); + } else { + List targetList = new ArrayList(); + for (Effect effect : ability.getEffects()) { + TargetPointer targetPointer = effect.getTargetPointer(); + if (targetPointer instanceof FixedTarget) { + targetList.add(((FixedTarget) targetPointer).getTarget()); } } - if (!names.isEmpty()) { - getRules().add("Targets: " + names.toString() + ""); + if (targetList.size() > 0) { + overrideTargets(targetList); + + for (UUID uuid : targetList) { + MageObject mageObject = game.getObject(uuid); + if (mageObject != null) { + names.add(mageObject.getName()); + } + } + } } } + if (!names.isEmpty()) { + getRules().add("Targets: " + names.toString() + ""); + } + // show for modal ability, which mode was choosen + if (ability.isModal()) { + Modes modes = ability.getModes(); + for(UUID modeId : modes.getSelectedModes()) { + modes.setMode(modes.get(modeId)); + this.rules.add("Chosen mode: " + ability.getEffects().getText(modes.get(modeId))+""); + } + } } public CardView getSourceCard() { diff --git a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java index ba03a46298..24cf4203a6 100644 --- a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java +++ b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java @@ -1230,7 +1230,13 @@ public class ComputerPlayer> extends PlayerImpl i return modes.getMode(); } //TODO: improve this; - return modes.values().iterator().next(); + for (Mode mode: modes.values()) { + if (!modes.getSelectedModes().contains(mode.getId()) // select only modes not already selected + && mode.getTargets().canChoose(source.getSourceId(), source.getControllerId(), game)) { // and where targets are available + return mode; + } + } + return null; } @Override diff --git a/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java b/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java index ce64108b87..cc6a3bbb5d 100644 --- a/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java +++ b/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java @@ -782,18 +782,23 @@ public class HumanPlayer extends PlayerImpl { MageObject obj = game.getObject(source.getSourceId()); Map modeMap = new LinkedHashMap(); for (Mode mode: modes.values()) { - String modeText = mode.getEffects().getText(mode); - if (obj != null) { - modeText = modeText.replace("{source}", obj.getName()); + if (!modes.getSelectedModes().contains(mode.getId()) // show only modes not already selected + && mode.getTargets().canChoose(source.getSourceId(), source.getControllerId(), game)) { // and where targets are available + String modeText = mode.getEffects().getText(mode); + if (obj != null) { + modeText = modeText.replace("{source}", obj.getName()); + } + modeMap.put(mode.getId(), modeText); } - modeMap.put(mode.getId(), modeText); } - game.fireGetModeEvent(playerId, "Choose Mode", modeMap); - waitForResponse(game); - if (response.getUUID() != null) { - for (Mode mode: modes.values()) { - if (mode.getId().equals(response.getUUID())) { - return mode; + if (modeMap.size() > 0) { + game.fireGetModeEvent(playerId, "Choose Mode", modeMap); + waitForResponse(game); + if (response.getUUID() != null) { + for (Mode mode: modes.values()) { + if (mode.getId().equals(response.getUUID())) { + return mode; + } } } } diff --git a/Mage/src/mage/abilities/AbilityImpl.java b/Mage/src/mage/abilities/AbilityImpl.java index 7bc757f7e0..4608c5828d 100644 --- a/Mage/src/mage/abilities/AbilityImpl.java +++ b/Mage/src/mage/abilities/AbilityImpl.java @@ -170,9 +170,12 @@ public abstract class AbilityImpl> implements Ability { if (card != null) { card.adjustChoices(this, game); } - if (getChoices().size() > 0 && getChoices().choose(game, this) == false) { - logger.debug("activate failed - choice"); - return false; + for (UUID modeId :this.getModes().getSelectedModes()) { + this.getModes().setMode(this.getModes().get(modeId)); + if (getChoices().size() > 0 && getChoices().choose(game, this) == false) { + logger.debug("activate failed - choice"); + return false; + } } // 20121001 - 601.2b @@ -198,33 +201,37 @@ public abstract class AbilityImpl> implements Ability { // its mana cost; see rule 107.3), the player announces the value of that variable. VariableManaCost variableManaCost = handleXCosts(game, noMana); - //20121001 - 601.2c - // 601.2c The player announces his or her choice of an appropriate player, object, or zone for - // each target the spell requires. A spell may require some targets only if an alternative or - // additional cost (such as a buyback or kicker cost), or a particular mode, was chosen for it; - // otherwise, the spell is cast as though it did not require those targets. If the spell has a - // variable number of targets, the player announces how many targets he or she will choose before - // he or she announces those targets. The same target can't be chosen multiple times for any one - // instance of the word "target" on the spell. However, if the spell uses the word "target" in - // multiple places, the same object, player, or zone can be chosen once for each instance of the - // word "target" (as long as it fits the targeting criteria). If any effects say that an object - // or player must be chosen as a target, the player chooses targets so that he or she obeys the - // maximum possible number of such effects without violating any rules or effects that say that - // an object or player can't be chosen as a target. The chosen players, objects, and/or zones - // each become a target of that spell. (Any abilities that trigger when those players, objects, - // and/or zones become the target of a spell trigger at this point; they'll wait to be put on - // the stack until the spell has finished being cast.) - if (card != null) { - card.adjustTargets(this, game); - } - if (getTargets().size() > 0 && getTargets().chooseTargets(getEffects().get(0).getOutcome(), this.controllerId, this, game) == false) { - if (variableManaCost != null) { - game.informPlayers(new StringBuilder(card.getName()).append(": no valid targets with this value of X").toString()); - } else { - logger.debug("activate failed - target"); + for (UUID modeId :this.getModes().getSelectedModes()) { + this.getModes().setMode(this.getModes().get(modeId)); + //20121001 - 601.2c + // 601.2c The player announces his or her choice of an appropriate player, object, or zone for + // each target the spell requires. A spell may require some targets only if an alternative or + // additional cost (such as a buyback or kicker cost), or a particular mode, was chosen for it; + // otherwise, the spell is cast as though it did not require those targets. If the spell has a + // variable number of targets, the player announces how many targets he or she will choose before + // he or she announces those targets. The same target can't be chosen multiple times for any one + // instance of the word "target" on the spell. However, if the spell uses the word "target" in + // multiple places, the same object, player, or zone can be chosen once for each instance of the + // word "target" (as long as it fits the targeting criteria). If any effects say that an object + // or player must be chosen as a target, the player chooses targets so that he or she obeys the + // maximum possible number of such effects without violating any rules or effects that say that + // an object or player can't be chosen as a target. The chosen players, objects, and/or zones + // each become a target of that spell. (Any abilities that trigger when those players, objects, + // and/or zones become the target of a spell trigger at this point; they'll wait to be put on + // the stack until the spell has finished being cast.) + + if (card != null) { + card.adjustTargets(this, game); } - return false; - } + if (getTargets().size() > 0 && getTargets().chooseTargets(getEffects().get(0).getOutcome(), this.controllerId, this, game) == false) { + if (variableManaCost != null) { + game.informPlayers(new StringBuilder(card != null ? card.getName(): "").append(": no valid targets with this value of X").toString()); + } else { + logger.debug("activate failed - target"); + } + return false; + } + } // end modes // TODO: Handle optionalCosts at the same time as already OptionalAdditionalSourceCosts are handled. for (Cost cost : optionalCosts) { diff --git a/Mage/src/mage/abilities/ActivatedAbilityImpl.java b/Mage/src/mage/abilities/ActivatedAbilityImpl.java index eb0e95f2da..fd270faf35 100644 --- a/Mage/src/mage/abilities/ActivatedAbilityImpl.java +++ b/Mage/src/mage/abilities/ActivatedAbilityImpl.java @@ -261,6 +261,22 @@ public abstract class ActivatedAbilityImpl> ex } } } + } else if (object instanceof Spell && ((Spell) object).getSpellAbility().getModes().size() > 1) { + Modes modes = ((Spell) object).getSpellAbility().getModes(); + int item = 0; + for (Mode mode : modes.values()) { + item++; + if (modes.getSelectedModes().contains(mode.getId())) { + modes.setMode(mode); + sb.append(" (mode ").append(item).append(")"); + if (getTargets().size() > 0) { + sb.append(" targeting "); + for (Target target: getTargets()) { + sb.append(target.getTargetedName(game)); + } + } + } + } } else { if (getTargets().size() > 0) { sb.append(" targeting "); diff --git a/Mage/src/mage/abilities/Modes.java b/Mage/src/mage/abilities/Modes.java index c1d15c99c1..0637e4a4fc 100644 --- a/Mage/src/mage/abilities/Modes.java +++ b/Mage/src/mage/abilities/Modes.java @@ -28,7 +28,10 @@ package mage.abilities; import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; import java.util.Map; +import java.util.Set; import java.util.UUID; import mage.game.Game; import mage.players.Player; @@ -40,11 +43,18 @@ import mage.players.Player; public class Modes extends LinkedHashMap { private UUID modeId; + private Set selectedModes = new LinkedHashSet(); + private int minModes; + private int maxModes; public Modes() { Mode mode = new Mode(); this.put(mode.getId(), mode); this.modeId = mode.getId(); + this.minModes = 1; + this.maxModes = 1; + this.selectedModes.add(modeId); + } public Modes(Modes modes) { @@ -52,6 +62,9 @@ public class Modes extends LinkedHashMap { for (Map.Entry entry: modes.entrySet()) { this.put(entry.getKey(), entry.getValue().copy()); } + this.minModes = modes.minModes; + this.maxModes = modes.maxModes; + this.selectedModes.addAll(modes.selectedModes); } public Modes copy() { @@ -62,9 +75,30 @@ public class Modes extends LinkedHashMap { return get(modeId); } + public Set getSelectedModes() { + return selectedModes; + } + + public void setMinModes(int minModes) { + this.minModes = minModes; + } + + public int getMinModes() { + return this.minModes; + } + + public void setMaxModes(int maxModes) { + this.maxModes = maxModes; + } + + public int getMaxModes() { + return this.maxModes; + } + public void setMode(Mode mode) { if (this.containsKey(mode.getId())) { this.modeId = mode.getId(); + this.selectedModes.add(mode.getId()); } } @@ -74,40 +108,59 @@ public class Modes extends LinkedHashMap { public boolean choose(Game game, Ability source) { if (this.size() > 1) { + this.selectedModes.clear(); + Player player = game.getPlayer(source.getControllerId()); - Mode choice = player.chooseMode(this, source, game); - if (choice == null) { - return false; + while (this.selectedModes.size() < this.getMaxModes()) { + Mode choice = player.chooseMode(this, source, game); + if (choice == null) { + return this.selectedModes.size() >= this.getMinModes(); + } + setMode(choice); + this.selectedModes.add(choice.getId()); } - setMode(choice); return true; } this.modeId = this.values().iterator().next().getId(); + this.selectedModes.add(modeId); return true; } public String getText() { + String andOr = ""; StringBuilder sb = new StringBuilder(); if (this.size() > 1) { - sb.append("Choose one - "); + if (this.getMinModes() == 1 && this.getMaxModes() == 3) { + sb.append("Choose one or more - "); + andOr = "; and/or "; + }else if (this.getMinModes() == 1 && this.getMaxModes() == 2) { + sb.append("Choose one or both - "); + andOr = "; and/or "; + } else if (this.getMinModes() == 2 && this.getMaxModes() == 2) { + sb.append("Choose two - "); + andOr = "; or "; + } else { + sb.append("Choose one - "); + andOr = "; or "; + } } for (Mode mode: this.values()) { - sb.append(mode.getEffects().getText(mode)).append("; or "); + sb.append(mode.getEffects().getText(mode)); + if (this.size() > 1) { + if (sb.length() > 2 && sb.substring(sb.length()-2, sb.length()).equals(". ")) { + sb.delete(sb.length()-2, sb.length()); + } + sb.append(andOr); + } + } + if (this.size() > 1) { + sb.delete(sb.length() - andOr.length(), sb.length()); } - sb.delete(sb.length() - 5, sb.length()); return sb.toString(); } public String getText(String sourceName) { - StringBuilder sb = new StringBuilder(); - if (this.size() > 1) { - sb.append("Choose one - "); - } - for (Mode mode: this.values()) { - sb.append(mode.getEffects().getText(mode)).append("; or "); - } - sb.delete(sb.length() - 5, sb.length()); - String text = sb.toString(); + String text = getText(); text = text.replace("{this}", sourceName); text = text.replace("{source}", sourceName); return text; diff --git a/Mage/src/mage/game/stack/Spell.java b/Mage/src/mage/game/stack/Spell.java index 006ea54001..6e94091519 100644 --- a/Mage/src/mage/game/stack/Spell.java +++ b/Mage/src/mage/game/stack/Spell.java @@ -138,10 +138,13 @@ public class Spell> implements StackObject, Card { result = false; boolean legalParts = false; for(SpellAbility spellAbility: this.spellAbilities) { - if (spellAbility.getTargets().stillLegal(spellAbility, game)) { - legalParts = true; - updateOptionalCosts(index); - result |= spellAbility.resolve(game); + for (UUID modeId :spellAbility.getModes().getSelectedModes()) { + spellAbility.getModes().setMode(spellAbility.getModes().get(modeId)); + if (spellAbility.getTargets().stillLegal(spellAbility, game)) { + legalParts = true; + updateOptionalCosts(index); + result |= spellAbility.resolve(game); + } } index++; } @@ -226,13 +229,16 @@ public class Spell> implements StackObject, Card { String name = null; if (object == null) { Player targetPlayer = game.getPlayer(targetId); - if (targetPlayer != null) name = targetPlayer.getName(); + if (targetPlayer != null) { + name = targetPlayer.getName(); + } } else { name = object.getName(); } if (name != null && player.chooseUse(spellAbility.getEffects().get(0).getOutcome(), "Change target from " + name + "?", game)) { - if (!player.chooseTarget(spellAbility.getEffects().get(0).getOutcome(), newTarget, spellAbility, game)) + if (!player.chooseTarget(spellAbility.getEffects().get(0).getOutcome(), newTarget, spellAbility, game)) { newTarget.addTarget(targetId, spellAbility, game, false); + } } else { newTarget.addTarget(targetId, spellAbility, game, false); From 4d3d76e8e90d35bb08536c2b1fedbb9b55f49d99 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sat, 22 Jun 2013 19:36:16 +0200 Subject: [PATCH 15/22] Changed some modal spells to the new handling of modal spells. --- .../src/mage/sets/gatecrash/ClanDefiance.java | 33 +++--------- .../src/mage/sets/lorwyn/CrypticCommand.java | 53 +++++++------------ .../sets/shardsofalara/BranchingBolt.java | 11 ++-- .../abilities/enters/DearlyDepartedTest.java | 10 ++++ 4 files changed, 38 insertions(+), 69 deletions(-) diff --git a/Mage.Sets/src/mage/sets/gatecrash/ClanDefiance.java b/Mage.Sets/src/mage/sets/gatecrash/ClanDefiance.java index 70cbf444f9..41739f433f 100644 --- a/Mage.Sets/src/mage/sets/gatecrash/ClanDefiance.java +++ b/Mage.Sets/src/mage/sets/gatecrash/ClanDefiance.java @@ -64,44 +64,23 @@ public class ClanDefiance extends CardImpl { this.color.setRed(true); this.color.setGreen(true); - // Choose one or more - Clan Defiance deals X damage to target creature with flying; Clan Defiance deals X damage to target creature without flying; and/or Clan Defiance deals X damage to target player. + // Choose one or more - + this.getSpellAbility().getModes().setMinModes(1); + this.getSpellAbility().getModes().setMaxModes(3); + // Clan Defiance deals X damage to target creature with flying; this.getSpellAbility().addEffect(new DamageTargetEffect(new ManacostVariableValue())); this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); - + // Clan Defiance deals X damage to target creature without flying; Mode mode1 = new Mode(); mode1.getEffects().add(new DamageTargetEffect(new ManacostVariableValue())); mode1.getTargets().add(new TargetCreaturePermanent(filter2)); this.getSpellAbility().addMode(mode1); - + // and/or Clan Defiance deals X damage to target player. Mode mode2 = new Mode(); mode2.getEffects().add(new DamageTargetEffect(new ManacostVariableValue())); mode2.getTargets().add(new TargetPlayer()); this.getSpellAbility().addMode(mode2); - - Mode mode3 = new Mode(); - mode3.getEffects().add(new DamageTargetEffect(new ManacostVariableValue(), true, "target creature with flying, then deals X damage to target creature without flying")); - mode3.getTargets().add(new TargetCreaturePermanent(filter)); - mode3.getTargets().add(new TargetCreaturePermanent(filter2)); - this.getSpellAbility().addMode(mode3); - - Mode mode4 = new Mode(); - mode4.getEffects().add(new DamageTargetEffect(new ManacostVariableValue(), true, "target creature with flying, then deals X damage to target player")); - mode4.getTargets().add(new TargetCreaturePermanent(filter)); - mode4.getTargets().add(new TargetPlayer()); - this.getSpellAbility().addMode(mode4); - - Mode mode5 = new Mode(); - mode5.getEffects().add(new DamageTargetEffect(new ManacostVariableValue(), true, "target creature without flying, then deals X damage to target player")); - mode5.getTargets().add(new TargetCreaturePermanent(filter2)); - mode5.getTargets().add(new TargetPlayer()); - this.getSpellAbility().addMode(mode5); - Mode mode6 = new Mode(); - mode6.getEffects().add(new DamageTargetEffect(new ManacostVariableValue(), true, "target creature with flying, then deals X damage to target creature without flying, then deals X damage to target player")); - mode6.getTargets().add(new TargetCreaturePermanent(filter)); - mode6.getTargets().add(new TargetCreaturePermanent(filter2)); - mode6.getTargets().add(new TargetPlayer()); - this.getSpellAbility().addMode(mode6); } public ClanDefiance(final ClanDefiance card) { diff --git a/Mage.Sets/src/mage/sets/lorwyn/CrypticCommand.java b/Mage.Sets/src/mage/sets/lorwyn/CrypticCommand.java index eee8f86cac..abef367a04 100644 --- a/Mage.Sets/src/mage/sets/lorwyn/CrypticCommand.java +++ b/Mage.Sets/src/mage/sets/lorwyn/CrypticCommand.java @@ -45,7 +45,6 @@ import mage.filter.predicate.permanent.ControllerPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; -import mage.target.TargetPlayer; import mage.target.TargetSpell; import mage.target.common.TargetCreaturePermanent; @@ -61,41 +60,25 @@ public class CrypticCommand extends CardImpl { this.color.setBlue(true); - // Choose two - Counter target spell; or return target permanent to its owner's hand; or tap all creatures your opponents control; or draw a card. - this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + // Choose two - + this.getSpellAbility().getModes().setMinModes(2); + this.getSpellAbility().getModes().setMaxModes(2); + // Counter target spell; + this.getSpellAbility().addEffect(new CounterTargetEffect()); this.getSpellAbility().addTarget(new TargetSpell()); - this.getSpellAbility().addEffect(new ReturnToHandTargetEffect()); - this.getSpellAbility().addEffect(new CounterSecondTargetEffect()); - - Mode mode1 = new Mode(); - mode1.getTargets().add(new TargetSpell()); - mode1.getEffects().add(new CounterTargetEffect()); - mode1.getEffects().add(new CrypticCommandEffect()); - this.getSpellAbility().addMode(mode1); - - Mode mode2 = new Mode(); - mode2.getTargets().add(new TargetSpell()); - mode2.getEffects().add(new CounterTargetEffect()); - mode2.getEffects().add(new DrawCardControllerEffect(1)); - this.getSpellAbility().addMode(mode2); - - Mode mode3 = new Mode(); - mode3.getTargets().add(new TargetCreaturePermanent()); - mode3.getEffects().add(new ReturnToHandTargetEffect()); - mode3.getEffects().add(new CrypticCommandEffect()); - this.getSpellAbility().addMode(mode3); - - Mode mode4 = new Mode(); - mode4.getTargets().add(new TargetCreaturePermanent()); - mode4.getEffects().add(new ReturnToHandTargetEffect()); - mode4.getEffects().add(new DrawCardControllerEffect(1)); - this.getSpellAbility().addMode(mode4); - - Mode mode5 = new Mode(); - mode5.getTargets().add(new TargetPlayer()); - mode5.getEffects().add(new CrypticCommandEffect()); - mode5.getEffects().add(new DrawCardControllerEffect(1)); - this.getSpellAbility().addMode(mode5); + // or return target permanent to its owner's hand; + Mode mode = new Mode(); + mode.getEffects().add(new ReturnToHandTargetEffect()); + mode.getTargets().add(new TargetCreaturePermanent()); + this.getSpellAbility().getModes().addMode(mode); + // or tap all creatures your opponents control; + mode = new Mode(); + mode.getEffects().add(new CrypticCommandEffect()); + this.getSpellAbility().getModes().addMode(mode); + // or draw a card. + mode = new Mode(); + mode.getEffects().add(new DrawCardControllerEffect(1)); + this.getSpellAbility().getModes().addMode(mode); } public CrypticCommand(final CrypticCommand card) { diff --git a/Mage.Sets/src/mage/sets/shardsofalara/BranchingBolt.java b/Mage.Sets/src/mage/sets/shardsofalara/BranchingBolt.java index 78275104c5..49d3b61504 100644 --- a/Mage.Sets/src/mage/sets/shardsofalara/BranchingBolt.java +++ b/Mage.Sets/src/mage/sets/shardsofalara/BranchingBolt.java @@ -65,7 +65,10 @@ public class BranchingBolt extends CardImpl { this.color.setRed(true); this.color.setGreen(true); - // Choose one or both - Branching Bolt deals 3 damage to target creature with flying; + // Choose one or both - + this.getSpellAbility().getModes().setMinModes(1); + this.getSpellAbility().getModes().setMaxModes(2); + // Branching Bolt deals 3 damage to target creature with flying; this.getSpellAbility().addEffect(new DamageTargetEffect(3)); this.getSpellAbility().addTarget(new TargetCreaturePermanent(filterFlying)); // or Branching Bolt deals 3 damage to target creature without flying. @@ -73,12 +76,6 @@ public class BranchingBolt extends CardImpl { mode.getEffects().add(new DamageTargetEffect(3)); mode.getTargets().add(new TargetCreaturePermanent(filterNotFlying)); this.getSpellAbility().addMode(mode); - // both - mode = new Mode(); - mode.getEffects().add(new DamageTargetEffect(3)); - mode.getTargets().add(new TargetCreaturePermanent(filterFlying)); - mode.getTargets().add(new TargetCreaturePermanent(filterNotFlying)); - this.getSpellAbility().addMode(mode); } public BranchingBolt(final BranchingBolt card) { diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/enters/DearlyDepartedTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/enters/DearlyDepartedTest.java index c8b1ce05da..d6ae457813 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/enters/DearlyDepartedTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/enters/DearlyDepartedTest.java @@ -16,7 +16,17 @@ public class DearlyDepartedTest extends CardTestPlayerBase { @Test public void testEnteringWithCounters() { addCard(Zone.BATTLEFIELD, playerA, "Plains", 5); + // Dearly Departed + // Creature — Spirit 5/5, 4WW (6) + // Flying + // As long as Dearly Departed is in your graveyard, each Human creature you control enters the battlefield with an additional +1/+1 counter on it. addCard(Zone.GRAVEYARD, playerA, "Dearly Departed"); + /** + * Thraben Doomsayer + * Creature — Human Cleric 2/2, 1WW (3) + * {T}: Put a 1/1 white Human creature token onto the battlefield. + * Fateful hour — As long as you have 5 or less life, other creatures you control get +2/+2. + */ addCard(Zone.BATTLEFIELD, playerA, "Thraben Doomsayer"); activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Put a 1/1 white Human creature token onto the battlefield."); From e55dd735a97dc3191fefb628d533b13ba49812e6 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sat, 22 Jun 2013 19:36:33 +0200 Subject: [PATCH 16/22] * Added Austere Command and Primal Command. --- .../mage/sets/commander/AustereCommand.java | 88 ++++++++++++ .../src/mage/sets/lorwyn/AustereCommand.java | 52 +++++++ .../src/mage/sets/lorwyn/PrimalCommand.java | 131 ++++++++++++++++++ 3 files changed, 271 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/commander/AustereCommand.java create mode 100644 Mage.Sets/src/mage/sets/lorwyn/AustereCommand.java create mode 100644 Mage.Sets/src/mage/sets/lorwyn/PrimalCommand.java diff --git a/Mage.Sets/src/mage/sets/commander/AustereCommand.java b/Mage.Sets/src/mage/sets/commander/AustereCommand.java new file mode 100644 index 0000000000..a6f6581c2d --- /dev/null +++ b/Mage.Sets/src/mage/sets/commander/AustereCommand.java @@ -0,0 +1,88 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.commander; + +import java.util.UUID; +import mage.abilities.Mode; +import mage.abilities.effects.common.DestroyAllEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.Filter; +import mage.filter.common.FilterArtifactPermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.common.FilterEnchantmentPermanent; +import mage.filter.predicate.mageobject.ConvertedManaCostPredicate; + +/** + * + * @author LevelX2 + */ +public class AustereCommand extends CardImpl { + + private static final FilterCreaturePermanent filter3orLess = new FilterCreaturePermanent("creatures with converted mana cost 3 or less"); + private static final FilterCreaturePermanent filter4orMore = new FilterCreaturePermanent("creatures with converted mana cost 4 or greater"); + static { + filter3orLess.add(new ConvertedManaCostPredicate(Filter.ComparisonType.LessThan, 4)); + filter4orMore.add(new ConvertedManaCostPredicate(Filter.ComparisonType.GreaterThan, 3)); + } + + public AustereCommand(UUID ownerId) { + super(ownerId, 8, "Austere Command", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{4}{W}{W}"); + this.expansionSetCode = "CMD"; + + this.color.setWhite(true); + + // Choose two - + this.getSpellAbility().getModes().setMinModes(2); + this.getSpellAbility().getModes().setMaxModes(2); + // Destroy all artifacts; + this.getSpellAbility().addEffect(new DestroyAllEffect(new FilterArtifactPermanent("artifacts"))); + // or destroy all enchantments; + Mode mode = new Mode(); + mode.getEffects().add(new DestroyAllEffect(new FilterEnchantmentPermanent("enchantments"))); + this.getSpellAbility().getModes().addMode(mode); + // or destroy all creatures with converted mana cost 3 or less; + mode = new Mode(); + mode.getEffects().add(new DestroyAllEffect(filter3orLess)); + this.getSpellAbility().getModes().addMode(mode); + // or destroy all creatures with converted mana cost 4 or greater. + mode = new Mode(); + mode.getEffects().add(new DestroyAllEffect(filter4orMore)); + this.getSpellAbility().getModes().addMode(mode); + } + + public AustereCommand(final AustereCommand card) { + super(card); + } + + @Override + public AustereCommand copy() { + return new AustereCommand(this); + } +} diff --git a/Mage.Sets/src/mage/sets/lorwyn/AustereCommand.java b/Mage.Sets/src/mage/sets/lorwyn/AustereCommand.java new file mode 100644 index 0000000000..2663bcd872 --- /dev/null +++ b/Mage.Sets/src/mage/sets/lorwyn/AustereCommand.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.lorwyn; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class AustereCommand extends mage.sets.commander.AustereCommand { + + public AustereCommand(UUID ownerId) { + super(ownerId); + this.cardNumber = 3; + this.expansionSetCode = "LRW"; + } + + public AustereCommand(final AustereCommand card) { + super(card); + } + + @Override + public AustereCommand copy() { + return new AustereCommand(this); + } +} diff --git a/Mage.Sets/src/mage/sets/lorwyn/PrimalCommand.java b/Mage.Sets/src/mage/sets/lorwyn/PrimalCommand.java new file mode 100644 index 0000000000..9fda7dde88 --- /dev/null +++ b/Mage.Sets/src/mage/sets/lorwyn/PrimalCommand.java @@ -0,0 +1,131 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.lorwyn; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.GainLifeTargetEffect; +import mage.abilities.effects.common.PutOnLibraryTargetEffect; +import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterCreatureCard; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.game.Game; +import mage.players.Player; +import mage.target.Target; +import mage.target.TargetPermanent; +import mage.target.TargetPlayer; +import mage.target.common.TargetCardInLibrary; + +/** + * + * @author LevelX2 + */ +public class PrimalCommand extends CardImpl { + + private static final FilterPermanent filterNonCreature = new FilterPermanent("noncreature permanent"); + static { + filterNonCreature.add(Predicates.not(new CardTypePredicate(CardType.CREATURE))); + } + + public PrimalCommand(UUID ownerId) { + super(ownerId, 233, "Primal Command", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{3}{G}{G}"); + this.expansionSetCode = "LRW"; + + this.color.setGreen(true); + + // Choose two - + this.getSpellAbility().getModes().setMinModes(2); + this.getSpellAbility().getModes().setMaxModes(2); + // Target player gains 7 life; + this.getSpellAbility().addEffect(new GainLifeTargetEffect(7)); + this.getSpellAbility().addTarget(new TargetPlayer(true)); + // or put target noncreature permanent on top of its owner's library; + Mode mode = new Mode(); + mode.getEffects().add(new PutOnLibraryTargetEffect(true)); + Target target = new TargetPermanent(filterNonCreature); + target.setRequired(true); + mode.getTargets().add(target); + this.getSpellAbility().getModes().addMode(mode); + // or target player shuffles his or her graveyard into his or her library; + mode = new Mode(); + mode.getEffects().add(new PrimalCommandShuffleGraveyardEffect()); + mode.getTargets().add(new TargetPlayer()); + this.getSpellAbility().getModes().addMode(mode); + // or search your library for a creature card, reveal it, put it into your hand, then shuffle your library. + mode = new Mode(); + mode.getEffects().add(new SearchLibraryPutInHandEffect(new TargetCardInLibrary(new FilterCreatureCard()), true, true)); + this.getSpellAbility().getModes().addMode(mode); + + } + + public PrimalCommand(final PrimalCommand card) { + super(card); + } + + @Override + public PrimalCommand copy() { + return new PrimalCommand(this); + } +} + +class PrimalCommandShuffleGraveyardEffect extends OneShotEffect { + + public PrimalCommandShuffleGraveyardEffect() { + super(Outcome.Neutral); + this.staticText = "target player shuffles his or her graveyard into his or her library"; + } + + public PrimalCommandShuffleGraveyardEffect(final PrimalCommandShuffleGraveyardEffect effect) { + super(effect); + } + + @Override + public PrimalCommandShuffleGraveyardEffect copy() { + return new PrimalCommandShuffleGraveyardEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getFirstTarget()); + if (player != null) { + player.getLibrary().addAll(player.getGraveyard().getCards(game), game); + player.getGraveyard().clear(); + player.getLibrary().shuffle(); + return true; + } + return false; + } +} From 621bc4e1cef155c5a647bf691e8b554573b6241c Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sat, 22 Jun 2013 23:00:39 +0200 Subject: [PATCH 17/22] * Added Entwine ability. --- Mage/src/mage/abilities/AbilityImpl.java | 4 +- Mage/src/mage/abilities/Modes.java | 24 ++- .../OptionalAdditionalModeSourceCosts.java | 42 +++++ .../abilities/keyword/EntwineAbility.java | 160 ++++++++++++++++++ Utils/keywords.txt | 1 + 5 files changed, 228 insertions(+), 3 deletions(-) create mode 100644 Mage/src/mage/abilities/costs/OptionalAdditionalModeSourceCosts.java create mode 100644 Mage/src/mage/abilities/keyword/EntwineAbility.java diff --git a/Mage/src/mage/abilities/AbilityImpl.java b/Mage/src/mage/abilities/AbilityImpl.java index 4608c5828d..be15e14b18 100644 --- a/Mage/src/mage/abilities/AbilityImpl.java +++ b/Mage/src/mage/abilities/AbilityImpl.java @@ -52,6 +52,7 @@ import org.apache.log4j.Logger; import java.util.ArrayList; import java.util.List; import java.util.UUID; +import mage.abilities.keyword.EntwineAbility; /** @@ -191,7 +192,8 @@ public abstract class AbilityImpl> implements Ability { break; } } - if (ability instanceof OptionalAdditionalSourceCosts) { + if (ability instanceof OptionalAdditionalSourceCosts + && !(ability instanceof EntwineAbility)) { ((OptionalAdditionalSourceCosts)ability).addOptionalAdditionalCosts(this, game); } } diff --git a/Mage/src/mage/abilities/Modes.java b/Mage/src/mage/abilities/Modes.java index 0637e4a4fc..a27df19db6 100644 --- a/Mage/src/mage/abilities/Modes.java +++ b/Mage/src/mage/abilities/Modes.java @@ -29,10 +29,12 @@ package mage.abilities; import java.util.LinkedHashMap; import java.util.LinkedHashSet; -import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; +import mage.abilities.costs.OptionalAdditionalModeSourceCosts; +import mage.abilities.costs.OptionalAdditionalSourceCosts; +import mage.cards.Card; import mage.game.Game; import mage.players.Player; @@ -109,7 +111,25 @@ public class Modes extends LinkedHashMap { public boolean choose(Game game, Ability source) { if (this.size() > 1) { this.selectedModes.clear(); - + // check if mode modifying abilities exist + Card card = game.getCard(source.getSourceId()); + if (card != null) { + for (Ability modeModifyingAbility : card.getAbilities()) { + if (modeModifyingAbility instanceof OptionalAdditionalModeSourceCosts) { + ((OptionalAdditionalModeSourceCosts)modeModifyingAbility).addOptionalAdditionalModeCosts(source, game); + } + } + } + // check if all modes can be activated automatically + if (this.size() == this.getMinModes()) { + for (Mode mode: this.values()) { + if (mode.getTargets().canChoose(source.getSourceId(), source.getControllerId(), game)) { + this.selectedModes.add(mode.getId()); + } + } + return selectedModes.size() > 0; + } + // player chooses modes manually Player player = game.getPlayer(source.getControllerId()); while (this.selectedModes.size() < this.getMaxModes()) { Mode choice = player.chooseMode(this, source, game); diff --git a/Mage/src/mage/abilities/costs/OptionalAdditionalModeSourceCosts.java b/Mage/src/mage/abilities/costs/OptionalAdditionalModeSourceCosts.java new file mode 100644 index 0000000000..104542486d --- /dev/null +++ b/Mage/src/mage/abilities/costs/OptionalAdditionalModeSourceCosts.java @@ -0,0 +1,42 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.abilities.costs; + +import mage.abilities.Ability; +import mage.game.Game; + +/** + * + * @author LevelX2 + */ + + +public interface OptionalAdditionalModeSourceCosts { + void addOptionalAdditionalModeCosts(Ability ability, Game game); + String getCastMessageSuffix(); +} diff --git a/Mage/src/mage/abilities/keyword/EntwineAbility.java b/Mage/src/mage/abilities/keyword/EntwineAbility.java new file mode 100644 index 0000000000..8e755cebde --- /dev/null +++ b/Mage/src/mage/abilities/keyword/EntwineAbility.java @@ -0,0 +1,160 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.abilities.keyword; + +import java.util.Iterator; + +import mage.constants.Zone; +import mage.abilities.Ability; +import mage.abilities.SpellAbility; +import mage.abilities.StaticAbility; +import mage.abilities.costs.Cost; +import mage.abilities.costs.Costs; +import mage.abilities.costs.OptionalAdditionalCost; +import mage.abilities.costs.OptionalAdditionalCostImpl; +import mage.abilities.costs.OptionalAdditionalModeSourceCosts; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.constants.Outcome; +import mage.game.Game; +import mage.players.Player; + +/** + * 702.40. Entwine + * + * 702.40a Entwine is a static ability of modal spells (see rule 700.2) that functions + * while the spell is on the stack. "Entwine [cost]" means "You may choose all modes + * of this spell instead of just one. If you do, you pay an additional [cost]." Using + * the entwine ability follows the rules for choosing modes and paying additional costs + * in rules 601.2b and 601.2e-g. + * + * 702.40b If the entwine cost was paid, follow the text of each of the modes in the order + * written on the card when the spell resolves. + * + * @author LevelX2 + */ + +public class EntwineAbility extends StaticAbility implements OptionalAdditionalModeSourceCosts { + + private static final String keywordText = "Entwine"; + private static final String reminderText = " (Choose both if you pay the entwine cost.)"; + protected OptionalAdditionalCost additionalCost; + + public EntwineAbility(String manaString) { + super(Zone.STACK, null); + this.additionalCost = new OptionalAdditionalCostImpl(keywordText, reminderText, new ManaCostsImpl(manaString)); + } + + public EntwineAbility(Cost cost) { + super(Zone.STACK, null); + this.additionalCost = new OptionalAdditionalCostImpl(keywordText, "-", reminderText, cost); + setRuleAtTheTop(true); + } + + public EntwineAbility(final EntwineAbility ability) { + super(ability); + additionalCost = ability.additionalCost; + } + + @Override + public EntwineAbility copy() { + return new EntwineAbility(this); + } + + @Override + public void addCost(Cost cost) { + if (additionalCost != null) { + ((Costs) additionalCost).add(cost); + } + } + + public boolean isActivated() { + if (additionalCost != null) { + return additionalCost.isActivated(); + } + return false; + } + + public void resetCosts() { + if (additionalCost != null) { + additionalCost.reset(); + } + } + + @Override + public void addOptionalAdditionalModeCosts(Ability ability, Game game) { + if (ability instanceof SpellAbility) { + Player player = game.getPlayer(controllerId); + if (player != null) { + this.resetCosts(); + if (additionalCost != null) { + if (player.chooseUse(Outcome.Benefit,new StringBuilder("Pay ").append(additionalCost.getText(false)).append(" ?").toString(), game)) { + additionalCost.activate(); + for (Iterator it = ((Costs) additionalCost).iterator(); it.hasNext();) { + Cost cost = (Cost) it.next(); + if (cost instanceof ManaCostsImpl) { + ability.getManaCostsToPay().add((ManaCostsImpl) cost.copy()); + } else { + ability.getCosts().add(cost.copy()); + } + } + ability.getModes().setMinModes(2); + ability.getModes().setMaxModes(2); + } + } + } + } + } + + + @Override + public String getRule() { + StringBuilder sb = new StringBuilder(); + if (additionalCost != null) { + sb.append(additionalCost.getText(false)); + sb.append(" ").append(additionalCost.getReminderText()); + } + return sb.toString(); + } + + @Override + public String getCastMessageSuffix() { + if (additionalCost != null) { + return additionalCost.getCastSuffixMessage(0); + } else { + return ""; + } + } + + public String getReminderText() { + if (additionalCost != null) { + return additionalCost.getReminderText(); + } else { + return ""; + } + } +} diff --git a/Utils/keywords.txt b/Utils/keywords.txt index 7703191a84..4b4a2e77d1 100644 --- a/Utils/keywords.txt +++ b/Utils/keywords.txt @@ -3,6 +3,7 @@ Bloodthirst|number| Bushido|number| Dredge|number| Evoke|card, manaString| +Entwine|manaString| Soulshift|number| Basic landcycling|cost| Forestcycling|cost| From ca42bfd7dab519c671af8cad4fe78f6473a1801a Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sat, 22 Jun 2013 23:01:06 +0200 Subject: [PATCH 18/22] [MMA] Added 4 cards with Entwine. --- .../src/mage/sets/darksteel/StirThePride.java | 52 ++++++ .../sets/elspethvstezzeret/BlindingBeam.java | 158 ++++++++++++++++++ .../mage/sets/fifthdawn/RudeAwakening.java | 52 ++++++ .../src/mage/sets/mirrodin/BlindingBeam.java | 52 ++++++ .../src/mage/sets/mirrodin/ToothAndNail.java | 52 ++++++ .../mage/sets/modernmasters/BlindingBeam.java | 52 ++++++ .../sets/modernmasters/RudeAwakening.java | 88 ++++++++++ .../mage/sets/modernmasters/StirThePride.java | 155 +++++++++++++++++ .../mage/sets/modernmasters/ToothAndNail.java | 117 +++++++++++++ 9 files changed, 778 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/darksteel/StirThePride.java create mode 100644 Mage.Sets/src/mage/sets/elspethvstezzeret/BlindingBeam.java create mode 100644 Mage.Sets/src/mage/sets/fifthdawn/RudeAwakening.java create mode 100644 Mage.Sets/src/mage/sets/mirrodin/BlindingBeam.java create mode 100644 Mage.Sets/src/mage/sets/mirrodin/ToothAndNail.java create mode 100644 Mage.Sets/src/mage/sets/modernmasters/BlindingBeam.java create mode 100644 Mage.Sets/src/mage/sets/modernmasters/RudeAwakening.java create mode 100644 Mage.Sets/src/mage/sets/modernmasters/StirThePride.java create mode 100644 Mage.Sets/src/mage/sets/modernmasters/ToothAndNail.java diff --git a/Mage.Sets/src/mage/sets/darksteel/StirThePride.java b/Mage.Sets/src/mage/sets/darksteel/StirThePride.java new file mode 100644 index 0000000000..866b3ac875 --- /dev/null +++ b/Mage.Sets/src/mage/sets/darksteel/StirThePride.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.darksteel; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class StirThePride extends mage.sets.modernmasters.StirThePride { + + public StirThePride(UUID ownerId) { + super(ownerId); + this.cardNumber = 16; + this.expansionSetCode = "DST"; + } + + public StirThePride(final StirThePride card) { + super(card); + } + + @Override + public StirThePride copy() { + return new StirThePride(this); + } +} diff --git a/Mage.Sets/src/mage/sets/elspethvstezzeret/BlindingBeam.java b/Mage.Sets/src/mage/sets/elspethvstezzeret/BlindingBeam.java new file mode 100644 index 0000000000..48c8445120 --- /dev/null +++ b/Mage.Sets/src/mage/sets/elspethvstezzeret/BlindingBeam.java @@ -0,0 +1,158 @@ +/* + * 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.elspethvstezzeret; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.effects.common.TapTargetEffect; +import mage.abilities.keyword.EntwineAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.PhaseStep; +import mage.constants.Rarity; +import mage.filter.common.FilterCreaturePermanent; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LevelX2 + */ +public class BlindingBeam extends CardImpl { + + public BlindingBeam(UUID ownerId) { + super(ownerId, 28, "Blinding Beam", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{2}{W}"); + this.expansionSetCode = "DDF"; + + this.color.setWhite(true); + + // Choose one - + this.getSpellAbility().getModes().setMinModes(1); + this.getSpellAbility().getModes().setMaxModes(1); + // Tap two target creatures; + this.getSpellAbility().addEffect(new TapTargetEffect()); + this.getSpellAbility().addTarget(new TargetCreaturePermanent(2,2)); + // or creatures don't untap during target player's next untap step. + Mode mode = new Mode(); + mode.getEffects().add(new BlindingBeamEffect()); + this.getSpellAbility().getModes().addMode(mode); + + // Entwine {1} + this.addAbility(new EntwineAbility("{1}")); + } + + public BlindingBeam(final BlindingBeam card) { + super(card); + } + + @Override + public BlindingBeam copy() { + return new BlindingBeam(this); + } +} + +class BlindingBeamEffect extends OneShotEffect { + + public BlindingBeamEffect() { + super(Outcome.Tap); + staticText = "creatures don't untap during target player's next untap step"; + } + + public BlindingBeamEffect(final BlindingBeamEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getFirstTarget()); + if (player != null) { + for (Permanent creature: game.getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), player.getId(), game)) { + game.addEffect(new BlindingBeamEffect2(creature.getId()), source); + } + return true; + } + return false; + } + + @Override + public BlindingBeamEffect copy() { + return new BlindingBeamEffect(this); + } + +} + +class BlindingBeamEffect2 extends ReplacementEffectImpl { + + protected UUID creatureId; + + public BlindingBeamEffect2(UUID creatureId) { + super(Duration.OneUse, Outcome.Detriment); + this.creatureId = creatureId; + } + + public BlindingBeamEffect2(final BlindingBeamEffect2 effect) { + super(effect); + creatureId = effect.creatureId; + } + + @Override + public BlindingBeamEffect2 copy() { + return new BlindingBeamEffect2(this); + } + + @Override + public boolean apply(Game game, Ability source) { + return false; + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + used = true; + return true; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (game.getTurn().getStepType() == PhaseStep.UNTAP && + event.getType() == EventType.UNTAP && + event.getTargetId().equals(creatureId)) { + return true; + } + return false; + } + +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/fifthdawn/RudeAwakening.java b/Mage.Sets/src/mage/sets/fifthdawn/RudeAwakening.java new file mode 100644 index 0000000000..816be8afe5 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fifthdawn/RudeAwakening.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.fifthdawn; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class RudeAwakening extends mage.sets.modernmasters.RudeAwakening { + + public RudeAwakening(UUID ownerId) { + super(ownerId); + this.cardNumber = 92; + this.expansionSetCode = "5DN"; + } + + public RudeAwakening(final RudeAwakening card) { + super(card); + } + + @Override + public RudeAwakening copy() { + return new RudeAwakening(this); + } +} diff --git a/Mage.Sets/src/mage/sets/mirrodin/BlindingBeam.java b/Mage.Sets/src/mage/sets/mirrodin/BlindingBeam.java new file mode 100644 index 0000000000..b762ddbc0c --- /dev/null +++ b/Mage.Sets/src/mage/sets/mirrodin/BlindingBeam.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.mirrodin; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class BlindingBeam extends mage.sets.elspethvstezzeret.BlindingBeam { + + public BlindingBeam(UUID ownerId) { + super(ownerId); + this.cardNumber = 7; + this.expansionSetCode = "MRD"; + } + + public BlindingBeam(final BlindingBeam card) { + super(card); + } + + @Override + public BlindingBeam copy() { + return new BlindingBeam(this); + } +} diff --git a/Mage.Sets/src/mage/sets/mirrodin/ToothAndNail.java b/Mage.Sets/src/mage/sets/mirrodin/ToothAndNail.java new file mode 100644 index 0000000000..a50188250a --- /dev/null +++ b/Mage.Sets/src/mage/sets/mirrodin/ToothAndNail.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.mirrodin; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class ToothAndNail extends mage.sets.modernmasters.ToothAndNail { + + public ToothAndNail(UUID ownerId) { + super(ownerId); + this.cardNumber = 134; + this.expansionSetCode = "MRD"; + } + + public ToothAndNail(final ToothAndNail card) { + super(card); + } + + @Override + public ToothAndNail copy() { + return new ToothAndNail(this); + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/BlindingBeam.java b/Mage.Sets/src/mage/sets/modernmasters/BlindingBeam.java new file mode 100644 index 0000000000..f6b2666b46 --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/BlindingBeam.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.modernmasters; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class BlindingBeam extends mage.sets.elspethvstezzeret.BlindingBeam { + + public BlindingBeam(UUID ownerId) { + super(ownerId); + this.cardNumber = 7; + this.expansionSetCode = "MMA"; + } + + public BlindingBeam(final BlindingBeam card) { + super(card); + } + + @Override + public BlindingBeam copy() { + return new BlindingBeam(this); + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/RudeAwakening.java b/Mage.Sets/src/mage/sets/modernmasters/RudeAwakening.java new file mode 100644 index 0000000000..bda59eebe3 --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/RudeAwakening.java @@ -0,0 +1,88 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.modernmasters; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Mode; +import mage.abilities.effects.common.UntapAllLandsControllerEffect; +import mage.abilities.effects.common.continious.BecomesCreatureAllEffect; +import mage.abilities.keyword.EntwineAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.filter.common.FilterControlledLandPermanent; +import mage.game.permanent.token.Token; + + +/** + * + * @author LevelX2 + */ +public class RudeAwakening extends CardImpl { + + public RudeAwakening(UUID ownerId) { + super(ownerId, 160, "Rude Awakening", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{4}{G}"); + this.expansionSetCode = "MMA"; + + this.color.setGreen(true); + + // Choose one - + this.getSpellAbility().getModes().setMinModes(1); + this.getSpellAbility().getModes().setMaxModes(1); + // Untap all lands you control; + this.getSpellAbility().addEffect(new UntapAllLandsControllerEffect()); + // or until end of turn, lands you control become 2/2 creatures that are still lands. + Mode mode = new Mode(); + mode.getEffects().add(new BecomesCreatureAllEffect(new RudeAwakeningToken(), "lands", new FilterControlledLandPermanent("lands you control"), Duration.EndOfTurn)); + this.getSpellAbility().getModes().addMode(mode); + + // Entwine {2}{G} + this.addAbility(new EntwineAbility("{2}{G}")); + } + + public RudeAwakening(final RudeAwakening card) { + super(card); + } + + @Override + public RudeAwakening copy() { + return new RudeAwakening(this); + } +} + +class RudeAwakeningToken extends Token { + public RudeAwakeningToken() { + super("", "2/2 creature"); + cardType.add(CardType.CREATURE); + power = new MageInt(2); + toughness = new MageInt(2); + } + +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/StirThePride.java b/Mage.Sets/src/mage/sets/modernmasters/StirThePride.java new file mode 100644 index 0000000000..ce6196b28a --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/StirThePride.java @@ -0,0 +1,155 @@ +/* + * 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.modernmasters; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continious.BoostControlledEffect; +import mage.abilities.effects.common.continious.GainAbilityControlledEffect; +import mage.abilities.keyword.EntwineAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; +import mage.players.Player; + +/** + * + * @author LevelX2 + */ +public class StirThePride extends CardImpl { + + public StirThePride(UUID ownerId) { + super(ownerId, 30, "Stir the Pride", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{4}{W}"); + this.expansionSetCode = "MMA"; + + this.color.setWhite(true); + + // Choose one - + this.getSpellAbility().getModes().setMinModes(1); + this.getSpellAbility().getModes().setMaxModes(1); + // Creatures you control get +2/+2 until end of turn; + this.getSpellAbility().addEffect(new BoostControlledEffect(2,2, Duration.EndOfTurn)); + // or until end of turn, creatures you control gain "Whenever this creature deals damage, you gain that much life." + Mode mode = new Mode(); + Effect effect = new GainAbilityControlledEffect(new StirThePrideTriggeredAbility(), Duration.EndOfTurn); + effect.setText("until end of turn, creatures you control gain \"Whenever this creature deals damage, you gain that much life.\""); + mode.getEffects().add(effect); + this.getSpellAbility().getModes().addMode(mode); + + // Entwine {1}{W} + this.addAbility(new EntwineAbility("{1}{W}")); + + } + + public StirThePride(final StirThePride card) { + super(card); + } + + @Override + public StirThePride copy() { + return new StirThePride(this); + } +} + +class StirThePrideTriggeredAbility extends TriggeredAbilityImpl { + + public StirThePrideTriggeredAbility() { + super(Zone.BATTLEFIELD, new StirThePrideGainLifeEffect(), false); + } + + public StirThePrideTriggeredAbility(final StirThePrideTriggeredAbility ability) { + super(ability); + } + + @Override + public StirThePrideTriggeredAbility copy() { + return new StirThePrideTriggeredAbility(this); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getType().equals(EventType.DAMAGED_CREATURE) + || event.getType().equals(GameEvent.EventType.DAMAGED_PLAYER) + || event.getType().equals(GameEvent.EventType.DAMAGED_PLANESWALKER)) { + if (event.getSourceId().equals(this.getSourceId())) { + for (Effect effect : this.getEffects()) { + effect.setValue("damage", event.getAmount()); + } + return true; + } + + } + return false; + } + + @Override + public String getRule() { + return "Whenever {this} deals damage, " + super.getRule(); + } + +} + +class StirThePrideGainLifeEffect extends OneShotEffect { + + public StirThePrideGainLifeEffect() { + super(Outcome.GainLife); + this.staticText = "you gain that much life"; + } + + public StirThePrideGainLifeEffect(final StirThePrideGainLifeEffect effect) { + super(effect); + } + + @Override + public StirThePrideGainLifeEffect copy() { + return new StirThePrideGainLifeEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + int amount = (Integer) getValue("damage"); + if (amount > 0) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + controller.gainLife(amount, game); + return true; + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/ToothAndNail.java b/Mage.Sets/src/mage/sets/modernmasters/ToothAndNail.java new file mode 100644 index 0000000000..62d5f76bbb --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/ToothAndNail.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.modernmasters; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect; +import mage.abilities.keyword.EntwineAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterCreatureCard; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetCardInHand; +import mage.target.common.TargetCardInLibrary; + +/** + * + * @author LevelX2 + */ +public class ToothAndNail extends CardImpl { + + public ToothAndNail(UUID ownerId) { + super(ownerId, 170, "Tooth and Nail", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{5}{G}{G}"); + this.expansionSetCode = "MMA"; + + this.color.setGreen(true); + + // Choose one - + // Search your library for up to two creature cards, reveal them, put them into your hand, then shuffle your library; + this.getSpellAbility().addEffect(new SearchLibraryPutInHandEffect(new TargetCardInLibrary(0, 2, new FilterCreatureCard()))); + // or put up to two creature cards from your hand onto the battlefield. + Mode mode = new Mode(); + mode.getEffects().add(new ToothAndNailPutCreatureOnBattlefieldEffect()); + this.getSpellAbility().getModes().addMode(mode); + + // Entwine {2} + this.addAbility(new EntwineAbility("{2}")); + } + + public ToothAndNail(final ToothAndNail card) { + super(card); + } + + @Override + public ToothAndNail copy() { + return new ToothAndNail(this); + } +} + +class ToothAndNailPutCreatureOnBattlefieldEffect extends OneShotEffect { + + public ToothAndNailPutCreatureOnBattlefieldEffect() { + super(Outcome.PutCreatureInPlay); + this.staticText = "Put up to two creature cards from your hand onto the battlefield"; + } + + public ToothAndNailPutCreatureOnBattlefieldEffect(final ToothAndNailPutCreatureOnBattlefieldEffect effect) { + super(effect); + } + + @Override + public ToothAndNailPutCreatureOnBattlefieldEffect copy() { + return new ToothAndNailPutCreatureOnBattlefieldEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return false; + } + + TargetCardInHand target = new TargetCardInHand(0, 2, new FilterCreatureCard("creature cards")); + if (player.choose(Outcome.PutCreatureInPlay, target, source.getSourceId(), game)) { + for (UUID targetId: target.getTargets()) { + Card card = game.getCard(targetId); + if (card != null) { + card.putOntoBattlefield(game, Zone.HAND, source.getId(), source.getControllerId()); + } + } + return true; + } + return false; + } +} From 5898f8a79890fd354713266bbf85f34f1b9965ee Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sun, 23 Jun 2013 02:45:30 +0200 Subject: [PATCH 19/22] [minor] Changed layout of create tournament table dialog. --- .../client/dialog/NewTournamentDialog.form | 89 +++++++++---------- .../client/dialog/NewTournamentDialog.java | 80 ++++++++--------- 2 files changed, 82 insertions(+), 87 deletions(-) diff --git a/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.form b/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.form index d2b4221f2d..fb97f4a2e4 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.form +++ b/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.form @@ -33,54 +33,51 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - @@ -111,10 +108,10 @@ - + - + diff --git a/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java b/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java index 04a623f5fd..3b8226bd44 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java @@ -258,45 +258,43 @@ public class NewTournamentDialog extends MageDialog { .addComponent(btnOk) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(btnCancel)) - .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() - .addComponent(jLabel2) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(spnNumPlayers, javax.swing.GroupLayout.PREFERRED_SIZE, 45, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(pnlDraftOptions, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addComponent(jLabel5, javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) - .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() - .addComponent(lblName) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(txtName, javax.swing.GroupLayout.PREFERRED_SIZE, 233, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(lbTimeLimit) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(cbTimeLimit, 0, 115, Short.MAX_VALUE)) - .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() - .addComponent(jLabel1) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(cbTournamentType, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(lblFreeMulligans) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(spnFreeMulligans, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(lblNumWins) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(spnNumWins, javax.swing.GroupLayout.PREFERRED_SIZE, 41, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() - .addGap(23, 23, 23) - .addComponent(lblConstructionTime) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(spnConstructTime, javax.swing.GroupLayout.PREFERRED_SIZE, 41, javax.swing.GroupLayout.PREFERRED_SIZE))))) - .addGap(0, 0, Short.MAX_VALUE))) + .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() + .addComponent(jLabel2) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(spnNumPlayers, javax.swing.GroupLayout.PREFERRED_SIZE, 45, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(pnlDraftOptions, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(jLabel5, javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) + .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() + .addComponent(lblName) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(txtName, javax.swing.GroupLayout.PREFERRED_SIZE, 233, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(lbTimeLimit) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(cbTimeLimit, 0, 115, Short.MAX_VALUE)) + .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() + .addComponent(jLabel1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(cbTournamentType, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(lblConstructionTime) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(spnConstructTime, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, Short.MAX_VALUE)) + .addGroup(layout.createSequentialGroup() + .addComponent(lblFreeMulligans) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(spnFreeMulligans, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(lblNumWins) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(spnNumWins, javax.swing.GroupLayout.PREFERRED_SIZE, 41, javax.swing.GroupLayout.PREFERRED_SIZE)))))) .addContainerGap()) ); layout.setVerticalGroup( @@ -321,10 +319,10 @@ public class NewTournamentDialog extends MageDialog { .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jLabel5) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(pnlPacks, javax.swing.GroupLayout.DEFAULT_SIZE, 60, Short.MAX_VALUE) + .addComponent(pnlPacks, javax.swing.GroupLayout.DEFAULT_SIZE, 62, Short.MAX_VALUE) .addGap(11, 11, 11) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(spnNumPlayers, javax.swing.GroupLayout.DEFAULT_SIZE, 23, Short.MAX_VALUE) + .addComponent(spnNumPlayers, javax.swing.GroupLayout.DEFAULT_SIZE, 25, Short.MAX_VALUE) .addComponent(pnlDraftOptions, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(jLabel2)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) From 0e87313e1ac17eef98f99c8f891bc2c48a303aba Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sun, 23 Jun 2013 02:53:55 +0200 Subject: [PATCH 20/22] CounterPredicates works now with card counters. Handle Exile to Exile movement. --- Mage/src/mage/cards/CardImpl.java | 3 +++ .../mage/filter/predicate/permanent/CounterPredicate.java | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Mage/src/mage/cards/CardImpl.java b/Mage/src/mage/cards/CardImpl.java index 4e0879a346..6f788edbb9 100644 --- a/Mage/src/mage/cards/CardImpl.java +++ b/Mage/src/mage/cards/CardImpl.java @@ -402,6 +402,9 @@ public abstract class CardImpl> extends MageObjectImpl case LIBRARY: game.getPlayer(ownerId).removeFromLibrary(this, game); break; + case EXILED: + game.getExile().removeCard(this, game); + break; default: logger.warn("moveToExile, not fully implemented: from="+fromZone); } diff --git a/Mage/src/mage/filter/predicate/permanent/CounterPredicate.java b/Mage/src/mage/filter/predicate/permanent/CounterPredicate.java index 1096383d4d..4c8852246f 100644 --- a/Mage/src/mage/filter/predicate/permanent/CounterPredicate.java +++ b/Mage/src/mage/filter/predicate/permanent/CounterPredicate.java @@ -27,16 +27,16 @@ */ package mage.filter.predicate.permanent; +import mage.cards.Card; import mage.counters.CounterType; import mage.filter.predicate.Predicate; import mage.game.Game; -import mage.game.permanent.Permanent; /** * * @author jeff */ -public class CounterPredicate implements Predicate { +public class CounterPredicate implements Predicate { private final CounterType counter; @@ -45,7 +45,7 @@ public class CounterPredicate implements Predicate { } @Override - public boolean apply(Permanent input, Game game) { + public boolean apply(Card input, Game game) { return input.getCounters().containsKey(counter); } From 72ca119ececce7b60fda04085c30c4c2c345f215 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sun, 23 Jun 2013 02:54:30 +0200 Subject: [PATCH 21/22] [minor] Fixed rule text generation. --- .../mage/sets/newphyrexia/MyrSuperion.java | 29 +++++++++++++++++-- Mage/src/mage/abilities/Modes.java | 2 +- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/Mage.Sets/src/mage/sets/newphyrexia/MyrSuperion.java b/Mage.Sets/src/mage/sets/newphyrexia/MyrSuperion.java index 31868181a0..fddf873753 100644 --- a/Mage.Sets/src/mage/sets/newphyrexia/MyrSuperion.java +++ b/Mage.Sets/src/mage/sets/newphyrexia/MyrSuperion.java @@ -28,10 +28,12 @@ package mage.sets.newphyrexia; import java.util.UUID; +import mage.MageInt; +import mage.abilities.StaticAbility; +import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Rarity; -import mage.MageInt; -import mage.cards.CardImpl; +import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; /** @@ -51,6 +53,7 @@ public class MyrSuperion extends CardImpl { this.toughness = new MageInt(6); // Spend only mana produced by creatures to cast Myr Superion. + this.addAbility(new MyrSuperionStaticAbility()); this.getSpellAbility().getManaCostsToPay().setSourceFilter(filter); this.getSpellAbility().getManaCosts().setSourceFilter(filter); } @@ -64,3 +67,25 @@ public class MyrSuperion extends CardImpl { return new MyrSuperion(this); } } + +class MyrSuperionStaticAbility extends StaticAbility { + + public MyrSuperionStaticAbility() { + super(Zone.STACK, null); + } + + public MyrSuperionStaticAbility(MyrSuperionStaticAbility ability) { + super(ability); + } + + @Override + public MyrSuperionStaticAbility copy() { + return new MyrSuperionStaticAbility(this); + } + + @Override + public String getRule() { + return "Spend only mana produced by creatures to cast {this}."; + } + +} diff --git a/Mage/src/mage/abilities/Modes.java b/Mage/src/mage/abilities/Modes.java index a27df19db6..47bd730475 100644 --- a/Mage/src/mage/abilities/Modes.java +++ b/Mage/src/mage/abilities/Modes.java @@ -33,7 +33,6 @@ import java.util.Map; import java.util.Set; import java.util.UUID; import mage.abilities.costs.OptionalAdditionalModeSourceCosts; -import mage.abilities.costs.OptionalAdditionalSourceCosts; import mage.cards.Card; import mage.game.Game; import mage.players.Player; @@ -175,6 +174,7 @@ public class Modes extends LinkedHashMap { } if (this.size() > 1) { sb.delete(sb.length() - andOr.length(), sb.length()); + sb.append("."); } return sb.toString(); } From 9180ecc1f0cfb79fa611ea915af4f3b52ab2d260 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sun, 23 Jun 2013 02:54:53 +0200 Subject: [PATCH 22/22] [MMA] Added 3 cards. --- .../championsofkamigawa/KodamasReach.java | 52 ++++++ .../src/mage/sets/commander/KodamasReach.java | 139 +++++++++++++++ .../mage/sets/futuresight/Imperiosaur.java | 54 ++++++ .../mage/sets/modernmasters/FuryCharm.java | 52 ++++++ .../mage/sets/modernmasters/Imperiosaur.java | 96 +++++++++++ .../mage/sets/modernmasters/KodamasReach.java | 52 ++++++ .../src/mage/sets/planarchaos/FuryCharm.java | 163 ++++++++++++++++++ 7 files changed, 608 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/championsofkamigawa/KodamasReach.java create mode 100644 Mage.Sets/src/mage/sets/commander/KodamasReach.java create mode 100644 Mage.Sets/src/mage/sets/futuresight/Imperiosaur.java create mode 100644 Mage.Sets/src/mage/sets/modernmasters/FuryCharm.java create mode 100644 Mage.Sets/src/mage/sets/modernmasters/Imperiosaur.java create mode 100644 Mage.Sets/src/mage/sets/modernmasters/KodamasReach.java create mode 100644 Mage.Sets/src/mage/sets/planarchaos/FuryCharm.java diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/KodamasReach.java b/Mage.Sets/src/mage/sets/championsofkamigawa/KodamasReach.java new file mode 100644 index 0000000000..0929eb3d74 --- /dev/null +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/KodamasReach.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.championsofkamigawa; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class KodamasReach extends mage.sets.commander.KodamasReach { + + public KodamasReach(UUID ownerId) { + super(ownerId); + this.cardNumber = 225; + this.expansionSetCode = "CHK"; + } + + public KodamasReach(final KodamasReach card) { + super(card); + } + + @Override + public KodamasReach copy() { + return new KodamasReach(this); + } +} diff --git a/Mage.Sets/src/mage/sets/commander/KodamasReach.java b/Mage.Sets/src/mage/sets/commander/KodamasReach.java new file mode 100644 index 0000000000..f05fa597b1 --- /dev/null +++ b/Mage.Sets/src/mage/sets/commander/KodamasReach.java @@ -0,0 +1,139 @@ +/* + * 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.commander; + +import java.util.List; +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.Cards; +import mage.cards.CardsImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.filter.common.FilterBasicLandCard; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.TargetCard; +import mage.target.common.TargetCardInLibrary; + +/** + * + * @author LevelX2 + */ +public class KodamasReach extends CardImpl { + + public KodamasReach(UUID ownerId) { + super(ownerId, 163, "Kodama's Reach", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{2}{G}"); + this.expansionSetCode = "CMD"; + this.subtype.add("Arcane"); + + this.color.setGreen(true); + + // Search your library for up to two basic land cards, reveal those cards, and put one onto the battlefield tapped and the other into your hand. Then shuffle your library. + this.getSpellAbility().addEffect(new KodamasReachEffect()); + } + + public KodamasReach(final KodamasReach card) { + super(card); + } + + @Override + public KodamasReach copy() { + return new KodamasReach(this); + } +} + +class KodamasReachEffect extends OneShotEffect { + + protected static final FilterCard filter = new FilterCard("card to put on the battlefield tapped"); + + public KodamasReachEffect() { + super(Outcome.PutLandInPlay); + staticText = "Search your library for up to two basic land cards, reveal those cards, and put one onto the battlefield tapped and the other into your hand. Then shuffle your library"; + } + + public KodamasReachEffect(final KodamasReachEffect effect) { + super(effect); + } + + @Override + public KodamasReachEffect copy() { + return new KodamasReachEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + TargetCardInLibrary target = new TargetCardInLibrary(0, 2, new FilterBasicLandCard()); + Player player = game.getPlayer(source.getControllerId()); + if (player.searchLibrary(target, game)) { + if (target.getTargets().size() > 0) { + Cards revealed = new CardsImpl(); + for (UUID cardId: (List)target.getTargets()) { + Card card = player.getLibrary().getCard(cardId, game); + revealed.add(card); + } + player.revealCards("Kodama's Reach", revealed, game); + if (target.getTargets().size() == 2) { + TargetCard target2 = new TargetCard(Zone.PICK, filter); + target2.setRequired(true); + player.choose(Outcome.Benefit, revealed, target2, game); + Card card = revealed.get(target2.getFirstTarget(), game); + card.putOntoBattlefield(game, Zone.LIBRARY, source.getId(), source.getControllerId()); + revealed.remove(card); + Permanent permanent = game.getPermanent(card.getId()); + if (permanent != null) { + permanent.setTapped(true); + } + card = revealed.getCards(game).iterator().next(); + card.moveToZone(Zone.HAND, source.getId(), game, false); + } + else if (target.getTargets().size() == 1) { + Card card = revealed.getCards(game).iterator().next(); + card.putOntoBattlefield(game, Zone.LIBRARY, source.getId(), source.getControllerId()); + Permanent permanent = game.getPermanent(card.getId()); + if (permanent != null) { + permanent.setTapped(true); + } + } + + } + player.shuffleLibrary(game); + return true; + } + player.shuffleLibrary(game); + return false; + + } + +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/futuresight/Imperiosaur.java b/Mage.Sets/src/mage/sets/futuresight/Imperiosaur.java new file mode 100644 index 0000000000..864ce03ce1 --- /dev/null +++ b/Mage.Sets/src/mage/sets/futuresight/Imperiosaur.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.futuresight; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author LevelX2 + */ +public class Imperiosaur extends mage.sets.modernmasters.Imperiosaur { + + public Imperiosaur(UUID ownerId) { + super(ownerId); + this.cardNumber = 145; + this.expansionSetCode = "FUT"; + this.rarity = Rarity.UNCOMMON; + } + + public Imperiosaur(final Imperiosaur card) { + super(card); + } + + @Override + public Imperiosaur copy() { + return new Imperiosaur(this); + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/FuryCharm.java b/Mage.Sets/src/mage/sets/modernmasters/FuryCharm.java new file mode 100644 index 0000000000..3d8fea9f95 --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/FuryCharm.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.modernmasters; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class FuryCharm extends mage.sets.planarchaos.FuryCharm { + + public FuryCharm(UUID ownerId) { + super(ownerId); + this.cardNumber = 114; + this.expansionSetCode = "MMA"; + } + + public FuryCharm(final FuryCharm card) { + super(card); + } + + @Override + public FuryCharm copy() { + return new FuryCharm(this); + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/Imperiosaur.java b/Mage.Sets/src/mage/sets/modernmasters/Imperiosaur.java new file mode 100644 index 0000000000..328d626568 --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/Imperiosaur.java @@ -0,0 +1,96 @@ +/* + * 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.modernmasters; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.StaticAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterLandPermanent; +import mage.filter.predicate.mageobject.SupertypePredicate; + +/** + * + * @author LevelX2 + */ +public class Imperiosaur extends CardImpl { + + private static final FilterLandPermanent filter = new FilterLandPermanent(); + static { + filter.add(new SupertypePredicate("Basic")); + } + + public Imperiosaur(UUID ownerId) { + super(ownerId, 148, "Imperiosaur", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{2}{G}{G}"); + this.expansionSetCode = "MMA"; + this.subtype.add("Lizard"); + + this.color.setGreen(true); + this.power = new MageInt(5); + this.toughness = new MageInt(5); + + // Spend only mana produced by basic lands to cast Imperiosaur. + this.addAbility(new ImperiosaurStaticAbility()); + this.getSpellAbility().getManaCostsToPay().setSourceFilter(filter); + this.getSpellAbility().getManaCosts().setSourceFilter(filter); + } + + public Imperiosaur(final Imperiosaur card) { + super(card); + } + + @Override + public Imperiosaur copy() { + return new Imperiosaur(this); + } +} + +class ImperiosaurStaticAbility extends StaticAbility { + + public ImperiosaurStaticAbility() { + super(Zone.STACK, null); + } + + public ImperiosaurStaticAbility(ImperiosaurStaticAbility ability) { + super(ability); + } + + @Override + public ImperiosaurStaticAbility copy() { + return new ImperiosaurStaticAbility(this); + } + + @Override + public String getRule() { + return "Spend only mana produced by basic lands to cast {this}."; + } + +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/KodamasReach.java b/Mage.Sets/src/mage/sets/modernmasters/KodamasReach.java new file mode 100644 index 0000000000..085b2a953e --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/KodamasReach.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.modernmasters; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class KodamasReach extends mage.sets.commander.KodamasReach { + + public KodamasReach(UUID ownerId) { + super(ownerId); + this.cardNumber = 151; + this.expansionSetCode = "MMA"; + } + + public KodamasReach(final KodamasReach card) { + super(card); + } + + @Override + public KodamasReach copy() { + return new KodamasReach(this); + } +} diff --git a/Mage.Sets/src/mage/sets/planarchaos/FuryCharm.java b/Mage.Sets/src/mage/sets/planarchaos/FuryCharm.java new file mode 100644 index 0000000000..facc65b445 --- /dev/null +++ b/Mage.Sets/src/mage/sets/planarchaos/FuryCharm.java @@ -0,0 +1,163 @@ +/* + * 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.planarchaos; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.SpellAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.effects.common.continious.BoostTargetEffect; +import mage.abilities.effects.common.continious.GainAbilityTargetEffect; +import mage.abilities.keyword.SuspendAbility; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.choices.Choice; +import mage.choices.ChoiceImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.counters.CounterType; +import mage.filter.FilterCard; +import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.filter.predicate.permanent.CounterPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.Target; +import mage.target.common.TargetArtifactPermanent; +import mage.target.common.TargetCardInExile; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LevelX2 + */ +public class FuryCharm extends CardImpl { + + private static final FilterCard filter = new FilterCard("suspended card"); + static { + filter.add(new CounterPredicate(CounterType.TIME)); + filter.add(new AbilityPredicate(SuspendAbility.class)); + } + + public FuryCharm(UUID ownerId) { + super(ownerId, 100, "Fury Charm", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{1}{R}"); + this.expansionSetCode = "PLC"; + + this.color.setRed(true); + + // Choose one - + this.getSpellAbility().getModes().setMinModes(1); + this.getSpellAbility().getModes().setMaxModes(1); + // Destroy target artifact; + this.getSpellAbility().addEffect(new DestroyTargetEffect()); + this.getSpellAbility().addTarget(new TargetArtifactPermanent()); + // or target creature gets +1/+1 and gains trample until end of turn; + Mode mode = new Mode(); + mode.getEffects().add(new BoostTargetEffect(1,1, Duration.EndOfTurn)); + mode.getEffects().add(new GainAbilityTargetEffect(TrampleAbility.getInstance(),Duration.EndOfTurn)); + mode.getTargets().add(new TargetCreaturePermanent()); + this.getSpellAbility().getModes().addMode(mode); + // or remove two time counters from target permanent or suspended card. + mode = new Mode(); + Choice targetChoice = new ChoiceImpl(); + targetChoice.setMessage("Choose what to target"); + targetChoice.getChoices().add("Permanent"); + targetChoice.getChoices().add("Suspended Card"); + mode.getChoices().add(targetChoice); + mode.getEffects().add(new FuryCharmRemoveCounterEffect()); + this.getSpellAbility().getModes().addMode(mode); + + + + } + + @Override + public void adjustTargets(Ability ability, Game game) { + if (ability instanceof SpellAbility) { + for(Effect effect :ability.getEffects()) { + if (effect instanceof FuryCharmRemoveCounterEffect) { + Choice targetChoice = ability.getChoices().get(0); + if (targetChoice.getChoice().equals("Permanent")) { + ability.addTarget(new TargetCreaturePermanent(true)); + } + if (targetChoice.getChoice().equals("Suspended Card")) { + Target target = new TargetCardInExile(1,1, filter, null, true); + target.setRequired(true); + ability.addTarget(target); + } + } + } + } + } + + public FuryCharm(final FuryCharm card) { + super(card); + } + + @Override + public FuryCharm copy() { + return new FuryCharm(this); + } +} + +class FuryCharmRemoveCounterEffect extends OneShotEffect { + + public FuryCharmRemoveCounterEffect() { + super(Outcome.Benefit); + this.staticText = "remove two time counters from target permanent or suspended card"; + } + + public FuryCharmRemoveCounterEffect(final FuryCharmRemoveCounterEffect effect) { + super(effect); + } + + @Override + public FuryCharmRemoveCounterEffect copy() { + return new FuryCharmRemoveCounterEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(this.getTargetPointer().getFirst(game, source)); + if (permanent != null) { + permanent.getCounters().removeCounter(CounterType.TIME, 2); + return true; + } + Card card = game.getCard(this.getTargetPointer().getFirst(game, source)); + if (card != null) { + card.getCounters().removeCounter(CounterType.TIME, 2); + return true; + } + return false; + } +}