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 9fc3658775a..03ba31aac40 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 @@ -251,6 +251,7 @@ public enum MythicspoilerComSource implements CardImageSource { supportedSets.add("E01"); supportedSets.add("HOU"); supportedSets.add("C17"); + supportedSets.add("IMA"); supportedSets.add("XLN"); sets = new LinkedHashMap<>(); diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSource.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSource.java index a54e5c0118f..759a9bdacf4 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSource.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSource.java @@ -199,11 +199,25 @@ public enum ScryfallImageSource implements CardImageSource { supportedSets.add("E01"); supportedSets.add("HOU"); supportedSets.add("C17"); + supportedSets.add("XLN"); +// supportedSets.add("DDT"); + supportedSets.add("IMA"); +// supportedSets.add("E02"); +// supportedSets.add("V17"); +// supportedSets.add("UST"); +// supportedSets.add("RIX"); +// supportedSets.add("A25"); +// supportedSets.add("DOM"); +// supportedSets.add("M19"); + } @Override public String generateURL(CardDownloadData card) throws Exception { - return "https://api.scryfall.com/cards/" + formatSetName(card.getSet()) + "/" + card.getCollectorId() + "?format=image"; + return "https://api.scryfall.com/cards/" + formatSetName(card.getSet()) + "/" + + card.getCollectorId() + + (card.isSecondSide() ? "b" : "") + + "?format=image"; } @Override diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/images/CardDownloadData.java b/Mage.Client/src/main/java/org/mage/plugins/card/images/CardDownloadData.java index 6c70b198107..9956f8e10ff 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/images/CardDownloadData.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/images/CardDownloadData.java @@ -40,7 +40,7 @@ public class CardDownloadData { } public CardDownloadData(String name, String set, String collectorId, boolean usesVariousArt, Integer type, String tokenSetCode, String tokenDescriptor, boolean token, boolean twoFacedCard, boolean secondSide) { - this(name, set, collectorId, usesVariousArt, type, tokenSetCode, tokenDescriptor, token, false, false, ""); + this(name, set, collectorId, usesVariousArt, type, tokenSetCode, tokenDescriptor, token, twoFacedCard, secondSide, ""); } public CardDownloadData(String name, String set, String collectorId, boolean usesVariousArt, Integer type, String tokenSetCode, String tokenDescriptor, boolean token, boolean twoFacedCard, boolean secondSide, String tokenClassName) { @@ -72,7 +72,7 @@ public class CardDownloadData { this.usesVariousArt = card.usesVariousArt; this.tokenSetCode = card.tokenSetCode; this.tokenDescriptor = card.tokenDescriptor; - this.tokenClassName = tokenClassName; + this.tokenClassName = card.tokenClassName; this.fileName = card.fileName; } @@ -163,7 +163,7 @@ public class CardDownloadData { public String getTokenDescriptor() { return tokenDescriptor; } - + public void setTokenClassName(String tokenClassName) { this.tokenClassName = tokenClassName; } diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPictures.java b/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPictures.java index d993eec652d..0895b792198 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPictures.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPictures.java @@ -429,6 +429,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab if (card.getSecondSideName() == null || card.getSecondSideName().trim().isEmpty()) { throw new IllegalStateException("Second side card can't have empty name."); } + url = new CardDownloadData(card.getSecondSideName(), card.getSetCode(), card.getCardNumber(), card.usesVariousArt(), 0, "", "", false, card.isDoubleFaced(), true); url.setType2(isType2); allCardsUrls.add(url); @@ -444,11 +445,11 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab allCardsUrls.add(cardDownloadData); } } else if (card.getCardNumber().isEmpty() || "0".equals(card.getCardNumber())) { - System.err.println("There was a critical error!"); logger.error("Card has no collector ID and won't be sent to client: " + card.getName()); } else if (card.getSetCode().isEmpty()) { - System.err.println("There was a critical error!"); logger.error("Card has no set name and won't be sent to client:" + card.getName()); + } else { + logger.info("Card was not selected: " + card.getName()); } }); allCardsUrls.addAll(getTokenCardUrls()); diff --git a/Mage.Client/src/main/resources/image.url.properties b/Mage.Client/src/main/resources/image.url.properties index 8b2b31bb074..0ded050d87f 100644 --- a/Mage.Client/src/main/resources/image.url.properties +++ b/Mage.Client/src/main/resources/image.url.properties @@ -74,6 +74,6 @@ dd3evg=ddaevg dd3gvl=ddagvl dd3jvc=ddajvc # Remove setname as soon as the images can be downloaded -ignore.urls=TOK,DDT,V17,IMA,RIX,E02,M19,M25,DOM,UST,H17 +ignore.urls=TOK,DDT,V17,RIX,E02,M19,M25,DOM,UST,H17 # sets ordered by release time (newest goes first) token.lookup.order=M19,M25,DOM,E02,RIX,UST,XLN,IMA,H17,C17,V17,E01,DDT,CMA,HOU,MM3,DDS,AKH,DD3DVD,DD3EVG,DD3GVL,DD3JVC,H09,AER,PCA,C16,V16,MPS,KLD,DDR,CN2,EMN,EMA,SOI,DDQ,CP,CMA,ARENA,SUS,APAC,EURO,UGIN,C15,OGW,EXP,DDP,BFZ,DRB,V09,V10,V11,V12,V13,V14,V15,TPR,MPRP,DD3,DDO,ORI,MM2,PTC,DTK,FRF,KTK,M15,VMA,CNS,JOU,BNG,THS,DDL,M14,MMA,DGM,GTC,RTR,M13,AVR,DDI,DKA,ISD,M12,NPH,MBS,SOM,M11,ROE,DDE,WWK,ZEN,M10,GVL,ARB,DVD,CFX,JVC,ALA,EVE,SHM,EVG,MOR,LRW,10E,CLS,CHK,GRC \ No newline at end of file diff --git a/Mage.Common/src/main/java/mage/utils/MageVersion.java b/Mage.Common/src/main/java/mage/utils/MageVersion.java index 0b45f8ca40a..e0c0a9435a3 100644 --- a/Mage.Common/src/main/java/mage/utils/MageVersion.java +++ b/Mage.Common/src/main/java/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 = 26; - public final static String MAGE_VERSION_MINOR_PATCH = "V3"; + public final static String MAGE_VERSION_MINOR_PATCH = "V4"; public final static String MAGE_VERSION_INFO = ""; private final int major; diff --git a/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java b/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java index 751e1739d29..69e89b0c08e 100644 --- a/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java +++ b/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java @@ -1112,8 +1112,10 @@ public class HumanPlayer extends PlayerImpl { // attack selected default defender declareAttacker(attacker.getId(), attackedDefender, game, false); } -// } else if (response.getInteger() != null) { // Ok or F-Key - + } else if (response.getInteger() != null) { // F-Key + if (checkIfAttackersValid(game)) { + return; + } } else if (response.getBoolean() != null) { // ok button if (checkIfAttackersValid(game)) { return; diff --git a/Mage.Sets/src/mage/cards/a/AdmiralBeckettBrass.java b/Mage.Sets/src/mage/cards/a/AdmiralBeckettBrass.java index 77f6f600259..84b6dcd8c19 100644 --- a/Mage.Sets/src/mage/cards/a/AdmiralBeckettBrass.java +++ b/Mage.Sets/src/mage/cards/a/AdmiralBeckettBrass.java @@ -53,6 +53,7 @@ import mage.filter.predicate.Predicate; import mage.filter.predicate.mageobject.SubtypePredicate; import mage.filter.predicate.permanent.ControllerPredicate; import mage.game.Game; +import mage.game.events.DamagedPlayerEvent; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.target.common.TargetNonlandPermanent; @@ -85,9 +86,8 @@ public class AdmiralBeckettBrass extends CardImpl { this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostAllEffect(1, 1, Duration.WhileOnBattlefield, filter, true))); // At the beginning of your end step, gain control of target nonland permanent controlled by a player who was dealt combat damage by three or more Pirates this turn. - Ability ability = new BeginningOfEndStepTriggeredAbility(new GainControlTargetEffect(Duration.Custom) - .setText("gain control of target nonland permanent controlled by a player who was dealt combat damage by three or more Pirates this turn"), TargetController.YOU, false); - ability.addTarget(new TargetNonlandPermanent()); + Ability ability = new BeginningOfEndStepTriggeredAbility(new GainControlTargetEffect(Duration.Custom), TargetController.YOU, false); + ability.addTarget(new TargetNonlandPermanent(new FilterNonlandPermanent("nonland permanent controlled by a player who was dealt combat damage by three or more Pirates this turn"))); originalId = ability.getOriginalId(); this.addAbility(ability, new DamagedByPiratesWatcher()); } @@ -138,15 +138,17 @@ class DamagedByPiratesWatcher extends Watcher { @Override public void watch(GameEvent event, Game game) { - if (event.getType() == GameEvent.EventType.DAMAGED_PLAYER && event.getFlag()) { - Permanent creature = game.getPermanentOrLKIBattlefield(event.getSourceId()); - if (creature != null && creature.getSubtype(game).contains(SubType.PIRATE)) { - if (damageSourceIds.keySet().contains(event.getTargetId())) { - damageSourceIds.get(event.getTargetId()).add(creature.getId()); - } else { - Set creatureSet = new HashSet(); - creatureSet.add(creature.getId()); - damageSourceIds.put(event.getTargetId(), creatureSet); + if (event.getType() == GameEvent.EventType.DAMAGED_PLAYER) { + if (((DamagedPlayerEvent) event).isCombatDamage()) { + Permanent creature = game.getPermanentOrLKIBattlefield(event.getSourceId()); + if (creature != null && creature.getSubtype(game).contains(SubType.PIRATE)) { + if (damageSourceIds.keySet().contains(event.getTargetId())) { + damageSourceIds.get(event.getTargetId()).add(creature.getId()); + } else { + Set creatureSet = new HashSet(); + creatureSet.add(creature.getId()); + damageSourceIds.put(event.getTargetId(), creatureSet); + } } } } diff --git a/Mage.Sets/src/mage/cards/a/AngrathsMarauders.java b/Mage.Sets/src/mage/cards/a/AngrathsMarauders.java index a08e15a0738..e6e12b2eec5 100644 --- a/Mage.Sets/src/mage/cards/a/AngrathsMarauders.java +++ b/Mage.Sets/src/mage/cards/a/AngrathsMarauders.java @@ -50,7 +50,7 @@ public class AngrathsMarauders extends CardImpl { public AngrathsMarauders(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{R}{R}"); - + this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.PIRATE); this.power = new MageInt(4); @@ -69,6 +69,7 @@ public class AngrathsMarauders extends CardImpl { return new AngrathsMarauders(this); } } + class AngrathsMaraudersEffect extends ReplacementEffectImpl { public AngrathsMaraudersEffect() { @@ -96,11 +97,11 @@ class AngrathsMaraudersEffect extends ReplacementEffectImpl { return true; } return false; - } - + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - return event.getSourceId().equals(source.getControllerId()); + return game.getControllerId(event.getSourceId()).equals(source.getControllerId()); } @Override diff --git a/Mage.Sets/src/mage/cards/b/BelligerentBrontodon.java b/Mage.Sets/src/mage/cards/b/BelligerentBrontodon.java index f1a1b50e254..df036bce3bf 100644 --- a/Mage.Sets/src/mage/cards/b/BelligerentBrontodon.java +++ b/Mage.Sets/src/mage/cards/b/BelligerentBrontodon.java @@ -37,7 +37,7 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.permanent.ControllerPredicate; +import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; /** @@ -54,7 +54,7 @@ public class BelligerentBrontodon extends CardImpl { this.toughness = new MageInt(6); // Each creature you control assigns combat damage equal to its toughness rather than its power. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new MilitantDinosaurCombatDamageRuleEffect())); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BelligerentBrontodonCombatDamageRuleEffect())); } public BelligerentBrontodon(final BelligerentBrontodon card) { @@ -67,31 +67,27 @@ public class BelligerentBrontodon extends CardImpl { } } -class MilitantDinosaurCombatDamageRuleEffect extends ContinuousEffectImpl { +class BelligerentBrontodonCombatDamageRuleEffect extends ContinuousEffectImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); - - static { - filter.add(new ControllerPredicate(TargetController.YOU)); - } - - public MilitantDinosaurCombatDamageRuleEffect() { + public BelligerentBrontodonCombatDamageRuleEffect() { super(Duration.WhileOnBattlefield, Outcome.Detriment); staticText = "Each creature you control assigns combat damage equal to its toughness rather than its power"; } - public MilitantDinosaurCombatDamageRuleEffect(final MilitantDinosaurCombatDamageRuleEffect effect) { + public BelligerentBrontodonCombatDamageRuleEffect(final BelligerentBrontodonCombatDamageRuleEffect effect) { super(effect); } @Override - public MilitantDinosaurCombatDamageRuleEffect copy() { - return new MilitantDinosaurCombatDamageRuleEffect(this); + public BelligerentBrontodonCombatDamageRuleEffect copy() { + return new BelligerentBrontodonCombatDamageRuleEffect(this); } @Override public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { // Change the rule + FilterCreaturePermanent filter = new FilterCreaturePermanent(); + filter.add(new ControllerIdPredicate(source.getControllerId())); game.getCombat().setUseToughnessForDamage(true); game.getCombat().addUseToughnessForDamageFilter(filter); return true; diff --git a/Mage.Sets/src/mage/cards/d/DeadeyeQuartermaster.java b/Mage.Sets/src/mage/cards/d/DeadeyeQuartermaster.java index c99d19e5e60..049f6915fad 100644 --- a/Mage.Sets/src/mage/cards/d/DeadeyeQuartermaster.java +++ b/Mage.Sets/src/mage/cards/d/DeadeyeQuartermaster.java @@ -49,7 +49,10 @@ public class DeadeyeQuartermaster extends CardImpl { private static final FilterCard filter = new FilterCard("an Equipment or Vehicle card"); static { - filter.add(Predicates.or(new SubtypePredicate(SubType.EQUIPMENT), new SubtypePredicate(SubType.EQUIPMENT))); + filter.add(Predicates.or( + new SubtypePredicate(SubType.EQUIPMENT), + new SubtypePredicate(SubType.VEHICLE) + )); } public DeadeyeQuartermaster(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/d/DeadeyeTracker.java b/Mage.Sets/src/mage/cards/d/DeadeyeTracker.java index 5915342b3df..405263345ef 100644 --- a/Mage.Sets/src/mage/cards/d/DeadeyeTracker.java +++ b/Mage.Sets/src/mage/cards/d/DeadeyeTracker.java @@ -40,12 +40,9 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.TargetController; import mage.constants.Zone; import mage.filter.FilterCard; -import mage.filter.predicate.Predicates; -import mage.filter.predicate.other.OwnerPredicate; -import mage.target.common.TargetCardInASingleGraveyard; +import mage.target.common.TargetCardInOpponentsGraveyard; /** * @@ -53,12 +50,6 @@ import mage.target.common.TargetCardInASingleGraveyard; */ public class DeadeyeTracker extends CardImpl { - private static final FilterCard filter = new FilterCard("cards from an opponent's graveyard"); - - static { - filter.add(Predicates.not(new OwnerPredicate(TargetController.YOU))); - } - public DeadeyeTracker(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B}"); @@ -73,7 +64,7 @@ public class DeadeyeTracker extends CardImpl { Effect effect = new ExploreSourceEffect(); effect.setText("{this} explores"); ability.addEffect(effect); - ability.addTarget(new TargetCardInASingleGraveyard(2, 2, filter)); + ability.addTarget(new TargetCardInOpponentsGraveyard(2, 2, new FilterCard("cards from an opponent's graveyard"), true)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/d/DeathgorgeScavenger.java b/Mage.Sets/src/mage/cards/d/DeathgorgeScavenger.java index 13b6ae13b3f..868409cd850 100644 --- a/Mage.Sets/src/mage/cards/d/DeathgorgeScavenger.java +++ b/Mage.Sets/src/mage/cards/d/DeathgorgeScavenger.java @@ -34,12 +34,12 @@ import mage.abilities.common.EntersBattlefieldOrAttacksSourceTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.cards.Card; -import mage.constants.SubType; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Outcome; +import mage.constants.SubType; import mage.constants.Zone; import mage.game.Game; import mage.players.Player; @@ -92,14 +92,16 @@ class DeathgorgeScavengerEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Card card = game.getCard(getTargetPointer().getFirst(game, source)); Player controller = game.getPlayer(source.getControllerId()); - if (controller != null && card != null) { - controller.moveCardToExileWithInfo(card, null, "", source.getSourceId(), game, Zone.GRAVEYARD, true); - if (card.isCreature()) { - controller.gainLife(2, game); - } else { - new BoostSourceEffect(1, 1, Duration.EndOfTurn).apply(game, source); + if (controller != null) { + Card card = game.getCard(getTargetPointer().getFirst(game, source)); + if (card != null) { + controller.moveCards(card, Zone.EXILED, source, game); + if (card.isCreature()) { + controller.gainLife(2, game); + } else { + game.addEffect(new BoostSourceEffect(1, 1, Duration.EndOfTurn), source); + } } return true; } diff --git a/Mage.Sets/src/mage/cards/d/DiveDown.java b/Mage.Sets/src/mage/cards/d/DiveDown.java index d094dade725..8ce6392e1c8 100644 --- a/Mage.Sets/src/mage/cards/d/DiveDown.java +++ b/Mage.Sets/src/mage/cards/d/DiveDown.java @@ -48,7 +48,7 @@ public class DiveDown extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{U}"); // Target creature you control gets +0/+3 and gains hexproof until end of turn. - Effect effect = new BoostTargetEffect(3, 3, Duration.EndOfTurn); + Effect effect = new BoostTargetEffect(0, 3, Duration.EndOfTurn); effect.setText("Target creature you control gets +0/+3"); this.getSpellAbility().addEffect(effect); effect = new GainAbilityTargetEffect(HexproofAbility.getInstance(), Duration.EndOfTurn); diff --git a/Mage.Sets/src/mage/cards/d/DualNature.java b/Mage.Sets/src/mage/cards/d/DualNature.java new file mode 100644 index 00000000000..23da3a36382 --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DualNature.java @@ -0,0 +1,234 @@ +/* + * 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.d; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; +import mage.abilities.common.LeavesBattlefieldAllTriggeredAbility; +import mage.abilities.common.ZoneChangeTriggeredAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateTokenCopyTargetEffect; +import mage.abilities.effects.common.ExileAllEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SetTargetPointer; +import mage.constants.Zone; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.NamePredicate; +import mage.filter.predicate.permanent.TokenPredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.util.CardUtil; + +/** + * + * @author TheElk801 + */ +public class DualNature extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nontoken creature"); + + static { + filter.add(Predicates.not(new TokenPredicate())); + } + + public DualNature(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{4}{G}{G}"); + + // Whenever a nontoken creature enters the battlefield, its controller creates a token that's a copy of that creature. + this.addAbility(new EntersBattlefieldAllTriggeredAbility( + Zone.BATTLEFIELD, new DualNatureCreateTokenEffect(), filter, false, SetTargetPointer.PERMANENT, + "Whenever a nontoken creature enters the battlefield, its controller creates a token that's a copy of that creature." + )); + + // Whenever a nontoken creature leaves the battlefield, exile all tokens with the same name as that creature. + this.addAbility(new LeavesBattlefieldAllTriggeredAbility( + Zone.BATTLEFIELD, new DualNatureCreatureLeavesEffect(), filter, false, SetTargetPointer.PERMANENT + )); + + // When Dual Nature leaves the battlefield, exile all tokens created with Dual Nature. + this.addAbility(new DualNatureLeavesBattlefieldTriggeredAbility()); + } + + public DualNature(final DualNature card) { + super(card); + } + + @Override + public DualNature copy() { + return new DualNature(this); + } +} + +class DualNatureCreateTokenEffect extends OneShotEffect { + + DualNatureCreateTokenEffect() { + super(Outcome.PutCardInPlay); + this.staticText = "its controller creates a token that's a copy of that creature"; + } + + DualNatureCreateTokenEffect(final DualNatureCreateTokenEffect effect) { + super(effect); + } + + @Override + public DualNatureCreateTokenEffect copy() { + return new DualNatureCreateTokenEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent != null) { + CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect(permanent.getControllerId()); + effect.setTargetPointer(targetPointer); + effect.apply(game, source); + Object object = game.getState().getValue(CardUtil.getCardZoneString("_tokensCreated", source.getSourceId(), game)); + Set tokensCreated; + if (object != null) { + tokensCreated = (Set) object; + } else { + tokensCreated = new HashSet<>(); + } + for (Permanent perm : effect.getAddedPermanent()) { + if (perm != null) { + tokensCreated.add(perm.getId()); + } + } + game.getState().setValue(CardUtil.getCardZoneString("_tokensCreated", source.getSourceId(), game), tokensCreated); + } + return true; + } +} + +class DualNatureCreatureLeavesEffect extends OneShotEffect { + + DualNatureCreatureLeavesEffect() { + super(Outcome.DestroyPermanent); + this.staticText = "exile all tokens with the same name as that creature"; + } + + DualNatureCreatureLeavesEffect(final DualNatureCreatureLeavesEffect effect) { + super(effect); + } + + @Override + public DualNatureCreatureLeavesEffect copy() { + return new DualNatureCreatureLeavesEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent creature = game.getPermanentOrLKIBattlefield(this.getTargetPointer().getFirst(game, source)); + if (creature != null) { + FilterPermanent filter = new FilterPermanent(); + filter.add(new TokenPredicate()); + filter.add(new NamePredicate(creature.getName())); + new ExileAllEffect(filter).apply(game, source); + return true; + } + return false; + } +} + +class DualNatureLeavesBattlefieldTriggeredAbility extends ZoneChangeTriggeredAbility { + + DualNatureLeavesBattlefieldTriggeredAbility() { + super(Zone.BATTLEFIELD, null, new DualNatureExileEffect(), "When {this} leaves the battlefield, ", false); + } + + DualNatureLeavesBattlefieldTriggeredAbility(DualNatureLeavesBattlefieldTriggeredAbility ability) { + super(ability); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (super.checkTrigger(event, game)) { + for (Effect effect : this.getEffects()) { + if (effect instanceof DualNatureExileEffect) { + ((DualNatureExileEffect) effect).setCardZoneString(CardUtil.getCardZoneString("_tokensCreated", this.getSourceId(), game, true)); + } + } + return true; + } + return false; + } + + @Override + public DualNatureLeavesBattlefieldTriggeredAbility copy() { + return new DualNatureLeavesBattlefieldTriggeredAbility(this); + } +} + +class DualNatureExileEffect extends OneShotEffect { + + private String cardZoneString; + + DualNatureExileEffect() { + super(Outcome.Benefit); + this.staticText = "exile all tokens created with {this}."; + } + + DualNatureExileEffect(final DualNatureExileEffect effect) { + super(effect); + this.cardZoneString = effect.cardZoneString; + } + + @Override + public DualNatureExileEffect copy() { + return new DualNatureExileEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Object object = game.getState().getValue(cardZoneString); + if (object != null) { + Set tokensCreated = (Set) object; + for (UUID tokenId : tokensCreated) { + Permanent token = game.getPermanent(tokenId); + if (token != null) { + token.destroy(source.getSourceId(), game, true); + } + } + } + return true; + } + + public void setCardZoneString(String cardZoneString) { + this.cardZoneString = cardZoneString; + } +} diff --git a/Mage.Sets/src/mage/cards/d/DuskborneSkymarcher.java b/Mage.Sets/src/mage/cards/d/DuskborneSkymarcher.java index 32423191b86..4eb31fefe5b 100644 --- a/Mage.Sets/src/mage/cards/d/DuskborneSkymarcher.java +++ b/Mage.Sets/src/mage/cards/d/DuskborneSkymarcher.java @@ -71,7 +71,7 @@ public class DuskborneSkymarcher extends CardImpl { // {W}, {T}: Target attacking vampire gets +1/+1 until end of turn. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostTargetEffect(1, 1, Duration.EndOfTurn), new ManaCostsImpl("{W}")); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent()); + ability.addTarget(new TargetCreaturePermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/e/EntrancingMelody.java b/Mage.Sets/src/mage/cards/e/EntrancingMelody.java index b84395188be..8a49d375f06 100644 --- a/Mage.Sets/src/mage/cards/e/EntrancingMelody.java +++ b/Mage.Sets/src/mage/cards/e/EntrancingMelody.java @@ -37,7 +37,6 @@ import mage.constants.CardType; import mage.constants.ComparisonType; import mage.constants.Duration; import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ConvertedManaCostPredicate; import mage.game.Game; import mage.target.common.TargetCreaturePermanent; @@ -65,8 +64,8 @@ public class EntrancingMelody extends CardImpl { if (ability instanceof SpellAbility) { ability.getTargets().clear(); int xValue = ability.getManaCostsToPay().getX(); - FilterCreaturePermanent filter = new FilterCreaturePermanent("creature with converted mana cost X or less"); - filter.add(Predicates.not(new ConvertedManaCostPredicate(ComparisonType.EQUAL_TO, xValue))); + FilterCreaturePermanent filter = new FilterCreaturePermanent("creature with converted mana cost X"); + filter.add(new ConvertedManaCostPredicate(ComparisonType.EQUAL_TO, xValue)); ability.addTarget(new TargetCreaturePermanent(filter)); } } diff --git a/Mage.Sets/src/mage/cards/f/FellFlagship.java b/Mage.Sets/src/mage/cards/f/FellFlagship.java index 1726fc2bdcb..c518dd75a15 100644 --- a/Mage.Sets/src/mage/cards/f/FellFlagship.java +++ b/Mage.Sets/src/mage/cards/f/FellFlagship.java @@ -28,6 +28,7 @@ package mage.cards.f; import java.util.UUID; +import mage.MageInt; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.continuous.BoostControlledEffect; @@ -58,6 +59,8 @@ public class FellFlagship extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); this.subtype.add(SubType.VEHICLE); + this.power = new MageInt(3); + this.toughness = new MageInt(3); // Pirates you control get +1/+0. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostControlledEffect(1, 0, Duration.WhileOnBattlefield, filter))); diff --git a/Mage.Sets/src/mage/cards/g/GildedSentinel.java b/Mage.Sets/src/mage/cards/g/GildedSentinel.java index 060dd11be00..1175fab4a72 100644 --- a/Mage.Sets/src/mage/cards/g/GildedSentinel.java +++ b/Mage.Sets/src/mage/cards/g/GildedSentinel.java @@ -28,6 +28,7 @@ package mage.cards.g; import java.util.UUID; +import mage.MageInt; import mage.constants.SubType; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -43,6 +44,9 @@ public class GildedSentinel extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{4}"); this.subtype.add(SubType.GOLEM); + + this.power = new MageInt(3); + this.toughness = new MageInt(3); } public GildedSentinel(final GildedSentinel card) { diff --git a/Mage.Sets/src/mage/cards/i/ImperialAerosaur.java b/Mage.Sets/src/mage/cards/i/ImperialAerosaur.java index 5fbffa9852b..a40cf227aae 100644 --- a/Mage.Sets/src/mage/cards/i/ImperialAerosaur.java +++ b/Mage.Sets/src/mage/cards/i/ImperialAerosaur.java @@ -72,7 +72,6 @@ public class ImperialAerosaur extends CardImpl { Effect effect = new BoostTargetEffect(1, 1, Duration.EndOfTurn); effect.setText("another target creature you control gets +1/+1"); EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(effect); - ability.addEffect(effect); effect = new GainAbilityTargetEffect(FlyingAbility.getInstance(), Duration.EndOfTurn); effect.setText("and gains flying until end of turn"); ability.addEffect(effect); diff --git a/Mage.Sets/src/mage/cards/i/IridescentDrake.java b/Mage.Sets/src/mage/cards/i/IridescentDrake.java new file mode 100644 index 00000000000..223ddb3276e --- /dev/null +++ b/Mage.Sets/src/mage/cards/i/IridescentDrake.java @@ -0,0 +1,117 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.i; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.constants.SubType; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.filter.predicate.other.AuraCardCanAttachToPermanentId; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.Target; +import mage.target.common.TargetCardInGraveyard; + +/** + * + * @author TheElk801 + */ +public class IridescentDrake extends CardImpl { + + public IridescentDrake(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}"); + + this.subtype.add(SubType.DRAKE); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // When Iridescent Drake enters the battlefield, put target Aura card from a graveyard onto the battlefield under your control attached to Iridescent Drake. + Ability ability = new EntersBattlefieldTriggeredAbility(new IridescentDrakeEffect()); + ability.addTarget(new TargetCardInGraveyard()); + this.addAbility(ability); + } + + public IridescentDrake(final IridescentDrake card) { + super(card); + } + + @Override + public IridescentDrake copy() { + return new IridescentDrake(this); + } +} + +class IridescentDrakeEffect extends OneShotEffect { + + public IridescentDrakeEffect() { + super(Outcome.Benefit); + this.staticText = "put target Aura card from a graveyard onto the battlefield under your control attached to {this}"; + } + + public IridescentDrakeEffect(final IridescentDrakeEffect effect) { + super(effect); + } + + @Override + public IridescentDrakeEffect copy() { + return new IridescentDrakeEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Permanent permanent = game.getPermanent(source.getSourceId()); + Card targetAuraCard = game.getCard(source.getFirstTarget()); + if (controller != null + && permanent != null + && controller.canRespond() + && targetAuraCard != null + && new AuraCardCanAttachToPermanentId(permanent.getId()).apply(targetAuraCard, game)) { + Target target = targetAuraCard.getSpellAbility().getTargets().get(0); + if (target != null) { + game.getState().setValue("attachTo:" + targetAuraCard.getId(), permanent); + controller.moveCards(targetAuraCard, Zone.BATTLEFIELD, source, game); + return permanent.addAttachment(targetAuraCard.getId(), game); + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/m/MaraudingLooter.java b/Mage.Sets/src/mage/cards/m/MaraudingLooter.java index 317c96ced25..c87a6297a66 100644 --- a/Mage.Sets/src/mage/cards/m/MaraudingLooter.java +++ b/Mage.Sets/src/mage/cards/m/MaraudingLooter.java @@ -57,7 +57,7 @@ public class MaraudingLooter extends CardImpl { // Raid - At the beginning of your end step, if you attacked with a creature this turn, you may draw a card. If you do, discard a card. Ability ability = new ConditionalTriggeredAbility( - new BeginningOfEndStepTriggeredAbility(new DrawDiscardControllerEffect(1, 1), TargetController.YOU, false), + new BeginningOfEndStepTriggeredAbility(new DrawDiscardControllerEffect(1, 1, true), TargetController.YOU, false), RaidCondition.instance, "Raid — At the beginning of your end step, " + "if you attacked with a creature this turn, " diff --git a/Mage.Sets/src/mage/cards/n/NullmageAdvocate.java b/Mage.Sets/src/mage/cards/n/NullmageAdvocate.java index 74edc354117..951a8c5ad04 100644 --- a/Mage.Sets/src/mage/cards/n/NullmageAdvocate.java +++ b/Mage.Sets/src/mage/cards/n/NullmageAdvocate.java @@ -54,7 +54,7 @@ import java.util.UUID; public class NullmageAdvocate extends CardImpl { public NullmageAdvocate(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}"); this.subtype.add(SubType.INSECT); this.subtype.add(SubType.DRUID); this.power = new MageInt(2); @@ -64,11 +64,11 @@ public class NullmageAdvocate extends CardImpl { Effect effect = new ReturnFromGraveyardToHandTargetEffect(); effect.setText("Return two target cards from an opponent's graveyard to his or her hand"); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new TapSourceCost()); - + effect = new DestroyTargetEffect("Destroy target artifact or enchantment"); effect.setTargetPointer(new SecondTargetPointer()); ability.addEffect(effect); - ability.addTarget(new TargetCardInOpponentsGraveyard(2,2, new FilterCard("two target cards from an opponent's graveyard"), true)); + ability.addTarget(new TargetCardInOpponentsGraveyard(2, 2, new FilterCard("cards from an opponent's graveyard"), true)); ability.addTarget(new TargetPermanent(StaticFilters.ARTIFACT_OR_ENCHANTMENT_PERMANENT)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/p/PrimalWellspring.java b/Mage.Sets/src/mage/cards/p/PrimalWellspring.java index fc8793547e8..cbdbae5b85c 100644 --- a/Mage.Sets/src/mage/cards/p/PrimalWellspring.java +++ b/Mage.Sets/src/mage/cards/p/PrimalWellspring.java @@ -81,7 +81,7 @@ class PyrimalWellspringTriggeredAbility extends TriggeredAbilityImpl { String abilityOriginalId; public PyrimalWellspringTriggeredAbility(UUID abilityOriginalId, Effect effect) { - super(Zone.ALL, effect, true); + super(Zone.ALL, effect, false); this.abilityOriginalId = abilityOriginalId.toString(); } diff --git a/Mage.Sets/src/mage/cards/p/PyromancersGoggles.java b/Mage.Sets/src/mage/cards/p/PyromancersGoggles.java index 742d616a057..fd658c276eb 100644 --- a/Mage.Sets/src/mage/cards/p/PyromancersGoggles.java +++ b/Mage.Sets/src/mage/cards/p/PyromancersGoggles.java @@ -54,7 +54,7 @@ import mage.target.targetpointer.FixedTarget; public class PyromancersGoggles extends CardImpl { public PyromancersGoggles(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{5}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{5}"); addSuperType(SuperType.LEGENDARY); // {T}: Add {R} to your mana pool. @@ -89,7 +89,7 @@ class PyromancersGogglesTriggeredAbility extends TriggeredAbilityImpl { String abilityOriginalId; public PyromancersGogglesTriggeredAbility(UUID abilityOriginalId, Effect effect) { - super(Zone.ALL, effect, true); + super(Zone.ALL, effect, false); this.abilityOriginalId = abilityOriginalId.toString(); } diff --git a/Mage.Sets/src/mage/cards/s/SearchForAzcanta.java b/Mage.Sets/src/mage/cards/s/SearchForAzcanta.java index 70389391b7c..1fe5f694a8d 100644 --- a/Mage.Sets/src/mage/cards/s/SearchForAzcanta.java +++ b/Mage.Sets/src/mage/cards/s/SearchForAzcanta.java @@ -64,7 +64,7 @@ public class SearchForAzcanta extends CardImpl { this.addSuperType(SuperType.LEGENDARY); // At the beginning of your upkeep, look at the top card of your library. You may put it into your graveyard. Then if you have seven or more cards in your graveyard, you may transform Search for Azcanta. - Ability ability = new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new SearchForAzcantaLookLibraryEffect(), TargetController.YOU, false); + Ability ability = new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new SearchForAzcantaLookLibraryEffect(), TargetController.YOU, true); ability.addEffect(new ConditionalOneShotEffect(new TransformSourceEffect(true), new CardsInControllerGraveCondition(7), "Then if you have seven or more cards in your graveyard, you may transform {this}")); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/s/SunCrownedHunters.java b/Mage.Sets/src/mage/cards/s/SunCrownedHunters.java index d9fa321f933..a433bbd376a 100644 --- a/Mage.Sets/src/mage/cards/s/SunCrownedHunters.java +++ b/Mage.Sets/src/mage/cards/s/SunCrownedHunters.java @@ -53,7 +53,9 @@ public class SunCrownedHunters extends CardImpl { this.toughness = new MageInt(4); // Enrage — Whenever Sun-Crowned Hunters is dealt damage, it deals 3 damage to target opponent. - Ability ability = new DealtDamageToSourceTriggeredAbility(Zone.BATTLEFIELD, new DamageTargetEffect(3, true, "it"), false, true); + Ability ability = new DealtDamageToSourceTriggeredAbility( + Zone.BATTLEFIELD, new DamageTargetEffect(3).setText("it deals 3 damage to target opponent"), false, true + ); ability.addTarget(new TargetOpponent()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SunbirdsInvocation.java b/Mage.Sets/src/mage/cards/s/SunbirdsInvocation.java index aca1f428e36..e451faaa090 100644 --- a/Mage.Sets/src/mage/cards/s/SunbirdsInvocation.java +++ b/Mage.Sets/src/mage/cards/s/SunbirdsInvocation.java @@ -92,7 +92,7 @@ class SunbirdsInvocationTriggeredAbility extends SpellCastControllerTriggeredAbi if (spell != null && spell.getFromZone() == Zone.HAND) { if (spell.getCard() != null) { for (Effect effect : getEffects()) { - effect.setTargetPointer(new FixedTarget(spell.getId())); + effect.setTargetPointer(new FixedTarget(spell.getId(), spell.getZoneChangeCounter(game))); } return true; } @@ -126,7 +126,7 @@ class SunbirdsInvocationEffect extends OneShotEffect { return false; } Cards cards = new CardsImpl(); - int xValue = game.getStack().getSpell(getTargetPointer().getFirst(game, source)).getConvertedManaCost(); + int xValue = game.getLastKnownInformation(this.getTargetPointer().getFirst(game, source), Zone.STACK).getConvertedManaCost(); cards.addAll(controller.getLibrary().getTopCards(game, xValue)); if (!cards.isEmpty()) { controller.revealCards(sourceObject.getIdName(), cards, game); @@ -139,10 +139,9 @@ class SunbirdsInvocationEffect extends OneShotEffect { Card card = cards.get(target.getFirstTarget(), game); if (card != null) { if (controller.chooseUse(outcome, "Do you wish to cast " + card.getName(), source, game)) { - Card copy = game.copyCard(card, source, source.getControllerId()); - controller.cast(copy.getSpellAbility(), game, true); + controller.cast(card.getSpellAbility(), game, true); + cards.remove(card); } - return true; } } } diff --git a/Mage.Sets/src/mage/cards/s/SunriseSeeker.java b/Mage.Sets/src/mage/cards/s/SunriseSeeker.java index 66deabb826a..c5194fb74aa 100644 --- a/Mage.Sets/src/mage/cards/s/SunriseSeeker.java +++ b/Mage.Sets/src/mage/cards/s/SunriseSeeker.java @@ -29,7 +29,7 @@ package mage.cards.s; import java.util.UUID; import mage.MageInt; -import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.effects.keyword.ExploreSourceEffect; import mage.abilities.keyword.VigilanceAbility; import mage.cards.CardImpl; @@ -55,7 +55,7 @@ public class SunriseSeeker extends CardImpl { this.addAbility(VigilanceAbility.getInstance()); // When Sunrise Seeker enters the battlefield, it explores. - this.addAbility(new EntersBattlefieldAbility(new ExploreSourceEffect())); + this.addAbility(new EntersBattlefieldTriggeredAbility(new ExploreSourceEffect())); } public SunriseSeeker(final SunriseSeeker card) { diff --git a/Mage.Sets/src/mage/sets/IconicMasters.java b/Mage.Sets/src/mage/sets/IconicMasters.java index 129666276b3..835ea5dd440 100644 --- a/Mage.Sets/src/mage/sets/IconicMasters.java +++ b/Mage.Sets/src/mage/sets/IconicMasters.java @@ -24,8 +24,7 @@ * The views and conclusions contained in the software and documentation are those of the * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. -*/ - + */ package mage.sets; import mage.cards.ExpansionSet; @@ -54,9 +53,9 @@ public class IconicMasters extends ExpansionSet { this.numBoosterUncommon = 3; this.numBoosterRare = 1; this.ratioBoosterMythic = 8; - + cards.add(new SetCardInfo("Scion of Ugin", 1, Rarity.COMMON, mage.cards.s.ScionOfUgin.class)); - cards.add(new SetCardInfo("Abzan Battle Priest", 2, Rarity.COMMON, mage.cards.a.AbzanBattlePriest.class)); + cards.add(new SetCardInfo("Abzan Battle Priest", 2, Rarity.UNCOMMON, mage.cards.a.AbzanBattlePriest.class)); cards.add(new SetCardInfo("Abzan Falconer", 3, Rarity.UNCOMMON, mage.cards.a.AbzanFalconer.class)); cards.add(new SetCardInfo("Ainok Bond-Kin", 4, Rarity.COMMON, mage.cards.a.AinokBondKin.class)); cards.add(new SetCardInfo("Ajani's Pridemate", 5, Rarity.UNCOMMON, mage.cards.a.AjanisPridemate.class)); @@ -197,7 +196,7 @@ public class IconicMasters extends ExpansionSet { cards.add(new SetCardInfo("Monastery Swiftspear", 140, Rarity.UNCOMMON, mage.cards.m.MonasterySwiftspear.class)); cards.add(new SetCardInfo("Pillar of Flame", 141, Rarity.COMMON, mage.cards.p.PillarOfFlame.class)); cards.add(new SetCardInfo("Prodigal Pyromancer", 142, Rarity.UNCOMMON, mage.cards.p.ProdigalPyromancer.class)); - cards.add(new SetCardInfo("Rift Bolt", 143, Rarity.COMMON, mage.cards.r.RiftBolt.class)); + cards.add(new SetCardInfo("Rift Bolt", 143, Rarity.UNCOMMON, mage.cards.r.RiftBolt.class)); cards.add(new SetCardInfo("Ryusei, the Falling Star", 144, Rarity.RARE, mage.cards.r.RyuseiTheFallingStar.class)); cards.add(new SetCardInfo("Scourge of Valkas", 145, Rarity.RARE, mage.cards.s.ScourgeOfValkas.class)); cards.add(new SetCardInfo("Splatter Thug", 146, Rarity.COMMON, mage.cards.s.SplatterThug.class)); @@ -227,7 +226,7 @@ public class IconicMasters extends ExpansionSet { cards.add(new SetCardInfo("Ivy Elemental", 170, Rarity.COMMON, mage.cards.i.IvyElemental.class)); cards.add(new SetCardInfo("Jaddi Offshoot", 171, Rarity.COMMON, mage.cards.j.JaddiOffshoot.class)); cards.add(new SetCardInfo("Jugan, the Rising Star", 172, Rarity.RARE, mage.cards.j.JuganTheRisingStar.class)); - cards.add(new SetCardInfo("Lead the Stampede", 173, Rarity.UNCOMMON, mage.cards.l.LeadTheStampede.class)); + cards.add(new SetCardInfo("Lead the Stampede", 173, Rarity.COMMON, mage.cards.l.LeadTheStampede.class)); cards.add(new SetCardInfo("Lotus Cobra", 174, Rarity.RARE, mage.cards.l.LotusCobra.class)); cards.add(new SetCardInfo("Lure", 175, Rarity.UNCOMMON, mage.cards.l.Lure.class)); cards.add(new SetCardInfo("Nantuko Shaman", 176, Rarity.COMMON, mage.cards.n.NantukoShaman.class)); diff --git a/Mage.Sets/src/mage/sets/Prophecy.java b/Mage.Sets/src/mage/sets/Prophecy.java index 0a6bea024a9..b238baeb123 100644 --- a/Mage.Sets/src/mage/sets/Prophecy.java +++ b/Mage.Sets/src/mage/sets/Prophecy.java @@ -81,6 +81,7 @@ public class Prophecy extends ExpansionSet { cards.add(new SetCardInfo("Despoil", 62, Rarity.COMMON, mage.cards.d.Despoil.class)); cards.add(new SetCardInfo("Devastate", 87, Rarity.COMMON, mage.cards.d.Devastate.class)); cards.add(new SetCardInfo("Diving Griffin", 6, Rarity.COMMON, mage.cards.d.DivingGriffin.class)); + cards.add(new SetCardInfo("Dual Nature", 112, Rarity.RARE, mage.cards.d.DualNature.class)); cards.add(new SetCardInfo("Entangler", 7, Rarity.UNCOMMON, mage.cards.e.Entangler.class)); cards.add(new SetCardInfo("Excavation", 33, Rarity.UNCOMMON, mage.cards.e.Excavation.class)); cards.add(new SetCardInfo("Fault Riders", 88, Rarity.COMMON, mage.cards.f.FaultRiders.class)); diff --git a/Mage.Sets/src/mage/sets/UrzasDestiny.java b/Mage.Sets/src/mage/sets/UrzasDestiny.java index 87ed6e299a5..e05b5e775aa 100644 --- a/Mage.Sets/src/mage/sets/UrzasDestiny.java +++ b/Mage.Sets/src/mage/sets/UrzasDestiny.java @@ -104,6 +104,7 @@ public class UrzasDestiny extends ExpansionSet { cards.add(new SetCardInfo("Hunting Moa", 109, Rarity.UNCOMMON, mage.cards.h.HuntingMoa.class)); cards.add(new SetCardInfo("Illuminated Wings", 34, Rarity.COMMON, mage.cards.i.IlluminatedWings.class)); cards.add(new SetCardInfo("Impatience", 88, Rarity.RARE, mage.cards.i.Impatience.class)); + cards.add(new SetCardInfo("Iridescent Drake", 35, Rarity.UNCOMMON, mage.cards.i.IridescentDrake.class)); cards.add(new SetCardInfo("Junk Diver", 132, Rarity.RARE, mage.cards.j.JunkDiver.class)); cards.add(new SetCardInfo("Keldon Champion", 90, Rarity.UNCOMMON, mage.cards.k.KeldonChampion.class)); cards.add(new SetCardInfo("Keldon Vandals", 91, Rarity.COMMON, mage.cards.k.KeldonVandals.class)); diff --git a/Mage/src/main/java/mage/abilities/common/LeavesBattlefieldAllTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/LeavesBattlefieldAllTriggeredAbility.java index 2c056774679..5ed3b300b7b 100644 --- a/Mage/src/main/java/mage/abilities/common/LeavesBattlefieldAllTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/LeavesBattlefieldAllTriggeredAbility.java @@ -30,12 +30,14 @@ package mage.abilities.common; import java.util.UUID; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.Effect; +import mage.constants.SetTargetPointer; import mage.constants.Zone; import mage.filter.FilterPermanent; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.ZoneChangeEvent; import mage.game.permanent.Permanent; +import mage.target.targetpointer.FixedTarget; /** * @@ -44,6 +46,7 @@ import mage.game.permanent.Permanent; public class LeavesBattlefieldAllTriggeredAbility extends TriggeredAbilityImpl { protected FilterPermanent filter; + protected SetTargetPointer setTargetPointer; public LeavesBattlefieldAllTriggeredAbility(Effect effect, FilterPermanent filter) { this(effect, filter, false); @@ -54,13 +57,19 @@ public class LeavesBattlefieldAllTriggeredAbility extends TriggeredAbilityImpl { } public LeavesBattlefieldAllTriggeredAbility(Zone zone, Effect effect, FilterPermanent filter, boolean optional) { + this(zone, effect, filter, optional, SetTargetPointer.NONE); + } + + public LeavesBattlefieldAllTriggeredAbility(Zone zone, Effect effect, FilterPermanent filter, boolean optional, SetTargetPointer setTargetPointer) { super(zone, effect, optional); this.filter = filter; + this.setTargetPointer = setTargetPointer; } public LeavesBattlefieldAllTriggeredAbility(final LeavesBattlefieldAllTriggeredAbility ability) { super(ability); filter = ability.filter; + setTargetPointer = ability.setTargetPointer; } @Override @@ -79,8 +88,20 @@ public class LeavesBattlefieldAllTriggeredAbility extends TriggeredAbilityImpl { if (zEvent.getFromZone() == Zone.BATTLEFIELD) { UUID targetId = event.getTargetId(); Permanent permanent = game.getPermanentOrLKIBattlefield(targetId); - if (permanent != null) { - return filter.match(permanent, getSourceId(), getControllerId(), game); + if (permanent != null && filter.match(permanent, getSourceId(), getControllerId(), game)) { + if (setTargetPointer != SetTargetPointer.NONE) { + for (Effect effect : this.getEffects()) { + switch (setTargetPointer) { + case PERMANENT: + effect.setTargetPointer(new FixedTarget(permanent.getId())); + break; + case PLAYER: + effect.setTargetPointer(new FixedTarget(permanent.getControllerId())); + break; + } + } + } + return true; } } return false; diff --git a/Mage/src/main/java/mage/cards/repository/CardRepository.java b/Mage/src/main/java/mage/cards/repository/CardRepository.java index 82248406626..36a866cf23a 100644 --- a/Mage/src/main/java/mage/cards/repository/CardRepository.java +++ b/Mage/src/main/java/mage/cards/repository/CardRepository.java @@ -58,7 +58,7 @@ public enum CardRepository { // raise this if db structure was changed private static final long CARD_DB_VERSION = 51; // raise this if new cards were added to the server - private static final long CARD_CONTENT_VERSION = 90; + private static final long CARD_CONTENT_VERSION = 91; private Dao cardDao; private Set classNames; diff --git a/Mage/src/main/java/mage/game/permanent/token/DefenderPlantToken.java b/Mage/src/main/java/mage/game/permanent/token/DefenderPlantToken.java index 046b1daab95..b1915879c10 100644 --- a/Mage/src/main/java/mage/game/permanent/token/DefenderPlantToken.java +++ b/Mage/src/main/java/mage/game/permanent/token/DefenderPlantToken.java @@ -52,7 +52,7 @@ public class DefenderPlantToken extends Token { cardType.add(CardType.CREATURE); subtype.add(SubType.PLANT); power = new MageInt(0); - toughness = new MageInt(1); + toughness = new MageInt(2); this.addAbility(DefenderAbility.getInstance()); } diff --git a/Utils/keywords.txt b/Utils/keywords.txt index fa26cf29240..f2c980846b1 100644 --- a/Utils/keywords.txt +++ b/Utils/keywords.txt @@ -54,7 +54,7 @@ Lifelink|instance| Living weapon|new| Madness|card, cost| Melee|new| -Menace|instance| +Menace|new| Miracle|cost| Mountaincycling|cost| Mountainwalk|new|