diff --git a/Mage.Sets/src/mage/sets/commander2015/DeadlyTempest.java b/Mage.Sets/src/mage/sets/commander2015/DeadlyTempest.java new file mode 100644 index 00000000000..7af864bd0f1 --- /dev/null +++ b/Mage.Sets/src/mage/sets/commander2015/DeadlyTempest.java @@ -0,0 +1,107 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.commander2015; + +import java.util.HashMap; +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.filter.common.FilterCreaturePermanent; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; + +/** + * + * @author LevelX2 + */ +public class DeadlyTempest extends CardImpl { + + public DeadlyTempest(UUID ownerId) { + super(ownerId, 19, "Deadly Tempest", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{4}{B}{B}"); + this.expansionSetCode = "C15"; + + // Destroy all creatures. Each player loses life equal to the number of creatures he or she controlled that were destroyed this way. + getSpellAbility().addEffect(new DeadlyTempestEffect()); + } + + public DeadlyTempest(final DeadlyTempest card) { + super(card); + } + + @Override + public DeadlyTempest copy() { + return new DeadlyTempest(this); + } +} + +class DeadlyTempestEffect extends OneShotEffect { + + public DeadlyTempestEffect() { + super(Outcome.DestroyPermanent); + this.staticText = "Destroy all creatures. Each player loses life equal to the number of creatures he or she controlled that were destroyed this way"; + } + + public DeadlyTempestEffect(final DeadlyTempestEffect effect) { + super(effect); + } + + @Override + public DeadlyTempestEffect copy() { + return new DeadlyTempestEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + HashMap destroyedCreatures = new HashMap<>(); + for (Permanent permanent : game.getBattlefield().getActivePermanents(new FilterCreaturePermanent(), source.getControllerId(), source.getSourceId(), game)) { + if (permanent.destroy(source.getSourceId(), game, false)) { + int count = destroyedCreatures.containsKey(permanent.getControllerId()) ? destroyedCreatures.get(permanent.getControllerId()) : 0; + destroyedCreatures.put(permanent.getControllerId(), count + 1); + } + } + for (UUID playerId : game.getState().getPlayerList(source.getControllerId())) { + int count = destroyedCreatures.containsKey(playerId) ? destroyedCreatures.get(playerId) : 0; + if (count > 0) { + Player player = game.getPlayer(playerId); + if (player != null) { + player.damage(count, playerId, game, false, true); + } + } + } + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/commander2015/DreadSummons.java b/Mage.Sets/src/mage/sets/commander2015/DreadSummons.java new file mode 100644 index 00000000000..4f2b645a370 --- /dev/null +++ b/Mage.Sets/src/mage/sets/commander2015/DreadSummons.java @@ -0,0 +1,111 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.commander2015; + +import java.util.Set; +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.permanent.token.ZombieToken; +import mage.players.Player; + +/** + * + * @author LevelX2 + */ +public class DreadSummons extends CardImpl { + + public DreadSummons(UUID ownerId) { + super(ownerId, 20, "Dread Summons", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{X}{B}{B}"); + this.expansionSetCode = "C15"; + + // Each player puts the top X cards of his or her library into his or her graveyard. For each creature card put into a graveyard this way, you put a 2/2 black Zombie creature token onto the battlefield tapped. + getSpellAbility().addEffect(new DreadSummonsEffect()); + } + + public DreadSummons(final DreadSummons card) { + super(card); + } + + @Override + public DreadSummons copy() { + return new DreadSummons(this); + } +} + +class DreadSummonsEffect extends OneShotEffect { + + public DreadSummonsEffect() { + super(Outcome.PutCreatureInPlay); + this.staticText = "Each player puts the top X cards of his or her library into his or her graveyard. For each creature card put into a graveyard this way, you put a 2/2 black Zombie creature token onto the battlefield tapped"; + } + + public DreadSummonsEffect(final DreadSummonsEffect effect) { + super(effect); + } + + @Override + public DreadSummonsEffect copy() { + return new DreadSummonsEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + int numberOfCards = source.getManaCostsToPay().getX(); + if (numberOfCards > 0) { + int numberOfCreatureCards = 0; + for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) { + Player player = game.getPlayer(playerId); + if (player != null) { + Set movedCards = player.moveCardsToGraveyardWithInfo(player.getLibrary().getTopCards(game, numberOfCards), source, game, Zone.LIBRARY); + for (Card card : movedCards) { + if (card.getCardType().contains(CardType.CREATURE)) { + numberOfCreatureCards++; + } + } + } + } + if (numberOfCreatureCards > 0) { + return new CreateTokenEffect(new ZombieToken(), numberOfCreatureCards, true, false).apply(game, source); + } + } + return true; + } + return false; + } +} diff --git a/Mage/src/mage/abilities/effects/common/PutTopCardOfLibraryIntoGraveEachPlayerEffect.java b/Mage/src/mage/abilities/effects/common/PutTopCardOfLibraryIntoGraveEachPlayerEffect.java index c52b88fff0a..421a97c768a 100644 --- a/Mage/src/mage/abilities/effects/common/PutTopCardOfLibraryIntoGraveEachPlayerEffect.java +++ b/Mage/src/mage/abilities/effects/common/PutTopCardOfLibraryIntoGraveEachPlayerEffect.java @@ -25,7 +25,6 @@ * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package mage.abilities.effects.common; import java.util.UUID; @@ -44,7 +43,6 @@ import mage.util.CardUtil; * * @author LevelX2 */ - public class PutTopCardOfLibraryIntoGraveEachPlayerEffect extends OneShotEffect { private final DynamicValue numberCards; @@ -53,7 +51,7 @@ public class PutTopCardOfLibraryIntoGraveEachPlayerEffect extends OneShotEffect public PutTopCardOfLibraryIntoGraveEachPlayerEffect(int numberCards, TargetController targetController) { this(new StaticValue(numberCards), targetController); } - + public PutTopCardOfLibraryIntoGraveEachPlayerEffect(DynamicValue numberCards, TargetController targetController) { super(Outcome.Discard); this.numberCards = numberCards; @@ -76,42 +74,42 @@ public class PutTopCardOfLibraryIntoGraveEachPlayerEffect extends OneShotEffect public boolean apply(Game game, Ability source) { Player player = game.getPlayer(source.getControllerId()); if (player != null) { - switch(targetController) { + switch (targetController) { case OPPONENT: - for(UUID playerId: game.getOpponents(source.getControllerId()) ) { + for (UUID playerId : game.getOpponents(source.getControllerId())) { putCardsToGravecard(playerId, source, game); } break; case ANY: - for(UUID playerId: player.getInRange() ) { + for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) { putCardsToGravecard(playerId, source, game); } break; case NOT_YOU: - for(UUID playerId: player.getInRange() ) { + for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) { if (!playerId.equals(source.getSourceId())) { putCardsToGravecard(playerId, source, game); } } break; default: - throw new UnsupportedOperationException("TargetController type not supported."); - } + throw new UnsupportedOperationException("TargetController type not supported."); + } return true; } return false; } - + private void putCardsToGravecard(UUID playerId, Ability source, Game game) { Player player = game.getPlayer(playerId); if (player != null) { - player.moveCards(player.getLibrary().getTopCards(game, numberCards.calculate(game, source, this)), Zone.LIBRARY, Zone.GRAVEYARD, source, game); + player.moveCards(player.getLibrary().getTopCards(game, numberCards.calculate(game, source, this)), Zone.GRAVEYARD, source, game); } } private String setText() { StringBuilder sb = new StringBuilder(); - switch(targetController) { + switch (targetController) { case OPPONENT: sb.append("Each opponent "); break; @@ -120,14 +118,14 @@ public class PutTopCardOfLibraryIntoGraveEachPlayerEffect extends OneShotEffect break; case NOT_YOU: sb.append("Each other player "); - break; + break; default: - throw new UnsupportedOperationException("TargetController type not supported."); + throw new UnsupportedOperationException("TargetController type not supported."); } sb.append("puts the top "); - sb.append(CardUtil.numberToText(numberCards.toString(),"a")); + sb.append(CardUtil.numberToText(numberCards.toString(), "a")); sb.append(" card"); - sb.append(numberCards.toString().equals("1")?"":"s"); + sb.append(numberCards.toString().equals("1") ? "" : "s"); sb.append(" of his or her library into his or her graveyard"); return sb.toString(); } diff --git a/Mage/src/mage/game/permanent/token/ZombieToken.java b/Mage/src/mage/game/permanent/token/ZombieToken.java index 90b93810049..28d1e5b4ce7 100644 --- a/Mage/src/mage/game/permanent/token/ZombieToken.java +++ b/Mage/src/mage/game/permanent/token/ZombieToken.java @@ -43,7 +43,7 @@ public class ZombieToken extends Token { final static private List tokenImageSets = new ArrayList<>(); static { - tokenImageSets.addAll(Arrays.asList("10E", "M10", "M11", "M12", "M13", "M14", "M15", "MBS", "ALA", "ISD", "C14", "CNS", "MMA", "BNG", "KTK", "DTK", "ORI")); + tokenImageSets.addAll(Arrays.asList("10E", "M10", "M11", "M12", "M13", "M14", "M15", "MBS", "ALA", "ISD", "C14", "C15", "CNS", "MMA", "BNG", "KTK", "DTK", "ORI")); } public ZombieToken() { diff --git a/Mage/src/mage/players/PlayerImpl.java b/Mage/src/mage/players/PlayerImpl.java index f21805dffc1..55ce77993b0 100644 --- a/Mage/src/mage/players/PlayerImpl.java +++ b/Mage/src/mage/players/PlayerImpl.java @@ -3075,7 +3075,7 @@ public abstract class PlayerImpl implements Player, Serializable { case GRAVEYARD: fromZone = game.getState().getZone(cards.iterator().next().getId()); successfulMovedCards = moveCardsToGraveyardWithInfo(cards, source, game, fromZone); - break; + return successfulMovedCards.size() > 0; case BATTLEFIELD: // new logic that does not yet add the permanents to battlefield while replacement effects are handled List permanents = new ArrayList<>(); List permanentsEntered = new ArrayList<>(); @@ -3285,6 +3285,7 @@ public abstract class PlayerImpl implements Player, Serializable { } } } + game.fireEvent(new ZoneChangeGroupEvent(movedCards, source == null ? null : source.getSourceId(), this.getId(), fromZone, Zone.GRAVEYARD)); return movedCards; }