diff --git a/Mage.Client/src/main/java/mage/client/MageFrame.java b/Mage.Client/src/main/java/mage/client/MageFrame.java index dfa734f1afc..7df4a984ff0 100644 --- a/Mage.Client/src/main/java/mage/client/MageFrame.java +++ b/Mage.Client/src/main/java/mage/client/MageFrame.java @@ -429,17 +429,41 @@ public class MageFrame extends javax.swing.JFrame implements MageClient { } } + private boolean isChrismasTime(){ + // from december 15 to january 15 + Calendar cal = Calendar.getInstance(); + int currentYear = cal.get(Calendar.YEAR); + Date currentTime = cal.getTime(); + + Date chrisFrom = new GregorianCalendar(currentYear, Calendar.DECEMBER, 15).getTime(); + Date chrisTo = new GregorianCalendar(currentYear + 1, Calendar.JANUARY, 15 + 1).getTime(); + + return currentTime.after(chrisFrom) && currentTime.before(chrisTo); + } + private void addMageLabel() { if (liteMode || grayMode) { return; } - String filename = "/label-xmage.png"; + + String filename; + float ratio; + if (isChrismasTime()){ + // chrismass logo + LOGGER.info("Yo Ho Ho, Merry Christmas and a Happy New Year"); + filename = "/label-xmage-christmas.png"; + ratio = 539.0f / 318.0f; + }else{ + // standard logo + filename = "/label-xmage.png"; + ratio = 509.0f / 288.0f; + } + try { InputStream is = this.getClass().getResourceAsStream(filename); - - float ratio = 1179.0f / 678.0f; - titleRectangle = new Rectangle(540, (int) (640 / ratio)); if (is != null) { + titleRectangle = new Rectangle(540, (int) (640 / ratio)); + BufferedImage image = ImageIO.read(is); //ImageIcon resized = new ImageIcon(image.getScaledInstance(titleRectangle.width, titleRectangle.height, java.awt.Image.SCALE_SMOOTH)); title = new JLabel(); diff --git a/Mage.Client/src/main/resources/label-xmage-christmas.png b/Mage.Client/src/main/resources/label-xmage-christmas.png new file mode 100644 index 00000000000..92edd1ee6c0 Binary files /dev/null and b/Mage.Client/src/main/resources/label-xmage-christmas.png differ diff --git a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java index f281d360e21..b4055ba53f8 100644 --- a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java +++ b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java @@ -489,7 +489,9 @@ public class ComputerPlayer6 extends ComputerPlayer /*implements Player*/ { maxSeconds = 3600; } logger.debug("maxThink: " + maxSeconds + " seconds "); - return task.get(maxSeconds, TimeUnit.SECONDS); + if (task.get(maxSeconds, TimeUnit.SECONDS) != null) { + return task.get(maxSeconds, TimeUnit.SECONDS); + } } catch (TimeoutException e) { logger.info("simulating - timed out"); task.cancel(true); diff --git a/Mage.Sets/src/mage/cards/a/AngrathMinotaurPirate.java b/Mage.Sets/src/mage/cards/a/AngrathMinotaurPirate.java new file mode 100644 index 00000000000..e685f257608 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AngrathMinotaurPirate.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.cards.a; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.LoyaltyAbility; +import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility; +import mage.abilities.effects.Effects; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DamageAllControlledTargetEffect; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.filter.FilterCard; +import mage.filter.StaticFilters; +import mage.filter.common.FilterCreatureCard; +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.common.TargetCardInYourGraveyard; +import mage.target.common.TargetOpponent; + +/** + * + * @author LevelX2 + */ +public class AngrathMinotaurPirate extends CardImpl { + + public AngrathMinotaurPirate(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{4}{B}{R}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.ANGRATH); + this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(5)); + + // +2: Angrath, Minotaur Pirate deals 1 damage to target opponent and each creature that player controls. + Effects effects1 = new Effects(); + effects1.add(new DamageTargetEffect(1)); + effects1.add(new DamageAllControlledTargetEffect(1, new FilterCreaturePermanent()).setText("and each creature that player controls")); + LoyaltyAbility ability1 = new LoyaltyAbility(effects1, +2); + ability1.addTarget(new TargetOpponent()); + this.addAbility(ability1); + + // -3: Return target Pirate card from your graveyard to the battlefield. + FilterCard filterPirateCard = new FilterCreatureCard("pirate card from your graveyard"); + filterPirateCard.add(new SubtypePredicate(SubType.PIRATE)); + Ability ability2 = new LoyaltyAbility(new ReturnFromGraveyardToBattlefieldTargetEffect() + .setText("Return target Pirate card from your graveyard to the battlefield"), -3); + ability2.addTarget(new TargetCardInYourGraveyard(filterPirateCard)); + this.addAbility(ability2); + + // -11: Destroy all creature target opponent controls. Angrath, Minotaur Pirate deals damage to that player equal to their total power. + Ability ability3 = new LoyaltyAbility(new AngrathMinotaurPirateThirdAbilityEffect(), -11); + ability3.addTarget(new TargetOpponent()); + this.addAbility(ability3); + } + + public AngrathMinotaurPirate(final AngrathMinotaurPirate card) { + super(card); + } + + @Override + public AngrathMinotaurPirate copy() { + return new AngrathMinotaurPirate(this); + } +} + +class AngrathMinotaurPirateThirdAbilityEffect extends OneShotEffect { + + public AngrathMinotaurPirateThirdAbilityEffect() { + super(Outcome.DestroyPermanent); + this.staticText = "Destroy all creature target opponent controls. {this} deals damage to that player equal to their total power"; + } + + public AngrathMinotaurPirateThirdAbilityEffect(final AngrathMinotaurPirateThirdAbilityEffect effect) { + super(effect); + } + + @Override + public AngrathMinotaurPirateThirdAbilityEffect copy() { + return new AngrathMinotaurPirateThirdAbilityEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player targetOpponent = game.getPlayer(getTargetPointer().getFirst(game, source)); + if (targetOpponent != null) { + int powerSum = 0; + for (Permanent permanent : game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getSourceId(), game)) { + permanent.destroy(source.getSourceId(), game, false); + powerSum += permanent.getPower().getValue(); + } + game.applyEffects(); + targetOpponent.damage(powerSum, source.getSourceId(), game, false, true); + } + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/a/AngrathsAmbusher.java b/Mage.Sets/src/mage/cards/a/AngrathsAmbusher.java new file mode 100644 index 00000000000..11a4483261c --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AngrathsAmbusher.java @@ -0,0 +1,82 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.a; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.predicate.mageobject.SubtypePredicate; + +/** + * + * @author LevelX2 + */ +public class AngrathsAmbusher extends CardImpl { + + private static final FilterControlledPermanent filter = new FilterControlledPermanent(); + + static { + filter.add(new CardTypePredicate(CardType.PLANESWALKER)); + filter.add(new SubtypePredicate(SubType.ANGRATH)); + } + + public AngrathsAmbusher(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}"); + + this.subtype.add(SubType.ORC); + this.subtype.add(SubType.PIRATE); + this.power = new MageInt(2); + this.toughness = new MageInt(3); + + // Angrath's Ambusher gets +2/+0 as long as you control an Angrath planeswalker. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, + new ConditionalContinuousEffect(new BoostSourceEffect(2, 0, Duration.WhileOnBattlefield), + new PermanentsOnTheBattlefieldCondition(filter), + "{this} gets +2/+0 as long as you control an Angrath planeswalker"))); + } + + public AngrathsAmbusher(final AngrathsAmbusher card) { + super(card); + } + + @Override + public AngrathsAmbusher copy() { + return new AngrathsAmbusher(this); + } +} diff --git a/Mage.Sets/src/mage/cards/a/AngrathsFury.java b/Mage.Sets/src/mage/cards/a/AngrathsFury.java new file mode 100644 index 00000000000..3141cb58d4b --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AngrathsFury.java @@ -0,0 +1,81 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.a; + +import java.util.UUID; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.effects.common.search.SearchLibraryGraveyardPutInHandEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.filter.FilterCard; +import mage.filter.predicate.mageobject.NamePredicate; +import mage.target.TargetPlayer; +import mage.target.common.TargetCreaturePermanent; +import mage.target.targetpointer.SecondTargetPointer; + +/** + * + * @author LevelX2 + */ +public class AngrathsFury extends CardImpl { + + private final static FilterCard filter = new FilterCard("Angrath, Minotaur Pirate"); + + static { + filter.add(new NamePredicate(filter.getMessage())); + } + + public AngrathsFury(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{B}{R}"); + + // Destroy target creature. + this.getSpellAbility().addEffect(new DestroyTargetEffect()); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + + // Angrath's Fury deals 3 damage to target player. + this.getSpellAbility().addEffect(new DamageTargetEffect(3).setTargetPointer(new SecondTargetPointer()) + .setText("{this} deals 3 damage to target player")); + this.getSpellAbility().addTarget(new TargetPlayer()); + + // You may search your library and/or graveyard for a card named Angrath, Minotaur Pirate, reveal it, and put it into your hand. If you search your library this way, shuffle it. + this.getSpellAbility().addEffect(new SearchLibraryGraveyardPutInHandEffect(filter) + .setText("You may search your library and/or graveyard for a card named Angrath, Minotaur Pirate, reveal it, and put it into your hand. If you search your library this way, shuffle it")); + + } + + public AngrathsFury(final AngrathsFury card) { + super(card); + } + + @Override + public AngrathsFury copy() { + return new AngrathsFury(this); + } +} diff --git a/Mage.Sets/src/mage/cards/a/ArlinnEmbracedByTheMoon.java b/Mage.Sets/src/mage/cards/a/ArlinnEmbracedByTheMoon.java index 2904b7e803b..793ed6ffbd3 100644 --- a/Mage.Sets/src/mage/cards/a/ArlinnEmbracedByTheMoon.java +++ b/Mage.Sets/src/mage/cards/a/ArlinnEmbracedByTheMoon.java @@ -43,7 +43,7 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; import mage.constants.SuperType; -import mage.filter.common.FilterCreaturePermanent; +import mage.filter.StaticFilters; import mage.game.command.emblems.ArlinnEmbracedByTheMoonEmblem; import mage.target.common.TargetCreatureOrPlayer; @@ -53,8 +53,6 @@ import mage.target.common.TargetCreatureOrPlayer; */ public class ArlinnEmbracedByTheMoon extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Creatures you control"); - public ArlinnEmbracedByTheMoon(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, ""); this.addSuperType(SuperType.LEGENDARY); @@ -66,10 +64,10 @@ public class ArlinnEmbracedByTheMoon extends CardImpl { this.transformable = true; // +1: Creatures you control get +1/+1 and gain trample until end of turn. - Effect effect = new BoostControlledEffect(1, 1, Duration.EndOfTurn, filter); + Effect effect = new BoostControlledEffect(1, 1, Duration.EndOfTurn, StaticFilters.FILTER_PERMANENT_CREATURE); effect.setText("Creatures you control get +1/+1"); LoyaltyAbility ability = new LoyaltyAbility(effect, 1); - effect = new GainAbilityControlledEffect(TrampleAbility.getInstance(), Duration.EndOfTurn, filter); + effect = new GainAbilityControlledEffect(TrampleAbility.getInstance(), Duration.EndOfTurn, StaticFilters.FILTER_PERMANENT_CREATURE); effect.setText("and gain trample until end of turn"); ability.addEffect(effect); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/a/AugurOfBolas.java b/Mage.Sets/src/mage/cards/a/AugurOfBolas.java index e0e3b2b31dd..5d626a7210f 100644 --- a/Mage.Sets/src/mage/cards/a/AugurOfBolas.java +++ b/Mage.Sets/src/mage/cards/a/AugurOfBolas.java @@ -44,7 +44,6 @@ 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.TargetCard; /** @@ -113,8 +112,8 @@ class AugurOfBolasEffect extends OneShotEffect { if (number == 1) { card = topCards.getCards(new FilterInstantOrSorceryCard(), source.getSourceId(), source.getControllerId(), game).iterator().next(); } else { - Target target = new TargetCard(Zone.LIBRARY, new FilterInstantOrSorceryCard()); - controller.chooseTarget(outcome, target, source, game); + TargetCard target = new TargetCard(Zone.LIBRARY, new FilterInstantOrSorceryCard()); + controller.chooseTarget(outcome, topCards, target, source, game); card = topCards.get(target.getFirstTarget(), game); } if (card != null) { diff --git a/Mage.Sets/src/mage/cards/b/BlatantThievery.java b/Mage.Sets/src/mage/cards/b/BlatantThievery.java index bd64506d75c..85c0c6b8645 100644 --- a/Mage.Sets/src/mage/cards/b/BlatantThievery.java +++ b/Mage.Sets/src/mage/cards/b/BlatantThievery.java @@ -28,7 +28,6 @@ package mage.cards.b; import java.util.*; -import mage.MageObject; import mage.abilities.Ability; import mage.abilities.SpellAbility; import mage.abilities.effects.ContinuousEffect; @@ -40,8 +39,10 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Outcome; import mage.filter.FilterPermanent; +import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; -import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.Target; import mage.target.TargetPermanent; import mage.target.targetpointer.FixedTarget; @@ -52,7 +53,7 @@ import mage.target.targetpointer.FixedTarget; public class BlatantThievery extends CardImpl { public BlatantThievery(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{4}{U}{U}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{U}{U}{U}"); // For each opponent, gain control of target permanent that player controls. this.getSpellAbility().addEffect(new BlatantThieveryEffect()); @@ -66,7 +67,15 @@ public class BlatantThievery extends CardImpl { public void adjustTargets(Ability ability, Game game) { if (ability instanceof SpellAbility) { ability.getTargets().clear(); - ability.addTarget(new BlatantThieveryTarget(game.getOpponents(ability.getControllerId()).size())); + for (UUID opponentId : game.getOpponents(ability.getControllerId())) { + Player opponent = game.getPlayer(opponentId); + if (opponent != null) { + FilterPermanent filter = new FilterPermanent("Permanent of player " + opponent.getName()); + filter.add(new ControllerIdPredicate(opponentId)); + TargetPermanent targetPermanent = new TargetPermanent(filter); + ability.addTarget(targetPermanent); + } + } } } @@ -94,117 +103,13 @@ class BlatantThieveryEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - for (UUID targetId : getTargetPointer().getTargets(game, source)) { - ContinuousEffect effect = new GainControlTargetEffect(Duration.EndOfGame); - effect.setTargetPointer(new FixedTarget(targetId)); - game.addEffect(effect, source); - } - return true; - } -} - -class BlatantThieveryTarget extends TargetPermanent { - - Map targetOpponent = new HashMap<>(); - - public BlatantThieveryTarget(int opponents) { - super(opponents, opponents, new FilterPermanent("a permanent for each opponent"), false); - } - - public BlatantThieveryTarget(final BlatantThieveryTarget target) { - super(target); - this.targetOpponent.putAll(target.targetOpponent); - } - - @Override - public boolean canTarget(UUID controllerId, UUID objectId, Ability source, Game game) { - Permanent targetObject = game.getPermanent(objectId); - if (targetObject == null || !game.getOpponents(source.getControllerId()).contains(targetObject.getControllerId())) { - return false; - } - // If a permanent changes controller after being targeted but before this spell resolves, you won't gain control of that permanent. - if (targetOpponent.containsKey(objectId)) { - if (!targetOpponent.get(objectId).equals(targetObject.getControllerId())) { - return false; - } - } else { - // if already a target from this opponent exists, another can't be target - if (targetOpponent.values().contains(targetObject.getControllerId())) { - return false; - } - } - return super.canTarget(controllerId, objectId, source, game); - } - - @Override - public Set possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) { - Set opponents = new HashSet<>(); - for (UUID targetId : getTargets()) { - Permanent oldTargets = game.getPermanent(targetId); - if (oldTargets != null) { - opponents.add(oldTargets.getControllerId()); - } - } - Set possibleTargets = new HashSet<>(); - MageObject mageObject = game.getObject(sourceId); - if (mageObject == null) { - return possibleTargets; - } - for (UUID opponentId : game.getOpponents(sourceControllerId)) { - if (opponents.contains(opponentId)) { - // Target for this opponent already selected - continue; - } - for (Permanent permanent : game.getBattlefield().getAllActivePermanents(opponentId)) { - if (permanent.canBeTargetedBy(mageObject, sourceControllerId, game)) { - possibleTargets.add(permanent.getId()); - } - } - } - return possibleTargets; - } - - @Override - public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) { - for (UUID opponentId : game.getOpponents(sourceControllerId)) { - boolean targetAvailable = false; - for (Permanent permanent : game.getBattlefield().getAllActivePermanents(opponentId)) { - if (!targets.containsKey(permanent.getId())) { - MageObject mageObject = game.getObject(sourceId); - if (mageObject != null && permanent.canBeTargetedBy(mageObject, sourceControllerId, game)) { - targetAvailable = true; - break; - } - - } else { - targetAvailable = true; - break; - } - } - if (!targetAvailable) { - return false; + for (Target target : source.getTargets()) { + if (target.getFirstTarget() != null) { + ContinuousEffect effect = new GainControlTargetEffect(Duration.EndOfGame); + effect.setTargetPointer(new FixedTarget(target.getFirstTarget())); + game.addEffect(effect, source); } } return true; } - - @Override - public void addTarget(UUID objectId, int amount, Ability source, Game game, boolean skipEvent) { - Permanent targetObject = game.getPermanent(objectId); - if (targetObject != null) { - targetOpponent.put(objectId, targetObject.getControllerId()); - } - super.addTarget(objectId, amount, source, game, skipEvent); - } - - @Override - public void remove(UUID id) { - super.remove(id); - targetOpponent.remove(id); - } - - @Override - public BlatantThieveryTarget copy() { - return new BlatantThieveryTarget(this); - } } diff --git a/Mage.Sets/src/mage/cards/c/CapitalOffense.java b/Mage.Sets/src/mage/cards/c/CapitalOffense.java index 07bc016c939..d6522a87965 100644 --- a/Mage.Sets/src/mage/cards/c/CapitalOffense.java +++ b/Mage.Sets/src/mage/cards/c/CapitalOffense.java @@ -27,16 +27,19 @@ */ package mage.cards.c; +import java.util.List; import java.util.UUID; import mage.abilities.Ability; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.effects.Effect; import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.cards.repository.CardInfo; import mage.constants.CardType; +import mage.cards.repository.CardRepository; import mage.constants.Duration; -import static mage.filter.predicate.permanent.ControllerControlsIslandPredicate.filter; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.common.TargetCreaturePermanent; @@ -78,18 +81,25 @@ class NumberOfCapitalsInTextOfTargetCreatureCount implements DynamicValue { Permanent permanent = game.getPermanent(sourceAbility.getTargets().get(0).getFirstTarget()); if (permanent != null) { int capitals = 0; - for (String line : permanent.getRules()) { - line = line.replaceAll("(?i)", ""); // Ignoring reminder text in italic - line = line.replaceAll("\\{this\\}", permanent.getName()); - capitals += line.length() - line.replaceAll("[A-Z]", "").length(); + List cards = CardRepository.instance.findCards(permanent.getName()); + + if (cards != null) { + for (CardInfo cardInfo : cards) { + Card dummy = cardInfo != null ? cardInfo.getCard() : null; + for (String line : dummy.getRules()) { + line = line.replaceAll("(?i)", ""); // Ignoring reminder text in italic + line = line.replaceAll("\\{this\\}", permanent.getName()); + capitals += line.length() - line.replaceAll("[A-Z]", "").length(); + } + return -1 * capitals; + } } - return -1 * capitals; } return 0; } @Override public String getMessage() { - return filter.getMessage() + " that player controls"; + return "target creature gets -x/-x until end of turn, where x is the number of times a capital letter appears in its rules text. (ignore reminder text and flavor text.)"; } } diff --git a/Mage.Sets/src/mage/cards/c/CaptainsHook.java b/Mage.Sets/src/mage/cards/c/CaptainsHook.java new file mode 100644 index 00000000000..20df6b3c6cf --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/CaptainsHook.java @@ -0,0 +1,90 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.c; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.common.UnattachedTriggeredAbility; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.DestroyEquippedEffect; +import mage.abilities.effects.common.continuous.AddCardSubtypeAttachedEffect; +import mage.abilities.effects.common.continuous.BoostEquippedEffect; +import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; +import mage.abilities.keyword.EquipAbility; +import mage.abilities.keyword.MenaceAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.AttachmentType; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.Zone; + +/** + * + * @author LevelX2 + */ +public class CaptainsHook extends CardImpl { + + public CaptainsHook(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); + + this.subtype.add(SubType.EQUIPMENT); + + // Equipped creature gets +2/+0 + Effect effect = new BoostEquippedEffect(2, 0); + effect.setText("Equipped creature gets +2/+0"); + Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, effect); + // has menace, + effect = new GainAbilityAttachedEffect(new MenaceAbility(), AttachmentType.EQUIPMENT); + effect.setText(", has menace"); + ability.addEffect(effect); + //, and is a Pirate in addition to its other creature types + effect = new AddCardSubtypeAttachedEffect(SubType.PIRATE, Duration.WhileOnBattlefield, AttachmentType.EQUIPMENT); + effect.setText(", and is a Pirate in addition to its other creature types"); + ability.addEffect(effect); + this.addAbility(ability); + // Whenever Captain's Hook becomes unattached from a permanent, destroy that permanent. + this.addAbility(new UnattachedTriggeredAbility(new DestroyEquippedEffect(), false)); + + // Equip {1} + this.addAbility(new EquipAbility(Outcome.BoostCreature, new GenericManaCost(1))); + } + + public CaptainsHook(final CaptainsHook card) { + super(card); + } + + @Override + public CaptainsHook copy() { + return new CaptainsHook(this); + } +} diff --git a/Mage.Sets/src/mage/cards/c/ChannelHarm.java b/Mage.Sets/src/mage/cards/c/ChannelHarm.java index df072718ee6..9123edb2340 100644 --- a/Mage.Sets/src/mage/cards/c/ChannelHarm.java +++ b/Mage.Sets/src/mage/cards/c/ChannelHarm.java @@ -41,6 +41,7 @@ import mage.game.Controllable; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; +import mage.players.Player; import mage.target.common.TargetCreaturePermanent; /** @@ -90,11 +91,14 @@ class ChannelHarmEffect extends PreventionEffectImpl { @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { + Player sourceController = game.getPlayer(source.getControllerId()); PreventionEffectData preventionData = preventDamageAction(event, source, game); if (preventionData.getPreventedDamage() > 0) { Permanent targetCreature = game.getPermanent(source.getFirstTarget()); if (targetCreature != null) { - targetCreature.damage(preventionData.getPreventedDamage(), source.getSourceId(), game, false, true); + if (sourceController != null && sourceController.chooseUse(outcome, "Would you like to have " + preventionData.getPreventedDamage() + " damage dealt to " + targetCreature.getLogName() + "?", source, game)) { + targetCreature.damage(preventionData.getPreventedDamage(), source.getSourceId(), game, false, true); + } } } return true; diff --git a/Mage.Sets/src/mage/cards/l/LastRites.java b/Mage.Sets/src/mage/cards/l/LastRites.java new file mode 100644 index 00000000000..151775f5e1a --- /dev/null +++ b/Mage.Sets/src/mage/cards/l/LastRites.java @@ -0,0 +1,125 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.l; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.discard.DiscardCardYouChooseTargetEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.cards.Cards; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.TargetController; +import mage.filter.FilterCard; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.game.Game; +import mage.players.Player; +import mage.target.TargetCard; +import mage.target.TargetPlayer; +import mage.target.common.TargetCardInHand; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author L_J + */ +public class LastRites extends CardImpl { + + public LastRites(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{2}{B}"); + + // Discard any number of cards. Target player reveals his or her hand, then you choose a nonland card from it for each card discarded this way. That player discards those cards. + this.getSpellAbility().addEffect(new LastRitesEffect()); + this.getSpellAbility().addTarget(new TargetPlayer()); + + } + + public LastRites(final LastRites card) { + super(card); + } + + @Override + public LastRites copy() { + return new LastRites(this); + } +} + +class LastRitesEffect extends OneShotEffect { + + LastRitesEffect() { + super(Outcome.Discard); + this.staticText = "Discard any number of cards. Target player reveals his or her hand, then you choose a nonland card from it for each card discarded this way. That player discards those cards"; + } + + LastRitesEffect(final LastRitesEffect effect) { + super(effect); + } + + @Override + public LastRitesEffect copy() { + return new LastRitesEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Player targetPlayer = game.getPlayer(this.getTargetPointer().getFirst(game, source)); + if (controller != null && targetPlayer != null) { + Cards cardsInHand = controller.getHand().copy(); + TargetCard target = new TargetCardInHand(0, cardsInHand.size(), new FilterCard("cards to discard")); + controller.chooseTarget(outcome, cardsInHand, target, source, game); + int discardCount = target.getTargets().size(); + if (discardCount > 0) { + for (UUID cardId : target.getTargets()) { + Card card = game.getCard(cardId); + if (card != null) { + controller.discard(card, source, game); + } + } + if (targetPlayer != null) { + FilterCard filter = new FilterCard((discardCount > 1 ? "" : "a") + " nonland card" + (discardCount > 1 ? "s" : "")); + filter.add(Predicates.not(new CardTypePredicate(CardType.LAND))); + StaticValue discardValue = new StaticValue(discardCount); + Effect effect = new DiscardCardYouChooseTargetEffect(discardValue, filter, TargetController.ANY); + effect.setTargetPointer(new FixedTarget(targetPlayer.getId())); + effect.apply(game, source); + } else { + return false; + } + } + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/m/MoxDiamond.java b/Mage.Sets/src/mage/cards/m/MoxDiamond.java index 8049ee94235..adc3c8950ce 100644 --- a/Mage.Sets/src/mage/cards/m/MoxDiamond.java +++ b/Mage.Sets/src/mage/cards/m/MoxDiamond.java @@ -34,7 +34,6 @@ import mage.abilities.costs.Cost; import mage.abilities.costs.common.DiscardTargetCost; import mage.abilities.effects.ReplacementEffectImpl; import mage.abilities.mana.AnyColorManaAbility; -import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -44,7 +43,7 @@ import mage.constants.Zone; import mage.filter.common.FilterLandCard; import mage.game.Game; import mage.game.events.GameEvent; -import mage.game.events.ZoneChangeEvent; +import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.TargetCardInHand; @@ -55,7 +54,7 @@ import mage.target.common.TargetCardInHand; public class MoxDiamond extends CardImpl { public MoxDiamond(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{0}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{0}"); // If Mox Diamond would enter the battlefield, you may discard a land card instead. If you do, put Mox Diamond onto the battlefield. If you don't, put it into its owner's graveyard. this.addAbility(new SimpleStaticAbility(Zone.ALL, new MoxDiamondReplacementEffect())); @@ -95,43 +94,36 @@ class MoxDiamondReplacementEffect extends ReplacementEffectImpl { } @Override - public boolean replaceEvent(GameEvent event, Ability source, Game game) { - Player player = game.getPlayer(source.getControllerId()); - if (player != null){ + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + Player player = game.getPlayer(source.getControllerId()); + if (player != null) { TargetCardInHand target = new TargetCardInHand(new FilterLandCard()); Cost cost = new DiscardTargetCost(target); - if (cost.canPay(source, source.getSourceId(), source.getControllerId(), game) && - player.chooseUse(outcome, "Discard land? (Otherwise Mox Diamond goes to graveyard)", source, game) && - player.chooseTarget(Outcome.Discard, target, source, game)){ + if (cost.canPay(source, source.getSourceId(), source.getControllerId(), game) + && player.chooseUse(outcome, "Discard land? (Otherwise Mox Diamond goes to graveyard)", source, game) + && player.chooseTarget(Outcome.Discard, target, source, game)) { player.discard(game.getCard(target.getFirstTarget()), source, game); return false; - } - else{ - Card card = game.getCard(event.getTargetId()); - if (card != null) { - player.moveCards(card, Zone.GRAVEYARD, source, game); + } else { + Permanent permanent = game.getPermanent(event.getTargetId()); + if (permanent != null) { + player.moveCards(permanent, Zone.GRAVEYARD, source, game); } return true; } - + } return false; } @Override public boolean checksEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.ZONE_CHANGE; + return event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD; } @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (source.getSourceId().equals(event.getTargetId())) { - ZoneChangeEvent zEvent = (ZoneChangeEvent) event; - if(zEvent.getToZone() == Zone.BATTLEFIELD){ - return true; - } - } - return false; + return source.getSourceId().equals(event.getTargetId()); } } diff --git a/Mage.Sets/src/mage/cards/o/OddlyUneven.java b/Mage.Sets/src/mage/cards/o/OddlyUneven.java index 55efccd531b..62ca1babcb5 100644 --- a/Mage.Sets/src/mage/cards/o/OddlyUneven.java +++ b/Mage.Sets/src/mage/cards/o/OddlyUneven.java @@ -96,10 +96,15 @@ class OddOrEvenEffect extends OneShotEffect { // Check the number of words in the name (based on number of spaces) if (creature != null) { String name = creature.getName(); - int spaces = name.length() - name.replace(" ", "").length(); - boolean nameIsOdd = (spaces % 2 == 0); - if (this.odd && nameIsOdd || !this.odd && !nameIsOdd) { + + if (name.equalsIgnoreCase("") && this.odd == false) { creature.destroy(source.getSourceId(), game, false); + } else { + int spaces = name.length() - name.replace(" ", "").length(); + boolean nameIsOdd = (spaces % 2 == 0); + if (this.odd && nameIsOdd || !this.odd && !nameIsOdd) { + creature.destroy(source.getSourceId(), game, false); + } } } } diff --git a/Mage.Sets/src/mage/cards/s/SpiritualFocus.java b/Mage.Sets/src/mage/cards/s/SpiritualFocus.java new file mode 100644 index 00000000000..5e14d68ba20 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SpiritualFocus.java @@ -0,0 +1,140 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.s; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.GainLifeEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; +import mage.game.permanent.Permanent; +import mage.game.stack.StackObject; +import mage.players.Player; + +/** + * + * @author L_J + */ +public class SpiritualFocus extends CardImpl { + + public SpiritualFocus(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}"); + + // Whenever a spell or ability an opponent controls causes you to discard a card, you gain 2 life and you may draw a card. + this.addAbility(new SpiritualFocusTriggeredAbility()); + } + + public SpiritualFocus(final SpiritualFocus card) { + super(card); + } + + @Override + public SpiritualFocus copy() { + return new SpiritualFocus(this); + } +} + +class SpiritualFocusTriggeredAbility extends TriggeredAbilityImpl { + + public SpiritualFocusTriggeredAbility() { + super(Zone.BATTLEFIELD, new GainLifeEffect(2), false); + this.addEffect(new SpiritualFocusDrawCardEffect()); + } + + public SpiritualFocusTriggeredAbility(final SpiritualFocusTriggeredAbility ability) { + super(ability); + } + + @Override + public SpiritualFocusTriggeredAbility copy() { + return new SpiritualFocusTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == EventType.DISCARDED_CARD; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + StackObject stackObject = game.getStack().getStackObject(event.getSourceId()); + if (stackObject != null) { + if (game.getOpponents(this.getControllerId()).contains(stackObject.getControllerId())) { + Permanent permanent = game.getPermanent(getSourceId()); + if (permanent != null) { + if (permanent.getControllerId() == event.getPlayerId()) { + return true; + } + } + } + } + return false; + } + + @Override + public String getRule() { + return "Whenever a spell or ability an opponent controls causes you to discard a card, you gain 2 life and you may draw a card."; + } +} + +class SpiritualFocusDrawCardEffect extends OneShotEffect { + + public SpiritualFocusDrawCardEffect() { + super(Outcome.DrawCard); + } + + public SpiritualFocusDrawCardEffect(final SpiritualFocusDrawCardEffect effect) { + super(effect); + } + + @Override + public SpiritualFocusDrawCardEffect copy() { + return new SpiritualFocusDrawCardEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(source.getSourceId()); + Player player = game.getPlayer(source.getControllerId()); + if (player != null && permanent != null) { + if (player.chooseUse(outcome, "Draw a card (" + permanent.getLogName() + ')', source, game)) { + player.drawCards(1, game); + } + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/s/SwabGoblin.java b/Mage.Sets/src/mage/cards/s/SwabGoblin.java new file mode 100644 index 00000000000..69705ad8f5f --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SwabGoblin.java @@ -0,0 +1,60 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.s; + +import java.util.UUID; +import mage.MageInt; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +/** + * + * @author LevelX2 + */ +public class SwabGoblin extends CardImpl { + + public SwabGoblin(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}"); + + this.subtype.add(SubType.GOBLIN); + this.subtype.add(SubType.PIRATE); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + } + + public SwabGoblin(final SwabGoblin card) { + super(card); + } + + @Override + public SwabGoblin copy() { + return new SwabGoblin(this); + } +} diff --git a/Mage.Sets/src/mage/cards/t/TetzimocPrimalDeath.java b/Mage.Sets/src/mage/cards/t/TetzimocPrimalDeath.java new file mode 100644 index 00000000000..751f6f6b3aa --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TetzimocPrimalDeath.java @@ -0,0 +1,99 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.t; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.ActivateIfConditionActivatedAbility; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.condition.common.MyTurnCondition; +import mage.abilities.costs.common.RevealSourceFromYourHandCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.DestroyAllEffect; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.abilities.keyword.DeathtouchAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.filter.predicate.permanent.CounterPredicate; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LevelX2 + */ +public class TetzimocPrimalDeath extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature your opponents control with a prey counter on it"); + + static { + filter.add(new ControllerPredicate(TargetController.OPPONENT)); + filter.add(new CounterPredicate(CounterType.PREY)); + } + + public TetzimocPrimalDeath(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{B}{B}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.ELDER); + this.subtype.add(SubType.DINOSAUR); + this.power = new MageInt(6); + this.toughness = new MageInt(6); + + // Deathtouch + this.addAbility(DeathtouchAbility.getInstance()); + + // {B}, Reveal Tetzimoc, Primal Death from your hand: Put a prey counter on target creature. Activate this ability only during your turn. + Ability ability = new ActivateIfConditionActivatedAbility(Zone.HAND, new AddCountersTargetEffect(CounterType.PREY.createInstance()), new ManaCostsImpl("{B}"), MyTurnCondition.instance); + ability.addTarget(new TargetCreaturePermanent()); + ability.addCost(new RevealSourceFromYourHandCost()); + this.addAbility(ability); + + // When Tetzimoc, Primal Death enters the battlefield, destroy each creature your opponents control with a prey counter on it. + this.addAbility(new EntersBattlefieldTriggeredAbility( + new DestroyAllEffect(filter).setText("destroy each creature your opponents control with a prey counter on it"), false)); + + } + + public TetzimocPrimalDeath(final TetzimocPrimalDeath card) { + super(card); + } + + @Override + public TetzimocPrimalDeath copy() { + return new TetzimocPrimalDeath(this); + } +} diff --git a/Mage.Sets/src/mage/cards/t/TheBigIdea.java b/Mage.Sets/src/mage/cards/t/TheBigIdea.java new file mode 100644 index 00000000000..96a9f59f6f1 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TheBigIdea.java @@ -0,0 +1,179 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.t; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.common.TapTargetCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.constants.Zone; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.permanent.TappedPredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.game.permanent.token.BrainiacToken; +import mage.players.Player; +import mage.target.common.TargetControlledCreaturePermanent; + +/** + * + * @author spjspj + */ +public class TheBigIdea extends CardImpl { + + private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(SubType.BRAINIAC, "Brainiac creatures"); + + static { + filter.add(Predicates.not(new TappedPredicate())); + } + + public TheBigIdea(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{R}{R}"); + + addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.BRAINIAC); + this.subtype.add(SubType.VILLAIN); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // 2{BR}{BR}, T: Roll a six-sided dice. Create a number of 1/1 red Brainiac creature tokens equal to the result. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TheBigIdeaEffect(), new ManaCostsImpl("{2}{B/R}{B/R}")); + ability.addCost(new TapSourceCost()); + this.addAbility(ability); + + // Tap three untapped Brainiacs you control: The next time you would roll a six-sided die, instead roll two six-sided dice and use the total of those results. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new TheBigIdeaReplacementEffect(), new TapTargetCost(new TargetControlledCreaturePermanent(3, 3, filter, true)))); + } + + public TheBigIdea(final TheBigIdea card) { + super(card); + } + + @Override + public TheBigIdea copy() { + return new TheBigIdea(this); + } +} + +class TheBigIdeaReplacementEffect extends ReplacementEffectImpl { + + TheBigIdeaReplacementEffect() { + super(Duration.EndOfTurn, Outcome.Damage); + staticText = "The next time you would roll a six-sided die, instead roll two six-sided dice and use the total of those results"; + } + + TheBigIdeaReplacementEffect(final TheBigIdeaReplacementEffect effect) { + super(effect); + } + + @Override + public TheBigIdeaReplacementEffect copy() { + return new TheBigIdeaReplacementEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + Player controller = game.getPlayer(source.getControllerId()); + if (event.getData() != null) { + String data = event.getData(); + int numSides = Integer.parseInt(data); + if (numSides != 6) { + return false; + } + } + + if (controller != null) { + discard(); + int amount = controller.rollDice(game, 6); + event.setAmount(event.getAmount() + amount); + return true; + } + return false; + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.ROLL_DICE; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (!this.used) { + return source.getControllerId().equals(event.getPlayerId()); + } + return false; + } +} + +class TheBigIdeaEffect extends OneShotEffect { + + public TheBigIdeaEffect() { + super(Outcome.PutCreatureInPlay); + this.staticText = "Roll a six-sided dice. Create a number of 1/1 red Brainiac creature tokens equal to the result"; + } + + public TheBigIdeaEffect(final TheBigIdeaEffect effect) { + super(effect); + } + + @Override + public TheBigIdeaEffect copy() { + return new TheBigIdeaEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Permanent permanent = game.getPermanent(source.getSourceId()); + if (controller != null && permanent != null) { + int amount = controller.rollDice(game, 6); + return new CreateTokenEffect(new BrainiacToken(), amount).apply(game, source); + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/t/TheImmortalSun.java b/Mage.Sets/src/mage/cards/t/TheImmortalSun.java new file mode 100644 index 00000000000..96d723723e8 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TheImmortalSun.java @@ -0,0 +1,129 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.t; + +import java.util.Optional; +import java.util.UUID; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.LoyaltyAbility; +import mage.abilities.common.BeginningOfDrawTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.abilities.effects.common.cost.SpellsCostReductionControllerEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.SuperType; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; + +/** + * + * @author LevelX2 + */ +public class TheImmortalSun extends CardImpl { + + public TheImmortalSun(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{6}"); + + this.addSuperType(SuperType.LEGENDARY); + + // Players can't activate loyalty abilities of planeswalkers. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new TheImmortalSunCantActivateEffect())); + // At the beginning of your draw step, draw an additional card. + this.addAbility(new BeginningOfDrawTriggeredAbility(new DrawCardSourceControllerEffect(1), TargetController.YOU, false)); + // Spells you cast cost {1} less to cast. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpellsCostReductionControllerEffect(new FilterCard("Spells you cast"), 1))); + // Creatures you control get +1/+1. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostControlledEffect(1, 1, Duration.WhileOnBattlefield))); + } + + public TheImmortalSun(final TheImmortalSun card) { + super(card); + } + + @Override + public TheImmortalSun copy() { + return new TheImmortalSun(this); + } +} + +class TheImmortalSunCantActivateEffect extends ContinuousRuleModifyingEffectImpl { + + public TheImmortalSunCantActivateEffect() { + super(Duration.WhileOnBattlefield, Outcome.Detriment); + staticText = "Players can't activate loyalty abilities of planeswalkers"; + } + + public TheImmortalSunCantActivateEffect(final TheImmortalSunCantActivateEffect effect) { + super(effect); + } + + @Override + public TheImmortalSunCantActivateEffect copy() { + return new TheImmortalSunCantActivateEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public String getInfoMessage(Ability source, GameEvent event, Game game) { + MageObject mageObject = game.getObject(source.getSourceId()); + if (mageObject != null) { + return "You can't activate loyalty abilities of planeswalkers (" + mageObject.getIdName() + ")."; + } + return null; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (event.getType() == GameEvent.EventType.ACTIVATE_ABILITY) { + Permanent permanent = game.getPermanentOrLKIBattlefield(event.getSourceId()); + if (permanent == null) { + return false; + } + if (permanent.isPlaneswalker()) { + Optional ability = game.getAbility(event.getTargetId(), event.getSourceId()); + return ability.isPresent() && (ability.get() instanceof LoyaltyAbility); + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/t/TreacherousLink.java b/Mage.Sets/src/mage/cards/t/TreacherousLink.java new file mode 100644 index 00000000000..f5b7ed121f4 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TreacherousLink.java @@ -0,0 +1,133 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.t; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.DamageEvent; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author L_J + */ +public class TreacherousLink extends CardImpl { + + public TreacherousLink(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{B}"); + this.subtype.add(SubType.AURA); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.Detriment)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + + // All damage that would be dealt to enchanted creature is dealt to its controller instead. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new TreacherousLinkEffect())); + } + + public TreacherousLink(final TreacherousLink card) { + super(card); + } + + @Override + public TreacherousLink copy() { + return new TreacherousLink(this); + } +} + +class TreacherousLinkEffect extends ReplacementEffectImpl { + + public TreacherousLinkEffect() { + super(Duration.WhileOnBattlefield, Outcome.RedirectDamage); + staticText = "All damage that would be dealt to enchanted creature is dealt to its controller instead"; + } + + public TreacherousLinkEffect(final TreacherousLinkEffect effect) { + super(effect); + } + + @Override + public TreacherousLinkEffect copy() { + return new TreacherousLinkEffect(this); + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DAMAGE_CREATURE; + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + DamageEvent damageEvent = (DamageEvent) event; + Permanent enchantedCreature = game.getPermanentOrLKIBattlefield(damageEvent.getTargetId()); + Player controller = game.getPlayer(enchantedCreature.getControllerId()); + if (enchantedCreature != null && controller != null) { + controller.damage(damageEvent.getAmount(), damageEvent.getSourceId(), game, damageEvent.isCombatDamage(), damageEvent.isPreventable(), damageEvent.getAppliedEffects()); + return true; + } + return false; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + Permanent enchantment = game.getPermanentOrLKIBattlefield(source.getSourceId()); + Player controller = game.getPlayer(source.getControllerId()); + DamageEvent damageEvent = (DamageEvent) event; + if (controller != null && enchantment != null) { + Permanent enchantedCreature = game.getPermanentOrLKIBattlefield(enchantment.getAttachedTo()); + if (enchantedCreature != null) { + return enchantedCreature.getId() == damageEvent.getTargetId(); + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/v/VampireChampion.java b/Mage.Sets/src/mage/cards/v/VampireChampion.java new file mode 100644 index 00000000000..95bb4358c93 --- /dev/null +++ b/Mage.Sets/src/mage/cards/v/VampireChampion.java @@ -0,0 +1,65 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.v; + +import java.util.UUID; +import mage.MageInt; +import mage.constants.SubType; +import mage.abilities.keyword.DeathtouchAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +/** + * + * @author LevelX2 + */ +public class VampireChampion extends CardImpl { + + public VampireChampion(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}"); + + this.subtype.add(SubType.VAMPIRE); + this.subtype.add(SubType.SOLDIER); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Deathtouch + this.addAbility(DeathtouchAbility.getInstance()); + + } + + public VampireChampion(final VampireChampion card) { + super(card); + } + + @Override + public VampireChampion copy() { + return new VampireChampion(this); + } +} diff --git a/Mage.Sets/src/mage/cards/v/VeryCrypticCommand.java b/Mage.Sets/src/mage/cards/v/VeryCrypticCommand.java new file mode 100644 index 00000000000..d922d4f7a4d --- /dev/null +++ b/Mage.Sets/src/mage/cards/v/VeryCrypticCommand.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.cards.v; + +import java.util.UUID; +import mage.MageObjectReference; +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ChooseNewTargetsTargetEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.ReturnToHandTargetEffect; +import mage.abilities.effects.common.continuous.BecomesFaceDownCreatureEffect; +import mage.abilities.effects.common.continuous.BecomesFaceDownCreatureEffect.FaceDownType; +import mage.abilities.effects.common.discard.DiscardControllerEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.filter.FilterStackObject; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.NumberOfTargetsPredicate; +import mage.filter.predicate.permanent.TokenPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; +import mage.target.TargetStackObject; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author spjspj + */ +public class VeryCrypticCommand extends CardImpl { + + private static final FilterStackObject filter = new FilterStackObject("spell or ability with a single target"); + private static final FilterCreaturePermanent filter2 = new FilterCreaturePermanent("nontoken creature"); + + static { + filter.add(new NumberOfTargetsPredicate(1)); + filter2.add(Predicates.not(new TokenPredicate())); + } + + public VeryCrypticCommand(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}{U}{U}"); + + // Choose two - + this.getSpellAbility().getModes().setMinModes(2); + this.getSpellAbility().getModes().setMaxModes(2); + + // Return target permanent to its controller�s hand. + this.getSpellAbility().addEffect(new ReturnToHandTargetEffect()); + this.getSpellAbility().addTarget(new TargetPermanent()); + + // Draw two cards, then discard a card. + Mode mode = new Mode(); + mode.getEffects().add(new DrawCardSourceControllerEffect(2)); + Effect effect = new DiscardControllerEffect(1); + effect.setText(", then discard a card"); + mode.getEffects().add(effect); + this.getSpellAbility().getModes().addMode(mode); + + // Change the target of target spell with a single target. + mode = new Mode(); + mode.getEffects().add(new ChooseNewTargetsTargetEffect(true, true)); + mode.getTargets().add(new TargetStackObject(filter)); + this.getSpellAbility().getModes().addMode(mode); + + // Turn over target nontoken creature. + mode = new Mode(); + mode.getEffects().add(new TurnOverEffect()); + mode.getTargets().add(new TargetCreaturePermanent(filter2)); + this.getSpellAbility().getModes().addMode(mode); + } + + public VeryCrypticCommand(final VeryCrypticCommand card) { + super(card); + } + + @Override + public VeryCrypticCommand copy() { + return new VeryCrypticCommand(this); + } +} + +class TurnOverEffect extends OneShotEffect { + + TurnOverEffect() { + super(Outcome.Benefit); + this.staticText = "Turn over target nontoken creature"; + } + + TurnOverEffect(final TurnOverEffect effect) { + super(effect); + } + + @Override + public TurnOverEffect copy() { + return new TurnOverEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent creature = game.getPermanent(source.getFirstTarget()); + if (creature != null) { + if (creature.isFaceDown(game)) { + creature.turnFaceUp(game, source.getControllerId()); + } else { + creature.turnFaceDown(game, source.getControllerId()); + MageObjectReference objectReference = new MageObjectReference(creature.getId(), creature.getZoneChangeCounter(game), game); + game.addEffect(new BecomesFaceDownCreatureEffect(null, objectReference, Duration.Custom, FaceDownType.MANUAL), source); + } + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/v/VraskaSchemingGorgon.java b/Mage.Sets/src/mage/cards/v/VraskaSchemingGorgon.java new file mode 100644 index 00000000000..fc7abafc50d --- /dev/null +++ b/Mage.Sets/src/mage/cards/v/VraskaSchemingGorgon.java @@ -0,0 +1,90 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.v; + +import java.util.UUID; +import mage.abilities.LoyaltyAbility; +import mage.abilities.TriggeredAbility; +import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; +import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.effects.common.LoseGameTargetPlayerEffect; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.abilities.keyword.DeathtouchAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.filter.StaticFilters; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LevelX2 + */ +public class VraskaSchemingGorgon extends CardImpl { + + public VraskaSchemingGorgon(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{4}{B}{B}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.VRASKA); + this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(5)); + + // +2: Creatures you control get +1/+0 until end of turn. + Effect effect = new BoostControlledEffect(1, 0, Duration.EndOfTurn, StaticFilters.FILTER_PERMANENT_CREATURE); + effect.setText("Creatures you control get +1/+0"); + this.addAbility(new LoyaltyAbility(effect, 2)); + + // -3: Destroy target creature. + LoyaltyAbility loyaltyAbility = new LoyaltyAbility(new DestroyTargetEffect(), -3); + loyaltyAbility.addTarget(new TargetCreaturePermanent()); + this.addAbility(loyaltyAbility); + + // -10: Until end of turn, creatures you control gain deathtouch and "Whenever this creature deals damage to an opponent, that player loses the game." + loyaltyAbility = new LoyaltyAbility(new GainAbilityControlledEffect(DeathtouchAbility.getInstance(), Duration.EndOfTurn) + .setText("Until end of turn, creatures you control gain deathtouch"), -10); + TriggeredAbility triggeredAbility = new DealsCombatDamageToAPlayerTriggeredAbility(new LoseGameTargetPlayerEffect(), false, true, true); + loyaltyAbility.addEffect(new GainAbilityControlledEffect(triggeredAbility, Duration.EndOfTurn) + .setText("and \"Whenever this creature deals damage to an opponent, that player loses the game.\"")); + this.addAbility(loyaltyAbility); + } + + public VraskaSchemingGorgon(final VraskaSchemingGorgon card) { + super(card); + } + + @Override + public VraskaSchemingGorgon copy() { + return new VraskaSchemingGorgon(this); + } +} diff --git a/Mage.Sets/src/mage/cards/v/VraskasConquistador.java b/Mage.Sets/src/mage/cards/v/VraskasConquistador.java new file mode 100644 index 00000000000..95c9dbc2c12 --- /dev/null +++ b/Mage.Sets/src/mage/cards/v/VraskasConquistador.java @@ -0,0 +1,85 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.v; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.TriggeredAbility; +import mage.abilities.common.AttacksOrBlocksTriggeredAbility; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.effects.common.LoseLifeTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.target.common.TargetOpponent; + +/** + * + * @author LevelX2 + */ +public class VraskasConquistador extends CardImpl { + + private static final FilterControlledPermanent filter = new FilterControlledPermanent(); + + static { + filter.add(new CardTypePredicate(CardType.PLANESWALKER)); + filter.add(new SubtypePredicate(SubType.VRASKA)); + } + + public VraskasConquistador(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}"); + + this.subtype.add(SubType.VAMPIRE); + this.subtype.add(SubType.SOLDIER); + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + // Whenever Vraska's Conquistador attacks or blocks, if you control a Vraska planeswalker, target opponent loses 2 life and you gain 2 life. + TriggeredAbility ability = new AttacksOrBlocksTriggeredAbility(new LoseLifeTargetEffect(2), false); + ability.addEffect(new GainLifeEffect(2).setText("and you gain 2 life")); + ability.addTarget(new TargetOpponent()); + this.addAbility(new ConditionalTriggeredAbility( + ability, new PermanentsOnTheBattlefieldCondition(filter), + "Whenever {this} attacks or blocks, if you control a Vraska planeswalker, target opponent loses 2 life and you gain 2 life.")); + } + + public VraskasConquistador(final VraskasConquistador card) { + super(card); + } + + @Override + public VraskasConquistador copy() { + return new VraskasConquistador(this); + } +} diff --git a/Mage.Sets/src/mage/cards/v/VraskasScorn.java b/Mage.Sets/src/mage/cards/v/VraskasScorn.java new file mode 100644 index 00000000000..b99ce79d7fe --- /dev/null +++ b/Mage.Sets/src/mage/cards/v/VraskasScorn.java @@ -0,0 +1,72 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.v; + +import java.util.UUID; +import mage.abilities.effects.common.LoseLifeTargetEffect; +import mage.abilities.effects.common.search.SearchLibraryGraveyardPutInHandEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.filter.FilterCard; +import mage.filter.predicate.mageobject.NamePredicate; +import mage.target.common.TargetOpponent; + +/** + * + * @author LevelX2 + */ +public class VraskasScorn extends CardImpl { + + private final static FilterCard filter = new FilterCard("Vraska, Scheming Gorgon"); + + static { + filter.add(new NamePredicate(filter.getMessage())); + } + + public VraskasScorn(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{B}{B}"); + + // Target opponent loses 4 life. + this.getSpellAbility().addEffect(new LoseLifeTargetEffect(4)); + this.getSpellAbility().addTarget(new TargetOpponent()); + + // You may search your library and/or graveyard for a card named Vraska, Scheming Gorgon, reveal it, and put it into your hand. If you search your library this way, shuffle it. + this.getSpellAbility().addEffect(new SearchLibraryGraveyardPutInHandEffect(filter) + .setText("You may search your library and/or graveyard for a card named Vraska, Scheming Gorgon, reveal it, and put it into your hand. If you search your library this way, shuffle it")); + } + + public VraskasScorn(final VraskasScorn card) { + super(card); + } + + @Override + public VraskasScorn copy() { + return new VraskasScorn(this); + } +} diff --git a/Mage.Sets/src/mage/cards/w/WalkingSponge.java b/Mage.Sets/src/mage/cards/w/WalkingSponge.java new file mode 100644 index 00000000000..0bc3b9fbbad --- /dev/null +++ b/Mage.Sets/src/mage/cards/w/WalkingSponge.java @@ -0,0 +1,134 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.w; + +import java.util.LinkedHashSet; +import java.util.Set; +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.LoseAbilityTargetEffect; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.choices.ChoiceImpl; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author L_J + */ +public class WalkingSponge extends CardImpl { + + public WalkingSponge(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{U}"); + this.subtype.add(SubType.SPONGE); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // {T}: Target creature loses your choice of flying, first strike, or trample until end of turn. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new WalkingSpongeEffect(), new TapSourceCost()); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + public WalkingSponge(final WalkingSponge card) { + super(card); + } + + @Override + public WalkingSponge copy() { + return new WalkingSponge(this); + } +} + +class WalkingSpongeEffect extends OneShotEffect { + + WalkingSpongeEffect() { + super(Outcome.Benefit); + this.staticText = "Target creature loses your choice of flying, first strike, or trample until end of turn"; + } + + WalkingSpongeEffect(final WalkingSpongeEffect effect) { + super(effect); + } + + @Override + public WalkingSpongeEffect copy() { + return new WalkingSpongeEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + Permanent permanent = game.getPermanent(source.getSourceId()); + if (player != null || permanent != null) { + ChoiceImpl chooseAbility = new ChoiceImpl(); + chooseAbility.setMessage("What ability do you wish to remove? (default is Flying)"); + Set choice = new LinkedHashSet<>(); + choice.add("Flying"); + choice.add("First strike"); + choice.add("Trample"); + chooseAbility.setChoices(choice); + // since the player can't pick "no ability", let's default to the first option + Ability ability = FlyingAbility.getInstance(); + + if (player.choose(Outcome.UnboostCreature, chooseAbility, game)) { + String chosenAbility = chooseAbility.getChoice(); + // if (chosenAbility.equals("Flying")) { + // ability = FlyingAbility.getInstance(); + // } + if (chosenAbility.equals("First strike")) { + ability = FirstStrikeAbility.getInstance(); + } + else if (chosenAbility.equals("Trample")) { + ability = TrampleAbility.getInstance(); + } + } + game.informPlayers(player.getLogName() + " has chosen " + ability.getRule()); + ContinuousEffect effect = new LoseAbilityTargetEffect(ability, Duration.EndOfTurn); + game.addEffect(effect, source); + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/MercadianMasques.java b/Mage.Sets/src/mage/sets/MercadianMasques.java index 92bb4bc0ab8..df71e3b1794 100644 --- a/Mage.Sets/src/mage/sets/MercadianMasques.java +++ b/Mage.Sets/src/mage/sets/MercadianMasques.java @@ -311,6 +311,7 @@ public class MercadianMasques extends ExpansionSet { cards.add(new SetCardInfo("Soul Channeling", 163, Rarity.COMMON, mage.cards.s.SoulChanneling.class)); cards.add(new SetCardInfo("Specter's Wail", 164, Rarity.COMMON, mage.cards.s.SpectersWail.class)); cards.add(new SetCardInfo("Spidersilk Armor", 273, Rarity.COMMON, mage.cards.s.SpidersilkArmor.class)); + cards.add(new SetCardInfo("Spiritual Focus", 49, Rarity.RARE, mage.cards.s.SpiritualFocus.class)); cards.add(new SetCardInfo("Spontaneous Generation", 274, Rarity.RARE, mage.cards.s.SpontaneousGeneration.class)); cards.add(new SetCardInfo("Squall", 275, Rarity.COMMON, mage.cards.s.Squall.class)); cards.add(new SetCardInfo("Squallmonger", 276, Rarity.UNCOMMON, mage.cards.s.Squallmonger.class)); diff --git a/Mage.Sets/src/mage/sets/Odyssey.java b/Mage.Sets/src/mage/sets/Odyssey.java index 7900768d2b5..5644b9dbd01 100644 --- a/Mage.Sets/src/mage/sets/Odyssey.java +++ b/Mage.Sets/src/mage/sets/Odyssey.java @@ -206,6 +206,7 @@ public class Odyssey extends ExpansionSet { cards.add(new SetCardInfo("Krosan Avenger", 247, Rarity.COMMON, mage.cards.k.KrosanAvenger.class)); cards.add(new SetCardInfo("Krosan Beast", 248, Rarity.RARE, mage.cards.k.KrosanBeast.class)); cards.add(new SetCardInfo("Laquatus's Creativity", 88, Rarity.UNCOMMON, mage.cards.l.LaquatussCreativity.class)); + cards.add(new SetCardInfo("Last Rites", 146, Rarity.COMMON, mage.cards.l.LastRites.class)); cards.add(new SetCardInfo("Lava Blister", 200, Rarity.UNCOMMON, mage.cards.l.LavaBlister.class)); cards.add(new SetCardInfo("Leaf Dancer", 249, Rarity.COMMON, mage.cards.l.LeafDancer.class)); cards.add(new SetCardInfo("Lieutenant Kirtar", 29, Rarity.RARE, mage.cards.l.LieutenantKirtar.class)); diff --git a/Mage.Sets/src/mage/sets/PDSGraveborn.java b/Mage.Sets/src/mage/sets/PDSGraveborn.java index 91192951d84..77e28025420 100644 --- a/Mage.Sets/src/mage/sets/PDSGraveborn.java +++ b/Mage.Sets/src/mage/sets/PDSGraveborn.java @@ -62,6 +62,7 @@ public class PDSGraveborn extends ExpansionSet { cards.add(new SetCardInfo("Faceless Butcher", 3, Rarity.COMMON, mage.cards.f.FacelessButcher.class)); cards.add(new SetCardInfo("Hidden Horror", 2, Rarity.UNCOMMON, mage.cards.h.HiddenHorror.class)); cards.add(new SetCardInfo("Inkwell Leviathan", 10, Rarity.RARE, mage.cards.i.InkwellLeviathan.class)); + cards.add(new SetCardInfo("Last Rites", 21, Rarity.COMMON, mage.cards.l.LastRites.class)); cards.add(new SetCardInfo("Polluted Mire", 26, Rarity.COMMON, mage.cards.p.PollutedMire.class)); cards.add(new SetCardInfo("Putrid Imp", 1, Rarity.COMMON, mage.cards.p.PutridImp.class)); cards.add(new SetCardInfo("Reanimate", 15, Rarity.UNCOMMON, mage.cards.r.Reanimate.class)); diff --git a/Mage.Sets/src/mage/sets/RivalsOfIxalan.java b/Mage.Sets/src/mage/sets/RivalsOfIxalan.java index 13449dd3e68..710c3994e78 100644 --- a/Mage.Sets/src/mage/sets/RivalsOfIxalan.java +++ b/Mage.Sets/src/mage/sets/RivalsOfIxalan.java @@ -1,65 +1,78 @@ -/* -* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. -* -* Redistribution and use in source and binary forms, with or without modification, are -* permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this list of -* conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, this list -* of conditions and the following disclaimer in the documentation and/or other materials -* provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED -* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR -* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -* The views and conclusions contained in the software and documentation are those of the -* authors and should not be interpreted as representing official policies, either expressed -* or implied, of BetaSteward_at_googlemail.com. - */ -package mage.sets; - -import mage.cards.ExpansionSet; -import mage.constants.Rarity; -import mage.constants.SetType; - -/** - * - * @author fireshoes - */ -public class RivalsOfIxalan extends ExpansionSet { - - private static final RivalsOfIxalan instance = new RivalsOfIxalan(); - - public static RivalsOfIxalan getInstance() { - return instance; - } - - private RivalsOfIxalan() { - super("Rivals of Ixalan", "RIX", ExpansionSet.buildDate(2018, 1, 19), SetType.EXPANSION); - this.blockName = "Ixalan"; - this.parentSet = Ixalan.getInstance(); - this.hasBoosters = true; - this.hasBasicLands = false; - this.numBoosterLands = 1; - this.numBoosterCommon = 11; - this.numBoosterUncommon = 3; - this.numBoosterRare = 1; - this.ratioBoosterMythic = 8; - - cards.add(new SetCardInfo("Brass's Bounty", 94, Rarity.RARE, mage.cards.b.BrasssBounty.class)); - cards.add(new SetCardInfo("Ghalta, Primal Hunger", 130, Rarity.RARE, mage.cards.g.GhaltaPrimalHunger.class)); - cards.add(new SetCardInfo("Silvergill Adept", 53, Rarity.UNCOMMON, mage.cards.s.SilvergillAdept.class)); - cards.add(new SetCardInfo("Storm the Vault", 173, Rarity.RARE, mage.cards.s.StormTheVault.class)); - cards.add(new SetCardInfo("Vault of Catlacan", 173, Rarity.RARE, mage.cards.v.VaultOfCatlacan.class)); - cards.add(new SetCardInfo("Vona's Hunger", 90, Rarity.RARE, mage.cards.v.VonasHunger.class)); - } -} +/* +* 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; + +import mage.cards.ExpansionSet; +import mage.constants.Rarity; +import mage.constants.SetType; + +/** + * + * @author fireshoes + */ +public class RivalsOfIxalan extends ExpansionSet { + + private static final RivalsOfIxalan instance = new RivalsOfIxalan(); + + public static RivalsOfIxalan getInstance() { + return instance; + } + + private RivalsOfIxalan() { + super("Rivals of Ixalan", "RIX", ExpansionSet.buildDate(2018, 1, 19), SetType.EXPANSION); + this.blockName = "Ixalan"; + this.parentSet = Ixalan.getInstance(); + this.hasBoosters = true; + this.hasBasicLands = false; + this.numBoosterLands = 1; + this.numBoosterCommon = 11; + this.numBoosterUncommon = 3; + this.numBoosterRare = 1; + this.ratioBoosterMythic = 8; + + cards.add(new SetCardInfo("Angrath's Ambusher", 202, Rarity.UNCOMMON, mage.cards.a.AngrathsAmbusher.class)); + cards.add(new SetCardInfo("Angrath's Fury", 204, Rarity.RARE, mage.cards.a.AngrathsFury.class)); + cards.add(new SetCardInfo("Angrath, Minotaur Pirate", 201, Rarity.MYTHIC, mage.cards.a.AngrathMinotaurPirate.class)); + cards.add(new SetCardInfo("Brass's Bounty", 94, Rarity.RARE, mage.cards.b.BrasssBounty.class)); + cards.add(new SetCardInfo("Captain's Hook", 177, Rarity.RARE, mage.cards.c.CaptainsHook.class)); + cards.add(new SetCardInfo("Cinder Barrens", 205, Rarity.RARE, mage.cards.c.CinderBarrens.class)); + cards.add(new SetCardInfo("Evolving Wilds", 186, Rarity.RARE, mage.cards.e.EvolvingWilds.class)); + cards.add(new SetCardInfo("Ghalta, Primal Hunger", 130, Rarity.RARE, mage.cards.g.GhaltaPrimalHunger.class)); + cards.add(new SetCardInfo("Silvergill Adept", 53, Rarity.UNCOMMON, mage.cards.s.SilvergillAdept.class)); + cards.add(new SetCardInfo("Storm the Vault", 173, Rarity.RARE, mage.cards.s.StormTheVault.class)); + cards.add(new SetCardInfo("Swab Goblin", 203, Rarity.COMMON, mage.cards.s.SwabGoblin.class)); + cards.add(new SetCardInfo("Tetzimoc, Primal Death", 86, Rarity.RARE, mage.cards.t.TetzimocPrimalDeath.class)); + cards.add(new SetCardInfo("The Immortal Sun", 180, Rarity.MYTHIC, mage.cards.t.TheImmortalSun.class)); + cards.add(new SetCardInfo("Vampire Champion", 198, Rarity.COMMON, mage.cards.v.VampireChampion.class)); + cards.add(new SetCardInfo("Vault of Catlacan", 173, Rarity.RARE, mage.cards.v.VaultOfCatlacan.class)); + cards.add(new SetCardInfo("Vona's Hunger", 90, Rarity.RARE, mage.cards.v.VonasHunger.class)); + cards.add(new SetCardInfo("Vraska's Conquistador", 199, Rarity.UNCOMMON, mage.cards.v.VraskasConquistador.class)); + cards.add(new SetCardInfo("Vraska's Scorn", 200, Rarity.RARE, mage.cards.v.VraskasScorn.class)); + cards.add(new SetCardInfo("Vraska, Scheming Gorgon", 197, Rarity.MYTHIC, mage.cards.v.VraskaSchemingGorgon.class)); + } +} diff --git a/Mage.Sets/src/mage/sets/Unstable.java b/Mage.Sets/src/mage/sets/Unstable.java index 1d016a207d4..c451dfa932f 100644 --- a/Mage.Sets/src/mage/sets/Unstable.java +++ b/Mage.Sets/src/mage/sets/Unstable.java @@ -79,6 +79,7 @@ public class Unstable extends ExpansionSet { cards.add(new SetCardInfo("Sword of Dungeons & Dragons", 1, Rarity.MYTHIC, mage.cards.s.SwordOfDungeonsAndDragons.class)); cards.add(new SetCardInfo("Target Minotaur", 98, Rarity.COMMON, mage.cards.t.TargetMinotaur.class)); cards.add(new SetCardInfo("Time Out", 48, Rarity.COMMON, mage.cards.t.TimeOut.class)); + cards.add(new SetCardInfo("Very Cryptic Command", 49, Rarity.RARE, mage.cards.v.VeryCrypticCommand.class)); cards.add(new SetCardInfo("Willing Test Subject", 126, Rarity.COMMON, mage.cards.w.WillingTestSubject.class)); cards.add(new SetCardInfo("capital offense", 52, Rarity.COMMON, mage.cards.c.CapitalOffense.class)); } diff --git a/Mage.Sets/src/mage/sets/UrzasLegacy.java b/Mage.Sets/src/mage/sets/UrzasLegacy.java index cadbddbd38a..38b8dff7ede 100644 --- a/Mage.Sets/src/mage/sets/UrzasLegacy.java +++ b/Mage.Sets/src/mage/sets/UrzasLegacy.java @@ -175,6 +175,7 @@ public class UrzasLegacy extends ExpansionSet { cards.add(new SetCardInfo("Ticking Gnomes", 136, Rarity.UNCOMMON, mage.cards.t.TickingGnomes.class)); cards.add(new SetCardInfo("Tinker", 45, Rarity.UNCOMMON, mage.cards.t.Tinker.class)); cards.add(new SetCardInfo("Tragic Poet", 24, Rarity.COMMON, mage.cards.t.TragicPoet.class)); + cards.add(new SetCardInfo("Treacherous Link", 71, Rarity.UNCOMMON, mage.cards.t.TreacherousLink.class)); cards.add(new SetCardInfo("Treefolk Mystic", 114, Rarity.COMMON, mage.cards.t.TreefolkMystic.class)); cards.add(new SetCardInfo("Treetop Village", 143, Rarity.UNCOMMON, mage.cards.t.TreetopVillage.class)); cards.add(new SetCardInfo("Unearth", 72, Rarity.COMMON, mage.cards.u.Unearth.class)); @@ -183,6 +184,7 @@ public class UrzasLegacy extends ExpansionSet { cards.add(new SetCardInfo("Viashino Heretic", 95, Rarity.UNCOMMON, mage.cards.v.ViashinoHeretic.class)); cards.add(new SetCardInfo("Viashino Sandscout", 96, Rarity.COMMON, mage.cards.v.ViashinoSandscout.class)); cards.add(new SetCardInfo("Vigilant Drake", 46, Rarity.COMMON, mage.cards.v.VigilantDrake.class)); + cards.add(new SetCardInfo("Walking Sponge", 47, Rarity.UNCOMMON, mage.cards.w.WalkingSponge.class)); cards.add(new SetCardInfo("Weatherseed Elf", 115, Rarity.COMMON, mage.cards.w.WeatherseedElf.class)); cards.add(new SetCardInfo("Weatherseed Faeries", 48, Rarity.COMMON, mage.cards.w.WeatherseedFaeries.class)); cards.add(new SetCardInfo("Weatherseed Treefolk", 116, Rarity.RARE, mage.cards.w.WeatherseedTreefolk.class)); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/enters/AugurOfBolasTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/enters/AugurOfBolasTest.java new file mode 100644 index 00000000000..f8530873451 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/enters/AugurOfBolasTest.java @@ -0,0 +1,39 @@ +package org.mage.test.cards.abilities.enters; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ +public class AugurOfBolasTest extends CardTestPlayerBase { + + /* + Aether Figment {1}{U} + Creature - Illusion + 1/1 + Kicker {3} (You may pay an additional as you cast this spell.) + Aether Figment can't be blocked. + If Aether Figment was kicked, it enters the battlefield with two +1/+1 counters on it. + */ + @Test + public void testEnteringWithCounters() { + addCard(Zone.LIBRARY, playerA, "Lightning Bolt", 3); + skipInitShuffling(); + addCard(Zone.BATTLEFIELD, playerA, "Island", 2); + // When Augur of Bolas enters the battlefield, look at the top three cards of your library. + // You may reveal an instant or sorcery card from among them and put it into your hand. Put the rest on the bottom of your library in any order. + addCard(Zone.HAND, playerA, "Augur of Bolas"); // Creature {1}{U} + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Augur of Bolas"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPermanentCount(playerA, "Augur of Bolas", 1); + assertHandCount(playerA, "Lightning Bolt", 1); + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/MorphTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/MorphTest.java index b4a15d9b529..8c8733d57dc 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/MorphTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/MorphTest.java @@ -816,4 +816,41 @@ public class MorphTest extends CardTestPlayerBase { assertPermanentCount(playerA, "", 0); } + + /** + * The Ur-Dragon reduces cost of face down morph Dragons Simple to reproduce + * - Dragons with Morph/Megamorph such as Quicksilver Dragon cost {2} to + * play face-down instead of the normal {3}. Other non-Dragon morph costs + * are unchanged. + */ + @Test + public void testNoCostReductionOfFaceDownCastCreature() { + /* + Quicksilver Dragon {4}{U}{U} + Creature - Dragon + 5/5 + Flying + {U}: If target spell has only one target and that target is Quicksilver Dragon, change that spell's target to another creature. + Morph {4}{U} + */ + addCard(Zone.HAND, playerA, "Quicksilver Dragon"); + addCard(Zone.BATTLEFIELD, playerA, "Island", 3); + + // Eminence - As long as The Ur-Dragon is in the command zone or on the battlefield, other Dragon spells you cast cost {1} less to cast. + // Flying + // Whenever one or more Dragons you control attack, draw that many cards, then you may put a permanent card from your hand onto the battlefield + addCard(Zone.BATTLEFIELD, playerA, "The Ur-Dragon", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Quicksilver Dragon"); + setChoice(playerA, "Yes"); // cast it face down as 2/2 creature + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPermanentCount(playerA, "", 1); + assertHandCount(playerA, 0); + + assertTappedCount("Island", true, 3); + + } } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/copy/MirrorworksTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/copy/MirrorworksTest.java new file mode 100644 index 00000000000..792a371bc99 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/copy/MirrorworksTest.java @@ -0,0 +1,94 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package org.mage.test.cards.copy; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ +public class MirrorworksTest extends CardTestPlayerBase { + + /** + * If you play Mox Diamond, with Mirrorworks in play, and create a token + * copy, and you have no lands in hand, the Mox will enter the battlefield + * as usual instead of the graveyard. + */ + @Test + public void TestCopyWithoutLand() { + addCard(Zone.HAND, playerA, "Mountain", 1); + addCard(Zone.BATTLEFIELD, playerA, "Island", 2); + + // If Mox Diamond would enter the battlefield, you may discard a land card instead. If you do, put Mox Diamond onto the battlefield. If you don't, put it into its owner's graveyard. + // {T}: Add one mana of any color to your mana pool. + addCard(Zone.HAND, playerA, "Mox Diamond", 1); // Artifact {0} + + // Whenever another nontoken artifact enters the battlefield under your control, you may pay {2}. + // If you do, create a token that's a copy of that artifact. + addCard(Zone.BATTLEFIELD, playerA, "Mirrorworks", 1); // Artifact {5} + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Mox Diamond"); + setChoice(playerA, "Yes"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPermanentCount(playerA, "Mox Diamond", 1); + assertTappedCount("Island", true, 2); + assertGraveyardCount(playerA, "Mountain", 1); + + } + + @Test + public void TestCorrectCopy() { + addCard(Zone.HAND, playerA, "Mountain", 2); + addCard(Zone.BATTLEFIELD, playerA, "Island", 2); + + // If Mox Diamond would enter the battlefield, you may discard a land card instead. If you do, put Mox Diamond onto the battlefield. If you don't, put it into its owner's graveyard. + // {T}: Add one mana of any color to your mana pool. + addCard(Zone.HAND, playerA, "Mox Diamond", 1); // Artifact {0} + + // Whenever another nontoken artifact enters the battlefield under your control, you may pay {2}. + // If you do, create a token that's a copy of that artifact. + addCard(Zone.BATTLEFIELD, playerA, "Mirrorworks", 1); // Artifact {5} + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Mox Diamond"); + setChoice(playerA, "Yes"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPermanentCount(playerA, "Mox Diamond", 2); + assertGraveyardCount(playerA, "Mountain", 2); + + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/multiplayer/BlatantThieveryTest.java b/Mage.Tests/src/test/java/org/mage/test/multiplayer/BlatantThieveryTest.java new file mode 100644 index 00000000000..a5447b94b15 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/multiplayer/BlatantThieveryTest.java @@ -0,0 +1,93 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.mage.test.multiplayer; + +import java.io.FileNotFoundException; +import mage.constants.MultiplayerAttackOption; +import mage.constants.PhaseStep; +import mage.constants.RangeOfInfluence; +import mage.constants.Zone; +import mage.game.FreeForAll; +import mage.game.Game; +import mage.game.GameException; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestMultiPlayerBase; + +/** + * + * @author LevelX2 + */ +public class BlatantThieveryTest extends CardTestMultiPlayerBase { + + @Override + protected Game createNewGameAndPlayers() throws GameException, FileNotFoundException { + Game game = new FreeForAll(MultiplayerAttackOption.MULTIPLE, RangeOfInfluence.ALL, 0, 20); + // Player order: A -> D -> C -> B + playerA = createPlayer(game, playerA, "PlayerA"); + playerB = createPlayer(game, playerB, "PlayerB"); + playerC = createPlayer(game, playerC, "PlayerC"); + playerD = createPlayer(game, playerD, "PlayerD"); + return game; + } + + @Test + public void NormalTest() { + // For each opponent, gain control of target permanent that player controls. + addCard(Zone.HAND, playerA, "Blatant Thievery"); // Sorcery {4}{U}{U}{U} + addCard(Zone.BATTLEFIELD, playerA, "Island", 7); + + // Player order: A -> D -> C -> B + addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion", 2); + addCard(Zone.BATTLEFIELD, playerC, "Walking Corpse", 2); + addCard(Zone.BATTLEFIELD, playerD, "Pillarfield Ox", 2); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Blatant Thievery"); + addTarget(playerA, "Silvercoat Lion"); + addTarget(playerA, "Walking Corpse"); + addTarget(playerA, "Pillarfield Ox"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPermanentCount(playerA, "Silvercoat Lion", 1); + assertPermanentCount(playerA, "Walking Corpse", 1); + assertPermanentCount(playerA, "Pillarfield Ox", 1); + assertPermanentCount(playerB, "Silvercoat Lion", 1); + assertPermanentCount(playerC, "Walking Corpse", 1); + assertPermanentCount(playerD, "Pillarfield Ox", 1); + } + + @Test + public void ControlChangeTest() { + // For each opponent, gain control of target permanent that player controls. + addCard(Zone.HAND, playerA, "Blatant Thievery"); // Sorcery {4}{U}{U}{U} + addCard(Zone.BATTLEFIELD, playerA, "Island", 7); + + addCard(Zone.HAND, playerB, "Act of Aggression"); // Instant {3}{M}{M} + addCard(Zone.BATTLEFIELD, playerB, "Mountain", 5); + + // Player order: A -> D -> C -> B + addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion", 1); + addCard(Zone.BATTLEFIELD, playerC, "Walking Corpse", 1); + addCard(Zone.BATTLEFIELD, playerD, "Pillarfield Ox", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Blatant Thievery"); + addTarget(playerA, "Silvercoat Lion"); + addTarget(playerA, "Walking Corpse"); + addTarget(playerA, "Pillarfield Ox"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Act of Aggression", "Pillarfield Ox", "Blatant Thievery"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertGraveyardCount(playerA, "Blatant Thievery", 1); + assertGraveyardCount(playerB, "Act of Aggression", 1); + + assertPermanentCount(playerA, "Silvercoat Lion", 1); + assertPermanentCount(playerA, "Walking Corpse", 1); + assertPermanentCount(playerB, "Pillarfield Ox", 1); + } +} diff --git a/Mage/src/main/java/mage/abilities/common/DealsCombatDamageToAPlayerTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/DealsCombatDamageToAPlayerTriggeredAbility.java index c13f59afbbd..392df68ec1f 100644 --- a/Mage/src/main/java/mage/abilities/common/DealsCombatDamageToAPlayerTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/DealsCombatDamageToAPlayerTriggeredAbility.java @@ -33,6 +33,7 @@ import mage.constants.Zone; import mage.game.Game; import mage.game.events.DamagedPlayerEvent; import mage.game.events.GameEvent; +import mage.players.Player; import mage.target.targetpointer.FixedTarget; /** @@ -43,14 +44,20 @@ public class DealsCombatDamageToAPlayerTriggeredAbility extends TriggeredAbility protected boolean setTargetPointer; protected String text; + protected boolean onlyOpponents; public DealsCombatDamageToAPlayerTriggeredAbility(Effect effect, boolean optional) { this(effect, optional, false); } public DealsCombatDamageToAPlayerTriggeredAbility(Effect effect, boolean optional, boolean setTargetPointer) { + this(effect, optional, setTargetPointer, false); + } + + public DealsCombatDamageToAPlayerTriggeredAbility(Effect effect, boolean optional, boolean setTargetPointer, boolean onlyOpponents) { super(Zone.BATTLEFIELD, effect, optional); this.setTargetPointer = setTargetPointer; + this.onlyOpponents = onlyOpponents; } public DealsCombatDamageToAPlayerTriggeredAbility(Effect effect, boolean optional, String text, boolean setTargetPointer) { @@ -63,6 +70,7 @@ public class DealsCombatDamageToAPlayerTriggeredAbility extends TriggeredAbility super(ability); this.text = ability.text; this.setTargetPointer = ability.setTargetPointer; + this.onlyOpponents = ability.onlyOpponents; } @Override @@ -79,6 +87,12 @@ public class DealsCombatDamageToAPlayerTriggeredAbility extends TriggeredAbility public boolean checkTrigger(GameEvent event, Game game) { if (event.getSourceId().equals(getSourceId()) && ((DamagedPlayerEvent) event).isCombatDamage()) { + if (onlyOpponents) { + Player controller = game.getPlayer(getControllerId()); + if (controller == null || !controller.hasOpponent(event.getPlayerId(), game)) { + return false; + } + } if (setTargetPointer) { for (Effect effect : this.getAllEffects()) { effect.setTargetPointer(new FixedTarget(event.getPlayerId())); @@ -93,7 +107,7 @@ public class DealsCombatDamageToAPlayerTriggeredAbility extends TriggeredAbility @Override public String getRule() { if (text == null || text.isEmpty()) { - return "Whenever {this} deals combat damage to a player, " + super.getRule(); + return "Whenever {this} deals combat damage to " + (onlyOpponents ? "an opponent, " : "a player, ") + super.getRule(); } return text; } diff --git a/Mage/src/main/java/mage/abilities/effects/Effect.java b/Mage/src/main/java/mage/abilities/effects/Effect.java index 17234c7f9dc..fc98f40a947 100644 --- a/Mage/src/main/java/mage/abilities/effects/Effect.java +++ b/Mage/src/main/java/mage/abilities/effects/Effect.java @@ -24,16 +24,15 @@ * The views and conclusions contained in the software and documentation are those of the * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. -*/ - + */ package mage.abilities.effects; import java.io.Serializable; import java.util.UUID; -import mage.constants.EffectType; -import mage.constants.Outcome; import mage.abilities.Ability; import mage.abilities.Mode; +import mage.constants.EffectType; +import mage.constants.Outcome; import mage.game.Game; import mage.target.targetpointer.TargetPointer; @@ -44,18 +43,31 @@ import mage.target.targetpointer.TargetPointer; public interface Effect extends Serializable { UUID getId(); + void newId(); + String getText(Mode mode); + Effect setText(String staticText); + boolean apply(Game game, Ability source); + Outcome getOutcome(); + void setOutcome(Outcome outcome); + EffectType getEffectType(); - void setTargetPointer(TargetPointer targetPointer); + + Effect setTargetPointer(TargetPointer targetPointer); + TargetPointer getTargetPointer(); + void setValue(String key, Object value); + Object getValue(String key); + void setApplyEffectsAfter(); + boolean applyEffectsAfter(); Effect copy(); diff --git a/Mage/src/main/java/mage/abilities/effects/EffectImpl.java b/Mage/src/main/java/mage/abilities/effects/EffectImpl.java index 91f82ddaa98..ccc7f08f3d8 100644 --- a/Mage/src/main/java/mage/abilities/effects/EffectImpl.java +++ b/Mage/src/main/java/mage/abilities/effects/EffectImpl.java @@ -24,20 +24,18 @@ * The views and conclusions contained in the software and documentation are those of the * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. -*/ - + */ package mage.abilities.effects; -import mage.constants.EffectType; -import mage.constants.Outcome; -import mage.abilities.MageSingleton; -import mage.abilities.Mode; -import mage.target.targetpointer.FirstTargetPointer; -import mage.target.targetpointer.TargetPointer; - import java.util.HashMap; import java.util.Map; import java.util.UUID; +import mage.abilities.MageSingleton; +import mage.abilities.Mode; +import mage.constants.EffectType; +import mage.constants.Outcome; +import mage.target.targetpointer.FirstTargetPointer; +import mage.target.targetpointer.TargetPointer; /** * @@ -106,8 +104,9 @@ public abstract class EffectImpl implements Effect { } @Override - public void setTargetPointer(TargetPointer targetPointer) { + public Effect setTargetPointer(TargetPointer targetPointer) { this.targetPointer = targetPointer; + return this; } @Override @@ -141,8 +140,8 @@ public abstract class EffectImpl implements Effect { } /** - * If set, the game.applyEffects() method will be called to apply the effects before the - * next effect (of the same ability) will resolve. + * If set, the game.applyEffects() method will be called to apply the + * effects before the next effect (of the same ability) will resolve. */ @Override public void setApplyEffectsAfter() { diff --git a/Mage/src/main/java/mage/abilities/effects/common/DestroyEquippedEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DestroyEquippedEffect.java new file mode 100644 index 00000000000..6d833155850 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/DestroyEquippedEffect.java @@ -0,0 +1,51 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package mage.abilities.effects.common; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.constants.Outcome; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * + * @author LevelX2 + */ +public class DestroyEquippedEffect extends OneShotEffect { + + public DestroyEquippedEffect() { + super(Outcome.DestroyPermanent); + staticText = "destroy that permanent"; + } + + public DestroyEquippedEffect(final DestroyEquippedEffect effect) { + super(effect); + } + + @Override + public DestroyEquippedEffect copy() { + return new DestroyEquippedEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent equipment = game.getPermanent(source.getSourceId()); + if (equipment != null && equipment.getAttachedTo() != null) { + UUID uuid = getTargetPointer().getFirst(game, source); + Permanent permanent = game.getPermanent(uuid); + if (permanent == null) { + permanent = game.getPermanent(equipment.getAttachedTo()); + } + if (permanent != null) { + return permanent.destroy(source.getSourceId(), game, false); + } + } + return false; + } + +} diff --git a/Mage/src/main/java/mage/abilities/keyword/MorphAbility.java b/Mage/src/main/java/mage/abilities/keyword/MorphAbility.java index dfe545198cd..46714d92439 100644 --- a/Mage/src/main/java/mage/abilities/keyword/MorphAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/MorphAbility.java @@ -230,6 +230,7 @@ public class MorphAbility extends StaticAbility implements AlternativeSourceCost spellColor.setGreen(false); spellColor.setWhite(false); spellColor.setBlue(false); + spell.getSubtype(game).clear(); } else { spell.setFaceDown(false, game); } diff --git a/Mage/src/main/java/mage/abilities/keyword/SquirrellinkAbility.java b/Mage/src/main/java/mage/abilities/keyword/SquirrellinkAbility.java index a2c1f55e389..246b42a8795 100644 --- a/Mage/src/main/java/mage/abilities/keyword/SquirrellinkAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/SquirrellinkAbility.java @@ -56,7 +56,7 @@ public class SquirrellinkAbility extends StaticAbility implements MageSingleton @Override public String getRule() { - return "Squirrellink (Damage dealt by this creature also causes you to create that many 1/1/ green Squirrel creature tokens.)"; + return "Squirrellink (Damage dealt by this creature also causes you to create that many 1/1 green Squirrel creature tokens.)"; } @Override diff --git a/Mage/src/main/java/mage/constants/SubType.java b/Mage/src/main/java/mage/constants/SubType.java index 4766d9114d4..276dcfd1897 100644 --- a/Mage/src/main/java/mage/constants/SubType.java +++ b/Mage/src/main/java/mage/constants/SubType.java @@ -179,7 +179,7 @@ public enum SubType { KAVU("Kavu", SubTypeSet.CreatureType), KELDOR("KelDor", SubTypeSet.CreatureType, true), KILLBOT("Killbot", SubTypeSet.CreatureType, true), // Unstable - KIRIN("Kirin", SubTypeSet.CreatureType), + KIRIN("Kirin", SubTypeSet.CreatureType), KITHKIN("Kithkin", SubTypeSet.CreatureType), KNIGHT("Knight", SubTypeSet.CreatureType), KOBOLD("Kobold", SubTypeSet.CreatureType), @@ -328,6 +328,7 @@ public enum SubType { VAMPIRE("Vampire", SubTypeSet.CreatureType), VEDALKEN("Vedalken", SubTypeSet.CreatureType), VIASHINO("Viashino", SubTypeSet.CreatureType), + VILLAIN("Villain", SubTypeSet.CreatureType, true), // Unstable VOLVER("Volver", SubTypeSet.CreatureType), //W WALL("Wall", SubTypeSet.CreatureType), @@ -352,6 +353,7 @@ public enum SubType { ZUBERA("Zubera", SubTypeSet.CreatureType), // Planeswalker AJANI("Ajani", SubTypeSet.PlaneswalkerType), + ANGRATH("Angrath", SubTypeSet.PlaneswalkerType), ARLINN("Arlinn", SubTypeSet.PlaneswalkerType), ASHIOK("Ashiok", SubTypeSet.PlaneswalkerType), AURRA("Aurra", SubTypeSet.PlaneswalkerType, true), // Star Wars diff --git a/Mage/src/main/java/mage/counters/CounterType.java b/Mage/src/main/java/mage/counters/CounterType.java index 82c783d3a75..769412a3849 100644 --- a/Mage/src/main/java/mage/counters/CounterType.java +++ b/Mage/src/main/java/mage/counters/CounterType.java @@ -107,6 +107,7 @@ public enum CounterType { POLYP("polyp"), POISON("poison"), PRESSURE("pressure"), + PREY("prey"), REPAIR("repair"), QUEST("quest"), SCREAM("scream"), diff --git a/Mage/src/main/java/mage/game/permanent/token/BrainiacToken.java b/Mage/src/main/java/mage/game/permanent/token/BrainiacToken.java new file mode 100644 index 00000000000..39d87fee1bb --- /dev/null +++ b/Mage/src/main/java/mage/game/permanent/token/BrainiacToken.java @@ -0,0 +1,48 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com AS IS AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.game.permanent.token; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.MageInt; + +/** + * + * @author spjspj + */ +public class BrainiacToken extends Token { + + public BrainiacToken() { + super("Brainiac", "1/1 red Brainiac creature token"); + cardType.add(CardType.CREATURE); + color.setRed(true); + subtype.add(SubType.BRAINIAC); + power = new MageInt(1); + toughness = new MageInt(1); + } +} diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index 6467fde19cc..c45de6289df 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -32777,3 +32777,6 @@ Wall of Fortune|Unstable|50|C|{1}{U}|Artifact Creature - Wall|0|4|Defender$You m Wild Crocodile|Unstable|125|C|{1}{G}|Host Creature - Crocodile|1|1|When this creature enters the battlefield, search your library for a basic land card, reveal it, put it into your hand, then shuffle your library.| Willing Test Subject|Unstable|126|C|{2}{G}|Creature- Spider Monkey Scientist|2|2|Reach$Whenever you roll a 4 or higher on a die, put a +1/+1 counter on Willing Test Subject.$6: Roll a six-sided die.| Garbage Elemental|Unstable|82|U|{4}{R}|Creature - Elemental|3|2|Battle cry (Whenever this creature attacks, each other attacking creature gets +1/+0 until end of turn.)$When Garbage Elemental enters the battlefield, roll two six-sided dice. Create a number of 1/1 red Goblin creature tokens equal to the difference between those results.| +Oddly Uneven|Unstable|15|R|{3}{W}{W}|Sorcery|||Choose one --$* Destroy each creature with an odd number of words in its name. (Hyphenated words are one word.)$* Destroy each creature with an even number of words in its name.| +capital offense|Unstable|52|C|{2}{B}{B}|Instant|||target creature gets -x/-x until end of turn, where x is the number of times a capital letter appears in its rules text. (ignore reminder text and flavor text.) +Very Cryptic Command|Unstable|49|R|{1}{U}{U}{U}|Instant|||Choose two - Return target permanent to its controller’s hand.; Draw two cards, then discard a card.; Change the target of target spell with a single target.; Turn over target nontoken creature.|