From 7a8055172d9371a735e85735025dc315f974bab4 Mon Sep 17 00:00:00 2001 From: spjspj Date: Sun, 8 Jan 2017 01:02:01 +1100 Subject: [PATCH 01/19] spjspj - Allow appending from the clipboard in deck editor --- .../client/deckeditor/DeckEditorPanel.java | 32 ++++++++++++++++++- Mage/src/main/java/mage/cards/decks/Deck.java | 23 +++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.java b/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.java index a040df0464c..63f4f7c48f6 100644 --- a/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.java +++ b/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.java @@ -71,6 +71,7 @@ import mage.remote.Session; import mage.view.CardView; import mage.view.SimpleCardView; import org.apache.log4j.Logger; + /** * * @author BetaSteward_at_googlemail.com @@ -693,7 +694,7 @@ public class DeckEditorPanel extends javax.swing.JPanel { btnImport.addActionListener(new java.awt.event.ActionListener() { @Override public void actionPerformed(java.awt.event.ActionEvent evt) { - Object[] options = {"File", "Clipboard"}; + Object[] options = {"File", "Clipboard", "Append from Clipboard"}; int n = JOptionPane.showOptionDialog(MageFrame.getDesktop(), "Where would you like to import from?", @@ -713,6 +714,8 @@ public class DeckEditorPanel extends javax.swing.JPanel { break; case 1: btnImportFromClipboardActionPerformed(evt); + case 2: + btnImportFromClipboardActionWAppendPerformed(evt); } } }); @@ -865,6 +868,33 @@ public class DeckEditorPanel extends javax.swing.JPanel { }); } + /** + * @param evt ActionEvent + */ + private void btnImportFromClipboardActionWAppendPerformed(ActionEvent evt) { + final DeckImportFromClipboardDialog dialog = new DeckImportFromClipboardDialog(); + dialog.pack(); + dialog.setVisible(true); + + dialog.addWindowListener(new WindowAdapter() { + @Override + public void windowClosed(WindowEvent e) { + Deck deckToAppend = null; + try { + deckToAppend = Deck.load(DeckImporterUtil.importDeck(dialog.getTmpPath()), true, true); + if (deckToAppend != null) { + deck = Deck.append(deckToAppend, deck); + refreshDeck(); + } + } catch (GameException e1) { + JOptionPane.showMessageDialog(MageFrame.getDesktop(), e1.getMessage(), "Error loading deck", JOptionPane.ERROR_MESSAGE); + } + + } + }); + } + + private void btnLoadActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnLoadActionPerformed //fcSelectDeck.setCurrentDirectory(new File()); String lastFolder = MageFrame.getPreferences().get("lastDeckFolder", ""); diff --git a/Mage/src/main/java/mage/cards/decks/Deck.java b/Mage/src/main/java/mage/cards/decks/Deck.java index 87bcb2f1bd1..7af38ed879c 100644 --- a/Mage/src/main/java/mage/cards/decks/Deck.java +++ b/Mage/src/main/java/mage/cards/decks/Deck.java @@ -56,6 +56,29 @@ public class Deck implements Serializable { public static Deck load(DeckCardLists deckCardLists, boolean ignoreErrors) throws GameException { return Deck.load(deckCardLists, ignoreErrors, true); } + + public static Deck append(Deck deckToAppend, Deck currentDeck) throws GameException { + List deckCardNames = new ArrayList<>(); + + for (Card card : deckToAppend.getCards()) { + if (card != null) { + currentDeck.cards.add(card); + deckCardNames.add(card.getName()); + } + } + List sbCardNames = new ArrayList<>(); + for (Card card : deckToAppend.getSideboard()) { + if (card != null) { + currentDeck.sideboard.add(card); + deckCardNames.add(card.getName()); + } + } + Collections.sort(deckCardNames); + Collections.sort(sbCardNames); + String deckString = deckCardNames.toString() + sbCardNames.toString(); + currentDeck.setDeckHashCode(DeckUtil.fixedHash(deckString)); + return currentDeck; + } public static Deck load(DeckCardLists deckCardLists, boolean ignoreErrors, boolean mockCards) throws GameException { Deck deck = new Deck(); From 2033095e3d439eb25afadf47325551c1d022e28c Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sat, 7 Jan 2017 19:12:58 +0100 Subject: [PATCH 02/19] [AER] Added 4 cards. --- .../src/mage/cards/g/GremlinInfestation.java | 98 ++++++++ .../src/mage/cards/h/HopeOfGhirapur.java | 229 ++++++++++++++++++ .../mage/cards/i/IndomitableCreativity.java | 169 +++++++++++++ .../mage/cards/m/MechanizedProduction.java | 135 +++++++++++ Mage.Sets/src/mage/sets/AetherRevolt.java | 4 + 5 files changed, 635 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/g/GremlinInfestation.java create mode 100644 Mage.Sets/src/mage/cards/h/HopeOfGhirapur.java create mode 100644 Mage.Sets/src/mage/cards/i/IndomitableCreativity.java create mode 100644 Mage.Sets/src/mage/cards/m/MechanizedProduction.java diff --git a/Mage.Sets/src/mage/cards/g/GremlinInfestation.java b/Mage.Sets/src/mage/cards/g/GremlinInfestation.java new file mode 100644 index 00000000000..499fd8a1108 --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GremlinInfestation.java @@ -0,0 +1,98 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.g; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfEndStepTriggeredAbility; +import mage.abilities.common.DiesAttachedTriggeredAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.DamageAttachedControllerEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.TargetController; +import mage.game.permanent.token.Token; +import mage.target.TargetPermanent; +import mage.target.common.TargetArtifactPermanent; + +/** + * + * @author LevelX2 + */ +public class GremlinInfestation extends CardImpl { + + public GremlinInfestation(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{R}"); + + this.subtype.add("Aura"); + + // Enchant artifact + TargetPermanent auraTarget = new TargetArtifactPermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.Damage)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + + // At the beginning of your end step, Gremlin Infestation deals 2 damage to enchanted artifact's controller. + Effect effect = new DamageAttachedControllerEffect(2); + effect.setText("{this} deals 2 damage to enchanted artifact's controller"); + this.addAbility(new BeginningOfEndStepTriggeredAbility(new DamageAttachedControllerEffect(2), TargetController.YOU, false)); + + // When enchanted artifact is put into a graveyard, create a 2/2 red Gremlin creature token. + this.addAbility(new DiesAttachedTriggeredAbility(new CreateTokenEffect(new GremlinInfestationToken()), "enchanted artifact", false, false)); + } + + public GremlinInfestation(final GremlinInfestation card) { + super(card); + } + + @Override + public GremlinInfestation copy() { + return new GremlinInfestation(this); + } +} + +class GremlinInfestationToken extends Token { + + GremlinInfestationToken() { + super("Gremlin", "2/2 red Gremlin creature token"); + this.setOriginalExpansionSetCode("AER"); + cardType.add(CardType.CREATURE); + color.setRed(true); + subtype.add("Gremlin"); + power = new MageInt(2); + toughness = new MageInt(2); + + } +} diff --git a/Mage.Sets/src/mage/cards/h/HopeOfGhirapur.java b/Mage.Sets/src/mage/cards/h/HopeOfGhirapur.java new file mode 100644 index 00000000000..396351dd1f6 --- /dev/null +++ b/Mage.Sets/src/mage/cards/h/HopeOfGhirapur.java @@ -0,0 +1,229 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and 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.h; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; +import mage.MageInt; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.WatcherScope; +import mage.constants.Zone; +import mage.filter.FilterPlayer; +import mage.filter.predicate.Predicate; +import mage.game.Game; +import mage.game.events.DamagedPlayerEvent; +import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; +import mage.players.Player; +import mage.target.TargetPlayer; +import mage.watchers.Watcher; + +/** + * + * @author LevelX2 + */ +public class HopeOfGhirapur extends CardImpl { + + public HopeOfGhirapur(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{1}"); + + this.supertype.add("Legendary"); + this.subtype.add("Thopter"); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Sacrifice Hope of Ghirapur: Until your next turn, target player who was dealt combat damage by Hope of Ghirapur this turn can't cast noncreature spells. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new HopeOfGhirapurCantCastEffect(), new SacrificeSourceCost()); + this.addAbility(ability, new HopeOfGhirapurCombatDamageWatcher()); + + } + + @Override + public void adjustTargets(Ability ability, Game game) { + if (ability instanceof SimpleActivatedAbility) { + if (ability.getEffects().size() > 0 && (ability.getEffects().get(0) instanceof HopeOfGhirapurCantCastEffect)) { + MageObject sourceObject = ability.getSourceObject(game); + if (sourceObject != null) { + ability.getTargets().clear(); + FilterPlayer playerFilter = new FilterPlayer("player who was dealt combat damage by " + sourceObject.getIdName() + " this turn"); + playerFilter.add(new HopeOfGhirapurPlayerLostLifePredicate(ability.getSourceId())); + ability.addTarget(new TargetPlayer(1, 1, false, playerFilter)); + } + } + } + } + + public HopeOfGhirapur(final HopeOfGhirapur card) { + super(card); + } + + @Override + public HopeOfGhirapur copy() { + return new HopeOfGhirapur(this); + } +} + +class HopeOfGhirapurCantCastEffect extends ContinuousRuleModifyingEffectImpl { + + public HopeOfGhirapurCantCastEffect() { + super(Duration.UntilYourNextTurn, Outcome.Benefit); + staticText = "Until your next turn, target player who was dealt combat damage by {this} this turn can't cast noncreature spells"; + } + + public HopeOfGhirapurCantCastEffect(final HopeOfGhirapurCantCastEffect effect) { + super(effect); + } + + @Override + public HopeOfGhirapurCantCastEffect copy() { + return new HopeOfGhirapurCantCastEffect(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 cast noncreature spells this turn (you were dealt damage by " + mageObject.getLogName() + ")"; + } + return null; + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.CAST_SPELL; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + Player player = game.getPlayer(getTargetPointer().getFirst(game, source)); + if (player != null && player.getId().equals(event.getPlayerId())) { + Card card = game.getCard(event.getSourceId()); + if (card != null && !card.getCardType().contains(CardType.CREATURE)) { + return true; + } + } + return false; + } +} + +class HopeOfGhirapurPlayerLostLifePredicate implements Predicate { + + private final UUID sourceId; + + public HopeOfGhirapurPlayerLostLifePredicate(UUID sourceId) { + this.sourceId = sourceId; + } + + @Override + public boolean apply(Player input, Game game) { + HopeOfGhirapurCombatDamageWatcher watcher = (HopeOfGhirapurCombatDamageWatcher) game.getState().getWatchers().get(HopeOfGhirapurCombatDamageWatcher.class.getName(), sourceId); + if (watcher != null) { + return watcher.playerGotCombatDamage(sourceId, input.getId()); + } + return false; + } +} + +class HopeOfGhirapurCombatDamageWatcher extends Watcher { + + private final HashMap> combatDamagedPlayers = new HashMap<>(); + + public HopeOfGhirapurCombatDamageWatcher() { + super(HopeOfGhirapurCombatDamageWatcher.class.getName(), WatcherScope.GAME); + } + + public HopeOfGhirapurCombatDamageWatcher(final HopeOfGhirapurCombatDamageWatcher watcher) { + super(watcher); + for (UUID objectId : watcher.combatDamagedPlayers.keySet()) { + Set players = new HashSet<>(); + players.addAll(watcher.combatDamagedPlayers.get(objectId)); + this.combatDamagedPlayers.put(objectId, players); + } + } + + @Override + public HopeOfGhirapurCombatDamageWatcher copy() { + return new HopeOfGhirapurCombatDamageWatcher(this); + } + + @Override + public void watch(GameEvent event, Game game) { + if (event.getType() == EventType.DAMAGED_PLAYER && ((DamagedPlayerEvent) event).isCombatDamage()) { + Set players; + if (combatDamagedPlayers.containsKey(event.getSourceId())) { + players = combatDamagedPlayers.get(event.getSourceId()); + } else { + players = new HashSet<>(); + combatDamagedPlayers.put(event.getSourceId(), players); + } + players.add(event.getTargetId()); + } + } + + /** + * Checks if the current object with sourceId has damaged the player during + * the current turn. The zoneChangeCounter will be taken into account. + * + * @param sourceId + * @param game + * @return + */ + public boolean playerGotCombatDamage(UUID sourceId, UUID playerId) { + if (combatDamagedPlayers.containsKey(sourceId)) { + return combatDamagedPlayers.get(sourceId).contains(playerId); + } + return false; + } + + @Override + public void reset() { + super.reset(); + combatDamagedPlayers.clear(); + } +} diff --git a/Mage.Sets/src/mage/cards/i/IndomitableCreativity.java b/Mage.Sets/src/mage/cards/i/IndomitableCreativity.java new file mode 100644 index 00000000000..c1b9e70a5c4 --- /dev/null +++ b/Mage.Sets/src/mage/cards/i/IndomitableCreativity.java @@ -0,0 +1,169 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and 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.i; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Set; +import java.util.UUID; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.SpellAbility; +import mage.abilities.effects.OneShotEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.cards.Cards; +import mage.cards.CardsImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.filter.FilterPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Library; +import mage.players.Player; +import mage.target.TargetPermanent; + +/** + * + * @author LevelX2 + */ +public class IndomitableCreativity extends CardImpl { + + private static final FilterPermanent filter = new FilterPermanent("artifacts and/or creatures"); + + static { + filter.add(Predicates.or(new CardTypePredicate(CardType.ARTIFACT), new CardTypePredicate(CardType.CREATURE))); + } + + public IndomitableCreativity(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{R}{R}{R}"); + + // Destroy X target artifacts and/or creatures. For each permanent destroyed this way, its controller reveals cards from the top of his or her library until an artifact or creature card is revealed and exiles that card. Those players put the exiled card onto the battlefield, then shuffle their libraries. + getSpellAbility().addEffect(new IndomitableCreativityEffect()); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); + } + + public IndomitableCreativity(final IndomitableCreativity card) { + super(card); + } + + @Override + public void adjustTargets(Ability ability, Game game) { + if (ability instanceof SpellAbility) { + ability.getTargets().clear(); + int xValue = ability.getManaCostsToPay().getX(); + ability.addTarget(new TargetPermanent(xValue, xValue, filter, false)); + } + } + + @Override + public IndomitableCreativity copy() { + return new IndomitableCreativity(this); + } +} + +class IndomitableCreativityEffect extends OneShotEffect { + + public IndomitableCreativityEffect() { + super(Outcome.Benefit); + this.staticText = "Destroy X target artifacts and/or creatures. For each permanent destroyed this way, its controller reveals cards from the top of his or her library until an artifact or creature card is revealed and exiles that card. Those players put the exiled card onto the battlefield, then shuffle their libraries"; + } + + public IndomitableCreativityEffect(final IndomitableCreativityEffect effect) { + super(effect); + } + + @Override + public IndomitableCreativityEffect copy() { + return new IndomitableCreativityEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + MageObject sourceObject = source.getSourceObject(game); + if (controller != null && sourceObject != null) { + ArrayList destroyedPermanents = new ArrayList<>(); + for (UUID targetId : getTargetPointer().getTargets(game, source)) { + Permanent target = game.getPermanent(targetId); + if (target != null) { + if (target.destroy(source.getSourceId(), game, false)) { + destroyedPermanents.add(target); + } + } + } + HashMap cardsToReveal = new HashMap<>(); + + for (Permanent permanent : destroyedPermanents) { + Player controllerOfDestroyedCreature = game.getPlayer(permanent.getControllerId()); + if (controllerOfDestroyedCreature != null) { + Library library = controllerOfDestroyedCreature.getLibrary(); + if (library.size() > 0) { + Cards cards = new CardsImpl(); + Cards revealCards; + if (cardsToReveal.containsKey(controllerOfDestroyedCreature)) { + revealCards = cardsToReveal.get(controllerOfDestroyedCreature); + } else { + revealCards = new CardsImpl(); + cardsToReveal.put(controllerOfDestroyedCreature, revealCards); + } + Card card = library.removeFromTop(game); + cards.add(card); + while (!card.getCardType().contains(CardType.CREATURE) && !card.getCardType().contains(CardType.ARTIFACT) && library.size() > 0) { + card = library.removeFromTop(game); + cards.add(card); + } + + if (card.getCardType().contains(CardType.CREATURE) || card.getCardType().contains(CardType.ARTIFACT)) { + controllerOfDestroyedCreature.moveCards(card, Zone.BATTLEFIELD, source, game); + } + + if (cards.size() > 0) { + revealCards.addAll(cards); + Set cardsToShuffle = cards.getCards(game); + cardsToShuffle.remove(card); + library.addAll(cardsToShuffle, game); + + } + controllerOfDestroyedCreature.shuffleLibrary(source, game); + } + } + } + // reveal cards at the end (because a player can have x permanents to be destroyed + for (Player player : cardsToReveal.keySet()) { + player.revealCards(sourceObject.getIdName(), cardsToReveal.get(player), game); + } + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/m/MechanizedProduction.java b/Mage.Sets/src/mage/cards/m/MechanizedProduction.java new file mode 100644 index 00000000000..e3e0aad4c8e --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/MechanizedProduction.java @@ -0,0 +1,135 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.m; + +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +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.Outcome; +import mage.constants.TargetController; +import mage.filter.common.FilterArtifactPermanent; +import mage.filter.common.FilterControlledArtifactPermanent; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.game.permanent.token.EmptyToken; +import mage.players.Player; +import mage.target.TargetPermanent; +import mage.target.common.TargetControlledPermanent; +import mage.util.CardUtil; + +/** + * + * @author LevelX2 + */ +public class MechanizedProduction extends CardImpl { + + public MechanizedProduction(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}{U}"); + + this.subtype.add("Aura"); + + // Enchant artifact you control + TargetPermanent auraTarget = new TargetControlledPermanent(new FilterControlledArtifactPermanent()); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.Copy)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + + // At the beginning of your upkeep, create a token that's a copy of enchanted artifact. Then if you control eight or more artifacts with the same name as one another, you win the game. + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new MechanizedProductionEffect(), TargetController.YOU, false)); + } + + public MechanizedProduction(final MechanizedProduction card) { + super(card); + } + + @Override + public MechanizedProduction copy() { + return new MechanizedProduction(this); + } +} + +class MechanizedProductionEffect extends OneShotEffect { + + public MechanizedProductionEffect() { + super(Outcome.Benefit); + this.staticText = "create a token that's a copy of enchanted artifact. Then if you control eight or more artifacts with the same name as one another, you win the game"; + } + + public MechanizedProductionEffect(final MechanizedProductionEffect effect) { + super(effect); + } + + @Override + public MechanizedProductionEffect copy() { + return new MechanizedProductionEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent sourceObject = game.getPermanentOrLKIBattlefield(source.getSourceId()); + if (sourceObject != null && sourceObject.getAttachedTo() != null) { + Permanent enchantedArtifact = game.getPermanentOrLKIBattlefield(sourceObject.getAttachedTo()); + if (enchantedArtifact != null) { + EmptyToken token = new EmptyToken(); + CardUtil.copyTo(token).from(enchantedArtifact); + token.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId()); + } + Map countNames = new HashMap<>(); + for (Permanent permanent : game.getBattlefield().getAllActivePermanents(new FilterArtifactPermanent(), source.getControllerId(), game)) { + int counter; + if (countNames.containsKey(permanent.getName())) { + counter = countNames.get(permanent.getName()); + } else { + counter = 0; + } + countNames.put(permanent.getName(), counter + 1); + } + for (Entry entry : countNames.entrySet()) { + if (entry.getValue() > 7) { + Player controller = game.getPlayer(source.getControllerId()); + game.informPlayers(controller.getLogName() + " controls eight or more artifacts with the same name as one another (" + entry.getKey() + ")."); + controller.won(game); + return true; + } + } + return true; + + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/AetherRevolt.java b/Mage.Sets/src/mage/sets/AetherRevolt.java index e79c56481df..22bbf59da5c 100644 --- a/Mage.Sets/src/mage/sets/AetherRevolt.java +++ b/Mage.Sets/src/mage/sets/AetherRevolt.java @@ -134,6 +134,7 @@ public class AetherRevolt extends ExpansionSet { cards.add(new SetCardInfo("Gonti's Machinations", 63, Rarity.UNCOMMON, mage.cards.g.GontisMachinations.class)); cards.add(new SetCardInfo("Greenbelt Rampager", 107, Rarity.RARE, mage.cards.g.GreenbeltRampager.class)); cards.add(new SetCardInfo("Greenwheel Liberator", 108, Rarity.RARE, mage.cards.g.GreenwheelLiberator.class)); + cards.add(new SetCardInfo("Gremlin Infestation", 83, Rarity.UNCOMMON, mage.cards.g.GremlinInfestation.class)); cards.add(new SetCardInfo("Heart of Kiran", 153, Rarity.MYTHIC, mage.cards.h.HeartOfKiran.class)); cards.add(new SetCardInfo("Herald of Anguish", 64, Rarity.MYTHIC, mage.cards.h.HeraldOfAnguish.class)); cards.add(new SetCardInfo("Heroic Intervention", 109, Rarity.RARE, mage.cards.h.HeroicIntervention.class)); @@ -141,6 +142,7 @@ public class AetherRevolt extends ExpansionSet { cards.add(new SetCardInfo("Hidden Stockpile", 129, Rarity.UNCOMMON, mage.cards.h.HiddenStockpile.class)); cards.add(new SetCardInfo("Highspire Infusion", 111, Rarity.COMMON, mage.cards.h.HighspireInfusion.class)); cards.add(new SetCardInfo("Hinterland Drake", 34, Rarity.COMMON, mage.cards.h.HinterlandDrake.class)); + cards.add(new SetCardInfo("Hope of Ghirapur", 154, Rarity.RARE, mage.cards.h.HopeOfGhirapur.class)); cards.add(new SetCardInfo("Hungry Flames", 84, Rarity.UNCOMMON, mage.cards.h.HungryFlames.class)); cards.add(new SetCardInfo("Ice Over", 35, Rarity.COMMON, mage.cards.i.IceOver.class)); cards.add(new SetCardInfo("Illusionist's Stratagem", 36, Rarity.UNCOMMON, mage.cards.i.IllusionistsStratagem.class)); @@ -149,6 +151,7 @@ public class AetherRevolt extends ExpansionSet { cards.add(new SetCardInfo("Implement of Ferocity", 157, Rarity.COMMON, mage.cards.i.ImplementOfFerocity.class)); cards.add(new SetCardInfo("Implement of Improvement", 158, Rarity.COMMON, mage.cards.i.ImplementOfImprovement.class)); cards.add(new SetCardInfo("Implement of Malice", 159, Rarity.COMMON, mage.cards.i.ImplementOfMalice.class)); + cards.add(new SetCardInfo("Indomitable Creativity", 85, Rarity.MYTHIC, mage.cards.i.IndomitableCreativity.class)); cards.add(new SetCardInfo("Inspiring Roar", 186, Rarity.COMMON, mage.cards.i.InspiringRoar.class)); cards.add(new SetCardInfo("Inspiring Statuary", 160, Rarity.RARE, mage.cards.i.InspiringStatuary.class)); cards.add(new SetCardInfo("Invigorated Rampage", 86, Rarity.UNCOMMON, mage.cards.i.InvigoratedRampage.class)); @@ -165,6 +168,7 @@ public class AetherRevolt extends ExpansionSet { cards.add(new SetCardInfo("Lightning Runner", 90, Rarity.MYTHIC, mage.cards.l.LightningRunner.class)); cards.add(new SetCardInfo("Maulfist Revolutionary", 115, Rarity.UNCOMMON, mage.cards.m.MaulfistRevolutionary.class)); cards.add(new SetCardInfo("Maverick Thopterist", 130, Rarity.UNCOMMON, mage.cards.m.MaverickThopterist.class)); + cards.add(new SetCardInfo("Mechanized Production", 38, Rarity.MYTHIC, mage.cards.m.MechanizedProduction.class)); cards.add(new SetCardInfo("Metallic Mimic", 164, Rarity.RARE, mage.cards.m.MetallicMimic.class)); cards.add(new SetCardInfo("Metallic Rebuke", 39, Rarity.COMMON, mage.cards.m.MetallicRebuke.class)); cards.add(new SetCardInfo("Midnight Entourage", 66, Rarity.RARE, mage.cards.m.MidnightEntourage.class)); From 24d0353672c3c26d1ecaeb41508e5f950e0e8321 Mon Sep 17 00:00:00 2001 From: fireshoes Date: Sat, 7 Jan 2017 12:14:50 -0600 Subject: [PATCH 03/19] [AER] Edited some cards for text or other minor fixes. --- .../mage/cards/a/AudaciousInfiltrator.java | 137 ++++++++--------- Mage.Sets/src/mage/cards/c/CallForUnity.java | 8 +- Mage.Sets/src/mage/cards/d/Disallow.java | 5 +- Mage.Sets/src/mage/cards/f/FoundryHornet.java | 2 +- Mage.Sets/src/mage/cards/h/HeartOfKiran.java | 11 +- .../src/mage/cards/h/HinterlandDrake.java | 141 +++++++++--------- .../src/mage/cards/p/PerilousPredicament.java | 4 +- Mage.Sets/src/mage/sets/FridayNightMagic.java | 1 + Mage.Sets/src/mage/sets/JudgePromo.java | 2 + .../src/mage/sets/WorldMagicCupQualifier.java | 1 + Utils/mtg-cards-data.txt | 4 + 11 files changed, 166 insertions(+), 150 deletions(-) diff --git a/Mage.Sets/src/mage/cards/a/AudaciousInfiltrator.java b/Mage.Sets/src/mage/cards/a/AudaciousInfiltrator.java index 066f702670f..690ce140679 100644 --- a/Mage.Sets/src/mage/cards/a/AudaciousInfiltrator.java +++ b/Mage.Sets/src/mage/cards/a/AudaciousInfiltrator.java @@ -1,67 +1,70 @@ -/* - * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of BetaSteward_at_googlemail.com. - */ -package mage.cards.a; - -import java.util.UUID; -import mage.MageInt; -import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesSourceEffect; -import mage.cards.CardImpl; -import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Zone; -import mage.filter.StaticFilters; - -/** - * - * @author Styxo - */ -public class AudaciousInfiltrator extends CardImpl { - - public AudaciousInfiltrator(UUID ownerId, CardSetInfo setInfo) { - super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}"); - - this.subtype.add("Dwarf"); - this.subtype.add("Rogue"); - this.power = new MageInt(3); - this.toughness = new MageInt(1); - - // Audacious Infiltrator can't be blocked by artifact creatures. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantBeBlockedByCreaturesSourceEffect(StaticFilters.FILTER_ARTIFACT_CREATURE_PERMANENT, Duration.WhileOnBattlefield))); - } - - public AudaciousInfiltrator(final AudaciousInfiltrator card) { - super(card); - } - - @Override - public AudaciousInfiltrator copy() { - return new AudaciousInfiltrator(this); - } -} +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.a; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesSourceEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Zone; +import mage.filter.StaticFilters; + +/** + * + * @author Styxo + */ +public class AudaciousInfiltrator extends CardImpl { + + public AudaciousInfiltrator(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}"); + + this.subtype.add("Dwarf"); + this.subtype.add("Rogue"); + this.power = new MageInt(3); + this.toughness = new MageInt(1); + + // Audacious Infiltrator can't be blocked by artifact creatures. + Effect effect = new CantBeBlockedByCreaturesSourceEffect(StaticFilters.FILTER_ARTIFACT_CREATURE_PERMANENT, Duration.WhileOnBattlefield); + effect.setText("{this} can't be blocked by artifact creatures"); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); + } + + public AudaciousInfiltrator(final AudaciousInfiltrator card) { + super(card); + } + + @Override + public AudaciousInfiltrator copy() { + return new AudaciousInfiltrator(this); + } +} diff --git a/Mage.Sets/src/mage/cards/c/CallForUnity.java b/Mage.Sets/src/mage/cards/c/CallForUnity.java index e9db569b7c5..c6f40f2e772 100644 --- a/Mage.Sets/src/mage/cards/c/CallForUnity.java +++ b/Mage.Sets/src/mage/cards/c/CallForUnity.java @@ -34,6 +34,7 @@ import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.RevoltCondition; import mage.abilities.decorator.ConditionalTriggeredAbility; import mage.abilities.dynamicvalue.common.CountersSourceCount; +import mage.abilities.effects.Effect; import mage.abilities.effects.common.continuous.BoostControlledEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.cards.CardImpl; @@ -61,9 +62,10 @@ public class CallForUnity extends CardImpl { this.addAbility(new ConditionalTriggeredAbility(ability, new RevoltCondition(), ruleText)); // Creatures you control get +1/+1 for each unity counter on Call for Unity. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, - new BoostControlledEffect(new CountersSourceCount(CounterType.UNITY), new CountersSourceCount(CounterType.UNITY), Duration.WhileOnBattlefield, - new FilterCreaturePermanent(), false))); + Effect effect = new BoostControlledEffect(new CountersSourceCount(CounterType.UNITY), new CountersSourceCount(CounterType.UNITY), Duration.WhileOnBattlefield, + new FilterCreaturePermanent(), false); + effect.setText("Creatures you control get +1/+1 for each unity counter on {this}"); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); } public CallForUnity(final CallForUnity card) { diff --git a/Mage.Sets/src/mage/cards/d/Disallow.java b/Mage.Sets/src/mage/cards/d/Disallow.java index a938a69e69d..337b685a596 100644 --- a/Mage.Sets/src/mage/cards/d/Disallow.java +++ b/Mage.Sets/src/mage/cards/d/Disallow.java @@ -34,6 +34,7 @@ import mage.constants.CardType; import mage.target.TargetStackObject; import java.util.UUID; +import mage.abilities.effects.Effect; /** * @author JRHerlehy @@ -45,7 +46,9 @@ public class Disallow extends CardImpl { // Counter target spell, activated ability, or triggered ability. - this.getSpellAbility().addEffect(new CounterTargetEffect()); + Effect effect = new CounterTargetEffect(); + effect.setText("Counter target spell, activated ability, or triggered ability"); + this.getSpellAbility().addEffect(effect); this.getSpellAbility().addTarget(new TargetStackObject()); } diff --git a/Mage.Sets/src/mage/cards/f/FoundryHornet.java b/Mage.Sets/src/mage/cards/f/FoundryHornet.java index 940795959b9..537f32fdee7 100644 --- a/Mage.Sets/src/mage/cards/f/FoundryHornet.java +++ b/Mage.Sets/src/mage/cards/f/FoundryHornet.java @@ -57,7 +57,7 @@ public class FoundryHornet extends CardImpl { static { filter.add(new CounterPredicate(CounterType.P1P1)); - filter.add(new ControllerPredicate(TargetController.OPPONENT)); + filterOpponent.add(new ControllerPredicate(TargetController.OPPONENT)); } private static final String rule = "When {this} enters the battlefield, if you control a creature with a +1/+1 counter on it, creatures your opponents control get -1/-1 until end of turn."; diff --git a/Mage.Sets/src/mage/cards/h/HeartOfKiran.java b/Mage.Sets/src/mage/cards/h/HeartOfKiran.java index dca01ade0a3..fe0875e9825 100644 --- a/Mage.Sets/src/mage/cards/h/HeartOfKiran.java +++ b/Mage.Sets/src/mage/cards/h/HeartOfKiran.java @@ -51,6 +51,7 @@ import mage.target.Target; import mage.target.common.TargetControlledPermanent; import java.util.UUID; +import mage.abilities.effects.Effect; /** * @author JRHerlehy @@ -76,13 +77,9 @@ public class HeartOfKiran extends CardImpl { // You may remove a loyalty counter from a planeswalker you control rather than pay Heart of Kiran's crew cost. Cost cost = new HeartOfKiranAlternateCrewCost(CounterType.LOYALTY, 1); - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddCardTypeSourceEffect(CardType.CREATURE, Duration.EndOfTurn), cost) { - @Override - public String getRule() { - return "You may remove a loyalty counter from a planeswalker you control rather than pay {this}'s crew cost."; - } - }; - this.addAbility(ability); + Effect effect = new AddCardTypeSourceEffect(CardType.CREATURE, Duration.EndOfTurn); + effect.setText("You may remove a loyalty counter from a planeswalker you control rather than pay {this}'s crew cost"); + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, cost)); } public HeartOfKiran(final HeartOfKiran card) { diff --git a/Mage.Sets/src/mage/cards/h/HinterlandDrake.java b/Mage.Sets/src/mage/cards/h/HinterlandDrake.java index a45eaec0b96..6cc40c4dde6 100644 --- a/Mage.Sets/src/mage/cards/h/HinterlandDrake.java +++ b/Mage.Sets/src/mage/cards/h/HinterlandDrake.java @@ -1,69 +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.h; - -import java.util.UUID; -import mage.MageInt; -import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.common.combat.CantBlockCreaturesSourceEffect; -import mage.abilities.keyword.FlyingAbility; -import mage.cards.CardImpl; -import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.Zone; -import mage.filter.StaticFilters; - -/** - * - * @author Styxo - */ -public class HinterlandDrake extends CardImpl { - - public HinterlandDrake(UUID ownerId, CardSetInfo setInfo) { - super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}"); - - this.subtype.add("Drake"); - this.power = new MageInt(2); - this.toughness = new MageInt(3); - - // Flying - this.addAbility(FlyingAbility.getInstance()); - - // Hinterland Drake can't block artifact creatures. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantBlockCreaturesSourceEffect(StaticFilters.FILTER_ARTIFACT_CREATURE_PERMANENT))); - } - - public HinterlandDrake(final HinterlandDrake card) { - super(card); - } - - @Override - public HinterlandDrake copy() { - return new HinterlandDrake(this); - } -} +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.h; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.combat.CantBlockCreaturesSourceEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.filter.StaticFilters; + +/** + * + * @author Styxo + */ +public class HinterlandDrake extends CardImpl { + + public HinterlandDrake(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}"); + + this.subtype.add("Drake"); + this.power = new MageInt(2); + this.toughness = new MageInt(3); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Hinterland Drake can't block artifact creatures. + Effect effect = new CantBlockCreaturesSourceEffect(StaticFilters.FILTER_ARTIFACT_CREATURE_PERMANENT); + effect.setText("{this} can't block artifact creatures"); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); + } + + public HinterlandDrake(final HinterlandDrake card) { + super(card); + } + + @Override + public HinterlandDrake copy() { + return new HinterlandDrake(this); + } +} diff --git a/Mage.Sets/src/mage/cards/p/PerilousPredicament.java b/Mage.Sets/src/mage/cards/p/PerilousPredicament.java index de27f4ba0b1..cc58fdfa98a 100644 --- a/Mage.Sets/src/mage/cards/p/PerilousPredicament.java +++ b/Mage.Sets/src/mage/cards/p/PerilousPredicament.java @@ -73,7 +73,7 @@ class PerilousPredicamentSacrificeOpponentsEffect extends OneShotEffect { public PerilousPredicamentSacrificeOpponentsEffect() { super(Outcome.Sacrifice); - staticText = "Each opponent sacrifices an artifact and a nonartifact creature"; + staticText = "Each opponent sacrifices an artifact creature and a nonartifact creature"; } public PerilousPredicamentSacrificeOpponentsEffect(final PerilousPredicamentSacrificeOpponentsEffect effect) { @@ -93,7 +93,7 @@ class PerilousPredicamentSacrificeOpponentsEffect extends OneShotEffect { if (player != null) { FilterArtifactCreaturePermanent filterArtifact = new FilterArtifactCreaturePermanent("an artifact creature"); filterArtifact.add(new ControllerIdPredicate(player.getId())); - FilterCreaturePermanent filterNonArtifact = new FilterCreaturePermanent("an non artifact creature"); + FilterCreaturePermanent filterNonArtifact = new FilterCreaturePermanent("a nonartifact creature"); filterNonArtifact.add(Predicates.not(new CardTypePredicate(CardType.ARTIFACT))); filterNonArtifact.add(new ControllerIdPredicate(player.getId())); if (game.getBattlefield().countAll(filterArtifact, player.getId(), game) > 0) { diff --git a/Mage.Sets/src/mage/sets/FridayNightMagic.java b/Mage.Sets/src/mage/sets/FridayNightMagic.java index 2db6bee6f05..69fe4f78abf 100644 --- a/Mage.Sets/src/mage/sets/FridayNightMagic.java +++ b/Mage.Sets/src/mage/sets/FridayNightMagic.java @@ -146,6 +146,7 @@ public class FridayNightMagic extends ExpansionSet { cards.add(new SetCardInfo("Hordeling Outburst", 178, Rarity.UNCOMMON, mage.cards.h.HordelingOutburst.class)); cards.add(new SetCardInfo("Icy Manipulator", 67, Rarity.UNCOMMON, mage.cards.i.IcyManipulator.class)); cards.add(new SetCardInfo("Impulse", 17, Rarity.COMMON, mage.cards.i.Impulse.class)); + cards.add(new SetCardInfo("Incendiary Flow", 202, Rarity.SPECIAL, mage.cards.i.IncendiaryFlow.class)); cards.add(new SetCardInfo("Isochron Scepter", 102, Rarity.UNCOMMON, mage.cards.i.IsochronScepter.class)); cards.add(new SetCardInfo("Izzet Charm", 157, Rarity.UNCOMMON, mage.cards.i.IzzetCharm.class)); cards.add(new SetCardInfo("Jace's Ingenuity", 134, Rarity.UNCOMMON, mage.cards.j.JacesIngenuity.class)); diff --git a/Mage.Sets/src/mage/sets/JudgePromo.java b/Mage.Sets/src/mage/sets/JudgePromo.java index cf91a0a67e0..be983bcdc4e 100644 --- a/Mage.Sets/src/mage/sets/JudgePromo.java +++ b/Mage.Sets/src/mage/sets/JudgePromo.java @@ -91,6 +91,7 @@ public class JudgePromo extends ExpansionSet { cards.add(new SetCardInfo("Hanna, Ship's Navigator", 84, Rarity.RARE, mage.cards.h.HannaShipsNavigator.class)); cards.add(new SetCardInfo("Hermit Druid", 19, Rarity.RARE, mage.cards.h.HermitDruid.class)); cards.add(new SetCardInfo("Imperial Recruiter", 74, Rarity.UNCOMMON, mage.cards.i.ImperialRecruiter.class)); + cards.add(new SetCardInfo("Imperial Seal", 109, Rarity.SPECIAL, mage.cards.i.ImperialSeal.class)); cards.add(new SetCardInfo("Intuition", 11, Rarity.RARE, mage.cards.i.Intuition.class)); cards.add(new SetCardInfo("Island", 90, Rarity.LAND, mage.cards.basiclands.Island.class, new CardGraphicInfo(null, true))); cards.add(new SetCardInfo("Karador, Ghost Chieftain", 80, Rarity.MYTHIC, mage.cards.k.KaradorGhostChieftain.class)); @@ -109,6 +110,7 @@ public class JudgePromo extends ExpansionSet { cards.add(new SetCardInfo("Mishra's Factory", 23, Rarity.UNCOMMON, mage.cards.m.MishrasFactory.class)); cards.add(new SetCardInfo("Morphling", 53, Rarity.RARE, mage.cards.m.Morphling.class)); cards.add(new SetCardInfo("Mountain", 92, Rarity.LAND, mage.cards.basiclands.Mountain.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Mystic Confluence", 109, Rarity.SPECIAL, mage.cards.basiclands.Mountain.class, new CardGraphicInfo(null, true))); cards.add(new SetCardInfo("Natural Order", 49, Rarity.RARE, mage.cards.n.NaturalOrder.class)); cards.add(new SetCardInfo("Nekusar, the Mindrazer", 86, Rarity.MYTHIC, mage.cards.n.NekusarTheMindrazer.class)); cards.add(new SetCardInfo("Noble Hierarch", 66, Rarity.RARE, mage.cards.n.NobleHierarch.class)); diff --git a/Mage.Sets/src/mage/sets/WorldMagicCupQualifier.java b/Mage.Sets/src/mage/sets/WorldMagicCupQualifier.java index 948030fc29b..6f2831ce4ba 100644 --- a/Mage.Sets/src/mage/sets/WorldMagicCupQualifier.java +++ b/Mage.Sets/src/mage/sets/WorldMagicCupQualifier.java @@ -50,6 +50,7 @@ public class WorldMagicCupQualifier extends ExpansionSet { this.hasBasicLands = false; cards.add(new SetCardInfo("Abrupt Decay", 6, Rarity.RARE, mage.cards.a.AbruptDecay.class)); cards.add(new SetCardInfo("Geist of Saint Traft", 2, Rarity.MYTHIC, mage.cards.g.GeistOfSaintTraft.class)); + cards.add(new SetCardInfo("Inkmoth Nexus", 6, Rarity.SPECIAL, mage.cards.i.InkmothNexus.class)); cards.add(new SetCardInfo("Liliana of the Veil", 4, Rarity.MYTHIC, mage.cards.l.LilianaOfTheVeil.class)); cards.add(new SetCardInfo("Snapcaster Mage", 5, Rarity.RARE, mage.cards.s.SnapcasterMage.class)); cards.add(new SetCardInfo("Thalia, Guardian of Thraben", 3, Rarity.RARE, mage.cards.t.ThaliaGuardianOfThraben.class)); diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index fd420b5db15..f0f03b4cdfe 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -8090,6 +8090,7 @@ Fiery Temper|Friday Night Magic|198|U|{1}{R}{R}|Instant|||Fiery Temper deals 3 d Call the Bloodline|Friday Night Magic|199|Special|{1}{B}|Enchantment|||{1}, Discard a card: Create a 1/1 black Vampire Knight creature token with lifelink. Activate this ability only once each turn.| Noose Constrictor|Friday Night Magic|200|Special|{1}{G}|Creature - Snake|2|2|Reach$Discard a card: Noose Constrictor gets +1/+1 until end of turn.| Fortune's Favor|Friday Night Magic|201|Special|{3}{U}|Instant|||Target opponent looks at the top four cards of your library and separates them into a face-down pile and a face-up pile. Put one pile into your hand and the other into your graveyard.| +Incendiary Flow|Friday Night Magic|202|Special|{1}{R}|Sorcery|||Incendiary Flow deals 3 damage to target creature or player. If a creature dealt damage this way would die this turn, exile it instead.| Akroma, Angel of Fury|From the Vault: Angels|1|M|{5}{R}{R}{R}|Legendary Creature - Angel|6|6|Akroma, Angel of Fury can't be countered.$Flying, trample, protection from white and from blue${R}: Akroma, Angel of Fury gets +1/+0 until end of turn.$Morph {3}{R}{R}{R} You may cast this card face downn as a 2/2 creature for {3}. Turn it face up any time for its morph cost.)| Akroma, Angel of Wrath|From the Vault: Angels|2|M|{5}{W}{W}{W}|Legendary Creature - Angel|6|6|Flying, first strike, vigilance, trample, haste, protection from black and from red| Archangel of Strife|From the Vault: Angels|3|M|{5}{W}{W}|Creature - Angel|6|6|Flying$As Archangel of Strife enters the battlefield, each player chooses war or peace.$Creatures controlled by players who chose war get +3/+0.$Creatures controlled by players who chose peace get +0/+3.| @@ -10281,6 +10282,8 @@ Grindstone|Judge Promo|104|R|{1}|Artifact|||{3}, {tap}: Target player puts the t Command Beacon|Judge Promo|105|R||Land|||{tap}: Add {C} to your mana pool.${tap}, Sacrifice Command Beacon: Put your commander into your hand from the command zone.| Defense of the Heart|Judge Promo|106|R|{3}{G}|Enchantment|||At the beginning of your upkeep, if an opponent controls three or more creatures, sacrifice Defense of the Heart, search your library for up to two creature cards, and put those cards onto the battlefield. Then shuffle your library.| Zur the Enchanter|Judge Promo|107|R|{1}{W}{U}{B}|Legendary Creature - Human Wizard|1|4|Flying$Whenever Zur the Enchanter attacks, you may search your library for an enchantment card with converted mana cost 3 or less and put it onto the battlefield. If you do, shuffle your library.| +Mystic Confluence|Judge Promo|108|Special{3}{U}{U}|Instant|||Choose three. You may choose the same mode more than once.$� Counter target spell unless its controller pays {3}.$� Return target creature to its owner's hand.$� Draw a card.| +Imperial Seal|Judge Promo|109|Special|{B}|Sorcery|||Search your library for a card, then shuffle your library and put that card on top of it. You lose 2 life.| Ancestor's Chosen|Judgment|1|U|{5}{W}{W}|Creature - Human Cleric|4|4|First strike (This creature deals combat damage before creatures without first strike.)$When Ancestor's Chosen enters the battlefield, you gain 1 life for each card in your graveyard.| Funeral Pyre|Judgment|10|C|{W}|Instant|||Exile target card from a graveyard. Its owner puts a 1/1 white Spirit creature token with flying onto the battlefield.| Spellgorger Barbarian|Judgment|100|C|{3}{R}|Creature - Human Nightmare Barbarian|3|1|When Spellgorger Barbarian enters the battlefield, discard a card at random.$When Spellgorger Barbarian leaves the battlefield, draw a card.| @@ -26845,6 +26848,7 @@ Geist of Saint Traft|World Magic Cup Qualifier|2|M|{1}{W}{U{|Legendary Creature Thalia, Guardian of Thraben|World Magic Cup Qualifier|3|R|{1}{W}|Legendary Creature - Human Soldier|2|1|First strike$Noncreature spells cost {1} more to cast.| Liliana of the Veil|World Magic Cup Qualifier|4|M|{1}{B}{B}|Planeswalker - Liliana|||+1: Each player discards a card.$-2: Target player sacrifices a creature.$-6: Separate all permanents target player controls into two piles. That player sacrifices all permanents in the pile of his or her choice.| Snapcaster Mage|World Magic Cup Qualifier|5|R|{1}{U}|Creature - Human Wizard|2|1|Flash$When Snapcaster Mage enters the battlefield, target instant or sorcery card in your graveyard gains flashback until end of turn. The flashback cost is equal to its mana cost. (You may cast that card from your graveyard for its flashback cost. Then exile it.)| +Inkmoth Nexus|World Magic Cup Qualifier|6|Special||Land|||{tap}: Add {C} to your mana pool.${1}: Blinkmoth Nexus becomes a 1/1 Blinkmoth artifact creature with flying until end of turn. It's still a land.${1}, {tap}: Target Blinkmoth creature gets +1/+1 until end of turn.| Abrupt Decay|World Magic Cup Qualifier|6|R|{B}{G}|Instant|||Abrupt Decay can't be countered by spells or abilities.$Destroy target nonland permanent with converted mana cost 3 or less.| Admonition Angel|Worldwake|1|M|{3}{W}{W}{W}|Creature - Angel|6|6|Flying$Landfall - Whenever a land enters the battlefield under your control, you may exile target nonland permanent other than Admonition Angel.$When Admonition Angel leaves the battlefield, return all cards exiled with it to the battlefield under their owners' control.| Kitesail Apprentice|Worldwake|10|C|{W}|Creature - Kor Soldier|1|1|As long as Kitesail Apprentice is equipped, it gets +1/+1 and has flying.| From c7e149904bff41702526e47426c5f31773437d9e Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sat, 7 Jan 2017 20:03:03 +0100 Subject: [PATCH 04/19] [AER] Fixed some problems with revolt. --- .../src/mage/cards/a/AidFromTheCowl.java | 8 +- Mage.Sets/src/mage/cards/c/CallForUnity.java | 3 +- Mage.Sets/src/mage/cards/s/SolemnRecruit.java | 7 +- Mage.Sets/src/mage/cards/v/VengefulRebel.java | 5 +- .../condition/common/RevoltCondition.java | 112 +++++++++--------- 5 files changed, 69 insertions(+), 66 deletions(-) diff --git a/Mage.Sets/src/mage/cards/a/AidFromTheCowl.java b/Mage.Sets/src/mage/cards/a/AidFromTheCowl.java index 5490cd08939..81d8be69464 100644 --- a/Mage.Sets/src/mage/cards/a/AidFromTheCowl.java +++ b/Mage.Sets/src/mage/cards/a/AidFromTheCowl.java @@ -46,6 +46,7 @@ import mage.constants.Zone; import mage.filter.common.FilterPermanentCard; import mage.game.Game; import mage.players.Player; +import mage.watchers.common.RevoltWatcher; /** * @@ -53,17 +54,16 @@ import mage.players.Player; */ public class AidFromTheCowl extends CardImpl { - private static final String ruleText = "Revolt — At the beginning of your end step, if a permanent you controlled left the battlefield this turn, " + - "you may reveal the top card of your library. If it's a permanent card, you may put it onto the battlefield. Otherwise, put it on the bottom of your library."; + private static final String ruleText = "Revolt — At the beginning of your end step, if a permanent you controlled left the battlefield this turn, " + + "you may reveal the top card of your library. If it's a permanent card, you may put it onto the battlefield. Otherwise, put it on the bottom of your library."; public AidFromTheCowl(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{G}{G}"); - // Revolt — At the beginning of your end step, if a permanent you controlled left the battlefield this turn, // reveal the top card of your library. If it is a permanent card, you may put it onto the battlefield. Otherwise, put it on the bottom of your library. TriggeredAbility ability = new BeginningOfYourEndStepTriggeredAbility(new AidFromTheCowlEffect(), false); - this.addAbility(new ConditionalTriggeredAbility(ability, new RevoltCondition(), ruleText)); + this.addAbility(new ConditionalTriggeredAbility(ability, RevoltCondition.getInstance(), ruleText), new RevoltWatcher()); } public AidFromTheCowl(final AidFromTheCowl card) { diff --git a/Mage.Sets/src/mage/cards/c/CallForUnity.java b/Mage.Sets/src/mage/cards/c/CallForUnity.java index e9db569b7c5..cb45b1a0ebd 100644 --- a/Mage.Sets/src/mage/cards/c/CallForUnity.java +++ b/Mage.Sets/src/mage/cards/c/CallForUnity.java @@ -43,6 +43,7 @@ import mage.constants.Duration; import mage.constants.Zone; import mage.counters.CounterType; import mage.filter.common.FilterCreaturePermanent; +import mage.watchers.common.RevoltWatcher; /** * @@ -58,7 +59,7 @@ public class CallForUnity extends CardImpl { // Revolt — At the beginning of your end step, if a permanent you controlled left the battlefield this turn, put a unity counter on Call for Unity. TriggeredAbility ability = new BeginningOfYourEndStepTriggeredAbility(new AddCountersSourceEffect(CounterType.UNITY.createInstance(), true), false); - this.addAbility(new ConditionalTriggeredAbility(ability, new RevoltCondition(), ruleText)); + this.addAbility(new ConditionalTriggeredAbility(ability, RevoltCondition.getInstance(), ruleText), new RevoltWatcher()); // Creatures you control get +1/+1 for each unity counter on Call for Unity. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, diff --git a/Mage.Sets/src/mage/cards/s/SolemnRecruit.java b/Mage.Sets/src/mage/cards/s/SolemnRecruit.java index 698b3a2f1d6..f386813c24b 100644 --- a/Mage.Sets/src/mage/cards/s/SolemnRecruit.java +++ b/Mage.Sets/src/mage/cards/s/SolemnRecruit.java @@ -39,6 +39,7 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.counters.CounterType; +import mage.watchers.common.RevoltWatcher; /** * @@ -46,8 +47,8 @@ import mage.counters.CounterType; */ public class SolemnRecruit extends CardImpl { - private static final String ruleText = "Revolt — At the beginning of your end step, if a permanent you controlled left the battlefield this turn, " + - "put a +1/+1 counter on {this}."; + private static final String ruleText = "Revolt — At the beginning of your end step, if a permanent you controlled left the battlefield this turn, " + + "put a +1/+1 counter on {this}."; public SolemnRecruit(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}{W}"); @@ -62,7 +63,7 @@ public class SolemnRecruit extends CardImpl { // Revolt — At the beginning of your end step, if a permanent you controlled left the battlefield this turn, put a +1/+1 counter on Solemn Recruit. TriggeredAbility ability = new BeginningOfYourEndStepTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance()), false); - this.addAbility(new ConditionalTriggeredAbility(ability, new RevoltCondition(), ruleText)); + this.addAbility(new ConditionalTriggeredAbility(ability, RevoltCondition.getInstance(), ruleText), new RevoltWatcher()); } public SolemnRecruit(final SolemnRecruit card) { diff --git a/Mage.Sets/src/mage/cards/v/VengefulRebel.java b/Mage.Sets/src/mage/cards/v/VengefulRebel.java index 937e338c0f0..81f292df2f4 100644 --- a/Mage.Sets/src/mage/cards/v/VengefulRebel.java +++ b/Mage.Sets/src/mage/cards/v/VengefulRebel.java @@ -43,6 +43,7 @@ import mage.constants.TargetController; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.ControllerPredicate; import mage.target.common.TargetCreaturePermanent; +import mage.watchers.common.RevoltWatcher; /** * @@ -68,12 +69,12 @@ public class VengefulRebel extends CardImpl { // target creature an opponent controls gets -3/-3 until end of turn. Ability ability = new ConditionalTriggeredAbility( new EntersBattlefieldTriggeredAbility(new BoostTargetEffect(-3, -3, Duration.EndOfTurn), false), - new RevoltCondition(), + RevoltCondition.getInstance(), "When {this} enters the battlefield, if a permanent you controlled left the battlefield this turn, " + "target creature an opponent controls gets -3/-3 until end of turn"); ability.addTarget(new TargetCreaturePermanent(filter)); ability.setAbilityWord(AbilityWord.REVOLT); - this.addAbility(ability); + this.addAbility(ability, new RevoltWatcher()); } public VengefulRebel(final VengefulRebel card) { diff --git a/Mage/src/main/java/mage/abilities/condition/common/RevoltCondition.java b/Mage/src/main/java/mage/abilities/condition/common/RevoltCondition.java index 5b0f0aa4b94..5045c9c2c02 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/RevoltCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/RevoltCondition.java @@ -1,56 +1,56 @@ -/* - * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of BetaSteward_at_googlemail.com. - */ -package mage.abilities.condition.common; - -import mage.abilities.Ability; -import mage.abilities.condition.Condition; -import mage.game.Game; -import mage.watchers.common.RevoltWatcher; - -/** - * @author emerald000 - */ -public class RevoltCondition implements Condition { - - private static final RevoltCondition fInstance = new RevoltCondition(); - - public static Condition getInstance() { - return fInstance; - } - - @Override - public boolean apply(Game game, Ability source) { - RevoltWatcher watcher = (RevoltWatcher) game.getState().getWatchers().get("Revolt"); - return watcher.revoltActive(source.getControllerId()); - } - - @Override - public String toString() { - return "if a permanent you control left the battlefield this turn"; - } -} +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.abilities.condition.common; + +import mage.abilities.Ability; +import mage.abilities.condition.Condition; +import mage.game.Game; +import mage.watchers.common.RevoltWatcher; + +/** + * @author emerald000 + */ +public class RevoltCondition implements Condition { + + private static final RevoltCondition fInstance = new RevoltCondition(); + + public static Condition getInstance() { + return fInstance; + } + + @Override + public boolean apply(Game game, Ability source) { + RevoltWatcher watcher = (RevoltWatcher) game.getState().getWatchers().get("Revolt"); + return watcher != null && watcher.revoltActive(source.getControllerId()); + } + + @Override + public String toString() { + return "if a permanent you control left the battlefield this turn"; + } +} From b358597bf4c5399eb5dd74723bffbf9cc1689b47 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sat, 7 Jan 2017 21:42:29 +0100 Subject: [PATCH 05/19] [AER] Added the last missing cards. Some fixes. --- .../src/mage/cards/a/AirdropAeronauts.java | 154 ++++++++-------- .../src/mage/cards/e/EmbraalGearSmasher.java | 74 ++++++++ .../src/mage/cards/h/HopeOfGhirapur.java | 3 +- .../src/mage/cards/m/MerchantsDockhand.java | 172 ++++++++++++++++++ .../src/mage/cards/r/RenegadeRallier.java | 4 +- .../src/mage/cards/t/TezzeretsSimulacrum.java | 78 ++++++++ Mage.Sets/src/mage/sets/AetherRevolt.java | 3 + .../condition/common/RevoltCondition.java | 2 +- 8 files changed, 409 insertions(+), 81 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/e/EmbraalGearSmasher.java create mode 100644 Mage.Sets/src/mage/cards/m/MerchantsDockhand.java create mode 100644 Mage.Sets/src/mage/cards/t/TezzeretsSimulacrum.java diff --git a/Mage.Sets/src/mage/cards/a/AirdropAeronauts.java b/Mage.Sets/src/mage/cards/a/AirdropAeronauts.java index a369919cfa8..5a465870a76 100644 --- a/Mage.Sets/src/mage/cards/a/AirdropAeronauts.java +++ b/Mage.Sets/src/mage/cards/a/AirdropAeronauts.java @@ -1,78 +1,76 @@ -/* - * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of BetaSteward_at_googlemail.com. - */ -package mage.cards.a; - -import java.util.UUID; -import mage.MageInt; -import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.condition.common.RevoltCondition; -import mage.abilities.decorator.ConditionalOneShotEffect; -import mage.abilities.effects.common.GainLifeEffect; -import mage.abilities.keyword.FlyingAbility; -import mage.cards.CardImpl; -import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.watchers.common.RevoltWatcher; - -/** - * - * @author Styxo - */ -public class AirdropAeronauts extends CardImpl { - - public AirdropAeronauts(UUID ownerId, CardSetInfo setInfo) { - super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}{W}"); - - this.subtype.add("Dwarf"); - this.subtype.add("Scout"); - this.power = new MageInt(4); - this.toughness = new MageInt(3); - - // Flying - this.addAbility(FlyingAbility.getInstance()); - - // Revolt — When Airdrop Aeronauts enters the battlefield, if a permanent you controlled left the battlefield this turn, you gain 5 life. - this.addAbility( - new EntersBattlefieldTriggeredAbility( - new ConditionalOneShotEffect(new GainLifeEffect(5), RevoltCondition.getInstance()), - false, - "Revolt — " - ), - new RevoltWatcher() - ); - } - - public AirdropAeronauts(final AirdropAeronauts card) { - super(card); - } - - @Override - public AirdropAeronauts copy() { - return new AirdropAeronauts(this); - } -} +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.a; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.condition.common.RevoltCondition; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.AbilityWord; +import mage.constants.CardType; +import mage.watchers.common.RevoltWatcher; + +/** + * + * @author Styxo + */ +public class AirdropAeronauts extends CardImpl { + + public AirdropAeronauts(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}{W}"); + + this.subtype.add("Dwarf"); + this.subtype.add("Scout"); + this.power = new MageInt(4); + this.toughness = new MageInt(3); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Revolt — When Airdrop Aeronauts enters the battlefield, if a permanent you controlled left the battlefield this turn, you gain 5 life. + Ability ability = new EntersBattlefieldTriggeredAbility( + new ConditionalOneShotEffect(new GainLifeEffect(5), RevoltCondition.getInstance()), false); + ability.setAbilityWord(AbilityWord.REVOLT); + this.addAbility(ability, new RevoltWatcher()); + } + + public AirdropAeronauts(final AirdropAeronauts card) { + super(card); + } + + @Override + public AirdropAeronauts copy() { + return new AirdropAeronauts(this); + } +} diff --git a/Mage.Sets/src/mage/cards/e/EmbraalGearSmasher.java b/Mage.Sets/src/mage/cards/e/EmbraalGearSmasher.java new file mode 100644 index 00000000000..69eec96752c --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/EmbraalGearSmasher.java @@ -0,0 +1,74 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.e; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.common.DamagePlayersEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.filter.common.FilterControlledArtifactPermanent; +import mage.target.common.TargetControlledPermanent; + +/** + * + * @author LevelX2 + */ +public class EmbraalGearSmasher extends CardImpl { + + public EmbraalGearSmasher(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}"); + + this.subtype.add("Human"); + this.subtype.add("Warrior"); + this.power = new MageInt(2); + this.toughness = new MageInt(3); + + // {T}, Sacrifice an artifact: Embraal Gear-Smasher deals 2 damage to each opponent. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamagePlayersEffect(2, TargetController.OPPONENT), new TapSourceCost()); + ability.addCost(new SacrificeTargetCost(new TargetControlledPermanent(new FilterControlledArtifactPermanent("an artifact")))); + this.addAbility(ability); + + } + + public EmbraalGearSmasher(final EmbraalGearSmasher card) { + super(card); + } + + @Override + public EmbraalGearSmasher copy() { + return new EmbraalGearSmasher(this); + } +} diff --git a/Mage.Sets/src/mage/cards/h/HopeOfGhirapur.java b/Mage.Sets/src/mage/cards/h/HopeOfGhirapur.java index 396351dd1f6..0dfb3029ca5 100644 --- a/Mage.Sets/src/mage/cards/h/HopeOfGhirapur.java +++ b/Mage.Sets/src/mage/cards/h/HopeOfGhirapur.java @@ -75,6 +75,7 @@ public class HopeOfGhirapur extends CardImpl { // Sacrifice Hope of Ghirapur: Until your next turn, target player who was dealt combat damage by Hope of Ghirapur this turn can't cast noncreature spells. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new HopeOfGhirapurCantCastEffect(), new SacrificeSourceCost()); + ability.addTarget(new TargetPlayer()); this.addAbility(ability, new HopeOfGhirapurCombatDamageWatcher()); } @@ -162,7 +163,7 @@ class HopeOfGhirapurPlayerLostLifePredicate implements Predicate { @Override public boolean apply(Player input, Game game) { - HopeOfGhirapurCombatDamageWatcher watcher = (HopeOfGhirapurCombatDamageWatcher) game.getState().getWatchers().get(HopeOfGhirapurCombatDamageWatcher.class.getName(), sourceId); + HopeOfGhirapurCombatDamageWatcher watcher = (HopeOfGhirapurCombatDamageWatcher) game.getState().getWatchers().get(HopeOfGhirapurCombatDamageWatcher.class.getName()); if (watcher != null) { return watcher.playerGotCombatDamage(sourceId, input.getId()); } diff --git a/Mage.Sets/src/mage/cards/m/MerchantsDockhand.java b/Mage.Sets/src/mage/cards/m/MerchantsDockhand.java new file mode 100644 index 00000000000..643091b4f4e --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/MerchantsDockhand.java @@ -0,0 +1,172 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and 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.m; + +import java.util.UUID; +import mage.MageInt; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.Cost; +import mage.abilities.costs.VariableCostImpl; +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.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.cards.Cards; +import mage.cards.CardsImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.filter.common.FilterControlledArtifactPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.permanent.TappedPredicate; +import mage.game.Game; +import mage.players.Player; +import mage.target.TargetCard; +import mage.target.common.TargetControlledPermanent; + +/** + * + * @author LevelX2 + */ +public class MerchantsDockhand extends CardImpl { + + public MerchantsDockhand(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{1}"); + + this.subtype.add("Construct"); + this.power = new MageInt(1); + this.toughness = new MageInt(2); + + // {3}{U}, {T}, Tap X untapped artifacts you control: Look at the top X cards of your library. Put one of them into your hand and the rest on the bottom of your library in any order. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new MerchantsDockhandEffect(), new ManaCostsImpl<>("{3}{U}")); + ability.addCost(new TapSourceCost()); + ability.addCost(new TapXTargetCost()); + this.addAbility(ability); + } + + public MerchantsDockhand(final MerchantsDockhand card) { + super(card); + } + + @Override + public MerchantsDockhand copy() { + return new MerchantsDockhand(this); + } +} + +class MerchantsDockhandEffect extends OneShotEffect { + + public MerchantsDockhandEffect() { + super(Outcome.DrawCard); + this.staticText = "Look at the top X cards of your library. Put one of them into your hand and the rest on the bottom of your library in any order"; + } + + public MerchantsDockhandEffect(final MerchantsDockhandEffect effect) { + super(effect); + } + + @Override + public MerchantsDockhandEffect copy() { + return new MerchantsDockhandEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + MageObject sourceObject = game.getObject(source.getSourceId()); + if (controller == null || sourceObject == null) { + return false; + } + + int xValue = source.getManaCostsToPay().getX(); + + for (Cost cost : source.getCosts()) { + if (cost instanceof TapXTargetCost) { + xValue = ((TapXTargetCost) cost).getAmount(); + break; + } + } + + Cards cards = new CardsImpl(); + cards.addAll(controller.getLibrary().getTopCards(game, xValue)); + controller.lookAtCards(sourceObject.getIdName(), cards, game); + + TargetCard target = new TargetCard(Zone.LIBRARY, new FilterCard("card to put into your hand")); + target.setNotTarget(true); + if (controller.chooseTarget(Outcome.DrawCard, cards, target, source, game)) { + Card card = cards.get(target.getFirstTarget(), game); + if (card != null) { + controller.moveCards(card, Zone.HAND, source, game); + cards.remove(card); + } + } + controller.putCardsOnBottomOfLibrary(cards, game, source, true); + return true; + } +} + +class TapXTargetCost extends VariableCostImpl { + + public final static FilterControlledArtifactPermanent filter = new FilterControlledArtifactPermanent("untapped artifacts you control"); + + static { + filter.add(Predicates.not(new TappedPredicate())); + } + + public TapXTargetCost() { + super("controlled untapped artifacts you like to tap"); + this.text = "Tap X untapped artifacts you control"; + } + + public TapXTargetCost(final TapXTargetCost cost) { + super(cost); + } + + @Override + public TapXTargetCost copy() { + return new TapXTargetCost(this); + } + + @Override + public int getMaxValue(Ability source, Game game) { + return game.getBattlefield().count(filter, source.getSourceId(), source.getControllerId(), game); + } + + @Override + public Cost getFixedCostsFromAnnouncedValue(int xValue) { + TargetControlledPermanent target = new TargetControlledPermanent(xValue, xValue, filter, true); + return new TapTargetCost(target); + } + +} diff --git a/Mage.Sets/src/mage/cards/r/RenegadeRallier.java b/Mage.Sets/src/mage/cards/r/RenegadeRallier.java index 6d72e819084..a7ee43d9da9 100644 --- a/Mage.Sets/src/mage/cards/r/RenegadeRallier.java +++ b/Mage.Sets/src/mage/cards/r/RenegadeRallier.java @@ -36,6 +36,7 @@ import mage.abilities.decorator.ConditionalOneShotEffect; import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.AbilityWord; import mage.constants.CardType; import mage.filter.Filter; import mage.filter.common.FilterPermanentCard; @@ -67,7 +68,8 @@ public class RenegadeRallier extends CardImpl { // return target permanent card with converted mana cost 2 or less from your graveyard to your battlefield. Ability ability = new EntersBattlefieldTriggeredAbility( new ConditionalOneShotEffect(new ReturnFromGraveyardToBattlefieldTargetEffect(), RevoltCondition.getInstance()), - false, "Revolt — "); + false); + ability.setAbilityWord(AbilityWord.REVOLT); ability.addTarget(new TargetCardInYourGraveyard(filter)); ability.addWatcher(new RevoltWatcher()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/t/TezzeretsSimulacrum.java b/Mage.Sets/src/mage/cards/t/TezzeretsSimulacrum.java new file mode 100644 index 00000000000..31df0d66112 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TezzeretsSimulacrum.java @@ -0,0 +1,78 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.t; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.common.LoseLifeTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.filter.common.FilterPlaneswalkerPermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.target.common.TargetOpponent; + +/** + * + * @author LevelX2 + */ +public class TezzeretsSimulacrum extends CardImpl { + + public TezzeretsSimulacrum(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{3}"); + + this.subtype.add("Golem"); + this.power = new MageInt(2); + this.toughness = new MageInt(3); + + // {T}: Target opponent loses 1 life. If you control a Tezzeret planeswalker, that player loses 3 life instead. + FilterPlaneswalkerPermanent filter = new FilterPlaneswalkerPermanent(); + filter.add(new SubtypePredicate("Tezzeret")); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, + new ConditionalOneShotEffect(new LoseLifeTargetEffect(3), new LoseLifeTargetEffect(1), + new PermanentsOnTheBattlefieldCondition(filter), + "Target opponent loses 1 life. If you control a Tezzeret planeswalker, that player loses 3 life instead"), new TapSourceCost()); + ability.addTarget(new TargetOpponent()); + this.addAbility(ability); + } + + public TezzeretsSimulacrum(final TezzeretsSimulacrum card) { + super(card); + } + + @Override + public TezzeretsSimulacrum copy() { + return new TezzeretsSimulacrum(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AetherRevolt.java b/Mage.Sets/src/mage/sets/AetherRevolt.java index 22bbf59da5c..ffc92ca84ab 100644 --- a/Mage.Sets/src/mage/sets/AetherRevolt.java +++ b/Mage.Sets/src/mage/sets/AetherRevolt.java @@ -116,6 +116,7 @@ public class AetherRevolt extends ExpansionSet { cards.add(new SetCardInfo("Dispersal Technician", 32, Rarity.COMMON, mage.cards.d.DispersalTechnician.class)); cards.add(new SetCardInfo("Druid of the Cowl", 106, Rarity.COMMON, mage.cards.d.DruidOfTheCowl.class)); cards.add(new SetCardInfo("Efficient Construction", 33, Rarity.UNCOMMON, mage.cards.e.EfficientConstruction.class)); + cards.add(new SetCardInfo("Embraal Gear-Smasher", 79, Rarity.COMMON, mage.cards.e.EmbraalGearSmasher.class)); cards.add(new SetCardInfo("Enraged Giant", 80, Rarity.UNCOMMON, mage.cards.e.EnragedGiant.class)); cards.add(new SetCardInfo("Exquisite Archangel", 18, Rarity.MYTHIC, mage.cards.e.ExquisiteArchangel.class)); cards.add(new SetCardInfo("Fatal Push", 57, Rarity.UNCOMMON, mage.cards.f.FatalPush.class)); @@ -169,6 +170,7 @@ public class AetherRevolt extends ExpansionSet { cards.add(new SetCardInfo("Maulfist Revolutionary", 115, Rarity.UNCOMMON, mage.cards.m.MaulfistRevolutionary.class)); cards.add(new SetCardInfo("Maverick Thopterist", 130, Rarity.UNCOMMON, mage.cards.m.MaverickThopterist.class)); cards.add(new SetCardInfo("Mechanized Production", 38, Rarity.MYTHIC, mage.cards.m.MechanizedProduction.class)); + cards.add(new SetCardInfo("Merchant's Dockhand", 163, Rarity.RARE, mage.cards.m.MerchantsDockhand.class)); cards.add(new SetCardInfo("Metallic Mimic", 164, Rarity.RARE, mage.cards.m.MetallicMimic.class)); cards.add(new SetCardInfo("Metallic Rebuke", 39, Rarity.COMMON, mage.cards.m.MetallicRebuke.class)); cards.add(new SetCardInfo("Midnight Entourage", 66, Rarity.RARE, mage.cards.m.MidnightEntourage.class)); @@ -233,6 +235,7 @@ public class AetherRevolt extends ExpansionSet { cards.add(new SetCardInfo("Take into Custody", 47, Rarity.COMMON, mage.cards.t.TakeIntoCustody.class)); cards.add(new SetCardInfo("Tezzeret the Schemer", 137, Rarity.MYTHIC, mage.cards.t.TezzeretTheSchemer.class)); cards.add(new SetCardInfo("Tezzeret's Betrayal", 191, Rarity.RARE, mage.cards.t.TezzeretsBetrayal.class)); + cards.add(new SetCardInfo("Tezzeret's Simulacrum", 193, Rarity.UNCOMMON, mage.cards.t.TezzeretsSimulacrum.class)); cards.add(new SetCardInfo("Tezzeret's Touch", 138, Rarity.UNCOMMON, mage.cards.t.TezzeretsTouch.class)); cards.add(new SetCardInfo("Tezzeret, Master of Metal", 190, Rarity.MYTHIC, mage.cards.t.TezzeretMasterOfMetal.class)); cards.add(new SetCardInfo("Thopter Arrest", 25, Rarity.UNCOMMON, mage.cards.t.ThopterArrest.class)); diff --git a/Mage/src/main/java/mage/abilities/condition/common/RevoltCondition.java b/Mage/src/main/java/mage/abilities/condition/common/RevoltCondition.java index 5045c9c2c02..799a7362f7c 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/RevoltCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/RevoltCondition.java @@ -51,6 +51,6 @@ public class RevoltCondition implements Condition { @Override public String toString() { - return "if a permanent you control left the battlefield this turn"; + return "a permanent you control left the battlefield this turn"; } } From d519aa55c12ddd2424327b431631fc3d790dc23d Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sat, 7 Jan 2017 21:58:34 +0100 Subject: [PATCH 06/19] [AER] Fixed wrong revolt tool tips. --- Mage.Sets/src/mage/cards/a/AirdropAeronauts.java | 4 +--- Mage.Sets/src/mage/cards/r/RenegadeRallier.java | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/Mage.Sets/src/mage/cards/a/AirdropAeronauts.java b/Mage.Sets/src/mage/cards/a/AirdropAeronauts.java index 5a465870a76..b2806a5ab4a 100644 --- a/Mage.Sets/src/mage/cards/a/AirdropAeronauts.java +++ b/Mage.Sets/src/mage/cards/a/AirdropAeronauts.java @@ -37,7 +37,6 @@ import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.AbilityWord; import mage.constants.CardType; import mage.watchers.common.RevoltWatcher; @@ -60,8 +59,7 @@ public class AirdropAeronauts extends CardImpl { // Revolt — When Airdrop Aeronauts enters the battlefield, if a permanent you controlled left the battlefield this turn, you gain 5 life. Ability ability = new EntersBattlefieldTriggeredAbility( - new ConditionalOneShotEffect(new GainLifeEffect(5), RevoltCondition.getInstance()), false); - ability.setAbilityWord(AbilityWord.REVOLT); + new ConditionalOneShotEffect(new GainLifeEffect(5), RevoltCondition.getInstance()), false, "Revolt — "); this.addAbility(ability, new RevoltWatcher()); } diff --git a/Mage.Sets/src/mage/cards/r/RenegadeRallier.java b/Mage.Sets/src/mage/cards/r/RenegadeRallier.java index a7ee43d9da9..6d72e819084 100644 --- a/Mage.Sets/src/mage/cards/r/RenegadeRallier.java +++ b/Mage.Sets/src/mage/cards/r/RenegadeRallier.java @@ -36,7 +36,6 @@ import mage.abilities.decorator.ConditionalOneShotEffect; import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.AbilityWord; import mage.constants.CardType; import mage.filter.Filter; import mage.filter.common.FilterPermanentCard; @@ -68,8 +67,7 @@ public class RenegadeRallier extends CardImpl { // return target permanent card with converted mana cost 2 or less from your graveyard to your battlefield. Ability ability = new EntersBattlefieldTriggeredAbility( new ConditionalOneShotEffect(new ReturnFromGraveyardToBattlefieldTargetEffect(), RevoltCondition.getInstance()), - false); - ability.setAbilityWord(AbilityWord.REVOLT); + false, "Revolt — "); ability.addTarget(new TargetCardInYourGraveyard(filter)); ability.addWatcher(new RevoltWatcher()); this.addAbility(ability); From 9353c5aa9c16aae6ff97948b919a17906f079876 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sat, 7 Jan 2017 22:22:17 +0100 Subject: [PATCH 07/19] [AER] Some more minor fixes. --- .../dl/sources/MythicspoilerComSource.java | 29 +- Mage.Common/src/mage/utils/MageVersion.java | 2 +- ...ndKingRaiders.java => WindKinRaiders.java} | 10 +- Mage.Sets/src/mage/sets/AetherRevolt.java | 548 +++++++++--------- .../mage/cards/repository/CardRepository.java | 11 +- 5 files changed, 299 insertions(+), 301 deletions(-) rename Mage.Sets/src/mage/cards/w/{WindKingRaiders.java => WindKinRaiders.java} (90%) diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MythicspoilerComSource.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MythicspoilerComSource.java index d6f17bb5bca..3611c81a633 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MythicspoilerComSource.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MythicspoilerComSource.java @@ -91,6 +91,8 @@ public class MythicspoilerComSource implements CardImageSource { cardNameAliases.put("BFZ-kozliekschanneler", "kozilekschanneler"); cardNameAliases.put("OGW-wastes", "wastes1"); cardNameAliases.put("OGW-wastes2", "wastes2"); + cardNameAliases.put("AER-locketofmyths", "lifecraftersbestiary"); + cardNameAliases.put("AER-aegisautomation", "aegisautomaton"); cardNameAliasesStart = new HashMap<>(); HashSet names = new HashSet<>(); @@ -123,8 +125,7 @@ public class MythicspoilerComSource implements CardImageSource { String doubleFacedUrl = baseUrl + "dfc.html"; pageLinks = getSetLinksFromPage(cardSet, aliasesStart, prefs, proxyType, baseUrl, doubleFacedUrl); setLinks.putAll(pageLinks); - } - catch (Exception ex) { + } catch (Exception ex) { // that's ok if we cannot download double-faced cards for some sets } } @@ -136,7 +137,7 @@ public class MythicspoilerComSource implements CardImageSource { } private Map getSetLinksFromPage(String cardSet, Set aliasesStart, Preferences prefs, - ProxyType proxyType, String baseUrl, String pageUrl) throws IOException { + ProxyType proxyType, String baseUrl, String pageUrl) throws IOException { Map pageLinks = new HashMap<>(); String urlDocument; @@ -181,16 +182,14 @@ public class MythicspoilerComSource implements CardImageSource { if (cardName != null && !cardName.isEmpty()) { if (cardNameAliases.containsKey(cardSet + "-" + cardName)) { cardName = cardNameAliases.get(cardSet + "-" + cardName); - } else { - if (cardName.endsWith("1") || cardName.endsWith("2") || cardName.endsWith("3") || cardName.endsWith("4") || cardName.endsWith("5")) { - if (!cardName.startsWith("forest") - && !cardName.startsWith("swamp") - && !cardName.startsWith("mountain") - && !cardName.startsWith("island") - && !cardName.startsWith("plains")) { + } else if (cardName.endsWith("1") || cardName.endsWith("2") || cardName.endsWith("3") || cardName.endsWith("4") || cardName.endsWith("5")) { + if (!cardName.startsWith("forest") + && !cardName.startsWith("swamp") + && !cardName.startsWith("mountain") + && !cardName.startsWith("island") + && !cardName.startsWith("plains")) { - cardName = cardName.substring(0, cardName.length() - 1); - } + cardName = cardName.substring(0, cardName.length() - 1); } } pageLinks.put(cardName, baseUrl + cardLink); @@ -244,17 +243,17 @@ public class MythicspoilerComSource implements CardImageSource { public String getFileForHttpImage(String httpImageUrl) { return null; } - + @Override public Integer getTotalImages() { return -1; } - + @Override public Boolean isTokenSource() { return false; } - + @Override public void doPause(String httpImageUrl) { } diff --git a/Mage.Common/src/mage/utils/MageVersion.java b/Mage.Common/src/mage/utils/MageVersion.java index 36aef1694a8..968fae23493 100644 --- a/Mage.Common/src/mage/utils/MageVersion.java +++ b/Mage.Common/src/mage/utils/MageVersion.java @@ -41,7 +41,7 @@ public class MageVersion implements Serializable, Comparable { public final static int MAGE_VERSION_MAJOR = 1; public final static int MAGE_VERSION_MINOR = 4; public final static int MAGE_VERSION_PATCH = 19; - public final static String MAGE_VERSION_MINOR_PATCH = "V1"; + public final static String MAGE_VERSION_MINOR_PATCH = "V2"; public final static String MAGE_VERSION_INFO = ""; private final int major; diff --git a/Mage.Sets/src/mage/cards/w/WindKingRaiders.java b/Mage.Sets/src/mage/cards/w/WindKinRaiders.java similarity index 90% rename from Mage.Sets/src/mage/cards/w/WindKingRaiders.java rename to Mage.Sets/src/mage/cards/w/WindKinRaiders.java index 7bda35a8a3c..758fdba14cc 100644 --- a/Mage.Sets/src/mage/cards/w/WindKingRaiders.java +++ b/Mage.Sets/src/mage/cards/w/WindKinRaiders.java @@ -39,9 +39,9 @@ import mage.constants.CardType; * * @author fireshoes */ -public class WindKingRaiders extends CardImpl { +public class WindKinRaiders extends CardImpl { - public WindKingRaiders(UUID ownerId, CardSetInfo setInfo) { + public WindKinRaiders(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{U}{U}"); this.subtype.add("Human"); @@ -56,12 +56,12 @@ public class WindKingRaiders extends CardImpl { this.addAbility(FlyingAbility.getInstance()); } - public WindKingRaiders(final WindKingRaiders card) { + public WindKinRaiders(final WindKinRaiders card) { super(card); } @Override - public WindKingRaiders copy() { - return new WindKingRaiders(this); + public WindKinRaiders copy() { + return new WindKinRaiders(this); } } diff --git a/Mage.Sets/src/mage/sets/AetherRevolt.java b/Mage.Sets/src/mage/sets/AetherRevolt.java index ffc92ca84ab..d1d810f1701 100644 --- a/Mage.Sets/src/mage/sets/AetherRevolt.java +++ b/Mage.Sets/src/mage/sets/AetherRevolt.java @@ -1,274 +1,274 @@ -/* - * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and 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 java.util.ArrayList; -import java.util.List; -import mage.cards.ExpansionSet; -import mage.cards.repository.CardCriteria; -import mage.cards.repository.CardInfo; -import mage.cards.repository.CardRepository; -import mage.constants.Rarity; -import mage.constants.SetType; - -/** - * - * @author fireshoes - */ -public class AetherRevolt extends ExpansionSet { - - private static final AetherRevolt fINSTANCE = new AetherRevolt(); - - public static AetherRevolt getInstance() { - return fINSTANCE; - } - - protected final List savedSpecialLand = new ArrayList<>(); - - private AetherRevolt() { - super("Aether Revolt", "AER", ExpansionSet.buildDate(2017, 1, 20), SetType.EXPANSION); - this.blockName = "Kaladesh"; - this.hasBoosters = true; - this.hasBasicLands = false; - this.numBoosterLands = 1; - this.numBoosterCommon = 10; - this.numBoosterUncommon = 3; - this.numBoosterRare = 1; - this.ratioBoosterMythic = 8; - this.maxCardNumberInBooster = 184; - this.ratioBoosterSpecialLand = 144; - this.parentSet = Kaladesh.getInstance(); - cards.add(new SetCardInfo("Aegis Automaton", 141, Rarity.COMMON, mage.cards.a.AegisAutomaton.class)); - cards.add(new SetCardInfo("Aerial Modification", 1, Rarity.UNCOMMON, mage.cards.a.AerialModification.class)); - cards.add(new SetCardInfo("Aeronaut Admiral", 2, Rarity.UNCOMMON, mage.cards.a.AeronautAdmiral.class)); - cards.add(new SetCardInfo("Aether Chaser", 76, Rarity.COMMON, mage.cards.a.AetherChaser.class)); - cards.add(new SetCardInfo("Aether Herder", 102, Rarity.COMMON, mage.cards.a.AetherHerder.class)); - cards.add(new SetCardInfo("Aether Inspector", 3, Rarity.COMMON, mage.cards.a.AetherInspector.class)); - cards.add(new SetCardInfo("Aether Poisoner", 51, Rarity.COMMON, mage.cards.a.AetherPoisoner.class)); - cards.add(new SetCardInfo("Aether Swooper", 26, Rarity.COMMON, mage.cards.a.AetherSwooper.class)); - cards.add(new SetCardInfo("Aethergeode Miner", 4, Rarity.RARE, mage.cards.a.AethergeodeMiner.class)); - cards.add(new SetCardInfo("Aethersphere Harvester", 142, Rarity.RARE, mage.cards.a.AethersphereHarvester.class)); - cards.add(new SetCardInfo("Aetherstream Leopard", 103, Rarity.COMMON, mage.cards.a.AetherstreamLeopard.class)); - cards.add(new SetCardInfo("Aethertide Whale", 27, Rarity.RARE, mage.cards.a.AethertideWhale.class)); - cards.add(new SetCardInfo("Aetherwind Basker", 104, Rarity.MYTHIC, mage.cards.a.AetherwindBasker.class)); - cards.add(new SetCardInfo("Aid from the Cowl", 105, Rarity.RARE, mage.cards.a.AidFromTheCowl.class)); - cards.add(new SetCardInfo("Airdrop Aeronauts", 5, Rarity.UNCOMMON, mage.cards.a.AirdropAeronauts.class)); - cards.add(new SetCardInfo("Ajani Unyielding", 127, Rarity.MYTHIC, mage.cards.a.AjaniUnyielding.class)); - cards.add(new SetCardInfo("Ajani's Aid", 188, Rarity.RARE, mage.cards.a.AjanisAid.class)); - cards.add(new SetCardInfo("Ajani's Comrade", 187, Rarity.UNCOMMON, mage.cards.a.AjanisComrade.class)); - cards.add(new SetCardInfo("Ajani, Valiant Protector", 185, Rarity.MYTHIC, mage.cards.a.AjaniValiantProtector.class)); - cards.add(new SetCardInfo("Alley Evasion", 6, Rarity.COMMON, mage.cards.a.AlleyEvasion.class)); - cards.add(new SetCardInfo("Alley Strangler", 52, Rarity.COMMON, mage.cards.a.AlleyStrangler.class)); - cards.add(new SetCardInfo("Audacious Infiltrator", 7, Rarity.COMMON, mage.cards.a.AudaciousInfiltrator.class)); - cards.add(new SetCardInfo("Augmenting Automaton", 143, Rarity.COMMON, mage.cards.a.AugmentingAutomaton.class)); - cards.add(new SetCardInfo("Baral's Expertise", 29, Rarity.RARE, mage.cards.b.BaralsExpertise.class)); - cards.add(new SetCardInfo("Baral, Chief of Compliance", 28, Rarity.RARE, mage.cards.b.BaralChiefOfCompliance.class)); - cards.add(new SetCardInfo("Barricade Breaker", 144, Rarity.UNCOMMON, mage.cards.b.BarricadeBreaker.class)); - cards.add(new SetCardInfo("Bastion Enforcer", 8, Rarity.COMMON, mage.cards.b.BastionEnforcer.class)); - cards.add(new SetCardInfo("Bastion Inventor", 30, Rarity.COMMON, mage.cards.b.BastionInventor.class)); - cards.add(new SetCardInfo("Battle at the Bridge", 53, Rarity.RARE, mage.cards.b.BattleAtTheBridge.class)); - cards.add(new SetCardInfo("Call for Unity", 9, Rarity.RARE, mage.cards.c.CallForUnity.class)); - cards.add(new SetCardInfo("Caught in the Brights", 10, Rarity.COMMON, mage.cards.c.CaughtInTheBrights.class)); - cards.add(new SetCardInfo("Chandra's Revolution", 77, Rarity.COMMON, mage.cards.c.ChandrasRevolution.class)); - cards.add(new SetCardInfo("Cogwork Assembler", 145, Rarity.UNCOMMON, mage.cards.c.CogworkAssembler.class)); - cards.add(new SetCardInfo("Consulate Crackdown", 11, Rarity.RARE, mage.cards.c.ConsulateCrackdown.class)); - cards.add(new SetCardInfo("Consulate Dreadnought", 146, Rarity.UNCOMMON, mage.cards.c.ConsulateDreadnought.class)); - cards.add(new SetCardInfo("Consulate Turret", 147, Rarity.COMMON, mage.cards.c.ConsulateTurret.class)); - cards.add(new SetCardInfo("Conviction", 12, Rarity.COMMON, mage.cards.c.Conviction.class)); - cards.add(new SetCardInfo("Countless Gears Renegade", 13, Rarity.COMMON, mage.cards.c.CountlessGearsRenegade.class)); - cards.add(new SetCardInfo("Crackdown Construct", 148, Rarity.UNCOMMON, mage.cards.c.CrackdownConstruct.class)); - cards.add(new SetCardInfo("Cruel Finality", 54, Rarity.COMMON, mage.cards.c.CruelFinality.class)); - cards.add(new SetCardInfo("Daredevil Dragster", 149, Rarity.UNCOMMON, mage.cards.d.DaredevilDragster.class)); - cards.add(new SetCardInfo("Daring Demolition", 55, Rarity.COMMON, mage.cards.d.DaringDemolition.class)); - cards.add(new SetCardInfo("Dark Intimations", 128, Rarity.RARE, mage.cards.d.DarkIntimations.class)); - cards.add(new SetCardInfo("Dawnfeather Eagle", 14, Rarity.COMMON, mage.cards.d.DawnfeatherEagle.class)); - cards.add(new SetCardInfo("Deadeye Harpooner", 15, Rarity.UNCOMMON, mage.cards.d.DeadeyeHarpooner.class)); - cards.add(new SetCardInfo("Decommission", 16, Rarity.COMMON, mage.cards.d.Decommission.class)); - cards.add(new SetCardInfo("Defiant Salvager", 56, Rarity.COMMON, mage.cards.d.DefiantSalvager.class)); - cards.add(new SetCardInfo("Deft Dismissal", 17, Rarity.UNCOMMON, mage.cards.d.DeftDismissal.class)); - cards.add(new SetCardInfo("Destructive Tampering", 78, Rarity.COMMON, mage.cards.d.DestructiveTampering.class)); - cards.add(new SetCardInfo("Disallow", 31, Rarity.RARE, mage.cards.d.Disallow.class)); - cards.add(new SetCardInfo("Dispersal Technician", 32, Rarity.COMMON, mage.cards.d.DispersalTechnician.class)); - cards.add(new SetCardInfo("Druid of the Cowl", 106, Rarity.COMMON, mage.cards.d.DruidOfTheCowl.class)); - cards.add(new SetCardInfo("Efficient Construction", 33, Rarity.UNCOMMON, mage.cards.e.EfficientConstruction.class)); - cards.add(new SetCardInfo("Embraal Gear-Smasher", 79, Rarity.COMMON, mage.cards.e.EmbraalGearSmasher.class)); - cards.add(new SetCardInfo("Enraged Giant", 80, Rarity.UNCOMMON, mage.cards.e.EnragedGiant.class)); - cards.add(new SetCardInfo("Exquisite Archangel", 18, Rarity.MYTHIC, mage.cards.e.ExquisiteArchangel.class)); - cards.add(new SetCardInfo("Fatal Push", 57, Rarity.UNCOMMON, mage.cards.f.FatalPush.class)); - cards.add(new SetCardInfo("Felidar Guardian", 19, Rarity.UNCOMMON, mage.cards.f.FelidarGuardian.class)); - cards.add(new SetCardInfo("Fen Hauler", 58, Rarity.COMMON, mage.cards.f.FenHauler.class)); - cards.add(new SetCardInfo("Filigree Crawler", 150, Rarity.COMMON, mage.cards.f.FiligreeCrawler.class)); - cards.add(new SetCardInfo("Foundry Assembler", 151, Rarity.COMMON, mage.cards.f.FoundryAssembler.class)); - cards.add(new SetCardInfo("Foundry Hornet", 59, Rarity.UNCOMMON, mage.cards.f.FoundryHornet.class)); - cards.add(new SetCardInfo("Fourth Bridge Prowler", 60, Rarity.COMMON, mage.cards.f.FourthBridgeProwler.class)); - cards.add(new SetCardInfo("Freejam Regent", 81, Rarity.RARE, mage.cards.f.FreejamRegent.class)); - cards.add(new SetCardInfo("Frontline Rebel", 82, Rarity.COMMON, mage.cards.f.FrontlineRebel.class)); - cards.add(new SetCardInfo("Ghirapur Osprey", 20, Rarity.COMMON, mage.cards.g.GhirapurOsprey.class)); - cards.add(new SetCardInfo("Gifted Aetherborn", 61, Rarity.UNCOMMON, mage.cards.g.GiftedAetherborn.class)); - cards.add(new SetCardInfo("Glint-Sleeve Siphoner", 62, Rarity.RARE, mage.cards.g.GlintSleeveSiphoner.class)); - cards.add(new SetCardInfo("Gonti's Aether Heart", 152, Rarity.MYTHIC, mage.cards.g.GontisAetherHeart.class)); - cards.add(new SetCardInfo("Gonti's Machinations", 63, Rarity.UNCOMMON, mage.cards.g.GontisMachinations.class)); - cards.add(new SetCardInfo("Greenbelt Rampager", 107, Rarity.RARE, mage.cards.g.GreenbeltRampager.class)); - cards.add(new SetCardInfo("Greenwheel Liberator", 108, Rarity.RARE, mage.cards.g.GreenwheelLiberator.class)); - cards.add(new SetCardInfo("Gremlin Infestation", 83, Rarity.UNCOMMON, mage.cards.g.GremlinInfestation.class)); - cards.add(new SetCardInfo("Heart of Kiran", 153, Rarity.MYTHIC, mage.cards.h.HeartOfKiran.class)); - cards.add(new SetCardInfo("Herald of Anguish", 64, Rarity.MYTHIC, mage.cards.h.HeraldOfAnguish.class)); - cards.add(new SetCardInfo("Heroic Intervention", 109, Rarity.RARE, mage.cards.h.HeroicIntervention.class)); - cards.add(new SetCardInfo("Hidden Herbalists", 110, Rarity.UNCOMMON, mage.cards.h.HiddenHerbalists.class)); - cards.add(new SetCardInfo("Hidden Stockpile", 129, Rarity.UNCOMMON, mage.cards.h.HiddenStockpile.class)); - cards.add(new SetCardInfo("Highspire Infusion", 111, Rarity.COMMON, mage.cards.h.HighspireInfusion.class)); - cards.add(new SetCardInfo("Hinterland Drake", 34, Rarity.COMMON, mage.cards.h.HinterlandDrake.class)); - cards.add(new SetCardInfo("Hope of Ghirapur", 154, Rarity.RARE, mage.cards.h.HopeOfGhirapur.class)); - cards.add(new SetCardInfo("Hungry Flames", 84, Rarity.UNCOMMON, mage.cards.h.HungryFlames.class)); - cards.add(new SetCardInfo("Ice Over", 35, Rarity.COMMON, mage.cards.i.IceOver.class)); - cards.add(new SetCardInfo("Illusionist's Stratagem", 36, Rarity.UNCOMMON, mage.cards.i.IllusionistsStratagem.class)); - cards.add(new SetCardInfo("Implement of Combustion", 155, Rarity.COMMON, mage.cards.i.ImplementOfCombustion.class)); - cards.add(new SetCardInfo("Implement of Examination", 156, Rarity.COMMON, mage.cards.i.ImplementOfExamination.class)); - cards.add(new SetCardInfo("Implement of Ferocity", 157, Rarity.COMMON, mage.cards.i.ImplementOfFerocity.class)); - cards.add(new SetCardInfo("Implement of Improvement", 158, Rarity.COMMON, mage.cards.i.ImplementOfImprovement.class)); - cards.add(new SetCardInfo("Implement of Malice", 159, Rarity.COMMON, mage.cards.i.ImplementOfMalice.class)); - cards.add(new SetCardInfo("Indomitable Creativity", 85, Rarity.MYTHIC, mage.cards.i.IndomitableCreativity.class)); - cards.add(new SetCardInfo("Inspiring Roar", 186, Rarity.COMMON, mage.cards.i.InspiringRoar.class)); - cards.add(new SetCardInfo("Inspiring Statuary", 160, Rarity.RARE, mage.cards.i.InspiringStatuary.class)); - cards.add(new SetCardInfo("Invigorated Rampage", 86, Rarity.UNCOMMON, mage.cards.i.InvigoratedRampage.class)); - cards.add(new SetCardInfo("Ironclad Revolutionary", 65, Rarity.UNCOMMON, mage.cards.i.IroncladRevolutionary.class)); - cards.add(new SetCardInfo("Irontread Crusher", 161, Rarity.COMMON, mage.cards.i.IrontreadCrusher.class)); - cards.add(new SetCardInfo("Kari Zev's Expertise", 88, Rarity.RARE, mage.cards.k.KariZevsExpertise.class)); - cards.add(new SetCardInfo("Kari Zev, Skyship Raider", 87, Rarity.RARE, mage.cards.k.KariZevSkyshipRaider.class)); - cards.add(new SetCardInfo("Lathnu Sailback", 89, Rarity.COMMON, mage.cards.l.LathnuSailback.class)); - cards.add(new SetCardInfo("Leave in the Dust", 37, Rarity.COMMON, mage.cards.l.LeaveInTheDust.class)); - cards.add(new SetCardInfo("Lifecraft Awakening", 112, Rarity.UNCOMMON, mage.cards.l.LifecraftAwakening.class)); - cards.add(new SetCardInfo("Lifecraft Cavalry", 113, Rarity.COMMON, mage.cards.l.LifecraftCavalry.class)); - cards.add(new SetCardInfo("Lifecrafter's Bestiary", 162, Rarity.RARE, mage.cards.l.LifecraftersBestiary.class)); - cards.add(new SetCardInfo("Lifecrafter's Gift", 114, Rarity.UNCOMMON, mage.cards.l.LifecraftersGift.class)); - cards.add(new SetCardInfo("Lightning Runner", 90, Rarity.MYTHIC, mage.cards.l.LightningRunner.class)); - cards.add(new SetCardInfo("Maulfist Revolutionary", 115, Rarity.UNCOMMON, mage.cards.m.MaulfistRevolutionary.class)); - cards.add(new SetCardInfo("Maverick Thopterist", 130, Rarity.UNCOMMON, mage.cards.m.MaverickThopterist.class)); - cards.add(new SetCardInfo("Mechanized Production", 38, Rarity.MYTHIC, mage.cards.m.MechanizedProduction.class)); - cards.add(new SetCardInfo("Merchant's Dockhand", 163, Rarity.RARE, mage.cards.m.MerchantsDockhand.class)); - cards.add(new SetCardInfo("Metallic Mimic", 164, Rarity.RARE, mage.cards.m.MetallicMimic.class)); - cards.add(new SetCardInfo("Metallic Rebuke", 39, Rarity.COMMON, mage.cards.m.MetallicRebuke.class)); - cards.add(new SetCardInfo("Midnight Entourage", 66, Rarity.RARE, mage.cards.m.MidnightEntourage.class)); - cards.add(new SetCardInfo("Mobile Garrison", 165, Rarity.COMMON, mage.cards.m.MobileGarrison.class)); - cards.add(new SetCardInfo("Monstrous Onslaught", 116, Rarity.UNCOMMON, mage.cards.m.MonstrousOnslaught.class)); - cards.add(new SetCardInfo("Narnam Renegade", 117, Rarity.UNCOMMON, mage.cards.n.NarnamRenegade.class)); - cards.add(new SetCardInfo("Natural Obsolescence", 118, Rarity.COMMON, mage.cards.n.NaturalObsolescence.class)); - cards.add(new SetCardInfo("Negate", 40, Rarity.COMMON, mage.cards.n.Negate.class)); - cards.add(new SetCardInfo("Night Market Aeronaut", 67, Rarity.COMMON, mage.cards.n.NightMarketAeronaut.class)); - cards.add(new SetCardInfo("Night Market Guard", 166, Rarity.COMMON, mage.cards.n.NightMarketGuard.class)); - cards.add(new SetCardInfo("Oath of Ajani", 131, Rarity.RARE, mage.cards.o.OathOfAjani.class)); - cards.add(new SetCardInfo("Ornithopter", 167, Rarity.UNCOMMON, mage.cards.o.Ornithopter.class)); - cards.add(new SetCardInfo("Outland Boar", 132, Rarity.UNCOMMON, mage.cards.o.OutlandBoar.class)); - cards.add(new SetCardInfo("Pacification Array", 168, Rarity.UNCOMMON, mage.cards.p.PacificationArray.class)); - cards.add(new SetCardInfo("Paradox Engine", 169, Rarity.MYTHIC, mage.cards.p.ParadoxEngine.class)); - cards.add(new SetCardInfo("Peacewalker Colossus", 170, Rarity.RARE, mage.cards.p.PeacewalkerColossus.class)); - cards.add(new SetCardInfo("Peema Aether-Seer", 119, Rarity.UNCOMMON, mage.cards.p.PeemaAetherSeer.class)); - cards.add(new SetCardInfo("Pendulum of Patterns", 192, Rarity.COMMON, mage.cards.p.PendulumOfPatterns.class)); - cards.add(new SetCardInfo("Perilous Predicament", 68, Rarity.UNCOMMON, mage.cards.p.PerilousPredicament.class)); - cards.add(new SetCardInfo("Pia's Revolution", 91, Rarity.RARE, mage.cards.p.PiasRevolution.class)); - cards.add(new SetCardInfo("Planar Bridge", 171, Rarity.MYTHIC, mage.cards.p.PlanarBridge.class)); - cards.add(new SetCardInfo("Precise Strike", 92, Rarity.COMMON, mage.cards.p.PreciseStrike.class)); - cards.add(new SetCardInfo("Prey Upon", 120, Rarity.COMMON, mage.cards.p.PreyUpon.class)); - cards.add(new SetCardInfo("Prizefighter Construct", 172, Rarity.COMMON, mage.cards.p.PrizefighterConstruct.class)); - cards.add(new SetCardInfo("Quicksmith Rebel", 93, Rarity.RARE, mage.cards.q.QuicksmithRebel.class)); - cards.add(new SetCardInfo("Quicksmith Spy", 41, Rarity.RARE, mage.cards.q.QuicksmithSpy.class)); - cards.add(new SetCardInfo("Ravenous Intruder", 94, Rarity.UNCOMMON, mage.cards.r.RavenousIntruder.class)); - cards.add(new SetCardInfo("Reckless Racer", 95, Rarity.UNCOMMON, mage.cards.r.RecklessRacer.class)); - cards.add(new SetCardInfo("Release the Gremlins", 96, Rarity.RARE, mage.cards.r.ReleaseTheGremlins.class)); - cards.add(new SetCardInfo("Renegade Map", 173, Rarity.COMMON, mage.cards.r.RenegadeMap.class)); - cards.add(new SetCardInfo("Renegade Rallier", 133, Rarity.UNCOMMON, mage.cards.r.RenegadeRallier.class)); - cards.add(new SetCardInfo("Renegade Wheelsmith", 134, Rarity.UNCOMMON, mage.cards.r.RenegadeWheelsmith.class)); - cards.add(new SetCardInfo("Renegade's Getaway", 69, Rarity.COMMON, mage.cards.r.RenegadesGetaway.class)); - cards.add(new SetCardInfo("Reservoir Walker", 174, Rarity.COMMON, mage.cards.r.ReservoirWalker.class)); - cards.add(new SetCardInfo("Resourceful Return", 70, Rarity.COMMON, mage.cards.r.ResourcefulReturn.class)); - cards.add(new SetCardInfo("Restoration Specialist", 21, Rarity.UNCOMMON, mage.cards.r.RestorationSpecialist.class)); - cards.add(new SetCardInfo("Reverse Engineer", 42, Rarity.UNCOMMON, mage.cards.r.ReverseEngineer.class)); - cards.add(new SetCardInfo("Ridgescale Tusker", 121, Rarity.UNCOMMON, mage.cards.r.RidgescaleTusker.class)); - cards.add(new SetCardInfo("Rishkar's Expertise", 123, Rarity.RARE, mage.cards.r.RishkarsExpertise.class)); - cards.add(new SetCardInfo("Rishkar, Peema Renegade", 122, Rarity.RARE, mage.cards.r.RishkarPeemaRenegade.class)); - cards.add(new SetCardInfo("Rogue Refiner", 135, Rarity.UNCOMMON, mage.cards.r.RogueRefiner.class)); - cards.add(new SetCardInfo("Salvage Scuttler", 43, Rarity.UNCOMMON, mage.cards.s.SalvageScuttler.class)); - cards.add(new SetCardInfo("Scrap Trawler", 175, Rarity.RARE, mage.cards.s.ScrapTrawler.class)); - cards.add(new SetCardInfo("Scrapper Champion", 97, Rarity.UNCOMMON, mage.cards.s.ScrapperChampion.class)); - cards.add(new SetCardInfo("Scrounging Bandar", 124, Rarity.COMMON, mage.cards.s.ScroungingBandar.class)); - cards.add(new SetCardInfo("Secret Salvage", 71, Rarity.RARE, mage.cards.s.SecretSalvage.class)); - cards.add(new SetCardInfo("Servo Schematic", 176, Rarity.UNCOMMON, mage.cards.s.ServoSchematic.class)); - cards.add(new SetCardInfo("Shielded Aether Thief", 44, Rarity.UNCOMMON, mage.cards.s.ShieldedAetherThief.class)); - cards.add(new SetCardInfo("Shipwreck Moray", 45, Rarity.COMMON, mage.cards.s.ShipwreckMoray.class)); - cards.add(new SetCardInfo("Shock", 98, Rarity.COMMON, mage.cards.s.Shock.class)); - cards.add(new SetCardInfo("Siege Modification", 99, Rarity.UNCOMMON, mage.cards.s.SiegeModification.class)); - cards.add(new SetCardInfo("Silkweaver Elite", 125, Rarity.COMMON, mage.cards.s.SilkweaverElite.class)); - cards.add(new SetCardInfo("Skyship Plunderer", 46, Rarity.UNCOMMON, mage.cards.s.SkyshipPlunderer.class)); - cards.add(new SetCardInfo("Sly Requisitioner", 72, Rarity.UNCOMMON, mage.cards.s.SlyRequisitioner.class)); - cards.add(new SetCardInfo("Solemn Recruit", 22, Rarity.RARE, mage.cards.s.SolemnRecruit.class)); - cards.add(new SetCardInfo("Spire Patrol", 136, Rarity.UNCOMMON, mage.cards.s.SpirePatrol.class)); - cards.add(new SetCardInfo("Spire of Industry", 184, Rarity.RARE, mage.cards.s.SpireOfIndustry.class)); - cards.add(new SetCardInfo("Sram's Expertise", 24, Rarity.RARE, mage.cards.s.SramsExpertise.class)); - cards.add(new SetCardInfo("Sram, Senior Edificer", 23, Rarity.RARE, mage.cards.s.SramSeniorEdificer.class)); - cards.add(new SetCardInfo("Submerged Boneyard", 194, Rarity.COMMON, mage.cards.s.SubmergedBoneyard.class)); - cards.add(new SetCardInfo("Sweatworks Brawler", 100, Rarity.COMMON, mage.cards.s.SweatworksBrawler.class)); - cards.add(new SetCardInfo("Take into Custody", 47, Rarity.COMMON, mage.cards.t.TakeIntoCustody.class)); - cards.add(new SetCardInfo("Tezzeret the Schemer", 137, Rarity.MYTHIC, mage.cards.t.TezzeretTheSchemer.class)); - cards.add(new SetCardInfo("Tezzeret's Betrayal", 191, Rarity.RARE, mage.cards.t.TezzeretsBetrayal.class)); - cards.add(new SetCardInfo("Tezzeret's Simulacrum", 193, Rarity.UNCOMMON, mage.cards.t.TezzeretsSimulacrum.class)); - cards.add(new SetCardInfo("Tezzeret's Touch", 138, Rarity.UNCOMMON, mage.cards.t.TezzeretsTouch.class)); - cards.add(new SetCardInfo("Tezzeret, Master of Metal", 190, Rarity.MYTHIC, mage.cards.t.TezzeretMasterOfMetal.class)); - cards.add(new SetCardInfo("Thopter Arrest", 25, Rarity.UNCOMMON, mage.cards.t.ThopterArrest.class)); - cards.add(new SetCardInfo("Tranquil Expanse", 189, Rarity.COMMON, mage.cards.t.TranquilExpanse.class)); - cards.add(new SetCardInfo("Treasure Keeper", 177, Rarity.UNCOMMON, mage.cards.t.TreasureKeeper.class)); - cards.add(new SetCardInfo("Trophy Mage", 48, Rarity.UNCOMMON, mage.cards.t.TrophyMage.class)); - cards.add(new SetCardInfo("Unbridled Growth", 126, Rarity.COMMON, mage.cards.u.UnbridledGrowth.class)); - cards.add(new SetCardInfo("Universal Solvent", 178, Rarity.COMMON, mage.cards.u.UniversalSolvent.class)); - cards.add(new SetCardInfo("Untethered Express", 179, Rarity.UNCOMMON, mage.cards.u.UntetheredExpress.class)); - cards.add(new SetCardInfo("Vengeful Rebel", 73, Rarity.UNCOMMON, mage.cards.v.VengefulRebel.class)); - cards.add(new SetCardInfo("Verdant Automaton", 180, Rarity.COMMON, mage.cards.v.VerdantAutomaton.class)); - cards.add(new SetCardInfo("Walking Ballista", 181, Rarity.RARE, mage.cards.w.WalkingBallista.class)); - cards.add(new SetCardInfo("Watchful Automaton", 182, Rarity.COMMON, mage.cards.w.WatchfulAutomaton.class)); - cards.add(new SetCardInfo("Welder Automaton", 183, Rarity.COMMON, mage.cards.w.WelderAutomaton.class)); - cards.add(new SetCardInfo("Weldfast Engineer", 139, Rarity.UNCOMMON, mage.cards.w.WeldfastEngineer.class)); - cards.add(new SetCardInfo("Whir of Invention", 49, Rarity.RARE, mage.cards.w.WhirOfInvention.class)); - cards.add(new SetCardInfo("Wind-King Raiders", 50, Rarity.UNCOMMON, mage.cards.w.WindKingRaiders.class)); - cards.add(new SetCardInfo("Winding Constrictor", 140, Rarity.UNCOMMON, mage.cards.w.WindingConstrictor.class)); - cards.add(new SetCardInfo("Wrangle", 101, Rarity.COMMON, mage.cards.w.Wrangle.class)); - cards.add(new SetCardInfo("Yahenni's Expertise", 75, Rarity.RARE, mage.cards.y.YahennisExpertise.class)); - cards.add(new SetCardInfo("Yahenni, Undying Partisan", 74, Rarity.RARE, mage.cards.y.YahenniUndyingPartisan.class)); - } - - @Override - public List getSpecialLand() { - if (savedSpecialLand.isEmpty()) { - CardCriteria criteria = new CardCriteria(); - criteria.setCodes("MPS"); - criteria.minCardNumber(31); - criteria.maxCardNumber(54); - savedSpecialLand.addAll(CardRepository.instance.findCards(criteria)); - } - - return new ArrayList<>(savedSpecialLand); - } -} +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and 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 java.util.ArrayList; +import java.util.List; +import mage.cards.ExpansionSet; +import mage.cards.repository.CardCriteria; +import mage.cards.repository.CardInfo; +import mage.cards.repository.CardRepository; +import mage.constants.Rarity; +import mage.constants.SetType; + +/** + * + * @author fireshoes + */ +public class AetherRevolt extends ExpansionSet { + + private static final AetherRevolt fINSTANCE = new AetherRevolt(); + + public static AetherRevolt getInstance() { + return fINSTANCE; + } + + protected final List savedSpecialLand = new ArrayList<>(); + + private AetherRevolt() { + super("Aether Revolt", "AER", ExpansionSet.buildDate(2017, 1, 20), SetType.EXPANSION); + this.blockName = "Kaladesh"; + this.hasBoosters = true; + this.hasBasicLands = false; + this.numBoosterLands = 1; + this.numBoosterCommon = 10; + this.numBoosterUncommon = 3; + this.numBoosterRare = 1; + this.ratioBoosterMythic = 8; + this.maxCardNumberInBooster = 184; + this.ratioBoosterSpecialLand = 144; + this.parentSet = Kaladesh.getInstance(); + cards.add(new SetCardInfo("Aegis Automaton", 141, Rarity.COMMON, mage.cards.a.AegisAutomaton.class)); + cards.add(new SetCardInfo("Aerial Modification", 1, Rarity.UNCOMMON, mage.cards.a.AerialModification.class)); + cards.add(new SetCardInfo("Aeronaut Admiral", 2, Rarity.UNCOMMON, mage.cards.a.AeronautAdmiral.class)); + cards.add(new SetCardInfo("Aether Chaser", 76, Rarity.COMMON, mage.cards.a.AetherChaser.class)); + cards.add(new SetCardInfo("Aether Herder", 102, Rarity.COMMON, mage.cards.a.AetherHerder.class)); + cards.add(new SetCardInfo("Aether Inspector", 3, Rarity.COMMON, mage.cards.a.AetherInspector.class)); + cards.add(new SetCardInfo("Aether Poisoner", 51, Rarity.COMMON, mage.cards.a.AetherPoisoner.class)); + cards.add(new SetCardInfo("Aether Swooper", 26, Rarity.COMMON, mage.cards.a.AetherSwooper.class)); + cards.add(new SetCardInfo("Aethergeode Miner", 4, Rarity.RARE, mage.cards.a.AethergeodeMiner.class)); + cards.add(new SetCardInfo("Aethersphere Harvester", 142, Rarity.RARE, mage.cards.a.AethersphereHarvester.class)); + cards.add(new SetCardInfo("Aetherstream Leopard", 103, Rarity.COMMON, mage.cards.a.AetherstreamLeopard.class)); + cards.add(new SetCardInfo("Aethertide Whale", 27, Rarity.RARE, mage.cards.a.AethertideWhale.class)); + cards.add(new SetCardInfo("Aetherwind Basker", 104, Rarity.MYTHIC, mage.cards.a.AetherwindBasker.class)); + cards.add(new SetCardInfo("Aid from the Cowl", 105, Rarity.RARE, mage.cards.a.AidFromTheCowl.class)); + cards.add(new SetCardInfo("Airdrop Aeronauts", 5, Rarity.UNCOMMON, mage.cards.a.AirdropAeronauts.class)); + cards.add(new SetCardInfo("Ajani Unyielding", 127, Rarity.MYTHIC, mage.cards.a.AjaniUnyielding.class)); + cards.add(new SetCardInfo("Ajani's Aid", 188, Rarity.RARE, mage.cards.a.AjanisAid.class)); + cards.add(new SetCardInfo("Ajani's Comrade", 187, Rarity.UNCOMMON, mage.cards.a.AjanisComrade.class)); + cards.add(new SetCardInfo("Ajani, Valiant Protector", 185, Rarity.MYTHIC, mage.cards.a.AjaniValiantProtector.class)); + cards.add(new SetCardInfo("Alley Evasion", 6, Rarity.COMMON, mage.cards.a.AlleyEvasion.class)); + cards.add(new SetCardInfo("Alley Strangler", 52, Rarity.COMMON, mage.cards.a.AlleyStrangler.class)); + cards.add(new SetCardInfo("Audacious Infiltrator", 7, Rarity.COMMON, mage.cards.a.AudaciousInfiltrator.class)); + cards.add(new SetCardInfo("Augmenting Automaton", 143, Rarity.COMMON, mage.cards.a.AugmentingAutomaton.class)); + cards.add(new SetCardInfo("Baral's Expertise", 29, Rarity.RARE, mage.cards.b.BaralsExpertise.class)); + cards.add(new SetCardInfo("Baral, Chief of Compliance", 28, Rarity.RARE, mage.cards.b.BaralChiefOfCompliance.class)); + cards.add(new SetCardInfo("Barricade Breaker", 144, Rarity.UNCOMMON, mage.cards.b.BarricadeBreaker.class)); + cards.add(new SetCardInfo("Bastion Enforcer", 8, Rarity.COMMON, mage.cards.b.BastionEnforcer.class)); + cards.add(new SetCardInfo("Bastion Inventor", 30, Rarity.COMMON, mage.cards.b.BastionInventor.class)); + cards.add(new SetCardInfo("Battle at the Bridge", 53, Rarity.RARE, mage.cards.b.BattleAtTheBridge.class)); + cards.add(new SetCardInfo("Call for Unity", 9, Rarity.RARE, mage.cards.c.CallForUnity.class)); + cards.add(new SetCardInfo("Caught in the Brights", 10, Rarity.COMMON, mage.cards.c.CaughtInTheBrights.class)); + cards.add(new SetCardInfo("Chandra's Revolution", 77, Rarity.COMMON, mage.cards.c.ChandrasRevolution.class)); + cards.add(new SetCardInfo("Cogwork Assembler", 145, Rarity.UNCOMMON, mage.cards.c.CogworkAssembler.class)); + cards.add(new SetCardInfo("Consulate Crackdown", 11, Rarity.RARE, mage.cards.c.ConsulateCrackdown.class)); + cards.add(new SetCardInfo("Consulate Dreadnought", 146, Rarity.UNCOMMON, mage.cards.c.ConsulateDreadnought.class)); + cards.add(new SetCardInfo("Consulate Turret", 147, Rarity.COMMON, mage.cards.c.ConsulateTurret.class)); + cards.add(new SetCardInfo("Conviction", 12, Rarity.COMMON, mage.cards.c.Conviction.class)); + cards.add(new SetCardInfo("Countless Gears Renegade", 13, Rarity.COMMON, mage.cards.c.CountlessGearsRenegade.class)); + cards.add(new SetCardInfo("Crackdown Construct", 148, Rarity.UNCOMMON, mage.cards.c.CrackdownConstruct.class)); + cards.add(new SetCardInfo("Cruel Finality", 54, Rarity.COMMON, mage.cards.c.CruelFinality.class)); + cards.add(new SetCardInfo("Daredevil Dragster", 149, Rarity.UNCOMMON, mage.cards.d.DaredevilDragster.class)); + cards.add(new SetCardInfo("Daring Demolition", 55, Rarity.COMMON, mage.cards.d.DaringDemolition.class)); + cards.add(new SetCardInfo("Dark Intimations", 128, Rarity.RARE, mage.cards.d.DarkIntimations.class)); + cards.add(new SetCardInfo("Dawnfeather Eagle", 14, Rarity.COMMON, mage.cards.d.DawnfeatherEagle.class)); + cards.add(new SetCardInfo("Deadeye Harpooner", 15, Rarity.UNCOMMON, mage.cards.d.DeadeyeHarpooner.class)); + cards.add(new SetCardInfo("Decommission", 16, Rarity.COMMON, mage.cards.d.Decommission.class)); + cards.add(new SetCardInfo("Defiant Salvager", 56, Rarity.COMMON, mage.cards.d.DefiantSalvager.class)); + cards.add(new SetCardInfo("Deft Dismissal", 17, Rarity.UNCOMMON, mage.cards.d.DeftDismissal.class)); + cards.add(new SetCardInfo("Destructive Tampering", 78, Rarity.COMMON, mage.cards.d.DestructiveTampering.class)); + cards.add(new SetCardInfo("Disallow", 31, Rarity.RARE, mage.cards.d.Disallow.class)); + cards.add(new SetCardInfo("Dispersal Technician", 32, Rarity.COMMON, mage.cards.d.DispersalTechnician.class)); + cards.add(new SetCardInfo("Druid of the Cowl", 106, Rarity.COMMON, mage.cards.d.DruidOfTheCowl.class)); + cards.add(new SetCardInfo("Efficient Construction", 33, Rarity.UNCOMMON, mage.cards.e.EfficientConstruction.class)); + cards.add(new SetCardInfo("Embraal Gear-Smasher", 79, Rarity.COMMON, mage.cards.e.EmbraalGearSmasher.class)); + cards.add(new SetCardInfo("Enraged Giant", 80, Rarity.UNCOMMON, mage.cards.e.EnragedGiant.class)); + cards.add(new SetCardInfo("Exquisite Archangel", 18, Rarity.MYTHIC, mage.cards.e.ExquisiteArchangel.class)); + cards.add(new SetCardInfo("Fatal Push", 57, Rarity.UNCOMMON, mage.cards.f.FatalPush.class)); + cards.add(new SetCardInfo("Felidar Guardian", 19, Rarity.UNCOMMON, mage.cards.f.FelidarGuardian.class)); + cards.add(new SetCardInfo("Fen Hauler", 58, Rarity.COMMON, mage.cards.f.FenHauler.class)); + cards.add(new SetCardInfo("Filigree Crawler", 150, Rarity.COMMON, mage.cards.f.FiligreeCrawler.class)); + cards.add(new SetCardInfo("Foundry Assembler", 151, Rarity.COMMON, mage.cards.f.FoundryAssembler.class)); + cards.add(new SetCardInfo("Foundry Hornet", 59, Rarity.UNCOMMON, mage.cards.f.FoundryHornet.class)); + cards.add(new SetCardInfo("Fourth Bridge Prowler", 60, Rarity.COMMON, mage.cards.f.FourthBridgeProwler.class)); + cards.add(new SetCardInfo("Freejam Regent", 81, Rarity.RARE, mage.cards.f.FreejamRegent.class)); + cards.add(new SetCardInfo("Frontline Rebel", 82, Rarity.COMMON, mage.cards.f.FrontlineRebel.class)); + cards.add(new SetCardInfo("Ghirapur Osprey", 20, Rarity.COMMON, mage.cards.g.GhirapurOsprey.class)); + cards.add(new SetCardInfo("Gifted Aetherborn", 61, Rarity.UNCOMMON, mage.cards.g.GiftedAetherborn.class)); + cards.add(new SetCardInfo("Glint-Sleeve Siphoner", 62, Rarity.RARE, mage.cards.g.GlintSleeveSiphoner.class)); + cards.add(new SetCardInfo("Gonti's Aether Heart", 152, Rarity.MYTHIC, mage.cards.g.GontisAetherHeart.class)); + cards.add(new SetCardInfo("Gonti's Machinations", 63, Rarity.UNCOMMON, mage.cards.g.GontisMachinations.class)); + cards.add(new SetCardInfo("Greenbelt Rampager", 107, Rarity.RARE, mage.cards.g.GreenbeltRampager.class)); + cards.add(new SetCardInfo("Greenwheel Liberator", 108, Rarity.RARE, mage.cards.g.GreenwheelLiberator.class)); + cards.add(new SetCardInfo("Gremlin Infestation", 83, Rarity.UNCOMMON, mage.cards.g.GremlinInfestation.class)); + cards.add(new SetCardInfo("Heart of Kiran", 153, Rarity.MYTHIC, mage.cards.h.HeartOfKiran.class)); + cards.add(new SetCardInfo("Herald of Anguish", 64, Rarity.MYTHIC, mage.cards.h.HeraldOfAnguish.class)); + cards.add(new SetCardInfo("Heroic Intervention", 109, Rarity.RARE, mage.cards.h.HeroicIntervention.class)); + cards.add(new SetCardInfo("Hidden Herbalists", 110, Rarity.UNCOMMON, mage.cards.h.HiddenHerbalists.class)); + cards.add(new SetCardInfo("Hidden Stockpile", 129, Rarity.UNCOMMON, mage.cards.h.HiddenStockpile.class)); + cards.add(new SetCardInfo("Highspire Infusion", 111, Rarity.COMMON, mage.cards.h.HighspireInfusion.class)); + cards.add(new SetCardInfo("Hinterland Drake", 34, Rarity.COMMON, mage.cards.h.HinterlandDrake.class)); + cards.add(new SetCardInfo("Hope of Ghirapur", 154, Rarity.RARE, mage.cards.h.HopeOfGhirapur.class)); + cards.add(new SetCardInfo("Hungry Flames", 84, Rarity.UNCOMMON, mage.cards.h.HungryFlames.class)); + cards.add(new SetCardInfo("Ice Over", 35, Rarity.COMMON, mage.cards.i.IceOver.class)); + cards.add(new SetCardInfo("Illusionist's Stratagem", 36, Rarity.UNCOMMON, mage.cards.i.IllusionistsStratagem.class)); + cards.add(new SetCardInfo("Implement of Combustion", 155, Rarity.COMMON, mage.cards.i.ImplementOfCombustion.class)); + cards.add(new SetCardInfo("Implement of Examination", 156, Rarity.COMMON, mage.cards.i.ImplementOfExamination.class)); + cards.add(new SetCardInfo("Implement of Ferocity", 157, Rarity.COMMON, mage.cards.i.ImplementOfFerocity.class)); + cards.add(new SetCardInfo("Implement of Improvement", 158, Rarity.COMMON, mage.cards.i.ImplementOfImprovement.class)); + cards.add(new SetCardInfo("Implement of Malice", 159, Rarity.COMMON, mage.cards.i.ImplementOfMalice.class)); + cards.add(new SetCardInfo("Indomitable Creativity", 85, Rarity.MYTHIC, mage.cards.i.IndomitableCreativity.class)); + cards.add(new SetCardInfo("Inspiring Roar", 186, Rarity.COMMON, mage.cards.i.InspiringRoar.class)); + cards.add(new SetCardInfo("Inspiring Statuary", 160, Rarity.RARE, mage.cards.i.InspiringStatuary.class)); + cards.add(new SetCardInfo("Invigorated Rampage", 86, Rarity.UNCOMMON, mage.cards.i.InvigoratedRampage.class)); + cards.add(new SetCardInfo("Ironclad Revolutionary", 65, Rarity.UNCOMMON, mage.cards.i.IroncladRevolutionary.class)); + cards.add(new SetCardInfo("Irontread Crusher", 161, Rarity.COMMON, mage.cards.i.IrontreadCrusher.class)); + cards.add(new SetCardInfo("Kari Zev's Expertise", 88, Rarity.RARE, mage.cards.k.KariZevsExpertise.class)); + cards.add(new SetCardInfo("Kari Zev, Skyship Raider", 87, Rarity.RARE, mage.cards.k.KariZevSkyshipRaider.class)); + cards.add(new SetCardInfo("Lathnu Sailback", 89, Rarity.COMMON, mage.cards.l.LathnuSailback.class)); + cards.add(new SetCardInfo("Leave in the Dust", 37, Rarity.COMMON, mage.cards.l.LeaveInTheDust.class)); + cards.add(new SetCardInfo("Lifecraft Awakening", 112, Rarity.UNCOMMON, mage.cards.l.LifecraftAwakening.class)); + cards.add(new SetCardInfo("Lifecraft Cavalry", 113, Rarity.COMMON, mage.cards.l.LifecraftCavalry.class)); + cards.add(new SetCardInfo("Lifecrafter's Bestiary", 162, Rarity.RARE, mage.cards.l.LifecraftersBestiary.class)); + cards.add(new SetCardInfo("Lifecrafter's Gift", 114, Rarity.UNCOMMON, mage.cards.l.LifecraftersGift.class)); + cards.add(new SetCardInfo("Lightning Runner", 90, Rarity.MYTHIC, mage.cards.l.LightningRunner.class)); + cards.add(new SetCardInfo("Maulfist Revolutionary", 115, Rarity.UNCOMMON, mage.cards.m.MaulfistRevolutionary.class)); + cards.add(new SetCardInfo("Maverick Thopterist", 130, Rarity.UNCOMMON, mage.cards.m.MaverickThopterist.class)); + cards.add(new SetCardInfo("Mechanized Production", 38, Rarity.MYTHIC, mage.cards.m.MechanizedProduction.class)); + cards.add(new SetCardInfo("Merchant's Dockhand", 163, Rarity.RARE, mage.cards.m.MerchantsDockhand.class)); + cards.add(new SetCardInfo("Metallic Mimic", 164, Rarity.RARE, mage.cards.m.MetallicMimic.class)); + cards.add(new SetCardInfo("Metallic Rebuke", 39, Rarity.COMMON, mage.cards.m.MetallicRebuke.class)); + cards.add(new SetCardInfo("Midnight Entourage", 66, Rarity.RARE, mage.cards.m.MidnightEntourage.class)); + cards.add(new SetCardInfo("Mobile Garrison", 165, Rarity.COMMON, mage.cards.m.MobileGarrison.class)); + cards.add(new SetCardInfo("Monstrous Onslaught", 116, Rarity.UNCOMMON, mage.cards.m.MonstrousOnslaught.class)); + cards.add(new SetCardInfo("Narnam Renegade", 117, Rarity.UNCOMMON, mage.cards.n.NarnamRenegade.class)); + cards.add(new SetCardInfo("Natural Obsolescence", 118, Rarity.COMMON, mage.cards.n.NaturalObsolescence.class)); + cards.add(new SetCardInfo("Negate", 40, Rarity.COMMON, mage.cards.n.Negate.class)); + cards.add(new SetCardInfo("Night Market Aeronaut", 67, Rarity.COMMON, mage.cards.n.NightMarketAeronaut.class)); + cards.add(new SetCardInfo("Night Market Guard", 166, Rarity.COMMON, mage.cards.n.NightMarketGuard.class)); + cards.add(new SetCardInfo("Oath of Ajani", 131, Rarity.RARE, mage.cards.o.OathOfAjani.class)); + cards.add(new SetCardInfo("Ornithopter", 167, Rarity.UNCOMMON, mage.cards.o.Ornithopter.class)); + cards.add(new SetCardInfo("Outland Boar", 132, Rarity.UNCOMMON, mage.cards.o.OutlandBoar.class)); + cards.add(new SetCardInfo("Pacification Array", 168, Rarity.UNCOMMON, mage.cards.p.PacificationArray.class)); + cards.add(new SetCardInfo("Paradox Engine", 169, Rarity.MYTHIC, mage.cards.p.ParadoxEngine.class)); + cards.add(new SetCardInfo("Peacewalker Colossus", 170, Rarity.RARE, mage.cards.p.PeacewalkerColossus.class)); + cards.add(new SetCardInfo("Peema Aether-Seer", 119, Rarity.UNCOMMON, mage.cards.p.PeemaAetherSeer.class)); + cards.add(new SetCardInfo("Pendulum of Patterns", 192, Rarity.COMMON, mage.cards.p.PendulumOfPatterns.class)); + cards.add(new SetCardInfo("Perilous Predicament", 68, Rarity.UNCOMMON, mage.cards.p.PerilousPredicament.class)); + cards.add(new SetCardInfo("Pia's Revolution", 91, Rarity.RARE, mage.cards.p.PiasRevolution.class)); + cards.add(new SetCardInfo("Planar Bridge", 171, Rarity.MYTHIC, mage.cards.p.PlanarBridge.class)); + cards.add(new SetCardInfo("Precise Strike", 92, Rarity.COMMON, mage.cards.p.PreciseStrike.class)); + cards.add(new SetCardInfo("Prey Upon", 120, Rarity.COMMON, mage.cards.p.PreyUpon.class)); + cards.add(new SetCardInfo("Prizefighter Construct", 172, Rarity.COMMON, mage.cards.p.PrizefighterConstruct.class)); + cards.add(new SetCardInfo("Quicksmith Rebel", 93, Rarity.RARE, mage.cards.q.QuicksmithRebel.class)); + cards.add(new SetCardInfo("Quicksmith Spy", 41, Rarity.RARE, mage.cards.q.QuicksmithSpy.class)); + cards.add(new SetCardInfo("Ravenous Intruder", 94, Rarity.UNCOMMON, mage.cards.r.RavenousIntruder.class)); + cards.add(new SetCardInfo("Reckless Racer", 95, Rarity.UNCOMMON, mage.cards.r.RecklessRacer.class)); + cards.add(new SetCardInfo("Release the Gremlins", 96, Rarity.RARE, mage.cards.r.ReleaseTheGremlins.class)); + cards.add(new SetCardInfo("Renegade Map", 173, Rarity.COMMON, mage.cards.r.RenegadeMap.class)); + cards.add(new SetCardInfo("Renegade Rallier", 133, Rarity.UNCOMMON, mage.cards.r.RenegadeRallier.class)); + cards.add(new SetCardInfo("Renegade Wheelsmith", 134, Rarity.UNCOMMON, mage.cards.r.RenegadeWheelsmith.class)); + cards.add(new SetCardInfo("Renegade's Getaway", 69, Rarity.COMMON, mage.cards.r.RenegadesGetaway.class)); + cards.add(new SetCardInfo("Reservoir Walker", 174, Rarity.COMMON, mage.cards.r.ReservoirWalker.class)); + cards.add(new SetCardInfo("Resourceful Return", 70, Rarity.COMMON, mage.cards.r.ResourcefulReturn.class)); + cards.add(new SetCardInfo("Restoration Specialist", 21, Rarity.UNCOMMON, mage.cards.r.RestorationSpecialist.class)); + cards.add(new SetCardInfo("Reverse Engineer", 42, Rarity.UNCOMMON, mage.cards.r.ReverseEngineer.class)); + cards.add(new SetCardInfo("Ridgescale Tusker", 121, Rarity.UNCOMMON, mage.cards.r.RidgescaleTusker.class)); + cards.add(new SetCardInfo("Rishkar's Expertise", 123, Rarity.RARE, mage.cards.r.RishkarsExpertise.class)); + cards.add(new SetCardInfo("Rishkar, Peema Renegade", 122, Rarity.RARE, mage.cards.r.RishkarPeemaRenegade.class)); + cards.add(new SetCardInfo("Rogue Refiner", 135, Rarity.UNCOMMON, mage.cards.r.RogueRefiner.class)); + cards.add(new SetCardInfo("Salvage Scuttler", 43, Rarity.UNCOMMON, mage.cards.s.SalvageScuttler.class)); + cards.add(new SetCardInfo("Scrap Trawler", 175, Rarity.RARE, mage.cards.s.ScrapTrawler.class)); + cards.add(new SetCardInfo("Scrapper Champion", 97, Rarity.UNCOMMON, mage.cards.s.ScrapperChampion.class)); + cards.add(new SetCardInfo("Scrounging Bandar", 124, Rarity.COMMON, mage.cards.s.ScroungingBandar.class)); + cards.add(new SetCardInfo("Secret Salvage", 71, Rarity.RARE, mage.cards.s.SecretSalvage.class)); + cards.add(new SetCardInfo("Servo Schematic", 176, Rarity.UNCOMMON, mage.cards.s.ServoSchematic.class)); + cards.add(new SetCardInfo("Shielded Aether Thief", 44, Rarity.UNCOMMON, mage.cards.s.ShieldedAetherThief.class)); + cards.add(new SetCardInfo("Shipwreck Moray", 45, Rarity.COMMON, mage.cards.s.ShipwreckMoray.class)); + cards.add(new SetCardInfo("Shock", 98, Rarity.COMMON, mage.cards.s.Shock.class)); + cards.add(new SetCardInfo("Siege Modification", 99, Rarity.UNCOMMON, mage.cards.s.SiegeModification.class)); + cards.add(new SetCardInfo("Silkweaver Elite", 125, Rarity.COMMON, mage.cards.s.SilkweaverElite.class)); + cards.add(new SetCardInfo("Skyship Plunderer", 46, Rarity.UNCOMMON, mage.cards.s.SkyshipPlunderer.class)); + cards.add(new SetCardInfo("Sly Requisitioner", 72, Rarity.UNCOMMON, mage.cards.s.SlyRequisitioner.class)); + cards.add(new SetCardInfo("Solemn Recruit", 22, Rarity.RARE, mage.cards.s.SolemnRecruit.class)); + cards.add(new SetCardInfo("Spire Patrol", 136, Rarity.UNCOMMON, mage.cards.s.SpirePatrol.class)); + cards.add(new SetCardInfo("Spire of Industry", 184, Rarity.RARE, mage.cards.s.SpireOfIndustry.class)); + cards.add(new SetCardInfo("Sram's Expertise", 24, Rarity.RARE, mage.cards.s.SramsExpertise.class)); + cards.add(new SetCardInfo("Sram, Senior Edificer", 23, Rarity.RARE, mage.cards.s.SramSeniorEdificer.class)); + cards.add(new SetCardInfo("Submerged Boneyard", 194, Rarity.COMMON, mage.cards.s.SubmergedBoneyard.class)); + cards.add(new SetCardInfo("Sweatworks Brawler", 100, Rarity.COMMON, mage.cards.s.SweatworksBrawler.class)); + cards.add(new SetCardInfo("Take into Custody", 47, Rarity.COMMON, mage.cards.t.TakeIntoCustody.class)); + cards.add(new SetCardInfo("Tezzeret the Schemer", 137, Rarity.MYTHIC, mage.cards.t.TezzeretTheSchemer.class)); + cards.add(new SetCardInfo("Tezzeret's Betrayal", 191, Rarity.RARE, mage.cards.t.TezzeretsBetrayal.class)); + cards.add(new SetCardInfo("Tezzeret's Simulacrum", 193, Rarity.UNCOMMON, mage.cards.t.TezzeretsSimulacrum.class)); + cards.add(new SetCardInfo("Tezzeret's Touch", 138, Rarity.UNCOMMON, mage.cards.t.TezzeretsTouch.class)); + cards.add(new SetCardInfo("Tezzeret, Master of Metal", 190, Rarity.MYTHIC, mage.cards.t.TezzeretMasterOfMetal.class)); + cards.add(new SetCardInfo("Thopter Arrest", 25, Rarity.UNCOMMON, mage.cards.t.ThopterArrest.class)); + cards.add(new SetCardInfo("Tranquil Expanse", 189, Rarity.COMMON, mage.cards.t.TranquilExpanse.class)); + cards.add(new SetCardInfo("Treasure Keeper", 177, Rarity.UNCOMMON, mage.cards.t.TreasureKeeper.class)); + cards.add(new SetCardInfo("Trophy Mage", 48, Rarity.UNCOMMON, mage.cards.t.TrophyMage.class)); + cards.add(new SetCardInfo("Unbridled Growth", 126, Rarity.COMMON, mage.cards.u.UnbridledGrowth.class)); + cards.add(new SetCardInfo("Universal Solvent", 178, Rarity.COMMON, mage.cards.u.UniversalSolvent.class)); + cards.add(new SetCardInfo("Untethered Express", 179, Rarity.UNCOMMON, mage.cards.u.UntetheredExpress.class)); + cards.add(new SetCardInfo("Vengeful Rebel", 73, Rarity.UNCOMMON, mage.cards.v.VengefulRebel.class)); + cards.add(new SetCardInfo("Verdant Automaton", 180, Rarity.COMMON, mage.cards.v.VerdantAutomaton.class)); + cards.add(new SetCardInfo("Walking Ballista", 181, Rarity.RARE, mage.cards.w.WalkingBallista.class)); + cards.add(new SetCardInfo("Watchful Automaton", 182, Rarity.COMMON, mage.cards.w.WatchfulAutomaton.class)); + cards.add(new SetCardInfo("Welder Automaton", 183, Rarity.COMMON, mage.cards.w.WelderAutomaton.class)); + cards.add(new SetCardInfo("Weldfast Engineer", 139, Rarity.UNCOMMON, mage.cards.w.WeldfastEngineer.class)); + cards.add(new SetCardInfo("Whir of Invention", 49, Rarity.RARE, mage.cards.w.WhirOfInvention.class)); + cards.add(new SetCardInfo("Wind-Kin Raiders", 50, Rarity.UNCOMMON, mage.cards.w.WindKinRaiders.class)); + cards.add(new SetCardInfo("Winding Constrictor", 140, Rarity.UNCOMMON, mage.cards.w.WindingConstrictor.class)); + cards.add(new SetCardInfo("Wrangle", 101, Rarity.COMMON, mage.cards.w.Wrangle.class)); + cards.add(new SetCardInfo("Yahenni's Expertise", 75, Rarity.RARE, mage.cards.y.YahennisExpertise.class)); + cards.add(new SetCardInfo("Yahenni, Undying Partisan", 74, Rarity.RARE, mage.cards.y.YahenniUndyingPartisan.class)); + } + + @Override + public List getSpecialLand() { + if (savedSpecialLand.isEmpty()) { + CardCriteria criteria = new CardCriteria(); + criteria.setCodes("MPS"); + criteria.minCardNumber(31); + criteria.maxCardNumber(54); + savedSpecialLand.addAll(CardRepository.instance.findCards(criteria)); + } + + return new ArrayList<>(savedSpecialLand); + } +} diff --git a/Mage/src/main/java/mage/cards/repository/CardRepository.java b/Mage/src/main/java/mage/cards/repository/CardRepository.java index 5a01631bbf3..e68aa969aaf 100644 --- a/Mage/src/main/java/mage/cards/repository/CardRepository.java +++ b/Mage/src/main/java/mage/cards/repository/CardRepository.java @@ -37,17 +37,16 @@ import com.j256.ormlite.stmt.Where; import com.j256.ormlite.support.ConnectionSource; import com.j256.ormlite.support.DatabaseConnection; import com.j256.ormlite.table.TableUtils; +import java.io.File; +import java.sql.SQLException; +import java.util.*; +import java.util.concurrent.Callable; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SetType; import mage.util.RandomUtil; import org.apache.log4j.Logger; -import java.io.File; -import java.sql.SQLException; -import java.util.*; -import java.util.concurrent.Callable; - /** * * @author North @@ -61,7 +60,7 @@ public enum CardRepository { // raise this if db structure was changed private static final long CARD_DB_VERSION = 49; // raise this if new cards were added to the server - private static final long CARD_CONTENT_VERSION = 65; + private static final long CARD_CONTENT_VERSION = 66; private final TreeSet landTypes = new TreeSet(); private Dao cardDao; private Set classNames; From 491ab5fbb083118a38c46589d4333fb5a8a94989 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sat, 7 Jan 2017 23:29:27 +0100 Subject: [PATCH 08/19] [AER] Fixed Daredevil Dragster. --- .../src/mage/cards/c/ClockworkAvian.java | 66 ++++++---------- .../src/mage/cards/c/ClockworkBeast.java | 75 ++++++++----------- .../src/mage/cards/d/DaredevilDragster.java | 43 +++-------- .../src/mage/cards/k/KytheonHeroOfAkros.java | 26 +++---- ...kedOrBlockedThisCombatSourceCondition.java | 52 +++++++++++++ ...> AttackedOrBlockedThisCombatWatcher.java} | 30 +++++--- 6 files changed, 147 insertions(+), 145 deletions(-) create mode 100644 Mage/src/main/java/mage/abilities/condition/common/AttackedOrBlockedThisCombatSourceCondition.java rename Mage/src/main/java/mage/watchers/common/{AttackedThisCombatWatcher.java => AttackedOrBlockedThisCombatWatcher.java} (55%) diff --git a/Mage.Sets/src/mage/cards/c/ClockworkAvian.java b/Mage.Sets/src/mage/cards/c/ClockworkAvian.java index c1c18814fd7..d37ecbc70da 100644 --- a/Mage.Sets/src/mage/cards/c/ClockworkAvian.java +++ b/Mage.Sets/src/mage/cards/c/ClockworkAvian.java @@ -30,30 +30,29 @@ package mage.cards.c; import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.common.AttacksOrBlocksTriggeredAbility; +import mage.abilities.common.EndOfCombatTriggeredAbility; import mage.abilities.common.EntersBattlefieldAbility; -import mage.abilities.common.delayed.AtTheEndOfCombatDelayedTriggeredAbility; +import mage.abilities.condition.common.AttackedOrBlockedThisCombatSourceCondition; import mage.abilities.condition.common.IsStepCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.decorator.ConditionalTriggeredAbility; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.ManacostVariableValue; -import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.effects.common.counter.RemoveCounterSourceEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.PhaseStep; import mage.constants.Zone; import mage.counters.Counter; import mage.counters.CounterType; import mage.counters.Counters; import mage.game.Game; -import mage.game.permanent.Permanent; +import mage.watchers.common.AttackedOrBlockedThisCombatWatcher; /** * @@ -62,7 +61,7 @@ import mage.game.permanent.Permanent; public class ClockworkAvian extends CardImpl { public ClockworkAvian(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{5}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{5}"); this.subtype.add("Bird"); this.power = new MageInt(0); this.toughness = new MageInt(4); @@ -71,10 +70,16 @@ public class ClockworkAvian extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // Clockwork Avian enters the battlefield with four +1/+0 counters on it. this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.P1P0.createInstance(4)), "{this} enters the battlefield with four +1/+0 counters on it")); + // At end of combat, if Clockwork Avian attacked or blocked this combat, remove a +1/+0 counter from it. - this.addAbility(new AttacksOrBlocksTriggeredAbility(new ClockworkAvianEffect(), false)); + this.addAbility(new ConditionalTriggeredAbility( + new EndOfCombatTriggeredAbility(new RemoveCounterSourceEffect(CounterType.P1P0.createInstance()), false), + new AttackedOrBlockedThisCombatSourceCondition(), + "At end of combat, if {this} attacked or blocked this combat, remove a +1/+0 counter from it."), + new AttackedOrBlockedThisCombatWatcher()); + // {X}, {tap}: Put up to X +1/+0 counters on Clockwork Avian. This ability can't cause the total number of +1/+0 counters on Clockwork Avian to be greater than four. Activate this ability only during your upkeep. - Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, + Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, new AvianAddCountersSourceEffect(CounterType.P1P0.createInstance(), new ManacostVariableValue(), true, true), new ManaCostsImpl("{X}"), new IsStepCondition(PhaseStep.UPKEEP), null); ability.addCost(new TapSourceCost()); this.addAbility(ability); @@ -92,48 +97,21 @@ public class ClockworkAvian extends CardImpl { class AvianAddCountersSourceEffect extends AddCountersSourceEffect { - public AvianAddCountersSourceEffect (Counter counter, DynamicValue amount, boolean informPlayers, boolean putOnCard){ - super(counter, amount, informPlayers, putOnCard); + public AvianAddCountersSourceEffect(Counter counter, DynamicValue amount, boolean informPlayers, boolean putOnCard) { + super(counter, amount, informPlayers, putOnCard); } - + @Override public boolean apply(Game game, Ability source) { //record how many counters Counters permCounters = game.getPermanent(source.getSourceId()).getCounters(game); int countersWas = permCounters.getCount(CounterType.P1P0); - if (countersWas < 4){ - super.apply(game, source); - if (permCounters.getCount(CounterType.P1P0)>4){ - permCounters.removeCounter(CounterType.P1P0, permCounters.getCount(CounterType.P1P0)-4); - }//if countersWas < 4 then counter is min(current,4); there is no setCounters function tho - }//else this is a rare case of an Avian getting boosted by outside sources :) Which is the sole purpose of this if, for the benefit of this rare but not impossible case :p + if (countersWas < 4) { + super.apply(game, source); + if (permCounters.getCount(CounterType.P1P0) > 4) { + permCounters.removeCounter(CounterType.P1P0, permCounters.getCount(CounterType.P1P0) - 4); + }//if countersWas < 4 then counter is min(current,4); there is no setCounters function tho + }//else this is a rare case of an Avian getting boosted by outside sources :) Which is the sole purpose of this if, for the benefit of this rare but not impossible case :p return true; } } - -class ClockworkAvianEffect extends OneShotEffect { - - ClockworkAvianEffect() { - super(Outcome.UnboostCreature); - staticText = "remove a +1/+0 counter from {this} at end of combat"; - } - - ClockworkAvianEffect(final ClockworkAvianEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent p = game.getPermanent(source.getSourceId()); - if (p != null) { - AtTheEndOfCombatDelayedTriggeredAbility ability = new AtTheEndOfCombatDelayedTriggeredAbility(new RemoveCounterSourceEffect(CounterType.P1P0.createInstance())); - game.addDelayedTriggeredAbility(ability, source); - } - return false; - } - - @Override - public ClockworkAvianEffect copy() { - return new ClockworkAvianEffect(this); - } -} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/c/ClockworkBeast.java b/Mage.Sets/src/mage/cards/c/ClockworkBeast.java index ee6fbbfd336..b91879d6b39 100644 --- a/Mage.Sets/src/mage/cards/c/ClockworkBeast.java +++ b/Mage.Sets/src/mage/cards/c/ClockworkBeast.java @@ -30,29 +30,28 @@ package mage.cards.c; import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.common.AttacksOrBlocksTriggeredAbility; +import mage.abilities.common.EndOfCombatTriggeredAbility; import mage.abilities.common.EntersBattlefieldAbility; -import mage.abilities.common.delayed.AtTheEndOfCombatDelayedTriggeredAbility; +import mage.abilities.condition.common.AttackedOrBlockedThisCombatSourceCondition; import mage.abilities.condition.common.IsStepCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.decorator.ConditionalTriggeredAbility; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.ManacostVariableValue; -import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.effects.common.counter.RemoveCounterSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.PhaseStep; import mage.constants.Zone; import mage.counters.Counter; import mage.counters.CounterType; import mage.counters.Counters; import mage.game.Game; -import mage.game.permanent.Permanent; +import mage.watchers.common.AttackedOrBlockedThisCombatWatcher; /** * @@ -61,19 +60,23 @@ import mage.game.permanent.Permanent; public class ClockworkBeast extends CardImpl { public ClockworkBeast(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{6}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{6}"); this.subtype.add("Beast"); this.power = new MageInt(0); this.toughness = new MageInt(4); // Clockwork Beast enters the battlefield with seven +1/+0 counters on it. this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.P1P0.createInstance(7)), "{this} enters the battlefield with seven +1/+0 counters on it")); - + // At end of combat, if Clockwork Beast attacked or blocked this combat, remove a +1/+0 counter from it. - this.addAbility(new AttacksOrBlocksTriggeredAbility(new ClockworkBeastEffect(), false)); - + this.addAbility(new ConditionalTriggeredAbility( + new EndOfCombatTriggeredAbility(new RemoveCounterSourceEffect(CounterType.P1P0.createInstance()), false), + new AttackedOrBlockedThisCombatSourceCondition(), + "At end of combat, if {this} attacked or blocked this combat, remove a +1/+0 counter from it."), + new AttackedOrBlockedThisCombatWatcher()); + // {X}, {tap}: Put up to X +1/+0 counters on Clockwork Beast. This ability can't cause the total number of +1/+0 counters on Clockwork Beast to be greater than seven. Activate this ability only during your upkeep. - Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, + Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, new BeastAddCountersSourceEffect(CounterType.P1P0.createInstance(), new ManacostVariableValue(), true, true), new ManaCostsImpl("{X}"), new IsStepCondition(PhaseStep.UPKEEP), null); ability.addCost(new TapSourceCost()); this.addAbility(ability); @@ -89,49 +92,31 @@ public class ClockworkBeast extends CardImpl { } } -class ClockworkBeastEffect extends OneShotEffect { - - ClockworkBeastEffect() { - super(Outcome.UnboostCreature); - staticText = "remove a +1/+0 counter from {this} at end of combat"; - } - - ClockworkBeastEffect(final ClockworkBeastEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent p = game.getPermanent(source.getSourceId()); - if (p != null) { - AtTheEndOfCombatDelayedTriggeredAbility ability = new AtTheEndOfCombatDelayedTriggeredAbility(new RemoveCounterSourceEffect(CounterType.P1P0.createInstance())); - game.addDelayedTriggeredAbility(ability, source); - } - return false; - } - - @Override - public ClockworkBeastEffect copy() { - return new ClockworkBeastEffect(this); - } -} - class BeastAddCountersSourceEffect extends AddCountersSourceEffect { - public BeastAddCountersSourceEffect (Counter counter, DynamicValue amount, boolean informPlayers, boolean putOnCard){ - super(counter, amount, informPlayers, putOnCard); + public BeastAddCountersSourceEffect(Counter counter, DynamicValue amount, boolean informPlayers, boolean putOnCard) { + super(counter, amount, informPlayers, putOnCard); } - + @Override public boolean apply(Game game, Ability source) { Counters permCounters = game.getPermanent(source.getSourceId()).getCounters(game); int countersWas = permCounters.getCount(CounterType.P1P0); - if (countersWas < 7){ - super.apply(game, source); - if (permCounters.getCount(CounterType.P1P0) > 7){ + if (countersWas < 7) { + super.apply(game, source); + if (permCounters.getCount(CounterType.P1P0) > 7) { permCounters.removeCounter(CounterType.P1P0, permCounters.getCount(CounterType.P1P0) - 7); }//if countersWas < 7 then counter is min(current,7); there is no setCounters function though - }//else this is a rare case of a Beast getting boosted by outside sources. Which is the sole purpose of this if, for the benefit of this rare but not impossible case + }//else this is a rare case of a Beast getting boosted by outside sources. Which is the sole purpose of this if, for the benefit of this rare but not impossible case return true; } -} \ No newline at end of file + + public BeastAddCountersSourceEffect(final BeastAddCountersSourceEffect effect) { + super(effect); + } + + @Override + public BeastAddCountersSourceEffect copy() { + return new BeastAddCountersSourceEffect(this); + } +} diff --git a/Mage.Sets/src/mage/cards/d/DaredevilDragster.java b/Mage.Sets/src/mage/cards/d/DaredevilDragster.java index c2abd91abdc..b1e570577e3 100644 --- a/Mage.Sets/src/mage/cards/d/DaredevilDragster.java +++ b/Mage.Sets/src/mage/cards/d/DaredevilDragster.java @@ -30,8 +30,9 @@ package mage.cards.d; import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.common.AttacksOrBlocksTriggeredAbility; -import mage.abilities.common.delayed.AtTheEndOfCombatDelayedTriggeredAbility; +import mage.abilities.common.EndOfCombatTriggeredAbility; +import mage.abilities.condition.common.AttackedOrBlockedThisCombatSourceCondition; +import mage.abilities.decorator.ConditionalTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.keyword.CrewAbility; import mage.cards.CardImpl; @@ -42,6 +43,7 @@ import mage.counters.CounterType; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.watchers.common.AttackedOrBlockedThisCombatWatcher; /** * @@ -57,7 +59,11 @@ public class DaredevilDragster extends CardImpl { this.toughness = new MageInt(4); // At end of combat, if Daredevil Dragster attacked or blocked this combat, put a velocity counter on it. Then if it has two or more velocity counters on it, sacrifice it and draw two cards. - this.addAbility(new AttacksOrBlocksTriggeredAbility(new DaredevilDragsterEffect(), false)); + this.addAbility(new ConditionalTriggeredAbility( + new EndOfCombatTriggeredAbility(new DaredevilDragsterEffect(), false), + new AttackedOrBlockedThisCombatSourceCondition(), + "At end of combat, if {this} attacked or blocked this combat, put a velocity counter on it. Then if it has two or more velocity counters on it, sacrifice it and draw two cards."), + new AttackedOrBlockedThisCombatWatcher()); // Crew 2 this.addAbility(new CrewAbility(2)); @@ -77,7 +83,7 @@ class DaredevilDragsterEffect extends OneShotEffect { public DaredevilDragsterEffect() { super(Outcome.Damage); - this.staticText = "At end of combat, if {this} attacked or blocked this combat, put a velocity counter on it. Then if it has two or more velocity counters on it, sacrifice it and draw two cards"; + this.staticText = "put a velocity counter on it. Then if it has two or more velocity counters on it, sacrifice it and draw two cards"; } public DaredevilDragsterEffect(final DaredevilDragsterEffect effect) { @@ -89,40 +95,13 @@ class DaredevilDragsterEffect extends OneShotEffect { return new DaredevilDragsterEffect(this); } - @Override - public boolean apply(Game game, Ability source) { - Permanent p = game.getPermanent(source.getSourceId()); - if (p != null) { - AtTheEndOfCombatDelayedTriggeredAbility ability = new AtTheEndOfCombatDelayedTriggeredAbility(new DaredevilDragsterEffect2()); - game.addDelayedTriggeredAbility(ability, source); - } - return false; - } -} - -class DaredevilDragsterEffect2 extends OneShotEffect { - - public DaredevilDragsterEffect2() { - super(Outcome.Damage); - this.staticText = "put a velocity counter on it. Then if it has two or more velocity counters on it, sacrifice it and draw two cards"; - } - - public DaredevilDragsterEffect2(final DaredevilDragsterEffect2 effect) { - super(effect); - } - - @Override - public DaredevilDragsterEffect2 copy() { - return new DaredevilDragsterEffect2(this); - } - @Override public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanent(source.getSourceId()); Player controller = game.getPlayer(source.getControllerId()); if (controller != null && permanent != null) { permanent.addCounters(CounterType.VELOCITY.createInstance(), source, game); - if (permanent != null && permanent.getCounters(game).getCount(CounterType.VELOCITY) >= 2) { + if (permanent.getCounters(game).getCount(CounterType.VELOCITY) >= 2) { permanent.sacrifice(source.getSourceId(), game); controller.drawCards(2, game); } diff --git a/Mage.Sets/src/mage/cards/k/KytheonHeroOfAkros.java b/Mage.Sets/src/mage/cards/k/KytheonHeroOfAkros.java index 690134360c5..968b0b7eed2 100644 --- a/Mage.Sets/src/mage/cards/k/KytheonHeroOfAkros.java +++ b/Mage.Sets/src/mage/cards/k/KytheonHeroOfAkros.java @@ -41,15 +41,15 @@ import mage.abilities.effects.common.ExileAndReturnTransformedSourceEffect.Gende import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.abilities.keyword.IndestructibleAbility; import mage.abilities.keyword.TransformAbility; -import mage.cards.g.GideonBattleForged; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.cards.g.GideonBattleForged; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Zone; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.watchers.common.AttackedThisCombatWatcher; +import mage.watchers.common.AttackedOrBlockedThisCombatWatcher; /** * @@ -58,26 +58,26 @@ import mage.watchers.common.AttackedThisCombatWatcher; public class KytheonHeroOfAkros extends CardImpl { public KytheonHeroOfAkros(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{W}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}"); this.supertype.add("Legendary"); this.subtype.add("Human"); this.subtype.add("Soldier"); this.power = new MageInt(2); this.toughness = new MageInt(1); - + this.transformable = true; this.secondSideCardClazz = GideonBattleForged.class; - // At end of combat, if Kytheon, Hero of Akros and at least two other creatures attacked this combat, exile Kytheon, + // At end of combat, if Kytheon, Hero of Akros and at least two other creatures attacked this combat, exile Kytheon, // then return him to the battlefield transformed under his owner's control. this.addAbility(new TransformAbility()); - this.addAbility(new ConditionalTriggeredAbility(new EndOfCombatTriggeredAbility(new ExileAndReturnTransformedSourceEffect(Gender.MALE), false), - new KytheonHeroOfAkrosCondition(), "At end of combat, if {this} and at least two other creatures attacked this combat, exile {this}, " + - "then return him to the battlefield transformed under his owner's control."), new AttackedThisCombatWatcher()); - + this.addAbility(new ConditionalTriggeredAbility(new EndOfCombatTriggeredAbility(new ExileAndReturnTransformedSourceEffect(Gender.MALE), false), + new KytheonHeroOfAkrosCondition(), "At end of combat, if {this} and at least two other creatures attacked this combat, exile {this}, " + + "then return him to the battlefield transformed under his owner's control."), new AttackedOrBlockedThisCombatWatcher()); + // {2}{W}: Kytheon gains indestructible until end of turn. this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new GainAbilitySourceEffect(IndestructibleAbility.getInstance(), Duration.EndOfTurn), new ManaCostsImpl<>("{2}{W}"))); - + } public KytheonHeroOfAkros(final KytheonHeroOfAkros card) { @@ -91,16 +91,16 @@ public class KytheonHeroOfAkros extends CardImpl { } class KytheonHeroOfAkrosCondition implements Condition { - + @Override public boolean apply(Game game, Ability source) { Permanent sourceObject = game.getPermanent(source.getSourceId()); if (sourceObject != null) { - AttackedThisCombatWatcher watcher = (AttackedThisCombatWatcher) game.getState().getWatchers().get("AttackedThisCombat"); + AttackedOrBlockedThisCombatWatcher watcher = (AttackedOrBlockedThisCombatWatcher) game.getState().getWatchers().get(AttackedOrBlockedThisCombatWatcher.class.getName()); if (watcher != null) { boolean sourceFound = false; int number = 0; - for (MageObjectReference mor: watcher.getAttackedThisTurnCreatures()) { + for (MageObjectReference mor : watcher.getAttackedThisTurnCreatures()) { if (mor.refersTo(sourceObject, game)) { sourceFound = true; } else { diff --git a/Mage/src/main/java/mage/abilities/condition/common/AttackedOrBlockedThisCombatSourceCondition.java b/Mage/src/main/java/mage/abilities/condition/common/AttackedOrBlockedThisCombatSourceCondition.java new file mode 100644 index 00000000000..81878af71a4 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/condition/common/AttackedOrBlockedThisCombatSourceCondition.java @@ -0,0 +1,52 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package mage.abilities.condition.common; + +import mage.MageObjectReference; +import mage.abilities.Ability; +import mage.abilities.condition.Condition; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.watchers.common.AttackedOrBlockedThisCombatWatcher; + +/** + * + * @author LevelX2 + */ +public class AttackedOrBlockedThisCombatSourceCondition implements Condition { + + private static final AttackedOrBlockedThisCombatSourceCondition fInstance = new AttackedOrBlockedThisCombatSourceCondition(); + + public static Condition getInstance() { + return fInstance; + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent sourceObject = game.getPermanentOrLKIBattlefield(source.getSourceId()); + if (sourceObject != null) { + AttackedOrBlockedThisCombatWatcher watcher = (AttackedOrBlockedThisCombatWatcher) game.getState().getWatchers().get(AttackedOrBlockedThisCombatWatcher.class.getName()); + if (watcher != null) { + for (MageObjectReference mor : watcher.getAttackedThisTurnCreatures()) { + if (mor.refersTo(sourceObject, game)) { + return true; + } + } + for (MageObjectReference mor : watcher.getBlockedThisTurnCreatures()) { + if (mor.refersTo(sourceObject, game)) { + return true; + } + } + } + } + return false; + } + + @Override + public String toString() { + return "{this} attacked or blocked this combat"; + } +} diff --git a/Mage/src/main/java/mage/watchers/common/AttackedThisCombatWatcher.java b/Mage/src/main/java/mage/watchers/common/AttackedOrBlockedThisCombatWatcher.java similarity index 55% rename from Mage/src/main/java/mage/watchers/common/AttackedThisCombatWatcher.java rename to Mage/src/main/java/mage/watchers/common/AttackedOrBlockedThisCombatWatcher.java index 0fa57f12773..e54875d681e 100644 --- a/Mage/src/main/java/mage/watchers/common/AttackedThisCombatWatcher.java +++ b/Mage/src/main/java/mage/watchers/common/AttackedOrBlockedThisCombatWatcher.java @@ -17,37 +17,45 @@ import mage.watchers.Watcher; * * @author LevelX2 */ - -public class AttackedThisCombatWatcher extends Watcher { +public class AttackedOrBlockedThisCombatWatcher extends Watcher { public final Set attackedThisTurnCreatures = new HashSet<>(); + public final Set blockedThisTurnCreatures = new HashSet<>(); - public AttackedThisCombatWatcher() { - super("AttackedThisCombat", WatcherScope.GAME); + public AttackedOrBlockedThisCombatWatcher() { + super(AttackedOrBlockedThisCombatWatcher.class.getName(), WatcherScope.GAME); } - public AttackedThisCombatWatcher(final AttackedThisCombatWatcher watcher) { + public AttackedOrBlockedThisCombatWatcher(final AttackedOrBlockedThisCombatWatcher watcher) { super(watcher); this.attackedThisTurnCreatures.addAll(watcher.attackedThisTurnCreatures); + this.blockedThisTurnCreatures.addAll(watcher.blockedThisTurnCreatures); } @Override public void watch(GameEvent event, Game game) { if (event.getType() == GameEvent.EventType.BEGIN_COMBAT_STEP_PRE) { this.attackedThisTurnCreatures.clear(); - } + } if (event.getType() == GameEvent.EventType.ATTACKER_DECLARED) { - this.attackedThisTurnCreatures.add(new MageObjectReference(event.getSourceId(),game)); + this.attackedThisTurnCreatures.add(new MageObjectReference(event.getSourceId(), game)); + } + if (event.getType() == GameEvent.EventType.BLOCKER_DECLARED) { + this.blockedThisTurnCreatures.add(new MageObjectReference(event.getSourceId(), game)); } } - - public Set getAttackedThisTurnCreatures() { + + public Set getAttackedThisTurnCreatures() { return this.attackedThisTurnCreatures; } + public Set getBlockedThisTurnCreatures() { + return this.blockedThisTurnCreatures; + } + @Override - public AttackedThisCombatWatcher copy() { - return new AttackedThisCombatWatcher(this); + public AttackedOrBlockedThisCombatWatcher copy() { + return new AttackedOrBlockedThisCombatWatcher(this); } } From 5b3c273da78eeab38e0298f9583cd9aec4490a73 Mon Sep 17 00:00:00 2001 From: fireshoes Date: Sat, 7 Jan 2017 16:39:16 -0600 Subject: [PATCH 09/19] [AER] Fix some more card text. --- .../src/mage/cards/m/MerchantsDockhand.java | 2 +- Mage.Sets/src/mage/cards/p/PreciseStrike.java | 131 +++++++++--------- .../mage/cards/r/RishkarPeemaRenegade.java | 2 +- 3 files changed, 70 insertions(+), 65 deletions(-) diff --git a/Mage.Sets/src/mage/cards/m/MerchantsDockhand.java b/Mage.Sets/src/mage/cards/m/MerchantsDockhand.java index 643091b4f4e..eec59421a97 100644 --- a/Mage.Sets/src/mage/cards/m/MerchantsDockhand.java +++ b/Mage.Sets/src/mage/cards/m/MerchantsDockhand.java @@ -145,7 +145,7 @@ class TapXTargetCost extends VariableCostImpl { } public TapXTargetCost() { - super("controlled untapped artifacts you like to tap"); + super("controlled untapped artifacts you would like to tap"); this.text = "Tap X untapped artifacts you control"; } diff --git a/Mage.Sets/src/mage/cards/p/PreciseStrike.java b/Mage.Sets/src/mage/cards/p/PreciseStrike.java index adf9b2268ad..891467b7e1e 100644 --- a/Mage.Sets/src/mage/cards/p/PreciseStrike.java +++ b/Mage.Sets/src/mage/cards/p/PreciseStrike.java @@ -1,63 +1,68 @@ -/* - * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of BetaSteward_at_googlemail.com. - */ -package mage.cards.p; - -import java.util.UUID; -import mage.abilities.effects.common.continuous.BoostTargetEffect; -import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; -import mage.abilities.keyword.FirstStrikeAbility; -import mage.cards.CardImpl; -import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.target.common.TargetCreaturePermanent; - -/** - * - * @author Styxo - */ -public class PreciseStrike extends CardImpl { - - public PreciseStrike(UUID ownerId, CardSetInfo setInfo) { - super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{R}"); - - // Target creature gets +1/+0 and gains first strike until end of turn. - this.getSpellAbility().addEffect(new BoostTargetEffect(1, 0, Duration.EndOfTurn)); - this.getSpellAbility().addEffect(new GainAbilityTargetEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent()); - } - - public PreciseStrike(final PreciseStrike card) { - super(card); - } - - @Override - public PreciseStrike copy() { - return new PreciseStrike(this); - } -} +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.p; + +import java.util.UUID; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author Styxo + */ +public class PreciseStrike extends CardImpl { + + public PreciseStrike(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{R}"); + + // Target creature gets +1/+0 and gains first strike until end of turn. + Effect effect = new BoostTargetEffect(1, 0, Duration.EndOfTurn); + effect.setText("Target creature gets +1/+0"); + this.getSpellAbility().addEffect(effect); + effect = new GainAbilityTargetEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn); + effect.setText("and gains first strike until end of turn"); + this.getSpellAbility().addEffect(effect); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + } + + public PreciseStrike(final PreciseStrike card) { + super(card); + } + + @Override + public PreciseStrike copy() { + return new PreciseStrike(this); + } +} diff --git a/Mage.Sets/src/mage/cards/r/RishkarPeemaRenegade.java b/Mage.Sets/src/mage/cards/r/RishkarPeemaRenegade.java index fa9754e6c01..7c15888396e 100644 --- a/Mage.Sets/src/mage/cards/r/RishkarPeemaRenegade.java +++ b/Mage.Sets/src/mage/cards/r/RishkarPeemaRenegade.java @@ -52,7 +52,7 @@ import mage.target.common.TargetCreaturePermanent; */ public class RishkarPeemaRenegade extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature with a counter on it"); + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Each creature with a counter on it"); static { filter.add(new CounterAnyPredicate()); From e04e69f947aa73446236a0300b08d189cb3bd5ef Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sat, 7 Jan 2017 23:52:55 +0100 Subject: [PATCH 10/19] [AER] Fixed Baral Chief of Compliance triggered ability. --- .../mage/cards/b/BaralChiefOfCompliance.java | 84 ++++--------------- .../src/mage/cards/b/BaralsExpertise.java | 1 - 2 files changed, 15 insertions(+), 70 deletions(-) diff --git a/Mage.Sets/src/mage/cards/b/BaralChiefOfCompliance.java b/Mage.Sets/src/mage/cards/b/BaralChiefOfCompliance.java index 0a18ded7c9e..4ef4168d43b 100644 --- a/Mage.Sets/src/mage/cards/b/BaralChiefOfCompliance.java +++ b/Mage.Sets/src/mage/cards/b/BaralChiefOfCompliance.java @@ -27,8 +27,6 @@ */ package mage.cards.b; -import java.util.HashMap; -import java.util.Map; import java.util.UUID; import mage.MageInt; import mage.abilities.TriggeredAbilityImpl; @@ -38,7 +36,6 @@ import mage.abilities.effects.common.cost.SpellsCostReductionControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.WatcherScope; import mage.constants.Zone; import mage.filter.FilterCard; import mage.filter.predicate.Predicates; @@ -46,10 +43,8 @@ import mage.filter.predicate.mageobject.CardTypePredicate; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; +import mage.game.stack.Spell; import mage.game.stack.StackObject; -import mage.target.Target; -import mage.target.TargetSpell; -import mage.watchers.Watcher; /** * @@ -58,10 +53,11 @@ import mage.watchers.Watcher; public class BaralChiefOfCompliance extends CardImpl { private static final FilterCard filter = new FilterCard("Instant and sorcery spells"); + static { filter.add(Predicates.or( - new CardTypePredicate(CardType.INSTANT), - new CardTypePredicate(CardType.SORCERY) + new CardTypePredicate(CardType.INSTANT), + new CardTypePredicate(CardType.SORCERY) )); } @@ -78,7 +74,7 @@ public class BaralChiefOfCompliance extends CardImpl { this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpellsCostReductionControllerEffect(filter, 1))); // Whenever a spell or ability you control counters a spell, you may draw a card. If you do, discard a card. - this.addAbility(new BaralChiefOfComplianceTriggeredAbility(), new CastedSpellsWithSpellTarget()); + this.addAbility(new BaralChiefOfComplianceTriggeredAbility()); } public BaralChiefOfCompliance(final BaralChiefOfCompliance card) { @@ -113,69 +109,19 @@ class BaralChiefOfComplianceTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - CastedSpellsWithSpellTarget watcher = (CastedSpellsWithSpellTarget) game.getState().getWatchers().get("CastedSpellsWithSpellTarget"); - UUID controllerIdCounter = watcher.getControllerSpell(event.getSourceId(), event.getTargetId()); - return controllerIdCounter != null && controllerIdCounter.equals(controllerId); + StackObject stackObjectThatCountered = (StackObject) game.getStack().getStackObject(event.getSourceId()); + if (stackObjectThatCountered == null) { + stackObjectThatCountered = (StackObject) game.getLastKnownInformation(event.getSourceId(), Zone.STACK); + } + if (stackObjectThatCountered != null && stackObjectThatCountered.getControllerId().equals(getControllerId())) { + StackObject counteredStackObject = (StackObject) game.getLastKnownInformation(event.getTargetId(), Zone.STACK); + return counteredStackObject != null && (counteredStackObject instanceof Spell); + } + return false; } @Override public String getRule() { - return new StringBuilder("Whenever a spell or ability you control counters a spell, ").append(super.getRule()).toString(); + return "Whenever a spell or ability you control counters a spell, " + super.getRule(); } } - -class CastedSpellsWithSpellTarget extends Watcher { - - private final Map casted = new HashMap<>(); - - public CastedSpellsWithSpellTarget() { - super("CastedSpellsWithSpellTarget", WatcherScope.GAME); - } - - public CastedSpellsWithSpellTarget(final CastedSpellsWithSpellTarget watcher) { - super(watcher); - for (Map.Entry entry: watcher.casted.entrySet()) { - casted.put(entry.getKey(), entry.getValue()); - } - } - - @Override - public void watch(GameEvent event, Game game) { - if (event.getType() == GameEvent.EventType.SPELL_CAST || event.getType() == GameEvent.EventType.ACTIVATED_ABILITY) { - StackObject stackObject = game.getStack().getStackObject(event.getTargetId()); - if (stackObject == null) { - stackObject = (StackObject) game.getLastKnownInformation(event.getTargetId(), Zone.STACK); - } - if (stackObject != null && stackObject.getStackAbility() != null) { - for (Target target: stackObject.getStackAbility().getTargets()) { - if (target instanceof TargetSpell && target.getFirstTarget() != null) { - casted.put(getKey(target.getFirstTarget(), stackObject.getSourceId()), stackObject.getControllerId()); - } - } - } - } - } - - private String getKey(UUID targetId, UUID sourceId) { - return new StringBuilder(targetId.toString()).append("_").append(sourceId.toString()).toString(); - } - - public UUID getControllerSpell(UUID sourceId, UUID counteredSpell) { - if (sourceId != null && counteredSpell != null){ - return casted.get(getKey(counteredSpell, sourceId)); - } - return null; - } - - @Override - public void reset() { - super.reset(); - casted.clear(); - } - - @Override - public CastedSpellsWithSpellTarget copy() { - return new CastedSpellsWithSpellTarget(this); - } - -} diff --git a/Mage.Sets/src/mage/cards/b/BaralsExpertise.java b/Mage.Sets/src/mage/cards/b/BaralsExpertise.java index 13e38e50b4f..67c40d1053e 100644 --- a/Mage.Sets/src/mage/cards/b/BaralsExpertise.java +++ b/Mage.Sets/src/mage/cards/b/BaralsExpertise.java @@ -54,7 +54,6 @@ public class BaralsExpertise extends CardImpl { public BaralsExpertise(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{U}{U}"); - // Return up to three target artifacts and/or creatures to their owners' hands. getSpellAbility().addEffect(new ReturnToHandTargetEffect()); getSpellAbility().addTarget(new TargetPermanent(0, 3, filter, false)); From a75e4f4fcb4c3e1d9b160fece2f048e94f8a2674 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sat, 7 Jan 2017 23:53:47 +0100 Subject: [PATCH 11/19] Fixed that adding counters to players did not work correctly (e.g. Winding Constrictor). --- Mage.Sets/src/mage/cards/i/IchorRats.java | 13 ++++++------- Mage/src/main/java/mage/players/PlayerImpl.java | 2 +- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/Mage.Sets/src/mage/cards/i/IchorRats.java b/Mage.Sets/src/mage/cards/i/IchorRats.java index b0ba58b1db3..5b9233e7ee9 100644 --- a/Mage.Sets/src/mage/cards/i/IchorRats.java +++ b/Mage.Sets/src/mage/cards/i/IchorRats.java @@ -25,12 +25,9 @@ * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package mage.cards.i; import java.util.UUID; - -import mage.constants.CardType; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; @@ -38,6 +35,7 @@ import mage.abilities.effects.OneShotEffect; import mage.abilities.keyword.InfectAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.CardType; import mage.constants.Outcome; import mage.counters.CounterType; import mage.game.Game; @@ -49,8 +47,8 @@ import mage.players.Player; */ public class IchorRats extends CardImpl { - public IchorRats (UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{B}{B}"); + public IchorRats(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}{B}"); this.subtype.add("Rat"); this.power = new MageInt(2); @@ -59,7 +57,7 @@ public class IchorRats extends CardImpl { this.addAbility(new EntersBattlefieldTriggeredAbility(new IchorRatsEffect(), false)); } - public IchorRats (final IchorRats card) { + public IchorRats(final IchorRats card) { super(card); } @@ -71,6 +69,7 @@ public class IchorRats extends CardImpl { } class IchorRatsEffect extends OneShotEffect { + public IchorRatsEffect() { super(Outcome.Damage); staticText = "each player gets a poison counter"; @@ -82,7 +81,7 @@ class IchorRatsEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - for (UUID playerId : game.getPlayerList()) { + for (UUID playerId : game.getState().getPlayerList(source.getControllerId())) { Player player = game.getPlayer(playerId); if (player != null) { player.addCounters(CounterType.POISON.createInstance(), game); diff --git a/Mage/src/main/java/mage/players/PlayerImpl.java b/Mage/src/main/java/mage/players/PlayerImpl.java index ef8067c3edf..9efa5814256 100644 --- a/Mage/src/main/java/mage/players/PlayerImpl.java +++ b/Mage/src/main/java/mage/players/PlayerImpl.java @@ -1856,7 +1856,7 @@ public abstract class PlayerImpl implements Player, Serializable { int finalAmount = amount; for (int i = 0; i < amount; i++) { Counter eventCounter = counter.copy(); - eventCounter.remove(amount - 1); + eventCounter.remove(eventCounter.getCount() - 1); GameEvent event = GameEvent.getEvent(EventType.ADD_COUNTER, playerId, null, playerId, counter.getName(), 1); if (!game.replaceEvent(event)) { getCounters().addCounter(eventCounter); From ee203cf98141c6741f9d6081c452d45617b7ebcb Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sun, 8 Jan 2017 01:36:05 +0100 Subject: [PATCH 12/19] Xmage Release 1.4.20V0 --- Mage.Client/pom.xml | 2 +- Mage.Common/pom.xml | 2 +- Mage.Common/src/mage/utils/MageVersion.java | 4 +- Mage.Plugins/Mage.Counter.Plugin/pom.xml | 2 +- Mage.Plugins/pom.xml | 2 +- Mage.Server.Console/pom.xml | 2 +- .../Mage.Deck.Constructed/pom.xml | 2 +- Mage.Server.Plugins/Mage.Deck.Limited/pom.xml | 2 +- .../Mage.Game.CommanderDuel/pom.xml | 2 +- .../Mage.Game.CommanderFreeForAll/pom.xml | 2 +- .../Mage.Game.FreeForAll/pom.xml | 2 +- .../Mage.Game.MomirDuel/pom.xml | 2 +- .../Mage.Game.TinyLeadersDuel/pom.xml | 2 +- .../Mage.Game.TwoPlayerDuel/pom.xml | 2 +- .../Mage.Player.AI.DraftBot/pom.xml | 2 +- Mage.Server.Plugins/Mage.Player.AI.MA/pom.xml | 2 +- Mage.Server.Plugins/Mage.Player.AI/pom.xml | 2 +- .../Mage.Player.AIMCTS/pom.xml | 2 +- .../Mage.Player.AIMinimax/pom.xml | 2 +- Mage.Server.Plugins/Mage.Player.Human/pom.xml | 2 +- .../Mage.Tournament.BoosterDraft/pom.xml | 2 +- .../Mage.Tournament.Constructed/pom.xml | 2 +- .../Mage.Tournament.Sealed/pom.xml | 2 +- Mage.Server.Plugins/pom.xml | 2 +- Mage.Server/pom.xml | 2 +- Mage.Sets/pom.xml | 2 +- Mage.Stats/pom.xml | 2 +- Mage.Tests/pom.xml | 2 +- Mage.Updater/pom.xml | 2 +- Mage.Verify/pom.xml | 2 +- Mage/pom.xml | 346 +++++++++--------- .../mage/cards/repository/CardRepository.java | 4 +- Utils/release/getting_implemented_cards.txt | 4 + pom.xml | 4 +- 34 files changed, 212 insertions(+), 208 deletions(-) diff --git a/Mage.Client/pom.xml b/Mage.Client/pom.xml index a2ec9aebd2a..818f319f927 100644 --- a/Mage.Client/pom.xml +++ b/Mage.Client/pom.xml @@ -6,7 +6,7 @@ org.mage mage-root - 1.4.19 + 1.4.20 org.mage diff --git a/Mage.Common/pom.xml b/Mage.Common/pom.xml index 1222c3954fb..e82a698d932 100644 --- a/Mage.Common/pom.xml +++ b/Mage.Common/pom.xml @@ -7,7 +7,7 @@ org.mage mage-root - 1.4.19 + 1.4.20 mage-common diff --git a/Mage.Common/src/mage/utils/MageVersion.java b/Mage.Common/src/mage/utils/MageVersion.java index 968fae23493..c90c6912cbe 100644 --- a/Mage.Common/src/mage/utils/MageVersion.java +++ b/Mage.Common/src/mage/utils/MageVersion.java @@ -40,8 +40,8 @@ public class MageVersion implements Serializable, Comparable { */ public final static int MAGE_VERSION_MAJOR = 1; public final static int MAGE_VERSION_MINOR = 4; - public final static int MAGE_VERSION_PATCH = 19; - public final static String MAGE_VERSION_MINOR_PATCH = "V2"; + public final static int MAGE_VERSION_PATCH = 20; + public final static String MAGE_VERSION_MINOR_PATCH = "V0"; public final static String MAGE_VERSION_INFO = ""; private final int major; diff --git a/Mage.Plugins/Mage.Counter.Plugin/pom.xml b/Mage.Plugins/Mage.Counter.Plugin/pom.xml index 1b72545fd9c..14c592301c1 100644 --- a/Mage.Plugins/Mage.Counter.Plugin/pom.xml +++ b/Mage.Plugins/Mage.Counter.Plugin/pom.xml @@ -7,7 +7,7 @@ org.mage mage-plugins - 1.4.19 + 1.4.20 mage-counter-plugin diff --git a/Mage.Plugins/pom.xml b/Mage.Plugins/pom.xml index a646bd2c51b..d3103062fbc 100644 --- a/Mage.Plugins/pom.xml +++ b/Mage.Plugins/pom.xml @@ -7,7 +7,7 @@ org.mage mage-root - 1.4.19 + 1.4.20 mage-plugins diff --git a/Mage.Server.Console/pom.xml b/Mage.Server.Console/pom.xml index b618d263c0f..0beffafde59 100644 --- a/Mage.Server.Console/pom.xml +++ b/Mage.Server.Console/pom.xml @@ -6,7 +6,7 @@ org.mage mage-root - 1.4.19 + 1.4.20 org.mage diff --git a/Mage.Server.Plugins/Mage.Deck.Constructed/pom.xml b/Mage.Server.Plugins/Mage.Deck.Constructed/pom.xml index cca7de8b2f0..f0bf68970d3 100644 --- a/Mage.Server.Plugins/Mage.Deck.Constructed/pom.xml +++ b/Mage.Server.Plugins/Mage.Deck.Constructed/pom.xml @@ -7,7 +7,7 @@ org.mage mage-server-plugins - 1.4.19 + 1.4.20 mage-deck-constructed diff --git a/Mage.Server.Plugins/Mage.Deck.Limited/pom.xml b/Mage.Server.Plugins/Mage.Deck.Limited/pom.xml index cecd477d96a..0af678370fc 100644 --- a/Mage.Server.Plugins/Mage.Deck.Limited/pom.xml +++ b/Mage.Server.Plugins/Mage.Deck.Limited/pom.xml @@ -7,7 +7,7 @@ org.mage mage-server-plugins - 1.4.19 + 1.4.20 mage-deck-limited diff --git a/Mage.Server.Plugins/Mage.Game.CommanderDuel/pom.xml b/Mage.Server.Plugins/Mage.Game.CommanderDuel/pom.xml index 4ef6ccff856..4f11eea8c43 100644 --- a/Mage.Server.Plugins/Mage.Game.CommanderDuel/pom.xml +++ b/Mage.Server.Plugins/Mage.Game.CommanderDuel/pom.xml @@ -7,7 +7,7 @@ org.mage mage-server-plugins - 1.4.19 + 1.4.20 mage-game-commanderduel diff --git a/Mage.Server.Plugins/Mage.Game.CommanderFreeForAll/pom.xml b/Mage.Server.Plugins/Mage.Game.CommanderFreeForAll/pom.xml index 364a9cab791..3e20eb3e960 100644 --- a/Mage.Server.Plugins/Mage.Game.CommanderFreeForAll/pom.xml +++ b/Mage.Server.Plugins/Mage.Game.CommanderFreeForAll/pom.xml @@ -6,7 +6,7 @@ org.mage mage-server-plugins - 1.4.19 + 1.4.20 mage-game-commanderfreeforall diff --git a/Mage.Server.Plugins/Mage.Game.FreeForAll/pom.xml b/Mage.Server.Plugins/Mage.Game.FreeForAll/pom.xml index ffe9de7e746..3a8f95b6961 100644 --- a/Mage.Server.Plugins/Mage.Game.FreeForAll/pom.xml +++ b/Mage.Server.Plugins/Mage.Game.FreeForAll/pom.xml @@ -7,7 +7,7 @@ org.mage mage-server-plugins - 1.4.19 + 1.4.20 mage-game-freeforall diff --git a/Mage.Server.Plugins/Mage.Game.MomirDuel/pom.xml b/Mage.Server.Plugins/Mage.Game.MomirDuel/pom.xml index d94283ec567..b7c46693585 100644 --- a/Mage.Server.Plugins/Mage.Game.MomirDuel/pom.xml +++ b/Mage.Server.Plugins/Mage.Game.MomirDuel/pom.xml @@ -7,7 +7,7 @@ org.mage mage-server-plugins - 1.4.19 + 1.4.20 mage-game-momirduel diff --git a/Mage.Server.Plugins/Mage.Game.TinyLeadersDuel/pom.xml b/Mage.Server.Plugins/Mage.Game.TinyLeadersDuel/pom.xml index adb73d5f9a7..48a4f3ac524 100644 --- a/Mage.Server.Plugins/Mage.Game.TinyLeadersDuel/pom.xml +++ b/Mage.Server.Plugins/Mage.Game.TinyLeadersDuel/pom.xml @@ -7,7 +7,7 @@ org.mage mage-server-plugins - 1.4.19 + 1.4.20 mage-game-tinyleadersduel diff --git a/Mage.Server.Plugins/Mage.Game.TwoPlayerDuel/pom.xml b/Mage.Server.Plugins/Mage.Game.TwoPlayerDuel/pom.xml index 525b3829e20..bb729f5ee93 100644 --- a/Mage.Server.Plugins/Mage.Game.TwoPlayerDuel/pom.xml +++ b/Mage.Server.Plugins/Mage.Game.TwoPlayerDuel/pom.xml @@ -7,7 +7,7 @@ org.mage mage-server-plugins - 1.4.19 + 1.4.20 mage-game-twoplayerduel diff --git a/Mage.Server.Plugins/Mage.Player.AI.DraftBot/pom.xml b/Mage.Server.Plugins/Mage.Player.AI.DraftBot/pom.xml index 37e8596841b..f55a49adc42 100644 --- a/Mage.Server.Plugins/Mage.Player.AI.DraftBot/pom.xml +++ b/Mage.Server.Plugins/Mage.Player.AI.DraftBot/pom.xml @@ -7,7 +7,7 @@ org.mage mage-server-plugins - 1.4.19 + 1.4.20 mage-player-ai-draftbot diff --git a/Mage.Server.Plugins/Mage.Player.AI.MA/pom.xml b/Mage.Server.Plugins/Mage.Player.AI.MA/pom.xml index b738c619bd0..791a6036cf0 100644 --- a/Mage.Server.Plugins/Mage.Player.AI.MA/pom.xml +++ b/Mage.Server.Plugins/Mage.Player.AI.MA/pom.xml @@ -7,7 +7,7 @@ org.mage mage-server-plugins - 1.4.19 + 1.4.20 mage-player-ai-ma diff --git a/Mage.Server.Plugins/Mage.Player.AI/pom.xml b/Mage.Server.Plugins/Mage.Player.AI/pom.xml index d6ec02212e9..53c235c45f5 100644 --- a/Mage.Server.Plugins/Mage.Player.AI/pom.xml +++ b/Mage.Server.Plugins/Mage.Player.AI/pom.xml @@ -7,7 +7,7 @@ org.mage mage-server-plugins - 1.4.19 + 1.4.20 mage-player-ai diff --git a/Mage.Server.Plugins/Mage.Player.AIMCTS/pom.xml b/Mage.Server.Plugins/Mage.Player.AIMCTS/pom.xml index 417506a20d1..2ff383a06bd 100644 --- a/Mage.Server.Plugins/Mage.Player.AIMCTS/pom.xml +++ b/Mage.Server.Plugins/Mage.Player.AIMCTS/pom.xml @@ -7,7 +7,7 @@ org.mage mage-server-plugins - 1.4.19 + 1.4.20 mage-player-ai-mcts diff --git a/Mage.Server.Plugins/Mage.Player.AIMinimax/pom.xml b/Mage.Server.Plugins/Mage.Player.AIMinimax/pom.xml index 6e46b343b25..ea6281b6747 100644 --- a/Mage.Server.Plugins/Mage.Player.AIMinimax/pom.xml +++ b/Mage.Server.Plugins/Mage.Player.AIMinimax/pom.xml @@ -7,7 +7,7 @@ org.mage mage-server-plugins - 1.4.19 + 1.4.20 mage-player-aiminimax diff --git a/Mage.Server.Plugins/Mage.Player.Human/pom.xml b/Mage.Server.Plugins/Mage.Player.Human/pom.xml index ced2793326a..9973b7c2d83 100644 --- a/Mage.Server.Plugins/Mage.Player.Human/pom.xml +++ b/Mage.Server.Plugins/Mage.Player.Human/pom.xml @@ -7,7 +7,7 @@ org.mage mage-server-plugins - 1.4.19 + 1.4.20 mage-player-human diff --git a/Mage.Server.Plugins/Mage.Tournament.BoosterDraft/pom.xml b/Mage.Server.Plugins/Mage.Tournament.BoosterDraft/pom.xml index a467978216a..9f1bf92794c 100644 --- a/Mage.Server.Plugins/Mage.Tournament.BoosterDraft/pom.xml +++ b/Mage.Server.Plugins/Mage.Tournament.BoosterDraft/pom.xml @@ -7,7 +7,7 @@ org.mage mage-server-plugins - 1.4.19 + 1.4.20 mage-tournament-boosterdraft diff --git a/Mage.Server.Plugins/Mage.Tournament.Constructed/pom.xml b/Mage.Server.Plugins/Mage.Tournament.Constructed/pom.xml index 95b6a1bd96c..0f0513588a6 100644 --- a/Mage.Server.Plugins/Mage.Tournament.Constructed/pom.xml +++ b/Mage.Server.Plugins/Mage.Tournament.Constructed/pom.xml @@ -7,7 +7,7 @@ org.mage mage-server-plugins - 1.4.19 + 1.4.20 mage-tournament-constructed diff --git a/Mage.Server.Plugins/Mage.Tournament.Sealed/pom.xml b/Mage.Server.Plugins/Mage.Tournament.Sealed/pom.xml index 082df783f90..db716440c0f 100644 --- a/Mage.Server.Plugins/Mage.Tournament.Sealed/pom.xml +++ b/Mage.Server.Plugins/Mage.Tournament.Sealed/pom.xml @@ -7,7 +7,7 @@ org.mage mage-server-plugins - 1.4.19 + 1.4.20 mage-tournament-sealed diff --git a/Mage.Server.Plugins/pom.xml b/Mage.Server.Plugins/pom.xml index 6000d6d9016..a56b5b66803 100644 --- a/Mage.Server.Plugins/pom.xml +++ b/Mage.Server.Plugins/pom.xml @@ -6,7 +6,7 @@ org.mage mage-root - 1.4.19 + 1.4.20 mage-server-plugins diff --git a/Mage.Server/pom.xml b/Mage.Server/pom.xml index 6e08bf39bbc..fbd5e364628 100644 --- a/Mage.Server/pom.xml +++ b/Mage.Server/pom.xml @@ -6,7 +6,7 @@ org.mage mage-root - 1.4.19 + 1.4.20 mage-server diff --git a/Mage.Sets/pom.xml b/Mage.Sets/pom.xml index 7262a6b8c3e..18096ae963a 100644 --- a/Mage.Sets/pom.xml +++ b/Mage.Sets/pom.xml @@ -7,7 +7,7 @@ org.mage mage-root - 1.4.19 + 1.4.20 org.mage diff --git a/Mage.Stats/pom.xml b/Mage.Stats/pom.xml index 7f87742109a..12091c9ccd1 100644 --- a/Mage.Stats/pom.xml +++ b/Mage.Stats/pom.xml @@ -6,7 +6,7 @@ org.mage mage-root - 1.4.19 + 1.4.20 org.mage diff --git a/Mage.Tests/pom.xml b/Mage.Tests/pom.xml index 5e6701323c6..2ea14d0ee4e 100644 --- a/Mage.Tests/pom.xml +++ b/Mage.Tests/pom.xml @@ -6,7 +6,7 @@ org.mage mage-root - 1.4.19 + 1.4.20 mage-tests diff --git a/Mage.Updater/pom.xml b/Mage.Updater/pom.xml index 5474a4706ce..a32ecc03324 100644 --- a/Mage.Updater/pom.xml +++ b/Mage.Updater/pom.xml @@ -5,7 +5,7 @@ mage-root org.mage - 1.4.19 + 1.4.20 4.0.0 diff --git a/Mage.Verify/pom.xml b/Mage.Verify/pom.xml index 3986a6cc4f3..649f089e9f1 100644 --- a/Mage.Verify/pom.xml +++ b/Mage.Verify/pom.xml @@ -6,7 +6,7 @@ org.mage mage-root - 1.4.19 + 1.4.20 mage-verify diff --git a/Mage/pom.xml b/Mage/pom.xml index f18623fbce2..481427be7eb 100644 --- a/Mage/pom.xml +++ b/Mage/pom.xml @@ -1,173 +1,173 @@ - - - 4.0.0 - - - org.mage - mage-root - 1.4.19 - - - mage - jar - Mage Framework - - - - log4j - log4j - jar - - - - com.h2database - h2 - 1.4.187 - runtime - - - com.j256.ormlite - ormlite-jdbc - 4.48 - - - junit - junit - - - com.google.protobuf - protobuf-java - ${protobuf.version} - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - - maven-resources-plugin - - UTF-8 - - - - - - - org.apache.maven.plugins - maven-dependency-plugin - ${maven-dependency-plugin.version} - - - copy-protoc - generate-sources - - copy - - - - - com.google.protobuf - protoc - ${protobuf.version} - ${os.detected.classifier} - exe - true - ${project.build.directory} - - - - - - - - - org.apache.maven.plugins - maven-antrun-plugin - ${maven-antrun-plugin.version} - - - exec-protoc - generate-sources - - - - - - - - - - - - - - - - - - - - - - - run - - - - - - - org.codehaus.mojo - build-helper-maven-plugin - ${build-helper-maven-plugin.version} - - - add-classes - generate-sources - - add-source - - - - ${protobuf.output.directory} - - - - - - - - mage - - - - - - kr.motd.maven - os-maven-plugin - ${os-maven-plugin.version} - - - - - - - - ${project.basedir}/src/main/proto - ${project.build.directory}/generated-sources - - - 1.9.1 - 1.8 - 2.10 - 2.4.2 - 1.4.1.Final - 3.0.0-beta-1 - - - + + + 4.0.0 + + + org.mage + mage-root + 1.4.20 + + + mage + jar + Mage Framework + + + + log4j + log4j + jar + + + + com.h2database + h2 + 1.4.187 + runtime + + + com.j256.ormlite + ormlite-jdbc + 4.48 + + + junit + junit + + + com.google.protobuf + protobuf-java + ${protobuf.version} + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + maven-resources-plugin + + UTF-8 + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + ${maven-dependency-plugin.version} + + + copy-protoc + generate-sources + + copy + + + + + com.google.protobuf + protoc + ${protobuf.version} + ${os.detected.classifier} + exe + true + ${project.build.directory} + + + + + + + + + org.apache.maven.plugins + maven-antrun-plugin + ${maven-antrun-plugin.version} + + + exec-protoc + generate-sources + + + + + + + + + + + + + + + + + + + + + + + run + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + ${build-helper-maven-plugin.version} + + + add-classes + generate-sources + + add-source + + + + ${protobuf.output.directory} + + + + + + + + mage + + + + + + kr.motd.maven + os-maven-plugin + ${os-maven-plugin.version} + + + + + + + + ${project.basedir}/src/main/proto + ${project.build.directory}/generated-sources + + + 1.9.1 + 1.8 + 2.10 + 2.4.2 + 1.4.1.Final + 3.0.0-beta-1 + + + diff --git a/Mage/src/main/java/mage/cards/repository/CardRepository.java b/Mage/src/main/java/mage/cards/repository/CardRepository.java index e68aa969aaf..d5c109e16eb 100644 --- a/Mage/src/main/java/mage/cards/repository/CardRepository.java +++ b/Mage/src/main/java/mage/cards/repository/CardRepository.java @@ -58,9 +58,9 @@ public enum CardRepository { private static final String JDBC_URL = "jdbc:h2:file:./db/cards.h2;AUTO_SERVER=TRUE"; private static final String VERSION_ENTITY_NAME = "card"; // raise this if db structure was changed - private static final long CARD_DB_VERSION = 49; + private static final long CARD_DB_VERSION = 50; // raise this if new cards were added to the server - private static final long CARD_CONTENT_VERSION = 66; + private static final long CARD_CONTENT_VERSION = 67; private final TreeSet landTypes = new TreeSet(); private Dao cardDao; private Set classNames; diff --git a/Utils/release/getting_implemented_cards.txt b/Utils/release/getting_implemented_cards.txt index 107dcd5332e..7f199775431 100644 --- a/Utils/release/getting_implemented_cards.txt +++ b/Utils/release/getting_implemented_cards.txt @@ -120,6 +120,10 @@ git log 7481b7f5b2e82698506a7dcdda3d5d335664bd60..head --diff-filter=A --name-st since 1.4.19V1 git log 61dd62b148ece4c0f9b45cb7ddbc4a2515cb7615..head --diff-filter=A --name-status | sed -ne "s/^A[^u]Mage.Sets\/src\/mage\/cards\///p" | sort > added_cards.txt +since 1.4.20V0 +git log 13659e064c0bd4e757e3030f236e04e2bd3dd810..head --diff-filter=A --name-status | sed -ne "s/^A[^u]Mage.Sets\/src\/mage\/cards\///p" | sort > added_cards.txt + + 3. Copy added_cards.txt to trunk\Utils folder 4. Run script: diff --git a/pom.xml b/pom.xml index ea69799e79d..86548cf48cd 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.mage mage-root - 1.4.19 + 1.4.20 pom Mage Root Mage Root POM @@ -84,7 +84,7 @@ - 1.4.19 + 1.4.20 UTF-8 From 0de89ca5b773f37ddf449ba40d4874c93e46c2bc Mon Sep 17 00:00:00 2001 From: spjspj Date: Sun, 8 Jan 2017 11:57:16 +1100 Subject: [PATCH 13/19] Some Chat Manager updates --- Mage.Server/src/main/java/mage/server/ChatManager.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Mage.Server/src/main/java/mage/server/ChatManager.java b/Mage.Server/src/main/java/mage/server/ChatManager.java index 06ed16d14d8..272ea8e9eb1 100644 --- a/Mage.Server/src/main/java/mage/server/ChatManager.java +++ b/Mage.Server/src/main/java/mage/server/ChatManager.java @@ -127,20 +127,23 @@ public class ChatManager { } if (!messageType.equals(MessageType.GAME)) { - + User user = UserManager.getInstance().getUserByName(userName); if (message != null && userName != null && !userName.equals("")) { if (message.equals(userMessages.get(userName))) { // prevent identical messages + String informUser = "Your message appears to be identical to your last message"; + chatSessions.get(chatId).broadcastInfoToUser(user, informUser); return; } userMessages.put(userName, message); if (containsSwearing(message)) { + String informUser = "Your message appears to contain profanity"; + chatSessions.get(chatId).broadcastInfoToUser(user, informUser); return; } } if (messageType.equals(MessageType.TALK)) { - User user = UserManager.getInstance().getUserByName(userName); if (user != null) { if (user.getChatLockedUntil() != null) { if (user.getChatLockedUntil().compareTo(Calendar.getInstance().getTime()) > 0) { From 4a5dc3c67d7630c4dc05473928ed9d60c9d24249 Mon Sep 17 00:00:00 2001 From: spjspj Date: Sun, 8 Jan 2017 17:05:51 +1100 Subject: [PATCH 14/19] Chat Manager - Add [Card Name] for colour highlighting of implemented cards --- .../main/java/mage/server/ChatManager.java | 43 +++++++++++++++++-- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/Mage.Server/src/main/java/mage/server/ChatManager.java b/Mage.Server/src/main/java/mage/server/ChatManager.java index 272ea8e9eb1..6ee8435d10e 100644 --- a/Mage.Server/src/main/java/mage/server/ChatManager.java +++ b/Mage.Server/src/main/java/mage/server/ChatManager.java @@ -33,6 +33,10 @@ import java.util.HashMap; import java.util.Locale; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import mage.cards.repository.CardInfo; +import mage.cards.repository.CardRepository; import mage.server.util.SystemUtil; import mage.view.ChatMessage.MessageColor; import mage.view.ChatMessage.MessageType; @@ -105,14 +109,16 @@ public class ChatManager { public void broadcast(UUID chatId, String userName, String message, MessageColor color, boolean withTime, MessageType messageType) { this.broadcast(chatId, userName, message, color, withTime, messageType, null); } - + private boolean containsSwearing(String message) { if (message != null && message.toLowerCase().matches("^.*(anal|asshole|balls|bastard|bitch|blowjob|cock|crap|cunt|cum|damn|dick|dildo|douche|fag|fuck|idiot|moron|penis|piss|prick|pussy|rape|rapist|sex|screw|shit|slut|vagina).*$")) { return true; } return false; } - + + Pattern cardNamePattern = Pattern.compile("\\[(.*?)\\]"); + public void broadcast(UUID chatId, String userName, String message, MessageColor color, boolean withTime, MessageType messageType, SoundToPlay soundToPlay) { ChatSession chatSession = chatSessions.get(chatId); if (chatSession != null) { @@ -129,14 +135,42 @@ public class ChatManager { if (!messageType.equals(MessageType.GAME)) { User user = UserManager.getInstance().getUserByName(userName); if (message != null && userName != null && !userName.equals("")) { + if (message.equals(userMessages.get(userName))) { // prevent identical messages String informUser = "Your message appears to be identical to your last message"; chatSessions.get(chatId).broadcastInfoToUser(user, informUser); return; } + + String messageToCheck = message; + Matcher matchPattern = cardNamePattern.matcher(message); + while (matchPattern.find()) { + String cardName = matchPattern.group(1); + CardInfo cardInfo = CardRepository.instance.findPreferedCoreExpansionCard(cardName, true); + if (cardInfo != null) { + String colour = "silver"; + if (cardInfo.getCard().getColor(null).isMulticolored()) { + colour = "yellow"; + } else if (cardInfo.getCard().getColor(null).isWhite()) { + colour = "white"; + } else if (cardInfo.getCard().getColor(null).isBlue()) { + colour = "blue"; + } else if (cardInfo.getCard().getColor(null).isBlack()) { + colour = "black"; + } else if (cardInfo.getCard().getColor(null).isRed()) { + colour = "red"; + } else if (cardInfo.getCard().getColor(null).isGreen()) { + colour = "green"; + } + messageToCheck = messageToCheck.replaceFirst("\\[" + cardName + "\\]", "card"); + String displayCardName = "" + cardName + ""; + message = message.replaceFirst("\\[" + cardName + "\\]", displayCardName); + } + } + userMessages.put(userName, message); - if (containsSwearing(message)) { + if (containsSwearing(messageToCheck)) { String informUser = "Your message appears to contain profanity"; chatSessions.get(chatId).broadcastInfoToUser(user, informUser); return; @@ -166,7 +200,8 @@ public class ChatManager { + "
\\history or \\h [username] - shows the history of a player" + "
\\me - shows the history of the current player" + "
\\list or \\l - Show a list of commands" - + "
\\whisper or \\w [player name] [text] - whisper to the player with the given name"; + + "
\\whisper or \\w [player name] [text] - whisper to the player with the given name" + + "
[Card Name] - Show a highlighted card name"; private boolean performUserCommand(User user, String message, UUID chatId, boolean doError) { String command = message.substring(1).trim().toUpperCase(Locale.ENGLISH); From fa4cf8161dc1f5e343a26ed0b8695c727e034f84 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sun, 8 Jan 2017 10:16:08 +0100 Subject: [PATCH 15/19] * Added missing creature type "Servo" to the creature type list. --- Mage/src/main/java/mage/cards/repository/CardRepository.java | 1 + 1 file changed, 1 insertion(+) diff --git a/Mage/src/main/java/mage/cards/repository/CardRepository.java b/Mage/src/main/java/mage/cards/repository/CardRepository.java index d5c109e16eb..e0b8a494958 100644 --- a/Mage/src/main/java/mage/cards/repository/CardRepository.java +++ b/Mage/src/main/java/mage/cards/repository/CardRepository.java @@ -277,6 +277,7 @@ public enum CardRepository { subtypes.add("Saproling"); subtypes.add("Scion"); subtypes.add("Serf"); + subtypes.add("Servo"); subtypes.add("Splinter"); subtypes.add("Survivor"); subtypes.add("Tetravite"); From 4dd023716eb02129aaf0d3a155994041c077009b Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sun, 8 Jan 2017 10:35:46 +0100 Subject: [PATCH 16/19] * Added another general static filter class. --- Mage.Sets/src/mage/cards/a/AetherBarrier.java | 21 +-- .../mage/cards/a/AnimarSoulOfElements.java | 12 +- .../mage/cards/e/EndrekSahrMasterBreeder.java | 13 +- Mage.Sets/src/mage/cards/e/Equilibrium.java | 18 +-- .../mage/cards/g/GarrukCallerOfBeasts.java | 11 +- Mage.Sets/src/mage/cards/h/HalcyonGlaze.java | 15 +-- .../mage/cards/k/KarametraGodOfHarvests.java | 8 +- .../mage/cards/l/LifecraftersBestiary.java | 6 +- .../src/mage/cards/m/MaskedAdmirers.java | 12 +- Mage.Sets/src/mage/cards/o/Onslaught.java | 13 +- .../src/mage/cards/p/PrimevalBounty.java | 11 +- .../src/mage/cards/p/PrimordialSage.java | 15 +-- .../mage/cards/q/QuestForTheHolyRelic.java | 13 +- .../src/mage/cards/s/SkitteringHorror.java | 13 +- .../mage/cards/s/SkitteringMonstrosity.java | 13 +- .../src/mage/cards/s/SkitteringSkirge.java | 15 +-- Mage.Sets/src/mage/cards/s/StrawGolem.java | 126 +++++++++--------- Mage.Sets/src/mage/cards/t/Tangleroot.java | 11 +- .../src/mage/cards/z/ZendikarResurgent.java | 14 +- .../main/java/mage/filter/StaticFilters.java | 3 + 20 files changed, 133 insertions(+), 230 deletions(-) diff --git a/Mage.Sets/src/mage/cards/a/AetherBarrier.java b/Mage.Sets/src/mage/cards/a/AetherBarrier.java index 7e9e69c5d04..d3bb1c3d57f 100644 --- a/Mage.Sets/src/mage/cards/a/AetherBarrier.java +++ b/Mage.Sets/src/mage/cards/a/AetherBarrier.java @@ -38,8 +38,7 @@ import mage.constants.CardType; import mage.constants.SetTargetPointer; import mage.constants.Zone; import mage.filter.FilterPermanent; -import mage.filter.FilterSpell; -import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.StaticFilters; import mage.game.Game; import mage.players.Player; @@ -49,22 +48,12 @@ import mage.players.Player; */ public class AetherBarrier extends CardImpl { - private static final FilterSpell filter = new FilterSpell("a creature spell"); - static { - filter.add(new CardTypePredicate(CardType.CREATURE)); - } - public AetherBarrier(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}"); // Whenever a player casts a creature spell, that player sacrifices a permanent unless he or she pays {1}. - this.addAbility(new SpellCastAllTriggeredAbility( - Zone.BATTLEFIELD, - new AetherBarrierEffect(), - filter, - false, - SetTargetPointer.PLAYER - )); + this.addAbility(new SpellCastAllTriggeredAbility(Zone.BATTLEFIELD, new AetherBarrierEffect(), + StaticFilters.FILTER_SPELL_A_CREATURE, false, SetTargetPointer.PLAYER)); } public AetherBarrier(final AetherBarrier card) { @@ -105,4 +94,4 @@ class AetherBarrierEffect extends SacrificeEffect { } return false; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/a/AnimarSoulOfElements.java b/Mage.Sets/src/mage/cards/a/AnimarSoulOfElements.java index d5fa20e12c7..b93ef3c5acb 100644 --- a/Mage.Sets/src/mage/cards/a/AnimarSoulOfElements.java +++ b/Mage.Sets/src/mage/cards/a/AnimarSoulOfElements.java @@ -47,8 +47,7 @@ import mage.constants.Duration; import mage.constants.Outcome; import mage.constants.Zone; import mage.counters.CounterType; -import mage.filter.FilterSpell; -import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; import mage.util.CardUtil; @@ -59,13 +58,8 @@ import mage.util.CardUtil; */ public class AnimarSoulOfElements extends CardImpl { - private static final FilterSpell filterSpell = new FilterSpell("a creature spell"); - static { - filterSpell.add(new CardTypePredicate(CardType.CREATURE)); - } - public AnimarSoulOfElements(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{U}{R}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{U}{R}{G}"); this.supertype.add("Legendary"); this.subtype.add("Elemental"); @@ -76,7 +70,7 @@ public class AnimarSoulOfElements extends CardImpl { this.addAbility(ProtectionAbility.from(ObjectColor.WHITE, ObjectColor.BLACK)); // Whenever you cast a creature spell, put a +1/+1 counter on Animar, Soul of Elements. - this.addAbility(new SpellCastControllerTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance()), filterSpell, false)); + this.addAbility(new SpellCastControllerTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance()), StaticFilters.FILTER_SPELL_A_CREATURE, false)); // Creature spells you cast cost {1} less to cast for each +1/+1 counter on Animar. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new AnimarCostReductionEffect())); diff --git a/Mage.Sets/src/mage/cards/e/EndrekSahrMasterBreeder.java b/Mage.Sets/src/mage/cards/e/EndrekSahrMasterBreeder.java index 0485d62e785..220b63e656e 100644 --- a/Mage.Sets/src/mage/cards/e/EndrekSahrMasterBreeder.java +++ b/Mage.Sets/src/mage/cards/e/EndrekSahrMasterBreeder.java @@ -41,9 +41,8 @@ import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.Zone; import mage.filter.Filter; -import mage.filter.FilterSpell; +import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.mageobject.CardTypePredicate; import mage.game.Game; import mage.game.permanent.token.ThrullToken; import mage.game.stack.Spell; @@ -55,14 +54,8 @@ import mage.target.targetpointer.FixedTarget; */ public class EndrekSahrMasterBreeder extends CardImpl { - private static final FilterSpell filter = new FilterSpell("a creature spell"); - - static { - filter.add(new CardTypePredicate(CardType.CREATURE)); - } - public EndrekSahrMasterBreeder(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{B}"); this.supertype.add("Legendary"); this.subtype.add("Human"); this.subtype.add("Wizard"); @@ -71,7 +64,7 @@ public class EndrekSahrMasterBreeder extends CardImpl { this.toughness = new MageInt(2); // Whenever you cast a creature spell, create X 1/1 black Thrull creature tokens, where X is that spell's converted mana cost. - this.addAbility(new SpellCastControllerTriggeredAbility(new EndrekSahrMasterBreederEffect(), filter, false, true)); + this.addAbility(new SpellCastControllerTriggeredAbility(new EndrekSahrMasterBreederEffect(), StaticFilters.FILTER_SPELL_A_CREATURE, false, true)); // When you control seven or more Thrulls, sacrifice Endrek Sahr, Master Breeder. this.addAbility(new ControlsPermanentsControllerTriggeredAbility( new FilterCreaturePermanent("Thrull", "seven or more Thrulls"), Filter.ComparisonType.GreaterThan, 6, diff --git a/Mage.Sets/src/mage/cards/e/Equilibrium.java b/Mage.Sets/src/mage/cards/e/Equilibrium.java index 2262aa06e85..191fe0ffe5b 100644 --- a/Mage.Sets/src/mage/cards/e/Equilibrium.java +++ b/Mage.Sets/src/mage/cards/e/Equilibrium.java @@ -28,36 +28,28 @@ package mage.cards.e; import java.util.UUID; -import mage.constants.CardType; import mage.abilities.Ability; +import mage.abilities.common.SpellCastControllerTriggeredAbility; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.common.DoIfCostPaid; import mage.abilities.effects.common.ReturnToHandTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.filter.FilterSpell; -import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.constants.CardType; +import mage.filter.StaticFilters; import mage.target.common.TargetCreaturePermanent; -import mage.abilities.common.SpellCastControllerTriggeredAbility; /** * * @author jeffwadsworth */ public class Equilibrium extends CardImpl { - - private static final FilterSpell filter = new FilterSpell("a creature spell"); - - static { - filter.add(new CardTypePredicate(CardType.CREATURE)); - } public Equilibrium(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{U}{U}"); - + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{U}{U}"); // Whenever you cast a creature spell, you may pay {1}. If you do, return target creature to its owner's hand. - Ability ability = new SpellCastControllerTriggeredAbility(new DoIfCostPaid(new ReturnToHandTargetEffect(), new GenericManaCost(1)), filter, false); + Ability ability = new SpellCastControllerTriggeredAbility(new DoIfCostPaid(new ReturnToHandTargetEffect(), new GenericManaCost(1)), StaticFilters.FILTER_SPELL_A_CREATURE, false); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/g/GarrukCallerOfBeasts.java b/Mage.Sets/src/mage/cards/g/GarrukCallerOfBeasts.java index 50615d70931..6f8f9e039c6 100644 --- a/Mage.Sets/src/mage/cards/g/GarrukCallerOfBeasts.java +++ b/Mage.Sets/src/mage/cards/g/GarrukCallerOfBeasts.java @@ -43,9 +43,8 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.Zone; -import mage.filter.FilterSpell; +import mage.filter.StaticFilters; import mage.filter.common.FilterCreatureCard; -import mage.filter.predicate.mageobject.CardTypePredicate; import mage.filter.predicate.mageobject.ColorPredicate; import mage.game.command.Emblem; import mage.target.common.TargetCardInLibrary; @@ -95,16 +94,10 @@ public class GarrukCallerOfBeasts extends CardImpl { */ class GarrukCallerOfBeastsEmblem extends Emblem { - private static final FilterSpell filter = new FilterSpell("a creature spell"); - - static { - filter.add(new CardTypePredicate(CardType.CREATURE)); - } - public GarrukCallerOfBeastsEmblem() { this.setName("Emblem Garruk"); Effect effect = new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(new FilterCreatureCard("creature card")), false, true, Outcome.PutCreatureInPlay); - Ability ability = new SpellCastControllerTriggeredAbility(Zone.COMMAND, effect, filter, true, false); + Ability ability = new SpellCastControllerTriggeredAbility(Zone.COMMAND, effect, StaticFilters.FILTER_SPELL_A_CREATURE, true, false); this.getAbilities().add(ability); } } diff --git a/Mage.Sets/src/mage/cards/h/HalcyonGlaze.java b/Mage.Sets/src/mage/cards/h/HalcyonGlaze.java index ed64dda0814..a289374348d 100644 --- a/Mage.Sets/src/mage/cards/h/HalcyonGlaze.java +++ b/Mage.Sets/src/mage/cards/h/HalcyonGlaze.java @@ -37,8 +37,7 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; -import mage.filter.FilterSpell; -import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.StaticFilters; import mage.game.permanent.token.Token; /** @@ -47,20 +46,13 @@ import mage.game.permanent.token.Token; */ public class HalcyonGlaze extends CardImpl { - private static final FilterSpell filter = new FilterSpell("a creature spell"); - - static { - filter.add(new CardTypePredicate(CardType.CREATURE)); - } - public HalcyonGlaze(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{U}{U}"); - + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{U}{U}"); // Whenever you cast a creature spell, Halcyon Glaze becomes a 4/4 Illusion creature with flying in addition to its other types until end of turn. Effect effect = new BecomesCreatureSourceEffect(new HalcyonGlazeToken(), "enchantment", Duration.EndOfTurn); effect.setText("Whenever you cast a creature spell, {this} becomes a 4/4 Illusion creature with flying in addition to its other types until end of turn"); - this.addAbility(new SpellCastControllerTriggeredAbility(effect, filter, false)); + this.addAbility(new SpellCastControllerTriggeredAbility(effect, StaticFilters.FILTER_SPELL_A_CREATURE, false)); } public HalcyonGlaze(final HalcyonGlaze card) { @@ -74,6 +66,7 @@ public class HalcyonGlaze extends CardImpl { } class HalcyonGlazeToken extends Token { + HalcyonGlazeToken() { super("", "4/4 Illusion creature with flying"); cardType.add(CardType.CREATURE); diff --git a/Mage.Sets/src/mage/cards/k/KarametraGodOfHarvests.java b/Mage.Sets/src/mage/cards/k/KarametraGodOfHarvests.java index 80b4b36a92f..d417a9881b2 100644 --- a/Mage.Sets/src/mage/cards/k/KarametraGodOfHarvests.java +++ b/Mage.Sets/src/mage/cards/k/KarametraGodOfHarvests.java @@ -42,7 +42,7 @@ import mage.constants.CardType; import mage.constants.ColoredManaSymbol; import mage.constants.Zone; import mage.filter.FilterCard; -import mage.filter.common.FilterCreatureSpell; +import mage.filter.StaticFilters; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.SubtypePredicate; import mage.target.common.TargetCardInLibrary; @@ -54,13 +54,15 @@ import mage.target.common.TargetCardInLibrary; public class KarametraGodOfHarvests extends CardImpl { private static final FilterCard filter = new FilterCard("a Forest or Plains card"); + static { filter.add(Predicates.or( new SubtypePredicate("Forest"), new SubtypePredicate("Plains"))); } + public KarametraGodOfHarvests(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT,CardType.CREATURE},"{3}{G}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT, CardType.CREATURE}, "{3}{G}{W}"); this.supertype.add("Legendary"); this.subtype.add("God"); @@ -75,7 +77,7 @@ public class KarametraGodOfHarvests extends CardImpl { this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); // Whenever you cast a creature spell, you may search your library for a Forest or Plains card, put it onto the battlefield tapped, then shuffle your library. this.addAbility(new SpellCastControllerTriggeredAbility( - new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(filter), true), new FilterCreatureSpell("a creature spell"), true)); + new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(filter), true), StaticFilters.FILTER_SPELL_A_CREATURE, true)); } public KarametraGodOfHarvests(final KarametraGodOfHarvests card) { diff --git a/Mage.Sets/src/mage/cards/l/LifecraftersBestiary.java b/Mage.Sets/src/mage/cards/l/LifecraftersBestiary.java index 3fb7fe0bf83..c1f165b987d 100644 --- a/Mage.Sets/src/mage/cards/l/LifecraftersBestiary.java +++ b/Mage.Sets/src/mage/cards/l/LifecraftersBestiary.java @@ -39,7 +39,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.TargetController; import mage.constants.Zone; -import mage.filter.common.FilterCreatureSpell; +import mage.filter.StaticFilters; /** * @@ -47,8 +47,6 @@ import mage.filter.common.FilterCreatureSpell; */ public class LifecraftersBestiary extends CardImpl { - private static final FilterCreatureSpell filter = new FilterCreatureSpell("a creature spell"); - public LifecraftersBestiary(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); @@ -56,7 +54,7 @@ public class LifecraftersBestiary extends CardImpl { this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new ScryEffect(1), TargetController.YOU, false)); // Whenever you cast a creature spell, you may pay {G}. If you do, draw a card. - this.addAbility(new SpellCastControllerTriggeredAbility(new DoIfCostPaid(new DrawCardSourceControllerEffect(1), new ManaCostsImpl("{G}")), filter, false)); + this.addAbility(new SpellCastControllerTriggeredAbility(new DoIfCostPaid(new DrawCardSourceControllerEffect(1), new ManaCostsImpl("{G}")), StaticFilters.FILTER_SPELL_A_CREATURE, false)); } public LifecraftersBestiary(final LifecraftersBestiary card) { diff --git a/Mage.Sets/src/mage/cards/m/MaskedAdmirers.java b/Mage.Sets/src/mage/cards/m/MaskedAdmirers.java index f2ada824b99..aa795e0970e 100644 --- a/Mage.Sets/src/mage/cards/m/MaskedAdmirers.java +++ b/Mage.Sets/src/mage/cards/m/MaskedAdmirers.java @@ -40,8 +40,7 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Zone; -import mage.filter.FilterSpell; -import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.StaticFilters; /** * @@ -49,13 +48,8 @@ import mage.filter.predicate.mageobject.CardTypePredicate; */ public class MaskedAdmirers extends CardImpl { - private static final FilterSpell filter = new FilterSpell("a creature spell"); - static { - filter.add(new CardTypePredicate(CardType.CREATURE)); - } - public MaskedAdmirers(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{G}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}{G}"); this.subtype.add("Elf"); this.subtype.add("Shaman"); @@ -68,7 +62,7 @@ public class MaskedAdmirers extends CardImpl { OneShotEffect effect = new ReturnToHandSourceEffect(); effect.setText("return {this} from your graveyard to your hand"); this.addAbility(new SpellCastControllerTriggeredAbility( - Zone.GRAVEYARD, new DoIfCostPaid(effect, new ManaCostsImpl("{G}{G}")), filter, false, false)); + Zone.GRAVEYARD, new DoIfCostPaid(effect, new ManaCostsImpl("{G}{G}")), StaticFilters.FILTER_SPELL_A_CREATURE, false, false)); } public MaskedAdmirers(final MaskedAdmirers card) { diff --git a/Mage.Sets/src/mage/cards/o/Onslaught.java b/Mage.Sets/src/mage/cards/o/Onslaught.java index db386198556..a236ea081d6 100644 --- a/Mage.Sets/src/mage/cards/o/Onslaught.java +++ b/Mage.Sets/src/mage/cards/o/Onslaught.java @@ -34,8 +34,7 @@ import mage.abilities.effects.common.TapTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.filter.FilterSpell; -import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.StaticFilters; import mage.target.common.TargetCreaturePermanent; /** @@ -44,17 +43,11 @@ import mage.target.common.TargetCreaturePermanent; */ public class Onslaught extends CardImpl { - private static final FilterSpell filter = new FilterSpell("a creature spell"); - - static { - filter.add(new CardTypePredicate(CardType.CREATURE)); - } - public Onslaught(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{R}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{R}"); // Whenever you cast a creature spell, tap target creature. - Ability ability = new SpellCastControllerTriggeredAbility(new TapTargetEffect(), filter, false); + Ability ability = new SpellCastControllerTriggeredAbility(new TapTargetEffect(), StaticFilters.FILTER_SPELL_A_CREATURE, false); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/p/PrimevalBounty.java b/Mage.Sets/src/mage/cards/p/PrimevalBounty.java index d99777cb01f..cb13384062f 100644 --- a/Mage.Sets/src/mage/cards/p/PrimevalBounty.java +++ b/Mage.Sets/src/mage/cards/p/PrimevalBounty.java @@ -40,6 +40,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.counters.CounterType; import mage.filter.FilterSpell; +import mage.filter.StaticFilters; import mage.filter.common.FilterLandPermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.CardTypePredicate; @@ -52,19 +53,17 @@ import mage.target.common.TargetControlledCreaturePermanent; */ public class PrimevalBounty extends CardImpl { - private static final FilterSpell filterCreature = new FilterSpell("a creature spell"); private static final FilterSpell filterNonCreature = new FilterSpell("a noncreature spell"); + static { - filterCreature.add(new CardTypePredicate(CardType.CREATURE)); filterNonCreature.add(Predicates.not(new CardTypePredicate(CardType.CREATURE))); } public PrimevalBounty(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{5}{G}"); - + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{5}{G}"); // Whenever you cast a creature spell, create a 3/3 green Beast creature token. - this.addAbility(new SpellCastControllerTriggeredAbility(new CreateTokenEffect(new BeastToken()), filterCreature, false)); + this.addAbility(new SpellCastControllerTriggeredAbility(new CreateTokenEffect(new BeastToken()), StaticFilters.FILTER_SPELL_A_CREATURE, false)); // Whenever you cast a noncreature spell, put three +1/+1 counters on target creature you control. Effect effect = new AddCountersTargetEffect(CounterType.P1P1.createInstance(3)); @@ -72,7 +71,7 @@ public class PrimevalBounty extends CardImpl { ability.addTarget(new TargetControlledCreaturePermanent()); this.addAbility(ability); - // Whenever a land enters the battlefield under your control, you gain 3 life. + // Whenever a land enters the battlefield under your control, you gain 3 life. effect = new GainLifeEffect(3); ability = new EntersBattlefieldControlledTriggeredAbility(effect, new FilterLandPermanent("a land")); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/p/PrimordialSage.java b/Mage.Sets/src/mage/cards/p/PrimordialSage.java index bf3c06d8f97..bb0a0ca8218 100644 --- a/Mage.Sets/src/mage/cards/p/PrimordialSage.java +++ b/Mage.Sets/src/mage/cards/p/PrimordialSage.java @@ -28,14 +28,13 @@ package mage.cards.p; import java.util.UUID; -import mage.constants.CardType; import mage.MageInt; import mage.abilities.common.SpellCastControllerTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.filter.FilterSpell; -import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.constants.CardType; +import mage.filter.StaticFilters; /** * @@ -43,21 +42,15 @@ import mage.filter.predicate.mageobject.CardTypePredicate; */ public class PrimordialSage extends CardImpl { - private static final FilterSpell filter = new FilterSpell("a creature spell"); - - static { - filter.add(new CardTypePredicate(CardType.CREATURE)); - } - public PrimordialSage(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{G}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{G}{G}"); this.subtype.add("Spirit"); this.power = new MageInt(4); this.toughness = new MageInt(5); // Whenever you cast a creature spell, you may draw a card. - this.addAbility(new SpellCastControllerTriggeredAbility(new DrawCardSourceControllerEffect(1), filter, true)); + this.addAbility(new SpellCastControllerTriggeredAbility(new DrawCardSourceControllerEffect(1), StaticFilters.FILTER_SPELL_A_CREATURE, true)); } public PrimordialSage(final PrimordialSage card) { diff --git a/Mage.Sets/src/mage/cards/q/QuestForTheHolyRelic.java b/Mage.Sets/src/mage/cards/q/QuestForTheHolyRelic.java index ee3455cf400..ce3d7dd9a9b 100644 --- a/Mage.Sets/src/mage/cards/q/QuestForTheHolyRelic.java +++ b/Mage.Sets/src/mage/cards/q/QuestForTheHolyRelic.java @@ -43,8 +43,7 @@ import mage.constants.Outcome; import mage.constants.Zone; import mage.counters.CounterType; import mage.filter.FilterCard; -import mage.filter.FilterSpell; -import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.StaticFilters; import mage.filter.predicate.mageobject.SubtypePredicate; import mage.game.Game; import mage.game.permanent.Permanent; @@ -59,17 +58,11 @@ import mage.target.common.TargetControlledCreaturePermanent; */ public class QuestForTheHolyRelic extends CardImpl { - private static final FilterSpell filter = new FilterSpell("a creature spell"); - - static { - filter.add(new CardTypePredicate(CardType.CREATURE)); - } - public QuestForTheHolyRelic(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{W}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{W}"); // Whenever you cast a creature spell, you may put a quest counter on Quest for the Holy Relic. - this.addAbility(new SpellCastControllerTriggeredAbility(new AddCountersSourceEffect(CounterType.QUEST.createInstance()), filter, true)); + this.addAbility(new SpellCastControllerTriggeredAbility(new AddCountersSourceEffect(CounterType.QUEST.createInstance()), StaticFilters.FILTER_SPELL_A_CREATURE, true)); // Remove five quest counters from Quest for the Holy Relic and sacrifice it: Search your library for an Equipment card, put it onto the battlefield, and attach it to a creature you control. Then shuffle your library. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new QuestForTheHolyRelicEffect(), new RemoveCountersSourceCost(CounterType.QUEST.createInstance(5))); ability.addCost(new SacrificeSourceCost()); diff --git a/Mage.Sets/src/mage/cards/s/SkitteringHorror.java b/Mage.Sets/src/mage/cards/s/SkitteringHorror.java index ba03266ad92..9be8cef8a60 100644 --- a/Mage.Sets/src/mage/cards/s/SkitteringHorror.java +++ b/Mage.Sets/src/mage/cards/s/SkitteringHorror.java @@ -34,8 +34,7 @@ import mage.abilities.effects.common.SacrificeSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.filter.FilterSpell; -import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.StaticFilters; /** * @@ -43,20 +42,14 @@ import mage.filter.predicate.mageobject.CardTypePredicate; */ public class SkitteringHorror extends CardImpl { - private static final FilterSpell filter = new FilterSpell("a creature spell"); - - static { - filter.add(new CardTypePredicate(CardType.CREATURE)); - } - public SkitteringHorror(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}"); this.subtype.add("Horror"); this.power = new MageInt(4); this.toughness = new MageInt(3); // When you cast a creature spell, sacrifice Skittering Horror. - this.addAbility(new SpellCastControllerTriggeredAbility(new SacrificeSourceEffect(), filter, false)); + this.addAbility(new SpellCastControllerTriggeredAbility(new SacrificeSourceEffect(), StaticFilters.FILTER_SPELL_A_CREATURE, false)); } public SkitteringHorror(final SkitteringHorror card) { diff --git a/Mage.Sets/src/mage/cards/s/SkitteringMonstrosity.java b/Mage.Sets/src/mage/cards/s/SkitteringMonstrosity.java index 82fdb87463b..74e592227e5 100644 --- a/Mage.Sets/src/mage/cards/s/SkitteringMonstrosity.java +++ b/Mage.Sets/src/mage/cards/s/SkitteringMonstrosity.java @@ -34,8 +34,7 @@ import mage.abilities.effects.common.SacrificeSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.filter.FilterSpell; -import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.StaticFilters; /** * @@ -43,20 +42,14 @@ import mage.filter.predicate.mageobject.CardTypePredicate; */ public class SkitteringMonstrosity extends CardImpl { - private static final FilterSpell filter = new FilterSpell("a creature spell"); - - static { - filter.add(new CardTypePredicate(CardType.CREATURE)); - } - public SkitteringMonstrosity(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{B}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{B}"); this.subtype.add("Horror"); this.power = new MageInt(5); this.toughness = new MageInt(5); // When you cast a creature spell, sacrifice Skittering Monstrosity. - this.addAbility(new SpellCastControllerTriggeredAbility(new SacrificeSourceEffect(), filter, false)); + this.addAbility(new SpellCastControllerTriggeredAbility(new SacrificeSourceEffect(), StaticFilters.FILTER_SPELL_A_CREATURE, false)); } public SkitteringMonstrosity(final SkitteringMonstrosity card) { diff --git a/Mage.Sets/src/mage/cards/s/SkitteringSkirge.java b/Mage.Sets/src/mage/cards/s/SkitteringSkirge.java index 38a8aed5c81..66f875c606e 100644 --- a/Mage.Sets/src/mage/cards/s/SkitteringSkirge.java +++ b/Mage.Sets/src/mage/cards/s/SkitteringSkirge.java @@ -35,32 +35,25 @@ import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.filter.FilterSpell; -import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.StaticFilters; /** * * @author hanasu */ public class SkitteringSkirge extends CardImpl { - - private static final FilterSpell filter = new FilterSpell("a creature spell"); - - static { - filter.add(new CardTypePredicate(CardType.CREATURE)); - } public SkitteringSkirge(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{B}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B}{B}"); this.subtype.add("Imp"); this.power = new MageInt(3); this.toughness = new MageInt(2); // Flying this.addAbility(FlyingAbility.getInstance()); - + // When you cast a creature spell, sacrifice Skittering Skirge. - this.addAbility(new SpellCastControllerTriggeredAbility(new SacrificeSourceEffect(), filter, false)); + this.addAbility(new SpellCastControllerTriggeredAbility(new SacrificeSourceEffect(), StaticFilters.FILTER_SPELL_A_CREATURE, false)); } public SkitteringSkirge(final SkitteringSkirge card) { diff --git a/Mage.Sets/src/mage/cards/s/StrawGolem.java b/Mage.Sets/src/mage/cards/s/StrawGolem.java index 8552fa2448c..8e5f720f4f0 100644 --- a/Mage.Sets/src/mage/cards/s/StrawGolem.java +++ b/Mage.Sets/src/mage/cards/s/StrawGolem.java @@ -1,63 +1,63 @@ -/* - * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of BetaSteward_at_googlemail.com. - */ -package mage.cards.s; - -import java.util.UUID; -import mage.MageInt; -import mage.abilities.common.SpellCastOpponentTriggeredAbility; -import mage.abilities.effects.common.SacrificeSourceEffect; -import mage.cards.CardImpl; -import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.filter.common.FilterCreatureSpell; - -/** - * - * @author Derpthemeus - */ -public class StrawGolem extends CardImpl { - - public StrawGolem(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{1}"); - this.subtype.add("Golem"); - this.power = new MageInt(2); - this.toughness = new MageInt(3); - - // When an opponent casts a creature spell, sacrifice Straw Golem. - this.addAbility(new SpellCastOpponentTriggeredAbility(new SacrificeSourceEffect(), new FilterCreatureSpell("a creature spell"), false)); - } - - public StrawGolem(final StrawGolem card) { - super(card); - } - - @Override - public StrawGolem copy() { - return new StrawGolem(this); - } -} +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.s; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SpellCastOpponentTriggeredAbility; +import mage.abilities.effects.common.SacrificeSourceEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.filter.StaticFilters; + +/** + * + * @author Derpthemeus + */ +public class StrawGolem extends CardImpl { + + public StrawGolem(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{1}"); + this.subtype.add("Golem"); + this.power = new MageInt(2); + this.toughness = new MageInt(3); + + // When an opponent casts a creature spell, sacrifice Straw Golem. + this.addAbility(new SpellCastOpponentTriggeredAbility(new SacrificeSourceEffect(), StaticFilters.FILTER_SPELL_A_CREATURE, false)); + } + + public StrawGolem(final StrawGolem card) { + super(card); + } + + @Override + public StrawGolem copy() { + return new StrawGolem(this); + } +} diff --git a/Mage.Sets/src/mage/cards/t/Tangleroot.java b/Mage.Sets/src/mage/cards/t/Tangleroot.java index 197f77c918e..659f13ab519 100644 --- a/Mage.Sets/src/mage/cards/t/Tangleroot.java +++ b/Mage.Sets/src/mage/cards/t/Tangleroot.java @@ -35,7 +35,7 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SetTargetPointer; -import mage.filter.common.FilterCreatureSpell; +import mage.filter.StaticFilters; /** * @@ -44,10 +44,11 @@ import mage.filter.common.FilterCreatureSpell; public class Tangleroot extends CardImpl { public Tangleroot(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{3}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); // Whenever a player casts a creature spell, that player adds {G} to his or her mana pool. - this.addAbility(new SpellCastAllTriggeredAbility(new AddManaToManaPoolTargetControllerEffect(Mana.GreenMana(1), "his or her"), new FilterCreatureSpell("a creature spell"), false, SetTargetPointer.PLAYER)); + this.addAbility(new SpellCastAllTriggeredAbility( + new AddManaToManaPoolTargetControllerEffect(Mana.GreenMana(1), "his or her"), StaticFilters.FILTER_SPELL_A_CREATURE, false, SetTargetPointer.PLAYER)); } public Tangleroot(final Tangleroot card) { @@ -58,5 +59,5 @@ public class Tangleroot extends CardImpl { public Tangleroot copy() { return new Tangleroot(this); } - -} \ No newline at end of file + +} diff --git a/Mage.Sets/src/mage/cards/z/ZendikarResurgent.java b/Mage.Sets/src/mage/cards/z/ZendikarResurgent.java index 302e7ac1193..f6fab6276b4 100644 --- a/Mage.Sets/src/mage/cards/z/ZendikarResurgent.java +++ b/Mage.Sets/src/mage/cards/z/ZendikarResurgent.java @@ -36,9 +36,8 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SetTargetPointer; -import mage.filter.FilterSpell; +import mage.filter.StaticFilters; import mage.filter.common.FilterControlledLandPermanent; -import mage.filter.predicate.mageobject.CardTypePredicate; /** * @@ -46,14 +45,8 @@ import mage.filter.predicate.mageobject.CardTypePredicate; */ public class ZendikarResurgent extends CardImpl { - private static final FilterSpell FILTER = new FilterSpell("a creature spell"); - - static { - FILTER.add(new CardTypePredicate(CardType.CREATURE)); - } - public ZendikarResurgent(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{5}{G}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{5}{G}{G}"); // Whenever you tap a land for mana, add one mana to your mana pool of any type that land produced. (The types of mana are white, blue, black, red, green, and colorless.) AddManaOfAnyTypeProducedEffect effect = new AddManaOfAnyTypeProducedEffect(); @@ -64,7 +57,8 @@ public class ZendikarResurgent extends CardImpl { SetTargetPointer.PERMANENT)); // Whenever you cast a creature spell, draw a card. - this.addAbility(new SpellCastControllerTriggeredAbility(new DrawCardSourceControllerEffect(1), FILTER, false)); + this.addAbility(new SpellCastControllerTriggeredAbility( + new DrawCardSourceControllerEffect(1), StaticFilters.FILTER_SPELL_A_CREATURE, false)); } public ZendikarResurgent(final ZendikarResurgent card) { diff --git a/Mage/src/main/java/mage/filter/StaticFilters.java b/Mage/src/main/java/mage/filter/StaticFilters.java index dd902cb3815..082eda39115 100644 --- a/Mage/src/main/java/mage/filter/StaticFilters.java +++ b/Mage/src/main/java/mage/filter/StaticFilters.java @@ -11,6 +11,7 @@ import mage.filter.common.FilterArtifactCreaturePermanent; import mage.filter.common.FilterControlledArtifactPermanent; import mage.filter.common.FilterControlledPermanent; import mage.filter.common.FilterCreaturePermanent; +import mage.filter.common.FilterCreatureSpell; import mage.filter.common.FilterNonlandCard; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.CardTypePredicate; @@ -32,6 +33,8 @@ public class StaticFilters { public static final FilterCreaturePermanent FILTER_PERMANENT_CREATURE_GOBLINS = new FilterCreaturePermanent("Goblin", "Goblin creatures"); public static final FilterCreaturePermanent FILTER_PERMANENT_CREATURE_SLIVERS = new FilterCreaturePermanent("Sliver", "Sliver creatures"); + public static final FilterCreatureSpell FILTER_SPELL_A_CREATURE = new FilterCreatureSpell("a creature spell"); + static { FILTER_PERMANENT_ARTIFACT_OR_CREATURE.add(Predicates.or( new CardTypePredicate(CardType.ARTIFACT), From 4697c16c3df8cbc32a2e42327066d792c0b1b823 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sun, 8 Jan 2017 10:47:18 +0100 Subject: [PATCH 17/19] * Outland Boar - fixed wrong P/T of 3/3 to 4/4. --- Mage.Sets/src/mage/cards/o/OutlandBoar.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Mage.Sets/src/mage/cards/o/OutlandBoar.java b/Mage.Sets/src/mage/cards/o/OutlandBoar.java index 6f27b5d1c67..18b42c630a4 100644 --- a/Mage.Sets/src/mage/cards/o/OutlandBoar.java +++ b/Mage.Sets/src/mage/cards/o/OutlandBoar.java @@ -55,8 +55,8 @@ public class OutlandBoar extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}{G}"); this.subtype.add("Boar"); - this.power = new MageInt(3); - this.toughness = new MageInt(3); + this.power = new MageInt(4); + this.toughness = new MageInt(4); // Outland Boar can't be blocked by creatures with power 2 or less. this.addAbility(new SimpleEvasionAbility(new CantBeBlockedByCreaturesSourceEffect(filter, Duration.WhileOnBattlefield))); From 267aee43a5e10ae52294610d57356cc123bcf077 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sun, 8 Jan 2017 13:07:03 +0100 Subject: [PATCH 18/19] * Implement of Ferocity - Fixed that the activated ability added the wrong counter type. --- Mage.Sets/src/mage/cards/i/ImplementOfFerocity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mage.Sets/src/mage/cards/i/ImplementOfFerocity.java b/Mage.Sets/src/mage/cards/i/ImplementOfFerocity.java index a04218163a5..feb953a3544 100644 --- a/Mage.Sets/src/mage/cards/i/ImplementOfFerocity.java +++ b/Mage.Sets/src/mage/cards/i/ImplementOfFerocity.java @@ -52,7 +52,7 @@ public class ImplementOfFerocity extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}"); // {G}, Sacrifice Implement of Ferocity: Put a +1/+1 counter on target creature. Activate this ability only any time you could cast a sorcery. - Ability ability = new ActivateAsSorceryActivatedAbility(Zone.BATTLEFIELD, new AddCountersTargetEffect(CounterType.UNITY.createInstance()),new ManaCostsImpl("{G}")); + Ability ability = new ActivateAsSorceryActivatedAbility(Zone.BATTLEFIELD, new AddCountersTargetEffect(CounterType.P1P1.createInstance()), new ManaCostsImpl("{G}")); ability.addCost(new SacrificeSourceCost()); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); From a9e76069c1921ebb40904f6406d1e36b8fa83109 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sun, 8 Jan 2017 13:13:07 +0100 Subject: [PATCH 19/19] * Caught in the Brights - Fixed that it triggered for all attacking vehicles not only controlled vehicles. --- .../src/mage/cards/c/CaughtInTheBrights.java | 180 +++++++++--------- 1 file changed, 91 insertions(+), 89 deletions(-) diff --git a/Mage.Sets/src/mage/cards/c/CaughtInTheBrights.java b/Mage.Sets/src/mage/cards/c/CaughtInTheBrights.java index 2c356c6b686..afa4f8092d7 100644 --- a/Mage.Sets/src/mage/cards/c/CaughtInTheBrights.java +++ b/Mage.Sets/src/mage/cards/c/CaughtInTheBrights.java @@ -1,89 +1,91 @@ -/* - * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and 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.AttacksAllTriggeredAbility; -import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.common.AttachEffect; -import mage.abilities.effects.common.ExileAttachedEffect; -import mage.abilities.effects.common.combat.CantAttackBlockAttachedEffect; -import mage.abilities.keyword.EnchantAbility; -import mage.cards.CardImpl; -import mage.cards.CardSetInfo; -import mage.constants.AttachmentType; -import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.SetTargetPointer; -import mage.constants.Zone; -import mage.filter.common.FilterArtifactCreaturePermanent; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.mageobject.SubtypePredicate; -import mage.target.TargetPermanent; -import mage.target.common.TargetCreaturePermanent; - -/** - * - * @author Styxo - */ -public class CaughtInTheBrights extends CardImpl { - - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Vehicle you control"); - - static { - filter.add(new SubtypePredicate("Vehicle")); - } - - public CaughtInTheBrights(UUID ownerId, CardSetInfo setInfo) { - super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}"); - this.subtype.add("Aura"); - - // Enchant creature - TargetPermanent auraTarget = new TargetCreaturePermanent(); - this.getSpellAbility().addTarget(auraTarget); - this.getSpellAbility().addEffect(new AttachEffect(Outcome.Benefit)); - Ability ability = new EnchantAbility(auraTarget.getTargetName()); - this.addAbility(ability); - - // Enchanted creature can't attack or block. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantAttackBlockAttachedEffect(AttachmentType.AURA))); - - // When a Vehicle you control attacks, exile enchanted creature. - this.addAbility(new AttacksAllTriggeredAbility(new ExileAttachedEffect(), false, filter, SetTargetPointer.NONE, false)); - } - - public CaughtInTheBrights(final CaughtInTheBrights card) { - super(card); - } - - @Override - public CaughtInTheBrights copy() { - return new CaughtInTheBrights(this); - } -} +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.c; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.AttacksAllTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.ExileAttachedEffect; +import mage.abilities.effects.common.combat.CantAttackBlockAttachedEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.AttachmentType; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SetTargetPointer; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author Styxo + */ +public class CaughtInTheBrights extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Vehicle you control"); + + static { + filter.add(new ControllerPredicate(TargetController.YOU)); + filter.add(new SubtypePredicate("Vehicle")); + } + + public CaughtInTheBrights(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}"); + this.subtype.add("Aura"); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.Benefit)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + + // Enchanted creature can't attack or block. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantAttackBlockAttachedEffect(AttachmentType.AURA))); + + // When a Vehicle you control attacks, exile enchanted creature. + this.addAbility(new AttacksAllTriggeredAbility(new ExileAttachedEffect(), false, filter, SetTargetPointer.NONE, false)); + } + + public CaughtInTheBrights(final CaughtInTheBrights card) { + super(card); + } + + @Override + public CaughtInTheBrights copy() { + return new CaughtInTheBrights(this); + } +}