diff --git a/Mage.Client/src/main/assembly/distribution.xml b/Mage.Client/src/main/assembly/distribution.xml index 9fc10c7aeeb..39c50ec1c99 100644 --- a/Mage.Client/src/main/assembly/distribution.xml +++ b/Mage.Client/src/main/assembly/distribution.xml @@ -72,7 +72,7 @@ false db/ - *.db + cards.h2.mv.db db/ 0644 diff --git a/Mage.Common/src/mage/utils/MageVersion.java b/Mage.Common/src/mage/utils/MageVersion.java index 260e9c8773c..7c4f67d2dfb 100644 --- a/Mage.Common/src/mage/utils/MageVersion.java +++ b/Mage.Common/src/mage/utils/MageVersion.java @@ -42,7 +42,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 = 0; - public final static String MAGE_VERSION_MINOR_PATCH = "v0"; + public final static String MAGE_VERSION_MINOR_PATCH = "v2"; public final static String MAGE_VERSION_INFO = ""; private final int major; diff --git a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java index e036a3f8200..f0bce292705 100644 --- a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java +++ b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java @@ -341,10 +341,12 @@ public class ComputerPlayer extends PlayerImpl implements Player { if (target instanceof TargetPermanentOrPlayer) { List targets; TargetPermanentOrPlayer t = ((TargetPermanentOrPlayer) target); + List ownedTargets = threats(playerId, sourceId, ((FilterPermanentOrPlayer) t.getFilter()).getPermanentFilter(), game, target.getTargets());; + List opponentTargets = threats(opponentId, sourceId, ((FilterPermanentOrPlayer) t.getFilter()).getPermanentFilter(), game, target.getTargets()); if (outcome.isGood()) { - targets = threats(playerId, sourceId, ((FilterPermanentOrPlayer) t.getFilter()).getPermanentFilter(), game, target.getTargets()); + targets = ownedTargets; } else { - targets = threats(opponentId, sourceId, ((FilterPermanentOrPlayer) t.getFilter()).getPermanentFilter(), game, target.getTargets()); + targets = opponentTargets; } for (Permanent permanent : targets) { List alreadyTargetted = target.getTargets(); @@ -366,7 +368,7 @@ public class ComputerPlayer extends PlayerImpl implements Player { return true; } } - if (!target.isRequired(sourceId, game)) { + if (!target.isRequired(sourceId, game) || target.getNumberOfTargets() == 0) { return false; } if (target.canTarget(opponentId, null, game)) { @@ -377,7 +379,21 @@ public class ComputerPlayer extends PlayerImpl implements Player { target.add(playerId, game); return true; } - throw new IllegalStateException("TargetPermanentOrPlayer wasn't handled. class:" + target.getClass().toString()); + if (outcome.isGood()) { // no other valid targets so use a permanent + targets = opponentTargets; + } else { + targets = ownedTargets; + } + for (Permanent permanent : targets) { + List alreadyTargetted = target.getTargets(); + if (t.canTarget(permanent.getId(), game)) { + if (alreadyTargetted != null && !alreadyTargetted.contains(permanent.getId())) { + target.add(permanent.getId(), game); + return true; + } + } + } + return false; } if (target instanceof TargetCardInGraveyard) { List cards = new ArrayList<>(); diff --git a/Mage.Sets/src/mage/sets/alliances/SchoolOfTheUnseen.java b/Mage.Sets/src/mage/sets/alliances/SchoolOfTheUnseen.java new file mode 100644 index 00000000000..88b9331e425 --- /dev/null +++ b/Mage.Sets/src/mage/sets/alliances/SchoolOfTheUnseen.java @@ -0,0 +1,66 @@ +/* + * 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.alliances; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.mana.AnyColorManaAbility; +import mage.abilities.mana.ColorlessManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; + +/** + * + * @author anonymous + */ +public class SchoolOfTheUnseen extends CardImpl { + + public SchoolOfTheUnseen(UUID ownerId) { + super(ownerId, 186, "School of the Unseen", Rarity.UNCOMMON, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "ALL"; + + // {tap}: Add {1} to your mana pool. + this.addAbility(new ColorlessManaAbility()); + // {2}, {tap}: Add one mana of any color to your mana pool. + Ability ability = new AnyColorManaAbility(new GenericManaCost(2)); + ability.addCost(new TapSourceCost()); + this.addAbility(ability); + } + + public SchoolOfTheUnseen(final SchoolOfTheUnseen card) { + super(card); + } + + @Override + public SchoolOfTheUnseen copy() { + return new SchoolOfTheUnseen(this); + } +} diff --git a/Mage.Sets/src/mage/sets/alliances/ShelteredValley.java b/Mage.Sets/src/mage/sets/alliances/ShelteredValley.java new file mode 100644 index 00000000000..b8d81deb48a --- /dev/null +++ b/Mage.Sets/src/mage/sets/alliances/ShelteredValley.java @@ -0,0 +1,94 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.alliances; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.costs.Cost; +import mage.abilities.costs.CostImpl; +import mage.abilities.costs.common.SacrificeAllCost; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.EnterBattlefieldPayCostOrPutGraveyardEffect; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.mana.ColorlessManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterLandPermanent; +import mage.filter.predicate.mageobject.NamePredicate; + +/** + * + * @author anonymous + */ +public class ShelteredValley extends CardImpl { + + private static final FilterLandPermanent filter = new FilterLandPermanent(); + private static final FilterPermanent filterShelteredValley = new FilterPermanent("permanent named Sheltered Valley"); + + static { + filterShelteredValley.add(new NamePredicate("Sheltered Valley")); + } + + public ShelteredValley(UUID ownerId) { + super(ownerId, 187, "Sheltered Valley", Rarity.RARE, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "ALL"; + + // If Sheltered Valley would enter the battlefield, instead sacrifice each other permanent named Sheltered Valley you control, then put Sheltered Valley onto the battlefield. + Effect effect = new EnterBattlefieldPayCostOrPutGraveyardEffect(new SacrificeAllCost(filterShelteredValley)); + effect.setText("If {this} would enter the battlefield, instead sacrifice each other permanent named {this} you control, then put {this} onto the battlefield."); + Ability ability = new SimpleStaticAbility(Zone.ALL, effect); + this.addAbility(ability); + + // At the beginning of your upkeep, if you control three or fewer lands, you gain 1 life. + Condition controls = new PermanentsOnTheBattlefieldCondition(filter, PermanentsOnTheBattlefieldCondition.CountType.FEWER_THAN, 4); + effect = new ConditionalOneShotEffect(new GainLifeEffect(1), controls); + effect.setText("if you control three or fewer lands, you gain 1 life"); + ability = new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, effect, TargetController.YOU, false); + this.addAbility(ability); + // {tap}: Add {1} to your mana pool. + this.addAbility(new ColorlessManaAbility()); + } + + public ShelteredValley(final ShelteredValley card) { + super(card); + } + + @Override + public ShelteredValley copy() { + return new ShelteredValley(this); + } +} diff --git a/Mage.Sets/src/mage/sets/anthologyjacevschandra/KeldonMegaliths.java b/Mage.Sets/src/mage/sets/anthologyjacevschandra/KeldonMegaliths.java new file mode 100644 index 00000000000..988ce46d238 --- /dev/null +++ b/Mage.Sets/src/mage/sets/anthologyjacevschandra/KeldonMegaliths.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.anthologyjacevschandra; + +import java.util.UUID; + +/** + * + * @author anonymous + */ +public class KeldonMegaliths extends mage.sets.jacevschandra.KeldonMegaliths { + + public KeldonMegaliths(UUID ownerId) { + super(ownerId); + this.cardNumber = 58; + this.expansionSetCode = "DD3D"; + } + + public KeldonMegaliths(final KeldonMegaliths card) { + super(card); + } + + @Override + public KeldonMegaliths copy() { + return new KeldonMegaliths(this); + } +} diff --git a/Mage.Sets/src/mage/sets/arabiannights/AliFromCairo.java b/Mage.Sets/src/mage/sets/arabiannights/AliFromCairo.java index 5979cec8a08..076d03c794f 100644 --- a/Mage.Sets/src/mage/sets/arabiannights/AliFromCairo.java +++ b/Mage.Sets/src/mage/sets/arabiannights/AliFromCairo.java @@ -83,35 +83,36 @@ class AliFromCairoReplacementEffect extends ReplacementEffectImpl { return new AliFromCairoReplacementEffect(this); } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DAMAGE_CAUSES_LIFE_LOSS; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType().equals(GameEvent.EventType.DAMAGE_CAUSES_LIFE_LOSS)) { - Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent != null) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null - && (controller.getLife() > 0) &&(controller.getLife() - event.getAmount()) < 1 - && event.getPlayerId().equals(controller.getId()) - ) { - event.setAmount(controller.getLife() - 1); - //unsure how to make this comply with - // 10/1/2008: The ability doesn't change how much damage is dealt; - // it just changes how much life that damage makes you lose. - // An effect such as Spirit Link will see the full amount of damage being dealt. - } + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent != null) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null + && (controller.getLife() > 0) &&(controller.getLife() - event.getAmount()) < 1 + && event.getPlayerId().equals(controller.getId()) + ) { + return true; + //unsure how to make this comply with + // 10/1/2008: The ability doesn't change how much damage is dealt; + // it just changes how much life that damage makes you lose. + // An effect such as Spirit Link will see the full amount of damage being dealt. } } - - return false; - } - - @Override - public boolean apply(Game game, Ability source) { return false; } @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + event.setAmount(controller.getLife() - 1); + } return false; } diff --git a/Mage.Sets/src/mage/sets/arabiannights/ElephantGraveyard.java b/Mage.Sets/src/mage/sets/arabiannights/ElephantGraveyard.java new file mode 100644 index 00000000000..f5b46ed2f5b --- /dev/null +++ b/Mage.Sets/src/mage/sets/arabiannights/ElephantGraveyard.java @@ -0,0 +1,54 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.arabiannights; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author anonymous + */ +public class ElephantGraveyard extends mage.sets.masterseditioniv.ElephantGraveyard { + + public ElephantGraveyard(UUID ownerId) { + super(ownerId); + this.cardNumber = 88; + this.expansionSetCode = "ARN"; + this.rarity = Rarity.RARE; + } + + public ElephantGraveyard(final ElephantGraveyard card) { + super(card); + } + + @Override + public ElephantGraveyard copy() { + return new ElephantGraveyard(this); + } +} diff --git a/Mage.Sets/src/mage/sets/arabiannights/IslandOfWakWak.java b/Mage.Sets/src/mage/sets/arabiannights/IslandOfWakWak.java new file mode 100644 index 00000000000..3a1fecf7c82 --- /dev/null +++ b/Mage.Sets/src/mage/sets/arabiannights/IslandOfWakWak.java @@ -0,0 +1,110 @@ +/* + * 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.arabiannights; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.SetPowerToughnessTargetEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author anonymous + */ +public class IslandOfWakWak extends CardImpl { + + private static final FilterCreaturePermanent filterWithFlying = new FilterCreaturePermanent("creature with flying"); + + static { + filterWithFlying.add(new AbilityPredicate(FlyingAbility.class)); + } + + public IslandOfWakWak(UUID ownerId) { + super(ownerId, 89, "Island of Wak-Wak", Rarity.RARE, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "ARN"; + + // {tap}: The power of target creature with flying becomes 0 until end of turn. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new IslandOfWakWakEffect(), new TapSourceCost()); + ability.addTarget(new TargetCreaturePermanent(filterWithFlying)); + this.addAbility(ability); + } + + public IslandOfWakWak(final IslandOfWakWak card) { + super(card); + } + + @Override + public IslandOfWakWak copy() { + return new IslandOfWakWak(this); + } +} + + +class IslandOfWakWakEffect extends OneShotEffect { + + public IslandOfWakWakEffect() { + super(Outcome.Detriment); + staticText = "The power of target creature with flying becomes 0 until end of turn"; + } + + public IslandOfWakWakEffect(final IslandOfWakWakEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent targetCreature = game.getPermanent(source.getFirstTarget()); + if (targetCreature != null) { + MageInt toughness = targetCreature.getToughness(); + game.addEffect(new SetPowerToughnessTargetEffect(0, toughness.getValue(), Duration.EndOfTurn), source); + return true; + } + return false; + } + + @Override + public Effect copy() { + return new IslandOfWakWakEffect(this); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/archenemy/MakeshiftMannequin.java b/Mage.Sets/src/mage/sets/archenemy/MakeshiftMannequin.java new file mode 100644 index 00000000000..e6f6c9a72df --- /dev/null +++ b/Mage.Sets/src/mage/sets/archenemy/MakeshiftMannequin.java @@ -0,0 +1,148 @@ +/* + * 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.archenemy; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.BecomesTargetTriggeredAbility; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.SacrificeSourceEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Layer; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.SubLayer; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.filter.common.FilterCreatureCard; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCardInYourGraveyard; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author emerald000 + */ +public class MakeshiftMannequin extends CardImpl { + + public MakeshiftMannequin(UUID ownerId) { + super(ownerId, 20, "Makeshift Mannequin", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{3}{B}"); + this.expansionSetCode = "ARC"; + + // Return target creature card from your graveyard to the battlefield with a mannequin counter on it. For as long as that creature has a mannequin counter on it, it has "When this creature becomes the target of a spell or ability, sacrifice it." + this.getSpellAbility().addEffect(new MakeshiftMannequinEffect()); + this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(new FilterCreatureCard("creature card from your graveyard"))); + } + + public MakeshiftMannequin(final MakeshiftMannequin card) { + super(card); + } + + @Override + public MakeshiftMannequin copy() { + return new MakeshiftMannequin(this); + } +} + +class MakeshiftMannequinEffect extends OneShotEffect { + + MakeshiftMannequinEffect() { + super(Outcome.PutCreatureInPlay); + this.staticText = "Return target creature card from your graveyard to the battlefield with a mannequin counter on it. For as long as that creature has a mannequin counter on it, it has \"When this creature becomes the target of a spell or ability, sacrifice it.\""; + } + + MakeshiftMannequinEffect(final MakeshiftMannequinEffect effect) { + super(effect); + } + + @Override + public MakeshiftMannequinEffect copy() { + return new MakeshiftMannequinEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + UUID cardId = this.getTargetPointer().getFirst(game, source); + Card card = controller.getGraveyard().get(cardId, game); + if (card != null) { + if (controller.putOntoBattlefieldWithInfo(card, game, Zone.GRAVEYARD, source.getSourceId())) { + Permanent permanent = game.getPermanent(cardId); + if (permanent != null) { + permanent.addCounters(CounterType.MANNEQUIN.createInstance(), game); + ContinuousEffect gainedEffect = new MakeshiftMannequinGainAbilityEffect(); + gainedEffect.setTargetPointer(new FixedTarget(cardId)); + game.addEffect(gainedEffect, source); + } + } + return true; + } + } + return false; + } +} + +class MakeshiftMannequinGainAbilityEffect extends ContinuousEffectImpl { + + MakeshiftMannequinGainAbilityEffect() { + super(Duration.Custom, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility); + } + + MakeshiftMannequinGainAbilityEffect(final MakeshiftMannequinGainAbilityEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(this.getTargetPointer().getFirst(game, source)); + if (permanent != null) { + permanent.addAbility(new BecomesTargetTriggeredAbility(new SacrificeSourceEffect()), source.getSourceId(), game); + return true; + } + return false; + } + + @Override + public boolean isInactive(Ability source, Game game) { + Permanent permanent = game.getPermanent(this.getTargetPointer().getFirst(game, source)); + return permanent == null || permanent.getCounters().getCount(CounterType.MANNEQUIN) < 1; + } + + @Override + public MakeshiftMannequinGainAbilityEffect copy() { + return new MakeshiftMannequinGainAbilityEffect(this); + } +} diff --git a/Mage.Sets/src/mage/sets/archenemy/NantukoMonastery.java b/Mage.Sets/src/mage/sets/archenemy/NantukoMonastery.java new file mode 100644 index 00000000000..485c90500a1 --- /dev/null +++ b/Mage.Sets/src/mage/sets/archenemy/NantukoMonastery.java @@ -0,0 +1,92 @@ +/* + * 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.archenemy; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.condition.common.CardsInControllerGraveCondition; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.abilities.mana.ColorlessManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.permanent.token.Token; + +/** + * + * @author anonymous + */ +public class NantukoMonastery extends CardImpl { + + public NantukoMonastery(UUID ownerId) { + super(ownerId, 131, "Nantuko Monastery", Rarity.UNCOMMON, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "ARC"; + + // {tap}: Add {1} to your mana pool. + this.addAbility(new ColorlessManaAbility()); + // Threshold - {G}{W}: Nantuko Monastery becomes a 4/4 green and white Insect Monk creature with first strike until end of turn. It's still a land. Activate this ability only if seven or more cards are in your graveyard. + Effect effect = new BecomesCreatureSourceEffect(new NantukoMonasteryToken(), "land", Duration.Custom); + effect.setText("{this} becomes a 4/4 green and white Insect Monk creature"); + Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl<>("{G}{W}"), + new CardsInControllerGraveCondition(7), + "Threshold - {G}{W}: Nantuko Monastery becomes a 4/4 green and white Insect Monk creature with first strike until end of turn. It's still a land. Activate this ability only if seven or more cards are in your graveyard."); + ability.addEffect(new GainAbilitySourceEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn)); + this.addAbility(ability); + } + + public NantukoMonastery(final NantukoMonastery card) { + super(card); + } + + @Override + public NantukoMonastery copy() { + return new NantukoMonastery(this); + } +} + +class NantukoMonasteryToken extends Token { + + public NantukoMonasteryToken() { + super("", "4/4 green and white Insect Monk creature"); + cardType.add(CardType.CREATURE); + subtype.add("Insect"); + subtype.add("Monk"); + color.setGreen(true); + color.setWhite(true); + power = new MageInt(4); + toughness = new MageInt(4); + } +} diff --git a/Mage.Sets/src/mage/sets/avacynrestored/CavernOfSouls.java b/Mage.Sets/src/mage/sets/avacynrestored/CavernOfSouls.java index 859098b82fa..bb147a16330 100644 --- a/Mage.Sets/src/mage/sets/avacynrestored/CavernOfSouls.java +++ b/Mage.Sets/src/mage/sets/avacynrestored/CavernOfSouls.java @@ -34,7 +34,6 @@ import mage.ConditionalMana; import mage.MageObject; import mage.Mana; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.common.TapSourceCost; diff --git a/Mage.Sets/src/mage/sets/avacynrestored/GloomSurgeon.java b/Mage.Sets/src/mage/sets/avacynrestored/GloomSurgeon.java index 6398ed2a5f7..1e1c67ad312 100644 --- a/Mage.Sets/src/mage/sets/avacynrestored/GloomSurgeon.java +++ b/Mage.Sets/src/mage/sets/avacynrestored/GloomSurgeon.java @@ -84,31 +84,24 @@ class GloomSurgeonEffect extends ReplacementEffectImpl { GameEvent preventEvent = new GameEvent(GameEvent.EventType.PREVENT_DAMAGE, source.getFirstTarget(), source.getSourceId(), source.getControllerId(), event.getAmount(), false); if (!game.replaceEvent(preventEvent)) { int preventedDamage = event.getAmount(); - event.setAmount(0); - - Player player = game.getPlayer(source.getControllerId()); - if (player != null) { - int cardsCount = Math.min(preventedDamage, player.getLibrary().size()); - for (int i = 0; i < cardsCount; i++) { - Card card = player.getLibrary().removeFromTop(game); - if (card != null) { - player.moveCardToExileWithInfo(card, null, null, source.getSourceId(), game, Zone.LIBRARY, true); - } else { - break; - } - } - } - game.fireEvent(GameEvent.getEvent(GameEvent.EventType.PREVENTED_DAMAGE, source.getFirstTarget(), source.getSourceId(), source.getControllerId(), preventedDamage)); + Player player = game.getPlayer(source.getControllerId()); + if (player != null) { + player.moveCards(player.getLibrary().getTopCards(game, preventedDamage), Zone.LIBRARY, Zone.EXILED, source, game); + } return true; } - return false; } - + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DAMAGE_CREATURE; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == GameEvent.EventType.DAMAGE_CREATURE && event.getTargetId().equals(source.getSourceId())) { + if (event.getTargetId().equals(source.getSourceId())) { DamageCreatureEvent damageEvent = (DamageCreatureEvent) event; if (damageEvent.isCombatDamage()) { return true; @@ -117,11 +110,6 @@ class GloomSurgeonEffect extends ReplacementEffectImpl { return false; } - @Override - public boolean apply(Game game, Ability source) { - return true; - } - @Override public GloomSurgeonEffect copy() { return new GloomSurgeonEffect(this); diff --git a/Mage.Sets/src/mage/sets/avacynrestored/InfiniteReflection.java b/Mage.Sets/src/mage/sets/avacynrestored/InfiniteReflection.java index 5add19975f2..3f79caf503d 100644 --- a/Mage.Sets/src/mage/sets/avacynrestored/InfiniteReflection.java +++ b/Mage.Sets/src/mage/sets/avacynrestored/InfiniteReflection.java @@ -131,23 +131,19 @@ class InfiniteReflectionEntersBattlefieldEffect extends ReplacementEffectImpl { super(effect); } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD) { - Permanent permanent = game.getPermanent(event.getTargetId()); - if (permanent != null && permanent.getControllerId().equals(source.getControllerId()) - && permanent.getCardType().contains(CardType.CREATURE) - && !(permanent instanceof PermanentToken)) { - return true; - } - } - return false; + Permanent permanent = game.getPermanent(event.getTargetId()); + return permanent != null && permanent.getControllerId().equals(source.getControllerId()) + && permanent.getCardType().contains(CardType.CREATURE) + && !(permanent instanceof PermanentToken); } - @Override - public boolean apply(Game game, Ability source) { - return false; - } @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { diff --git a/Mage.Sets/src/mage/sets/avacynrestored/Malignus.java b/Mage.Sets/src/mage/sets/avacynrestored/Malignus.java index ec21e7895b3..401e828148e 100644 --- a/Mage.Sets/src/mage/sets/avacynrestored/Malignus.java +++ b/Mage.Sets/src/mage/sets/avacynrestored/Malignus.java @@ -27,22 +27,25 @@ */ package mage.sets.avacynrestored; +import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.CardsInControllerHandCount; +import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; import mage.abilities.effects.Effect; -import mage.abilities.effects.ReplacementEffectImpl; import mage.abilities.effects.common.continuous.SetPowerToughnessSourceEffect; import mage.cards.CardImpl; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; import mage.players.Player; -import java.util.UUID; - /** * @author noxx */ @@ -111,7 +114,7 @@ class HighestLifeTotalAmongOpponentsCount implements DynamicValue { } } -class MalignusEffect extends ReplacementEffectImpl { +class MalignusEffect extends ContinuousRuleModifyingEffectImpl { public MalignusEffect() { super(Duration.WhileOnBattlefield, Outcome.Benefit); @@ -126,23 +129,15 @@ class MalignusEffect extends ReplacementEffectImpl { public MalignusEffect copy() { return new MalignusEffect(this); } - + @Override - public boolean apply(Game game, Ability source) { - return true; + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.PREVENT_DAMAGE; } - - @Override - public boolean replaceEvent(GameEvent event, Ability source, Game game) { - return true; - } - + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == GameEvent.EventType.PREVENT_DAMAGE && event.getSourceId().equals(source.getSourceId())) { - return true; - } - return false; + return event.getSourceId().equals(source.getSourceId()); } } diff --git a/Mage.Sets/src/mage/sets/avacynrestored/PillarOfFlame.java b/Mage.Sets/src/mage/sets/avacynrestored/PillarOfFlame.java index a4fc0537d13..014284bd8e5 100644 --- a/Mage.Sets/src/mage/sets/avacynrestored/PillarOfFlame.java +++ b/Mage.Sets/src/mage/sets/avacynrestored/PillarOfFlame.java @@ -37,11 +37,13 @@ import mage.abilities.effects.ReplacementEffectImpl; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.replacement.DealtDamageToCreatureBySourceDies; import mage.cards.CardImpl; +import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; import mage.game.events.ZoneChangeEvent; import mage.game.permanent.Permanent; +import mage.players.Player; import mage.target.common.TargetCreatureOrPlayer; import mage.watchers.common.DamagedByWatcher; @@ -55,7 +57,6 @@ public class PillarOfFlame extends CardImpl { super(ownerId, 149, "Pillar of Flame", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{R}"); this.expansionSetCode = "AVR"; - // Pillar of Flame deals 2 damage to target creature or player. this.getSpellAbility().addEffect(new DamageTargetEffect(2)); this.getSpellAbility().addTarget(new TargetCreatureOrPlayer()); @@ -97,19 +98,25 @@ class PillarOfFlameEffect extends ReplacementEffectImpl { @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { + Player controller = game.getPlayer(source.getControllerId()); Permanent permanent = ((ZoneChangeEvent) event).getTarget(); - if (permanent != null) { - return permanent.moveToExile(null, "", source.getSourceId(), game); + if (controller != null && permanent != null) { + return controller.moveCards(permanent, Zone.BATTLEFIELD, Zone.EXILED, source, game); } return false; } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.ZONE_CHANGE; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == EventType.ZONE_CHANGE && ((ZoneChangeEvent) event).isDiesEvent()) { + if (((ZoneChangeEvent) event).isDiesEvent()) { DamagedByWatcher watcher = (DamagedByWatcher) game.getState().getWatchers().get("DamagedByWatcher", source.getSourceId()); if (watcher != null) { - return watcher.damagedCreatures.contains(event.getTargetId()); + return watcher.wasDamaged(event.getTargetId(), game); } } return false; diff --git a/Mage.Sets/src/mage/sets/avacynrestored/RestorationAngel.java b/Mage.Sets/src/mage/sets/avacynrestored/RestorationAngel.java index feea58d9e9f..bd3043c6e72 100644 --- a/Mage.Sets/src/mage/sets/avacynrestored/RestorationAngel.java +++ b/Mage.Sets/src/mage/sets/avacynrestored/RestorationAngel.java @@ -111,7 +111,7 @@ class RestorationAngelEffect extends OneShotEffect { Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); Permanent permanent = game.getPermanent(targetPointer.getFirst(game, source)); if (permanent != null && sourcePermanent != null) { - controller.moveCardToExileWithInfo(permanent, source.getSourceId(), sourcePermanent.getName(), source.getSourceId(), game, Zone.BATTLEFIELD, true); + controller.moveCardToExileWithInfo(permanent, source.getSourceId(), sourcePermanent.getIdName(), source.getSourceId(), game, Zone.BATTLEFIELD, true); Card card = game.getCard(targetPointer.getFirst(game, source)); if (card != null) { Zone currentZone = game.getState().getZone(card.getId()); diff --git a/Mage.Sets/src/mage/sets/avacynrestored/SigardaHostOfHerons.java b/Mage.Sets/src/mage/sets/avacynrestored/SigardaHostOfHerons.java index f1946da2444..6807769fbe2 100644 --- a/Mage.Sets/src/mage/sets/avacynrestored/SigardaHostOfHerons.java +++ b/Mage.Sets/src/mage/sets/avacynrestored/SigardaHostOfHerons.java @@ -34,6 +34,7 @@ import mage.MageInt; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; import mage.abilities.effects.ReplacementEffectImpl; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.HexproofAbility; @@ -75,7 +76,7 @@ public class SigardaHostOfHerons extends CardImpl { } } -class SigardaHostOfHeronsEffect extends ReplacementEffectImpl { +class SigardaHostOfHeronsEffect extends ContinuousRuleModifyingEffectImpl { public SigardaHostOfHeronsEffect() { super(Duration.WhileOnBattlefield, Outcome.Benefit); @@ -92,18 +93,13 @@ class SigardaHostOfHeronsEffect extends ReplacementEffectImpl { } @Override - public boolean apply(Game game, Ability source) { - return true; + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.SACRIFICE_PERMANENT; } - - @Override - public boolean replaceEvent(GameEvent event, Ability source, Game game) { - return true; - } - + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == GameEvent.EventType.SACRIFICE_PERMANENT && event.getPlayerId().equals(source.getControllerId())) { + if (event.getPlayerId().equals(source.getControllerId())) { MageObject object = game.getObject(event.getSourceId()); if (object instanceof PermanentCard) { if (game.getOpponents(source.getControllerId()).contains(((PermanentCard)object).getControllerId())) { diff --git a/Mage.Sets/src/mage/sets/avacynrestored/StolenGoods.java b/Mage.Sets/src/mage/sets/avacynrestored/StolenGoods.java index 908feaafca0..0d1a260fe2c 100644 --- a/Mage.Sets/src/mage/sets/avacynrestored/StolenGoods.java +++ b/Mage.Sets/src/mage/sets/avacynrestored/StolenGoods.java @@ -40,6 +40,7 @@ import mage.players.Player; import mage.target.common.TargetOpponent; import java.util.UUID; +import mage.MageObject; import mage.abilities.effects.ContinuousEffect; import mage.target.targetpointer.FixedTarget; @@ -88,13 +89,14 @@ class StolenGoodsEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player opponent = game.getPlayer(targetPointer.getFirst(game, source)); - if (opponent != null && opponent.getLibrary().size() > 0) { + MageObject sourceObject = source.getSourceObject(game); + if (opponent != null && opponent.getLibrary().size() > 0 && sourceObject != null) { Library library = opponent.getLibrary(); Card card; do { card = library.removeFromTop(game); if (card != null) { - opponent.moveCardToExileWithInfo(card, source.getSourceId(), "Stolen Goods", source.getSourceId(), game, Zone.LIBRARY, true); + opponent.moveCardToExileWithInfo(card, source.getSourceId(), sourceObject.getIdName(), source.getSourceId(), game, Zone.LIBRARY, true); } } while (library.size() > 0 && card != null && card.getCardType().contains(CardType.LAND)); diff --git a/Mage.Sets/src/mage/sets/betrayersofkamigawa/KumanosBlessing.java b/Mage.Sets/src/mage/sets/betrayersofkamigawa/KumanosBlessing.java index f5bf7ddc56e..6f181f5b103 100644 --- a/Mage.Sets/src/mage/sets/betrayersofkamigawa/KumanosBlessing.java +++ b/Mage.Sets/src/mage/sets/betrayersofkamigawa/KumanosBlessing.java @@ -65,7 +65,6 @@ public class KumanosBlessing extends CardImpl { this.expansionSetCode = "BOK"; this.subtype.add("Aura"); - // Flash this.addAbility(FlashAbility.getInstance()); // Enchant creature @@ -106,11 +105,6 @@ class KumanosBlessingEffect extends ReplacementEffectImpl { return new KumanosBlessingEffect(this); } - @Override - public boolean apply(Game game, Ability source) { - return true; - } - @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { Permanent permanent = ((ZoneChangeEvent)event).getTarget(); @@ -121,15 +115,18 @@ class KumanosBlessingEffect extends ReplacementEffectImpl { return false; } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.ZONE_CHANGE; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == EventType.ZONE_CHANGE) { - ZoneChangeEvent zce = (ZoneChangeEvent) event; - if (zce.isDiesEvent()) { - DamagedByEnchantedWatcher watcher = (DamagedByEnchantedWatcher) game.getState().getWatchers().get("DamagedByEnchantedWatcher", source.getSourceId()); - if (watcher != null) { - return watcher.wasDamaged(zce.getTarget(), game); - } + ZoneChangeEvent zce = (ZoneChangeEvent) event; + if (zce.isDiesEvent()) { + DamagedByEnchantedWatcher watcher = (DamagedByEnchantedWatcher) game.getState().getWatchers().get("DamagedByEnchantedWatcher", source.getSourceId()); + if (watcher != null) { + return watcher.wasDamaged(zce.getTarget(), game); } } return false; diff --git a/Mage.Sets/src/mage/sets/betrayersofkamigawa/OpalEyeKondasYojimbo.java b/Mage.Sets/src/mage/sets/betrayersofkamigawa/OpalEyeKondasYojimbo.java index 6c4f04570e0..d76893538ab 100644 --- a/Mage.Sets/src/mage/sets/betrayersofkamigawa/OpalEyeKondasYojimbo.java +++ b/Mage.Sets/src/mage/sets/betrayersofkamigawa/OpalEyeKondasYojimbo.java @@ -41,6 +41,7 @@ import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.PreventionEffectImpl; import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.effects.common.PreventDamageToSourceEffect; import mage.abilities.keyword.BushidoAbility; import mage.abilities.keyword.DefenderAbility; import mage.cards.CardImpl; @@ -78,8 +79,8 @@ public class OpalEyeKondasYojimbo extends CardImpl { ability.addTarget(new TargetSource()); this.addAbility(ability); - // {1}{W}: Prevent the next 1 damage that would be dealt to Opal-Eye this turn. - this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new OpalEyeKondasYojimboPreventEffect(), new ManaCostsImpl("{1}{W}"))); + // {1}{W}: Prevent the next 1 damage that would be dealt to Opal-Eye this turn. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new PreventDamageToSourceEffect(Duration.EndOfTurn, 1), new ManaCostsImpl("{1}{W}"))); } @@ -94,32 +95,43 @@ public class OpalEyeKondasYojimbo extends CardImpl { } class OpalEyeKondasYojimboRedirectionEffect extends ReplacementEffectImpl { - + + private final TargetSource target; + OpalEyeKondasYojimboRedirectionEffect() { super(Duration.EndOfTurn, Outcome.RedirectDamage); staticText = "The next time a source of your choice would deal damage this turn, that damage is dealt to {this} instead"; + this.target = new TargetSource(); } OpalEyeKondasYojimboRedirectionEffect(final OpalEyeKondasYojimboRedirectionEffect effect) { super(effect); + this.target = effect.target.copy(); + } + + @Override + public void init(Ability source, Game game) { + this.target.choose(Outcome.PreventDamage, source.getControllerId(), source.getSourceId(), game); + super.init(source, game); } @Override - public boolean applies(GameEvent event, Ability source, Game game) { - if (!this.used) { - if (event.getType().equals(GameEvent.EventType.DAMAGE_CREATURE ) || + public boolean checksEventType(GameEvent event, Game game) { + return event.getType().equals(GameEvent.EventType.DAMAGE_CREATURE ) || event.getType().equals(GameEvent.EventType.DAMAGE_PLANESWALKER ) || - event.getType().equals(GameEvent.EventType.DAMAGE_PLAYER ) ) { - if (event.getSourceId().equals(targetPointer.getFirst(game, source))) { - // check source - MageObject object = game.getObject(event.getSourceId()); - if (object == null) { - game.informPlayers("Couldn't find source of damage"); - return false; - } - return true; - } + event.getType().equals(GameEvent.EventType.DAMAGE_PLAYER ); + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (event.getSourceId().equals(target.getFirstTarget())) { + // check source + MageObject object = game.getObject(event.getSourceId()); + if (object == null) { + game.informPlayers("Couldn't find source of damage"); + return false; } + return true; } return false; } @@ -148,64 +160,15 @@ class OpalEyeKondasYojimboRedirectionEffect extends ReplacementEffectImpl { } game.informPlayers(message.toString()); // redirect damage - this.used = true; + discard(); sourcePermanent.damage(damageEvent.getAmount(), damageEvent.getSourceId(), game, damageEvent.isCombatDamage(), damageEvent.isPreventable(), event.getAppliedEffects()); return true; } return false; } - @Override - public boolean apply(Game game, Ability source) { - return true; - } - @Override public OpalEyeKondasYojimboRedirectionEffect copy() { return new OpalEyeKondasYojimboRedirectionEffect(this); } } - -class OpalEyeKondasYojimboPreventEffect extends PreventionEffectImpl { - - public OpalEyeKondasYojimboPreventEffect() { - super(Duration.EndOfTurn); - staticText = "Prevent the next 1 damage that would be dealt to {this} this turn"; - } - - public OpalEyeKondasYojimboPreventEffect(final OpalEyeKondasYojimboPreventEffect effect) { - super(effect); - } - - @Override - public OpalEyeKondasYojimboPreventEffect copy() { - return new OpalEyeKondasYojimboPreventEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - return true; - } - - @Override - public boolean replaceEvent(GameEvent event, Ability source, Game game) { - GameEvent preventEvent = new GameEvent(GameEvent.EventType.PREVENT_DAMAGE, source.getFirstTarget(), source.getSourceId(), source.getControllerId(), event.getAmount(), false); - if (!game.replaceEvent(preventEvent)) { - if (event.getAmount() >= 1) { - int damage = 1; - event.setAmount(event.getAmount() - 1); - this.used = true; - game.fireEvent(GameEvent.getEvent(GameEvent.EventType.PREVENTED_DAMAGE, source.getFirstTarget(), source.getSourceId(), source.getControllerId(), damage)); - } - } - return false; - } - - @Override - public boolean applies(GameEvent event, Ability source, Game game) { - if (!this.used && super.applies(event, source, game) && event.getTargetId().equals(source.getSourceId())) { - return true; - } - return false; - } -} diff --git a/Mage.Sets/src/mage/sets/betrayersofkamigawa/OrbOfDreams.java b/Mage.Sets/src/mage/sets/betrayersofkamigawa/OrbOfDreams.java index 6dfdc70dce1..b896f12a2c3 100644 --- a/Mage.Sets/src/mage/sets/betrayersofkamigawa/OrbOfDreams.java +++ b/Mage.Sets/src/mage/sets/betrayersofkamigawa/OrbOfDreams.java @@ -85,19 +85,17 @@ public class OrbOfDreams extends CardImpl { } return false; } - + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD) { - return true; - } - return false; + return true; } - @Override - public boolean apply(Game game, Ability source) { - return false; - } } } diff --git a/Mage.Sets/src/mage/sets/betrayersofkamigawa/ToshiroUmezawa.java b/Mage.Sets/src/mage/sets/betrayersofkamigawa/ToshiroUmezawa.java index 9e176256d23..f7b16531b17 100644 --- a/Mage.Sets/src/mage/sets/betrayersofkamigawa/ToshiroUmezawa.java +++ b/Mage.Sets/src/mage/sets/betrayersofkamigawa/ToshiroUmezawa.java @@ -130,7 +130,7 @@ class ToshiroUmezawaEffect extends OneShotEffect { class ToshiroUmezawaReplacementEffect extends ReplacementEffectImpl { - private UUID cardId; + private final UUID cardId; public ToshiroUmezawaReplacementEffect(UUID cardId) { super(Duration.EndOfTurn, Outcome.Exile); @@ -147,11 +147,6 @@ class ToshiroUmezawaReplacementEffect extends ReplacementEffectImpl { return new ToshiroUmezawaReplacementEffect(this); } - @Override - public boolean apply(Game game, Ability source) { - return true; - } - @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { UUID eventObject = ((ZoneChangeEvent) event).getTargetId(); @@ -167,16 +162,16 @@ class ToshiroUmezawaReplacementEffect extends ReplacementEffectImpl { } return false; } - + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.ZONE_CHANGE; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == EventType.ZONE_CHANGE) { - ZoneChangeEvent zEvent = (ZoneChangeEvent) event; - if (zEvent.getToZone() == Zone.GRAVEYARD - && ((ZoneChangeEvent) event).getTargetId().equals(cardId)) { - return true; - } - } - return false; + ZoneChangeEvent zEvent = (ZoneChangeEvent) event; + return zEvent.getToZone() == Zone.GRAVEYARD + && ((ZoneChangeEvent) event).getTargetId().equals(cardId); } } diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/AkkiLavarunner.java b/Mage.Sets/src/mage/sets/championsofkamigawa/AkkiLavarunner.java index de318507a64..c30235ab5f1 100644 --- a/Mage.Sets/src/mage/sets/championsofkamigawa/AkkiLavarunner.java +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/AkkiLavarunner.java @@ -118,25 +118,24 @@ class TokTokVolcanoBornEffect extends ReplacementEffectImpl { super(effect); } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DAMAGE_PLAYER; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == GameEvent.EventType.DAMAGE_PLAYER) { - Card card = game.getCard(event.getSourceId()); - if (card != null && card.getColor().isRed()) { - event.setAmount(event.getAmount() + 1); - } + Card card = game.getCard(event.getSourceId()); + if (card != null && card.getColor().isRed()) { + return true; } return false; } - @Override - public boolean apply(Game game, Ability source) { - return true; - } - @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { - return apply(game, source); + event.setAmount(event.getAmount() + 1); + return false; } @Override diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/Hinder.java b/Mage.Sets/src/mage/sets/championsofkamigawa/Hinder.java index 963f1cd4503..afdac715e26 100644 --- a/Mage.Sets/src/mage/sets/championsofkamigawa/Hinder.java +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/Hinder.java @@ -60,7 +60,6 @@ public class Hinder extends CardImpl { super(ownerId, 65, "Hinder", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{1}{U}{U}"); this.expansionSetCode = "CHK"; - // Counter target spell. If that spell is countered this way, put that card on the top or bottom of its owner's library instead of into that player's graveyard. this.getSpellAbility().addEffect(new HinderEffect()); this.getSpellAbility().addTarget(new TargetSpell()); @@ -143,11 +142,6 @@ class HinderReplacementEffect extends ReplacementEffectImpl { return new HinderReplacementEffect(this); } - @Override - public boolean apply(Game game, Ability source) { - return false; - } - @Override public boolean isInactive(Ability source, Game game) { if (!game.getPhase().getStep().getType().equals(phaseStep)) { @@ -179,9 +173,14 @@ class HinderReplacementEffect extends ReplacementEffectImpl { return false; } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.ZONE_CHANGE; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == EventType.ZONE_CHANGE && ((ZoneChangeEvent)event).getToZone().equals(Zone.GRAVEYARD)) { + if (((ZoneChangeEvent)event).getToZone().equals(Zone.GRAVEYARD)) { MageObject mageObject = game.getLastKnownInformation(getTargetPointer().getFirst(game, source), Zone.STACK); if (mageObject instanceof Spell) { return ((Spell)mageObject).getSourceId().equals(event.getTargetId()); diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/LongForgottenGohei.java b/Mage.Sets/src/mage/sets/championsofkamigawa/LongForgottenGohei.java index 2cac959bbe7..35429ee0b0a 100644 --- a/Mage.Sets/src/mage/sets/championsofkamigawa/LongForgottenGohei.java +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/LongForgottenGohei.java @@ -45,7 +45,7 @@ import mage.filter.predicate.mageobject.SubtypePredicate; /** * - * @author Ludwig + * @author LevelX2 */ public class LongForgottenGohei extends CardImpl { @@ -61,8 +61,10 @@ public class LongForgottenGohei extends CardImpl { public LongForgottenGohei(UUID ownerId) { super(ownerId, 261, "Long-Forgotten Gohei", Rarity.RARE, new CardType[]{CardType.ARTIFACT}, "{3}"); this.expansionSetCode = "CHK"; + // Arcane spells you cast cost {1} less to cast. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpellsCostReductionControllerEffect(arcaneFilter, 1))); + // Spirit creatures you control get +1/+1. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostControlledEffect(1, 1, Duration.WhileOnBattlefield, spiritFilter, false))); } diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/OtherworldlyJourney.java b/Mage.Sets/src/mage/sets/championsofkamigawa/OtherworldlyJourney.java index 35f6d792be0..00a11497edb 100644 --- a/Mage.Sets/src/mage/sets/championsofkamigawa/OtherworldlyJourney.java +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/OtherworldlyJourney.java @@ -38,7 +38,6 @@ import mage.abilities.DelayedTriggeredAbility; import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.ReplacementEffectImpl; -import mage.abilities.effects.common.counter.AddCountersTargetEffect; import mage.cards.Card; import mage.cards.CardImpl; import mage.constants.Duration; @@ -52,7 +51,6 @@ import mage.game.events.GameEvent.EventType; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.TargetCreaturePermanent; -import mage.target.targetpointer.FixedTarget; /** * @author LevelX @@ -146,16 +144,15 @@ class OtherworldlyJourneyReturnFromExileEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - Card card = game.getCard(objectToReturn.getSourceId()); - if (card != null && objectToReturn.refersTo(card, game)) { + Card card = game.getCard(objectToReturn.getSourceId()); + if (card != null && objectToReturn.refersTo(card, game)) { + Player owner = game.getPlayer(card.getOwnerId()); + if (owner != null) { game.addEffect(new OtherworldlyJourneyEntersBattlefieldEffect(objectToReturn), source); - controller.putOntoBattlefieldWithInfo(card, game, Zone.EXILED, source.getSourceId()); + owner.putOntoBattlefieldWithInfo(card, game, Zone.EXILED, source.getSourceId()); } - return true; } - return false; + return true; } } diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/SamuraiOfThePaleCurtain.java b/Mage.Sets/src/mage/sets/championsofkamigawa/SamuraiOfThePaleCurtain.java index 5a340f6d805..8d5a6b433ab 100644 --- a/Mage.Sets/src/mage/sets/championsofkamigawa/SamuraiOfThePaleCurtain.java +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/SamuraiOfThePaleCurtain.java @@ -96,11 +96,6 @@ class SamuraiOfThePaleCurtainEffect extends ReplacementEffectImpl { return new SamuraiOfThePaleCurtainEffect(this); } - @Override - public boolean apply(Game game, Ability source) { - return true; - } - @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { Permanent permanent = ((ZoneChangeEvent)event).getTarget(); @@ -110,15 +105,15 @@ class SamuraiOfThePaleCurtainEffect extends ReplacementEffectImpl { return false; } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.ZONE_CHANGE; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == EventType.ZONE_CHANGE ) { - ZoneChangeEvent zEvent = (ZoneChangeEvent)event; - if (zEvent.getToZone() == Zone.GRAVEYARD) { - return true; - } - } - return false; + ZoneChangeEvent zEvent = (ZoneChangeEvent)event; + return zEvent.getToZone() == Zone.GRAVEYARD; } } diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/UntaidakeTheCloudKeeper.java b/Mage.Sets/src/mage/sets/championsofkamigawa/UntaidakeTheCloudKeeper.java new file mode 100644 index 00000000000..1319d9af8c3 --- /dev/null +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/UntaidakeTheCloudKeeper.java @@ -0,0 +1,115 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.championsofkamigawa; + +import java.util.UUID; +import mage.ConditionalMana; +import mage.MageObject; +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.SpellAbility; +import mage.abilities.common.EntersBattlefieldTappedAbility; +import mage.abilities.condition.Condition; +import mage.abilities.costs.common.PayLifeCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.mana.ConditionalColorlessManaAbility; +import mage.abilities.mana.builder.ConditionalManaBuilder; +import mage.abilities.mana.conditional.ManaCondition; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.game.Game; + +/** + * + * @author anonymous + */ +public class UntaidakeTheCloudKeeper extends CardImpl { + + public UntaidakeTheCloudKeeper(UUID ownerId) { + super(ownerId, 285, "Untaidake, the Cloud Keeper", Rarity.RARE, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "CHK"; + this.supertype.add("Legendary"); + + // Untaidake, the Cloud Keeper enters the battlefield tapped. + this.addAbility(new EntersBattlefieldTappedAbility()); + // {tap}, Pay 2 life: Add {2} to your mana pool. Spend this mana only to cast legendary spells. + Ability ability = new ConditionalColorlessManaAbility(new TapSourceCost(), 2, new LegendarySpellManaBuilder()); + ability.addCost(new PayLifeCost(2)); + this.addAbility(ability); + + } + + public UntaidakeTheCloudKeeper(final UntaidakeTheCloudKeeper card) { + super(card); + } + + @Override + public UntaidakeTheCloudKeeper copy() { + return new UntaidakeTheCloudKeeper(this); + } +} + +class LegendarySpellManaBuilder extends ConditionalManaBuilder { + @Override + public ConditionalMana build(Object... options) { + return new LegendaryCastConditionalMana(this.mana); + } + + @Override + public String getRule() { + return "Spend this mana only to cast legendary spells"; + } +} + +class LegendaryCastConditionalMana extends ConditionalMana { + + public LegendaryCastConditionalMana(Mana mana) { + super(mana); + staticText = "Spend this mana only to cast legendary spells"; + addCondition(new LegendaryCastManaCondition()); + } +} + +class LegendaryCastManaCondition extends ManaCondition implements Condition { + @Override + public boolean apply(Game game, Ability source) { + if (source instanceof SpellAbility) { + MageObject object = game.getObject(source.getSourceId()); + if (object != null && object.getSupertype().contains("Legendary")) { + return true; + } + } + return false; + } + + @Override + public boolean apply(Game game, Ability source, UUID originalId) { + return apply(game, source); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/YamabushisStorm.java b/Mage.Sets/src/mage/sets/championsofkamigawa/YamabushisStorm.java index 42195113735..9ec4a27bccf 100644 --- a/Mage.Sets/src/mage/sets/championsofkamigawa/YamabushisStorm.java +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/YamabushisStorm.java @@ -39,28 +39,29 @@ import mage.abilities.effects.ReplacementEffectImpl; import mage.abilities.effects.common.DamageAllEffect; import mage.abilities.effects.common.replacement.DealtDamageToCreatureBySourceDies; import mage.cards.CardImpl; +import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; import mage.game.events.ZoneChangeEvent; import mage.game.permanent.Permanent; +import mage.players.Player; import mage.watchers.common.DamagedByWatcher; /** * * @author LevelX */ - public class YamabushisStorm extends CardImpl { public YamabushisStorm(UUID ownerId) { super(ownerId, 199, "Yamabushi's Storm", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{1}{R}"); this.expansionSetCode = "CHK"; - // Yamabushi's Storm deals 1 damage to each creature. this.getSpellAbility().addEffect(new DamageAllEffect(1, new FilterCreaturePermanent())); + // If a creature dealt damage this way would die this turn, exile it instead. this.getSpellAbility().addEffect(new DealtDamageToCreatureBySourceDies(this, Duration.EndOfTurn)); this.getSpellAbility().addWatcher(new DamagedByWatcher()); @@ -79,43 +80,42 @@ public class YamabushisStorm extends CardImpl { class YamabushisStormEffect extends ReplacementEffectImpl { - public YamabushisStormEffect() { - super(Duration.EndOfTurn, Outcome.Exile); - staticText = "If a creature dealt damage this way would die this turn, exile it instead"; - } + public YamabushisStormEffect() { + super(Duration.EndOfTurn, Outcome.Exile); + staticText = "If a creature dealt damage this way would die this turn, exile it instead"; + } - public YamabushisStormEffect(final YamabushisStormEffect effect) { - super(effect); - } + public YamabushisStormEffect(final YamabushisStormEffect effect) { + super(effect); + } - @Override - public YamabushisStormEffect copy() { - return new YamabushisStormEffect(this); - } + @Override + public YamabushisStormEffect copy() { + return new YamabushisStormEffect(this); + } - @Override - public boolean apply(Game game, Ability source) { - return true; + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + Player controller = game.getPlayer(source.getControllerId()); + Permanent permanent = ((ZoneChangeEvent) event).getTarget(); + if (controller != null && permanent != null) { + return controller.moveCardToExileWithInfo(permanent, null, "", source.getSourceId(), game, Zone.BATTLEFIELD, true); } + return false; + } - @Override - public boolean replaceEvent(GameEvent event, Ability source, Game game) { - Permanent permanent = ((ZoneChangeEvent)event).getTarget(); - if (permanent != null) { - return permanent.moveToExile(null, "", source.getSourceId(), game); - } - return false; + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.ZONE_CHANGE; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (((ZoneChangeEvent) event).isDiesEvent()) { + DamagedByWatcher watcher = (DamagedByWatcher) game.getState().getWatchers().get("DamagedByWatcher", source.getSourceId()); + return watcher != null && watcher.wasDamaged(event.getTargetId(), game); } + return false; + } - @Override - public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == EventType.ZONE_CHANGE && ((ZoneChangeEvent)event).isDiesEvent()) { - DamagedByWatcher watcher = - (DamagedByWatcher) game.getState().getWatchers().get("DamagedByWatcher", source.getSourceId()); - if (watcher != null) - return watcher.damagedCreatures.contains(event.getTargetId()); - } - return false; - } - -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/sets/commander/SpellCrumple.java b/Mage.Sets/src/mage/sets/commander/SpellCrumple.java index c545647b17d..08c38924c81 100644 --- a/Mage.Sets/src/mage/sets/commander/SpellCrumple.java +++ b/Mage.Sets/src/mage/sets/commander/SpellCrumple.java @@ -61,7 +61,6 @@ public class SpellCrumple extends CardImpl { super(ownerId, 63, "Spell Crumple", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{1}{U}{U}"); this.expansionSetCode = "CMD"; - // Counter target spell. If that spell is countered this way, put it on the bottom of its owner's library instead of into that player's graveyard. Put Spell Crumple on the bottom of its owner's library. this.getSpellAbility().addTarget(new TargetSpell()); this.getSpellAbility().addEffect(new SpellCrumpleCounterEffect()); @@ -145,11 +144,6 @@ class SpellCrumpleReplacementEffect extends ReplacementEffectImpl { return new SpellCrumpleReplacementEffect(this); } - @Override - public boolean apply(Game game, Ability source) { - return false; - } - @Override public boolean isInactive(Ability source, Game game) { if (!game.getPhase().getStep().getType().equals(phaseStep)) { @@ -180,9 +174,14 @@ class SpellCrumpleReplacementEffect extends ReplacementEffectImpl { return false; } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.ZONE_CHANGE; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == EventType.ZONE_CHANGE && ((ZoneChangeEvent)event).getToZone().equals(Zone.GRAVEYARD)) { + if (((ZoneChangeEvent)event).getToZone().equals(Zone.GRAVEYARD)) { MageObject mageObject = game.getLastKnownInformation(getTargetPointer().getFirst(game, source), Zone.STACK); if (mageObject instanceof Spell) { return ((Spell)mageObject).getSourceId().equals(event.getTargetId()); diff --git a/Mage.Sets/src/mage/sets/commander/SvogthosTheRestlessTomb.java b/Mage.Sets/src/mage/sets/commander/SvogthosTheRestlessTomb.java new file mode 100644 index 00000000000..806aa410f90 --- /dev/null +++ b/Mage.Sets/src/mage/sets/commander/SvogthosTheRestlessTomb.java @@ -0,0 +1,89 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.commander; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount; +import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; +import mage.abilities.effects.common.continuous.SetPowerToughnessSourceEffect; +import mage.abilities.mana.ColorlessManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterCreatureCard; +import mage.game.permanent.token.Token; + +/** + * + * @author anonymous + */ +public class SvogthosTheRestlessTomb extends CardImpl { + + public SvogthosTheRestlessTomb(UUID ownerId) { + super(ownerId, 289, "Svogthos, the Restless Tomb", Rarity.UNCOMMON, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "CMD"; + + // {tap}: Add {1} to your mana pool. + this.addAbility(new ColorlessManaAbility()); + // {3}{B}{G}: Until end of turn, Svogthos, the Restless Tomb becomes a black and green Plant Zombie creature with "This creature's power and toughness are each equal to the number of creature cards in your graveyard." It's still a land. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BecomesCreatureSourceEffect(new SvogthosToken(), "land", Duration.EndOfTurn), new ManaCostsImpl<>("{3}{B}{G}")); + this.addAbility(ability); + } + + public SvogthosTheRestlessTomb(final SvogthosTheRestlessTomb card) { + super(card); + } + + @Override + public SvogthosTheRestlessTomb copy() { + return new SvogthosTheRestlessTomb(this); + } +} + +class SvogthosToken extends Token { + + public SvogthosToken() { + super("", "black and green Plant Zombie creature with \"This creature's power and toughness are each equal to the number of creature cards in your graveyard.\""); + cardType.add(CardType.CREATURE); + subtype.add("Plant"); + subtype.add("Zombie"); + color.setGreen(true); + color.setBlack(true); + power = new MageInt(0); + toughness = new MageInt(0); + CardsInControllerGraveyardCount count = new CardsInControllerGraveyardCount(new FilterCreatureCard("creature cards")); + this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetPowerToughnessSourceEffect(count, Duration.EndOfGame))); + } +} diff --git a/Mage.Sets/src/mage/sets/commander2013/NayaSoulbeast.java b/Mage.Sets/src/mage/sets/commander2013/NayaSoulbeast.java index f7474d20df2..a858e59187f 100644 --- a/Mage.Sets/src/mage/sets/commander2013/NayaSoulbeast.java +++ b/Mage.Sets/src/mage/sets/commander2013/NayaSoulbeast.java @@ -137,27 +137,22 @@ class NayaSoulbeastReplacementEffect extends ReplacementEffectImpl { public NayaSoulbeastReplacementEffect(final NayaSoulbeastReplacementEffect effect) { super(effect); } - + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.ENTERS_THE_BATTLEFIELD; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == EventType.ENTERS_THE_BATTLEFIELD) { - if (event.getTargetId().equals(source.getSourceId())) { - return true; - } - } - return false; - } - - @Override - public boolean apply(Game game, Ability source) { - return false; + return event.getTargetId().equals(source.getSourceId()); } @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { Object object = this.getValue("NayaSoulbeastCounters"); if (object instanceof Integer) { - int amount = ((Integer)object).intValue(); + int amount = ((Integer)object); new AddCountersSourceEffect(CounterType.P1P1.createInstance(amount)).apply(game, source); } return false; diff --git a/Mage.Sets/src/mage/sets/commander2013/OpalPalace.java b/Mage.Sets/src/mage/sets/commander2013/OpalPalace.java index 609212f2dfb..33704e9e315 100644 --- a/Mage.Sets/src/mage/sets/commander2013/OpalPalace.java +++ b/Mage.Sets/src/mage/sets/commander2013/OpalPalace.java @@ -146,19 +146,15 @@ class OpalPalaceEntersBattlefieldEffect extends ReplacementEffectImpl { } @Override - public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == EventType.ENTERS_THE_BATTLEFIELD) { - OpalPalaceWatcher watcher = (OpalPalaceWatcher) game.getState().getWatchers().get("ManaPaidFromOpalPalaceWatcher", source.getSourceId()); - if (watcher != null) { - return watcher.commanderId.contains(event.getTargetId()); - } - } - return false; + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.ENTERS_THE_BATTLEFIELD; } - + @Override - public boolean apply(Game game, Ability source) { - return false; + public boolean applies(GameEvent event, Ability source, Game game) { + OpalPalaceWatcher watcher = (OpalPalaceWatcher) game.getState().getWatchers().get("ManaPaidFromOpalPalaceWatcher", source.getSourceId()); + return watcher != null && + watcher.commanderId.contains(event.getTargetId()); } @Override diff --git a/Mage.Sets/src/mage/sets/commander2013/RoonOfTheHiddenRealm.java b/Mage.Sets/src/mage/sets/commander2013/RoonOfTheHiddenRealm.java index e60ca34c814..1228928f8ae 100644 --- a/Mage.Sets/src/mage/sets/commander2013/RoonOfTheHiddenRealm.java +++ b/Mage.Sets/src/mage/sets/commander2013/RoonOfTheHiddenRealm.java @@ -121,7 +121,7 @@ class RoonOfTheHiddenRealmEffect extends OneShotEffect { Card card = game.getCard(getTargetPointer().getFirst(game, source)); if (permanent != null) { UUID exileId = UUID.randomUUID(); - if (controller.moveCardToExileWithInfo(permanent, exileId, sourceObject.getName(), source.getSourceId(), game, Zone.BATTLEFIELD, true)) { + if (controller.moveCardToExileWithInfo(permanent, exileId, sourceObject.getIdName(), source.getSourceId(), game, Zone.BATTLEFIELD, true)) { if (card != null) { AtTheBeginOfNextEndStepDelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new ReturnFromExileEffect(exileId, Zone.BATTLEFIELD)); delayedAbility.setSourceId(source.getSourceId()); diff --git a/Mage.Sets/src/mage/sets/commander2013/WarCadence.java b/Mage.Sets/src/mage/sets/commander2013/WarCadence.java index 5663e853d60..d34d2bd6ab5 100644 --- a/Mage.Sets/src/mage/sets/commander2013/WarCadence.java +++ b/Mage.Sets/src/mage/sets/commander2013/WarCadence.java @@ -83,11 +83,6 @@ class WarCadenceReplacementEffect extends ReplacementEffectImpl { super(effect); } - @Override - public boolean apply(Game game, Ability source) { - return true; - } - @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { Player player = game.getPlayer(event.getPlayerId()); @@ -108,9 +103,14 @@ class WarCadenceReplacementEffect extends ReplacementEffectImpl { return false; } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DECLARE_BLOCKER; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - return event.getType().equals(GameEvent.EventType.DECLARE_BLOCKER); + return true; } @Override diff --git a/Mage.Sets/src/mage/sets/conflux/Banefire.java b/Mage.Sets/src/mage/sets/conflux/Banefire.java index 8e504b49679..ef147d081d2 100644 --- a/Mage.Sets/src/mage/sets/conflux/Banefire.java +++ b/Mage.Sets/src/mage/sets/conflux/Banefire.java @@ -57,13 +57,11 @@ public class Banefire extends CardImpl { super(ownerId, 58, "Banefire", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{X}{R}"); this.expansionSetCode = "CON"; - // Banefire deals X damage to target creature or player. this.getSpellAbility().addEffect(new BaneFireEffect()); this.getSpellAbility().addTarget(new TargetCreatureOrPlayer()); // If X is 5 or more, Banefire can't be countered by spells or abilities and the damage can't be prevented. this.addAbility(new SimpleStaticAbility(Zone.STACK, new BanefireCantCounterEffect())); - } public Banefire(final Banefire card) { @@ -118,7 +116,7 @@ class BaneFireEffect extends OneShotEffect { Player targetPlayer = game.getPlayer(source.getFirstTarget()); Permanent targetCreature = game.getPermanent(source.getFirstTarget()); int damage = source.getManaCostsToPay().getX(); - boolean preventable = damage >= 5; + boolean preventable = damage < 5; if (targetPlayer != null) { targetPlayer.damage(damage, source.getSourceId(), game, false, preventable); return true; diff --git a/Mage.Sets/src/mage/sets/conflux/HellsparkElemental.java b/Mage.Sets/src/mage/sets/conflux/HellsparkElemental.java index b4d33ca0521..cb274cb4309 100644 --- a/Mage.Sets/src/mage/sets/conflux/HellsparkElemental.java +++ b/Mage.Sets/src/mage/sets/conflux/HellsparkElemental.java @@ -63,7 +63,7 @@ public class HellsparkElemental extends CardImpl { // At the beginning of the end step, sacrifice Hellspark Elemental. this.addAbility(new OnEventTriggeredAbility(EventType.END_TURN_STEP_PRE, "beginning of the end step", true, new SacrificeSourceEffect())); - // Unearth {1}{R} ({1}{R}: Return this card from your graveyard to the battlefield. It gains haste. Exile it at the beginning of the next end step or if it would leave the battlefield. Unearth only as a sorcery.) + // Unearth {1}{R}: Return this card from your graveyard to the battlefield. It gains haste. Exile it at the beginning of the next end step or if it would leave the battlefield. Unearth only as a sorcery.) this.addAbility(new UnearthAbility(new ManaCostsImpl("{1}{R}"))); } diff --git a/Mage.Sets/src/mage/sets/conspiracy/SilentArbiter.java b/Mage.Sets/src/mage/sets/conspiracy/SilentArbiter.java new file mode 100644 index 00000000000..19543752f90 --- /dev/null +++ b/Mage.Sets/src/mage/sets/conspiracy/SilentArbiter.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.conspiracy; + +import java.util.UUID; + +/** + * + * @author emerald000 + */ +public class SilentArbiter extends mage.sets.fifthdawn.SilentArbiter { + + public SilentArbiter(UUID ownerId) { + super(ownerId); + this.cardNumber = 204; + this.expansionSetCode = "CNS"; + } + + public SilentArbiter(final SilentArbiter card) { + super(card); + } + + @Override + public SilentArbiter copy() { + return new SilentArbiter(this); + } +} diff --git a/Mage.Sets/src/mage/sets/darkascension/Immerwolf.java b/Mage.Sets/src/mage/sets/darkascension/Immerwolf.java index 35ed6b36b97..b209e272a5d 100644 --- a/Mage.Sets/src/mage/sets/darkascension/Immerwolf.java +++ b/Mage.Sets/src/mage/sets/darkascension/Immerwolf.java @@ -27,23 +27,27 @@ */ package mage.sets.darkascension; -import mage.constants.*; +import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; import mage.abilities.effects.common.continuous.BoostControlledEffect; import mage.abilities.keyword.IntimidateAbility; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.SubtypePredicate; import mage.game.Game; import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; import mage.game.permanent.Permanent; -import java.util.UUID; - /** * * @author BetaSteward @@ -84,14 +88,13 @@ public class Immerwolf extends CardImpl { } } -class ImmerwolfEffect extends ReplacementEffectImpl { +class ImmerwolfEffect extends ContinuousRuleModifyingEffectImpl { - private static final FilterCreaturePermanent filterWerewolf = new FilterCreaturePermanent("Werewolf creature"); - private static final FilterCreaturePermanent filterNonhuman = new FilterCreaturePermanent("Non-human creature"); + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); static { - filterWerewolf.add(new SubtypePredicate("Werewolf")); - filterNonhuman.add(Predicates.not(new SubtypePredicate("Human"))); + filter.add(new SubtypePredicate("Werewolf")); + filter.add(Predicates.not(new SubtypePredicate("Human"))); } public ImmerwolfEffect() { @@ -109,23 +112,15 @@ class ImmerwolfEffect extends ReplacementEffectImpl { } @Override - public boolean apply(Game game, Ability source) { - return true; + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.TRANSFORM; } - - @Override - public boolean replaceEvent(GameEvent event, Ability source, Game game) { - return true; - } - + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == GameEvent.EventType.TRANSFORM) { - Permanent permanent = game.getPermanent(event.getTargetId()); - if (permanent != null && permanent.getControllerId().equals(source.getControllerId()) && filterWerewolf.match(permanent, game) && filterNonhuman.match(permanent, game)) { - return true; - } - } - return false; + Permanent permanent = game.getPermanent(event.getTargetId()); + return permanent != null && + permanent.getControllerId().equals(source.getControllerId()) && + filter.match(permanent, game) ; } } diff --git a/Mage.Sets/src/mage/sets/darkascension/SuddenDisappearance.java b/Mage.Sets/src/mage/sets/darkascension/SuddenDisappearance.java index 34b83d782cb..1e1fce38f17 100644 --- a/Mage.Sets/src/mage/sets/darkascension/SuddenDisappearance.java +++ b/Mage.Sets/src/mage/sets/darkascension/SuddenDisappearance.java @@ -29,6 +29,7 @@ package mage.sets.darkascension; import java.util.List; import java.util.UUID; +import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; import mage.abilities.effects.OneShotEffect; @@ -87,11 +88,12 @@ class SuddenDisappearanceEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { + MageObject sourceObject = source.getSourceObject(game); + if (controller != null && sourceObject != null) { List perms = game.getBattlefield().getAllActivePermanents(filter, source.getFirstTarget(), game); if (perms.size() > 0) { for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, source.getFirstTarget(), game)) { - controller.moveCardToExileWithInfo(permanent, source.getSourceId(), "Sudden Disappearance", source.getSourceId(), game, Zone.BATTLEFIELD, true); + controller.moveCardToExileWithInfo(permanent, source.getSourceId(), sourceObject.getIdName(), source.getSourceId(), game, Zone.BATTLEFIELD, true); } AtTheBeginOfNextEndStepDelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new ReturnFromExileEffect(source.getSourceId(), Zone.BATTLEFIELD)); delayedAbility.setSourceId(source.getSourceId()); diff --git a/Mage.Sets/src/mage/sets/darksteel/ArcboundCrusher.java b/Mage.Sets/src/mage/sets/darksteel/ArcboundCrusher.java new file mode 100644 index 00000000000..83f267ab0c1 --- /dev/null +++ b/Mage.Sets/src/mage/sets/darksteel/ArcboundCrusher.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.darksteel; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class ArcboundCrusher extends mage.sets.planechase.ArcboundCrusher { + + public ArcboundCrusher(UUID ownerId) { + super(ownerId); + this.cardNumber = 95; + this.expansionSetCode = "DST"; + } + + public ArcboundCrusher(final ArcboundCrusher card) { + super(card); + } + + @Override + public ArcboundCrusher copy() { + return new ArcboundCrusher(this); + } +} diff --git a/Mage.Sets/src/mage/sets/darksteel/SerumPowder.java b/Mage.Sets/src/mage/sets/darksteel/SerumPowder.java index 9df04257243..3b07147d6d0 100644 --- a/Mage.Sets/src/mage/sets/darksteel/SerumPowder.java +++ b/Mage.Sets/src/mage/sets/darksteel/SerumPowder.java @@ -87,6 +87,9 @@ class SerumPowderReplaceEffect extends ReplacementEffectImpl { Player controller = game.getPlayer(source.getControllerId()); Card sourceCard = game.getCard(source.getSourceId()); if (controller != null && sourceCard != null) { + if (!controller.chooseUse(outcome, "Exile all cards from hand and draw that many cards?", game)) { + return false; + } int cardsHand = controller.getHand().size(); if (cardsHand > 0){ Cards cards = new CardsImpl(); @@ -98,26 +101,20 @@ class SerumPowderReplaceEffect extends ReplacementEffectImpl { } controller.drawCards(cardsHand, game); } - game.informPlayers(new StringBuilder(sourceCard.getName()).append(": ").append(controller.getLogName()).append(" exiles hand and draws ").append(cardsHand).append(" card(s)").toString()); + game.informPlayers(sourceCard.getLogName() +": " + controller.getLogName() + " exiles hand and draws " + cardsHand + " card(s)"); return true; } return false; } @Override - public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == GameEvent.EventType.CAN_TAKE_MULLIGAN && source.getControllerId().equals(event.getPlayerId())) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - return controller.chooseUse(outcome, "Exile all cards from hand and draw that many cards?", game); - } - } - return false; + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.CAN_TAKE_MULLIGAN; } - + @Override - public boolean apply(Game game, Ability source) { - return false; + public boolean applies(GameEvent event, Ability source, Game game) { + return source.getControllerId().equals(event.getPlayerId()); } @Override diff --git a/Mage.Sets/src/mage/sets/dissension/IsperiaTheInscrutable.java b/Mage.Sets/src/mage/sets/dissension/IsperiaTheInscrutable.java new file mode 100644 index 00000000000..b7363b81be8 --- /dev/null +++ b/Mage.Sets/src/mage/sets/dissension/IsperiaTheInscrutable.java @@ -0,0 +1,125 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.dissension; + +import java.util.UUID; +import mage.MageInt; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.NameACardEffect; +import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.filter.FilterCard; +import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetCardInLibrary; + +/** + * + * @author lunaskyrise + */ +public class IsperiaTheInscrutable extends CardImpl { + + public IsperiaTheInscrutable(UUID ownerId) { + super(ownerId, 114, "Isperia the Inscrutable", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{1}{W}{W}{U}{U}"); + this.expansionSetCode = "DIS"; + this.supertype.add("Legendary"); + this.subtype.add("Sphinx"); + this.power = new MageInt(3); + this.toughness = new MageInt(6); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Whenever Isperia the Inscrutable deals combat damage to a player, name a card. That player reveals his or her hand. If he or she reveals the named card, search your library for a creature card with flying, reveal it, put it into your hand, then shuffle your library. + Effect effect1 = new NameACardEffect(NameACardEffect.TypeOfName.ALL); + Ability ability = new DealsCombatDamageToAPlayerTriggeredAbility(effect1, true, true); + Effect effect2 = new IsperiaTheInscrutableEffect(); + ability.addEffect(effect2); + this.addAbility(ability); + } + + public IsperiaTheInscrutable(final IsperiaTheInscrutable card) { + super(card); + } + + @Override + public IsperiaTheInscrutable copy() { + return new IsperiaTheInscrutable(this); + } +} + +class IsperiaTheInscrutableEffect extends OneShotEffect { + + private static final FilterCard filter = new FilterCard("creature card with flying"); + + static { + filter.add(new AbilityPredicate(FlyingAbility.class)); + filter.add(new CardTypePredicate(CardType.CREATURE)); + } + + public IsperiaTheInscrutableEffect() { + super(Outcome.Neutral); + staticText = "That player reveals his or her hand. If he or she reveals the named card, search your library for a creature card with flying, reveal it, put it into your hand, then shuffle your library"; + } + + public IsperiaTheInscrutableEffect(final IsperiaTheInscrutableEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(getTargetPointer().getFirst(game, source)); + Object object = (String) game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY); + if (player != null && object instanceof String) { + String namedCard = (String) object; + for (Card card : player.getHand().getCards(game)) { + if (card != null && card.getName().equals(namedCard)) { + return new SearchLibraryPutInHandEffect(new TargetCardInLibrary(filter), true, true).apply(game, source); + } + } + return true; + } + return false; + } + + @Override + public Effect copy() { + return new IsperiaTheInscrutableEffect(this); + } +} diff --git a/Mage.Sets/src/mage/sets/dissension/RainOfGore.java b/Mage.Sets/src/mage/sets/dissension/RainOfGore.java index fe97130d4cc..02db58c59eb 100644 --- a/Mage.Sets/src/mage/sets/dissension/RainOfGore.java +++ b/Mage.Sets/src/mage/sets/dissension/RainOfGore.java @@ -86,11 +86,6 @@ class RainOfGoreEffect extends ReplacementEffectImpl { return new RainOfGoreEffect(this); } - @Override - public boolean apply(Game game, Ability source) { - return true; - } - @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { Player player = game.getPlayer(event.getPlayerId()); @@ -100,16 +95,18 @@ class RainOfGoreEffect extends ReplacementEffectImpl { return true; } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.GAIN_LIFE; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - switch (event.getType()) { - case GAIN_LIFE: - if (!game.getStack().isEmpty()) { - StackObject stackObject = game.getStack().getFirst(); - if (stackObject != null) { - return stackObject.getControllerId().equals(event.getPlayerId()); - } - } + if (!game.getStack().isEmpty()) { + StackObject stackObject = game.getStack().getFirst(); + if (stackObject != null) { + return stackObject.getControllerId().equals(event.getPlayerId()); + } } return false; } diff --git a/Mage.Sets/src/mage/sets/dissension/TasteForMayhem.java b/Mage.Sets/src/mage/sets/dissension/TasteForMayhem.java new file mode 100644 index 00000000000..6f9bfd53ae3 --- /dev/null +++ b/Mage.Sets/src/mage/sets/dissension/TasteForMayhem.java @@ -0,0 +1,79 @@ +/* + * 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.dissension; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.HellbentCondition; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.continuous.BoostEnchantedEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author emerald000 + */ +public class TasteForMayhem extends CardImpl { + + public TasteForMayhem(UUID ownerId) { + super(ownerId, 75, "Taste for Mayhem", Rarity.COMMON, new CardType[]{CardType.ENCHANTMENT}, "{R}"); + this.expansionSetCode = "DIS"; + this.subtype.add("Aura"); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + + // Enchanted creature gets +2/+0. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEnchantedEffect(2, 0))); + + // Hellbent - Enchanted creature gets an additional +2/+0 as long as you have no cards in hand. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(new BoostEnchantedEffect(2, 0), HellbentCondition.getInstance(), "Hellbent — Enchanted creature gets an additional +2/+0 as long as you have no cards in hand"))); + } + + public TasteForMayhem(final TasteForMayhem card) { + super(card); + } + + @Override + public TasteForMayhem copy() { + return new TasteForMayhem(this); + } +} diff --git a/Mage.Sets/src/mage/sets/dragonsmaze/MasterOfCruelties.java b/Mage.Sets/src/mage/sets/dragonsmaze/MasterOfCruelties.java index 138f8dd8fe0..ff74e7bdacc 100644 --- a/Mage.Sets/src/mage/sets/dragonsmaze/MasterOfCruelties.java +++ b/Mage.Sets/src/mage/sets/dragonsmaze/MasterOfCruelties.java @@ -36,6 +36,7 @@ import mage.constants.Zone; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.ReplacementEffectImpl; import mage.abilities.keyword.CanAttackOnlyAloneAbility; @@ -153,7 +154,7 @@ class MasterOfCrueltiesEffect extends OneShotEffect { } } -class MasterOfCrueltiesNoDamageEffect extends ReplacementEffectImpl { +class MasterOfCrueltiesNoDamageEffect extends ContinuousRuleModifyingEffectImpl { public MasterOfCrueltiesNoDamageEffect() { super(Duration.EndOfCombat, Outcome.PreventDamage); @@ -170,25 +171,21 @@ class MasterOfCrueltiesNoDamageEffect extends ReplacementEffectImpl { } @Override - public boolean apply(Game game, Ability source) { - return true; - } - - @Override - public boolean replaceEvent(GameEvent event, Ability source, Game game) { - return true; - } - - @Override - public boolean applies(GameEvent event, Ability source, Game game) { + public boolean checksEventType(GameEvent event, Game game) { switch (event.getType()) { case DAMAGE_CREATURE: case DAMAGE_PLAYER: case DAMAGE_PLANESWALKER: - DamageEvent damageEvent = (DamageEvent) event; - return event.getSourceId().equals(source.getSourceId()) && damageEvent.isCombatDamage(); + return true; default: return false; } } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + DamageEvent damageEvent = (DamageEvent) event; + return event.getSourceId().equals(source.getSourceId()) && damageEvent.isCombatDamage(); + + } } diff --git a/Mage.Sets/src/mage/sets/dragonsmaze/PossibilityStorm.java b/Mage.Sets/src/mage/sets/dragonsmaze/PossibilityStorm.java index 7e1becddfbc..24f21aa767a 100644 --- a/Mage.Sets/src/mage/sets/dragonsmaze/PossibilityStorm.java +++ b/Mage.Sets/src/mage/sets/dragonsmaze/PossibilityStorm.java @@ -137,19 +137,19 @@ class PossibilityStormEffect extends OneShotEffect { if (sourceObject != null && spell != null) { Player spellController = game.getPlayer(spell.getControllerId()); if (spellController != null && - spellController.moveCardToExileWithInfo(spell, source.getSourceId(), sourceObject.getName(), source.getSourceId(), game, Zone.STACK, true)) { + spellController.moveCardToExileWithInfo(spell, source.getSourceId(), sourceObject.getIdName(), source.getSourceId(), game, Zone.STACK, true)) { if (spellController.getLibrary().size() > 0) { Library library = spellController.getLibrary(); Card card; do { card = library.removeFromTop(game); if (card != null) { - spellController.moveCardToExileWithInfo(card, source.getSourceId(), sourceObject.getName(), source.getSourceId(), game, Zone.LIBRARY, true); + spellController.moveCardToExileWithInfo(card, source.getSourceId(), sourceObject.getIdName(), source.getSourceId(), game, Zone.LIBRARY, true); } } while (library.size() > 0 && card != null && !sharesType(card, spell.getCardType())); if (card != null && sharesType(card, spell.getCardType())) { - if (spellController.chooseUse(Outcome.PlayForFree, new StringBuilder("Cast ").append(card.getName()).append(" without paying cost?").toString(), game)) { + if (spellController.chooseUse(Outcome.PlayForFree, "Cast " + card.getLogName() + " without paying cost?", game)) { spellController.cast(card.getSpellAbility(), game, true); } } diff --git a/Mage.Sets/src/mage/sets/dragonsoftarkir/CommuneWithLava.java b/Mage.Sets/src/mage/sets/dragonsoftarkir/CommuneWithLava.java index a12f5d63124..1518ef2cc86 100644 --- a/Mage.Sets/src/mage/sets/dragonsoftarkir/CommuneWithLava.java +++ b/Mage.Sets/src/mage/sets/dragonsoftarkir/CommuneWithLava.java @@ -97,7 +97,7 @@ class CommuneWithLavaEffect extends OneShotEffect { List cards = controller.getLibrary().getTopCards(game, amount); for (Card card : cards) { if (card != null) { - controller.moveCardToExileWithInfo(card, CardUtil.getCardExileZoneId(game, source), sourceCard.getName(), source.getSourceId(), game, Zone.LIBRARY, true); + controller.moveCardToExileWithInfo(card, CardUtil.getCardExileZoneId(game, source), sourceCard.getIdName(), source.getSourceId(), game, Zone.LIBRARY, true); ContinuousEffect effect = new CommuneWithLavaMayPlayEffect(); effect.setTargetPointer(new FixedTarget(card.getId())); game.addEffect(effect, source); diff --git a/Mage.Sets/src/mage/sets/dragonsoftarkir/HedonistsTrove.java b/Mage.Sets/src/mage/sets/dragonsoftarkir/HedonistsTrove.java index 2516d6a4806..ab7d60e272d 100644 --- a/Mage.Sets/src/mage/sets/dragonsoftarkir/HedonistsTrove.java +++ b/Mage.Sets/src/mage/sets/dragonsoftarkir/HedonistsTrove.java @@ -106,7 +106,7 @@ class HedonistsTroveExileEffect extends OneShotEffect { for (UUID cardId : graveyard) { Card card = game.getCard(cardId); if (card != null) { - controller.moveCardToExileWithInfo(card, exileId, sourceObject.getName(), source.getSourceId(), game, Zone.GRAVEYARD, true); + controller.moveCardToExileWithInfo(card, exileId, sourceObject.getIdName(), source.getSourceId(), game, Zone.GRAVEYARD, true); } } return true; diff --git a/Mage.Sets/src/mage/sets/dragonsoftarkir/IreShaman.java b/Mage.Sets/src/mage/sets/dragonsoftarkir/IreShaman.java index 05f6cb5bfb5..093bc8ae692 100644 --- a/Mage.Sets/src/mage/sets/dragonsoftarkir/IreShaman.java +++ b/Mage.Sets/src/mage/sets/dragonsoftarkir/IreShaman.java @@ -110,7 +110,7 @@ class IreShamanExileEffect extends OneShotEffect { Library library = controller.getLibrary(); Card card = library.removeFromTop(game); if (card != null) { - String exileName = new StringBuilder(sourcePermanent.getName()).append(" ").toString(); + String exileName = new StringBuilder(sourcePermanent.getIdName()).append(" ").toString(); controller.moveCardToExileWithInfo(card, source.getSourceId(), exileName, source.getSourceId(), game, Zone.LIBRARY, true); ContinuousEffect effect = new IreShamanCastFromExileEffect(); effect.setTargetPointer(new FixedTarget(card.getId())); diff --git a/Mage.Sets/src/mage/sets/dragonsoftarkir/LivingLore.java b/Mage.Sets/src/mage/sets/dragonsoftarkir/LivingLore.java index 9180814c0da..627a332ce4b 100644 --- a/Mage.Sets/src/mage/sets/dragonsoftarkir/LivingLore.java +++ b/Mage.Sets/src/mage/sets/dragonsoftarkir/LivingLore.java @@ -113,7 +113,7 @@ class LivingLoreExileEffect extends OneShotEffect { UUID exileId = CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter()); Card card = controller.getGraveyard().get(target.getFirstTarget(), game); if (card != null) { - controller.moveCardToExileWithInfo(card, exileId, sourceObject.getName(), source.getSourceId(), game, Zone.GRAVEYARD, true); + controller.moveCardToExileWithInfo(card, exileId, sourceObject.getIdName(), source.getSourceId(), game, Zone.GRAVEYARD, true); } } return true; diff --git a/Mage.Sets/src/mage/sets/dragonsoftarkir/SurrakTheHuntCaller.java b/Mage.Sets/src/mage/sets/dragonsoftarkir/SurrakTheHuntCaller.java index e313950d6c3..80f824abe41 100644 --- a/Mage.Sets/src/mage/sets/dragonsoftarkir/SurrakTheHuntCaller.java +++ b/Mage.Sets/src/mage/sets/dragonsoftarkir/SurrakTheHuntCaller.java @@ -61,7 +61,7 @@ public class SurrakTheHuntCaller extends CardImpl { Ability ability = new ConditionalTriggeredAbility( new BeginningOfCombatTriggeredAbility(new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn), TargetController.YOU, false), FormidableCondition.getInstance(), - "Formidable — Whenever {this} attacks, if creatures you control have total power 8 or greater, target creature you control gains haste until end of turn."); + "Formidable — At the beginning of combat on your turn, if creatures you control have total power 8 or greater, target creature you control gains haste until end of turn."); ability.addTarget(new TargetControlledCreaturePermanent()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/sets/eighthedition/ManaClash.java b/Mage.Sets/src/mage/sets/eighthedition/ManaClash.java new file mode 100644 index 00000000000..232905b94ff --- /dev/null +++ b/Mage.Sets/src/mage/sets/eighthedition/ManaClash.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.eighthedition; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class ManaClash extends mage.sets.fourthedition.ManaClash { + + public ManaClash(UUID ownerId) { + super(ownerId); + this.cardNumber = 202; + this.expansionSetCode = "8ED"; + } + + public ManaClash(final ManaClash card) { + super(card); + } + + @Override + public ManaClash copy() { + return new ManaClash(this); + } +} diff --git a/Mage.Sets/src/mage/sets/eventide/Flickerwisp.java b/Mage.Sets/src/mage/sets/eventide/Flickerwisp.java index 596fd51524e..eaac92ae999 100644 --- a/Mage.Sets/src/mage/sets/eventide/Flickerwisp.java +++ b/Mage.Sets/src/mage/sets/eventide/Flickerwisp.java @@ -103,7 +103,7 @@ class FlickerwispEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); if (controller != null && permanent != null && sourcePermanent != null) { - if (controller.moveCardToExileWithInfo(permanent, source.getSourceId(), sourcePermanent.getName(), source.getSourceId(), game, Zone.BATTLEFIELD, true)) { + if (controller.moveCardToExileWithInfo(permanent, source.getSourceId(), sourcePermanent.getIdName(), source.getSourceId(), game, Zone.BATTLEFIELD, true)) { //create delayed triggered ability AtTheBeginOfNextEndStepDelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new ReturnFromExileEffect(source.getSourceId(), Zone.BATTLEFIELD, false)); delayedAbility.setSourceId(source.getSourceId()); diff --git a/Mage.Sets/src/mage/sets/exodus/KorChant.java b/Mage.Sets/src/mage/sets/exodus/KorChant.java index 33d0c0d38c0..0269d443edd 100644 --- a/Mage.Sets/src/mage/sets/exodus/KorChant.java +++ b/Mage.Sets/src/mage/sets/exodus/KorChant.java @@ -117,10 +117,14 @@ class KorChantEffect extends RedirectionEffect { this.target.choose(Outcome.PreventDamage, source.getControllerId(), source.getSourceId(), game); } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DAMAGE_CREATURE; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == GameEvent.EventType.DAMAGE_CREATURE - && event.getTargetId().equals(this.getTargetPointer().getFirst(game, source)) + if (event.getTargetId().equals(this.getTargetPointer().getFirst(game, source)) && event.getSourceId().equals(this.target.getFirstTarget())) { this.redirectTarget = source.getTargets().get(1); return true; diff --git a/Mage.Sets/src/mage/sets/fallenempires/BottomlessVault.java b/Mage.Sets/src/mage/sets/fallenempires/BottomlessVault.java new file mode 100644 index 00000000000..85705452450 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fallenempires/BottomlessVault.java @@ -0,0 +1,85 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.fallenempires; + +import java.util.UUID; +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.EntersBattlefieldTappedAbility; +import mage.abilities.common.SkipUntapOptionalAbility; +import mage.abilities.condition.common.SourceTappedCondition; +import mage.abilities.costs.common.RemoveVariableCountersSourceCost; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.dynamicvalue.common.RemovedCountersForCostValue; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.mana.DynamicManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.counters.CounterType; + +/** + * + * @author anonymous + */ +public class BottomlessVault extends CardImpl { + + public BottomlessVault(UUID ownerId) { + super(ownerId, 177, "Bottomless Vault", Rarity.RARE, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "FEM"; + + // Bottomless Vault enters the battlefield tapped. + this.addAbility(new EntersBattlefieldTappedAbility()); + // You may choose not to untap Bottomless Vault during your untap step. + this.addAbility(new SkipUntapOptionalAbility()); + // At the beginning of your upkeep, if Bottomless Vault is tapped, put a storage counter on it. + OneShotEffect addStorageCounter = new AddCountersSourceEffect(CounterType.STORAGE.createInstance()); + Effect effect = new ConditionalOneShotEffect(addStorageCounter, SourceTappedCondition.getInstance(), "if {this} is tapped, put a storage counter on it"); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, effect, TargetController.YOU, false)); + // {tap}, Remove any number of storage counters from Bottomless Vault: Add {B} to your mana pool for each storage counter removed this way. + Ability ability = new DynamicManaAbility(Mana.BlackMana, new RemovedCountersForCostValue(), + "Add {B} to your mana pool for each storage counter removed this way"); + ability.addCost(new RemoveVariableCountersSourceCost( + CounterType.STORAGE.createInstance(), "Remove any number of storage counters from {this}")); + this.addAbility(ability); + } + + public BottomlessVault(final BottomlessVault card) { + super(card); + } + + @Override + public BottomlessVault copy() { + return new BottomlessVault(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fallenempires/DwarvenHold.java b/Mage.Sets/src/mage/sets/fallenempires/DwarvenHold.java new file mode 100644 index 00000000000..2eec20e78d3 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fallenempires/DwarvenHold.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.fallenempires; + +import java.util.UUID; + +/** + * + * @author anonymous + */ +public class DwarvenHold extends mage.sets.fifthedition.DwarvenHold { + + public DwarvenHold(UUID ownerId) { + super(ownerId); + this.cardNumber = 178; + this.expansionSetCode = "FEM"; + } + + public DwarvenHold(final DwarvenHold card) { + super(card); + } + + @Override + public DwarvenHold copy() { + return new DwarvenHold(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fallenempires/HollowTrees.java b/Mage.Sets/src/mage/sets/fallenempires/HollowTrees.java new file mode 100644 index 00000000000..f14cdd1f50b --- /dev/null +++ b/Mage.Sets/src/mage/sets/fallenempires/HollowTrees.java @@ -0,0 +1,85 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.fallenempires; + +import java.util.UUID; +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.EntersBattlefieldTappedAbility; +import mage.abilities.common.SkipUntapOptionalAbility; +import mage.abilities.condition.common.SourceTappedCondition; +import mage.abilities.costs.common.RemoveVariableCountersSourceCost; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.dynamicvalue.common.RemovedCountersForCostValue; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.mana.DynamicManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.counters.CounterType; + +/** + * + * @author anonymous + */ +public class HollowTrees extends CardImpl { + + public HollowTrees(UUID ownerId) { + super(ownerId, 182, "Hollow Trees", Rarity.RARE, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "FEM"; + + // Hollow Trees enters the battlefield tapped. + this.addAbility(new EntersBattlefieldTappedAbility()); + // You may choose not to untap Hollow Trees during your untap step. + this.addAbility(new SkipUntapOptionalAbility()); + // At the beginning of your upkeep, if Hollow Trees is tapped, put a storage counter on it. + OneShotEffect addStorageCounter = new AddCountersSourceEffect(CounterType.STORAGE.createInstance()); + Effect effect = new ConditionalOneShotEffect(addStorageCounter, SourceTappedCondition.getInstance(), "if {this} is tapped, put a storage counter on it"); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, effect, TargetController.YOU, false)); + // {tap}, Remove any number of storage counters from Hollow Trees: Add {G} to your mana pool for each storage counter removed this way. + Ability ability = new DynamicManaAbility(Mana.BlackMana, new RemovedCountersForCostValue(), + "Add {B} to your mana pool for each storage counter removed this way"); + ability.addCost(new RemoveVariableCountersSourceCost( + CounterType.STORAGE.createInstance(), "Remove any number of storage counters from {this}")); + this.addAbility(ability); + } + + public HollowTrees(final HollowTrees card) { + super(card); + } + + @Override + public HollowTrees copy() { + return new HollowTrees(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fallenempires/IcatianStore.java b/Mage.Sets/src/mage/sets/fallenempires/IcatianStore.java new file mode 100644 index 00000000000..ad30635e7ef --- /dev/null +++ b/Mage.Sets/src/mage/sets/fallenempires/IcatianStore.java @@ -0,0 +1,85 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.fallenempires; + +import java.util.UUID; +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.EntersBattlefieldTappedAbility; +import mage.abilities.common.SkipUntapOptionalAbility; +import mage.abilities.condition.common.SourceTappedCondition; +import mage.abilities.costs.common.RemoveVariableCountersSourceCost; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.dynamicvalue.common.RemovedCountersForCostValue; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.mana.DynamicManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.counters.CounterType; + +/** + * + * @author anonymous + */ +public class IcatianStore extends CardImpl { + + public IcatianStore(UUID ownerId) { + super(ownerId, 183, "Icatian Store", Rarity.RARE, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "FEM"; + + // Icatian Store enters the battlefield tapped. + this.addAbility(new EntersBattlefieldTappedAbility()); + // You may choose not to untap Icatian Store during your untap step. + this.addAbility(new SkipUntapOptionalAbility()); + // At the beginning of your upkeep, if Icatian Store is tapped, put a storage counter on it. + OneShotEffect addStorageCounter = new AddCountersSourceEffect(CounterType.STORAGE.createInstance()); + Effect effect = new ConditionalOneShotEffect(addStorageCounter, SourceTappedCondition.getInstance(), "if {this} is tapped, put a storage counter on it"); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, effect, TargetController.YOU, false)); + // {tap}, Remove any number of storage counters from Icatian Store: Add {W} to your mana pool for each storage counter removed this way. + Ability ability = new DynamicManaAbility(Mana.WhiteMana, new RemovedCountersForCostValue(), + "Add {W} to your mana pool for each storage counter removed this way"); + ability.addCost(new RemoveVariableCountersSourceCost( + CounterType.STORAGE.createInstance(), "Remove any number of storage counters from {this}")); + this.addAbility(ability); + } + + public IcatianStore(final IcatianStore card) { + super(card); + } + + @Override + public IcatianStore copy() { + return new IcatianStore(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fallenempires/SandSilos.java b/Mage.Sets/src/mage/sets/fallenempires/SandSilos.java new file mode 100644 index 00000000000..f16a6a2ebf7 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fallenempires/SandSilos.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.fallenempires; + +import java.util.UUID; + +/** + * + * @author anonymous + */ +public class SandSilos extends mage.sets.fifthedition.SandSilos { + + public SandSilos(UUID ownerId) { + super(ownerId); + this.cardNumber = 186; + this.expansionSetCode = "FEM"; + } + + public SandSilos(final SandSilos card) { + super(card); + } + + @Override + public SandSilos copy() { + return new SandSilos(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fatereforged/JeskaiInfiltrator.java b/Mage.Sets/src/mage/sets/fatereforged/JeskaiInfiltrator.java index f0010e1d536..2b64b4db950 100644 --- a/Mage.Sets/src/mage/sets/fatereforged/JeskaiInfiltrator.java +++ b/Mage.Sets/src/mage/sets/fatereforged/JeskaiInfiltrator.java @@ -113,12 +113,12 @@ class JeskaiInfiltratorEffect extends OneShotEffect { Permanent sourcePermanent = game.getPermanent(source.getSourceId()); Card sourceCard = game.getCard(source.getSourceId()); if (sourcePermanent != null && sourceCard != null) { - player.moveCardToExileWithInfo(sourcePermanent, sourcePermanent.getId(), sourcePermanent.getName(), source.getSourceId(), game, Zone.BATTLEFIELD, true); + player.moveCardToExileWithInfo(sourcePermanent, sourcePermanent.getId(), sourcePermanent.getIdName(), source.getSourceId(), game, Zone.BATTLEFIELD, true); cardsToManifest.add(sourceCard); } if (sourcePermanent!= null && player.getLibrary().size() > 0) { Card cardFromLibrary = player.getLibrary().removeFromTop(game); - player.moveCardToExileWithInfo(cardFromLibrary, sourcePermanent.getId(), sourcePermanent.getName(), source.getSourceId(), game, Zone.LIBRARY, true); + player.moveCardToExileWithInfo(cardFromLibrary, sourcePermanent.getId(), sourcePermanent.getIdName(), source.getSourceId(), game, Zone.LIBRARY, true); cardsToManifest.add(cardFromLibrary); } Collections.shuffle(cardsToManifest); diff --git a/Mage.Sets/src/mage/sets/fatereforged/SoulfireGrandMaster.java b/Mage.Sets/src/mage/sets/fatereforged/SoulfireGrandMaster.java index 7ae39c928db..00b2744e19f 100644 --- a/Mage.Sets/src/mage/sets/fatereforged/SoulfireGrandMaster.java +++ b/Mage.Sets/src/mage/sets/fatereforged/SoulfireGrandMaster.java @@ -27,8 +27,6 @@ */ package mage.sets.fatereforged; -import java.util.HashSet; -import java.util.Iterator; import java.util.UUID; import mage.MageInt; import mage.MageObject; @@ -48,7 +46,6 @@ import mage.constants.Layer; import mage.constants.Outcome; import mage.constants.Rarity; import mage.constants.SubLayer; -import mage.constants.WatcherScope; import mage.constants.Zone; import mage.filter.FilterCard; import mage.filter.FilterObject; @@ -61,7 +58,6 @@ import mage.game.permanent.Permanent; import mage.game.stack.Spell; import mage.game.stack.StackObject; import mage.players.Player; -import mage.watchers.Watcher; /** * @@ -89,7 +85,7 @@ public class SoulfireGrandMaster extends CardImpl { // Instant and sorcery spells you control have lifelink. Effect effect = new GainAbilitySpellsEffect(LifelinkAbility.getInstance(), filter); effect.setText("Instant and sorcery spells you control have lifelink"); - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect), new SoulfireGrandMasterLeavesStackWatcher()); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); // {2}{U/R}{U/R}: The next time you cast an instant or sorcery spell from your hand this turn, put that card into your hand instead of your graveyard as it resolves. this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new SoulfireGrandMasterCastFromHandReplacementEffect(), new ManaCostsImpl("{2}{U/R}{U/R}"))); @@ -134,17 +130,32 @@ class GainAbilitySpellsEffect extends ContinuousEffectImpl { Player player = game.getPlayer(source.getControllerId()); Permanent permanent = game.getPermanent(source.getSourceId()); if (player != null && permanent != null) { - for (Iterator iterator = game.getStack().iterator(); iterator.hasNext();) { - StackObject stackObject = iterator.next(); + for (Card card: game.getExile().getAllCards(game)) { + if (card.getOwnerId().equals(source.getControllerId()) && filter.match(card, game)) { + game.getState().addOtherAbility(card, ability); + } + } + for (Card card: player.getLibrary().getCards(game)) { + if (filter.match(card, game)) { + game.getState().addOtherAbility(card, ability); + } + } + for (Card card: player.getHand().getCards(game)) { + if (filter.match(card, game)) { + game.getState().addOtherAbility(card, ability); + } + } + for (Card card: player.getGraveyard().getCards(game)) { + if (filter.match(card, game)) { + game.getState().addOtherAbility(card, ability); + } + } + for (StackObject stackObject : game.getStack()) { if (stackObject.getControllerId().equals(source.getControllerId())) { Card card = game.getCard(stackObject.getSourceId()); if (card != null && filter.match(card, game)) { if (!card.getAbilities().contains(ability)) { game.getState().addOtherAbility(card, ability); - SoulfireGrandMasterLeavesStackWatcher watcher = (SoulfireGrandMasterLeavesStackWatcher) game.getState().getWatchers().get("SoulfireGrandMasterLeavesStackWatcher"); - if (watcher != null) { - watcher.addCardId(card.getId()); - } } } } @@ -238,44 +249,3 @@ class SoulfireGrandMasterCastFromHandReplacementEffect extends ReplacementEffect } } - -class SoulfireGrandMasterLeavesStackWatcher extends Watcher { - - private final HashSet cardIds = new HashSet<>(); - - public SoulfireGrandMasterLeavesStackWatcher() { - super("SoulfireGrandMasterLeavesStackWatcher", WatcherScope.GAME); - } - - public SoulfireGrandMasterLeavesStackWatcher(final SoulfireGrandMasterLeavesStackWatcher watcher) { - super(watcher); - } - - @Override - public void watch(GameEvent event, Game game) { - if (event.getType() == GameEvent.EventType.ZONE_CHANGE && cardIds.contains(event.getTargetId())) { - Card card = game.getCard(event.getTargetId()); - if (card != null) { - Iterator it = card.getAbilities().iterator(); - while (it.hasNext()) { - if (it.next() instanceof LifelinkAbility) { - it.remove(); - break; - } - } - cardIds.remove(event.getTargetId()); - } - } - } - - public void addCardId(UUID cardId) { - cardIds.add(cardId); - } - - @Override - public SoulfireGrandMasterLeavesStackWatcher copy() { - return new SoulfireGrandMasterLeavesStackWatcher(this); - } - -} - diff --git a/Mage.Sets/src/mage/sets/fifthdawn/GoblinBrawler.java b/Mage.Sets/src/mage/sets/fifthdawn/GoblinBrawler.java index 3dffc7e3c9e..13b1344e3da 100644 --- a/Mage.Sets/src/mage/sets/fifthdawn/GoblinBrawler.java +++ b/Mage.Sets/src/mage/sets/fifthdawn/GoblinBrawler.java @@ -32,6 +32,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; import mage.abilities.effects.ReplacementEffectImpl; import mage.abilities.keyword.FirstStrikeAbility; import mage.cards.CardImpl; @@ -75,7 +76,7 @@ public class GoblinBrawler extends CardImpl { } } -class CantBeEquippedSourceEffect extends ReplacementEffectImpl { +class CantBeEquippedSourceEffect extends ContinuousRuleModifyingEffectImpl { public CantBeEquippedSourceEffect(CantBeEquippedSourceEffect effect) { super(effect); @@ -92,18 +93,13 @@ class CantBeEquippedSourceEffect extends ReplacementEffectImpl { } @Override - public boolean apply(Game game, Ability source) { - return true; + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.ATTACH; } - - @Override - public boolean replaceEvent(GameEvent event, Ability source, Game game) { - return true; - } - + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == GameEvent.EventType.ATTACH && event.getTargetId().equals(source.getSourceId())) { + if (event.getTargetId().equals(source.getSourceId())) { Permanent permanent = game.getPermanent(event.getSourceId()); if(permanent != null && permanent.getSubtype().contains("Equipment")){ return true; diff --git a/Mage.Sets/src/mage/sets/fifthdawn/SilentArbiter.java b/Mage.Sets/src/mage/sets/fifthdawn/SilentArbiter.java new file mode 100644 index 00000000000..e5ede523d67 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fifthdawn/SilentArbiter.java @@ -0,0 +1,125 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.fifthdawn; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.RestrictionEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * + * @author emerald000 + */ +public class SilentArbiter extends CardImpl { + + public SilentArbiter(UUID ownerId) { + super(ownerId, 150, "Silent Arbiter", Rarity.RARE, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{4}"); + this.expansionSetCode = "5DN"; + this.subtype.add("Construct"); + this.power = new MageInt(1); + this.toughness = new MageInt(5); + + // No more than one creature can attack each combat. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SilentArbiterAttackRestrictionEffect())); + + // No more than one creature can block each combat. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SilentArbiterBlockRestrictionEffect())); + } + + public SilentArbiter(final SilentArbiter card) { + super(card); + } + + @Override + public SilentArbiter copy() { + return new SilentArbiter(this); + } +} + +class SilentArbiterAttackRestrictionEffect extends RestrictionEffect { + + SilentArbiterAttackRestrictionEffect() { + super(Duration.WhileOnBattlefield); + staticText = "No more than one creature can attack each combat"; + } + + SilentArbiterAttackRestrictionEffect(final SilentArbiterAttackRestrictionEffect effect) { + super(effect); + } + + @Override + public SilentArbiterAttackRestrictionEffect copy() { + return new SilentArbiterAttackRestrictionEffect(this); + } + + @Override + public boolean applies(Permanent permanent, Ability source, Game game) { + return true; + } + + @Override + public boolean canAttack(UUID defenderId, Ability source, Game game) { + return game.getCombat().getAttackers().isEmpty(); + } +} + +class SilentArbiterBlockRestrictionEffect extends RestrictionEffect { + + SilentArbiterBlockRestrictionEffect() { + super(Duration.WhileOnBattlefield); + staticText = "No more than one creature can block each combat"; + } + + SilentArbiterBlockRestrictionEffect(final SilentArbiterBlockRestrictionEffect effect) { + super(effect); + } + + @Override + public SilentArbiterBlockRestrictionEffect copy() { + return new SilentArbiterBlockRestrictionEffect(this); + } + + @Override + public boolean applies(Permanent permanent, Ability source, Game game) { + return true; + } + + @Override + public boolean canBlock(Permanent attacker, Permanent blocker, Ability source, Game game) { + return game.getCombat().getBlockers().isEmpty(); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/fifthdawn/SummonersEgg.java b/Mage.Sets/src/mage/sets/fifthdawn/SummonersEgg.java index 1fd2ea4f749..f0deeee1443 100644 --- a/Mage.Sets/src/mage/sets/fifthdawn/SummonersEgg.java +++ b/Mage.Sets/src/mage/sets/fifthdawn/SummonersEgg.java @@ -97,7 +97,7 @@ class SummonersEggImprintEffect extends OneShotEffect { && controller.choose(Outcome.Benefit, controller.getHand(), target, game)) { Card card = controller.getHand().get(target.getFirstTarget(), game); if (card != null) { - controller.moveCardToExileWithInfo(card, source.getSourceId(), sourcePermanent.getName() +" (Imprint)", source.getSourceId(), game, Zone.HAND, true); + controller.moveCardToExileWithInfo(card, source.getSourceId(), sourcePermanent.getIdName() +" (Imprint)", source.getSourceId(), game, Zone.HAND, true); card.setFaceDown(true, game); Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent != null) { diff --git a/Mage.Sets/src/mage/sets/fifthedition/BottomlessVault.java b/Mage.Sets/src/mage/sets/fifthedition/BottomlessVault.java new file mode 100644 index 00000000000..764ce6ab9c9 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fifthedition/BottomlessVault.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.fifthedition; + +import java.util.UUID; + +/** + * + * @author anonymous + */ +public class BottomlessVault extends mage.sets.fallenempires.BottomlessVault { + + public BottomlessVault(UUID ownerId) { + super(ownerId); + this.cardNumber = 411; + this.expansionSetCode = "5ED"; + } + + public BottomlessVault(final BottomlessVault card) { + super(card); + } + + @Override + public BottomlessVault copy() { + return new BottomlessVault(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fifthedition/DwarvenHold.java b/Mage.Sets/src/mage/sets/fifthedition/DwarvenHold.java new file mode 100644 index 00000000000..f7e8c8afd0f --- /dev/null +++ b/Mage.Sets/src/mage/sets/fifthedition/DwarvenHold.java @@ -0,0 +1,85 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.fifthedition; + +import java.util.UUID; +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.EntersBattlefieldTappedAbility; +import mage.abilities.common.SkipUntapOptionalAbility; +import mage.abilities.condition.common.SourceTappedCondition; +import mage.abilities.costs.common.RemoveVariableCountersSourceCost; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.dynamicvalue.common.RemovedCountersForCostValue; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.mana.DynamicManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.counters.CounterType; + +/** + * + * @author anonymous + */ +public class DwarvenHold extends CardImpl { + + public DwarvenHold(UUID ownerId) { + super(ownerId, 414, "Dwarven Hold", Rarity.RARE, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "5ED"; + + // Dwarven Hold enters the battlefield tapped. + this.addAbility(new EntersBattlefieldTappedAbility()); + // You may choose not to untap Dwarven Hold during your untap step. + this.addAbility(new SkipUntapOptionalAbility()); + // At the beginning of your upkeep, if Dwarven Hold is tapped, put a storage counter on it. + OneShotEffect addStorageCounter = new AddCountersSourceEffect(CounterType.STORAGE.createInstance()); + Effect effect = new ConditionalOneShotEffect(addStorageCounter, SourceTappedCondition.getInstance(), "if {this} is tapped, put a storage counter on it"); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, effect, TargetController.YOU, false)); + // {tap}, Remove any number of storage counters from Dwarven Hold: Add {R} to your mana pool for each storage counter removed this way. + Ability ability = new DynamicManaAbility(Mana.RedMana, new RemovedCountersForCostValue(), + "Add {R} to your mana pool for each storage counter removed this way"); + ability.addCost(new RemoveVariableCountersSourceCost( + CounterType.STORAGE.createInstance(), "Remove any number of storage counters from {this}")); + this.addAbility(ability); + } + + public DwarvenHold(final DwarvenHold card) { + super(card); + } + + @Override + public DwarvenHold copy() { + return new DwarvenHold(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fifthedition/HollowTrees.java b/Mage.Sets/src/mage/sets/fifthedition/HollowTrees.java new file mode 100644 index 00000000000..fb7c8abc47e --- /dev/null +++ b/Mage.Sets/src/mage/sets/fifthedition/HollowTrees.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.fifthedition; + +import java.util.UUID; + +/** + * + * @author anonymous + */ +public class HollowTrees extends mage.sets.fallenempires.HollowTrees { + + public HollowTrees(UUID ownerId) { + super(ownerId); + this.cardNumber = 422; + this.expansionSetCode = "5ED"; + } + + public HollowTrees(final HollowTrees card) { + super(card); + } + + @Override + public HollowTrees copy() { + return new HollowTrees(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fifthedition/IcatianStore.java b/Mage.Sets/src/mage/sets/fifthedition/IcatianStore.java new file mode 100644 index 00000000000..a7a9455453c --- /dev/null +++ b/Mage.Sets/src/mage/sets/fifthedition/IcatianStore.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.fifthedition; + +import java.util.UUID; + +/** + * + * @author anonymous + */ +public class IcatianStore extends mage.sets.fallenempires.IcatianStore { + + public IcatianStore(UUID ownerId) { + super(ownerId); + this.cardNumber = 423; + this.expansionSetCode = "5ED"; + } + + public IcatianStore(final IcatianStore card) { + super(card); + } + + @Override + public IcatianStore copy() { + return new IcatianStore(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fifthedition/Kismet.java b/Mage.Sets/src/mage/sets/fifthedition/Kismet.java index 3dfb9ed242a..9e327b22775 100644 --- a/Mage.Sets/src/mage/sets/fifthedition/Kismet.java +++ b/Mage.Sets/src/mage/sets/fifthedition/Kismet.java @@ -39,6 +39,7 @@ import mage.constants.Rarity; import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; import mage.game.permanent.Permanent; /** @@ -51,7 +52,6 @@ public class Kismet extends CardImpl { super(ownerId, 319, "Kismet", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT}, "{3}{W}"); this.expansionSetCode = "5ED"; - // Artifacts, creatures, and lands played by your opponents enter the battlefield tapped. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new KismetEffect())); } @@ -86,9 +86,15 @@ class KismetEffect extends ReplacementEffectImpl { return false; } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.ENTERS_THE_BATTLEFIELD; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD && game.getOpponents(source.getControllerId()).contains(event.getPlayerId())) { + if (game.getOpponents(source.getControllerId()).contains(event.getPlayerId())) { Permanent permanent = game.getPermanent(event.getTargetId()); if (permanent != null && (permanent.getCardType().contains(CardType.ARTIFACT) || permanent.getCardType().contains(CardType.CREATURE) || @@ -99,11 +105,6 @@ class KismetEffect extends ReplacementEffectImpl { return false; } - @Override - public boolean apply(Game game, Ability source) { - return false; - } - @Override public KismetEffect copy() { return new KismetEffect(this); diff --git a/Mage.Sets/src/mage/sets/fifthedition/ManaClash.java b/Mage.Sets/src/mage/sets/fifthedition/ManaClash.java new file mode 100644 index 00000000000..3dac56f688c --- /dev/null +++ b/Mage.Sets/src/mage/sets/fifthedition/ManaClash.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.fifthedition; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class ManaClash extends mage.sets.fourthedition.ManaClash { + + public ManaClash(UUID ownerId) { + super(ownerId); + this.cardNumber = 248; + this.expansionSetCode = "5ED"; + } + + public ManaClash(final ManaClash card) { + super(card); + } + + @Override + public ManaClash copy() { + return new ManaClash(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fifthedition/SandSilos.java b/Mage.Sets/src/mage/sets/fifthedition/SandSilos.java new file mode 100644 index 00000000000..7e8a942094e --- /dev/null +++ b/Mage.Sets/src/mage/sets/fifthedition/SandSilos.java @@ -0,0 +1,85 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.fifthedition; + +import java.util.UUID; +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.EntersBattlefieldTappedAbility; +import mage.abilities.common.SkipUntapOptionalAbility; +import mage.abilities.condition.common.SourceTappedCondition; +import mage.abilities.costs.common.RemoveVariableCountersSourceCost; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.dynamicvalue.common.RemovedCountersForCostValue; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.mana.DynamicManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.counters.CounterType; + +/** + * + * @author anonymous + */ +public class SandSilos extends CardImpl { + + public SandSilos(UUID ownerId) { + super(ownerId, 439, "Sand Silos", Rarity.RARE, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "5ED"; + + // Sand Silos enters the battlefield tapped. + this.addAbility(new EntersBattlefieldTappedAbility()); + // You may choose not to untap Sand Silos during your untap step. + this.addAbility(new SkipUntapOptionalAbility()); + // At the beginning of your upkeep, if Sand Silos is tapped, put a storage counter on it. + OneShotEffect addStorageCounter = new AddCountersSourceEffect(CounterType.STORAGE.createInstance()); + Effect effect = new ConditionalOneShotEffect(addStorageCounter, SourceTappedCondition.getInstance(), "if {this} is tapped, put a storage counter on it"); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, effect, TargetController.YOU, false)); + // {tap}, Remove any number of storage counters from Sand Silos: Add {U} to your mana pool for each storage counter removed this way. + Ability ability = new DynamicManaAbility(Mana.BlueMana, new RemovedCountersForCostValue(), + "Add {U} to your mana pool for each storage counter removed this way"); + ability.addCost(new RemoveVariableCountersSourceCost( + CounterType.STORAGE.createInstance(), "Remove any number of storage counters from {this}")); + this.addAbility(ability); + } + + public SandSilos(final SandSilos card) { + super(card); + } + + @Override + public SandSilos copy() { + return new SandSilos(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fourthedition/ManaClash.java b/Mage.Sets/src/mage/sets/fourthedition/ManaClash.java new file mode 100644 index 00000000000..3af50806837 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fourthedition/ManaClash.java @@ -0,0 +1,108 @@ +/* + * 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.fourthedition; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetOpponent; + +/** + * + * @author LevelX2 + */ +public class ManaClash extends CardImpl { + + public ManaClash(UUID ownerId) { + super(ownerId, 228, "Mana Clash", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{R}"); + this.expansionSetCode = "4ED"; + + // You and target opponent each flip a coin. Mana Clash deals 1 damage to each player whose coin comes up tails. Repeat this process until both players' coins come up heads on the same flip. + this.getSpellAbility().addEffect(new ManaClashEffect()); + this.getSpellAbility().addTarget(new TargetOpponent()); + } + + public ManaClash(final ManaClash card) { + super(card); + } + + @Override + public ManaClash copy() { + return new ManaClash(this); + } +} + +class ManaClashEffect extends OneShotEffect { + + public ManaClashEffect() { + super(Outcome.Detriment); + this.staticText = "You and target opponent each flip a coin. {this} deals 1 damage to each player whose coin comes up tails. Repeat this process until both players' coins come up heads on the same flip"; + } + + public ManaClashEffect(final ManaClashEffect effect) { + super(effect); + } + + @Override + public ManaClashEffect copy() { + return new ManaClashEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Player targetOpponent = game.getPlayer(getTargetPointer().getFirst(game, source)); + if (controller != null && targetOpponent != null) { + boolean bothHeads = false; + while (!bothHeads) { + if (!targetOpponent.isInGame() || !controller.isInGame()) { + return false; + } + boolean controllerFlip = controller.flipCoin(game); + boolean opponentFlip = targetOpponent.flipCoin(game); + if (controllerFlip && opponentFlip) { + bothHeads = true; + } + if (!controllerFlip) { + controller.damage(1, source.getSourceId(), game, false, true); + } + if (!opponentFlip) { + targetOpponent.damage(1, source.getSourceId(), game, false, true); + } + } + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/futuresight/AvenMindcensor.java b/Mage.Sets/src/mage/sets/futuresight/AvenMindcensor.java index d9e317a7052..bd967595537 100644 --- a/Mage.Sets/src/mage/sets/futuresight/AvenMindcensor.java +++ b/Mage.Sets/src/mage/sets/futuresight/AvenMindcensor.java @@ -95,19 +95,14 @@ class AvenMindcensorEffect extends ReplacementEffectImpl { } @Override - public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == GameEvent.EventType.SEARCH_LIBRARY) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null && game.isOpponent(controller, event.getPlayerId())) { - return true; - } - } - return false; + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.SEARCH_LIBRARY; } - + @Override - public boolean apply(Game game, Ability source) { - return false; + public boolean applies(GameEvent event, Ability source, Game game) { + Player controller = game.getPlayer(source.getControllerId()); + return controller != null && game.isOpponent(controller, event.getPlayerId()); } @Override diff --git a/Mage.Sets/src/mage/sets/futuresight/KeldonMegaliths.java b/Mage.Sets/src/mage/sets/futuresight/KeldonMegaliths.java new file mode 100644 index 00000000000..86a276194ff --- /dev/null +++ b/Mage.Sets/src/mage/sets/futuresight/KeldonMegaliths.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.futuresight; + +import java.util.UUID; + +/** + * + * @author anonymous + */ +public class KeldonMegaliths extends mage.sets.jacevschandra.KeldonMegaliths { + + public KeldonMegaliths(UUID ownerId) { + super(ownerId); + this.cardNumber = 170; + this.expansionSetCode = "FUT"; + } + + public KeldonMegaliths(final KeldonMegaliths card) { + super(card); + } + + @Override + public KeldonMegaliths copy() { + return new KeldonMegaliths(this); + } +} diff --git a/Mage.Sets/src/mage/sets/gatecrash/AlmsBeast.java b/Mage.Sets/src/mage/sets/gatecrash/AlmsBeast.java index 58aac5ecfb2..d5216ee0eac 100644 --- a/Mage.Sets/src/mage/sets/gatecrash/AlmsBeast.java +++ b/Mage.Sets/src/mage/sets/gatecrash/AlmsBeast.java @@ -60,7 +60,7 @@ public class AlmsBeast extends CardImpl { FilterCreaturePermanent filter = new FilterCreaturePermanent(); filter.add(Predicates.or(new BlockedByIdPredicate(this.getId()), new BlockingAttackerIdPredicate(this.getId()))); - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAllEffect(LifelinkAbility.getInstance(), Duration.EndOfCombat, filter, + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAllEffect(LifelinkAbility.getInstance(), Duration.WhileOnBattlefield, filter, "Creatures blocking or blocked by {this} have lifelink"))); } diff --git a/Mage.Sets/src/mage/sets/gatecrash/BlindObedience.java b/Mage.Sets/src/mage/sets/gatecrash/BlindObedience.java index 9051f4bc474..3bc36d45269 100644 --- a/Mage.Sets/src/mage/sets/gatecrash/BlindObedience.java +++ b/Mage.Sets/src/mage/sets/gatecrash/BlindObedience.java @@ -89,10 +89,15 @@ class BlindObedienceTapEffect extends ReplacementEffectImpl { } return false; } - + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD && game.getOpponents(source.getControllerId()).contains(event.getPlayerId())) { + if (game.getOpponents(source.getControllerId()).contains(event.getPlayerId())) { Permanent permanent = game.getPermanent(event.getTargetId()); if (permanent != null && (permanent.getCardType().contains(CardType.CREATURE) || permanent.getCardType().contains(CardType.ARTIFACT))) { return true; @@ -101,11 +106,6 @@ class BlindObedienceTapEffect extends ReplacementEffectImpl { return false; } - @Override - public boolean apply(Game game, Ability source) { - return false; - } - @Override public BlindObedienceTapEffect copy() { return new BlindObedienceTapEffect(this); diff --git a/Mage.Sets/src/mage/sets/gatecrash/MasterBiomancer.java b/Mage.Sets/src/mage/sets/gatecrash/MasterBiomancer.java index 5d967f7609d..eeb0b6346dd 100644 --- a/Mage.Sets/src/mage/sets/gatecrash/MasterBiomancer.java +++ b/Mage.Sets/src/mage/sets/gatecrash/MasterBiomancer.java @@ -86,23 +86,18 @@ class MasterBiomancerEntersBattlefieldEffect extends ReplacementEffectImpl { public MasterBiomancerEntersBattlefieldEffect(MasterBiomancerEntersBattlefieldEffect effect) { super(effect); } - + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.ENTERS_THE_BATTLEFIELD; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == EventType.ENTERS_THE_BATTLEFIELD) { - Permanent creature = game.getPermanent(event.getTargetId()); - if (creature != null && creature.getControllerId().equals(source.getControllerId()) - && creature.getCardType().contains(CardType.CREATURE) - && !event.getTargetId().equals(source.getSourceId())) { - return true; - } - } - return false; - } - - @Override - public boolean apply(Game game, Ability source) { - return false; + Permanent creature = game.getPermanent(event.getTargetId()); + return creature != null && creature.getControllerId().equals(source.getControllerId()) + && creature.getCardType().contains(CardType.CREATURE) + && !event.getTargetId().equals(source.getSourceId()); } @Override diff --git a/Mage.Sets/src/mage/sets/gatecrash/NightveilSpecter.java b/Mage.Sets/src/mage/sets/gatecrash/NightveilSpecter.java index 88f9aaca2ea..25086caf897 100644 --- a/Mage.Sets/src/mage/sets/gatecrash/NightveilSpecter.java +++ b/Mage.Sets/src/mage/sets/gatecrash/NightveilSpecter.java @@ -111,7 +111,7 @@ class NightveilSpecterExileEffect extends OneShotEffect { Card card = player.getLibrary().removeFromTop(game); MageObject sourceObject = game.getObject(source.getSourceId()); if (card != null && sourceObject != null) { - player.moveCardToExileWithInfo(card, CardUtil.getCardExileZoneId(game, source), sourceObject.getName(), source.getSourceId(), game, Zone.LIBRARY, true); + player.moveCardToExileWithInfo(card, CardUtil.getCardExileZoneId(game, source), sourceObject.getIdName(), source.getSourceId(), game, Zone.LIBRARY, true); return true; } } diff --git a/Mage.Sets/src/mage/sets/gatecrash/Skullcrack.java b/Mage.Sets/src/mage/sets/gatecrash/Skullcrack.java index d7303a90eb7..f541d990372 100644 --- a/Mage.Sets/src/mage/sets/gatecrash/Skullcrack.java +++ b/Mage.Sets/src/mage/sets/gatecrash/Skullcrack.java @@ -33,6 +33,7 @@ import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.Rarity; import mage.abilities.Ability; +import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; import mage.abilities.effects.ReplacementEffectImpl; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.continuous.CantGainLifeAllEffect; @@ -71,7 +72,7 @@ public class Skullcrack extends CardImpl { } } -class DamageCantBePreventedEffect extends ReplacementEffectImpl { +class DamageCantBePreventedEffect extends ContinuousRuleModifyingEffectImpl { public DamageCantBePreventedEffect() { super(Duration.EndOfTurn, Outcome.Benefit); @@ -91,17 +92,14 @@ class DamageCantBePreventedEffect extends ReplacementEffectImpl { public boolean apply(Game game, Ability source) { return true; } - + @Override - public boolean replaceEvent(GameEvent event, Ability source, Game game) { - return true; + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.PREVENT_DAMAGE; } - + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType().equals(GameEvent.EventType.PREVENT_DAMAGE)) { - return true; - } - return false; + return true; } } diff --git a/Mage.Sets/src/mage/sets/guildpact/GhostCouncilOfOrzhova.java b/Mage.Sets/src/mage/sets/guildpact/GhostCouncilOfOrzhova.java index 0682a27f865..6dc19286a3a 100644 --- a/Mage.Sets/src/mage/sets/guildpact/GhostCouncilOfOrzhova.java +++ b/Mage.Sets/src/mage/sets/guildpact/GhostCouncilOfOrzhova.java @@ -134,7 +134,7 @@ class GhostCouncilOfOrzhovaRemovingEffect extends OneShotEffect { if (controller != null) { Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent != null) { - if (controller.moveCardToExileWithInfo(permanent, source.getSourceId(), permanent.getName(), source.getSourceId(), game, Zone.BATTLEFIELD, true)) { + if (controller.moveCardToExileWithInfo(permanent, source.getSourceId(), permanent.getIdName(), source.getSourceId(), game, Zone.BATTLEFIELD, true)) { //create delayed triggered ability AtTheBeginOfNextEndStepDelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility( new ReturnFromExileEffect(source.getSourceId(), Zone.BATTLEFIELD)); diff --git a/Mage.Sets/src/mage/sets/guildpact/Ghostway.java b/Mage.Sets/src/mage/sets/guildpact/Ghostway.java index 55bc13ccd30..776e27e8ac7 100644 --- a/Mage.Sets/src/mage/sets/guildpact/Ghostway.java +++ b/Mage.Sets/src/mage/sets/guildpact/Ghostway.java @@ -98,7 +98,7 @@ class GhostwayEffect extends OneShotEffect { UUID exileId = CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter()); for (Permanent creature : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), game)) { if (creature != null) { - controller.moveCardToExileWithInfo(creature, exileId,sourceObject.getName(), source.getSourceId(), game, Zone.BATTLEFIELD, true); + controller.moveCardToExileWithInfo(creature, exileId,sourceObject.getIdName(), source.getSourceId(), game, Zone.BATTLEFIELD, true); numberCreatures++; } } diff --git a/Mage.Sets/src/mage/sets/heroesvsmonsters/SkarrganFirebird.java b/Mage.Sets/src/mage/sets/heroesvsmonsters/SkarrganFirebird.java index 029a6c6655d..9a170f2e022 100644 --- a/Mage.Sets/src/mage/sets/heroesvsmonsters/SkarrganFirebird.java +++ b/Mage.Sets/src/mage/sets/heroesvsmonsters/SkarrganFirebird.java @@ -88,7 +88,7 @@ class OpponentWasDealtDamageCondition implements Condition { @Override public boolean apply(Game game, Ability source) { BloodthirstWatcher watcher = (BloodthirstWatcher) game.getState().getWatchers().get("DamagedOpponents", source.getControllerId()); - return !watcher.conditionMet(); + return watcher.conditionMet(); } @Override diff --git a/Mage.Sets/src/mage/sets/homelands/AnHavvaTownship.java b/Mage.Sets/src/mage/sets/homelands/AnHavvaTownship.java new file mode 100644 index 00000000000..5a1919ced64 --- /dev/null +++ b/Mage.Sets/src/mage/sets/homelands/AnHavvaTownship.java @@ -0,0 +1,75 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.homelands; + +import java.util.UUID; +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.mana.ColorlessManaAbility; +import mage.abilities.mana.SimpleManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; + +/** + * + * @author anonymous + */ +public class AnHavvaTownship extends CardImpl { + + public AnHavvaTownship(UUID ownerId) { + super(ownerId, 136, "An-Havva Township", Rarity.UNCOMMON, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "HML"; + + // {tap}: Add {1} to your mana pool. + this.addAbility(new ColorlessManaAbility()); + // {1}, {tap}: Add {G} to your mana pool. + Ability ability = new SimpleManaAbility(Zone.BATTLEFIELD, Mana.GreenMana, new GenericManaCost(1)); + ability.addCost(new TapSourceCost()); + this.addAbility(ability); + // {2}, {tap}: Add {R} or {W} to your mana pool. + ability = new SimpleManaAbility(Zone.BATTLEFIELD, Mana.RedMana, new GenericManaCost(2)); + ability.addCost(new TapSourceCost()); + this.addAbility(ability); + ability = new SimpleManaAbility(Zone.BATTLEFIELD, Mana.WhiteMana, new GenericManaCost(2)); + ability.addCost(new TapSourceCost()); + this.addAbility(ability); + } + + public AnHavvaTownship(final AnHavvaTownship card) { + super(card); + } + + @Override + public AnHavvaTownship copy() { + return new AnHavvaTownship(this); + } +} diff --git a/Mage.Sets/src/mage/sets/homelands/AysenAbbey.java b/Mage.Sets/src/mage/sets/homelands/AysenAbbey.java new file mode 100644 index 00000000000..b8974e29087 --- /dev/null +++ b/Mage.Sets/src/mage/sets/homelands/AysenAbbey.java @@ -0,0 +1,75 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.homelands; + +import java.util.UUID; +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.mana.ColorlessManaAbility; +import mage.abilities.mana.SimpleManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; + +/** + * + * @author anonymous + */ +public class AysenAbbey extends CardImpl { + + public AysenAbbey(UUID ownerId) { + super(ownerId, 137, "Aysen Abbey", Rarity.UNCOMMON, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "HML"; + + // {tap}: Add {1} to your mana pool. + this.addAbility(new ColorlessManaAbility()); + // {1}, {tap}: Add {W} to your mana pool. + Ability ability = new SimpleManaAbility(Zone.BATTLEFIELD, Mana.WhiteMana, new GenericManaCost(1)); + ability.addCost(new TapSourceCost()); + this.addAbility(ability); + // {2}, {tap}: Add {G} or {U} to your mana pool. + ability = new SimpleManaAbility(Zone.BATTLEFIELD, Mana.GreenMana, new GenericManaCost(2)); + ability.addCost(new TapSourceCost()); + this.addAbility(ability); + ability = new SimpleManaAbility(Zone.BATTLEFIELD, Mana.BlueMana, new GenericManaCost(2)); + ability.addCost(new TapSourceCost()); + this.addAbility(ability); + } + + public AysenAbbey(final AysenAbbey card) { + super(card); + } + + @Override + public AysenAbbey copy() { + return new AysenAbbey(this); + } +} diff --git a/Mage.Sets/src/mage/sets/homelands/CastleSengir.java b/Mage.Sets/src/mage/sets/homelands/CastleSengir.java new file mode 100644 index 00000000000..091f4368d51 --- /dev/null +++ b/Mage.Sets/src/mage/sets/homelands/CastleSengir.java @@ -0,0 +1,75 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.homelands; + +import java.util.UUID; +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.mana.ColorlessManaAbility; +import mage.abilities.mana.SimpleManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; + +/** + * + * @author anonymous + */ +public class CastleSengir extends CardImpl { + + public CastleSengir(UUID ownerId) { + super(ownerId, 138, "Castle Sengir", Rarity.UNCOMMON, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "HML"; + + // {tap}: Add {1} to your mana pool. + this.addAbility(new ColorlessManaAbility()); + // {1}, {tap}: Add {B} to your mana pool. + Ability ability = new SimpleManaAbility(Zone.BATTLEFIELD, Mana.BlackMana, new GenericManaCost(1)); + ability.addCost(new TapSourceCost()); + this.addAbility(ability); + // {2}, {tap}: Add {U} or {R} to your mana pool. + ability = new SimpleManaAbility(Zone.BATTLEFIELD, Mana.BlueMana, new GenericManaCost(2)); + ability.addCost(new TapSourceCost()); + this.addAbility(ability); + ability = new SimpleManaAbility(Zone.BATTLEFIELD, Mana.RedMana, new GenericManaCost(2)); + ability.addCost(new TapSourceCost()); + this.addAbility(ability); + } + + public CastleSengir(final CastleSengir card) { + super(card); + } + + @Override + public CastleSengir copy() { + return new CastleSengir(this); + } +} diff --git a/Mage.Sets/src/mage/sets/homelands/KoskunKeep.java b/Mage.Sets/src/mage/sets/homelands/KoskunKeep.java new file mode 100644 index 00000000000..8764ad81b04 --- /dev/null +++ b/Mage.Sets/src/mage/sets/homelands/KoskunKeep.java @@ -0,0 +1,75 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.homelands; + +import java.util.UUID; +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.mana.ColorlessManaAbility; +import mage.abilities.mana.SimpleManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; + +/** + * + * @author anonymous + */ +public class KoskunKeep extends CardImpl { + + public KoskunKeep(UUID ownerId) { + super(ownerId, 139, "Koskun Keep", Rarity.UNCOMMON, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "HML"; + + // {tap}: Add {1} to your mana pool. + this.addAbility(new ColorlessManaAbility()); + // {1}, {tap}: Add {R} to your mana pool. + Ability ability = new SimpleManaAbility(Zone.BATTLEFIELD, Mana.RedMana, new GenericManaCost(1)); + ability.addCost(new TapSourceCost()); + this.addAbility(ability); + // {2}, {tap}: Add {B} or {G} to your mana pool. + ability = new SimpleManaAbility(Zone.BATTLEFIELD, Mana.BlackMana, new GenericManaCost(2)); + ability.addCost(new TapSourceCost()); + this.addAbility(ability); + ability = new SimpleManaAbility(Zone.BATTLEFIELD, Mana.GreenMana, new GenericManaCost(2)); + ability.addCost(new TapSourceCost()); + this.addAbility(ability); + } + + public KoskunKeep(final KoskunKeep card) { + super(card); + } + + @Override + public KoskunKeep copy() { + return new KoskunKeep(this); + } +} diff --git a/Mage.Sets/src/mage/sets/homelands/WizardsSchool.java b/Mage.Sets/src/mage/sets/homelands/WizardsSchool.java new file mode 100644 index 00000000000..e6907b2655b --- /dev/null +++ b/Mage.Sets/src/mage/sets/homelands/WizardsSchool.java @@ -0,0 +1,75 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.homelands; + +import java.util.UUID; +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.mana.ColorlessManaAbility; +import mage.abilities.mana.SimpleManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; + +/** + * + * @author anonymous + */ +public class WizardsSchool extends CardImpl { + + public WizardsSchool(UUID ownerId) { + super(ownerId, 140, "Wizards' School", Rarity.UNCOMMON, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "HML"; + + // {tap}: Add {1} to your mana pool. + this.addAbility(new ColorlessManaAbility()); + // {1}, {tap}: Add {U} to your mana pool. + Ability ability = new SimpleManaAbility(Zone.BATTLEFIELD, Mana.BlueMana, new GenericManaCost(1)); + ability.addCost(new TapSourceCost()); + this.addAbility(ability); + // {2}, {tap}: Add {W} or {B} to your mana pool. + ability = new SimpleManaAbility(Zone.BATTLEFIELD, Mana.WhiteMana, new GenericManaCost(2)); + ability.addCost(new TapSourceCost()); + this.addAbility(ability); + ability = new SimpleManaAbility(Zone.BATTLEFIELD, Mana.BlackMana, new GenericManaCost(2)); + ability.addCost(new TapSourceCost()); + this.addAbility(ability); + } + + public WizardsSchool(final WizardsSchool card) { + super(card); + } + + @Override + public WizardsSchool copy() { + return new WizardsSchool(this); + } +} diff --git a/Mage.Sets/src/mage/sets/iceage/KjeldoranRoyalGuard.java b/Mage.Sets/src/mage/sets/iceage/KjeldoranRoyalGuard.java index 3ef0d4d97d9..ee7134946b0 100644 --- a/Mage.Sets/src/mage/sets/iceage/KjeldoranRoyalGuard.java +++ b/Mage.Sets/src/mage/sets/iceage/KjeldoranRoyalGuard.java @@ -103,11 +103,15 @@ class KjeldoranRoyalGuardEffect extends ReplacementEffectImpl { } return true; } - + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DAMAGE_PLAYER; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == GameEvent.EventType.DAMAGE_PLAYER - && event.getPlayerId().equals(source.getControllerId()) + if (event.getPlayerId().equals(source.getControllerId()) && ((DamageEvent)event).isCombatDamage()) { Permanent p = game.getPermanent(source.getSourceId()); if (p != null) { @@ -121,11 +125,6 @@ class KjeldoranRoyalGuardEffect extends ReplacementEffectImpl { return false; } - @Override - public boolean apply(Game game, Ability source) { - return true; - } - @Override public KjeldoranRoyalGuardEffect copy() { return new KjeldoranRoyalGuardEffect(this); diff --git a/Mage.Sets/src/mage/sets/iceage/LandCap.java b/Mage.Sets/src/mage/sets/iceage/LandCap.java new file mode 100644 index 00000000000..ebb3dcb35f5 --- /dev/null +++ b/Mage.Sets/src/mage/sets/iceage/LandCap.java @@ -0,0 +1,87 @@ +/* + * 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.iceage; + +import java.util.UUID; +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.SourceHasCounterCondition; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.decorator.ConditionalContinuousRuleModifyingEffect; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.DontUntapInControllersUntapStepSourceEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.effects.common.counter.RemoveCounterSourceEffect; +import mage.abilities.mana.SimpleManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.counters.CounterType; + +/** + * + * @author anonymous + */ +public class LandCap extends CardImpl { + + public LandCap(UUID ownerId) { + super(ownerId, 319, "Land Cap", Rarity.RARE, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "ICE"; + + // Land Cap doesn't untap during your untap step if it has a depletion counter on it. + Effect effect = new ConditionalContinuousRuleModifyingEffect(new DontUntapInControllersUntapStepSourceEffect(), + new SourceHasCounterCondition(CounterType.DEPLETION, 0)); + effect.setText("{this} doesn't untap during your untap step if it has a depletion counter on it"); + Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, effect); + this.addAbility(ability); + // At the beginning of your upkeep, remove a depletion counter from Land Cap. + Ability ability2 = new BeginningOfUpkeepTriggeredAbility(new RemoveCounterSourceEffect(CounterType.DEPLETION.createInstance()), TargetController.YOU, false); + this.addAbility(ability2); + // {tap}: Add {W} or {U} to your mana pool. Put a depletion counter on Land Cap. + Ability ability3 = new SimpleManaAbility(Zone.BATTLEFIELD, Mana.WhiteMana, new TapSourceCost()); + ability3.addEffect(new AddCountersSourceEffect(CounterType.DEPLETION.createInstance())); + this.addAbility(ability3); + Ability ability4 = new SimpleManaAbility(Zone.BATTLEFIELD, Mana.BlueMana, new TapSourceCost()); + ability4.addEffect(new AddCountersSourceEffect(CounterType.DEPLETION.createInstance())); + this.addAbility(ability4); + } + + public LandCap(final LandCap card) { + super(card); + } + + @Override + public LandCap copy() { + return new LandCap(this); + } +} diff --git a/Mage.Sets/src/mage/sets/iceage/LavaTubes.java b/Mage.Sets/src/mage/sets/iceage/LavaTubes.java new file mode 100644 index 00000000000..26cd59dc92f --- /dev/null +++ b/Mage.Sets/src/mage/sets/iceage/LavaTubes.java @@ -0,0 +1,86 @@ +/* + * 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.iceage; + +import java.util.UUID; +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.SourceHasCounterCondition; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.decorator.ConditionalContinuousRuleModifyingEffect; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.DontUntapInControllersUntapStepSourceEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.effects.common.counter.RemoveCounterSourceEffect; +import mage.abilities.mana.SimpleManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.counters.CounterType; + +/** + * + * @author anonymous + */ +public class LavaTubes extends CardImpl { + + public LavaTubes(UUID ownerId) { + super(ownerId, 339, "Lava Tubes", Rarity.RARE, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "ICE"; + + // Lava Tubes doesn't untap during your untap step if it has a depletion counter on it. + Effect effect = new ConditionalContinuousRuleModifyingEffect(new DontUntapInControllersUntapStepSourceEffect(), + new SourceHasCounterCondition(CounterType.DEPLETION, 0)); + effect.setText("{this} doesn't untap during your untap step if it has a depletion counter on it"); + Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, effect); + this.addAbility(ability); + // At the beginning of your upkeep, remove a depletion counter from Lava Tubes. + Ability ability2 = new BeginningOfUpkeepTriggeredAbility(new RemoveCounterSourceEffect(CounterType.DEPLETION.createInstance()), TargetController.YOU, false); + this.addAbility(ability2); + // {tap}: Add {B} or {R} to your mana pool. Put a depletion counter on Lava Tubes. + Ability ability3 = new SimpleManaAbility(Zone.BATTLEFIELD, Mana.BlackMana, new TapSourceCost()); + ability3.addEffect(new AddCountersSourceEffect(CounterType.DEPLETION.createInstance())); + this.addAbility(ability3); + Ability ability4 = new SimpleManaAbility(Zone.BATTLEFIELD, Mana.RedMana, new TapSourceCost()); + ability4.addEffect(new AddCountersSourceEffect(CounterType.DEPLETION.createInstance())); + this.addAbility(ability4); + } + + public LavaTubes(final LavaTubes card) { + super(card); + } + + @Override + public LavaTubes copy() { + return new LavaTubes(this); + } +} diff --git a/Mage.Sets/src/mage/sets/iceage/MysticRemora.java b/Mage.Sets/src/mage/sets/iceage/MysticRemora.java new file mode 100644 index 00000000000..4d9f6ae3efb --- /dev/null +++ b/Mage.Sets/src/mage/sets/iceage/MysticRemora.java @@ -0,0 +1,162 @@ +/* + * 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.iceage; + +import java.util.UUID; +import mage.MageObject; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.keyword.CumulativeUpkeepAbility; +import mage.game.stack.Spell; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.costs.Cost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.OneShotEffect; +import mage.cards.CardImpl; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.players.Player; +import mage.target.targetpointer.FixedTarget; + + +/** + * + * @author TGower + */ +public class MysticRemora extends CardImpl { + + public MysticRemora(UUID ownerId) { + super(ownerId, 87, "Mystic Remora", Rarity.COMMON, new CardType[]{CardType.ENCHANTMENT}, "{U}"); + this.expansionSetCode = "ICE"; + + // Cumulative upkeep {1} + this.addAbility(new CumulativeUpkeepAbility(new ManaCostsImpl("{1}"))); + // Whenever an opponent casts a noncreature spell, you may draw a card unless that player pays {4}. + this.addAbility(new MysticRemoraTriggeredAbility()); + + } + + public MysticRemora(final MysticRemora card) { + super(card); + } + + @Override + public MysticRemora copy() { + return new MysticRemora(this); + } +} + +class MysticRemoraTriggeredAbility extends TriggeredAbilityImpl { + + + public MysticRemoraTriggeredAbility() { + super(Zone.BATTLEFIELD, new MysticRemoraEffect(), false); + + } + + public MysticRemoraTriggeredAbility(final MysticRemoraTriggeredAbility ability) { + super(ability); + } + + @Override + public MysticRemoraTriggeredAbility copy() { + return new MysticRemoraTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.SPELL_CAST; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (game.getOpponents(controllerId).contains(event.getPlayerId())) { + if (event.getType() == GameEvent.EventType.SPELL_CAST) { + Spell spell = game.getStack().getSpell(event.getTargetId()); + if (spell != null && !spell.getCardType().contains(CardType.CREATURE)) { + Player controller = game.getPlayer(game.getControllerId(this.controllerId)); + Player player = game.getPlayer(spell.getControllerId()); + if (controller != player) { + this.getEffects().get(0).setTargetPointer(new FixedTarget(event.getPlayerId())); + } + return true; + } + } + } + return false; + } + + @Override + public String getRule() { + return "Whenever an opponent casts a noncreature spell, you may draw a card unless that player pays {4}."; + } +} + + class MysticRemoraEffect extends OneShotEffect { + + public MysticRemoraEffect() { + super(Outcome.DrawCard); + this.staticText = "you may draw a card unless that player pays {4}"; + } + + public MysticRemoraEffect(final MysticRemoraEffect effect) { + super(effect); + } + + @Override + public MysticRemoraEffect copy() { + return new MysticRemoraEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Player opponent = game.getPlayer(targetPointer.getFirst(game, source)); + MageObject sourceObject = source.getSourceObject(game); + if (controller != null && opponent != null && sourceObject != null) { + Cost cost = new GenericManaCost(4); + String message = "Would you like to pay {4} to prevent the opponent to draw a card?"; + if (!(opponent.chooseUse(Outcome.Benefit, message, game) && cost.pay(source, game, source.getSourceId(), opponent.getId(), false))) { + if(controller.chooseUse(Outcome.DrawCard, "Draw a card (" + sourceObject.getLogName() +")", game)) { + controller.drawCards(1, game); + } + } + return true; + } + return false; + } + +} + + + + diff --git a/Mage.Sets/src/mage/sets/iceage/RiverDelta.java b/Mage.Sets/src/mage/sets/iceage/RiverDelta.java new file mode 100644 index 00000000000..b5f91fff064 --- /dev/null +++ b/Mage.Sets/src/mage/sets/iceage/RiverDelta.java @@ -0,0 +1,87 @@ +/* + * 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.iceage; + +import java.util.UUID; +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.SourceHasCounterCondition; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.decorator.ConditionalContinuousRuleModifyingEffect; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.DontUntapInControllersUntapStepSourceEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.effects.common.counter.RemoveCounterSourceEffect; +import mage.abilities.mana.SimpleManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.counters.CounterType; + +/** + * + * @author anonymous + */ +public class RiverDelta extends CardImpl { + + public RiverDelta(UUID ownerId) { + super(ownerId, 346, "River Delta", Rarity.RARE, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "ICE"; + + // River Delta doesn't untap during your untap step if it has a depletion counter on it. + Effect effect = new ConditionalContinuousRuleModifyingEffect(new DontUntapInControllersUntapStepSourceEffect(), + new SourceHasCounterCondition(CounterType.DEPLETION, 0)); + effect.setText("{this} doesn't untap during your untap step if it has a depletion counter on it"); + Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, effect); + this.addAbility(ability); + // At the beginning of your upkeep, remove a depletion counter from River Delta. + Ability ability2 = new BeginningOfUpkeepTriggeredAbility(new RemoveCounterSourceEffect(CounterType.DEPLETION.createInstance()), TargetController.YOU, false); + this.addAbility(ability2); + // {tap}: Add {U} or {B} to your mana pool. Put a depletion counter on River Delta. + Ability ability3 = new SimpleManaAbility(Zone.BATTLEFIELD, Mana.BlueMana, new TapSourceCost()); + ability3.addEffect(new AddCountersSourceEffect(CounterType.DEPLETION.createInstance())); + this.addAbility(ability3); + Ability ability4 = new SimpleManaAbility(Zone.BATTLEFIELD, Mana.BlackMana, new TapSourceCost()); + ability4.addEffect(new AddCountersSourceEffect(CounterType.DEPLETION.createInstance())); + this.addAbility(ability4); + } + + public RiverDelta(final RiverDelta card) { + super(card); + } + + @Override + public RiverDelta copy() { + return new RiverDelta(this); + } +} diff --git a/Mage.Sets/src/mage/sets/iceage/TimberlineRidge.java b/Mage.Sets/src/mage/sets/iceage/TimberlineRidge.java new file mode 100644 index 00000000000..56a826a8e0a --- /dev/null +++ b/Mage.Sets/src/mage/sets/iceage/TimberlineRidge.java @@ -0,0 +1,86 @@ +/* + * 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.iceage; + +import java.util.UUID; +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.SourceHasCounterCondition; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.decorator.ConditionalContinuousRuleModifyingEffect; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.DontUntapInControllersUntapStepSourceEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.effects.common.counter.RemoveCounterSourceEffect; +import mage.abilities.mana.SimpleManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.counters.CounterType; + +/** + * + * @author anonymous + */ +public class TimberlineRidge extends CardImpl { + + public TimberlineRidge(UUID ownerId) { + super(ownerId, 356, "Timberline Ridge", Rarity.RARE, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "ICE"; + + // Timberline Ridge doesn't untap during your untap step if it has a depletion counter on it. + Effect effect = new ConditionalContinuousRuleModifyingEffect(new DontUntapInControllersUntapStepSourceEffect(), + new SourceHasCounterCondition(CounterType.DEPLETION, 0)); + effect.setText("{this} doesn't untap during your untap step if it has a depletion counter on it"); + Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, effect); + this.addAbility(ability); + // At the beginning of your upkeep, remove a depletion counter from Timberline Ridge. + Ability ability2 = new BeginningOfUpkeepTriggeredAbility(new RemoveCounterSourceEffect(CounterType.DEPLETION.createInstance()), TargetController.YOU, false); + this.addAbility(ability2); + // {tap}: Add {R} or {G} to your mana pool. Put a depletion counter on Timberline Ridge. + Ability ability3 = new SimpleManaAbility(Zone.BATTLEFIELD, Mana.RedMana, new TapSourceCost()); + ability3.addEffect(new AddCountersSourceEffect(CounterType.DEPLETION.createInstance())); + this.addAbility(ability3); + Ability ability4 = new SimpleManaAbility(Zone.BATTLEFIELD, Mana.GreenMana, new TapSourceCost()); + ability4.addEffect(new AddCountersSourceEffect(CounterType.DEPLETION.createInstance())); + this.addAbility(ability4); + } + + public TimberlineRidge(final TimberlineRidge card) { + super(card); + } + + @Override + public TimberlineRidge copy() { + return new TimberlineRidge(this); + } +} diff --git a/Mage.Sets/src/mage/sets/iceage/Veldt.java b/Mage.Sets/src/mage/sets/iceage/Veldt.java new file mode 100644 index 00000000000..437370080e8 --- /dev/null +++ b/Mage.Sets/src/mage/sets/iceage/Veldt.java @@ -0,0 +1,86 @@ +/* + * 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.iceage; + +import java.util.UUID; +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.SourceHasCounterCondition; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.decorator.ConditionalContinuousRuleModifyingEffect; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.DontUntapInControllersUntapStepSourceEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.effects.common.counter.RemoveCounterSourceEffect; +import mage.abilities.mana.SimpleManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.counters.CounterType; + +/** + * + * @author anonymous + */ +public class Veldt extends CardImpl { + + public Veldt(UUID ownerId) { + super(ownerId, 358, "Veldt", Rarity.RARE, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "ICE"; + + // Veldt doesn't untap during your untap step if it has a depletion counter on it. + Effect effect = new ConditionalContinuousRuleModifyingEffect(new DontUntapInControllersUntapStepSourceEffect(), + new SourceHasCounterCondition(CounterType.DEPLETION, 0)); + effect.setText("{this} doesn't untap during your untap step if it has a depletion counter on it"); + Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, effect); + this.addAbility(ability); + // At the beginning of your upkeep, remove a depletion counter from Veldt. + Ability ability2 = new BeginningOfUpkeepTriggeredAbility(new RemoveCounterSourceEffect(CounterType.DEPLETION.createInstance()), TargetController.YOU, false); + this.addAbility(ability2); + // {tap}: Add {G} or {W} to your mana pool. Put a depletion counter on Veldt. + Ability ability3 = new SimpleManaAbility(Zone.BATTLEFIELD, Mana.GreenMana, new TapSourceCost()); + ability3.addEffect(new AddCountersSourceEffect(CounterType.DEPLETION.createInstance())); + this.addAbility(ability3); + Ability ability4 = new SimpleManaAbility(Zone.BATTLEFIELD, Mana.WhiteMana, new TapSourceCost()); + ability4.addEffect(new AddCountersSourceEffect(CounterType.DEPLETION.createInstance())); + this.addAbility(ability4); + } + + public Veldt(final Veldt card) { + super(card); + } + + @Override + public Veldt copy() { + return new Veldt(this); + } +} diff --git a/Mage.Sets/src/mage/sets/innistrad/DearlyDeparted.java b/Mage.Sets/src/mage/sets/innistrad/DearlyDeparted.java index 4a3a953c42c..4a1345a52c9 100644 --- a/Mage.Sets/src/mage/sets/innistrad/DearlyDeparted.java +++ b/Mage.Sets/src/mage/sets/innistrad/DearlyDeparted.java @@ -51,13 +51,14 @@ import mage.game.stack.Spell; import mage.target.targetpointer.FixedTarget; import java.util.UUID; +import mage.game.events.GameEvent.EventType; /** * @author nantuko */ public class DearlyDeparted extends CardImpl { - private static final String ruleText = "As long as Dearly Departed is in your graveyard, each Human creature you control enters the battlefield with an additional +1/+1 counter on it"; + private static final String ruleText = "As long as {this} is in your graveyard, each Human creature you control enters the battlefield with an additional +1/+1 counter on it"; public DearlyDeparted(UUID ownerId) { super(ownerId, 9, "Dearly Departed", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{4}{W}{W}"); @@ -110,24 +111,22 @@ class EntersBattlefieldEffect extends ReplacementEffectImpl { public void addEffect(Effect effect) { baseEffects.add(effect); } - + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.ENTERS_THE_BATTLEFIELD; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD) { - Permanent permanent = game.getPermanent(event.getTargetId()); - if (permanent != null && permanent.getControllerId().equals(source.getControllerId()) && permanent.hasSubtype("Human")) { - setValue("target", permanent); - return true; - } + Permanent permanent = game.getPermanent(event.getTargetId()); + if (permanent != null && permanent.getControllerId().equals(source.getControllerId()) && permanent.hasSubtype("Human")) { + setValue("target", permanent); + return true; } return false; } - @Override - public boolean apply(Game game, Ability source) { - return false; - } - @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { Spell spell = game.getStack().getSpell(event.getSourceId()); diff --git a/Mage.Sets/src/mage/sets/innistrad/EssenceOfTheWild.java b/Mage.Sets/src/mage/sets/innistrad/EssenceOfTheWild.java index 8633a1bab21..90844048974 100644 --- a/Mage.Sets/src/mage/sets/innistrad/EssenceOfTheWild.java +++ b/Mage.Sets/src/mage/sets/innistrad/EssenceOfTheWild.java @@ -86,21 +86,16 @@ class EssenceOfTheWildEffect extends ReplacementEffectImpl { } @Override - public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == EventType.ENTERS_THE_BATTLEFIELD) { - Permanent perm = game.getPermanent(event.getTargetId()); - if (perm != null && perm.getCardType().contains(CardType.CREATURE) && perm.getControllerId().equals(source.getControllerId())) { - return true; - } - } - return false; + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.ENTERS_THE_BATTLEFIELD; } - + @Override - public boolean apply(Game game, Ability source) { - return false; + public boolean applies(GameEvent event, Ability source, Game game) { + Permanent perm = game.getPermanent(event.getTargetId()); + return perm != null && perm.getCardType().contains(CardType.CREATURE) && perm.getControllerId().equals(source.getControllerId()); } - + @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { Permanent perm = game.getPermanent(source.getSourceId()); @@ -122,8 +117,8 @@ class EssenceOfTheWildEffect extends ReplacementEffectImpl { class EssenceOfTheWildCopyEffect extends ContinuousEffectImpl { - private Permanent essence; - private UUID targetId; + private final Permanent essence; + private final UUID targetId; public EssenceOfTheWildCopyEffect(Permanent essence, UUID targetId) { super(Duration.EndOfGame, Layer.CopyEffects_1, SubLayer.NA, Outcome.BecomeCreature); diff --git a/Mage.Sets/src/mage/sets/invasion/ArmadilloCloak.java b/Mage.Sets/src/mage/sets/invasion/ArmadilloCloak.java index c517f2bb141..87596dd3e25 100644 --- a/Mage.Sets/src/mage/sets/invasion/ArmadilloCloak.java +++ b/Mage.Sets/src/mage/sets/invasion/ArmadilloCloak.java @@ -29,11 +29,12 @@ package mage.sets.invasion; import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.DealsDamageAttachedTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.dynamicvalue.common.NumericSetToEffectValues; import mage.abilities.effects.Effect; -import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.continuous.BoostEnchantedEffect; import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; import mage.abilities.keyword.EnchantAbility; @@ -45,10 +46,6 @@ import mage.constants.Duration; import mage.constants.Outcome; import mage.constants.Rarity; import mage.constants.Zone; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.permanent.Permanent; -import mage.players.Player; import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; @@ -63,7 +60,6 @@ public class ArmadilloCloak extends CardImpl { this.expansionSetCode = "INV"; this.subtype.add("Aura"); - // Enchant creature TargetPermanent auraTarget = new TargetCreaturePermanent(); this.getSpellAbility().addTarget(auraTarget); @@ -72,11 +68,14 @@ public class ArmadilloCloak extends CardImpl { this.addAbility(ability); // Enchanted creature gets +2/+2 and has trample. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEnchantedEffect(2, 2, Duration.WhileOnBattlefield))); - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(TrampleAbility.getInstance(), AttachmentType.AURA))); + ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEnchantedEffect(2, 2, Duration.WhileOnBattlefield)); + Effect effect = new GainAbilityAttachedEffect(TrampleAbility.getInstance(), AttachmentType.AURA); + effect.setText("and has trample"); + ability.addEffect(effect); + this.addAbility(ability); // Whenever enchanted creature deals damage, you gain that much life. - this.addAbility(new ArmadilloCloakTriggeredAbility()); + this.addAbility(new DealsDamageAttachedTriggeredAbility(Zone.BATTLEFIELD, new GainLifeEffect(new NumericSetToEffectValues("that much", "damage")), false)); } @@ -89,74 +88,3 @@ public class ArmadilloCloak extends CardImpl { return new ArmadilloCloak(this); } } - -class ArmadilloCloakTriggeredAbility extends TriggeredAbilityImpl { - - public ArmadilloCloakTriggeredAbility() { - super(Zone.BATTLEFIELD, new ArmadilloCloakEffect(), false); - } - - public ArmadilloCloakTriggeredAbility(final ArmadilloCloakTriggeredAbility ability) { - super(ability); - } - - @Override - public ArmadilloCloakTriggeredAbility copy() { - return new ArmadilloCloakTriggeredAbility(this); - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (event.getType().equals(GameEvent.EventType.DAMAGED_CREATURE) - || event.getType().equals(GameEvent.EventType.DAMAGED_PLAYER) - || event.getType().equals(GameEvent.EventType.DAMAGED_PLANESWALKER)) { - Permanent enchantment = game.getPermanent(this.getSourceId()); - if (enchantment == null || enchantment.getAttachedTo() == null) { - return false; - } - Permanent enchanted = game.getPermanent(enchantment.getAttachedTo()); - if (enchanted != null && event.getSourceId().equals(enchanted.getId())) { - for (Effect effect : this.getEffects()) { - effect.setValue("damage", event.getAmount()); - } - return true; - } - } - return false; - } - - @Override - public String getRule() { - return "Whenever enchanted creature deals damage, " + super.getRule(); - } -} - -class ArmadilloCloakEffect extends OneShotEffect { - - public ArmadilloCloakEffect() { - super(Outcome.GainLife); - this.staticText = "you gain that much life"; - } - - public ArmadilloCloakEffect(final ArmadilloCloakEffect effect) { - super(effect); - } - - @Override - public ArmadilloCloakEffect copy() { - return new ArmadilloCloakEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - int amount = (Integer) getValue("damage"); - if (amount > 0) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - controller.gainLife(amount, game); - return true; - } - } - return false; - } -} diff --git a/Mage.Sets/src/mage/sets/invasion/TsabosWeb.java b/Mage.Sets/src/mage/sets/invasion/TsabosWeb.java index d83a3216f99..6c97c4cfc66 100644 --- a/Mage.Sets/src/mage/sets/invasion/TsabosWeb.java +++ b/Mage.Sets/src/mage/sets/invasion/TsabosWeb.java @@ -33,6 +33,7 @@ import mage.abilities.ActivatedAbility; import mage.abilities.PlayLandAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; import mage.abilities.effects.ReplacementEffectImpl; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.mana.ManaAbility; @@ -61,7 +62,6 @@ public class TsabosWeb extends CardImpl { this.addAbility(new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1), false)); // Each land with an activated ability that isn't a mana ability doesn't untap during its controller's untap step. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new TsabosWebPreventUntapEffect())); - } public TsabosWeb(final TsabosWeb card) { @@ -74,7 +74,7 @@ public class TsabosWeb extends CardImpl { } } -class TsabosWebPreventUntapEffect extends ReplacementEffectImpl { +class TsabosWebPreventUntapEffect extends ContinuousRuleModifyingEffectImpl { public TsabosWebPreventUntapEffect() { super(Duration.WhileOnBattlefield, Outcome.Detriment); @@ -85,24 +85,19 @@ class TsabosWebPreventUntapEffect extends ReplacementEffectImpl { super(effect); } - @Override - public boolean apply(Game game, Ability source) { - return true; - } - @Override public TsabosWebPreventUntapEffect copy() { return new TsabosWebPreventUntapEffect(this); } @Override - public boolean replaceEvent(GameEvent event, Ability source, Game game) { - return true; + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.UNTAP; } - + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (game.getTurn().getStepType() == PhaseStep.UNTAP && event.getType() == GameEvent.EventType.UNTAP) { + if (game.getTurn().getStepType() == PhaseStep.UNTAP) { Permanent permanent = game.getPermanent(event.getTargetId()); if (permanent != null && permanent.getCardType().contains(CardType.LAND)) { for (Ability ability :permanent.getAbilities()) { diff --git a/Mage.Sets/src/mage/sets/invasion/YawgmothsAgenda.java b/Mage.Sets/src/mage/sets/invasion/YawgmothsAgenda.java index cc6b266c700..94605a43478 100644 --- a/Mage.Sets/src/mage/sets/invasion/YawgmothsAgenda.java +++ b/Mage.Sets/src/mage/sets/invasion/YawgmothsAgenda.java @@ -61,7 +61,6 @@ public class YawgmothsAgenda extends CardImpl { super(ownerId, 135, "Yawgmoth's Agenda", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{3}{B}{B}"); this.expansionSetCode = "INV"; - // You can't cast more than one spell each turn. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantCastMoreThanOneSpellEffect(TargetController.YOU))); // You may play cards from your graveyard. @@ -134,11 +133,6 @@ class YawgmothsAgendaReplacementEffect extends ReplacementEffectImpl { return new YawgmothsAgendaReplacementEffect(this); } - @Override - public boolean apply(Game game, Ability source) { - return true; - } - @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { Player controller = game.getPlayer(source.getControllerId()); @@ -159,9 +153,14 @@ class YawgmothsAgendaReplacementEffect extends ReplacementEffectImpl { return true; } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.ZONE_CHANGE; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == EventType.ZONE_CHANGE && ((ZoneChangeEvent) event).getToZone() == Zone.GRAVEYARD) { + if (((ZoneChangeEvent) event).getToZone() == Zone.GRAVEYARD) { Card card = game.getCard(event.getTargetId()); if (card != null && card.getOwnerId().equals(source.getControllerId())) { Permanent permanent = ((ZoneChangeEvent) event).getTarget(); diff --git a/Mage.Sets/src/mage/sets/izzetvsgolgari/SvogthosTheRestlessTomb.java b/Mage.Sets/src/mage/sets/izzetvsgolgari/SvogthosTheRestlessTomb.java new file mode 100644 index 00000000000..77bc7c0abd6 --- /dev/null +++ b/Mage.Sets/src/mage/sets/izzetvsgolgari/SvogthosTheRestlessTomb.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.izzetvsgolgari; + +import java.util.UUID; + +/** + * + * @author anonymous + */ +public class SvogthosTheRestlessTomb extends mage.sets.commander.SvogthosTheRestlessTomb { + + public SvogthosTheRestlessTomb(UUID ownerId) { + super(ownerId); + this.cardNumber = 81; + this.expansionSetCode = "DDJ"; + } + + public SvogthosTheRestlessTomb(final SvogthosTheRestlessTomb card) { + super(card); + } + + @Override + public SvogthosTheRestlessTomb copy() { + return new SvogthosTheRestlessTomb(this); + } +} diff --git a/Mage.Sets/src/mage/sets/jacevschandra/KeldonMegaliths.java b/Mage.Sets/src/mage/sets/jacevschandra/KeldonMegaliths.java new file mode 100644 index 00000000000..c1ffdf3b879 --- /dev/null +++ b/Mage.Sets/src/mage/sets/jacevschandra/KeldonMegaliths.java @@ -0,0 +1,73 @@ +/* + * 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.jacevschandra; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTappedAbility; +import mage.abilities.condition.common.HellbentCondition; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.mana.RedManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.target.common.TargetCreatureOrPlayer; + +/** + * + * @author anonymous + */ +public class KeldonMegaliths extends CardImpl { + + public KeldonMegaliths(UUID ownerId) { + super(ownerId, 58, "Keldon Megaliths", Rarity.UNCOMMON, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "DD2"; + + // Keldon Megaliths enters the battlefield tapped. + this.addAbility(new EntersBattlefieldTappedAbility()); + // {tap}: Add {R} to your mana pool. + this.addAbility(new RedManaAbility()); + // Hellbent - {1}{R}, {tap}: Keldon Megaliths deals 1 damage to target creature or player. Activate this ability only if you have no cards in hand. + Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(1), new ManaCostsImpl<>("{1}{R}"), HellbentCondition.getInstance(), + "Hellbent - {1}{R}, {tap}: {this} deals 1 damage to target creature or player. Activate this ability only if you have no cards in hand."); + ability.addTarget(new TargetCreatureOrPlayer()); + this.addAbility(ability); + } + + public KeldonMegaliths(final KeldonMegaliths card) { + super(card); + } + + @Override + public KeldonMegaliths copy() { + return new KeldonMegaliths(this); + } +} diff --git a/Mage.Sets/src/mage/sets/journeyintonyx/BrainMaggot.java b/Mage.Sets/src/mage/sets/journeyintonyx/BrainMaggot.java index 81dff8b6534..5406412f5f0 100644 --- a/Mage.Sets/src/mage/sets/journeyintonyx/BrainMaggot.java +++ b/Mage.Sets/src/mage/sets/journeyintonyx/BrainMaggot.java @@ -118,7 +118,7 @@ class BrainMaggotExileEffect extends OneShotEffect { Card card = opponent.getHand().get(target.getFirstTarget(), game); // If source permanent leaves the battlefield before its triggered ability resolves, the target card won't be exiled. if (card != null && game.getState().getZone(source.getSourceId()) == Zone.BATTLEFIELD) { - controller.moveCardToExileWithInfo(card, CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter()), sourcePermanent.getName(), source.getSourceId(), game, Zone.HAND, true); + controller.moveCardToExileWithInfo(card, CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter()), sourcePermanent.getIdName(), source.getSourceId(), game, Zone.HAND, true); } } } diff --git a/Mage.Sets/src/mage/sets/journeyintonyx/Godsend.java b/Mage.Sets/src/mage/sets/journeyintonyx/Godsend.java index f9034448b6e..52aad224e4e 100644 --- a/Mage.Sets/src/mage/sets/journeyintonyx/Godsend.java +++ b/Mage.Sets/src/mage/sets/journeyintonyx/Godsend.java @@ -190,7 +190,7 @@ class GodsendExileEffect extends OneShotEffect { if (creature != null && controller != null && sourcePermanent != null) { UUID exileId = CardUtil.getCardExileZoneId(game, source); controller.moveCardToExileWithInfo(creature, exileId, - new StringBuilder(sourcePermanent.getName()).append(" (").append(sourcePermanent.getZoneChangeCounter(game)).append(")").toString() + sourcePermanent.getIdName() + " (" + sourcePermanent.getZoneChangeCounter(game) + ")" , source.getSourceId(), game, Zone.BATTLEFIELD, true); } diff --git a/Mage.Sets/src/mage/sets/journeyintonyx/PropheticFlamespeaker.java b/Mage.Sets/src/mage/sets/journeyintonyx/PropheticFlamespeaker.java index 52724502644..9d4da3d5a30 100644 --- a/Mage.Sets/src/mage/sets/journeyintonyx/PropheticFlamespeaker.java +++ b/Mage.Sets/src/mage/sets/journeyintonyx/PropheticFlamespeaker.java @@ -107,7 +107,7 @@ class PropheticFlamespeakerExileEffect extends OneShotEffect { Library library = controller.getLibrary(); Card card = library.removeFromTop(game); if (card != null) { - String exileName = new StringBuilder(sourcePermanent.getName()).append(" ").toString(); + String exileName = new StringBuilder(sourcePermanent.getIdName()).append(" ").toString(); controller.moveCardToExileWithInfo(card, source.getSourceId(), exileName, source.getSourceId(), game, Zone.LIBRARY, true); ContinuousEffect effect = new PropheticFlamespeakerCastFromExileEffect(); effect.setTargetPointer(new FixedTarget(card.getId())); diff --git a/Mage.Sets/src/mage/sets/judgment/BenevolentBodyguard.java b/Mage.Sets/src/mage/sets/judgment/BenevolentBodyguard.java new file mode 100644 index 00000000000..5ee34497118 --- /dev/null +++ b/Mage.Sets/src/mage/sets/judgment/BenevolentBodyguard.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.judgment; + +import java.util.UUID; + +/** + * + * @author emerald000 + */ +public class BenevolentBodyguard extends mage.sets.vintagemasters.BenevolentBodyguard { + + public BenevolentBodyguard(UUID ownerId) { + super(ownerId); + this.cardNumber = 5; + this.expansionSetCode = "JUD"; + } + + public BenevolentBodyguard(final BenevolentBodyguard card) { + super(card); + } + + @Override + public BenevolentBodyguard copy() { + return new BenevolentBodyguard(this); + } +} diff --git a/Mage.Sets/src/mage/sets/judgment/CephalidConstable.java b/Mage.Sets/src/mage/sets/judgment/CephalidConstable.java new file mode 100644 index 00000000000..0d3f8629c7d --- /dev/null +++ b/Mage.Sets/src/mage/sets/judgment/CephalidConstable.java @@ -0,0 +1,115 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.judgment; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.common.ReturnToHandTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.FilterPermanent; +import mage.filter.predicate.permanent.ControllerIdPredicate; +import mage.game.Game; +import mage.game.events.DamagedPlayerEvent; +import mage.game.events.GameEvent; +import mage.target.Target; +import mage.target.TargetPermanent; + +/** + * + * @author emerald000 + */ +public class CephalidConstable extends CardImpl { + + public CephalidConstable(UUID ownerId) { + super(ownerId, 35, "Cephalid Constable", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{1}{U}{U}"); + this.expansionSetCode = "JUD"; + this.subtype.add("Cephalid"); + this.subtype.add("Wizard"); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Whenever Cephalid Constable deals combat damage to a player, return up to that many target permanents that player controls to their owners' hands. + Ability ability = new CephalidConstableTriggeredAbility(); + ability.addTarget(new TargetPermanent(0, 1, new FilterPermanent(), false)); // Ajusted when it triggers. + this.addAbility(ability); + } + + public CephalidConstable(final CephalidConstable card) { + super(card); + } + + @Override + public CephalidConstable copy() { + return new CephalidConstable(this); + } +} + +class CephalidConstableTriggeredAbility extends TriggeredAbilityImpl { + + CephalidConstableTriggeredAbility() { + super(Zone.BATTLEFIELD, new ReturnToHandTargetEffect(), false); + } + + CephalidConstableTriggeredAbility(final CephalidConstableTriggeredAbility ability) { + super(ability); + } + + @Override + public CephalidConstableTriggeredAbility copy() { + return new CephalidConstableTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DAMAGED_PLAYER; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getSourceId().equals(this.sourceId) && ((DamagedPlayerEvent) event).isCombatDamage()) { + FilterPermanent filter = new FilterPermanent("permanent" + (event.getAmount() > 1 ? "s" : "") + " damaged player control"); + filter.add(new ControllerIdPredicate(event.getPlayerId())); + Target target = new TargetPermanent(0, event.getAmount(), filter, false); + this.getTargets().clear(); + this.getTargets().add(target); + return true; + } + return false; + } + + @Override + public String getRule() { + return "Whenever {this} deals combat damage to a player, return up to that many target permanents that player controls to their owners' hands"; + } + +} diff --git a/Mage.Sets/src/mage/sets/judgment/NantukoMonastery.java b/Mage.Sets/src/mage/sets/judgment/NantukoMonastery.java new file mode 100644 index 00000000000..fd2d3d35074 --- /dev/null +++ b/Mage.Sets/src/mage/sets/judgment/NantukoMonastery.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.judgment; + +import java.util.UUID; + +/** + * + * @author anonymous + */ +public class NantukoMonastery extends mage.sets.archenemy.NantukoMonastery { + + public NantukoMonastery(UUID ownerId) { + super(ownerId); + this.cardNumber = 142; + this.expansionSetCode = "JUD"; + } + + public NantukoMonastery(final NantukoMonastery card) { + super(card); + } + + @Override + public NantukoMonastery copy() { + return new NantukoMonastery(this); + } +} diff --git a/Mage.Sets/src/mage/sets/judgment/WorldgorgerDragon.java b/Mage.Sets/src/mage/sets/judgment/WorldgorgerDragon.java index 131c7a9395f..03ba405c9dd 100644 --- a/Mage.Sets/src/mage/sets/judgment/WorldgorgerDragon.java +++ b/Mage.Sets/src/mage/sets/judgment/WorldgorgerDragon.java @@ -114,7 +114,7 @@ class WorldgorgerDragonEntersEffect extends OneShotEffect { if (exileId != null) { for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, source.getControllerId(), game)) { if (!permanent.getId().equals(source.getSourceId())) { // Another - controller.moveCardToExileWithInfo(permanent, exileId, sourceObject.getName(), source.getSourceId(), game, Zone.BATTLEFIELD, true); + controller.moveCardToExileWithInfo(permanent, exileId, sourceObject.getIdName(), source.getSourceId(), game, Zone.BATTLEFIELD, true); } } return true; diff --git a/Mage.Sets/src/mage/sets/judgment/WormfangDrake.java b/Mage.Sets/src/mage/sets/judgment/WormfangDrake.java index 4a3b650618b..f9c5f47a426 100644 --- a/Mage.Sets/src/mage/sets/judgment/WormfangDrake.java +++ b/Mage.Sets/src/mage/sets/judgment/WormfangDrake.java @@ -134,7 +134,7 @@ class WormfangDrakeExileCost extends CostImpl { if (permanent == null) { return false; } - paid |= controller.moveCardToExileWithInfo(permanent, exileId, sourceObject.getName() + " exiled permanents", sourceId, game, Zone.BATTLEFIELD, true); + paid |= controller.moveCardToExileWithInfo(permanent, exileId, sourceObject.getIdName() + " exiled permanents", sourceId, game, Zone.BATTLEFIELD, true); } } } diff --git a/Mage.Sets/src/mage/sets/khansoftarkir/DeflectingPalm.java b/Mage.Sets/src/mage/sets/khansoftarkir/DeflectingPalm.java index a3a55908669..85b05826dbb 100644 --- a/Mage.Sets/src/mage/sets/khansoftarkir/DeflectingPalm.java +++ b/Mage.Sets/src/mage/sets/khansoftarkir/DeflectingPalm.java @@ -54,7 +54,6 @@ public class DeflectingPalm extends CardImpl { super(ownerId, 173, "Deflecting Palm", Rarity.RARE, new CardType[]{CardType.INSTANT}, "{R}{W}"); this.expansionSetCode = "KTK"; - // The next time a source of your choice would deal damage to you this turn, prevent that damage. If damage is prevented this way, Deflecting Palm deals that much damage to that source's controller. this.getSpellAbility().addEffect(new DeflectingPalmEffect()); } @@ -89,14 +88,10 @@ class DeflectingPalmEffect extends PreventionEffectImpl { return new DeflectingPalmEffect(this); } - @Override - public boolean apply(Game game, Ability source) { - return true; - } - @Override public void init(Ability source, Game game) { this.target.choose(Outcome.PreventDamage, source.getControllerId(), source.getSourceId(), game); + super.init(source, game); } @Override diff --git a/Mage.Sets/src/mage/sets/khansoftarkir/NarsetEnlightenedMaster.java b/Mage.Sets/src/mage/sets/khansoftarkir/NarsetEnlightenedMaster.java index c74254cced0..f67946340fd 100644 --- a/Mage.Sets/src/mage/sets/khansoftarkir/NarsetEnlightenedMaster.java +++ b/Mage.Sets/src/mage/sets/khansoftarkir/NarsetEnlightenedMaster.java @@ -105,7 +105,7 @@ class NarsetEnlightenedMasterExileEffect extends OneShotEffect { if (player.getLibrary().size() > 0) { Card card = player.getLibrary().getFromTop(game); if (card != null) { - player.moveCardToExileWithInfo(card, CardUtil.getCardExileZoneId(game, source), sourceObject.getName(), source.getSourceId(), game, Zone.LIBRARY, true); + player.moveCardToExileWithInfo(card, CardUtil.getCardExileZoneId(game, source), sourceObject.getIdName(), source.getSourceId(), game, Zone.LIBRARY, true); if (!card.getCardType().contains(CardType.CREATURE) && !card.getCardType().contains(CardType.LAND)) { ContinuousEffect effect = new NarsetEnlightenedMasterCastFromExileEffect(); effect.setTargetPointer(new FixedTarget(card.getId())); diff --git a/Mage.Sets/src/mage/sets/khansoftarkir/UginsNexus.java b/Mage.Sets/src/mage/sets/khansoftarkir/UginsNexus.java index a066b66d67c..02059b65d7c 100644 --- a/Mage.Sets/src/mage/sets/khansoftarkir/UginsNexus.java +++ b/Mage.Sets/src/mage/sets/khansoftarkir/UginsNexus.java @@ -90,11 +90,6 @@ class UginsNexusSkipExtraTurnsEffect extends ReplacementEffectImpl { return new UginsNexusSkipExtraTurnsEffect(this); } - @Override - public boolean apply(Game game, Ability source) { - return true; - } - @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { Player player = game.getPlayer(event.getPlayerId()); @@ -104,10 +99,15 @@ class UginsNexusSkipExtraTurnsEffect extends ReplacementEffectImpl { } return true; } - + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.EXTRA_TURN; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - return event.getType() == EventType.EXTRA_TURN; + return true; } } diff --git a/Mage.Sets/src/mage/sets/khansoftarkir/VillainousWealth.java b/Mage.Sets/src/mage/sets/khansoftarkir/VillainousWealth.java index 9e3a5ed6b37..aba4dd07822 100644 --- a/Mage.Sets/src/mage/sets/khansoftarkir/VillainousWealth.java +++ b/Mage.Sets/src/mage/sets/khansoftarkir/VillainousWealth.java @@ -107,7 +107,7 @@ class VillainousWealthEffect extends OneShotEffect { for (int i = 0; i < cardsCount; i++) { Card card = player.getLibrary().getFromTop(game); if (card != null) { - controller.moveCardToExileWithInfo(card, exileId, "Cards exiled by " + mageObject.getLogName(), source.getSourceId(), game, Zone.LIBRARY, true); + controller.moveCardToExileWithInfo(card, exileId, mageObject.getIdName(), source.getSourceId(), game, Zone.LIBRARY, true); } } } diff --git a/Mage.Sets/src/mage/sets/legends/NetherVoid.java b/Mage.Sets/src/mage/sets/legends/NetherVoid.java index b99ccca8498..9899b75a2d5 100644 --- a/Mage.Sets/src/mage/sets/legends/NetherVoid.java +++ b/Mage.Sets/src/mage/sets/legends/NetherVoid.java @@ -47,7 +47,6 @@ public class NetherVoid extends CardImpl { this.expansionSetCode = "LEG"; this.supertype.add("World"); - // Whenever a player casts a spell, counter it unless that player pays {3}. this.addAbility(new SpellCastAllTriggeredAbility(new CounterUnlessPaysEffect(new GenericManaCost(3)), new FilterSpell("a spell"), false, true)); } diff --git a/Mage.Sets/src/mage/sets/legends/Urborg.java b/Mage.Sets/src/mage/sets/legends/Urborg.java new file mode 100644 index 00000000000..6e268839122 --- /dev/null +++ b/Mage.Sets/src/mage/sets/legends/Urborg.java @@ -0,0 +1,73 @@ +/* + * 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.legends; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.common.continuous.LoseAbilityOrAnotherAbilityTargetEffect; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.abilities.keyword.SwampwalkAbility; +import mage.abilities.mana.GreenManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author anonymous + */ +public class Urborg extends CardImpl { + + public Urborg(UUID ownerId) { + super(ownerId, 107, "Urborg", Rarity.UNCOMMON, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "LEG"; + this.supertype.add("Legendary"); + + // {tap}: Add {B} to your mana pool. + this.addAbility(new GreenManaAbility()); + // {tap}: Target creature loses first strike or swampwalk until end of turn. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new LoseAbilityOrAnotherAbilityTargetEffect(FirstStrikeAbility.getInstance(), new SwampwalkAbility()), new TapSourceCost()); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + public Urborg(final Urborg card) { + super(card); + } + + @Override + public Urborg copy() { + return new Urborg(this); + } +} + + diff --git a/Mage.Sets/src/mage/sets/limitedalpha/JadeMonolith.java b/Mage.Sets/src/mage/sets/limitedalpha/JadeMonolith.java index 7ab124a2d66..a90fb2a9caa 100644 --- a/Mage.Sets/src/mage/sets/limitedalpha/JadeMonolith.java +++ b/Mage.Sets/src/mage/sets/limitedalpha/JadeMonolith.java @@ -39,6 +39,7 @@ import mage.constants.Duration; import mage.constants.Outcome; import mage.constants.Rarity; import mage.constants.Zone; +import mage.filter.FilterObject; import mage.game.Game; import mage.game.events.DamageEvent; import mage.game.events.GameEvent; @@ -79,9 +80,9 @@ class JadeMonolithRedirectionEffect extends ReplacementEffectImpl { private final TargetSource targetSource; public JadeMonolithRedirectionEffect() { - super(Duration.EndOfTurn, Outcome.RedirectDamage); + super(Duration.OneUse, Outcome.RedirectDamage); this.staticText = "The next time a source of your choice would deal damage to target creature this turn, that source deals that damage to you instead"; - this.targetSource = new TargetSource(); + this.targetSource = new TargetSource(new FilterObject("source of your choice")); } public JadeMonolithRedirectionEffect(final JadeMonolithRedirectionEffect effect) { @@ -98,11 +99,6 @@ class JadeMonolithRedirectionEffect extends ReplacementEffectImpl { public void init(Ability source, Game game) { this.targetSource.choose(Outcome.PreventDamage, source.getControllerId(), source.getSourceId(), game); } - - @Override - public boolean apply(Game game, Ability source) { - return true; - } @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { @@ -111,27 +107,26 @@ class JadeMonolithRedirectionEffect extends ReplacementEffectImpl { MageObject sourceObject = game.getObject(source.getSourceId()); DamageEvent damageEvent = (DamageEvent) event; if (controller != null && targetCreature != null) { - this.used = true; - controller.damage(damageEvent.getAmount(), damageEvent.getSourceId(), game, damageEvent.isCombatDamage(), damageEvent.isPreventable(), damageEvent.getAppliedEffects()); - + controller.damage(damageEvent.getAmount(), damageEvent.getSourceId(), game, damageEvent.isCombatDamage(), damageEvent.isPreventable(), damageEvent.getAppliedEffects()); StringBuilder sb = new StringBuilder(sourceObject != null ? sourceObject.getLogName() : ""); sb.append(": ").append(damageEvent.getAmount()).append(" damage redirected from ").append(targetCreature.getLogName()); sb.append(" to ").append(controller.getLogName()); game.informPlayers(sb.toString()); - + discard(); // only one use return true; } return false; } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.DAMAGE_CREATURE; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (!this.used) { - if (event.getType().equals(EventType.DAMAGE_CREATURE)) { - if (event.getSourceId().equals(targetSource.getFirstTarget()) && event.getTargetId().equals(source.getFirstTarget())) { - return true; - } - } + if (event.getSourceId().equals(targetSource.getFirstTarget()) && event.getTargetId().equals(source.getFirstTarget())) { + return true; } return false; } diff --git a/Mage.Sets/src/mage/sets/lorwyn/MakeshiftMannequin.java b/Mage.Sets/src/mage/sets/lorwyn/MakeshiftMannequin.java new file mode 100644 index 00000000000..f223e221a14 --- /dev/null +++ b/Mage.Sets/src/mage/sets/lorwyn/MakeshiftMannequin.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.lorwyn; + +import java.util.UUID; + +/** + * + * @author emerald000 + */ +public class MakeshiftMannequin extends mage.sets.archenemy.MakeshiftMannequin { + + public MakeshiftMannequin(UUID ownerId) { + super(ownerId); + this.cardNumber = 124; + this.expansionSetCode = "LRW"; + } + + public MakeshiftMannequin(final MakeshiftMannequin card) { + super(card); + } + + @Override + public MakeshiftMannequin copy() { + return new MakeshiftMannequin(this); + } +} diff --git a/Mage.Sets/src/mage/sets/lorwyn/Vigor.java b/Mage.Sets/src/mage/sets/lorwyn/Vigor.java index af064b86519..be79e7b13ed 100644 --- a/Mage.Sets/src/mage/sets/lorwyn/Vigor.java +++ b/Mage.Sets/src/mage/sets/lorwyn/Vigor.java @@ -107,19 +107,18 @@ class VigorReplacementEffect extends ReplacementEffectImpl { } return false; } - + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DAMAGE_CREATURE; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - return event.getType() == GameEvent.EventType.DAMAGE_CREATURE - && event.getPlayerId().equals(source.getControllerId()) + return event.getPlayerId().equals(source.getControllerId()) && !event.getTargetId().equals(source.getSourceId()); } - @Override - public boolean apply(Game game, Ability source) { - return true; - } - @Override public VigorReplacementEffect copy() { return new VigorReplacementEffect(this); diff --git a/Mage.Sets/src/mage/sets/magic2010/HarmsWay.java b/Mage.Sets/src/mage/sets/magic2010/HarmsWay.java index bfdce00dd2b..12a58405a48 100644 --- a/Mage.Sets/src/mage/sets/magic2010/HarmsWay.java +++ b/Mage.Sets/src/mage/sets/magic2010/HarmsWay.java @@ -35,6 +35,7 @@ import mage.abilities.effects.PreventionEffectImpl; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Duration; +import mage.constants.Outcome; import mage.constants.Rarity; import mage.game.Game; import mage.game.events.GameEvent; @@ -53,10 +54,8 @@ public class HarmsWay extends CardImpl { super(ownerId, 14, "Harm's Way", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{W}"); this.expansionSetCode = "M10"; - // The next 2 damage that a source of your choice would deal to you and/or permanents you control this turn is dealt to target creature or player instead. this.getSpellAbility().addEffect(new HarmsWayPreventDamageTargetEffect()); - this.getSpellAbility().addTarget(new TargetSource()); this.getSpellAbility().addTarget(new TargetCreatureOrPlayer()); } @@ -71,24 +70,29 @@ public class HarmsWay extends CardImpl { } class HarmsWayPreventDamageTargetEffect extends PreventionEffectImpl { - + + private final TargetSource target; + public HarmsWayPreventDamageTargetEffect() { super(Duration.EndOfTurn, 2, false, true); staticText = "The next 2 damage that a source of your choice would deal to you and/or permanents you control this turn is dealt to target creature or player instead"; + this.target = new TargetSource(); } public HarmsWayPreventDamageTargetEffect(final HarmsWayPreventDamageTargetEffect effect) { super(effect); + this.target = effect.target.copy(); } @Override public HarmsWayPreventDamageTargetEffect copy() { return new HarmsWayPreventDamageTargetEffect(this); } - + @Override - public boolean apply(Game game, Ability source) { - return true; + public void init(Ability source, Game game) { + this.target.choose(Outcome.PreventDamage, source.getControllerId(), source.getSourceId(), game); + super.init(source, game); } @Override @@ -96,18 +100,20 @@ class HarmsWayPreventDamageTargetEffect extends PreventionEffectImpl { PreventionEffectData preventionData = preventDamageAction(event, source, game); // deal damage now if (preventionData.getPreventedDamage() > 0) { - UUID redirectTo = source.getTargets().get(1).getFirstTarget(); + UUID redirectTo = source.getFirstTarget(); Permanent permanent = game.getPermanent(redirectTo); if (permanent != null) { game.informPlayers("Dealing " + preventionData.getPreventedDamage() + " to " + permanent.getLogName() + " instead"); // keep the original source id as it is redirecting permanent.damage(preventionData.getPreventedDamage(), event.getSourceId(), game, false, true); + discard(); } Player player = game.getPlayer(redirectTo); if (player != null) { game.informPlayers("Dealing " + preventionData.getPreventedDamage() + " to " + player.getLogName() + " instead"); // keep the original source id as it is redirecting player.damage(preventionData.getPreventedDamage(), event.getSourceId(), game, false, true); + discard(); } } return false; @@ -115,7 +121,7 @@ class HarmsWayPreventDamageTargetEffect extends PreventionEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (!this.used && super.applies(event, source, game)) { + if (super.applies(event, source, game)) { // check source MageObject object = game.getObject(event.getSourceId()); if (object == null) { @@ -123,8 +129,8 @@ class HarmsWayPreventDamageTargetEffect extends PreventionEffectImpl { return false; } - if (!object.getId().equals(source.getFirstTarget()) - && (!(object instanceof Spell) || !((Spell) object).getSourceId().equals(source.getFirstTarget()))) { + if (!object.getId().equals(target.getFirstTarget()) + && (!(object instanceof Spell) || !((Spell) object).getSourceId().equals(target.getFirstTarget()))) { return false; } diff --git a/Mage.Sets/src/mage/sets/magic2011/HoardingDragon.java b/Mage.Sets/src/mage/sets/magic2011/HoardingDragon.java index 6d5920967db..409bfe4f207 100644 --- a/Mage.Sets/src/mage/sets/magic2011/HoardingDragon.java +++ b/Mage.Sets/src/mage/sets/magic2011/HoardingDragon.java @@ -30,6 +30,7 @@ package mage.sets.magic2011; import java.util.UUID; import mage.MageInt; +import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.DiesTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; @@ -101,13 +102,14 @@ class HoardingDragonEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { + MageObject sourceObject = source.getSourceObject(game); + if (controller != null && sourceObject != null) { TargetCardInLibrary target = new TargetCardInLibrary(new FilterArtifactCard()); if (controller.searchLibrary(target, game)) { if (target.getTargets().size() > 0) { Card card = controller.getLibrary().getCard(target.getFirstTarget(), game); if (card != null) { - controller.moveCardToExileWithInfo(card, exileId, "Hoarding Dragon", source.getSourceId(), game, Zone.LIBRARY, true); + controller.moveCardToExileWithInfo(card, exileId, sourceObject.getIdName(), source.getSourceId(), game, Zone.LIBRARY, true); } } } diff --git a/Mage.Sets/src/mage/sets/magic2011/LeylineOfPunishment.java b/Mage.Sets/src/mage/sets/magic2011/LeylineOfPunishment.java index 31e242ba383..8c6ecef50a4 100644 --- a/Mage.Sets/src/mage/sets/magic2011/LeylineOfPunishment.java +++ b/Mage.Sets/src/mage/sets/magic2011/LeylineOfPunishment.java @@ -39,6 +39,7 @@ import mage.constants.Zone; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; import mage.abilities.effects.ReplacementEffectImpl; import mage.abilities.effects.common.continuous.CantGainLifeAllEffect; import mage.abilities.keyword.LeylineAbility; @@ -58,7 +59,6 @@ public class LeylineOfPunishment extends CardImpl { super(ownerId, 148, "Leyline of Punishment", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}{R}"); this.expansionSetCode = "M11"; - // If Leyline of Punishment is in your opening hand, you may begin the game with it on the battlefield. this.addAbility(LeylineAbility.getInstance()); // Players can't gain life. @@ -78,7 +78,7 @@ public class LeylineOfPunishment extends CardImpl { } -class LeylineOfPunishmentEffect2 extends ReplacementEffectImpl { +class LeylineOfPunishmentEffect2 extends ContinuousRuleModifyingEffectImpl { public LeylineOfPunishmentEffect2() { super(Duration.WhileOnBattlefield, Outcome.Benefit); @@ -95,21 +95,13 @@ class LeylineOfPunishmentEffect2 extends ReplacementEffectImpl { } @Override - public boolean apply(Game game, Ability source) { - return true; - } - - @Override - public boolean replaceEvent(GameEvent event, Ability source, Game game) { - return true; + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.PREVENT_DAMAGE; } @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == EventType.PREVENT_DAMAGE) { - return true; - } - return false; + return true; } } diff --git a/Mage.Sets/src/mage/sets/magic2011/LeylineOfTheVoid.java b/Mage.Sets/src/mage/sets/magic2011/LeylineOfTheVoid.java index a082fad325f..522a640e339 100644 --- a/Mage.Sets/src/mage/sets/magic2011/LeylineOfTheVoid.java +++ b/Mage.Sets/src/mage/sets/magic2011/LeylineOfTheVoid.java @@ -90,11 +90,6 @@ class LeylineOfTheVoidEffect extends ReplacementEffectImpl { return new LeylineOfTheVoidEffect(this); } - @Override - public boolean apply(Game game, Ability source) { - return true; - } - @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { Player controller = game.getPlayer(source.getControllerId()); @@ -114,10 +109,15 @@ class LeylineOfTheVoidEffect extends ReplacementEffectImpl { } return false; } - + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.ZONE_CHANGE; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == EventType.ZONE_CHANGE && ((ZoneChangeEvent)event).getToZone() == Zone.GRAVEYARD) { + if (((ZoneChangeEvent)event).getToZone() == Zone.GRAVEYARD) { Card card = game.getCard(event.getTargetId()); if (card != null && game.getOpponents(source.getControllerId()).contains(card.getOwnerId())) { return true; diff --git a/Mage.Sets/src/mage/sets/magic2011/ObstinateBaloth.java b/Mage.Sets/src/mage/sets/magic2011/ObstinateBaloth.java index d2adbc1706e..f4675b3bc48 100644 --- a/Mage.Sets/src/mage/sets/magic2011/ObstinateBaloth.java +++ b/Mage.Sets/src/mage/sets/magic2011/ObstinateBaloth.java @@ -96,10 +96,15 @@ class ObstinateBalothEffect extends ReplacementEffectImpl { public ObstinateBalothEffect copy() { return new ObstinateBalothEffect(this); } - + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.ZONE_CHANGE; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == EventType.ZONE_CHANGE && event.getTargetId().equals(source.getSourceId())) { + if (event.getTargetId().equals(source.getSourceId())) { ZoneChangeEvent zcEvent = (ZoneChangeEvent) event; if (zcEvent.getFromZone() == Zone.HAND && zcEvent.getToZone() == Zone.GRAVEYARD) { StackObject spell = game.getStack().getStackObject(event.getSourceId()); @@ -112,7 +117,7 @@ class ObstinateBalothEffect extends ReplacementEffectImpl { } @Override - public boolean apply(Game game, Ability source) { + public boolean replaceEvent(GameEvent event, Ability source, Game game) { Card card = game.getCard(source.getSourceId()); if (card != null) { Player owner = game.getPlayer(card.getOwnerId()); @@ -125,9 +130,4 @@ class ObstinateBalothEffect extends ReplacementEffectImpl { return false; } - @Override - public boolean replaceEvent(GameEvent event, Ability source, Game game) { - return apply(game, source); - } - } \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/magic2013/ElderscaleWurm.java b/Mage.Sets/src/mage/sets/magic2013/ElderscaleWurm.java index ae076d44e66..b2e9325a778 100644 --- a/Mage.Sets/src/mage/sets/magic2013/ElderscaleWurm.java +++ b/Mage.Sets/src/mage/sets/magic2013/ElderscaleWurm.java @@ -38,7 +38,6 @@ import mage.abilities.keyword.TrampleAbility; import mage.cards.CardImpl; import mage.game.Game; import mage.game.events.GameEvent; -import mage.game.permanent.Permanent; import mage.players.Player; import java.util.UUID; @@ -120,34 +119,30 @@ class ElderscaleWurmReplacementEffect extends ReplacementEffectImpl { public ElderscaleWurmReplacementEffect copy() { return new ElderscaleWurmReplacementEffect(this); } - + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DAMAGE_CAUSES_LIFE_LOSS; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType().equals(GameEvent.EventType.DAMAGE_CAUSES_LIFE_LOSS)) { - Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent == null) { - permanent = (Permanent) game.getLastKnownInformation(source.getSourceId(), Zone.BATTLEFIELD); - } - if (permanent != null) { - Player controller = game.getPlayer(permanent.getControllerId()); - if (controller != null && controller.getLife() >= 7 - && (controller.getLife() - event.getAmount()) < 7 - && event.getPlayerId().equals(controller.getId())) { - event.setAmount(controller.getLife() - 7); - } + if (event.getPlayerId().equals(source.getControllerId())) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null && controller.getLife() >= 7 + && (controller.getLife() - event.getAmount()) < 7) { + return true; } } - - return false; - } - - @Override - public boolean apply(Game game, Ability source) { return false; } @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + event.setAmount(controller.getLife() - 7); + } return false; } diff --git a/Mage.Sets/src/mage/sets/magic2014/ChandraPyromaster.java b/Mage.Sets/src/mage/sets/magic2014/ChandraPyromaster.java index 2e653e7eab8..0323d025555 100644 --- a/Mage.Sets/src/mage/sets/magic2014/ChandraPyromaster.java +++ b/Mage.Sets/src/mage/sets/magic2014/ChandraPyromaster.java @@ -36,7 +36,6 @@ import mage.abilities.LoyaltyAbility; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.effects.AsThoughEffectImpl; import mage.abilities.effects.ContinuousEffect; -import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.combat.CantBlockTargetEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; @@ -210,11 +209,12 @@ class ChandraPyromasterEffect2 extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - if (controller != null && controller.getLibrary().size() > 0) { + MageObject sourceObject = source.getSourceObject(game); + if (controller != null && sourceObject != null && controller.getLibrary().size() > 0) { Library library = controller.getLibrary(); Card card = library.removeFromTop(game); if (card != null) { - controller.moveCardToExileWithInfo(card, source.getSourceId(), "Chandra Pyromaster ", source.getSourceId(), game, Zone.LIBRARY, true); + controller.moveCardToExileWithInfo(card, source.getSourceId(), sourceObject.getIdName() + " ", source.getSourceId(), game, Zone.LIBRARY, true); ContinuousEffect effect = new ChandraPyromasterCastFromExileEffect(); effect.setTargetPointer(new FixedTarget(card.getId())); game.addEffect(effect, source); diff --git a/Mage.Sets/src/mage/sets/magic2014/ImposingSovereign.java b/Mage.Sets/src/mage/sets/magic2014/ImposingSovereign.java index c9f35721b65..0a7c07a1299 100644 --- a/Mage.Sets/src/mage/sets/magic2014/ImposingSovereign.java +++ b/Mage.Sets/src/mage/sets/magic2014/ImposingSovereign.java @@ -91,9 +91,14 @@ class ImposingSovereignEffect extends ReplacementEffectImpl { return false; } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD && game.getOpponents(source.getControllerId()).contains(event.getPlayerId())) { + if (game.getOpponents(source.getControllerId()).contains(event.getPlayerId())) { Permanent permanent = game.getPermanent(event.getTargetId()); if (permanent != null && permanent.getCardType().contains(CardType.CREATURE)) { return true; @@ -102,11 +107,6 @@ class ImposingSovereignEffect extends ReplacementEffectImpl { return false; } - @Override - public boolean apply(Game game, Ability source) { - return false; - } - @Override public ImposingSovereignEffect copy() { return new ImposingSovereignEffect(this); diff --git a/Mage.Sets/src/mage/sets/magic2014/PyromancersGauntlet.java b/Mage.Sets/src/mage/sets/magic2014/PyromancersGauntlet.java index 0547801c6d5..574a2d664f6 100644 --- a/Mage.Sets/src/mage/sets/magic2014/PyromancersGauntlet.java +++ b/Mage.Sets/src/mage/sets/magic2014/PyromancersGauntlet.java @@ -79,31 +79,29 @@ class PyromancersGauntletReplacementEffect extends ReplacementEffectImpl { } @Override - public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType().equals(GameEvent.EventType.DAMAGE_PLAYER) + public boolean checksEventType(GameEvent event, Game game) { + return event.getType().equals(GameEvent.EventType.DAMAGE_PLAYER) || event.getType().equals(GameEvent.EventType.DAMAGE_CREATURE) - || event.getType().equals(GameEvent.EventType.DAMAGE_PLANESWALKER)) { - MageObject object = game.getObject(event.getSourceId()); - if (object != null && object instanceof Spell) { - if (((Spell) object).getControllerId().equals(source.getControllerId()) - && (object.getCardType().contains(CardType.INSTANT) - || object.getCardType().contains(CardType.SORCERY))){ - return true; - } - } - Permanent permanent = game.getBattlefield().getPermanent(event.getSourceId()); - if(permanent != null && permanent.getCardType().contains(CardType.PLANESWALKER)){ + || event.getType().equals(GameEvent.EventType.DAMAGE_PLANESWALKER); + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + MageObject object = game.getObject(event.getSourceId()); + if (object != null && object instanceof Spell) { + if (((Spell) object).getControllerId().equals(source.getControllerId()) + && (object.getCardType().contains(CardType.INSTANT) + || object.getCardType().contains(CardType.SORCERY))){ return true; } } + Permanent permanent = game.getBattlefield().getPermanent(event.getSourceId()); + if(permanent != null && permanent.getCardType().contains(CardType.PLANESWALKER)){ + return true; + } return false; } - @Override - public boolean apply(Game game, Ability source) { - return true; - } - @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { event.setAmount(event.getAmount() + 2); diff --git a/Mage.Sets/src/mage/sets/magic2014/SavageSummoning.java b/Mage.Sets/src/mage/sets/magic2014/SavageSummoning.java index c323b750f90..6e1407ba2d0 100644 --- a/Mage.Sets/src/mage/sets/magic2014/SavageSummoning.java +++ b/Mage.Sets/src/mage/sets/magic2014/SavageSummoning.java @@ -50,6 +50,7 @@ import mage.constants.WatcherScope; import mage.counters.CounterType; import mage.game.Game; import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; import mage.game.permanent.Permanent; import mage.game.stack.Spell; import mage.watchers.Watcher; @@ -193,10 +194,7 @@ class SavageSummoningWatcher extends Watcher { public boolean isSpellCastWithThisSavageSummoning(UUID spellId, UUID cardId, int zoneChangeCounter) { String cardKey = new StringBuilder(cardId.toString()).append("_").append(zoneChangeCounter).toString(); HashSet savageSpells = (HashSet) spellsCastWithSavageSummoning.get(spellId); - if (savageSpells != null && savageSpells.contains(cardKey)) { - return true; - } - return false; + return savageSpells != null && savageSpells.contains(cardKey); } public boolean isCardCastWithThisSavageSummoning(Card card, UUID cardId, int zoneChangeCounter, Game game) { @@ -204,10 +202,7 @@ class SavageSummoningWatcher extends Watcher { // add one because card is now gone to battlefield as creature String cardKey = new StringBuilder(cardId.toString()).append("_").append(zoneChangeCounter).toString(); HashSet savageSpells = (HashSet) cardsCastWithSavageSummoning.get(creatureCardKey); - if (savageSpells != null && savageSpells.contains(cardKey)) { - return true; - } - return false; + return savageSpells != null && savageSpells.contains(cardKey); } @Override @@ -307,11 +302,6 @@ class SavageSummoningEntersBattlefieldEffect extends ReplacementEffectImpl { return new SavageSummoningEntersBattlefieldEffect(this); } - @Override - public boolean apply(Game game, Ability source) { - return true; - } - @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { Permanent creature = game.getPermanent(event.getTargetId()); @@ -322,15 +312,15 @@ class SavageSummoningEntersBattlefieldEffect extends ReplacementEffectImpl { return false; } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.ENTERS_THE_BATTLEFIELD; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if ((event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD)) { - Card card = game.getCard(event.getTargetId()); - if (card != null && watcher.isCardCastWithThisSavageSummoning(card, source.getSourceId(), zoneChangeCounter, game)) { - return true; - } - } - return false; + Card card = game.getCard(event.getTargetId()); + return card != null && watcher.isCardCastWithThisSavageSummoning(card, source.getSourceId(), zoneChangeCounter, game); } } diff --git a/Mage.Sets/src/mage/sets/magic2015/Quickling.java b/Mage.Sets/src/mage/sets/magic2015/Quickling.java index b508d869fd9..c23893233e4 100644 --- a/Mage.Sets/src/mage/sets/magic2015/Quickling.java +++ b/Mage.Sets/src/mage/sets/magic2015/Quickling.java @@ -102,8 +102,7 @@ class QuicklingEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { boolean targetChosen = false; - TargetPermanent target = new TargetPermanent(1, 1, filter, false); - + TargetPermanent target = new TargetPermanent(1, 1, filter, true); if (target.canChoose(controller.getId(), game) && controller.chooseUse(outcome, "Return another creature you control to its owner's hand?", game)) { controller.chooseTarget(Outcome.ReturnToHand, target, source, game); Permanent permanent = game.getPermanent(target.getFirstTarget()); diff --git a/Mage.Sets/src/mage/sets/magic2015/SliverHive.java b/Mage.Sets/src/mage/sets/magic2015/SliverHive.java index 1d2c1a0578f..d28e5e4d8eb 100644 --- a/Mage.Sets/src/mage/sets/magic2015/SliverHive.java +++ b/Mage.Sets/src/mage/sets/magic2015/SliverHive.java @@ -70,7 +70,7 @@ public class SliverHive extends CardImpl { this.addAbility(new ColorlessManaAbility()); // {T}: Add one mana of any color to your mana pool. Spend this mana only to cast a Sliver spell. - this.addAbility(new ConditionalAnyColorManaAbility(1, new SliverHiveManaBuilder())); + this.addAbility(new ConditionalAnyColorManaAbility(new TapSourceCost(), 1, new SliverHiveManaBuilder(), true)); // {5}, {T}: Put a 1/1 colorless Sliver creature token onto the battlefield. Activate this ability only if you control a Sliver. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new SliverToken()), new TapSourceCost()); diff --git a/Mage.Sets/src/mage/sets/mastersedition/IslandOfWakWak.java b/Mage.Sets/src/mage/sets/mastersedition/IslandOfWakWak.java new file mode 100644 index 00000000000..68b4898e3ff --- /dev/null +++ b/Mage.Sets/src/mage/sets/mastersedition/IslandOfWakWak.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.mastersedition; + +import java.util.UUID; + +/** + * + * @author anonymous + */ +public class IslandOfWakWak extends mage.sets.arabiannights.IslandOfWakWak { + + public IslandOfWakWak(UUID ownerId) { + super(ownerId); + this.cardNumber = 176; + this.expansionSetCode = "MED"; + } + + public IslandOfWakWak(final IslandOfWakWak card) { + super(card); + } + + @Override + public IslandOfWakWak copy() { + return new IslandOfWakWak(this); + } +} diff --git a/Mage.Sets/src/mage/sets/mastersedition/MysticRemora.java b/Mage.Sets/src/mage/sets/mastersedition/MysticRemora.java new file mode 100644 index 00000000000..8d8ecb153fd --- /dev/null +++ b/Mage.Sets/src/mage/sets/mastersedition/MysticRemora.java @@ -0,0 +1,54 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.mastersedition; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author TGower + */ +public class MysticRemora extends mage.sets.iceage.MysticRemora { + + public MysticRemora(UUID ownerId) { + super(ownerId); + this.cardNumber = 42; + this.expansionSetCode = "MED"; + this.rarity = Rarity.UNCOMMON; + } + + public MysticRemora(final MysticRemora card) { + super(card); + } + + @Override + public MysticRemora copy() { + return new MysticRemora(this); + } +} diff --git a/Mage.Sets/src/mage/sets/masterseditioniii/CityOfShadows.java b/Mage.Sets/src/mage/sets/masterseditioniii/CityOfShadows.java new file mode 100644 index 00000000000..e22c114e82c --- /dev/null +++ b/Mage.Sets/src/mage/sets/masterseditioniii/CityOfShadows.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.masterseditioniii; + +import java.util.UUID; + +/** + * + * @author anonymous + */ +public class CityOfShadows extends mage.sets.thedark.CityOfShadows { + + public CityOfShadows(UUID ownerId) { + super(ownerId); + this.cardNumber = 206; + this.expansionSetCode = "ME3"; + } + + public CityOfShadows(final CityOfShadows card) { + super(card); + } + + @Override + public CityOfShadows copy() { + return new CityOfShadows(this); + } +} diff --git a/Mage.Sets/src/mage/sets/masterseditioniii/Urborg.java b/Mage.Sets/src/mage/sets/masterseditioniii/Urborg.java new file mode 100644 index 00000000000..115558fcf7e --- /dev/null +++ b/Mage.Sets/src/mage/sets/masterseditioniii/Urborg.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.masterseditioniii; + +import java.util.UUID; + +/** + * + * @author anonymous + */ +public class Urborg extends mage.sets.legends.Urborg { + + public Urborg(UUID ownerId) { + super(ownerId); + this.cardNumber = 214; + this.expansionSetCode = "ME3"; + } + + public Urborg(final Urborg card) { + super(card); + } + + @Override + public Urborg copy() { + return new Urborg(this); + } +} diff --git a/Mage.Sets/src/mage/sets/masterseditioniv/ElephantGraveyard.java b/Mage.Sets/src/mage/sets/masterseditioniv/ElephantGraveyard.java new file mode 100644 index 00000000000..74064359648 --- /dev/null +++ b/Mage.Sets/src/mage/sets/masterseditioniv/ElephantGraveyard.java @@ -0,0 +1,71 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.masterseditioniv; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.common.RegenerateTargetEffect; +import mage.abilities.mana.ColorlessManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.FilterPermanent; +import mage.target.TargetPermanent; + +/** + * + * @author anonymous + */ +public class ElephantGraveyard extends CardImpl { + + private static final FilterPermanent filter = new FilterPermanent("Elephant", "Elephant"); + + public ElephantGraveyard(UUID ownerId) { + super(ownerId, 244, "Elephant Graveyard", Rarity.UNCOMMON, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "ME4"; + + // {tap}: Add {1} to your mana pool. + this.addAbility(new ColorlessManaAbility()); + // {tap}: Regenerate target Elephant. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new RegenerateTargetEffect(), new TapSourceCost()); + ability.addTarget(new TargetPermanent(filter)); + this.addAbility(ability); + } + + public ElephantGraveyard(final ElephantGraveyard card) { + super(card); + } + + @Override + public ElephantGraveyard copy() { + return new ElephantGraveyard(this); + } +} diff --git a/Mage.Sets/src/mage/sets/mercadianmasques/FountainOfCho.java b/Mage.Sets/src/mage/sets/mercadianmasques/FountainOfCho.java new file mode 100644 index 00000000000..5074f07c584 --- /dev/null +++ b/Mage.Sets/src/mage/sets/mercadianmasques/FountainOfCho.java @@ -0,0 +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.sets.mercadianmasques; + +import java.util.UUID; +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTappedAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.RemoveVariableCountersSourceCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.dynamicvalue.common.RemovedCountersForCostValue; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.mana.DynamicManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.counters.CounterType; + +/** + * + * @author anonymous + */ +public class FountainOfCho extends CardImpl { + + public FountainOfCho(UUID ownerId) { + super(ownerId, 317, "Fountain of Cho", Rarity.UNCOMMON, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "MMQ"; + + // Fountain of Cho enters the battlefield tapped. + this.addAbility(new EntersBattlefieldTappedAbility()); + // {tap}: Put a storage counter on Fountain of Cho. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.STORAGE.createInstance()), new TapSourceCost())); + // {tap}, Remove any number of storage counters from Fountain of Cho: Add {W} to your mana pool for each storage counter removed this way. + Ability ability = new DynamicManaAbility(Mana.WhiteMana, new RemovedCountersForCostValue(), + "Add {W} to your mana pool for each storage counter removed this way"); + ability.addCost(new RemoveVariableCountersSourceCost( + CounterType.STORAGE.createInstance(), "Remove any number of storage counters from {this}")); + this.addAbility(ability); + } + + public FountainOfCho(final FountainOfCho card) { + super(card); + } + + @Override + public FountainOfCho copy() { + return new FountainOfCho(this); + } +} diff --git a/Mage.Sets/src/mage/sets/mercadianmasques/HengeOfRamos.java b/Mage.Sets/src/mage/sets/mercadianmasques/HengeOfRamos.java new file mode 100644 index 00000000000..fa3fe67ba7f --- /dev/null +++ b/Mage.Sets/src/mage/sets/mercadianmasques/HengeOfRamos.java @@ -0,0 +1,66 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.mercadianmasques; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.mana.AnyColorManaAbility; +import mage.abilities.mana.ColorlessManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; + +/** + * + * @author anonymous + */ +public class HengeOfRamos extends CardImpl { + + public HengeOfRamos(UUID ownerId) { + super(ownerId, 318, "Henge of Ramos", Rarity.UNCOMMON, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "MMQ"; + + // {tap}: Add {1} to your mana pool. + this.addAbility(new ColorlessManaAbility()); + // {2}, {tap}: Add one mana of any color to your mana pool. + Ability ability = new AnyColorManaAbility(new ManaCostsImpl<>("{2}")); + ability.addCost(new TapSourceCost()); + this.addAbility(ability); + } + + public HengeOfRamos(final HengeOfRamos card) { + super(card); + } + + @Override + public HengeOfRamos copy() { + return new HengeOfRamos(this); + } +} diff --git a/Mage.Sets/src/mage/sets/mercadianmasques/MercadianBazaar.java b/Mage.Sets/src/mage/sets/mercadianmasques/MercadianBazaar.java new file mode 100644 index 00000000000..b89398ad4a3 --- /dev/null +++ b/Mage.Sets/src/mage/sets/mercadianmasques/MercadianBazaar.java @@ -0,0 +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.sets.mercadianmasques; + +import java.util.UUID; +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTappedAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.RemoveVariableCountersSourceCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.dynamicvalue.common.RemovedCountersForCostValue; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.mana.DynamicManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.counters.CounterType; + +/** + * + * @author anonymous + */ +public class MercadianBazaar extends CardImpl { + + public MercadianBazaar(UUID ownerId) { + super(ownerId, 321, "Mercadian Bazaar", Rarity.UNCOMMON, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "MMQ"; + + // Mercadian Bazaar enters the battlefield tapped. + this.addAbility(new EntersBattlefieldTappedAbility()); + // {tap}: Put a storage counter on Mercadian Bazaar. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.STORAGE.createInstance()), new TapSourceCost())); + // {tap}, Remove any number of storage counters from Mercadian Bazaar: Add {R} to your mana pool for each storage counter removed this way. + Ability ability = new DynamicManaAbility(Mana.RedMana, new RemovedCountersForCostValue(), + "Add {R} to your mana pool for each storage counter removed this way"); + ability.addCost(new RemoveVariableCountersSourceCost( + CounterType.STORAGE.createInstance(), "Remove any number of storage counters from {this}")); + this.addAbility(ability); + } + + public MercadianBazaar(final MercadianBazaar card) { + super(card); + } + + @Override + public MercadianBazaar copy() { + return new MercadianBazaar(this); + } +} diff --git a/Mage.Sets/src/mage/sets/mercadianmasques/RushwoodGrove.java b/Mage.Sets/src/mage/sets/mercadianmasques/RushwoodGrove.java new file mode 100644 index 00000000000..df971fa382f --- /dev/null +++ b/Mage.Sets/src/mage/sets/mercadianmasques/RushwoodGrove.java @@ -0,0 +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.sets.mercadianmasques; + +import java.util.UUID; +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTappedAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.RemoveVariableCountersSourceCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.dynamicvalue.common.RemovedCountersForCostValue; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.mana.DynamicManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.counters.CounterType; + +/** + * + * @author anonymous + */ +public class RushwoodGrove extends CardImpl { + + public RushwoodGrove(UUID ownerId) { + super(ownerId, 325, "Rushwood Grove", Rarity.UNCOMMON, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "MMQ"; + + // Rushwood Grove enters the battlefield tapped. + this.addAbility(new EntersBattlefieldTappedAbility()); + // {tap}: Put a storage counter on Rushwood Grove. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.STORAGE.createInstance()), new TapSourceCost())); + // {tap}, Remove any number of storage counters from Rushwood Grove: Add {G} to your mana pool for each storage counter removed this way. + Ability ability = new DynamicManaAbility(Mana.GreenMana, new RemovedCountersForCostValue(), + "Add {G} to your mana pool for each storage counter removed this way"); + ability.addCost(new RemoveVariableCountersSourceCost( + CounterType.STORAGE.createInstance(), "Remove any number of storage counters from {this}")); + this.addAbility(ability); + } + + public RushwoodGrove(final RushwoodGrove card) { + super(card); + } + + @Override + public RushwoodGrove copy() { + return new RushwoodGrove(this); + } +} diff --git a/Mage.Sets/src/mage/sets/mercadianmasques/SaprazzanCove.java b/Mage.Sets/src/mage/sets/mercadianmasques/SaprazzanCove.java new file mode 100644 index 00000000000..7d841973f70 --- /dev/null +++ b/Mage.Sets/src/mage/sets/mercadianmasques/SaprazzanCove.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.sets.mercadianmasques; + +import java.util.UUID; +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTappedAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.RemoveVariableCountersSourceCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.dynamicvalue.common.RemovedCountersForCostValue; +import mage.abilities.effects.common.AddManaInAnyCombinationEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.mana.DynamicManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.ColoredManaSymbol; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.counters.CounterType; + +/** + * + * @author anonymous + */ +public class SaprazzanCove extends CardImpl { + + public SaprazzanCove(UUID ownerId) { + super(ownerId, 327, "Saprazzan Cove", Rarity.UNCOMMON, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "MMQ"; + + // Saprazzan Cove enters the battlefield tapped. + this.addAbility(new EntersBattlefieldTappedAbility()); + // {tap}: Put a storage counter on Saprazzan Cove. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.STORAGE.createInstance()), new TapSourceCost())); + // {tap}, Remove any number of storage counters from Saprazzan Cove: Add {U} to your mana pool for each storage counter removed this way. + Ability ability = new DynamicManaAbility(Mana.BlueMana, new RemovedCountersForCostValue(), + "Add {U} to your mana pool for each storage counter removed this way"); + ability.addCost(new RemoveVariableCountersSourceCost( + CounterType.STORAGE.createInstance(), "Remove any number of storage counters from {this}")); + this.addAbility(ability); + } + + public SaprazzanCove(final SaprazzanCove card) { + super(card); + } + + @Override + public SaprazzanCove copy() { + return new SaprazzanCove(this); + } +} diff --git a/Mage.Sets/src/mage/sets/mercadianmasques/SubterraneanHangar.java b/Mage.Sets/src/mage/sets/mercadianmasques/SubterraneanHangar.java new file mode 100644 index 00000000000..245b09cbd4a --- /dev/null +++ b/Mage.Sets/src/mage/sets/mercadianmasques/SubterraneanHangar.java @@ -0,0 +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.sets.mercadianmasques; + +import java.util.UUID; +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTappedAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.RemoveVariableCountersSourceCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.dynamicvalue.common.RemovedCountersForCostValue; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.mana.DynamicManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.counters.CounterType; + +/** + * + * @author anonymous + */ +public class SubterraneanHangar extends CardImpl { + + public SubterraneanHangar(UUID ownerId) { + super(ownerId, 329, "Subterranean Hangar", Rarity.UNCOMMON, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "MMQ"; + + // Subterranean Hangar enters the battlefield tapped. + this.addAbility(new EntersBattlefieldTappedAbility()); + // {tap}: Put a storage counter on Subterranean Hangar. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.STORAGE.createInstance()), new TapSourceCost())); + // {tap}, Remove any number of storage counters from Subterranean Hangar: Add {B} to your mana pool for each storage counter removed this way. + Ability ability = new DynamicManaAbility(Mana.BlackMana, new RemovedCountersForCostValue(), + "Add {B} to your mana pool for each storage counter removed this way"); + ability.addCost(new RemoveVariableCountersSourceCost( + CounterType.STORAGE.createInstance(), "Remove any number of storage counters from {this}")); + this.addAbility(ability); + } + + public SubterraneanHangar(final SubterraneanHangar card) { + super(card); + } + + @Override + public SubterraneanHangar copy() { + return new SubterraneanHangar(this); + } +} diff --git a/Mage.Sets/src/mage/sets/mirage/ForbiddenCrypt.java b/Mage.Sets/src/mage/sets/mirage/ForbiddenCrypt.java index 321f592e935..e886dc432b5 100644 --- a/Mage.Sets/src/mage/sets/mirage/ForbiddenCrypt.java +++ b/Mage.Sets/src/mage/sets/mirage/ForbiddenCrypt.java @@ -89,11 +89,6 @@ class ForbiddenCryptDrawCardReplacementEffect extends ReplacementEffectImpl { public ForbiddenCryptDrawCardReplacementEffect copy() { return new ForbiddenCryptDrawCardReplacementEffect(this); } - - @Override - public boolean apply(Game game, Ability source) { - return true; - } @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { @@ -119,9 +114,14 @@ class ForbiddenCryptDrawCardReplacementEffect extends ReplacementEffectImpl { return false; } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.DRAW_CARD; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - return event.getType() == EventType.DRAW_CARD && event.getPlayerId().equals(source.getControllerId()); + return event.getPlayerId().equals(source.getControllerId()); } } diff --git a/Mage.Sets/src/mage/sets/mirage/GravebaneZombie.java b/Mage.Sets/src/mage/sets/mirage/GravebaneZombie.java index 210d3155ffb..e64a6e958c5 100644 --- a/Mage.Sets/src/mage/sets/mirage/GravebaneZombie.java +++ b/Mage.Sets/src/mage/sets/mirage/GravebaneZombie.java @@ -94,18 +94,15 @@ class GravebaneZombieEffect extends ReplacementEffectImpl { } return false; } - + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.ZONE_CHANGE; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == EventType.ZONE_CHANGE && event.getTargetId().equals(source.getSourceId())) { - return ((ZoneChangeEvent) event).isDiesEvent(); - } - return false; - } - - @Override - public boolean apply(Game game, Ability source) { - return true; + return event.getTargetId().equals(source.getSourceId()) && ((ZoneChangeEvent) event).isDiesEvent(); } @Override diff --git a/Mage.Sets/src/mage/sets/mirrodin/Bonesplitter.java b/Mage.Sets/src/mage/sets/mirrodin/Bonesplitter.java index 7e0283aeb0c..ccf8f2c157c 100644 --- a/Mage.Sets/src/mage/sets/mirrodin/Bonesplitter.java +++ b/Mage.Sets/src/mage/sets/mirrodin/Bonesplitter.java @@ -48,6 +48,8 @@ public class Bonesplitter extends CardImpl { super(ownerId, 146, "Bonesplitter", Rarity.COMMON, new CardType[]{CardType.ARTIFACT}, "{1}"); this.expansionSetCode = "MRD"; this.subtype.add("Equipment"); + + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(2, 0))); this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(1))); } diff --git a/Mage.Sets/src/mage/sets/mirrodin/ChromaticSphere.java b/Mage.Sets/src/mage/sets/mirrodin/ChromaticSphere.java index b2f02a3e621..0d8ee852342 100644 --- a/Mage.Sets/src/mage/sets/mirrodin/ChromaticSphere.java +++ b/Mage.Sets/src/mage/sets/mirrodin/ChromaticSphere.java @@ -28,16 +28,15 @@ package mage.sets.mirrodin; import java.util.UUID; - -import mage.constants.CardType; -import mage.constants.Rarity; -import mage.abilities.Ability; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.mana.AnyColorManaAbility; +import mage.abilities.mana.ManaAbility; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; /** * @@ -48,10 +47,13 @@ public class ChromaticSphere extends CardImpl { public ChromaticSphere(UUID ownerId) { super(ownerId, 151, "Chromatic Sphere", Rarity.COMMON, new CardType[]{CardType.ARTIFACT}, "{1}"); this.expansionSetCode = "MRD"; - Ability ability = new AnyColorManaAbility(new GenericManaCost(1)); + + // {1}, {T}, Sacrifice Chromatic Sphere: Add one mana of any color to your mana pool. Draw a card. + ManaAbility ability = new AnyColorManaAbility(new GenericManaCost(1)); ability.addCost(new TapSourceCost()); ability.addCost(new SacrificeSourceCost()); ability.addEffect(new DrawCardSourceControllerEffect(1)); + ability.setUndoPossible(false); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/sets/mirrodin/DampingMatrix.java b/Mage.Sets/src/mage/sets/mirrodin/DampingMatrix.java index ca28187abe7..491766f4fd2 100644 --- a/Mage.Sets/src/mage/sets/mirrodin/DampingMatrix.java +++ b/Mage.Sets/src/mage/sets/mirrodin/DampingMatrix.java @@ -89,11 +89,6 @@ class DampingMatrixEffect extends ReplacementEffectImpl { super(effect); } - @Override - public boolean apply(Game game, Ability source) { - return true; - } - @Override public DampingMatrixEffect copy() { return new DampingMatrixEffect(this); @@ -103,16 +98,19 @@ class DampingMatrixEffect extends ReplacementEffectImpl { public boolean replaceEvent(GameEvent event, Ability source, Game game) { return true; } - + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.ACTIVATE_ABILITY; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == EventType.ACTIVATE_ABILITY) { - MageObject object = game.getObject(event.getSourceId()); - if (object instanceof Permanent && filter.match((Permanent)object, game)) { - Ability ability = object.getAbilities().get(event.getTargetId()); - if (ability != null && !(ability instanceof ManaAbility)) { - return true; - } + MageObject object = game.getObject(event.getSourceId()); + if (object instanceof Permanent && filter.match((Permanent)object, game)) { + Ability ability = object.getAbilities().get(event.getTargetId()); + if (ability != null && !(ability instanceof ManaAbility)) { + return true; } } return false; diff --git a/Mage.Sets/src/mage/sets/mirrodin/IsochronScepter.java b/Mage.Sets/src/mage/sets/mirrodin/IsochronScepter.java index a1b31dbabfd..2e723551388 100644 --- a/Mage.Sets/src/mage/sets/mirrodin/IsochronScepter.java +++ b/Mage.Sets/src/mage/sets/mirrodin/IsochronScepter.java @@ -109,7 +109,7 @@ class IsochronScepterImprintEffect extends OneShotEffect { && controller.choose(Outcome.Benefit, controller.getHand(), target, game)) { Card card = controller.getHand().get(target.getFirstTarget(), game); if (card != null) { - controller.moveCardToExileWithInfo(card, source.getSourceId(), sourcePermanent.getName() +" (Imprint)", source.getSourceId(), game, Zone.HAND, true); + controller.moveCardToExileWithInfo(card, source.getSourceId(), sourcePermanent.getIdName() +" (Imprint)", source.getSourceId(), game, Zone.HAND, true); Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent != null) { permanent.imprint(card.getId(), game); diff --git a/Mage.Sets/src/mage/sets/mirrodin/KrarksThumb.java b/Mage.Sets/src/mage/sets/mirrodin/KrarksThumb.java index efd82bfd8e9..fda4d43fcc2 100644 --- a/Mage.Sets/src/mage/sets/mirrodin/KrarksThumb.java +++ b/Mage.Sets/src/mage/sets/mirrodin/KrarksThumb.java @@ -27,6 +27,7 @@ */ package mage.sets.mirrodin; +import java.util.Random; import java.util.UUID; import mage.constants.CardType; import mage.constants.Duration; @@ -80,7 +81,11 @@ class KrarksThumbEffect extends ReplacementEffectImpl { public boolean replaceEvent(GameEvent event, Ability source, Game game) { Player player = game.getPlayer(event.getPlayerId()); if (player != null) { - boolean secondCoinFlip = player.flipCoin(game, event.getAppliedEffects()); + // because second flip is ignored it may not be done by the player method + boolean secondCoinFlip = new Random().nextBoolean(); + if (!game.isSimulation()) { + game.informPlayers("[Flip a coin] " + player.getLogName() + (secondCoinFlip ? " won (head)." : " lost (tail).")); + } if (player.chooseUse(outcome, "Ignore the first coin flip?", game)) { event.setFlag(secondCoinFlip); game.informPlayers(new StringBuilder(player.getLogName()).append(" ignores the first coin flip.").toString()); @@ -91,12 +96,14 @@ class KrarksThumbEffect extends ReplacementEffectImpl { return false; } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.FLIP_COIN; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == GameEvent.EventType.FLIP_COIN && source.getControllerId().equals(event.getPlayerId())) { - return true; - } - return false; + return source.getControllerId().equals(event.getPlayerId()); } @Override diff --git a/Mage.Sets/src/mage/sets/mirrodin/SoulFoundry.java b/Mage.Sets/src/mage/sets/mirrodin/SoulFoundry.java index c505eaed3e6..cd94be9ca31 100644 --- a/Mage.Sets/src/mage/sets/mirrodin/SoulFoundry.java +++ b/Mage.Sets/src/mage/sets/mirrodin/SoulFoundry.java @@ -130,7 +130,7 @@ class SoulFoundryImprintEffect extends OneShotEffect { && controller.choose(Outcome.Benefit, controller.getHand(), target, game)) { Card card = controller.getHand().get(target.getFirstTarget(), game); if (card != null) { - controller.moveCardToExileWithInfo(card, source.getSourceId(), sourcePermanent.getName() + " (Imprint)", source.getSourceId(), game, Zone.HAND, true); + controller.moveCardToExileWithInfo(card, source.getSourceId(), sourcePermanent.getIdName() + " (Imprint)", source.getSourceId(), game, Zone.HAND, true); Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent != null) { permanent.imprint(card.getId(), game); diff --git a/Mage.Sets/src/mage/sets/mirrodin/TelJiladStylus.java b/Mage.Sets/src/mage/sets/mirrodin/TelJiladStylus.java new file mode 100644 index 00000000000..b6a5e99a576 --- /dev/null +++ b/Mage.Sets/src/mage/sets/mirrodin/TelJiladStylus.java @@ -0,0 +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.sets.mirrodin; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.PutOnLibraryTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.filter.FilterPermanent; +import mage.filter.predicate.other.OwnerPredicate; +import mage.target.TargetPermanent; + +/** + * + * @author LevelX2 + */ +public class TelJiladStylus extends CardImpl { + + private final static FilterPermanent filter = new FilterPermanent(); + + static { + filter.add(new OwnerPredicate(TargetController.YOU)); + } + + public TelJiladStylus(UUID ownerId) { + super(ownerId, 260, "Tel-Jilad Stylus", Rarity.UNCOMMON, new CardType[]{CardType.ARTIFACT}, "{1}"); + this.expansionSetCode = "MRD"; + + // {T}: Put target permanent you own on the bottom of your library. + Effect effect = new PutOnLibraryTargetEffect(false,"put target permanent you own on the bottom of your library"); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new TapSourceCost()); + ability.addTarget(new TargetPermanent(filter)); + this.addAbility(ability); + } + + public TelJiladStylus(final TelJiladStylus card) { + super(card); + } + + @Override + public TelJiladStylus copy() { + return new TelJiladStylus(this); + } +} diff --git a/Mage.Sets/src/mage/sets/mirrodinbesieged/MelirasKeepers.java b/Mage.Sets/src/mage/sets/mirrodinbesieged/MelirasKeepers.java index 81f77ae8f91..899228b0ee5 100644 --- a/Mage.Sets/src/mage/sets/mirrodinbesieged/MelirasKeepers.java +++ b/Mage.Sets/src/mage/sets/mirrodinbesieged/MelirasKeepers.java @@ -36,7 +36,7 @@ import mage.constants.Zone; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; import mage.cards.CardImpl; import mage.game.Game; import mage.game.events.GameEvent; @@ -57,6 +57,7 @@ public class MelirasKeepers extends CardImpl { this.power = new MageInt(4); this.toughness = new MageInt(4); + // Melira's Keepers can't have counters placed on it this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new MelirasKeepersEffect())); } @@ -71,7 +72,7 @@ public class MelirasKeepers extends CardImpl { } -class MelirasKeepersEffect extends ReplacementEffectImpl { +class MelirasKeepersEffect extends ContinuousRuleModifyingEffectImpl { public MelirasKeepersEffect() { super(Duration.WhileOnBattlefield, Outcome.PreventDamage); @@ -82,27 +83,19 @@ class MelirasKeepersEffect extends ReplacementEffectImpl { super(effect); } - @Override - public boolean apply(Game game, Ability source) { - return true; - } - @Override public MelirasKeepersEffect copy() { return new MelirasKeepersEffect(this); } - + @Override - public boolean replaceEvent(GameEvent event, Ability source, Game game) { - return true; + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.ADD_COUNTER; } - + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == EventType.ADD_COUNTER && event.getTargetId().equals(source.getSourceId())) { - return true; - } - return false; + return event.getTargetId().equals(source.getSourceId()); } } diff --git a/Mage.Sets/src/mage/sets/morningtide/BramblewoodParagon.java b/Mage.Sets/src/mage/sets/morningtide/BramblewoodParagon.java index ba50f12ecfd..51657bef406 100644 --- a/Mage.Sets/src/mage/sets/morningtide/BramblewoodParagon.java +++ b/Mage.Sets/src/mage/sets/morningtide/BramblewoodParagon.java @@ -99,24 +99,19 @@ class BramblewoodParagonReplacementEffect extends ReplacementEffectImpl { BramblewoodParagonReplacementEffect(BramblewoodParagonReplacementEffect effect) { super(effect); } - + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD) { - Permanent creature = game.getPermanent(event.getTargetId()); - if (creature != null && creature.getControllerId().equals(source.getControllerId()) - && creature.getCardType().contains(CardType.CREATURE) - && creature.hasSubtype("Warrior") - && !event.getTargetId().equals(source.getSourceId())) { - return true; - } - } - return false; - } - - @Override - public boolean apply(Game game, Ability source) { - return false; + Permanent creature = game.getPermanent(event.getTargetId()); + return creature != null && creature.getControllerId().equals(source.getControllerId()) + && creature.getCardType().contains(CardType.CREATURE) + && creature.hasSubtype("Warrior") + && !event.getTargetId().equals(source.getSourceId()); } @Override diff --git a/Mage.Sets/src/mage/sets/morningtide/OonasBlackguard.java b/Mage.Sets/src/mage/sets/morningtide/OonasBlackguard.java index 9e5d846240b..69d1fd40a34 100644 --- a/Mage.Sets/src/mage/sets/morningtide/OonasBlackguard.java +++ b/Mage.Sets/src/mage/sets/morningtide/OonasBlackguard.java @@ -31,7 +31,6 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; -import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.ReplacementEffectImpl; @@ -47,6 +46,7 @@ import mage.counters.CounterType; import mage.game.Game; import mage.game.events.DamagedPlayerEvent; import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; import mage.game.permanent.Permanent; import mage.target.targetpointer.FixedTarget; @@ -95,16 +95,19 @@ class OonasBlackguardReplacementEffect extends ReplacementEffectImpl { super(effect); } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.ENTERS_THE_BATTLEFIELD; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD) { - Permanent creature = game.getPermanent(event.getTargetId()); - if (creature != null && creature.getControllerId().equals(source.getControllerId()) - && creature.getCardType().contains(CardType.CREATURE) - && creature.getSubtype().contains("Rogue") - && !event.getTargetId().equals(source.getSourceId())) { - return true; - } + Permanent creature = game.getPermanent(event.getTargetId()); + if (creature != null && creature.getControllerId().equals(source.getControllerId()) + && creature.getCardType().contains(CardType.CREATURE) + && creature.getSubtype().contains("Rogue") + && !event.getTargetId().equals(source.getSourceId())) { + return true; } return false; } diff --git a/Mage.Sets/src/mage/sets/morningtide/PrimalBeyond.java b/Mage.Sets/src/mage/sets/morningtide/PrimalBeyond.java new file mode 100644 index 00000000000..c58aba7dd96 --- /dev/null +++ b/Mage.Sets/src/mage/sets/morningtide/PrimalBeyond.java @@ -0,0 +1,121 @@ +/* + * 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.morningtide; + +import java.util.UUID; +import mage.ConditionalMana; +import mage.MageObject; +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.common.AsEntersBattlefieldAbility; +import mage.abilities.condition.Condition; +import mage.abilities.costs.common.RevealTargetFromHandCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.common.TapSourceUnlessPaysEffect; +import mage.abilities.mana.ColorlessManaAbility; +import mage.abilities.mana.ConditionalAnyColorManaAbility; +import mage.abilities.mana.builder.ConditionalManaBuilder; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.FilterCard; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.game.Game; + +import mage.target.common.TargetCardInHand; + +/** + * + * @author TGower + */ +public class PrimalBeyond extends CardImpl { + + private static final FilterCard filter = new FilterCard("a Elemental card from your hand"); + + static { + filter.add(new SubtypePredicate("Elemental")); + } + + + public PrimalBeyond(UUID ownerId) { + super(ownerId, 149, "Primal Beyond", Rarity.RARE, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "MOR"; + + // As Primal Beyond enters the battlefield, you may reveal an Elemental card from your hand. If you don't, Primal Beyond enters the battlefield tapped. + this.addAbility(new AsEntersBattlefieldAbility(new TapSourceUnlessPaysEffect(new RevealTargetFromHandCost(new TargetCardInHand(filter))), "you may reveal a Elemental card from your hand. If you don't, {this} enters the battlefield tapped")); + // {tap}: Add {1} to your mana pool. + this.addAbility(new ColorlessManaAbility()); + // {tap}: Add one mana of any color to your mana pool. Spend this mana only to cast an Elemental spell or activate an ability of an Elemental. + Ability ability = new ConditionalAnyColorManaAbility(new TapSourceCost(), 1, new PrimalBeyondManaBuilder(), true); + this.addAbility(ability); + } + + public PrimalBeyond(final PrimalBeyond card) { + super(card); + } + + @Override + public PrimalBeyond copy() { + return new PrimalBeyond(this); + } +} + + +class PrimalBeyondManaBuilder extends ConditionalManaBuilder { + + @Override + public ConditionalMana build(Object... options) { + return new PrimalBeyondConditionalMana(this.mana); + } + + @Override + public String getRule() { + return "Spend this mana only to cast Elemental spells or activate abilities of Elementals"; + } +} + +class PrimalBeyondConditionalMana extends ConditionalMana { + + public PrimalBeyondConditionalMana(Mana mana) { + super(mana); + this.staticText = "Spend this mana only to cast Elemental spells or activate abilities of Elementals"; + addCondition(new PrimalBeyondManaCondition()); + } +} + +class PrimalBeyondManaCondition implements Condition { + + @Override + public boolean apply(Game game, Ability source) { + MageObject object = game.getObject(source.getSourceId()); + if (object != null && object.hasSubtype("Elemental")) { + return true; + } + return false; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/morningtide/SageOfFables.java b/Mage.Sets/src/mage/sets/morningtide/SageOfFables.java index 813fcd3af38..c7a423909b4 100644 --- a/Mage.Sets/src/mage/sets/morningtide/SageOfFables.java +++ b/Mage.Sets/src/mage/sets/morningtide/SageOfFables.java @@ -91,19 +91,19 @@ class SageOfFablesReplacementEffect extends ReplacementEffectImpl { SageOfFablesReplacementEffect(SageOfFablesReplacementEffect effect) { super(effect); } - + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD) { - Permanent creature = game.getPermanent(event.getTargetId()); - if (creature != null && creature.getControllerId().equals(source.getControllerId()) - && creature.getCardType().contains(CardType.CREATURE) - && creature.getSubtype().contains("Wizard") - && !event.getTargetId().equals(source.getSourceId())) { - return true; - } - } - return false; + Permanent creature = game.getPermanent(event.getTargetId()); + return creature != null && creature.getControllerId().equals(source.getControllerId()) + && creature.getCardType().contains(CardType.CREATURE) + && creature.getSubtype().contains("Wizard") + && !event.getTargetId().equals(source.getSourceId()); } @Override diff --git a/Mage.Sets/src/mage/sets/nemesis/OraclesAttendants.java b/Mage.Sets/src/mage/sets/nemesis/OraclesAttendants.java index a7f5e850f65..d87c60cee96 100644 --- a/Mage.Sets/src/mage/sets/nemesis/OraclesAttendants.java +++ b/Mage.Sets/src/mage/sets/nemesis/OraclesAttendants.java @@ -42,6 +42,7 @@ import mage.constants.Zone; import mage.game.Game; import mage.game.events.DamageCreatureEvent; import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; import mage.game.permanent.Permanent; import mage.target.TargetSource; import mage.target.common.TargetCreaturePermanent; @@ -101,11 +102,6 @@ class OraclesAttendantsReplacementEffect extends ReplacementEffectImpl { public void init(Ability source, Game game) { this.targetSource.choose(Outcome.PreventDamage, source.getControllerId(), source.getSourceId(), game); } - - @Override - public boolean apply(Game game, Ability source) { - return true; - } @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { @@ -118,14 +114,15 @@ class OraclesAttendantsReplacementEffect extends ReplacementEffectImpl { return false; } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.DAMAGE_CREATURE; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == GameEvent.EventType.DAMAGE_CREATURE - && event.getTargetId().equals(source.getFirstTarget()) - && event.getSourceId().equals(targetSource.getFirstTarget())) { - return true; - } - return false; + return event.getTargetId().equals(source.getFirstTarget()) + && event.getSourceId().equals(targetSource.getFirstTarget()); } } diff --git a/Mage.Sets/src/mage/sets/nemesis/RathsEdge.java b/Mage.Sets/src/mage/sets/nemesis/RathsEdge.java new file mode 100644 index 00000000000..b4b8f28c357 --- /dev/null +++ b/Mage.Sets/src/mage/sets/nemesis/RathsEdge.java @@ -0,0 +1,77 @@ +/* + * 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.nemesis; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.mana.ColorlessManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterControlledLandPermanent; +import mage.target.common.TargetControlledPermanent; +import mage.target.common.TargetCreatureOrPlayer; + +/** + * + * @author anonymous + */ +public class RathsEdge extends CardImpl { + + private static final FilterControlledLandPermanent filter = new FilterControlledLandPermanent("a land"); + + public RathsEdge(UUID ownerId) { + super(ownerId, 142, "Rath's Edge", Rarity.RARE, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "NMS"; + this.supertype.add("Legendary"); + + // {tap}: Add {1} to your mana pool. + this.addAbility(new ColorlessManaAbility()); + // {4}, {tap}, Sacrifice a land: Rath's Edge deals 1 damage to target creature or player. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(1), new ManaCostsImpl<>("{4}")); + ability.addCost(new TapSourceCost()); + ability.addCost(new SacrificeTargetCost(new TargetControlledPermanent(filter))); + ability.addTarget(new TargetCreatureOrPlayer()); + this.addAbility(ability); + } + + public RathsEdge(final RathsEdge card) { + super(card); + } + + @Override + public RathsEdge copy() { + return new RathsEdge(this); + } +} diff --git a/Mage.Sets/src/mage/sets/newphyrexia/DueRespect.java b/Mage.Sets/src/mage/sets/newphyrexia/DueRespect.java index b39778b6064..2fef2672aa1 100644 --- a/Mage.Sets/src/mage/sets/newphyrexia/DueRespect.java +++ b/Mage.Sets/src/mage/sets/newphyrexia/DueRespect.java @@ -91,17 +91,15 @@ class DueRespectEffect extends ReplacementEffectImpl { } return false; } - + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD) { - return true; - } - return false; + return true; } - @Override - public boolean apply(Game game, Ability source) { - return false; - } } diff --git a/Mage.Sets/src/mage/sets/newphyrexia/ExclusionRitual.java b/Mage.Sets/src/mage/sets/newphyrexia/ExclusionRitual.java index 6e59b3509e4..1477e7020d9 100644 --- a/Mage.Sets/src/mage/sets/newphyrexia/ExclusionRitual.java +++ b/Mage.Sets/src/mage/sets/newphyrexia/ExclusionRitual.java @@ -95,7 +95,7 @@ class ExclusionRitualImprintEffect extends OneShotEffect { Permanent targetPermanent = game.getPermanent(targetPointer.getFirst(game, source)); Player controller = game.getPlayer(source.getControllerId()); if (controller != null && sourcePermanent != null && targetPermanent != null) { - controller.moveCardToExileWithInfo(targetPermanent, getId(), sourcePermanent.getName(), source.getSourceId(), game, Zone.BATTLEFIELD, true); + controller.moveCardToExileWithInfo(targetPermanent, getId(), sourcePermanent.getIdName(), source.getSourceId(), game, Zone.BATTLEFIELD, true); sourcePermanent.imprint(targetPermanent.getId(), game); } return true; diff --git a/Mage.Sets/src/mage/sets/newphyrexia/KarnLiberated.java b/Mage.Sets/src/mage/sets/newphyrexia/KarnLiberated.java index 65334e81479..09348348fc0 100644 --- a/Mage.Sets/src/mage/sets/newphyrexia/KarnLiberated.java +++ b/Mage.Sets/src/mage/sets/newphyrexia/KarnLiberated.java @@ -30,6 +30,7 @@ package mage.sets.newphyrexia; import java.util.ArrayList; import java.util.List; import java.util.UUID; +import mage.MageObject; import mage.abilities.Ability; import mage.abilities.DelayedTriggeredAbility; import mage.abilities.LoyaltyAbility; @@ -114,6 +115,10 @@ class KarnLiberatedEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { + MageObject sourceObject = source.getSourceObject(game); + if (sourceObject == null) { + return false; + } List cards = new ArrayList<>(); for (ExileZone zone: game.getExile().getExileZones()) { if (zone.getId().equals(exileId)) { @@ -143,7 +148,7 @@ class KarnLiberatedEffect extends OneShotEffect { } for (Card card: cards) { if ( CardUtil.isPermanentCard(card) && !card.getSubtype().contains("Aura") ) { - game.getExile().add(exileId, "Karn Liberated", card); + game.getExile().add(exileId, sourceObject.getIdName(), card); } } DelayedTriggeredAbility delayedAbility = new KarnLiberatedDelayedTriggeredAbility(exileId); diff --git a/Mage.Sets/src/mage/sets/newphyrexia/MeliraSylvokOutcast.java b/Mage.Sets/src/mage/sets/newphyrexia/MeliraSylvokOutcast.java index 7a363fa84e3..b43ddb45473 100644 --- a/Mage.Sets/src/mage/sets/newphyrexia/MeliraSylvokOutcast.java +++ b/Mage.Sets/src/mage/sets/newphyrexia/MeliraSylvokOutcast.java @@ -99,11 +99,6 @@ class MeliraSylvokOutcastEffect extends ReplacementEffectImpl { super(effect); } - @Override - public boolean apply(Game game, Ability source) { - return true; - } - @Override public MeliraSylvokOutcastEffect copy() { return new MeliraSylvokOutcastEffect(this); @@ -114,12 +109,14 @@ class MeliraSylvokOutcastEffect extends ReplacementEffectImpl { return true; } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.ADD_COUNTER; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == EventType.ADD_COUNTER && event.getData().equals(CounterType.POISON.getName()) && event.getTargetId().equals(source.getControllerId())) { - return true; - } - return false; + return event.getData().equals(CounterType.POISON.getName()) && event.getTargetId().equals(source.getControllerId()); } } @@ -135,11 +132,6 @@ class MeliraSylvokOutcastEffect2 extends ReplacementEffectImpl { super(effect); } - @Override - public boolean apply(Game game, Ability source) { - return true; - } - @Override public MeliraSylvokOutcastEffect2 copy() { return new MeliraSylvokOutcastEffect2(this); @@ -149,13 +141,19 @@ class MeliraSylvokOutcastEffect2 extends ReplacementEffectImpl { public boolean replaceEvent(GameEvent event, Ability source, Game game) { return true; } - + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.ADD_COUNTER; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == EventType.ADD_COUNTER && event.getData().equals(CounterType.M1M1.getName())) { + if (event.getData().equals(CounterType.M1M1.getName())) { Permanent perm = game.getPermanent(event.getTargetId()); - if (perm != null && perm.getCardType().contains(CardType.CREATURE) && perm.getControllerId().equals(source.getControllerId())) + if (perm != null && perm.getCardType().contains(CardType.CREATURE) && perm.getControllerId().equals(source.getControllerId())) { return true; + } } return false; } diff --git a/Mage.Sets/src/mage/sets/newphyrexia/Mindcrank.java b/Mage.Sets/src/mage/sets/newphyrexia/Mindcrank.java index 56411b9a645..cecf7dd574d 100644 --- a/Mage.Sets/src/mage/sets/newphyrexia/Mindcrank.java +++ b/Mage.Sets/src/mage/sets/newphyrexia/Mindcrank.java @@ -54,6 +54,8 @@ public class Mindcrank extends CardImpl { super(ownerId, 144, "Mindcrank", Rarity.UNCOMMON, new CardType[]{CardType.ARTIFACT}, "{2}"); this.expansionSetCode = "NPH"; + // Whenever an opponent loses life, that player puts that many cards from the top of his or her library into his or her graveyard. + // (Damage dealt by sources without infect causes loss of life.) this.addAbility(new MindcrankTriggeredAbility()); } @@ -91,8 +93,10 @@ class MindcrankTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { Set opponents = game.getOpponents(this.getControllerId()); if (opponents.contains(event.getPlayerId())) { - Effect effect = this.getEffects().get(0); - effect.setTargetPointer(new FixedTarget(event.getPlayerId())); + for (Effect effect : this.getEffects()) { + effect.setValue("lostLife", event.getAmount()); + effect.setTargetPointer(new FixedTarget(event.getPlayerId())); + } return true; } return false; @@ -123,7 +127,7 @@ class MindcrankEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player targetPlayer = game.getPlayer(getTargetPointer().getFirst(game, source)); if (targetPlayer != null) { - Integer amount = (Integer) getValue("amount"); + Integer amount = (Integer) getValue("lostLife"); if (amount == null) { amount = 0; } diff --git a/Mage.Sets/src/mage/sets/newphyrexia/PhyrexianIngester.java b/Mage.Sets/src/mage/sets/newphyrexia/PhyrexianIngester.java index f204d40458c..1809c230364 100644 --- a/Mage.Sets/src/mage/sets/newphyrexia/PhyrexianIngester.java +++ b/Mage.Sets/src/mage/sets/newphyrexia/PhyrexianIngester.java @@ -36,6 +36,7 @@ import mage.constants.Rarity; import mage.constants.SubLayer; import mage.constants.Zone; import mage.MageInt; +import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; @@ -108,11 +109,12 @@ class PhyrexianIngesterImprintEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { + MageObject sourceObject = source.getSourceObject(game); + if (controller != null && sourceObject != null) { Permanent sourcePermanent = game.getPermanent(source.getSourceId()); Permanent targetPermanent = game.getPermanent(source.getFirstTarget()); if (targetPermanent != null) { - controller.moveCardToExileWithInfo(targetPermanent, getId(), "Phyrexian Ingester (Imprint)", source.getSourceId(), game, Zone.BATTLEFIELD, true); + controller.moveCardToExileWithInfo(targetPermanent, getId(), sourceObject.getIdName() + " (Imprint)", source.getSourceId(), game, Zone.BATTLEFIELD, true); sourcePermanent.imprint(targetPermanent.getId(), game); return true; } diff --git a/Mage.Sets/src/mage/sets/newphyrexia/PhyrexianUnlife.java b/Mage.Sets/src/mage/sets/newphyrexia/PhyrexianUnlife.java index eedd8bc52eb..2928637381f 100644 --- a/Mage.Sets/src/mage/sets/newphyrexia/PhyrexianUnlife.java +++ b/Mage.Sets/src/mage/sets/newphyrexia/PhyrexianUnlife.java @@ -98,11 +98,6 @@ class PhyrexianUnlifeEffect2 extends ReplacementEffectImpl { return new PhyrexianUnlifeEffect2(this); } - @Override - public boolean apply(Game game, Ability source) { - return true; - } - @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { DamagePlayerEvent damageEvent = (DamagePlayerEvent) event; @@ -119,10 +114,15 @@ class PhyrexianUnlifeEffect2 extends ReplacementEffectImpl { } return true; } - + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.DAMAGE_PLAYER; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == EventType.DAMAGE_PLAYER && event.getPlayerId().equals(source.getControllerId())) { + if (event.getPlayerId().equals(source.getControllerId())) { Player player = game.getPlayer(source.getControllerId()); if (player != null) { // The decision if the player has more than 0 life has to be checked only at start of a combat damage step diff --git a/Mage.Sets/src/mage/sets/newphyrexia/UrabraskTheHidden.java b/Mage.Sets/src/mage/sets/newphyrexia/UrabraskTheHidden.java index 31fbda858a9..45d79931645 100644 --- a/Mage.Sets/src/mage/sets/newphyrexia/UrabraskTheHidden.java +++ b/Mage.Sets/src/mage/sets/newphyrexia/UrabraskTheHidden.java @@ -41,6 +41,7 @@ import mage.cards.CardImpl; import mage.filter.common.FilterControlledCreaturePermanent; import mage.game.Game; import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; import mage.game.permanent.Permanent; /** @@ -91,20 +92,22 @@ class UrabraskTheHiddenEffect extends ReplacementEffectImpl { return false; } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.ENTERS_THE_BATTLEFIELD; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD && game.getOpponents(source.getControllerId()).contains(event.getPlayerId())) { - Card c = game.getCard(event.getTargetId()); - if (c != null && c.getCardType().contains(CardType.CREATURE)) + if (game.getOpponents(source.getControllerId()).contains(event.getPlayerId())) { + Card card = game.getCard(event.getTargetId()); + if (card != null && card.getCardType().contains(CardType.CREATURE)) { return true; + } } return false; } - @Override - public boolean apply(Game game, Ability source) { - return false; - } @Override public UrabraskTheHiddenEffect copy() { diff --git a/Mage.Sets/src/mage/sets/ninthedition/BoilingSeas.java b/Mage.Sets/src/mage/sets/ninthedition/BoilingSeas.java new file mode 100644 index 00000000000..c78108a055d --- /dev/null +++ b/Mage.Sets/src/mage/sets/ninthedition/BoilingSeas.java @@ -0,0 +1,65 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.ninthedition; + +import java.util.UUID; +import mage.abilities.effects.common.DestroyAllEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.FilterPermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; + +/** + * + * @author emerald000 + */ +public class BoilingSeas extends CardImpl { + + private static final FilterPermanent filter = new FilterPermanent("Islands"); + static { + filter.add(new SubtypePredicate("Island")); + } + + public BoilingSeas(UUID ownerId) { + super(ownerId, 178, "Boiling Seas", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{3}{R}"); + this.expansionSetCode = "9ED"; + + // Destroy all Islands. + this.getSpellAbility().addEffect(new DestroyAllEffect(filter)); + } + + public BoilingSeas(final BoilingSeas card) { + super(card); + } + + @Override + public BoilingSeas copy() { + return new BoilingSeas(this); + } +} diff --git a/Mage.Sets/src/mage/sets/ninthedition/EarlyHarvest.java b/Mage.Sets/src/mage/sets/ninthedition/EarlyHarvest.java index 546cc205f7b..73b1e44f7f2 100644 --- a/Mage.Sets/src/mage/sets/ninthedition/EarlyHarvest.java +++ b/Mage.Sets/src/mage/sets/ninthedition/EarlyHarvest.java @@ -71,7 +71,7 @@ class UntapAllLandsTargetEffect extends OneShotEffect { private static final FilterLandPermanent filter = new FilterLandPermanent(); static { - filter.add(Predicates.not(new SupertypePredicate("Basic"))); + filter.add(new SupertypePredicate("Basic")); } public UntapAllLandsTargetEffect() { diff --git a/Mage.Sets/src/mage/sets/ninthedition/ManaClash.java b/Mage.Sets/src/mage/sets/ninthedition/ManaClash.java new file mode 100644 index 00000000000..cfc678f1fd4 --- /dev/null +++ b/Mage.Sets/src/mage/sets/ninthedition/ManaClash.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.ninthedition; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class ManaClash extends mage.sets.fourthedition.ManaClash { + + public ManaClash(UUID ownerId) { + super(ownerId); + this.cardNumber = 203; + this.expansionSetCode = "9ED"; + } + + public ManaClash(final ManaClash card) { + super(card); + } + + @Override + public ManaClash copy() { + return new ManaClash(this); + } +} diff --git a/Mage.Sets/src/mage/sets/ninthedition/StorageMatrix.java b/Mage.Sets/src/mage/sets/ninthedition/StorageMatrix.java index 26540a0fb8d..76871a019db 100644 --- a/Mage.Sets/src/mage/sets/ninthedition/StorageMatrix.java +++ b/Mage.Sets/src/mage/sets/ninthedition/StorageMatrix.java @@ -102,16 +102,18 @@ class StorageMatrixRestrictionEffect extends RestrictionEffect { applies = false; Permanent storageMatrix = game.getPermanent(source.getSourceId()); if (storageMatrix != null && !storageMatrix.isTapped()) { - Choice choiceImpl = new ChoiceImpl(); + Choice choiceImpl = new ChoiceImpl(true); choiceImpl.setMessage("Untap which kind of permanent?"); choiceImpl.setChoices(choice); Player player = game.getPlayer(game.getActivePlayerId()); if(player != null){ while(!player.choose(outcome, choiceImpl, game)) { - // player has to choose + if (player.isInGame()) { + return false; + } } String choosenType = choiceImpl.getChoice(); - game.informPlayers(new StringBuilder(storageMatrix.getName()).append(": ").append(player.getLogName()).append(" chose to untap ").append(choosenType).toString()); + game.informPlayers(storageMatrix.getLogName() + ": " + player.getLogName() + " chose to untap " + choosenType); if(choosenType.equals(CardType.ARTIFACT.toString())){ type = CardType.ARTIFACT; diff --git a/Mage.Sets/src/mage/sets/odyssey/AegisOfHonor.java b/Mage.Sets/src/mage/sets/odyssey/AegisOfHonor.java index becd3df993e..3e138111998 100644 --- a/Mage.Sets/src/mage/sets/odyssey/AegisOfHonor.java +++ b/Mage.Sets/src/mage/sets/odyssey/AegisOfHonor.java @@ -31,7 +31,6 @@ package mage.sets.odyssey; import java.util.UUID; -import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.ManaCostsImpl; @@ -46,26 +45,24 @@ import mage.game.Game; import mage.game.events.GameEvent; import mage.game.stack.Spell; import mage.game.stack.StackObject; -import mage.target.TargetPermanent; +import mage.target.TargetPlayer; /** * @author cbt33 / LevelX2 */ +public class AegisOfHonor extends CardImpl { -public class AegisOfHonor extends CardImpl{ - - public AegisOfHonor(UUID ownerId){ - super(ownerId, 1, "Aegis of Honor", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{W}"); - this.expansionSetCode = "ODY"; - + public AegisOfHonor(UUID ownerId) { + super(ownerId, 1, "Aegis of Honor", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{W}"); + this.expansionSetCode = "ODY"; // {1}: The next time an instant or sorcery spell would deal damage to you this - //turn, that spell deals that damage to its controller instead. - this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new AegisOfHonorEffect(), new ManaCostsImpl("{1}"))); + //turn, that spell deals that damage to its controller instead. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new AegisOfHonorEffect(), new ManaCostsImpl("{1}"))); + } - } - public AegisOfHonor(final AegisOfHonor card) { + public AegisOfHonor(final AegisOfHonor card) { super(card); } @@ -97,11 +94,14 @@ class AegisOfHonorEffect extends RedirectionEffect { return true; } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DAMAGE_PLAYER; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType().equals(GameEvent.EventType.DAMAGE_PLAYER) //Checks for player damage - && event.getTargetId().equals(source.getControllerId())) //Checks to see the damage is to Aegis of Honor's controller - { + if (event.getTargetId().equals(source.getControllerId())) { //Checks to see the damage is to Aegis of Honor's controller Spell spell = null; StackObject stackObject = game.getStack().getStackObject(event.getSourceId()); if (stackObject == null) { @@ -112,7 +112,7 @@ class AegisOfHonorEffect extends RedirectionEffect { } //Checks if damage is from a sorcery or instants if (spell != null && instantOrSorceryfilter.match(spell.getCard(), game)) { - TargetPermanent target = new TargetPermanent(); + TargetPlayer target = new TargetPlayer(); target.add(spell.getControllerId(), game); redirectTarget = target; return true; diff --git a/Mage.Sets/src/mage/sets/odyssey/ChanceEncounter.java b/Mage.Sets/src/mage/sets/odyssey/ChanceEncounter.java new file mode 100644 index 00000000000..d93d7c6b4b0 --- /dev/null +++ b/Mage.Sets/src/mage/sets/odyssey/ChanceEncounter.java @@ -0,0 +1,105 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.odyssey; + +import java.util.UUID; +import mage.abilities.TriggeredAbility; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.condition.common.SourceHasCounterCondition; +import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.effects.common.WinGameSourceControllerEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.game.Game; +import mage.game.events.GameEvent; + +/** + * + * @author LevelX2 + */ +public class ChanceEncounter extends CardImpl { + + public ChanceEncounter(UUID ownerId) { + super(ownerId, 182, "Chance Encounter", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}{R}"); + this.expansionSetCode = "ODY"; + + // Whenever you win a coin flip, put a luck counter on Chance Encounter. + this.addAbility(new ChanceEncounterTriggeredAbility()); + + // At the beginning of your upkeep, if Chance Encounter has ten or more luck counters on it, you win the game. + TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new WinGameSourceControllerEffect(), TargetController.YOU, false); + this.addAbility(new ConditionalTriggeredAbility(ability, new SourceHasCounterCondition(CounterType.LUCK, 10, Integer.MAX_VALUE), + "At the beginning of your upkeep, if {this} has ten or more luck counters on it, you win the game")); + } + + public ChanceEncounter(final ChanceEncounter card) { + super(card); + } + + @Override + public ChanceEncounter copy() { + return new ChanceEncounter(this); + } +} + +class ChanceEncounterTriggeredAbility extends TriggeredAbilityImpl { + + public ChanceEncounterTriggeredAbility() { + super(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.LUCK.createInstance()), false); + } + + public ChanceEncounterTriggeredAbility(final ChanceEncounterTriggeredAbility ability) { + super(ability); + } + + @Override + public ChanceEncounterTriggeredAbility copy() { + return new ChanceEncounterTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.COIN_FLIPPED; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + return this.getControllerId().equals(event.getPlayerId()) && event.getFlag(); + } + + @Override + public String getRule() { + return "Whenever you win a coin flip, " + super.getRule(); + } +} diff --git a/Mage.Sets/src/mage/sets/odyssey/DelayingShield.java b/Mage.Sets/src/mage/sets/odyssey/DelayingShield.java index 132e60bac0f..8d62548220a 100644 --- a/Mage.Sets/src/mage/sets/odyssey/DelayingShield.java +++ b/Mage.Sets/src/mage/sets/odyssey/DelayingShield.java @@ -99,13 +99,13 @@ class DelayingShieldReplacementEffect extends ReplacementEffectImpl { } @Override - public boolean applies(GameEvent event, Ability source, Game game) { - return event.getType() == EventType.DAMAGE_PLAYER && event.getTargetId().equals(source.getControllerId()); + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.DAMAGE_PLAYER; } - + @Override - public boolean apply(Game game, Ability source) { - return true; + public boolean applies(GameEvent event, Ability source, Game game) { + return event.getTargetId().equals(source.getControllerId()); } @Override diff --git a/Mage.Sets/src/mage/sets/onslaught/AstralSlide.java b/Mage.Sets/src/mage/sets/onslaught/AstralSlide.java index 8a87cd35a7a..dbdb507c03d 100644 --- a/Mage.Sets/src/mage/sets/onslaught/AstralSlide.java +++ b/Mage.Sets/src/mage/sets/onslaught/AstralSlide.java @@ -91,7 +91,7 @@ class AstralSlideEffect extends OneShotEffect { Permanent permanent = game.getPermanent(source.getFirstTarget()); if (permanent != null) { UUID exileId = UUID.randomUUID(); - if (controller.moveCardToExileWithInfo(permanent, exileId, sourceObject.getName(), source.getSourceId(), game, Zone.BATTLEFIELD, true)) { + if (controller.moveCardToExileWithInfo(permanent, exileId, sourceObject.getIdName(), source.getSourceId(), game, Zone.BATTLEFIELD, true)) { //create delayed triggered ability AtTheBeginOfNextEndStepDelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new ReturnFromExileEffect(exileId, Zone.BATTLEFIELD, false)); delayedAbility.setSourceId(source.getSourceId()); diff --git a/Mage.Sets/src/mage/sets/onslaught/FeedingFrenzy.java b/Mage.Sets/src/mage/sets/onslaught/FeedingFrenzy.java new file mode 100644 index 00000000000..ff57cf267b9 --- /dev/null +++ b/Mage.Sets/src/mage/sets/onslaught/FeedingFrenzy.java @@ -0,0 +1,72 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.onslaught; + +import java.util.UUID; + +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.ManacostVariableValue; +import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.dynamicvalue.common.SignInversionDynamicValue; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.counters.CounterType; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author openSrcCoder + */ +public class FeedingFrenzy extends CardImpl { + + public FeedingFrenzy(UUID ownerId) { + super(ownerId, 147, "Feeding Frenzy", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{2}{B}"); + this.expansionSetCode = "ONS"; + + // Target creature gets -X/-X until end of turn, where X is the number of Zombies on the battlefield. + DynamicValue x = new PermanentsOnBattlefieldCount(new FilterCreaturePermanent("Zombie", "Zombie on the battlefield"), -1); + this.getSpellAbility().addEffect(new BoostTargetEffect(x, x, Duration.EndOfTurn)); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + } + + public FeedingFrenzy(final FeedingFrenzy card) { + super(card); + } + + @Override + public FeedingFrenzy copy() { + return new FeedingFrenzy(this); + } +} diff --git a/Mage.Sets/src/mage/sets/onslaught/SeasideHaven.java b/Mage.Sets/src/mage/sets/onslaught/SeasideHaven.java new file mode 100644 index 00000000000..193ab18919c --- /dev/null +++ b/Mage.Sets/src/mage/sets/onslaught/SeasideHaven.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.sets.onslaught; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.mana.ColorlessManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.target.common.TargetControlledPermanent; + +/** + * + * @author anonymous + */ +public class SeasideHaven extends CardImpl { + + private static final FilterControlledPermanent filter = new FilterControlledPermanent("Bird"); + + static{ + filter.add(new SubtypePredicate("Bird")); + } + + public SeasideHaven(UUID ownerId) { + super(ownerId, 323, "Seaside Haven", Rarity.UNCOMMON, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "ONS"; + + // {tap}: Add {1} to your mana pool. + this.addAbility(new ColorlessManaAbility()); + // {W}{U}, {tap}, Sacrifice a Bird: Draw a card. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, null, new ManaCostsImpl<>("{W}{U}")); + ability.addCost(new TapSourceCost()); + ability.addCost(new SacrificeTargetCost(new TargetControlledPermanent(filter))); + this.addAbility(ability); + } + + public SeasideHaven(final SeasideHaven card) { + super(card); + } + + @Override + public SeasideHaven copy() { + return new SeasideHaven(this); + } +} diff --git a/Mage.Sets/src/mage/sets/onslaught/StarlitSanctum.java b/Mage.Sets/src/mage/sets/onslaught/StarlitSanctum.java new file mode 100644 index 00000000000..6c46627377c --- /dev/null +++ b/Mage.Sets/src/mage/sets/onslaught/StarlitSanctum.java @@ -0,0 +1,155 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.onslaught; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.Cost; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.mana.ColorlessManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetControlledCreaturePermanent; + +/** + * + * @author anonymous + */ +public class StarlitSanctum extends CardImpl { + + private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("Cleric", "a Cleric creature"); + + public StarlitSanctum(UUID ownerId) { + super(ownerId, 325, "Starlit Sanctum", Rarity.UNCOMMON, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "ONS"; + + // {tap}: Add {1} to your mana pool. + this.addAbility(new ColorlessManaAbility()); + // {W}, {tap}, Sacrifice a Cleric creature: You gain life equal to the sacrificed creature's toughness. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new StarlitSanctumWhiteEffect(), new ManaCostsImpl<>("{W}")); + ability.addCost(new TapSourceCost()); + ability.addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent(filter))); + this.addAbility(ability); + // {B}, {tap}, Sacrifice a Cleric creature: Target player loses life equal to the sacrificed creature's power. + ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new StarlitSanctumBlackEffect(), new ManaCostsImpl<>("{B}")); + ability.addCost(new TapSourceCost()); + ability.addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent(filter))); + this.addAbility(ability); + } + + public StarlitSanctum(final StarlitSanctum card) { + super(card); + } + + @Override + public StarlitSanctum copy() { + return new StarlitSanctum(this); + } +} + +class StarlitSanctumWhiteEffect extends OneShotEffect { + + public StarlitSanctumWhiteEffect() { + super(Outcome.GainLife); + staticText = "You gain life equal to the sacrificed creature's toughness"; + } + + public StarlitSanctumWhiteEffect(final StarlitSanctumWhiteEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + int amount = 0; + for (Cost cost : source.getCosts()) { + if (cost instanceof SacrificeTargetCost && ((SacrificeTargetCost) cost).getPermanents().size() > 0) { + amount = ((SacrificeTargetCost) cost).getPermanents().get(0).getToughness().getValue(); + break; + } + } + if (amount > 0) { + Player player = game.getPlayer(source.getControllerId()); + if (player != null) { + player.gainLife(amount, game); + return true; + } + } + return false; + } + + @Override + public StarlitSanctumWhiteEffect copy() { + return new StarlitSanctumWhiteEffect(this); + } +} + +class StarlitSanctumBlackEffect extends OneShotEffect { + + public StarlitSanctumBlackEffect() { + super(Outcome.Damage); + staticText = "Target player loses life equal to the sacrificed creature's power"; + } + + public StarlitSanctumBlackEffect(final StarlitSanctumBlackEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + int amount = 0; + for (Cost cost : source.getCosts()) { + if (cost instanceof SacrificeTargetCost && ((SacrificeTargetCost) cost).getPermanents().size() > 0) { + amount = ((SacrificeTargetCost) cost).getPermanents().get(0).getPower().getValue(); + break; + } + } + if (amount > 0) { + Player player = game.getPlayer(source.getFirstTarget()); + if (player != null) { + player.damage(amount, source.getSourceId(), game, false, true); + return true; + } + } + return false; + } + + @Override + public StarlitSanctumBlackEffect copy() { + return new StarlitSanctumBlackEffect(this); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/onslaught/UnholyGrotto.java b/Mage.Sets/src/mage/sets/onslaught/UnholyGrotto.java new file mode 100644 index 00000000000..f2cb660c7bc --- /dev/null +++ b/Mage.Sets/src/mage/sets/onslaught/UnholyGrotto.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.sets.onslaught; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.PutOnLibraryTargetEffect; +import mage.abilities.mana.ColorlessManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.target.common.TargetCardInYourGraveyard; + +/** + * + * @author anonymous + */ +public class UnholyGrotto extends CardImpl { + + private static final FilterCard filter = new FilterCard("Zombie card from your graveyard"); + + static { + filter.add(new SubtypePredicate("Zombie")); + } + + public UnholyGrotto(UUID ownerId) { + super(ownerId, 327, "Unholy Grotto", Rarity.RARE, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "ONS"; + + // {tap}: Add {1} to your mana pool. + this.addAbility(new ColorlessManaAbility()); + // {B}, {tap}: Put target Zombie card from your graveyard on top of your library. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new PutOnLibraryTargetEffect(true), new ManaCostsImpl<>("{B}")); + ability.addCost(new TapSourceCost()); + ability.addTarget(new TargetCardInYourGraveyard(filter)); + this.addAbility(ability); + } + + public UnholyGrotto(final UnholyGrotto card) { + super(card); + } + + @Override + public UnholyGrotto copy() { + return new UnholyGrotto(this); + } +} diff --git a/Mage.Sets/src/mage/sets/planarchaos/DawnCharm.java b/Mage.Sets/src/mage/sets/planarchaos/DawnCharm.java index f15dcfc3b63..0a1917f461c 100644 --- a/Mage.Sets/src/mage/sets/planarchaos/DawnCharm.java +++ b/Mage.Sets/src/mage/sets/planarchaos/DawnCharm.java @@ -62,14 +62,14 @@ public class DawnCharm extends CardImpl { this.expansionSetCode = "PLC"; - // Choose one - Prevent all combat damage that would be dealt this turn; or regenerate target creature; or counter target spell that targets you. - this.getSpellAbility().addEffect(new PreventAllDamageByAllEffect(Duration.EndOfTurn)); - + // Choose one - Prevent all combat damage that would be dealt this turn + this.getSpellAbility().addEffect(new PreventAllDamageByAllEffect(Duration.EndOfTurn, true)); + // or regenerate target creature; Mode mode = new Mode(); mode.getEffects().add(new RegenerateTargetEffect()); mode.getTargets().add(new TargetCreaturePermanent()); this.getSpellAbility().addMode(mode); - + // or counter target spell that targets you. mode = new Mode(); mode.getEffects().add(new CounterTargetEffect()); mode.getTargets().add(new TargetSpell(filter)); diff --git a/Mage.Sets/src/mage/sets/planarchaos/DustCorona.java b/Mage.Sets/src/mage/sets/planarchaos/DustCorona.java new file mode 100644 index 00000000000..778136e09d5 --- /dev/null +++ b/Mage.Sets/src/mage/sets/planarchaos/DustCorona.java @@ -0,0 +1,90 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.planarchaos; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesAttachedEffect; +import mage.abilities.effects.common.continuous.BoostEnchantedEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.constants.AttachmentType; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author emerald000 + */ +public class DustCorona extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures with flying"); + static { + filter.add(new AbilityPredicate(FlyingAbility.class)); + } + + public DustCorona(UUID ownerId) { + super(ownerId, 97, "Dust Corona", Rarity.COMMON, new CardType[]{CardType.ENCHANTMENT}, "{R}"); + this.expansionSetCode = "PLC"; + this.subtype.add("Aura"); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + + // Enchanted creature gets +2/+0 and can't be blocked by creatures with flying. + ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEnchantedEffect(2, 0)); + Effect effect = new CantBeBlockedByCreaturesAttachedEffect(Duration.WhileOnBattlefield, filter, AttachmentType.AURA); + effect.setText("and can't be blocked by creatures with flying"); + ability.addEffect(effect); + this.addAbility(ability); + } + + public DustCorona(final DustCorona card) { + super(card); + } + + @Override + public DustCorona copy() { + return new DustCorona(this); + } +} diff --git a/Mage.Sets/src/mage/sets/planarchaos/FrozenAEther.java b/Mage.Sets/src/mage/sets/planarchaos/FrozenAEther.java index 38c4e082ead..39c827a0a17 100644 --- a/Mage.Sets/src/mage/sets/planarchaos/FrozenAEther.java +++ b/Mage.Sets/src/mage/sets/planarchaos/FrozenAEther.java @@ -39,6 +39,7 @@ import mage.constants.Rarity; import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; import mage.game.permanent.Permanent; /** @@ -84,9 +85,14 @@ class FrozenAEtherTapEffect extends ReplacementEffectImpl { return false; } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.ENTERS_THE_BATTLEFIELD; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD && game.getOpponents(source.getControllerId()).contains(event.getPlayerId())) { + if (game.getOpponents(source.getControllerId()).contains(event.getPlayerId())) { Permanent permanent = game.getPermanent(event.getTargetId()); if (permanent != null && (permanent.getCardType().contains(CardType.CREATURE) || @@ -98,11 +104,6 @@ class FrozenAEtherTapEffect extends ReplacementEffectImpl { return false; } - @Override - public boolean apply(Game game, Ability source) { - return false; - } - @Override public FrozenAEtherTapEffect copy() { return new FrozenAEtherTapEffect(this); diff --git a/Mage.Sets/src/mage/sets/planarchaos/IntetTheDreamer.java b/Mage.Sets/src/mage/sets/planarchaos/IntetTheDreamer.java index 4e23186000f..f286cdf5b97 100644 --- a/Mage.Sets/src/mage/sets/planarchaos/IntetTheDreamer.java +++ b/Mage.Sets/src/mage/sets/planarchaos/IntetTheDreamer.java @@ -104,7 +104,7 @@ class IntetTheDreamerExileEffect extends OneShotEffect { MageObject sourceObject = source.getSourceObject(game); if (card != null && sourceObject != null) { UUID exileZoneId = CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter()); - player.moveCardToExileWithInfo(card, exileZoneId, sourceObject.getName(), source.getSourceId(), game, Zone.LIBRARY, false); + player.moveCardToExileWithInfo(card, exileZoneId, sourceObject.getIdName(), source.getSourceId(), game, Zone.LIBRARY, false); card.setFaceDown(true, game); return true; } diff --git a/Mage.Sets/src/mage/sets/planarchaos/LifeAndLimb.java b/Mage.Sets/src/mage/sets/planarchaos/LifeAndLimb.java new file mode 100644 index 00000000000..ef75978269e --- /dev/null +++ b/Mage.Sets/src/mage/sets/planarchaos/LifeAndLimb.java @@ -0,0 +1,158 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.planarchaos; + +import java.util.UUID; +import mage.ObjectColor; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.mana.GreenManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Layer; +import static mage.constants.Layer.AbilityAddingRemovingEffects_6; +import static mage.constants.Layer.PTChangingEffects_7; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.SubLayer; +import mage.constants.Zone; +import mage.filter.FilterPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; + +/** + * + * @author emerald000 + */ +public class LifeAndLimb extends CardImpl { + + public LifeAndLimb(UUID ownerId) { + super(ownerId, 133, "Life and Limb", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{3}{G}"); + this.expansionSetCode = "PLC"; + + // All Forests and all Saprolings are 1/1 green Saproling creatures and Forest lands in addition to their other types. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new LifeAndLimbEffect())); + } + + public LifeAndLimb(final LifeAndLimb card) { + super(card); + } + + @Override + public LifeAndLimb copy() { + return new LifeAndLimb(this); + } +} + +class LifeAndLimbEffect extends ContinuousEffectImpl { + + private static final FilterPermanent filter = new FilterPermanent("All Forests and all Saprolings"); + static { + filter.add(Predicates.or(new SubtypePredicate("Forest"), new SubtypePredicate("Saproling"))); + } + + LifeAndLimbEffect() { + super(Duration.WhileOnBattlefield, Outcome.Neutral); + staticText = "All Forests and all Saprolings are 1/1 green Saproling creatures and Forest lands in addition to their other types"; + } + + LifeAndLimbEffect(final LifeAndLimbEffect effect) { + super(effect); + } + + @Override + public LifeAndLimbEffect copy() { + return new LifeAndLimbEffect(this); + } + + @Override + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + Player player = game.getPlayer(source.getControllerId()); + if (player != null) { + for (Permanent permanent : game.getState().getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) { + switch (layer) { + case TypeChangingEffects_4: + if (!permanent.getCardType().contains(CardType.CREATURE)) { + permanent.getCardType().add(CardType.CREATURE); + } + if (!permanent.getSubtype().contains("Saproling")) { + permanent.getSubtype().add("Saproling"); + } + if (!permanent.getCardType().contains(CardType.LAND)) { + permanent.getCardType().add(CardType.LAND); + } + if (!permanent.getSubtype().contains("Forest")) { + permanent.getSubtype().add("Forest"); + } + break; + case ColorChangingEffects_5: + permanent.getColor().setColor(ObjectColor.GREEN); + break; + case AbilityAddingRemovingEffects_6: + boolean flag = false; + for (Ability ability : permanent.getAbilities(game)) { + if (ability instanceof GreenManaAbility) { + flag = true; + break; + } + } + if (!flag) { + permanent.addAbility(new GreenManaAbility(), source.getSourceId(), game); + } + break; + case PTChangingEffects_7: + if (sublayer.equals(SubLayer.SetPT_7b)) { + permanent.getPower().setValue(1); + permanent.getToughness().setValue(1); + } + break; + } + } + return true; + } + return false; + } + + @Override + public boolean apply(Game game, Ability source) { + return false; + } + + @Override + public boolean hasLayer(Layer layer) { + return layer == Layer.TypeChangingEffects_4 + || layer == Layer.ColorChangingEffects_5 + || layer == Layer.AbilityAddingRemovingEffects_6 + || layer == Layer.PTChangingEffects_7; + } +} diff --git a/Mage.Sets/src/mage/sets/planarchaos/VampiricLink.java b/Mage.Sets/src/mage/sets/planarchaos/VampiricLink.java new file mode 100644 index 00000000000..1cdd62a59fd --- /dev/null +++ b/Mage.Sets/src/mage/sets/planarchaos/VampiricLink.java @@ -0,0 +1,75 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.planarchaos; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.DealsDamageAttachedTriggeredAbility; +import mage.abilities.dynamicvalue.common.NumericSetToEffectValues; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LevelX2 + */ +public class VampiricLink extends CardImpl { + + public VampiricLink(UUID ownerId) { + super(ownerId, 92, "Vampiric Link", Rarity.COMMON, new CardType[]{CardType.ENCHANTMENT}, "{B}"); + this.expansionSetCode = "PLC"; + this.subtype.add("Aura"); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.Detriment)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + + // Whenever enchanted creature deals damage, you gain that much life. + this.addAbility(new DealsDamageAttachedTriggeredAbility(Zone.BATTLEFIELD, new GainLifeEffect(new NumericSetToEffectValues("that much", "damage")), false)); + } + + public VampiricLink(final VampiricLink card) { + super(card); + } + + @Override + public VampiricLink copy() { + return new VampiricLink(this); + } +} diff --git a/Mage.Sets/src/mage/sets/planechase/ArcboundCrusher.java b/Mage.Sets/src/mage/sets/planechase/ArcboundCrusher.java new file mode 100644 index 00000000000..c616edcfcf4 --- /dev/null +++ b/Mage.Sets/src/mage/sets/planechase/ArcboundCrusher.java @@ -0,0 +1,82 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.planechase; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.keyword.ModularAbility; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.counters.CounterType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterArtifactPermanent; +import mage.filter.predicate.permanent.AnotherPredicate; + +/** + * + * @author LevelX2 + */ +public class ArcboundCrusher extends CardImpl { + + private static final FilterPermanent filter = new FilterArtifactPermanent("another artifact"); + + static { + filter.add(new AnotherPredicate()); + } + + public ArcboundCrusher(UUID ownerId) { + super(ownerId, 105, "Arcbound Crusher", Rarity.UNCOMMON, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{4}"); + this.expansionSetCode = "HOP"; + this.subtype.add("Juggernaut"); + this.power = new MageInt(0); + this.toughness = new MageInt(0); + + // Trample + this.addAbility(TrampleAbility.getInstance()); + + // Whenever another artifact enters the battlefield, put a +1/+1 counter on Arcbound Crusher. + this.addAbility(new EntersBattlefieldAllTriggeredAbility( + new AddCountersSourceEffect(CounterType.P1P1.createInstance()), filter)); + + // Modular 1 + this.addAbility(new ModularAbility(this, 1)); + } + + public ArcboundCrusher(final ArcboundCrusher card) { + super(card); + } + + @Override + public ArcboundCrusher copy() { + return new ArcboundCrusher(this); + } +} diff --git a/Mage.Sets/src/mage/sets/planeshift/ForsakenCity.java b/Mage.Sets/src/mage/sets/planeshift/ForsakenCity.java new file mode 100644 index 00000000000..6c811609580 --- /dev/null +++ b/Mage.Sets/src/mage/sets/planeshift/ForsakenCity.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.sets.planeshift; + +import java.util.UUID; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.common.ExileFromHandCost; +import mage.abilities.effects.common.DoIfCostPaid; +import mage.abilities.effects.common.DontUntapInControllersUntapStepSourceEffect; +import mage.abilities.effects.common.UntapSourceEffect; +import mage.abilities.mana.ColorlessManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.target.common.TargetCardInHand; + +/** + * + * @author anonymous + */ +public class ForsakenCity extends CardImpl { + + private static final FilterCard filter = new FilterCard("a card from your hand"); + + public ForsakenCity(UUID ownerId) { + super(ownerId, 139, "Forsaken City", Rarity.RARE, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "PLS"; + + // Forsaken City doesn't untap during your untap step. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new DontUntapInControllersUntapStepSourceEffect())); + // At the beginning of your upkeep, you may exile a card from your hand. If you do, untap Forsaken City. + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new DoIfCostPaid(new UntapSourceEffect(), new ExileFromHandCost(new TargetCardInHand(filter))), TargetController.YOU, true)); + // {tap}: Add one mana of any color to your mana pool. + this.addAbility(new ColorlessManaAbility()); + } + + public ForsakenCity(final ForsakenCity card) { + super(card); + } + + @Override + public ForsakenCity copy() { + return new ForsakenCity(this); + } +} diff --git a/Mage.Sets/src/mage/sets/planeshift/MeteorCrater.java b/Mage.Sets/src/mage/sets/planeshift/MeteorCrater.java new file mode 100644 index 00000000000..813ac559688 --- /dev/null +++ b/Mage.Sets/src/mage/sets/planeshift/MeteorCrater.java @@ -0,0 +1,210 @@ +/* + * 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.planeshift; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import mage.Mana; +import mage.ObjectColor; +import mage.abilities.Abilities; +import mage.abilities.Ability; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.common.ManaEffect; +import mage.abilities.mana.ManaAbility; +import mage.abilities.mana.SimpleManaAbility; +import mage.cards.CardImpl; +import mage.choices.Choice; +import mage.choices.ChoiceImpl; +import mage.constants.CardType; +import mage.constants.ColoredManaSymbol; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterControlledPermanent; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; + +/** + * + * @author anonymous + */ +public class MeteorCrater extends CardImpl { + + public MeteorCrater(UUID ownerId) { + super(ownerId, 140, "Meteor Crater", Rarity.RARE, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "PLS"; + + // {tap}: Choose a color of a permanent you control. Add one mana of that color to your mana pool. + this.addAbility(new SimpleManaAbility(Zone.BATTLEFIELD, new MeteorCraterEffect(), new TapSourceCost())); + } + + public MeteorCrater(final MeteorCrater card) { + super(card); + } + + @Override + public MeteorCrater copy() { + return new MeteorCrater(this); + } +} + +class MeteorCraterEffect extends ManaEffect { + + /*** + * 04/10/2004 You can't choose "colorless". You have to choose one of the five colors. + */ + + private static final FilterControlledPermanent filter = new FilterControlledPermanent(); + + public MeteorCraterEffect() { + super(); + staticText = "Choose a color of a permanent you control. Add one mana of that color to your mana pool"; + } + + public MeteorCraterEffect(final MeteorCraterEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Mana types = getManaTypes(game, source); + Choice choice = new ChoiceImpl(false); + choice.setMessage("Pick a mana color"); + if (types.getBlack() > 0) { + choice.getChoices().add("Black"); + } + if (types.getRed() > 0) { + choice.getChoices().add("Red"); + } + if (types.getBlue() > 0) { + choice.getChoices().add("Blue"); + } + if (types.getGreen() > 0) { + choice.getChoices().add("Green"); + } + if (types.getWhite() > 0) { + choice.getChoices().add("White"); + } + if (types.getAny() > 0) { + choice.getChoices().add("Black"); + choice.getChoices().add("Red"); + choice.getChoices().add("Blue"); + choice.getChoices().add("Green"); + choice.getChoices().add("White"); + } + if (choice.getChoices().size() > 0) { + Player player = game.getPlayer(source.getControllerId()); + if (choice.getChoices().size() == 1) { + choice.setChoice(choice.getChoices().iterator().next()); + } else { + player.choose(outcome, choice, game); + } + if (choice.getChoice() != null) { + Mana mana = new Mana(); + switch (choice.getChoice()) { + case "Black": + mana.setBlack(1); + break; + case "Blue": + mana.setBlue(1); + break; + case "Red": + mana.setRed(1); + break; + case "Green": + mana.setGreen(1); + break; + case "White": + mana.setWhite(1); + break; + } + checkToFirePossibleEvents(mana, game, source); + player.getManaPool().addMana(mana, game, source); + return true; + } + return false; + } + return true; + } + + public List getNetMana(Game game, Ability source) { + List netManas = new ArrayList<>(); + Mana types = getManaTypes(game, source); + if (types.getBlack() > 0) { + netManas.add(new Mana(ColoredManaSymbol.B)); + } + if (types.getRed() > 0) { + netManas.add(new Mana(ColoredManaSymbol.R)); + } + if (types.getBlue() > 0) { + netManas.add(new Mana(ColoredManaSymbol.U)); + } + if (types.getGreen() > 0) { + netManas.add(new Mana(ColoredManaSymbol.G)); + } + if (types.getWhite() > 0) { + netManas.add(new Mana(ColoredManaSymbol.W)); + } + return netManas; + } + + private Mana getManaTypes(Game game, Ability source) { + List controlledPermanents = game.getBattlefield().getActivePermanents(filter, source.getControllerId(), game); + Mana types = new Mana(); + for (Permanent permanent : controlledPermanents) { + ObjectColor color = permanent.getColor(); + if (color.isBlack()) { + types.add(Mana.BlackMana); + } + if (color.isBlue()) { + types.add(Mana.BlueMana); + } + if (color.isGreen()) { + types.add(Mana.GreenMana); + } + if(color.isRed()) { + types.add(Mana.RedMana); + } + if(color.isWhite()) { + types.add(Mana.WhiteMana); + } + } + return types; + } + + @Override + public Mana getMana(Game game, Ability source) { + return null; + } + + @Override + public MeteorCraterEffect copy() { + return new MeteorCraterEffect(this); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/planeshift/SkyshipWeatherlight.java b/Mage.Sets/src/mage/sets/planeshift/SkyshipWeatherlight.java index 341b2d8ab99..4342192abcb 100644 --- a/Mage.Sets/src/mage/sets/planeshift/SkyshipWeatherlight.java +++ b/Mage.Sets/src/mage/sets/planeshift/SkyshipWeatherlight.java @@ -98,7 +98,7 @@ class SkyshipWeatherlightEffect extends SearchEffect { for (UUID cardID : target.getTargets()) { Card card = controller.getLibrary().getCard(cardID, game); if (card != null) { - controller.moveCardToExileWithInfo(card, exileZone, sourceObject.getName(), source.getSourceId(), game, Zone.LIBRARY, true); + controller.moveCardToExileWithInfo(card, exileZone, sourceObject.getIdName(), source.getSourceId(), game, Zone.LIBRARY, true); } } } diff --git a/Mage.Sets/src/mage/sets/planeshift/TerminalMoraine.java b/Mage.Sets/src/mage/sets/planeshift/TerminalMoraine.java new file mode 100644 index 00000000000..2db3a01cc0c --- /dev/null +++ b/Mage.Sets/src/mage/sets/planeshift/TerminalMoraine.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.sets.planeshift; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect; +import mage.abilities.mana.ColorlessManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterBasicLandCard; +import mage.target.common.TargetCardInLibrary; + +/** + * + * @author anonymous + */ +public class TerminalMoraine extends CardImpl { + + private static final FilterBasicLandCard filter = new FilterBasicLandCard(); + + public TerminalMoraine(UUID ownerId) { + super(ownerId, 142, "Terminal Moraine", Rarity.UNCOMMON, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "PLS"; + + // {tap}: Add {1} to your mana pool. + this.addAbility(new ColorlessManaAbility()); + // {2}, {tap}, Sacrifice Terminal Moraine: Search your library for a basic land card and put that card onto the battlefield tapped. Then shuffle your library. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(filter), true, true), new ManaCostsImpl<>("{2}")); + ability.addCost(new TapSourceCost()); + ability.addCost(new SacrificeSourceCost()); + this.addAbility(ability); + } + + public TerminalMoraine(final TerminalMoraine card) { + super(card); + } + + @Override + public TerminalMoraine copy() { + return new TerminalMoraine(this); + } +} diff --git a/Mage.Sets/src/mage/sets/portal/BoilingSeas.java b/Mage.Sets/src/mage/sets/portal/BoilingSeas.java new file mode 100644 index 00000000000..a2c29bcea6f --- /dev/null +++ b/Mage.Sets/src/mage/sets/portal/BoilingSeas.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.portal; + +import java.util.UUID; + +/** + * + * @author emerald000 + */ +public class BoilingSeas extends mage.sets.ninthedition.BoilingSeas { + + public BoilingSeas(UUID ownerId) { + super(ownerId); + this.cardNumber = 124; + this.expansionSetCode = "POR"; + } + + public BoilingSeas(final BoilingSeas card) { + super(card); + } + + @Override + public BoilingSeas copy() { + return new BoilingSeas(this); + } +} diff --git a/Mage.Sets/src/mage/sets/prophecy/ShieldDancer.java b/Mage.Sets/src/mage/sets/prophecy/ShieldDancer.java index c21941250c4..8176e796711 100644 --- a/Mage.Sets/src/mage/sets/prophecy/ShieldDancer.java +++ b/Mage.Sets/src/mage/sets/prophecy/ShieldDancer.java @@ -92,10 +92,14 @@ class ShieldDancerRedirectionEffect extends RedirectionEffect { return new ShieldDancerRedirectionEffect(this); } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.DAMAGE_CREATURE; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == EventType.DAMAGE_CREATURE - && event.getTargetId().equals(source.getSourceId()) + if (event.getTargetId().equals(source.getSourceId()) && event.getSourceId().equals(source.getTargets().get(0).getFirstTarget())) { DamageEvent damageEvent = (DamageEvent) event; if (damageEvent.isCombatDamage()) { diff --git a/Mage.Sets/src/mage/sets/prophecy/WintermoonMesa.java b/Mage.Sets/src/mage/sets/prophecy/WintermoonMesa.java new file mode 100644 index 00000000000..959aa4e37c9 --- /dev/null +++ b/Mage.Sets/src/mage/sets/prophecy/WintermoonMesa.java @@ -0,0 +1,73 @@ +/* + * 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.prophecy; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTappedAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.TapTargetEffect; +import mage.abilities.mana.ColorlessManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.target.common.TargetLandPermanent; + +/** + * + * @author anonymous + */ +public class WintermoonMesa extends CardImpl { + + public WintermoonMesa(UUID ownerId) { + super(ownerId, 143, "Wintermoon Mesa", Rarity.RARE, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "PCY"; + + // Wintermoon Mesa enters the battlefield tapped. + this.addAbility(new EntersBattlefieldTappedAbility()); + // {tap}: Add {1} to your mana pool. + this.addAbility(new ColorlessManaAbility()); + // {2}, {tap}, Sacrifice Wintermoon Mesa: Tap two target lands. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TapTargetEffect(), new ManaCostsImpl<>("{2}")); + ability.addCost(new TapSourceCost()); + ability.addTarget(new TargetLandPermanent(2)); + this.addAbility(ability); + } + + public WintermoonMesa(final WintermoonMesa card) { + super(card); + } + + @Override + public WintermoonMesa copy() { + return new WintermoonMesa(this); + } +} diff --git a/Mage.Sets/src/mage/sets/ravnica/LoxodonGatekeeper.java b/Mage.Sets/src/mage/sets/ravnica/LoxodonGatekeeper.java index 89e44549466..5b4297fba72 100644 --- a/Mage.Sets/src/mage/sets/ravnica/LoxodonGatekeeper.java +++ b/Mage.Sets/src/mage/sets/ravnica/LoxodonGatekeeper.java @@ -40,6 +40,7 @@ import mage.constants.Outcome; import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; import mage.game.permanent.Permanent; @@ -91,10 +92,15 @@ class LoxodonGatekeeperTapEffect extends ReplacementEffectImpl { } return false; } - + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.ENTERS_THE_BATTLEFIELD; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD && game.getOpponents(source.getControllerId()).contains(event.getPlayerId())) { + if (game.getOpponents(source.getControllerId()).contains(event.getPlayerId())) { Permanent permanent = game.getPermanent(event.getTargetId()); if (permanent != null && (permanent.getCardType().contains(CardType.CREATURE) || @@ -106,11 +112,6 @@ class LoxodonGatekeeperTapEffect extends ReplacementEffectImpl { return false; } - @Override - public boolean apply(Game game, Ability source) { - return false; - } - @Override public LoxodonGatekeeperTapEffect copy() { return new LoxodonGatekeeperTapEffect(this); diff --git a/Mage.Sets/src/mage/sets/ravnica/Phytohydra.java b/Mage.Sets/src/mage/sets/ravnica/Phytohydra.java index 8e13c6aa989..13de6e22cae 100644 --- a/Mage.Sets/src/mage/sets/ravnica/Phytohydra.java +++ b/Mage.Sets/src/mage/sets/ravnica/Phytohydra.java @@ -39,6 +39,7 @@ import mage.counters.CounterType; import mage.game.Game; import mage.game.events.DamageCreatureEvent; import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; import mage.game.permanent.Permanent; /** @@ -89,13 +90,15 @@ class PhytohydraEffect extends ReplacementEffectImpl { } return true; } - + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.DAMAGE_CREATURE; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == GameEvent.EventType.DAMAGE_CREATURE && event.getTargetId().equals(source.getSourceId())) { - return true; - } - return false; + return event.getTargetId().equals(source.getSourceId()); } @Override diff --git a/Mage.Sets/src/mage/sets/ravnica/SvogthosTheRestlessTomb.java b/Mage.Sets/src/mage/sets/ravnica/SvogthosTheRestlessTomb.java new file mode 100644 index 00000000000..5afa92f2e30 --- /dev/null +++ b/Mage.Sets/src/mage/sets/ravnica/SvogthosTheRestlessTomb.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.ravnica; + +import java.util.UUID; + +/** + * + * @author anonymous + */ +public class SvogthosTheRestlessTomb extends mage.sets.commander.SvogthosTheRestlessTomb { + + public SvogthosTheRestlessTomb(UUID ownerId) { + super(ownerId); + this.cardNumber = 283; + this.expansionSetCode = "RAV"; + } + + public SvogthosTheRestlessTomb(final SvogthosTheRestlessTomb card) { + super(card); + } + + @Override + public SvogthosTheRestlessTomb copy() { + return new SvogthosTheRestlessTomb(this); + } +} diff --git a/Mage.Sets/src/mage/sets/returntoravnica/DetentionSphere.java b/Mage.Sets/src/mage/sets/returntoravnica/DetentionSphere.java index 487635f102c..dbf86cc492f 100644 --- a/Mage.Sets/src/mage/sets/returntoravnica/DetentionSphere.java +++ b/Mage.Sets/src/mage/sets/returntoravnica/DetentionSphere.java @@ -112,12 +112,12 @@ class DetentionSphereEntersEffect extends OneShotEffect { if (sourceObject != null && exileId != null && targetPermanent != null && controller != null) { if (targetPermanent.getName().isEmpty()) { // face down creature - controller.moveCardToExileWithInfo(targetPermanent, exileId, sourceObject.getName(), source.getSourceId(), game, Zone.BATTLEFIELD, true); + controller.moveCardToExileWithInfo(targetPermanent, exileId, sourceObject.getIdName(), source.getSourceId(), game, Zone.BATTLEFIELD, true); } else { String name = targetPermanent.getName(); for (Permanent permanent : game.getBattlefield().getActivePermanents(source.getControllerId(), game)) { if (permanent != null && permanent.getName().equals(name)) { - controller.moveCardToExileWithInfo(permanent, exileId, sourceObject.getName(), source.getSourceId(), game, Zone.BATTLEFIELD, true); + controller.moveCardToExileWithInfo(permanent, exileId, sourceObject.getIdName(), source.getSourceId(), game, Zone.BATTLEFIELD, true); } } } diff --git a/Mage.Sets/src/mage/sets/returntoravnica/EpicExperiment.java b/Mage.Sets/src/mage/sets/returntoravnica/EpicExperiment.java index 1fdac6a7e3e..b7f0c5c403b 100644 --- a/Mage.Sets/src/mage/sets/returntoravnica/EpicExperiment.java +++ b/Mage.Sets/src/mage/sets/returntoravnica/EpicExperiment.java @@ -101,7 +101,7 @@ class EpicExperimentEffect extends OneShotEffect { for (int i = 0; i < source.getManaCostsToPay().getX(); i++) { if (controller.getLibrary().size() > 0) { Card topCard = controller.getLibrary().getFromTop(game); - controller.moveCardToExileWithInfo(topCard, source.getSourceId(), "Cards exiled by " + sourceObject.getName(), source.getSourceId(), game, Zone.LIBRARY, true); + controller.moveCardToExileWithInfo(topCard, source.getSourceId(), sourceObject.getIdName(), source.getSourceId(), game, Zone.LIBRARY, true); } } // cast the possible cards without paying the mana diff --git a/Mage.Sets/src/mage/sets/returntoravnica/JaceArchitectOfThought.java b/Mage.Sets/src/mage/sets/returntoravnica/JaceArchitectOfThought.java index 8348c5e0dfa..ece1c64a992 100644 --- a/Mage.Sets/src/mage/sets/returntoravnica/JaceArchitectOfThought.java +++ b/Mage.Sets/src/mage/sets/returntoravnica/JaceArchitectOfThought.java @@ -308,7 +308,7 @@ class JaceArchitectOfThoughtEffect3 extends OneShotEffect { UUID targetId = target.getFirstTarget(); Card card = player.getLibrary().remove(targetId, game); if (card != null) { - controller.moveCardToExileWithInfo(card, CardUtil.getCardExileZoneId(game, source), sourcePermanent.getName(), source.getSourceId(), game, Zone.LIBRARY, true); + controller.moveCardToExileWithInfo(card, CardUtil.getCardExileZoneId(game, source), sourcePermanent.getIdName(), source.getSourceId(), game, Zone.LIBRARY, true); } } player.shuffleLibrary(game); diff --git a/Mage.Sets/src/mage/sets/returntoravnica/RestInPeace.java b/Mage.Sets/src/mage/sets/returntoravnica/RestInPeace.java index d4c29e9ca9b..0462939b00b 100644 --- a/Mage.Sets/src/mage/sets/returntoravnica/RestInPeace.java +++ b/Mage.Sets/src/mage/sets/returntoravnica/RestInPeace.java @@ -42,6 +42,7 @@ import mage.constants.Rarity; import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; import mage.game.events.ZoneChangeEvent; import mage.game.permanent.Permanent; import mage.players.Player; @@ -142,11 +143,6 @@ class RestInPeaceReplacementEffect extends ReplacementEffectImpl { return new RestInPeaceReplacementEffect(this); } - @Override - public boolean apply(Game game, Ability source) { - return true; - } - @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { Player controller = game.getPlayer(source.getControllerId()); @@ -167,10 +163,15 @@ class RestInPeaceReplacementEffect extends ReplacementEffectImpl { } return false; } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.ZONE_CHANGE; + } @Override public boolean applies(GameEvent event, Ability source, Game game) { - return event.getType() == GameEvent.EventType.ZONE_CHANGE && ((ZoneChangeEvent)event).getToZone() == Zone.GRAVEYARD; + return ((ZoneChangeEvent)event).getToZone() == Zone.GRAVEYARD; } } diff --git a/Mage.Sets/src/mage/sets/riseoftheeldrazi/EldraziTemple.java b/Mage.Sets/src/mage/sets/riseoftheeldrazi/EldraziTemple.java index 2e689706b11..d677a7c819f 100644 --- a/Mage.Sets/src/mage/sets/riseoftheeldrazi/EldraziTemple.java +++ b/Mage.Sets/src/mage/sets/riseoftheeldrazi/EldraziTemple.java @@ -36,9 +36,10 @@ import mage.MageObject; import mage.Mana; import mage.abilities.Ability; import mage.abilities.condition.Condition; -import mage.abilities.effects.common.BasicManaEffect; -import mage.abilities.mana.BasicManaAbility; +import mage.abilities.costs.common.TapSourceCost; import mage.abilities.mana.ColorlessManaAbility; +import mage.abilities.mana.ConditionalColorlessManaAbility; +import mage.abilities.mana.builder.ConditionalManaBuilder; import mage.cards.CardImpl; import mage.game.Game; @@ -52,8 +53,11 @@ public class EldraziTemple extends CardImpl { super(ownerId, 227, "Eldrazi Temple", Rarity.RARE, new CardType[]{ CardType.LAND }, null); this.expansionSetCode = "ROE"; + // {T}: Add {1} to your mana pool. this.addAbility(new ColorlessManaAbility()); - this.addAbility(new EldraziTempleManaAbility()); + + // {T}: Add {2} to your mana pool. Spend this mana only to cast colorless Eldrazi spells or activate abilities of colorless Eldrazi. + this.addAbility(new ConditionalColorlessManaAbility(new TapSourceCost(), 2, new EldraziTempleManaBuilder())); } public EldraziTemple(final EldraziTemple card) { @@ -66,39 +70,32 @@ public class EldraziTemple extends CardImpl { } } -class EldraziTempleManaAbility extends BasicManaAbility { +class EldraziTempleManaBuilder extends ConditionalManaBuilder { - EldraziTempleManaAbility ( ) { - super(new BasicManaEffect(new EldraziConditionalMana())); - this.netMana.add(new Mana(0,0,0,0,0,2,0)); - } - - EldraziTempleManaAbility ( EldraziTempleManaAbility ability ) { - super(ability); + @Override + public ConditionalMana build(Object... options) { + return new EldraziTempleConditionalMana(this.mana); } @Override - public EldraziTempleManaAbility copy ( ) { - return new EldraziTempleManaAbility(this); + public String getRule() { + return "Spend this mana only to cast colorless Eldrazi spells or activate abilities of colorless Eldrazi"; } } -class EldraziConditionalMana extends ConditionalMana { +class EldraziTempleConditionalMana extends ConditionalMana { - public EldraziConditionalMana() { - super(Mana.ColorlessMana(2)); - staticText = "Spend this mana only to cast colorless Eldrazi spells or activate abilities of colorless Eldrazi"; - addCondition(new EldraziManaCondition()); + public EldraziTempleConditionalMana(Mana mana) { + super(mana); + addCondition(new EldraziTempleCondition()); } } -class EldraziManaCondition implements Condition { +class EldraziTempleCondition implements Condition { + @Override public boolean apply(Game game, Ability source) { MageObject object = game.getObject(source.getSourceId()); - if (object != null && object.hasSubtype("Eldrazi") && !object.getColor().hasColor()) { - return true; - } - return false; + return object != null && object.hasSubtype("Eldrazi") && object.getColor().isColorless(); } } diff --git a/Mage.Sets/src/mage/sets/riseoftheeldrazi/TajuruPreserver.java b/Mage.Sets/src/mage/sets/riseoftheeldrazi/TajuruPreserver.java index 9a22c9cdf4b..f242ffd914d 100644 --- a/Mage.Sets/src/mage/sets/riseoftheeldrazi/TajuruPreserver.java +++ b/Mage.Sets/src/mage/sets/riseoftheeldrazi/TajuruPreserver.java @@ -85,29 +85,27 @@ class TajuruPreserverEffect extends ReplacementEffectImpl { return new TajuruPreserverEffect(this); } - @Override - public boolean apply(Game game, Ability source) { - return true; - } - @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { return true; } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.SACRIFICE_PERMANENT; + } @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == GameEvent.EventType.SACRIFICE_PERMANENT) { - MageObject object = game.getObject(event.getSourceId()); - if (object instanceof PermanentCard) { - if (game.getOpponents(source.getControllerId()).contains(((PermanentCard)object).getControllerId())) { - return true; - } + MageObject object = game.getObject(event.getSourceId()); + if (object instanceof PermanentCard) { + if (game.getOpponents(source.getControllerId()).contains(((PermanentCard)object).getControllerId())) { + return true; } - if (object instanceof Spell) { - if (game.getOpponents(source.getControllerId()).contains(((Spell)object).getControllerId())) { - return true; - } + } + if (object instanceof Spell) { + if (game.getOpponents(source.getControllerId()).contains(((Spell)object).getControllerId())) { + return true; } } return false; diff --git a/Mage.Sets/src/mage/sets/saviorsofkamigawa/KahoMinamoHistorian.java b/Mage.Sets/src/mage/sets/saviorsofkamigawa/KahoMinamoHistorian.java index ec90fd57683..3c514c3b498 100644 --- a/Mage.Sets/src/mage/sets/saviorsofkamigawa/KahoMinamoHistorian.java +++ b/Mage.Sets/src/mage/sets/saviorsofkamigawa/KahoMinamoHistorian.java @@ -122,7 +122,7 @@ class KahoMinamoHistorianEffect extends SearchEffect { for (UUID cardId : target.getTargets()) { Card card = controller.getLibrary().getCard(cardId, game); if (card != null) { - controller.moveCardToExileWithInfo(card, exileZone, sourceObject.getName(), source.getSourceId(), game, Zone.LIBRARY, true); + controller.moveCardToExileWithInfo(card, exileZone, sourceObject.getIdName(), source.getSourceId(), game, Zone.LIBRARY, true); } } } diff --git a/Mage.Sets/src/mage/sets/scarsofmirrodin/GlintHawkIdol.java b/Mage.Sets/src/mage/sets/scarsofmirrodin/GlintHawkIdol.java index 6c912c45296..036480edf6b 100644 --- a/Mage.Sets/src/mage/sets/scarsofmirrodin/GlintHawkIdol.java +++ b/Mage.Sets/src/mage/sets/scarsofmirrodin/GlintHawkIdol.java @@ -69,6 +69,7 @@ public class GlintHawkIdol extends CardImpl { this.addAbility(new EntersBattlefieldControlledTriggeredAbility( Zone.BATTLEFIELD, new BecomesCreatureSourceEffect(new GlintHawkIdolToken(), "", Duration.EndOfTurn), filter, true)); + // {W}: Glint Hawk Idol becomes a 2/2 Bird artifact creature with flying until end of turn. this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BecomesCreatureSourceEffect(new GlintHawkIdolToken(), "", Duration.EndOfTurn), new ColoredManaCost(ColoredManaSymbol.W))); } diff --git a/Mage.Sets/src/mage/sets/scarsofmirrodin/HeavyArbalest.java b/Mage.Sets/src/mage/sets/scarsofmirrodin/HeavyArbalest.java index 814dd794d29..4ec89a1a626 100644 --- a/Mage.Sets/src/mage/sets/scarsofmirrodin/HeavyArbalest.java +++ b/Mage.Sets/src/mage/sets/scarsofmirrodin/HeavyArbalest.java @@ -100,20 +100,19 @@ class HeavyArbalestEffect extends ReplacementEffectImpl { return new HeavyArbalestEffect(this); } - @Override - public boolean apply(Game game, Ability source) { - return false; - } - @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { return true; } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.UNTAP; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (game.getTurn().getStepType() == PhaseStep.UNTAP - && event.getType() == EventType.UNTAP ) { + if (game.getTurn().getStepType() == PhaseStep.UNTAP) { Permanent equipment = game.getPermanent(source.getSourceId()); if (equipment != null && equipment.getAttachedTo() != null) { Permanent equipped = game.getPermanent(equipment.getAttachedTo()); diff --git a/Mage.Sets/src/mage/sets/seventhedition/ManaClash.java b/Mage.Sets/src/mage/sets/seventhedition/ManaClash.java new file mode 100644 index 00000000000..05e2cb58973 --- /dev/null +++ b/Mage.Sets/src/mage/sets/seventhedition/ManaClash.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.seventhedition; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class ManaClash extends mage.sets.fourthedition.ManaClash { + + public ManaClash(UUID ownerId) { + super(ownerId); + this.cardNumber = 202; + this.expansionSetCode = "7ED"; + } + + public ManaClash(final ManaClash card) { + super(card); + } + + @Override + public ManaClash copy() { + return new ManaClash(this); + } +} diff --git a/Mage.Sets/src/mage/sets/seventhedition/SpiritLink.java b/Mage.Sets/src/mage/sets/seventhedition/SpiritLink.java index 9845f487f69..f973d97ec88 100644 --- a/Mage.Sets/src/mage/sets/seventhedition/SpiritLink.java +++ b/Mage.Sets/src/mage/sets/seventhedition/SpiritLink.java @@ -29,20 +29,16 @@ package mage.sets.seventhedition; import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.TriggeredAbilityImpl; -import mage.abilities.effects.Effect; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.common.DealsDamageAttachedTriggeredAbility; +import mage.abilities.dynamicvalue.common.NumericSetToEffectValues; import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.keyword.EnchantAbility; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.Rarity; import mage.constants.Zone; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.permanent.Permanent; -import mage.players.Player; import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; @@ -57,7 +53,6 @@ public class SpiritLink extends CardImpl { this.expansionSetCode = "7ED"; this.subtype.add("Aura"); - // Enchant creature TargetPermanent auraTarget = new TargetCreaturePermanent(); this.getSpellAbility().addTarget(auraTarget); @@ -66,7 +61,7 @@ public class SpiritLink extends CardImpl { this.addAbility(ability); // Whenever enchanted creature deals damage, you gain that much life. - this.addAbility(new SpiritLinkTriggeredAbility()); + this.addAbility(new DealsDamageAttachedTriggeredAbility(Zone.BATTLEFIELD, new GainLifeEffect(new NumericSetToEffectValues("that much", "damage")), false)); } public SpiritLink(final SpiritLink card) { @@ -78,74 +73,3 @@ public class SpiritLink extends CardImpl { return new SpiritLink(this); } } - -class SpiritLinkTriggeredAbility extends TriggeredAbilityImpl { - - public SpiritLinkTriggeredAbility() { - super(Zone.BATTLEFIELD, new SpiritLinkEffect(), false); - } - - public SpiritLinkTriggeredAbility(final SpiritLinkTriggeredAbility ability) { - super(ability); - } - - @Override - public SpiritLinkTriggeredAbility copy() { - return new SpiritLinkTriggeredAbility(this); - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (event.getType().equals(GameEvent.EventType.DAMAGED_CREATURE) - || event.getType().equals(GameEvent.EventType.DAMAGED_PLAYER) - || event.getType().equals(GameEvent.EventType.DAMAGED_PLANESWALKER)) { - Permanent enchantment = game.getPermanent(this.getSourceId()); - if (enchantment == null || enchantment.getAttachedTo() == null) { - return false; - } - Permanent enchanted = game.getPermanent(enchantment.getAttachedTo()); - if (enchanted != null && event.getSourceId().equals(enchanted.getId())) { - for (Effect effect : this.getEffects()) { - effect.setValue("damage", event.getAmount()); - } - return true; - } - } - return false; - } - - @Override - public String getRule() { - return "Whenever enchanted creature deals damage, " + super.getRule(); - } -} - -class SpiritLinkEffect extends OneShotEffect { - - public SpiritLinkEffect() { - super(Outcome.GainLife); - this.staticText = "you gain that much life"; - } - - public SpiritLinkEffect(final SpiritLinkEffect effect) { - super(effect); - } - - @Override - public SpiritLinkEffect copy() { - return new SpiritLinkEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - int amount = (Integer) getValue("damage"); - if (amount > 0) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - controller.gainLife(amount, game); - return true; - } - } - return false; - } -} diff --git a/Mage.Sets/src/mage/sets/shadowmoor/MossbridgeTroll.java b/Mage.Sets/src/mage/sets/shadowmoor/MossbridgeTroll.java index d72317de5d1..9fa0b2ed6ca 100644 --- a/Mage.Sets/src/mage/sets/shadowmoor/MossbridgeTroll.java +++ b/Mage.Sets/src/mage/sets/shadowmoor/MossbridgeTroll.java @@ -78,8 +78,7 @@ public class MossbridgeTroll extends CardImpl { Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostSourceEffect(20, 20, Duration.EndOfTurn), new MossbridgeTrollCost()); ability.setAdditionalCostsRuleVisible(false); this.addAbility(ability); - - + } public MossbridgeTroll(final MossbridgeTroll card) { @@ -103,11 +102,6 @@ class MossbridgeTrollReplacementEffect extends ReplacementEffectImpl { super(effect); } - @Override - public boolean apply(Game game, Ability source) { - return true; - } - @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { Permanent mossbridgeTroll = game.getPermanent(event.getTargetId()); @@ -117,13 +111,14 @@ class MossbridgeTrollReplacementEffect extends ReplacementEffectImpl { return false; } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DESTROY_PERMANENT; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == GameEvent.EventType.DESTROY_PERMANENT - && event.getTargetId() == source.getSourceId()) { - return true; - } - return false; + return event.getTargetId() == source.getSourceId(); } @Override diff --git a/Mage.Sets/src/mage/sets/shadowmoor/PuresightMerrow.java b/Mage.Sets/src/mage/sets/shadowmoor/PuresightMerrow.java index 431d12e7e65..f9b55a50bb7 100644 --- a/Mage.Sets/src/mage/sets/shadowmoor/PuresightMerrow.java +++ b/Mage.Sets/src/mage/sets/shadowmoor/PuresightMerrow.java @@ -29,6 +29,7 @@ package mage.sets.shadowmoor; import java.util.UUID; import mage.MageInt; +import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.UntapSourceCost; @@ -96,14 +97,15 @@ class PuresightMerrowEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { + MageObject sourceObject = source.getSourceObject(game); + if (controller != null && sourceObject != null) { Card card = controller.getLibrary().getFromTop(game); if (card != null) { Cards cards = new CardsImpl(); cards.add(card); controller.lookAtCards("Puresight Merrow", cards, game); if (controller.chooseUse(Outcome.Removal, "Do you wish to exile the card from the top of your library?", game)) { - controller.moveCardToExileWithInfo(card, source.getSourceId(), "Puresight Merrow", source.getSourceId(), game, Zone.LIBRARY, true); + controller.moveCardToExileWithInfo(card, source.getSourceId(), sourceObject.getIdName(), source.getSourceId(), game, Zone.LIBRARY, true); } else { game.informPlayers(controller.getLogName() + " puts the card back on top of their library."); } diff --git a/Mage.Sets/src/mage/sets/shadowmoor/WheelOfSunAndMoon.java b/Mage.Sets/src/mage/sets/shadowmoor/WheelOfSunAndMoon.java index db1f8e3602d..d028787067d 100644 --- a/Mage.Sets/src/mage/sets/shadowmoor/WheelOfSunAndMoon.java +++ b/Mage.Sets/src/mage/sets/shadowmoor/WheelOfSunAndMoon.java @@ -62,7 +62,6 @@ public class WheelOfSunAndMoon extends CardImpl { this.expansionSetCode = "SHM"; this.subtype.add("Aura"); - // Enchant player TargetPlayer auraTarget = new TargetPlayer(); this.getSpellAbility().addTarget(auraTarget); @@ -99,29 +98,27 @@ class WheelOfSunAndMoonEffect extends ReplacementEffectImpl { return new WheelOfSunAndMoonEffect(this); } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.ZONE_CHANGE; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (EventType.ZONE_CHANGE.equals(event.getType())) { - ZoneChangeEvent zEvent = (ZoneChangeEvent) event; - if (zEvent.getToZone().equals(Zone.GRAVEYARD)) { - Card card = game.getCard(event.getTargetId()); - if (card != null) { - Permanent enchantment = game.getPermanent(source.getSourceId()); - if (enchantment != null && enchantment.getAttachedTo() != null && - card.getOwnerId().equals(enchantment.getAttachedTo())) { - return true; - } + ZoneChangeEvent zEvent = (ZoneChangeEvent) event; + if (zEvent.getToZone().equals(Zone.GRAVEYARD)) { + Card card = game.getCard(event.getTargetId()); + if (card != null) { + Permanent enchantment = game.getPermanent(source.getSourceId()); + if (enchantment != null && enchantment.getAttachedTo() != null && + card.getOwnerId().equals(enchantment.getAttachedTo())) { + return true; } } } return false; } - @Override - public boolean apply(Game game, Ability source) { - return true; - } - @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { Player controller = game.getPlayer(source.getControllerId()); diff --git a/Mage.Sets/src/mage/sets/shardsofalara/EmpyrialArchangel.java b/Mage.Sets/src/mage/sets/shardsofalara/EmpyrialArchangel.java index 3ddeb53edc4..4dfdca070c0 100644 --- a/Mage.Sets/src/mage/sets/shardsofalara/EmpyrialArchangel.java +++ b/Mage.Sets/src/mage/sets/shardsofalara/EmpyrialArchangel.java @@ -94,15 +94,13 @@ class EmpyrialArchangelEffect extends ReplacementEffectImpl { } @Override - public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == GameEvent.EventType.DAMAGE_PLAYER && event.getPlayerId().equals(source.getControllerId())) - return true; - return false; + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DAMAGE_PLAYER; } - + @Override - public boolean apply(Game game, Ability source) { - return true; + public boolean applies(GameEvent event, Ability source, Game game) { + return event.getPlayerId().equals(source.getControllerId()); } @Override diff --git a/Mage.Sets/src/mage/sets/shardsofalara/TidehollowSculler.java b/Mage.Sets/src/mage/sets/shardsofalara/TidehollowSculler.java index ef631580a15..f0a2e2f5bd3 100644 --- a/Mage.Sets/src/mage/sets/shardsofalara/TidehollowSculler.java +++ b/Mage.Sets/src/mage/sets/shardsofalara/TidehollowSculler.java @@ -115,7 +115,7 @@ class TidehollowScullerExileEffect extends OneShotEffect { if (controller.choose(Outcome.Exile, opponent.getHand(), target, game)) { Card card = opponent.getHand().get(target.getFirstTarget(), game); if (card != null) { - controller.moveCardToExileWithInfo(card, CardUtil.getObjectExileZoneId(game, sourcePermanent), sourcePermanent.getName(), source.getSourceId(), game, Zone.HAND, true); + controller.moveCardToExileWithInfo(card, CardUtil.getObjectExileZoneId(game, sourcePermanent), sourcePermanent.getIdName(), source.getSourceId(), game, Zone.HAND, true); } } diff --git a/Mage.Sets/src/mage/sets/stronghold/ShamanEnKor.java b/Mage.Sets/src/mage/sets/stronghold/ShamanEnKor.java index 3285803e740..97c5d5349e0 100644 --- a/Mage.Sets/src/mage/sets/stronghold/ShamanEnKor.java +++ b/Mage.Sets/src/mage/sets/stronghold/ShamanEnKor.java @@ -46,6 +46,7 @@ import mage.constants.Zone; import mage.game.Game; import mage.game.events.DamageEvent; import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.TargetSource; @@ -155,10 +156,15 @@ class ShamanEnKorReplacementEffect extends ReplacementEffectImpl { } } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.DAMAGE_CREATURE; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { if (!this.used) { - if (event.getType().equals(GameEvent.EventType.DAMAGE_CREATURE) && targetSource != null) { + if (targetSource != null) { if (event.getSourceId().equals(targetSource.getFirstTarget())) { // check source MageObject object = game.getObject(event.getSourceId()); @@ -220,4 +226,4 @@ class ShamanEnKorReplacementEffect extends ReplacementEffectImpl { public ShamanEnKorReplacementEffect copy() { return new ShamanEnKorReplacementEffect(this); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/sets/tempest/FurnaceOfRath.java b/Mage.Sets/src/mage/sets/tempest/FurnaceOfRath.java index cfbf7d803c5..7e03c9d1f33 100644 --- a/Mage.Sets/src/mage/sets/tempest/FurnaceOfRath.java +++ b/Mage.Sets/src/mage/sets/tempest/FurnaceOfRath.java @@ -84,7 +84,7 @@ class FurnaceOfRathEffect extends ReplacementEffectImpl { } @Override - public boolean applies(GameEvent event, Ability source, Game game) { + public boolean checksEventType(GameEvent event, Game game) { switch (event.getType()) { case DAMAGE_PLAYER: return true; @@ -92,29 +92,16 @@ class FurnaceOfRathEffect extends ReplacementEffectImpl { return true; } return false; - } - + } + @Override - public boolean apply(Game game, Ability source) { + public boolean applies(GameEvent event, Ability source, Game game) { return true; } @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { - DamageEvent damageEvent = (DamageEvent)event; - if (damageEvent.getType() == EventType.DAMAGE_PLAYER) { - Player targetPlayer = game.getPlayer(event.getTargetId()); - if (targetPlayer != null) { - targetPlayer.damage(damageEvent.getAmount()*2, damageEvent.getSourceId(), game, damageEvent.isPreventable(), damageEvent.isCombatDamage(), event.getAppliedEffects()); - return true; - } - } else { - Permanent targetPermanent = game.getPermanent(event.getTargetId()); - if (targetPermanent != null) { - targetPermanent.damage(damageEvent.getAmount()*2, damageEvent.getSourceId(), game, damageEvent.isCombatDamage(), damageEvent.isPreventable(), event.getAppliedEffects()); - return true; - } - } + event.setAmount(2 * event.getAmount()); return false; } } diff --git a/Mage.Sets/src/mage/sets/tempest/LivingDeath.java b/Mage.Sets/src/mage/sets/tempest/LivingDeath.java index 81f109de857..fd01450856a 100644 --- a/Mage.Sets/src/mage/sets/tempest/LivingDeath.java +++ b/Mage.Sets/src/mage/sets/tempest/LivingDeath.java @@ -93,7 +93,7 @@ class LivingDeathEffect extends OneShotEffect { Player player = game.getPlayer(playerId); if (player != null) { for (Card card :player.getGraveyard().getCards(new FilterCreatureCard(), game)) { - controller.moveCardToExileWithInfo(card, source.getSourceId(), sourceObject.getName(), source.getSourceId(), game, Zone.GRAVEYARD, true); + controller.moveCardToExileWithInfo(card, source.getSourceId(), sourceObject.getIdName(), source.getSourceId(), game, Zone.GRAVEYARD, true); } } } diff --git a/Mage.Sets/src/mage/sets/tempest/ReflectingPool.java b/Mage.Sets/src/mage/sets/tempest/ReflectingPool.java index c0c8f643134..005b0e53f88 100644 --- a/Mage.Sets/src/mage/sets/tempest/ReflectingPool.java +++ b/Mage.Sets/src/mage/sets/tempest/ReflectingPool.java @@ -179,6 +179,10 @@ class ReflectingPoolEffect extends ManaEffect { public List getNetMana(Game game, Ability source) { List netManas = new ArrayList<>(); Mana types = getManaTypes(game, source); + if (types.getAny()> 0) { + netManas.add(new Mana(0,0,0,0,0,0,1)); + return netManas; + } if (types.getBlack() > 0) { netManas.add(new Mana(ColoredManaSymbol.B)); } @@ -209,6 +213,9 @@ class ReflectingPoolEffect extends ManaEffect { if (!ability.equals(source) && ability.definesMana()) { for (Mana netMana: ability.getNetMana(game)) { types.add(netMana); + if (netMana.getAny() > 0) { + return types; + } } } } diff --git a/Mage.Sets/src/mage/sets/tempest/RootMaze.java b/Mage.Sets/src/mage/sets/tempest/RootMaze.java index e79acbf4201..36109448c25 100644 --- a/Mage.Sets/src/mage/sets/tempest/RootMaze.java +++ b/Mage.Sets/src/mage/sets/tempest/RootMaze.java @@ -52,7 +52,6 @@ public class RootMaze extends CardImpl { super(ownerId, 144, "Root Maze", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{G}"); this.expansionSetCode = "TMP"; - // Artifacts and lands enter the battlefield tapped. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new RootMazeEffect())); } @@ -85,21 +84,16 @@ class RootMazeEffect extends ReplacementEffectImpl { } return false; } - + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.ENTERS_THE_BATTLEFIELD; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == EventType.ENTERS_THE_BATTLEFIELD) { - Permanent permanent = game.getPermanent(event.getTargetId()); - if (permanent != null && (permanent.getCardType().contains(CardType.LAND) || permanent.getCardType().contains(CardType.ARTIFACT))) { - return true; - } - } - return false; - } - - @Override - public boolean apply(Game game, Ability source) { - return false; + Permanent permanent = game.getPermanent(event.getTargetId()); + return permanent != null && (permanent.getCardType().contains(CardType.LAND) || permanent.getCardType().contains(CardType.ARTIFACT)); } @Override diff --git a/Mage.Sets/src/mage/sets/tenthedition/CephalidConstable.java b/Mage.Sets/src/mage/sets/tenthedition/CephalidConstable.java new file mode 100644 index 00000000000..fbc5884eec5 --- /dev/null +++ b/Mage.Sets/src/mage/sets/tenthedition/CephalidConstable.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.tenthedition; + +import java.util.UUID; + +/** + * + * @author emerald000 + */ +public class CephalidConstable extends mage.sets.judgment.CephalidConstable { + + public CephalidConstable(UUID ownerId) { + super(ownerId); + this.cardNumber = 72; + this.expansionSetCode = "10E"; + } + + public CephalidConstable(final CephalidConstable card) { + super(card); + } + + @Override + public CephalidConstable copy() { + return new CephalidConstable(this); + } +} diff --git a/Mage.Sets/src/mage/sets/tenthedition/ChromaticStar.java b/Mage.Sets/src/mage/sets/tenthedition/ChromaticStar.java index e87f1b20c72..2851ec86340 100644 --- a/Mage.Sets/src/mage/sets/tenthedition/ChromaticStar.java +++ b/Mage.Sets/src/mage/sets/tenthedition/ChromaticStar.java @@ -48,10 +48,14 @@ public class ChromaticStar extends CardImpl { public ChromaticStar(UUID ownerId) { super(ownerId, 314, "Chromatic Star", Rarity.UNCOMMON, new CardType[]{CardType.ARTIFACT}, "{1}"); this.expansionSetCode = "10E"; + + // {1}, {T}, Sacrifice Chromatic Star: Add one mana of any color to your mana pool. Ability ability = new AnyColorManaAbility(new GenericManaCost(1)); ability.addCost(new TapSourceCost()); ability.addCost(new SacrificeSourceCost()); this.addAbility(ability); + + // When Chromatic Star is put into a graveyard from the battlefield, draw a card. this.addAbility(new PutIntoGraveFromBattlefieldSourceTriggeredAbility(new DrawCardSourceControllerEffect(1))); } diff --git a/Mage.Sets/src/mage/sets/thedark/CityOfShadows.java b/Mage.Sets/src/mage/sets/thedark/CityOfShadows.java new file mode 100644 index 00000000000..6e4381050e3 --- /dev/null +++ b/Mage.Sets/src/mage/sets/thedark/CityOfShadows.java @@ -0,0 +1,73 @@ +/* + * 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.thedark; + +import java.util.UUID; +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.ExileTargetCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.mana.DynamicManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.target.common.TargetControlledCreaturePermanent; + +/** + * + * @author anonymous + */ +public class CityOfShadows extends CardImpl { + + public CityOfShadows(UUID ownerId) { + super(ownerId, 113, "City of Shadows", Rarity.RARE, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "DRK"; + + // {tap}, Exile a creature you control: Put a storage counter on City of Shadows. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.STORAGE.createInstance()), new TapSourceCost()); + ability.addCost(new ExileTargetCost(new TargetControlledCreaturePermanent())); + // {tap}: Add {X} to your mana pool, where X is the number of storage counters on City of Shadows. + ability = new DynamicManaAbility(Mana.ColorlessMana, new CountersCount(CounterType.STORAGE), + "{tap}: Add {X} to your mana pool, where X is the number of storage counters on City of Shadows"); + this.addAbility(ability); + } + + public CityOfShadows(final CityOfShadows card) { + super(card); + } + + @Override + public CityOfShadows copy() { + return new CityOfShadows(this); + } +} diff --git a/Mage.Sets/src/mage/sets/thedark/ManaClash.java b/Mage.Sets/src/mage/sets/thedark/ManaClash.java new file mode 100644 index 00000000000..16e9e6dd951 --- /dev/null +++ b/Mage.Sets/src/mage/sets/thedark/ManaClash.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.thedark; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class ManaClash extends mage.sets.fourthedition.ManaClash { + + public ManaClash(UUID ownerId) { + super(ownerId); + this.cardNumber = 71; + this.expansionSetCode = "DRK"; + } + + public ManaClash(final ManaClash card) { + super(card); + } + + @Override + public ManaClash copy() { + return new ManaClash(this); + } +} diff --git a/Mage.Sets/src/mage/sets/theros/AkroanHorse.java b/Mage.Sets/src/mage/sets/theros/AkroanHorse.java index fe4c0b1f05b..014fb58c23a 100644 --- a/Mage.Sets/src/mage/sets/theros/AkroanHorse.java +++ b/Mage.Sets/src/mage/sets/theros/AkroanHorse.java @@ -105,6 +105,7 @@ class AkroanHorseChangeControlEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Target target = new TargetOpponent(); + target.setNotTarget(true); Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { if (controller.chooseTarget(outcome, target, source, game)) { diff --git a/Mage.Sets/src/mage/sets/theros/AshiokNightmareWeaver.java b/Mage.Sets/src/mage/sets/theros/AshiokNightmareWeaver.java index 6b8c0c122cd..f742e0790fb 100644 --- a/Mage.Sets/src/mage/sets/theros/AshiokNightmareWeaver.java +++ b/Mage.Sets/src/mage/sets/theros/AshiokNightmareWeaver.java @@ -126,7 +126,7 @@ class AshiokNightmareWeaverExileEffect extends OneShotEffect { for (int i = 0; i < 3; i++) { Card card = opponent.getLibrary().getFromTop(game); if (card != null) { - controller.moveCardToExileWithInfo(card, exileZone, sourceObject.getName(), source.getSourceId(), game, Zone.LIBRARY, true); + controller.moveCardToExileWithInfo(card, exileZone, sourceObject.getIdName(), source.getSourceId(), game, Zone.LIBRARY, true); } } return true; @@ -275,7 +275,7 @@ class AshiokNightmareWeaverExileAllEffect extends OneShotEffect { for (UUID cardId : cards) { Card card = game.getCard(cardId); if (card != null) { - controller.moveCardToExileWithInfo(card, exileId, sourceObject.getName(), source.getSourceId(), game, Zone.HAND, true); + controller.moveCardToExileWithInfo(card, exileId, sourceObject.getIdName(), source.getSourceId(), game, Zone.HAND, true); } } cards.clear(); @@ -283,7 +283,7 @@ class AshiokNightmareWeaverExileAllEffect extends OneShotEffect { for (UUID cardId :cards) { Card card = game.getCard(cardId); if (card != null) { - controller.moveCardToExileWithInfo(card, exileId, sourceObject.getName(), source.getSourceId(), game, Zone.GRAVEYARD, true); + controller.moveCardToExileWithInfo(card, exileId, sourceObject.getIdName(), source.getSourceId(), game, Zone.GRAVEYARD, true); } } } diff --git a/Mage.Sets/src/mage/sets/theros/CommuneWithTheGods.java b/Mage.Sets/src/mage/sets/theros/CommuneWithTheGods.java index 1a16b219244..e38d8d7c346 100644 --- a/Mage.Sets/src/mage/sets/theros/CommuneWithTheGods.java +++ b/Mage.Sets/src/mage/sets/theros/CommuneWithTheGods.java @@ -56,7 +56,6 @@ public class CommuneWithTheGods extends CardImpl { super(ownerId, 155, "Commune with the Gods", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{1}{G}"); this.expansionSetCode = "THS"; - // Reveal the top five cards of your library. You may put a creature or enchantment card from among them into your hand. Put the rest into your graveyard. this.getSpellAbility().addEffect(new CommuneWithTheGodsEffect()); @@ -119,7 +118,7 @@ class CommuneWithTheGodsEffect extends OneShotEffect { Card card = game.getCard(target.getFirstTarget()); if (card != null) { cards.remove(card); - controller.moveCards(card, Zone.LIBRARY, Zone.GRAVEYARD, source, game); + controller.moveCards(card, Zone.LIBRARY, Zone.HAND, source, game); } } diff --git a/Mage.Sets/src/mage/sets/theros/DaxosOfMeletis.java b/Mage.Sets/src/mage/sets/theros/DaxosOfMeletis.java index d2023b4d810..ee8929301d0 100644 --- a/Mage.Sets/src/mage/sets/theros/DaxosOfMeletis.java +++ b/Mage.Sets/src/mage/sets/theros/DaxosOfMeletis.java @@ -119,7 +119,7 @@ class DaxosOfMeletisEffect extends OneShotEffect { Card card = damagedPlayer.getLibrary().getFromTop(game); if (card != null) { // move card to exile - controller.moveCardToExileWithInfo(card, exileId, sourceObject.getName(), source.getSourceId(), game, Zone.LIBRARY, true); + controller.moveCardToExileWithInfo(card, exileId, sourceObject.getIdName(), source.getSourceId(), game, Zone.LIBRARY, true); // player gains life int cmc = card.getManaCost().convertedManaCost(); if (cmc > 0) { diff --git a/Mage.Sets/src/mage/sets/theros/PsychicIntrusion.java b/Mage.Sets/src/mage/sets/theros/PsychicIntrusion.java index 2376ca65ae7..3ca67cd231b 100644 --- a/Mage.Sets/src/mage/sets/theros/PsychicIntrusion.java +++ b/Mage.Sets/src/mage/sets/theros/PsychicIntrusion.java @@ -135,7 +135,7 @@ class PsychicIntrusionExileEffect extends OneShotEffect { if (card != null) { // move card to exile UUID exileId = CardUtil.getCardExileZoneId(game, source); - controller.moveCardToExileWithInfo(card, exileId, sourceObject.getName(), source.getSourceId(), game, fromHand ? Zone.HAND:Zone.GRAVEYARD, true); + controller.moveCardToExileWithInfo(card, exileId, sourceObject.getIdName(), source.getSourceId(), game, fromHand ? Zone.HAND:Zone.GRAVEYARD, true); // allow to cast the card ContinuousEffect effect = new PsychicIntrusionCastFromExileEffect(); effect.setTargetPointer(new FixedTarget(card.getId())); diff --git a/Mage.Sets/src/mage/sets/theros/PyxisOfPandemonium.java b/Mage.Sets/src/mage/sets/theros/PyxisOfPandemonium.java index 05ebfb9baa6..ce637215919 100644 --- a/Mage.Sets/src/mage/sets/theros/PyxisOfPandemonium.java +++ b/Mage.Sets/src/mage/sets/theros/PyxisOfPandemonium.java @@ -122,7 +122,7 @@ class PyxisOfPandemoniumExileEffect extends OneShotEffect { exileIds.put(exileKey, exileId); } player.moveCardToExileWithInfo(card, exileId, - new StringBuilder(sourceObject.getName() +" (").append(player.getLogName()).append(")").toString(), + new StringBuilder(sourceObject.getIdName() +" (").append(player.getLogName()).append(")").toString(), source.getSourceId(), game, Zone.LIBRARY, true); card.setFaceDown(true, game); } diff --git a/Mage.Sets/src/mage/sets/timeshifted/GrinningTotem.java b/Mage.Sets/src/mage/sets/timeshifted/GrinningTotem.java index 8cd942ebf69..c59d4e01187 100644 --- a/Mage.Sets/src/mage/sets/timeshifted/GrinningTotem.java +++ b/Mage.Sets/src/mage/sets/timeshifted/GrinningTotem.java @@ -117,7 +117,7 @@ class GrinningTotemSearchAndExileEffect extends OneShotEffect { if (you.searchLibrary(targetCard, game, targetOpponent.getId())) { Card card = targetOpponent.getLibrary().remove(targetCard.getFirstTarget(), game); if (card != null) { - you.moveCardToExileWithInfo(card, CardUtil.getCardExileZoneId(game, source), sourcObject != null ? sourcObject.getName() : "", source.getSourceId(), game, Zone.LIBRARY, true); + you.moveCardToExileWithInfo(card, CardUtil.getCardExileZoneId(game, source), sourcObject != null ? sourcObject.getIdName() : "", source.getSourceId(), game, Zone.LIBRARY, true); ContinuousEffect effect = new GrinningTotemMayPlayEffect(); effect.setTargetPointer(new FixedTarget(card.getId())); game.addEffect(effect, source); diff --git a/Mage.Sets/src/mage/sets/timespiral/DeepSeaKraken.java b/Mage.Sets/src/mage/sets/timespiral/DeepSeaKraken.java index fea5aba999d..28b6e618f45 100644 --- a/Mage.Sets/src/mage/sets/timespiral/DeepSeaKraken.java +++ b/Mage.Sets/src/mage/sets/timespiral/DeepSeaKraken.java @@ -40,6 +40,7 @@ import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Rarity; import mage.constants.TargetController; +import mage.constants.Zone; import mage.counters.CounterType; import mage.filter.FilterSpell; import mage.filter.predicate.permanent.ControllerPredicate; @@ -69,7 +70,7 @@ public class DeepSeaKraken extends CardImpl { this.addAbility(new SuspendAbility(9, new ManaCostsImpl("{2}{U}"), this)); // Whenever an opponent casts a spell, if Deep-Sea Kraken is suspended, remove a time counter from it. this.addAbility(new ConditionalTriggeredAbility( - new SpellCastAllTriggeredAbility(new RemoveCounterSourceEffect(CounterType.TIME.createInstance()), filter, false), SuspendedCondition.getInstance(), + new SpellCastAllTriggeredAbility(Zone.EXILED, new RemoveCounterSourceEffect(CounterType.TIME.createInstance()), filter, false, false), SuspendedCondition.getInstance(), "Whenever an opponent casts a spell, if Deep-Sea Kraken is suspended, remove a time counter from it.", false)); } diff --git a/Mage.Sets/src/mage/sets/timespiral/DralnuLichLord.java b/Mage.Sets/src/mage/sets/timespiral/DralnuLichLord.java index abcb883f06a..104eb94b3fa 100644 --- a/Mage.Sets/src/mage/sets/timespiral/DralnuLichLord.java +++ b/Mage.Sets/src/mage/sets/timespiral/DralnuLichLord.java @@ -116,13 +116,13 @@ class DralnuLichLordReplacementEffect extends ReplacementEffectImpl { } @Override - public boolean applies(GameEvent event, Ability source, Game game) { - return event.getType() == GameEvent.EventType.DAMAGE_CREATURE && event.getTargetId().equals(source.getSourceId()); + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DAMAGE_CREATURE; } - + @Override - public boolean apply(Game game, Ability source) { - return true; + public boolean applies(GameEvent event, Ability source, Game game) { + return event.getTargetId().equals(source.getSourceId()); } @Override diff --git a/Mage.Sets/src/mage/sets/timespiral/FlickeringSpirit.java b/Mage.Sets/src/mage/sets/timespiral/FlickeringSpirit.java index 240355f9bd1..93e1dbde31f 100644 --- a/Mage.Sets/src/mage/sets/timespiral/FlickeringSpirit.java +++ b/Mage.Sets/src/mage/sets/timespiral/FlickeringSpirit.java @@ -29,10 +29,16 @@ package mage.sets.timespiral; import java.util.UUID; import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.ExileSourceEffect; +import mage.abilities.effects.common.ReturnToBattlefieldUnderOwnerControlSourceEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Rarity; +import mage.constants.Zone; /** * @@ -49,7 +55,12 @@ public class FlickeringSpirit extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); + // {3}{W}: Exile Flickering Spirit, then return it to the battlefield under its owner's control. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ExileSourceEffect(true), new ManaCostsImpl("{3}{W}")); + ability.addEffect(new ReturnToBattlefieldUnderOwnerControlSourceEffect()); + this.addAbility(ability); + } public FlickeringSpirit(final FlickeringSpirit card) { diff --git a/Mage.Sets/src/mage/sets/timespiral/FortuneThief.java b/Mage.Sets/src/mage/sets/timespiral/FortuneThief.java index c819fd42304..e928af4fd73 100644 --- a/Mage.Sets/src/mage/sets/timespiral/FortuneThief.java +++ b/Mage.Sets/src/mage/sets/timespiral/FortuneThief.java @@ -91,31 +91,28 @@ class FortuneThiefReplacementEffect extends ReplacementEffectImpl { public FortuneThiefReplacementEffect copy() { return new FortuneThiefReplacementEffect(this); } - + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DAMAGE_CAUSES_LIFE_LOSS; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType().equals(GameEvent.EventType.DAMAGE_CAUSES_LIFE_LOSS)) { - Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent != null) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null - && (controller.getLife() > 0) &&(controller.getLife() - event.getAmount()) < 1 - && event.getPlayerId().equals(controller.getId()) - ) { - event.setAmount(controller.getLife() - 1); - //unsure how to make this comply with - // 10/1/2008: The ability doesn't change how much damage is dealt; - // it just changes how much life that damage makes you lose. - // An effect such as Spirit Link will see the full amount of damage being dealt. - } + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent != null) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null + && (controller.getLife() > 0) &&(controller.getLife() - event.getAmount()) < 1 + && event.getPlayerId().equals(controller.getId()) + ) { + event.setAmount(controller.getLife() - 1); + //unsure how to make this comply with + // 10/1/2008: The ability doesn't change how much damage is dealt; + // it just changes how much life that damage makes you lose. + // An effect such as Spirit Link will see the full amount of damage being dealt. } } - - return false; - } - - @Override - public boolean apply(Game game, Ability source) { return false; } diff --git a/Mage.Sets/src/mage/sets/timespiral/FungusSliver.java b/Mage.Sets/src/mage/sets/timespiral/FungusSliver.java new file mode 100644 index 00000000000..b36fbcef7f3 --- /dev/null +++ b/Mage.Sets/src/mage/sets/timespiral/FungusSliver.java @@ -0,0 +1,80 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.timespiral; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.DealtDamageToSourceTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.continuous.GainAbilityAllEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; + +/** + * + * @author emerald000 + */ +public class FungusSliver extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); + static { + filter.add(new SubtypePredicate("Sliver")); + } + + public FungusSliver(UUID ownerId) { + super(ownerId, 195, "Fungus Sliver", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{3}{G}"); + this.expansionSetCode = "TSP"; + this.subtype.add("Fungus"); + this.subtype.add("Sliver"); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // All Sliver creatures have "Whenever this creature is dealt damage, put a +1/+1 counter on it." + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAllEffect( + new DealtDamageToSourceTriggeredAbility(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.P1P1.createInstance(1)), false), + Duration.WhileOnBattlefield, + filter, + "All Sliver creatures have \"Whenever this creature is dealt damage, put a +1/+1 counter on it.\""))); + } + + public FungusSliver(final FungusSliver card) { + super(card); + } + + @Override + public FungusSliver copy() { + return new FungusSliver(this); + } +} diff --git a/Mage.Sets/src/mage/sets/timespiral/LivingEnd.java b/Mage.Sets/src/mage/sets/timespiral/LivingEnd.java index e350f20eacd..398a3e28fc2 100644 --- a/Mage.Sets/src/mage/sets/timespiral/LivingEnd.java +++ b/Mage.Sets/src/mage/sets/timespiral/LivingEnd.java @@ -102,7 +102,7 @@ class LivingEndEffect extends OneShotEffect { Player player = game.getPlayer(playerId); if (player != null) { for (Card card :player.getGraveyard().getCards(new FilterCreatureCard(), game)) { - controller.moveCardToExileWithInfo(card, source.getSourceId(), sourceObject.getName(), source.getSourceId(), game, Zone.GRAVEYARD, true); + controller.moveCardToExileWithInfo(card, source.getSourceId(), sourceObject.getIdName(), source.getSourceId(), game, Zone.GRAVEYARD, true); } } } diff --git a/Mage.Sets/src/mage/sets/timespiral/NorinTheWary.java b/Mage.Sets/src/mage/sets/timespiral/NorinTheWary.java index 6b4964df67d..fc878f375c9 100644 --- a/Mage.Sets/src/mage/sets/timespiral/NorinTheWary.java +++ b/Mage.Sets/src/mage/sets/timespiral/NorinTheWary.java @@ -125,7 +125,7 @@ class NorinTheWaryRemovingEffect extends OneShotEffect { if (controller != null) { Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent != null) { - if (controller.moveCardToExileWithInfo(permanent, source.getSourceId(), permanent.getName(), source.getSourceId(), game, Zone.BATTLEFIELD, true)) { + if (controller.moveCardToExileWithInfo(permanent, source.getSourceId(), permanent.getIdName(), source.getSourceId(), game, Zone.BATTLEFIELD, true)) { //create delayed triggered ability AtTheBeginOfNextEndStepDelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility( new ReturnFromExileEffect(source.getSourceId(), Zone.BATTLEFIELD)); diff --git a/Mage.Sets/src/mage/sets/timespiral/SpiritLoop.java b/Mage.Sets/src/mage/sets/timespiral/SpiritLoop.java index 3760226eb71..3c8a325682e 100644 --- a/Mage.Sets/src/mage/sets/timespiral/SpiritLoop.java +++ b/Mage.Sets/src/mage/sets/timespiral/SpiritLoop.java @@ -32,19 +32,15 @@ import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Rarity; import mage.abilities.Ability; -import mage.abilities.TriggeredAbilityImpl; -import mage.abilities.effects.Effect; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.common.DealsDamageAttachedTriggeredAbility; import mage.abilities.common.PutIntoGraveFromBattlefieldSourceTriggeredAbility; +import mage.abilities.dynamicvalue.common.NumericSetToEffectValues; import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.ReturnToHandSourceEffect; import mage.abilities.keyword.EnchantAbility; import mage.constants.Outcome; import mage.constants.Zone; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.permanent.Permanent; -import mage.players.Player; import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; /** @@ -58,7 +54,6 @@ public class SpiritLoop extends CardImpl { this.expansionSetCode = "TSP"; this.subtype.add("Aura"); - // Enchant creature you control TargetPermanent auraTarget = new TargetControlledCreaturePermanent(); this.getSpellAbility().addTarget(auraTarget); @@ -67,7 +62,7 @@ public class SpiritLoop extends CardImpl { this.addAbility(ability); // Whenever enchanted creature deals damage, you gain that much life. - this.addAbility(new SpiritLoopTriggeredAbility()); + this.addAbility(new DealsDamageAttachedTriggeredAbility(Zone.BATTLEFIELD, new GainLifeEffect(new NumericSetToEffectValues("that much", "damage")), false)); // When Spirit Loop is put into a graveyard from the battlefield, return Spirit Loop to its owner's hand. this.addAbility(new PutIntoGraveFromBattlefieldSourceTriggeredAbility(new ReturnToHandSourceEffect())); @@ -82,75 +77,4 @@ public class SpiritLoop extends CardImpl { public SpiritLoop copy() { return new SpiritLoop(this); } -} - -class SpiritLoopTriggeredAbility extends TriggeredAbilityImpl { - - public SpiritLoopTriggeredAbility() { - super(Zone.BATTLEFIELD, new SpiritLoopEffect(), false); - } - - public SpiritLoopTriggeredAbility(final SpiritLoopTriggeredAbility ability) { - super(ability); - } - - @Override - public SpiritLoopTriggeredAbility copy() { - return new SpiritLoopTriggeredAbility(this); - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (event.getType().equals(GameEvent.EventType.DAMAGED_CREATURE) - || event.getType().equals(GameEvent.EventType.DAMAGED_PLAYER) - || event.getType().equals(GameEvent.EventType.DAMAGED_PLANESWALKER)) { - Permanent enchantment = game.getPermanent(this.getSourceId()); - if (enchantment == null || enchantment.getAttachedTo() == null) { - return false; - } - Permanent enchanted = game.getPermanent(enchantment.getAttachedTo()); - if (enchanted != null && event.getSourceId().equals(enchanted.getId())) { - for (Effect effect : this.getEffects()) { - effect.setValue("damage", event.getAmount()); - } - return true; - } - } - return false; - } - - @Override - public String getRule() { - return "Whenever enchanted creature deals damage, " + super.getRule(); - } -} - -class SpiritLoopEffect extends OneShotEffect { - - public SpiritLoopEffect() { - super(Outcome.GainLife); - this.staticText = "you gain that much life"; - } - - public SpiritLoopEffect(final SpiritLoopEffect effect) { - super(effect); - } - - @Override - public SpiritLoopEffect copy() { - return new SpiritLoopEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - int amount = (Integer) getValue("damage"); - if (amount > 0) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - controller.gainLife(amount, game); - return true; - } - } - return false; - } } \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/torment/DevastatingDreams.java b/Mage.Sets/src/mage/sets/torment/DevastatingDreams.java new file mode 100644 index 00000000000..55a583904f9 --- /dev/null +++ b/Mage.Sets/src/mage/sets/torment/DevastatingDreams.java @@ -0,0 +1,109 @@ +/* + * 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.torment; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.costs.Cost; +import mage.abilities.costs.VariableCostImpl; +import mage.abilities.costs.common.DiscardTargetCost; +import mage.abilities.dynamicvalue.common.GetXValue; +import mage.abilities.effects.common.DamageAllEffect; +import mage.abilities.effects.common.SacrificeAllEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.FilterCard; +import mage.filter.common.FilterControlledLandPermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetCardInHand; + +/** + * + * @author emerald000 + */ +public class DevastatingDreams extends CardImpl { + + public DevastatingDreams(UUID ownerId) { + super(ownerId, 95, "Devastating Dreams", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{R}{R}"); + this.expansionSetCode = "TOR"; + + // As an additional cost to cast Devastating Dreams, discard X cards at random. + this.getSpellAbility().addCost(new DevastatingDreamsAdditionalCost()); + + // Each player sacrifices X lands. + this.getSpellAbility().addEffect(new SacrificeAllEffect(new GetXValue(), new FilterControlledLandPermanent("lands"))); + + // Devastating Dreams deals X damage to each creature. + this.getSpellAbility().addEffect(new DamageAllEffect(new GetXValue(), new FilterCreaturePermanent())); + } + + public DevastatingDreams(final DevastatingDreams card) { + super(card); + } + + @Override + public DevastatingDreams copy() { + return new DevastatingDreams(this); + } +} + +class DevastatingDreamsAdditionalCost extends VariableCostImpl { + + DevastatingDreamsAdditionalCost() { + super("cards to discard randomly"); + this.text = "As an additional cost to cast {this}, discard X cards at random"; + } + + DevastatingDreamsAdditionalCost(final DevastatingDreamsAdditionalCost cost) { + super(cost); + } + + @Override + public DevastatingDreamsAdditionalCost copy() { + return new DevastatingDreamsAdditionalCost(this); + } + + @Override + public int getMaxValue(Ability source, Game game) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + return controller.getHand().size(); + } + return 0; + } + + @Override + public Cost getFixedCostsFromAnnouncedValue(int xValue) { + TargetCardInHand target = new TargetCardInHand(xValue, new FilterCard()); + return new DiscardTargetCost(target, true); + } +} + diff --git a/Mage.Sets/src/mage/sets/torment/MesmericFiend.java b/Mage.Sets/src/mage/sets/torment/MesmericFiend.java index 22392f4c574..e04a248377b 100644 --- a/Mage.Sets/src/mage/sets/torment/MesmericFiend.java +++ b/Mage.Sets/src/mage/sets/torment/MesmericFiend.java @@ -111,7 +111,7 @@ class MesmericFiendExileEffect extends OneShotEffect { if (controller.choose(Outcome.Exile, opponent.getHand(), target, game)) { Card card = opponent.getHand().get(target.getFirstTarget(), game); if (card != null) { - controller.moveCardToExileWithInfo(card, CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter()), sourcePermanent.getName(), source.getSourceId(), game, Zone.HAND, true); + controller.moveCardToExileWithInfo(card, CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter()), sourcePermanent.getIdName(), source.getSourceId(), game, Zone.HAND, true); } } diff --git a/Mage.Sets/src/mage/sets/unlimitededition/TimeVault.java b/Mage.Sets/src/mage/sets/unlimitededition/TimeVault.java index e5525fea2b8..f81de7e109d 100644 --- a/Mage.Sets/src/mage/sets/unlimitededition/TimeVault.java +++ b/Mage.Sets/src/mage/sets/unlimitededition/TimeVault.java @@ -98,9 +98,14 @@ class TimeVaultReplacementEffect extends ReplacementEffectImpl { return new TimeVaultReplacementEffect(this); } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.PLAY_TURN; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == EventType.PLAY_TURN && source.getControllerId().equals(event.getPlayerId())) { + if (source.getControllerId().equals(event.getPlayerId())) { Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent != null && permanent.isTapped()) { return true; @@ -108,12 +113,7 @@ class TimeVaultReplacementEffect extends ReplacementEffectImpl { } return false; } - - @Override - public boolean apply(Game game, Ability source) { - return true; - } - + @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { Player player = game.getPlayer(source.getControllerId()); diff --git a/Mage.Sets/src/mage/sets/urzasdestiny/Flicker.java b/Mage.Sets/src/mage/sets/urzasdestiny/Flicker.java index b690ecf5f90..d60bacd5209 100644 --- a/Mage.Sets/src/mage/sets/urzasdestiny/Flicker.java +++ b/Mage.Sets/src/mage/sets/urzasdestiny/Flicker.java @@ -28,21 +28,37 @@ package mage.sets.urzasdestiny; import java.util.UUID; +import mage.abilities.effects.common.ExileTargetForSourceEffect; +import mage.abilities.effects.common.ReturnToBattlefieldUnderOwnerControlTargetEffect; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Rarity; +import mage.filter.FilterPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.permanent.TokenPredicate; +import mage.target.TargetPermanent; /** * * @author LevelX2 */ public class Flicker extends CardImpl { - + + private static final FilterPermanent filter = new FilterPermanent("nontoken permanent"); + + static { + filter.add(Predicates.not(new TokenPredicate())); + } + public Flicker(UUID ownerId) { super(ownerId, 9, "Flicker", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{1}{W}"); this.expansionSetCode = "UDS"; // Exile target nontoken permanent, then return it to the battlefield under its owner's control. + this.getSpellAbility().addTarget(new TargetPermanent(filter)); + this.getSpellAbility().addEffect(new ExileTargetForSourceEffect()); + this.getSpellAbility().addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect()); + } public Flicker(final Flicker card) { diff --git a/Mage.Sets/src/mage/sets/urzassaga/Pariah.java b/Mage.Sets/src/mage/sets/urzassaga/Pariah.java index a2967c460b0..e5502f2785f 100644 --- a/Mage.Sets/src/mage/sets/urzassaga/Pariah.java +++ b/Mage.Sets/src/mage/sets/urzassaga/Pariah.java @@ -57,12 +57,12 @@ public class Pariah extends CardImpl { this.expansionSetCode = "USG"; this.subtype.add("Aura"); - // Enchant creature TargetPermanent auraTarget = new TargetCreaturePermanent(); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); this.addAbility(new EnchantAbility(auraTarget.getTargetName())); + // All damage that would be dealt to you is dealt to enchanted creature instead. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new PariahEffect())); } @@ -90,22 +90,25 @@ class PariahEffect extends ReplacementEffectImpl { @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { DamagePlayerEvent damageEvent = (DamagePlayerEvent) event; - Permanent equipment = game.getPermanent(source.getSourceId()); - if(equipment != null){ + Permanent equipment = game.getPermanent(source.getSourceId()); + if (equipment != null) { Permanent p = game.getPermanent(equipment.getAttachedTo()); - if (p != null) { - p.damage(damageEvent.getAmount(), event.getSourceId(), game, damageEvent.isCombatDamage(), damageEvent.isPreventable()); - return true; - } - } + if (p != null) { + p.damage(damageEvent.getAmount(), event.getSourceId(), game, damageEvent.isCombatDamage(), damageEvent.isPreventable()); + return true; + } + } return true; } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DAMAGE_PLAYER; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == GameEvent.EventType.DAMAGE_PLAYER && event.getPlayerId().equals(source.getControllerId())) - return true; - return false; + return event.getPlayerId().equals(source.getControllerId()); } @Override diff --git a/Mage.Sets/src/mage/sets/urzassaga/Worship.java b/Mage.Sets/src/mage/sets/urzassaga/Worship.java index 0053b2fcbe8..8b3743841fb 100644 --- a/Mage.Sets/src/mage/sets/urzassaga/Worship.java +++ b/Mage.Sets/src/mage/sets/urzassaga/Worship.java @@ -35,7 +35,6 @@ import mage.cards.CardImpl; import mage.filter.common.FilterControlledCreaturePermanent; import mage.game.Game; import mage.game.events.GameEvent; -import mage.game.permanent.Permanent; import mage.players.Player; import java.util.UUID; @@ -49,7 +48,6 @@ public class Worship extends CardImpl { super(ownerId, 57, "Worship", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{3}{W}"); this.expansionSetCode = "USG"; - // If you control a creature, damage that would reduce your life total to less than 1 reduces it to 1 instead. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new WorshipReplacementEffect())); } @@ -79,26 +77,23 @@ class WorshipReplacementEffect extends ReplacementEffectImpl { public WorshipReplacementEffect copy() { return new WorshipReplacementEffect(this); } - + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DAMAGE_CAUSES_LIFE_LOSS; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType().equals(GameEvent.EventType.DAMAGE_CAUSES_LIFE_LOSS)) { - Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent == null) { - permanent = (Permanent) game.getLastKnownInformation(source.getSourceId(), Zone.BATTLEFIELD); - } - if (permanent != null) { - Player controller = game.getPlayer(permanent.getControllerId()); - if (controller != null - && (controller.getLife() - event.getAmount()) < 1 - && event.getPlayerId().equals(controller.getId()) - && game.getBattlefield().count(new FilterControlledCreaturePermanent(), source.getSourceId(), event.getPlayerId(), game) > 0 - ) { - event.setAmount(controller.getLife() - 1); - } + if (source.getControllerId().equals(event.getPlayerId())) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null + && (controller.getLife() - event.getAmount()) < 1 + && game.getBattlefield().count(new FilterControlledCreaturePermanent(), source.getSourceId(), event.getPlayerId(), game) > 0 + ) { + event.setAmount(controller.getLife() - 1); } } - return false; } @@ -111,5 +106,4 @@ class WorshipReplacementEffect extends ReplacementEffectImpl { public boolean replaceEvent(GameEvent event, Ability source, Game game) { return false; } - } diff --git a/Mage.Sets/src/mage/sets/urzassaga/YawgmothsWill.java b/Mage.Sets/src/mage/sets/urzassaga/YawgmothsWill.java index 5f20f765e6a..caa8114d837 100644 --- a/Mage.Sets/src/mage/sets/urzassaga/YawgmothsWill.java +++ b/Mage.Sets/src/mage/sets/urzassaga/YawgmothsWill.java @@ -58,7 +58,6 @@ public class YawgmothsWill extends CardImpl { super(ownerId, 171, "Yawgmoth's Will", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{2}{B}"); this.expansionSetCode = "USG"; - // Until end of turn, you may play cards from your graveyard. this.getSpellAbility().addEffect(new CanPlayCardsFromGraveyardEffect()); @@ -130,11 +129,6 @@ class YawgmothsWillReplacementEffect extends ReplacementEffectImpl { return new YawgmothsWillReplacementEffect(this); } - @Override - public boolean apply(Game game, Ability source) { - return true; - } - @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { Player controller = game.getPlayer(source.getControllerId()); @@ -154,10 +148,15 @@ class YawgmothsWillReplacementEffect extends ReplacementEffectImpl { } return true; } - + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.ZONE_CHANGE; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == EventType.ZONE_CHANGE && ((ZoneChangeEvent) event).getToZone() == Zone.GRAVEYARD) { + if (((ZoneChangeEvent) event).getToZone() == Zone.GRAVEYARD) { Card card = game.getCard(event.getTargetId()); if (card != null && card.getOwnerId().equals(source.getControllerId())) { Permanent permanent = ((ZoneChangeEvent) event).getTarget(); diff --git a/Mage.Sets/src/mage/sets/venservskoth/GalepowderMage.java b/Mage.Sets/src/mage/sets/venservskoth/GalepowderMage.java index 7a843471387..7305b139aa9 100644 --- a/Mage.Sets/src/mage/sets/venservskoth/GalepowderMage.java +++ b/Mage.Sets/src/mage/sets/venservskoth/GalepowderMage.java @@ -114,7 +114,7 @@ class GalepowderMageEffect extends OneShotEffect { Card card = game.getCard(getTargetPointer().getFirst(game, source)); if (permanent != null) { UUID exileId = UUID.randomUUID(); - if (controller.moveCardToExileWithInfo(permanent, exileId, sourceObject.getName(), source.getSourceId(), game, Zone.BATTLEFIELD, true)) { + if (controller.moveCardToExileWithInfo(permanent, exileId, sourceObject.getIdName(), source.getSourceId(), game, Zone.BATTLEFIELD, true)) { if (card != null) { AtTheBeginOfNextEndStepDelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new ReturnFromExileEffect(exileId, Zone.BATTLEFIELD)); delayedAbility.setSourceId(source.getSourceId()); diff --git a/Mage.Sets/src/mage/sets/vintagemasters/BenevolentBodyguard.java b/Mage.Sets/src/mage/sets/vintagemasters/BenevolentBodyguard.java new file mode 100644 index 00000000000..f06fbab48f4 --- /dev/null +++ b/Mage.Sets/src/mage/sets/vintagemasters/BenevolentBodyguard.java @@ -0,0 +1,71 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.vintagemasters; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.effects.common.continuous.GainProtectionFromColorTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.target.common.TargetControlledCreaturePermanent; + +/** + * + * @author emerald000 + */ +public class BenevolentBodyguard extends CardImpl { + + public BenevolentBodyguard(UUID ownerId) { + super(ownerId, 17, "Benevolent Bodyguard", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{W}"); + this.expansionSetCode = "VMA"; + this.subtype.add("Human"); + this.subtype.add("Cleric"); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Sacrifice Benevolent Bodyguard: Target creature you control gains protection from the color of your choice until end of turn. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new GainProtectionFromColorTargetEffect(Duration.EndOfTurn), new SacrificeSourceCost()); + ability.addTarget(new TargetControlledCreaturePermanent()); + this.addAbility(ability); + } + + public BenevolentBodyguard(final BenevolentBodyguard card) { + super(card); + } + + @Override + public BenevolentBodyguard copy() { + return new BenevolentBodyguard(this); + } +} diff --git a/Mage.Sets/src/mage/sets/vintagemasters/MindsDesire.java b/Mage.Sets/src/mage/sets/vintagemasters/MindsDesire.java index 28ae81dca87..2d9aeb91bbb 100644 --- a/Mage.Sets/src/mage/sets/vintagemasters/MindsDesire.java +++ b/Mage.Sets/src/mage/sets/vintagemasters/MindsDesire.java @@ -28,6 +28,7 @@ package mage.sets.vintagemasters; import java.util.UUID; +import mage.MageObject; import mage.abilities.Ability; import mage.abilities.effects.AsThoughEffectImpl; import mage.abilities.effects.ContinuousEffect; @@ -91,13 +92,14 @@ class MindsDesireEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - if (player != null) { - player.shuffleLibrary(game); - if (player.getLibrary().size() > 0) { - Card card = player.getLibrary().removeFromTop(game); + Player controller = game.getPlayer(source.getControllerId()); + MageObject sourceObject = source.getSourceObject(game); + if (controller != null && sourceObject != null) { + controller.shuffleLibrary(game); + if (controller.getLibrary().size() > 0) { + Card card = controller.getLibrary().removeFromTop(game); if (card != null) { - player.moveCardToExileWithInfo(card, source.getSourceId(), "Mind's Desire", source.getSourceId(), game, Zone.LIBRARY, true); + controller.moveCardToExileWithInfo(card, source.getSourceId(), sourceObject.getIdName(), source.getSourceId(), game, Zone.LIBRARY, true); ContinuousEffect effect = new MindsDesireCastFromExileEffect(); effect.setTargetPointer(new FixedTarget(card.getId())); game.addEffect(effect, source); diff --git a/Mage.Sets/src/mage/sets/visions/ElephantGrass.java b/Mage.Sets/src/mage/sets/visions/ElephantGrass.java index c54819decd6..11f14fe5eb5 100644 --- a/Mage.Sets/src/mage/sets/visions/ElephantGrass.java +++ b/Mage.Sets/src/mage/sets/visions/ElephantGrass.java @@ -71,7 +71,6 @@ public class ElephantGrass extends CardImpl { class ElephantGrassReplacementEffect extends ReplacementEffectImpl { - ElephantGrassReplacementEffect ( ) { super(Duration.WhileOnBattlefield, Outcome.Neutral); @@ -101,8 +100,7 @@ class ElephantGrassReplacementEffect extends ReplacementEffectImpl { @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { return true; - } - + } @Override public ElephantGrassReplacementEffect copy() { @@ -122,32 +120,30 @@ class ElephantGrassReplacementEffect2 extends ReplacementEffectImpl { super(effect); } - @Override - public boolean apply(Game game, Ability source) { - return true; - } - @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { - if ( event.getType() == GameEvent.EventType.DECLARE_ATTACKER) { - Player player = game.getPlayer(event.getPlayerId()); - if ( player != null && event.getTargetId().equals(source.getControllerId())) { - ManaCostsImpl attackCost = new ManaCostsImpl("{2}"); - if ( attackCost.canPay(source, source.getSourceId(), event.getPlayerId(), game) && - player.chooseUse(Outcome.Benefit, "Pay {2} to attack player?", game) ) { - if (attackCost.payOrRollback(source, game, this.getId(), event.getPlayerId())) { - return false; - } + Player player = game.getPlayer(event.getPlayerId()); + if ( player != null && event.getTargetId().equals(source.getControllerId())) { + ManaCostsImpl attackCost = new ManaCostsImpl("{2}"); + if ( attackCost.canPay(source, source.getSourceId(), event.getPlayerId(), game) && + player.chooseUse(Outcome.Benefit, "Pay {2} to attack player?", game) ) { + if (attackCost.payOrRollback(source, game, this.getId(), event.getPlayerId())) { + return false; } - return true; } + return true; } return false; } - + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DECLARE_ATTACKER; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if ( event.getType() == GameEvent.EventType.DECLARE_ATTACKER && event.getTargetId().equals(source.getControllerId()) ) { + if (event.getTargetId().equals(source.getControllerId()) ) { Permanent creature = game.getPermanent(event.getSourceId()); if (creature != null && !creature.getColor().isBlack()) { Player attackedPlayer = game.getPlayer(event.getTargetId()); diff --git a/Mage.Sets/src/mage/sets/visions/GriffinCanyon.java b/Mage.Sets/src/mage/sets/visions/GriffinCanyon.java new file mode 100644 index 00000000000..1e1879095dd --- /dev/null +++ b/Mage.Sets/src/mage/sets/visions/GriffinCanyon.java @@ -0,0 +1,109 @@ +/* + * 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.visions; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.abilities.mana.ColorlessManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; + +/** + * + * @author anonymous + */ +public class GriffinCanyon extends CardImpl { + + private static final FilterPermanent filter = new FilterPermanent("Griffin", "target Griffin"); + + public GriffinCanyon(UUID ownerId) { + super(ownerId, 163, "Griffin Canyon", Rarity.RARE, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "VIS"; + + // {tap}: Add {1} to your mana pool. + this.addAbility(new ColorlessManaAbility()); + // {tap}: Untap target Griffin. If it's a creature, it gets +1/+1 until end of turn. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new GriffinCanyonEffect(), new TapSourceCost()); + ability.addTarget(new TargetPermanent(filter)); + this.addAbility(ability); + } + + public GriffinCanyon(final GriffinCanyon card) { + super(card); + } + + @Override + public GriffinCanyon copy() { + return new GriffinCanyon(this); + } +} + +class GriffinCanyonEffect extends OneShotEffect { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("a creature"); + + public GriffinCanyonEffect() { + super(Outcome.Benefit); + this.staticText = "Untap target Griffin. If it's a creature, it gets +1/+1 until end of turn"; + } + + public GriffinCanyonEffect(final GriffinCanyonEffect effect) { + super(effect); + } + + @Override + public GriffinCanyonEffect copy() { + return new GriffinCanyonEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent targetCreature = game.getPermanent(source.getFirstTarget()); + if (targetCreature != null) { + targetCreature.untap(game); + if (filter.match(targetCreature, game)) { + game.addEffect(new BoostTargetEffect(1, 1, Duration.EndOfTurn), source); + } + return true; + } + return false; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/visions/TeferisRealm.java b/Mage.Sets/src/mage/sets/visions/TeferisRealm.java new file mode 100644 index 00000000000..9664f0e51d0 --- /dev/null +++ b/Mage.Sets/src/mage/sets/visions/TeferisRealm.java @@ -0,0 +1,144 @@ +/* + * 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.visions; + +import java.util.HashSet; +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.cards.CardImpl; +import mage.choices.Choice; +import mage.choices.ChoiceImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.filter.FilterPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.filter.predicate.permanent.TokenPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; + +/** + * + * @author LevelX2 + */ +public class TeferisRealm extends CardImpl { + + public TeferisRealm(UUID ownerId) { + super(ownerId, 44, "Teferi's Realm", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{1}{U}{U}"); + this.expansionSetCode = "VIS"; + this.supertype.add("World"); + + // At the beginning of each player's upkeep, that player chooses artifact, creature, land, or non-Aura enchantment. All nontoken permanents of that type phase out. + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new TeferisRealmEffect(), TargetController.ANY, false)); + } + + public TeferisRealm(final TeferisRealm card) { + super(card); + } + + @Override + public TeferisRealm copy() { + return new TeferisRealm(this); + } +} + +class TeferisRealmEffect extends OneShotEffect { + + private static final String ARTIFACT = "Artifact"; + private static final String CREATURE = "Creature"; + private static final String LAND = "Land"; + private static final String NON_AURA_ENCHANTMENT = "Non-Aura enchantment"; + private static final HashSet choices = new HashSet<>(); + static{ + choices.add(ARTIFACT); + choices.add(CREATURE); + choices.add(LAND); + choices.add(NON_AURA_ENCHANTMENT); + } + + public TeferisRealmEffect() { + super(Outcome.Detriment); + this.staticText = "that player chooses artifact, creature, land, or non-Aura enchantment. All nontoken permanents of that type phase out"; + } + + public TeferisRealmEffect(final TeferisRealmEffect effect) { + super(effect); + } + + @Override + public TeferisRealmEffect copy() { + return new TeferisRealmEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(getTargetPointer().getFirst(game, source)); + if (player != null) { + Choice choiceImpl = new ChoiceImpl(true); + choiceImpl.setMessage("Phase out which kind of permanents?"); + choiceImpl.setChoices(choices); + while(!player.choose(outcome, choiceImpl, game)) { + if (player.isInGame()) { + return false; + } + } + String choosenType = choiceImpl.getChoice(); + FilterPermanent filter = new FilterPermanent(); + filter.add(Predicates.not(new TokenPredicate())); + switch(choosenType) { + case ARTIFACT: + filter.add(new CardTypePredicate(CardType.ARTIFACT)); + break; + case CREATURE: + filter.add(new CardTypePredicate(CardType.CREATURE)); + break; + case LAND: + filter.add(new CardTypePredicate(CardType.LAND)); + break; + case NON_AURA_ENCHANTMENT: + filter.add(new CardTypePredicate(CardType.ENCHANTMENT)); + filter.add(Predicates.not(new SubtypePredicate("Aura"))); + break; + default: + return false; + } + game.informPlayers(player.getLogName() + " chooses " + choosenType +"s to phase out"); + for(Permanent permanent: game.getBattlefield().getAllActivePermanents(filter, player.getId(), game)) { + permanent.phaseOut(game); + } + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/weatherlight/LotusVale.java b/Mage.Sets/src/mage/sets/weatherlight/LotusVale.java new file mode 100644 index 00000000000..9183f46d57c --- /dev/null +++ b/Mage.Sets/src/mage/sets/weatherlight/LotusVale.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.sets.weatherlight; + +import java.util.UUID; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.effects.common.EnterBattlefieldPayCostOrPutGraveyardEffect; +import mage.abilities.mana.AnyColorManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterControlledLandPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.permanent.TappedPredicate; +import mage.target.common.TargetControlledPermanent; + +/** + * + * @author anonymous + */ +public class LotusVale extends CardImpl { + + private static final FilterControlledLandPermanent filter = new FilterControlledLandPermanent("two untapped lands"); + static { + filter.add(Predicates.not(new TappedPredicate())); + } + + public LotusVale(UUID ownerId) { + super(ownerId, 165, "Lotus Vale", Rarity.RARE, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "WTH"; + + // If Lotus Vale would enter the battlefield, sacrifice two untapped lands instead. If you do, put Lotus Vale onto the battlefield. If you don't, put it into its owner's graveyard. + this.addAbility(new SimpleStaticAbility(Zone.ALL, new EnterBattlefieldPayCostOrPutGraveyardEffect(new SacrificeTargetCost(new TargetControlledPermanent(2, 2, filter, false))))); + + // {tap}: Add three mana of any one color to your mana pool. + this.addAbility(new AnyColorManaAbility()); + } + + public LotusVale(final LotusVale card) { + super(card); + } + + @Override + public LotusVale copy() { + return new LotusVale(this); + } +} diff --git a/Mage.Sets/src/mage/sets/weatherlight/SpinningDarkness.java b/Mage.Sets/src/mage/sets/weatherlight/SpinningDarkness.java new file mode 100644 index 00000000000..97623904f4a --- /dev/null +++ b/Mage.Sets/src/mage/sets/weatherlight/SpinningDarkness.java @@ -0,0 +1,139 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.weatherlight; + +import java.util.Iterator; +import java.util.Set; +import java.util.UUID; +import mage.ObjectColor; +import mage.abilities.Ability; +import mage.abilities.costs.AlternativeCostSourceAbility; +import mage.abilities.costs.CostImpl; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.GainLifeEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.Cards; +import mage.cards.CardsImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.ColorPredicate; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author emerald000 + */ +public class SpinningDarkness extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nonblack creature"); + static { + filter.add(Predicates.not(new ColorPredicate(ObjectColor.BLACK))); + } + + public SpinningDarkness(UUID ownerId) { + super(ownerId, 23, "Spinning Darkness", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{4}{B}{B}"); + this.expansionSetCode = "WTH"; + + // You may exile the top three black cards of your graveyard rather than pay Spinning Darkness's mana cost. + this.addAbility(new AlternativeCostSourceAbility(new SpinningDarknessCost())); + + // Spinning Darkness deals 3 damage to target nonblack creature. You gain 3 life. + this.getSpellAbility().addEffect(new DamageTargetEffect(3)); + this.getSpellAbility().addEffect(new GainLifeEffect(3)); + this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + } + + public SpinningDarkness(final SpinningDarkness card) { + super(card); + } + + @Override + public SpinningDarkness copy() { + return new SpinningDarkness(this); + } +} + +class SpinningDarknessCost extends CostImpl { + + private static final FilterCard filter = new FilterCard("black card"); + static { + filter.add(new ColorPredicate(ObjectColor.BLACK)); + } + + SpinningDarknessCost() { + this.text = "exile the top three black cards of your graveyard"; + } + + SpinningDarknessCost(final SpinningDarknessCost cost) { + super(cost); + } + + @Override + public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) { + Player controller = game.getPlayer(controllerId); + if (controller != null) { + Set blackCardsInGraveyard = controller.getGraveyard().getCards(filter, game); + int size = blackCardsInGraveyard.size(); + if (size >= 3) { + Iterator it = blackCardsInGraveyard.iterator(); + Cards cardsToExile = new CardsImpl(); + int i = 1; + while (cardsToExile.size() < 3) { + Card card = it.next(); + if (i > size - 3) { + cardsToExile.add(card); + } + i++; + } + paid = controller.moveCards(cardsToExile, Zone.GRAVEYARD, Zone.EXILED, ability, game); + } + } + return paid; + } + + @Override + public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) { + Player controller = game.getPlayer(controllerId); + if (controller != null) { + return controller.getGraveyard().getCards(filter, game).size() >= 3; + } + return false; + } + + @Override + public SpinningDarknessCost copy() { + return new SpinningDarknessCost(this); + } +} diff --git a/Mage.Sets/src/mage/sets/worldwake/ThadaAdelAcquisitor.java b/Mage.Sets/src/mage/sets/worldwake/ThadaAdelAcquisitor.java index 8db182345cf..75ef0f6be80 100644 --- a/Mage.Sets/src/mage/sets/worldwake/ThadaAdelAcquisitor.java +++ b/Mage.Sets/src/mage/sets/worldwake/ThadaAdelAcquisitor.java @@ -107,7 +107,7 @@ class ThadaAdelAcquisitorEffect extends OneShotEffect { if (target.getTargets().size() > 0) { Card card = damagedPlayer.getLibrary().remove(target.getFirstTarget(), game); if (card != null) { - controller.moveCardToExileWithInfo(card, source.getSourceId(), sourceObject.getName(), source.getSourceId(), game, Zone.LIBRARY, true); + controller.moveCardToExileWithInfo(card, source.getSourceId(), sourceObject.getIdName(), source.getSourceId(), game, Zone.LIBRARY, true); ContinuousEffect effect = new ThadaAdelPlayFromExileEffect(); effect.setTargetPointer(new FixedTarget(card.getId())); game.addEffect(effect, source); diff --git a/Mage.Sets/src/mage/sets/worldwake/WrexialTheRisenDeep.java b/Mage.Sets/src/mage/sets/worldwake/WrexialTheRisenDeep.java index 873b913bb6c..c0c76991785 100644 --- a/Mage.Sets/src/mage/sets/worldwake/WrexialTheRisenDeep.java +++ b/Mage.Sets/src/mage/sets/worldwake/WrexialTheRisenDeep.java @@ -153,35 +153,35 @@ class WrexialReplacementEffect extends ReplacementEffectImpl { } @Override - public boolean apply(Game game, Ability source) { - return true; + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.ZONE_CHANGE; } - + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + ZoneChangeEvent zEvent = (ZoneChangeEvent) event; + if (zEvent.getToZone() == Zone.GRAVEYARD + && ((ZoneChangeEvent) event).getTargetId() == cardid) { + return true; + } + return false; + } + @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { UUID eventObject = ((ZoneChangeEvent) event).getTargetId(); StackObject card = game.getStack().getStackObject(eventObject); - if (card != null) { + Player controller = game.getPlayer(source.getControllerId()); + if (card != null && controller != null) { if (card instanceof Spell) { game.rememberLKI(card.getId(), Zone.STACK, (Spell) card); } - if (card instanceof Card && eventObject == cardid) { - ((Card) card).moveToExile(source.getSourceId(), "Wrexial, The Risen Deep", source.getSourceId(), game); + if (card instanceof Card) { + controller.moveCardToExileWithInfo((Card)card, null, "", source.getSourceId(), game, game.getState().getZone(event.getTargetId()), true); return true; } } return false; } - @Override - public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == EventType.ZONE_CHANGE) { - ZoneChangeEvent zEvent = (ZoneChangeEvent) event; - if (zEvent.getToZone() == Zone.GRAVEYARD - && ((ZoneChangeEvent) event).getTargetId() == cardid) { - return true; - } - } - return false; - } } diff --git a/Mage.Sets/src/mage/sets/zendikar/NissasChosen.java b/Mage.Sets/src/mage/sets/zendikar/NissasChosen.java index 3b4b5e1bda7..008deec3f2e 100644 --- a/Mage.Sets/src/mage/sets/zendikar/NissasChosen.java +++ b/Mage.Sets/src/mage/sets/zendikar/NissasChosen.java @@ -43,6 +43,7 @@ import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; import mage.game.events.ZoneChangeEvent; import mage.game.permanent.Permanent; +import mage.players.Player; /** * @@ -59,6 +60,7 @@ public class NissasChosen extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(3); + // If Nissa's Chosen would be put into a graveyard from the battlefield, put it on the bottom of its owner's library instead this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new NissasChosenEffect())); } @@ -89,27 +91,13 @@ class NissasChosenEffect extends ReplacementEffectImpl { } @Override - public boolean apply(Game game, Ability source) { - return false; + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.ZONE_CHANGE; } - - @Override - public boolean replaceEvent(GameEvent event, Ability source, Game game) { - Permanent permanent = ((ZoneChangeEvent) event).getTarget(); - if (permanent != null) { - if(permanent.moveToZone(Zone.LIBRARY, source.getSourceId(), game, false)) { - game.informPlayers(new StringBuilder(permanent.getName()).append(" was put on the bottom of its owner's library").toString()); - return true; - } - - } - return false; - } - + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if ( event.getType() == EventType.ZONE_CHANGE && event.getTargetId().equals(source.getSourceId()) ) - { + if (event.getTargetId().equals(source.getSourceId())) { ZoneChangeEvent zEvent = (ZoneChangeEvent)event; if ( zEvent.getFromZone() == Zone.BATTLEFIELD && zEvent.getToZone() == Zone.GRAVEYARD ) { return true; @@ -117,5 +105,15 @@ class NissasChosenEffect extends ReplacementEffectImpl { } return false; } - + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + Permanent permanent = ((ZoneChangeEvent) event).getTarget(); + Player controller = game.getPlayer(source.getControllerId()); + if (permanent != null && controller != null) { + controller.moveCardToLibraryWithInfo(permanent, source.getSourceId(), game, Zone.BATTLEFIELD, false, true); + return true; + } + return false; + } } diff --git a/Mage.Sets/src/mage/sets/zendikar/UnstableFooting.java b/Mage.Sets/src/mage/sets/zendikar/UnstableFooting.java index 913efaeefa7..51de9cffdc0 100644 --- a/Mage.Sets/src/mage/sets/zendikar/UnstableFooting.java +++ b/Mage.Sets/src/mage/sets/zendikar/UnstableFooting.java @@ -43,6 +43,7 @@ import mage.cards.CardImpl; import mage.constants.Duration; import mage.game.Game; import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; import mage.target.TargetPlayer; /** @@ -55,7 +56,6 @@ public class UnstableFooting extends CardImpl { super(ownerId, 153, "Unstable Footing", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{R}"); this.expansionSetCode = "ZEN"; - // Kicker {3}{R} (You may pay an additional {3}{R} as you cast this spell.) this.addAbility(new KickerAbility("{3}{R}")); @@ -64,9 +64,7 @@ public class UnstableFooting extends CardImpl { this.getSpellAbility().addEffect(new ConditionalOneShotEffect( new DamageTargetEffect(5), KickedCondition.getInstance(), - "If Unstable Footing was kicked, it deals 5 damage to target player")); - - + "If {this} was kicked, it deals 5 damage to target player")); } @@ -106,22 +104,19 @@ class UnstableFootingEffect extends ReplacementEffectImpl { return new UnstableFootingEffect(this); } - @Override - public boolean apply(Game game, Ability source) { - return true; - } - @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { return true; } - + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.PREVENT_DAMAGE; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == GameEvent.EventType.PREVENT_DAMAGE) { - return true; - } - return false; + return true; } } \ No newline at end of file diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/activated/PutOntoBattlefieldTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/activated/PutOntoBattlefieldTest.java index 1ab753078be..b89eb696780 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/activated/PutOntoBattlefieldTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/activated/PutOntoBattlefieldTest.java @@ -1,51 +1,49 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.mage.test.cards.abilities.activated; - -import mage.constants.PhaseStep; -import mage.constants.Zone; -import mage.game.permanent.Permanent; -import org.junit.Assert; -import org.junit.Test; -import org.mage.test.serverside.base.CardTestPlayerBase; - -/** - * - * @author LevelX2 - */ - -public class PutOntoBattlefieldTest extends CardTestPlayerBase { - - /** - * Tests to put a token onto the battlefield - */ - @Test - public void testOozeFlux() { - // Enchantment - // {1}{G}, Remove one or more +1/+1 counters from among creatures you control: Put an X/X green Ooze creature token onto the battlefield, where X is the number of +1/+1 counters removed this way. - addCard(Zone.BATTLEFIELD, playerA, "Ooze Flux"); - // Trample - // Kalonian Hydra enters the battlefield with four +1/+1 counters on it. - // Whenever Kalonian Hydra attacks, double the number of +1/+1 counters on each creature you control. - addCard(Zone.BATTLEFIELD, playerA, "Kalonian Hydra"); - addCard(Zone.BATTLEFIELD, playerA, "Forest", 2); - - activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}{G},"); - setChoice(playerA, "X=2"); // Remove how many - setChoice(playerA,"Kalonian Hydra"); - setChoice(playerA, "X=2"); // Remove from Hydra - - setStopAt(1, PhaseStep.BEGIN_COMBAT); - execute(); - - assertPowerToughness(playerA, "Kalonian Hydra", 2, 2); - assertPermanentCount(playerA, "Ooze", 1); - assertPowerToughness(playerA, "Ooze", 2, 2); - - } - - +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.mage.test.cards.abilities.activated; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ + +public class PutOntoBattlefieldTest extends CardTestPlayerBase { + + /** + * Tests to put a token onto the battlefield + */ + @Test + public void testOozeFlux() { + // Enchantment + // {1}{G}, Remove one or more +1/+1 counters from among creatures you control: Put an X/X green Ooze creature token onto the battlefield, where X is the number of +1/+1 counters removed this way. + addCard(Zone.BATTLEFIELD, playerA, "Ooze Flux"); + // Trample + // Kalonian Hydra enters the battlefield with four +1/+1 counters on it. + // Whenever Kalonian Hydra attacks, double the number of +1/+1 counters on each creature you control. + addCard(Zone.BATTLEFIELD, playerA, "Kalonian Hydra"); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 2); + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}{G},"); + setChoice(playerA, "X=2"); // Remove how many + setChoice(playerA,"Kalonian Hydra"); + setChoice(playerA, "X=2"); // Remove from Hydra + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPowerToughness(playerA, "Kalonian Hydra", 2, 2); + assertPermanentCount(playerA, "Ooze", 1); + assertPowerToughness(playerA, "Ooze", 2, 2); + + } + + } \ No newline at end of file diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/activated/ReturnToHandTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/activated/ReturnToHandTest.java new file mode 100644 index 00000000000..3b87ec843a1 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/activated/ReturnToHandTest.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 org.mage.test.cards.abilities.activated; + +import mage.abilities.keyword.BloodthirstAbility; +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ + +public class ReturnToHandTest extends CardTestPlayerBase { + + /** + * Tests to put a token onto the battlefield + */ + @Test + public void SkarrganFirebirdTest() { + addCard(Zone.BATTLEFIELD, playerA, "Pillarfield Ox"); + // Bloodthirst 3 + // Flying + // {R}{R}{R}: Return Skarrgan Firebird from your graveyard to your hand. Activate this ability only if an opponent was dealt damage this turn. + addCard(Zone.BATTLEFIELD, playerB, "Skarrgan Firebird"); + addCard(Zone.BATTLEFIELD, playerB, "Swamp", 2); + addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion"); + addCard(Zone.BATTLEFIELD, playerB, "Mountain", 3); + addCard(Zone.HAND, playerB, "Bone Splinters"); + + // As an additional cost to cast Bone Splinters, sacrifice a creature. + // Destroy target creature. + castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Bone Splinters", "Pillarfield Ox"); + setChoice(playerB, "Skarrgan Firebird"); + + attack(2, playerB, "Silvercoat Lion"); + + activateAbility(2, PhaseStep.POSTCOMBAT_MAIN, playerB, "{R}{R}{R}: Return"); + setStopAt(2, PhaseStep.END_TURN); + + execute(); + + assertPermanentCount(playerA, "Skarrgan Firebird", 0); + assertGraveyardCount(playerA, "Pillarfield Ox", 1); + assertGraveyardCount(playerB, "Bone Splinters", 1); + assertHandCount(playerB, "Skarrgan Firebird", 1); + + } + + +} \ No newline at end of file diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ChangelingTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ChangelingTest.java new file mode 100644 index 00000000000..c2010548151 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ChangelingTest.java @@ -0,0 +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 org.mage.test.cards.abilities.keywords; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ + +public class ChangelingTest extends CardTestPlayerBase { + + /** + * Casting changelings with a Long-Forgotten Gohei in play reduces its casting cost by {1}. + */ + + @Test + public void testLongForgottenGohei() { + addCard(Zone.BATTLEFIELD, playerA, "Forest", 1); + addCard(Zone.HAND, playerA, "Woodland Changeling"); + + addCard(Zone.BATTLEFIELD, playerA, "Long-Forgotten Gohei"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Woodland Changeling"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPermanentCount(playerA, "Woodland Changeling", 0); // Casting cost of spell is not reduced so not on the battlefield + assertHandCount(playerA, "Woodland Changeling", 1); + + } + +} \ No newline at end of file diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/PhasingTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/PhasingTest.java new file mode 100644 index 00000000000..53027c46f22 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/PhasingTest.java @@ -0,0 +1,67 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package org.mage.test.cards.abilities.keywords; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ + +public class PhasingTest extends CardTestPlayerBase { + + + + /** + * Test that abilities of phased out cards do not trigger or apply their effects + */ + @Test + public void TestAbilitiesOfPhasedOutAreNotApplied() { + addCard(Zone.BATTLEFIELD, playerA, "Island", 3); + // At the beginning of each player's upkeep, that player chooses artifact, creature, land, or non-Aura enchantment. + // All nontoken permanents of that type phase out. + addCard(Zone.HAND, playerA, "Teferi's Realm", 1); + + addCard(Zone.BATTLEFIELD, playerB, "Crusade", 1); + addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Teferi's Realm"); + + setChoice(playerB, "Non-Aura enchantment"); + setStopAt(2, PhaseStep.PRECOMBAT_MAIN); + execute(); + + assertPermanentCount(playerB, "Crusade", 0); + assertPermanentCount(playerB, "Silvercoat Lion", 1); + assertPowerToughness(playerB, "Silvercoat Lion", 2, 2); + } +} \ No newline at end of file diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ProliferateTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ProliferateTest.java index d8d9751f26c..316543911b2 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ProliferateTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ProliferateTest.java @@ -69,4 +69,48 @@ public class ProliferateTest extends CardTestPlayerBase{ assertCounterCount("Chandra, Pyromaster", CounterType.LOYALTY, 5); // 4 + 1 from proliferate } + + /** + * Counters aren't cancelling each other out. Reproducible with any creature (graft and bloodthirst in my case) + * with a single +1/+1 counter on it, with a single -1/-1 placed on it (Grim Affliction, Instill Infection, etc). + * The counters should cancel each other out, leaving neither on the creature, which they don't (though visually + * there aren't any counters sitting on the card). Triggering proliferate at any point now (Thrumming Bird, + * Steady Progress, etc) will give you the option to add another of either counter, where you shouldn't have any as an option. + */ + @Test + public void testValidTargets() { + addCard(Zone.BATTLEFIELD, playerA, "Forest", 1); + addCard(Zone.BATTLEFIELD, playerA, "Island", 3); + addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion"); + // Put a +1/+1 counter on target creature. + addCard(Zone.HAND, playerA, "Battlegrowth"); // {G} + // Proliferate. (You choose any number of permanents and/or players with counters on them, then give each another counter of a kind already there.) + // Draw a card. + addCard(Zone.HAND, playerA, "Steady Progress"); // {U}{2} + + addCard(Zone.BATTLEFIELD, playerB, "Sporeback Troll"); // has two +1/+1 counter + addCard(Zone.BATTLEFIELD, playerB, "Swamp", 3); + // Put a -1/-1 counter on target creature, then proliferate. + addCard(Zone.HAND, playerB, "Grim Affliction"); // {B}{2} + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Battlegrowth", "Silvercoat Lion"); + + castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Grim Affliction", "Silvercoat Lion"); + // proliferate Sporeback Troll + + castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerA, "Steady Progress"); + // Silvercoat Lion may not be a valid target now + + setStopAt(2, PhaseStep.BEGIN_COMBAT); + execute(); + + + assertGraveyardCount(playerA, "Battlegrowth", 1); + assertGraveyardCount(playerA, "Steady Progress", 1); + assertGraveyardCount(playerB, "Grim Affliction", 1); + + assertCounterCount("Silvercoat Lion", CounterType.P1P1, 0); // no valid target because no counter + assertCounterCount("Sporeback Troll", CounterType.P1P1, 3); // 2 + 1 from proliferate + + } } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/SuspendTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/SuspendTest.java index 36824165d1f..16de1ce5615 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/SuspendTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/SuspendTest.java @@ -29,6 +29,7 @@ package org.mage.test.cards.abilities.keywords; import mage.constants.PhaseStep; import mage.constants.Zone; +import mage.counters.CounterType; import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBase; @@ -114,4 +115,28 @@ public class SuspendTest extends CardTestPlayerBase { assertPermanentCount(playerA, "Silvercoat Lion", 1); } + @Test + public void testDeepSeaKraken() { + addCard(Zone.BATTLEFIELD, playerA, "Island", 3); + // Suspend 9-{2}{U} + // Whenever an opponent casts a spell, if Deep-Sea Kraken is suspended, remove a time counter from it. + addCard(Zone.HAND, playerA, "Deep-Sea Kraken",1); + + // Instant {1}{U} + // Counter target spell. If the spell is countered this way, exile it with three time counters on it instead of putting it into its owner's graveyard. If it doesn't have suspend, it gains suspend. (At the beginning of its owner's upkeep, remove a counter from that card. When the last is removed, the player plays it without paying its mana cost. If it's a creature, it has haste.) + addCard(Zone.HAND, playerB, "Lightning Bolt",1); + addCard(Zone.BATTLEFIELD, playerB, "Mountain", 1); + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Suspend"); + castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Lightning Bolt", playerA); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertGraveyardCount(playerB, "Lightning Bolt", 1); + assertExileCount("Deep-Sea Kraken", 1); + + assertCounterOnExiledCardCount("Deep-Sea Kraken", CounterType.TIME, 8); // -1 from spell of player B + + } } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/UnearthTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/UnearthTest.java new file mode 100644 index 00000000000..1d6911fd8ef --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/UnearthTest.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 org.mage.test.cards.abilities.keywords; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ + +public class UnearthTest extends CardTestPlayerBase { + + /** + * Hellspark Elemental (and probably other cards with the unearth ability) - If I unearth the elemental, + * attack, and then go to the end of my turn both the "sacrifice" and "exile" clauses will trigger and + * the game will ask me which one I want to put on the stack first. If I choose "sacrifice" first and + * "exile" second, all good, the exile part resolves first and the elemental is exiled, the sacrifice + * part does nothing afterwards. But if I choose "exile" first and "sacrifice" second then the elemental + * will be sacrificed and placed on my graveyard and after that the "exile" resolves but does nothing, as + * I'm guessing it can't "find" the elemental anymore and so it stays in my graveyard, despite the fact + * that because I use its unearth ability it should always be exiled once leaving the battlefield no matter what. + * The bug should be easy to reproduce if following the order I mention above (click the exile part, + * so the sacrifice goes on the top of the stack). + */ + @Test + public void testUnearthAttackExile() { + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2); + // 3/1 - Trample, haste + // At the beginning of the end step, sacrifice Hellspark Elemental. + // Unearth {1}{R} ({1}{R}: Return this card from your graveyard to the battlefield. + // It gains haste. Exile it at the beginning of the next end step or if it would + // leave the battlefield. Unearth only as a sorcery.) + addCard(Zone.GRAVEYARD, playerA, "Hellspark Elemental", 1); + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Unearth"); + + attack(1, playerA, "Hellspark Elemental"); + + setStopAt(2, PhaseStep.UNTAP); + execute(); + + assertGraveyardCount(playerA, "Hellspark Elemental", 0); + assertLife(playerB, 17); + + assertPermanentCount(playerA, "Hellspark Elemental", 0); + assertExileCount("Hellspark Elemental", 1); + } + +} \ No newline at end of file diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/SoulfireGrandMasterTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/SoulfireGrandMasterTest.java index 5d7dff07e3b..795122d82e1 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/SoulfireGrandMasterTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/SoulfireGrandMasterTest.java @@ -205,7 +205,7 @@ public class SoulfireGrandMasterTest extends CardTestPlayerBase { } /** * Test that if Soulfire Grand Master has left the battlefield - * spell have no longer lifelink + * spell has no longer lifelink */ @Test @@ -294,5 +294,39 @@ public class SoulfireGrandMasterTest extends CardTestPlayerBase { assertLife(playerB, 20); assertLife(playerA, 20); - } + } + /** + * With a Soulfire Grand Master in play, Deflecting Palm doesn't gain the caster life. + * It should as it has lifelink, and it's Deflecting Palm (an instant) dealing damage. + * I was playing against a human in Standard Constructed. + * + */ + + @Test + public void testWithDeflectingPalm() { + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1); + addCard(Zone.BATTLEFIELD, playerA, "Plains", 1); + // Instant -{R}{W} + // The next time a source of your choice would deal damage to you this turn, prevent that damage. + // If damage is prevented this way, Deflecting Palm deals that much damage to that source's controller. + addCard(Zone.HAND, playerA, "Deflecting Palm"); + addCard(Zone.BATTLEFIELD, playerA, "Soulfire Grand Master", 1); + + addCard(Zone.BATTLEFIELD, playerB, "Mountain", 1); + addCard(Zone.HAND, playerB, "Lightning Bolt", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Lightning Bolt", playerA); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Deflecting Palm", null, "Lightning Bolt"); + setChoice(playerA, "Lightning Bolt"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertGraveyardCount(playerB, "Lightning Bolt", 1); + assertGraveyardCount(playerA, "Deflecting Palm", 1); + + assertLife(playerB, 17); + assertLife(playerA, 23); // damage is prevented + lifelink + 3 + + } } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/asthough/PlayFromNonHandZoneTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/asthough/PlayFromNonHandZoneTest.java new file mode 100644 index 00000000000..a55b021a775 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/asthough/PlayFromNonHandZoneTest.java @@ -0,0 +1,82 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package org.mage.test.cards.asthough; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ + +public class PlayFromNonHandZoneTest extends CardTestPlayerBase { + + @Test + public void testWorldheartPhoenixNoMana() { + // Creature - Phoenix {3}{R} + // Flying + // You may cast Worldheart Phoenix from your graveyard by paying {W}{U}{B}{R}{G} rather than paying its mana cost. + // If you do, it enters the battlefield with two +1/+1 counters on it. + addCard(Zone.GRAVEYARD, playerA, "Worldheart Phoenix"); + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Worldheart Phoenix"); // can only be cast by {W}{U}{B}{R}{G} + + setStopAt(1, PhaseStep.END_COMBAT); + execute(); + + assertPermanentCount(playerA, "Worldheart Phoenix", 0); + + } + + + @Test + public void testWorldheartPhoenix() { + // Creature - Phoenix {3}{R} + // Flying + // You may cast Worldheart Phoenix from your graveyard by paying {W}{U}{B}{R}{G} rather than paying its mana cost. + // If you do, it enters the battlefield with two +1/+1 counters on it. + addCard(Zone.GRAVEYARD, playerA, "Worldheart Phoenix"); + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1); + addCard(Zone.BATTLEFIELD, playerA, "Island", 1); + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 1); + addCard(Zone.BATTLEFIELD, playerA, "Plains", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Worldheart Phoenix"); // can only be cast by {W}{U}{B}{R}{G} + + setStopAt(1, PhaseStep.END_COMBAT); + execute(); + + assertPermanentCount(playerA, "Worldheart Phoenix", 1); + + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/continuous/AlmsBeastTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/continuous/AlmsBeastTest.java new file mode 100644 index 00000000000..60ab1450bba --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/continuous/AlmsBeastTest.java @@ -0,0 +1,86 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package org.mage.test.cards.continuous; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ +public class AlmsBeastTest extends CardTestPlayerBase { + + @Test + public void testLifelink() { + // Creatures blocking or blocked by Alms Beast have lifelink. + addCard(Zone.BATTLEFIELD, playerA, "Alms Beast"); + + addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion"); + + attack(2, playerB, "Silvercoat Lion"); + block(2, playerA, "Alms Beast", "Silvercoat Lion"); + + setStopAt(2, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertGraveyardCount(playerB, "Silvercoat Lion", 1); + + assertLife(playerB, 22); // 20 + 2 from lifelink + } + + @Test + public void testNoLifelinkAfterCombat() { + // {T}: Rootwater Hunter deals 1 damage to target creature or player. + addCard(Zone.BATTLEFIELD, playerA, "Rootwater Hunter"); + addCard(Zone.BATTLEFIELD, playerA, "Plains"); + // Prevent all damage that would be dealt to target creature this turn. + addCard(Zone.HAND, playerA, "Shielded Passage"); + + + // Creatures blocking or blocked by Alms Beast have lifelink. + addCard(Zone.BATTLEFIELD, playerB, "Alms Beast"); + + attack(2, playerB, "Alms Beast"); + block(2, playerA, "Rootwater Hunter", "Alms Beast"); + castSpell(2, PhaseStep.DECLARE_BLOCKERS, playerA, "Shielded Passage", "Rootwater Hunter"); + + activateAbility(2, PhaseStep.POSTCOMBAT_MAIN, playerA, "{T}: ", playerB); // no life because lifelink ends at combat end + + setStopAt(2, PhaseStep.END_TURN); + execute(); + + assertGraveyardCount(playerA, "Shielded Passage", 1); + assertPermanentCount(playerA, "Rootwater Hunter", 1); + + assertLife(playerA, 21); // 20 + 1 from lifelink block + assertLife(playerB, 19); // -1 from Rootwater Hunter + } +} \ No newline at end of file diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/dynamicvalue/NumericSetToEffectValueTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/dynamicvalue/NumericSetToEffectValueTest.java new file mode 100644 index 00000000000..e4656134b23 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/dynamicvalue/NumericSetToEffectValueTest.java @@ -0,0 +1,72 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package org.mage.test.cards.dynamicvalue; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ + +public class NumericSetToEffectValueTest extends CardTestPlayerBase { + + + /** + * Check that the dealt damage is added to life + * + */ + @Test + public void ArmadilloCloakTest() { + addCard(Zone.BATTLEFIELD, playerA, "Forest", 2); + addCard(Zone.BATTLEFIELD, playerA, "Plains", 1); + // Enchant creature + // Enchanted creature gets +2/+2 and has trample. + // Whenever enchanted creature deals damage, you gain that much life. + addCard(Zone.HAND, playerA, "Armadillo Cloak"); + addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Armadillo Cloak", "Silvercoat Lion"); + + attack(3, playerA, "Silvercoat Lion"); + + setStopAt(3, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertPermanentCount(playerA,"Armadillo Cloak", 1); + assertPowerToughness(playerA, "Silvercoat Lion", 4, 4); + + assertLife(playerA, 24); + assertLife(playerB, 16); + + } + +} \ No newline at end of file diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/mana/ConditionalManaTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/mana/ConditionalManaTest.java index 197b794d575..d7a9ca20297 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/mana/ConditionalManaTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/mana/ConditionalManaTest.java @@ -29,7 +29,6 @@ package org.mage.test.cards.mana; import mage.constants.PhaseStep; import mage.constants.Zone; -import org.junit.Assert; import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBase; @@ -73,5 +72,36 @@ public class ConditionalManaTest extends CardTestPlayerBase { assertHandCount(playerA, "Silvercoat Lion", 1); // player A could not cast Silvercoat Lion because the conditional mana is not available } - + + @Test + public void testWorkingWithReflectingPool() { + addCard(Zone.BATTLEFIELD, playerA, "Cavern of Souls", 1); + addCard(Zone.BATTLEFIELD, playerA, "Reflecting Pool", 1); // can create white mana without restriction from the Cavern + addCard(Zone.HAND, playerA, "Silvercoat Lion", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Silvercoat Lion"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPermanentCount(playerA, "Silvercoat Lion", 1); + } + + @Test + public void testWorkingWithReflectingPool2() { + addCard(Zone.BATTLEFIELD, playerA, "Reflecting Pool", 1); // can create white mana without restriction from the Hive + addCard(Zone.BATTLEFIELD, playerA, "Sliver Hive", 1); + addCard(Zone.HAND, playerA, "Silvercoat Lion", 1); + + activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {1} to your mana pool"); + activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add to your mana pool one mana of any type"); + setChoice(playerA, "White"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Silvercoat Lion"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPermanentCount(playerA, "Silvercoat Lion", 1); + } } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/prevention/SwansOfBrynArgollTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/prevention/SwansOfBrynArgollTest.java index 4ef1adf1a67..f66f70aeb56 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/prevention/SwansOfBrynArgollTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/prevention/SwansOfBrynArgollTest.java @@ -64,4 +64,30 @@ public class SwansOfBrynArgollTest extends CardTestPlayerBase{ assertHandCount(playerA, 0); } + /** + * Since you can't prevent damage that Combust deals, it should be able to kill Swans of Bryn Argoll. + */ + @Test + public void testAgainstBanefire() { + // 4/3 Flying + // If a source would deal damage to Swans of Bryn Argoll, prevent that damage. The source's controller draws cards equal to the damage prevented this way. + addCard(Zone.BATTLEFIELD, playerA, "Swans of Bryn Argoll"); + + // Banefire deals X damage to target creature or player. + // If X is 5 or more, Banefire can't be countered by spells or abilities and the damage can't be prevented. + addCard(Zone.HAND, playerB, "Banefire", 1); + addCard(Zone.BATTLEFIELD, playerB, "Mountain", 8); + + castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Banefire", "Swans of Bryn Argoll"); + setChoice(playerB, "X=7"); + + setStopAt(2, PhaseStep.BEGIN_COMBAT); + execute(); + + assertGraveyardCount(playerB, "Banefire", 1); + assertPermanentCount(playerA, "Swans of Bryn Argoll", 0); + assertGraveyardCount(playerA, "Swans of Bryn Argoll", 1); + assertHandCount(playerA, 0); + + } } \ No newline at end of file diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/replacement/prevent/HarmsWayRedirectDamageTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/replacement/prevent/HarmsWayRedirectDamageTest.java index 6ef787e1103..f609e5ed8e8 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/replacement/prevent/HarmsWayRedirectDamageTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/replacement/prevent/HarmsWayRedirectDamageTest.java @@ -25,7 +25,8 @@ public class HarmsWayRedirectDamageTest extends CardTestPlayerBase { addCard(Zone.BATTLEFIELD, playerB, "Plains"); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB); - castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Harm's Way", "Lightning Bolt^targetPlayer=PlayerA"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Harm's Way", playerA); + setChoice(playerB, "Lightning Bolt"); setStopAt(1, PhaseStep.END_TURN); execute(); @@ -48,8 +49,9 @@ public class HarmsWayRedirectDamageTest extends CardTestPlayerBase { addCard(Zone.BATTLEFIELD, playerB, "Craw Wurm"); attack(2, playerB, "Craw Wurm"); - castSpell(2, PhaseStep.DECLARE_BLOCKERS, playerA, "Harm's Way", "Craw Wurm^targetPlayer=PlayerB"); - + castSpell(2, PhaseStep.DECLARE_BLOCKERS, playerA, "Harm's Way", playerB); + setChoice(playerA, "Craw Wurm"); + setStopAt(2, PhaseStep.END_TURN); execute(); @@ -76,8 +78,9 @@ public class HarmsWayRedirectDamageTest extends CardTestPlayerBase { // When Magma Phoenix dies, it deals 3 damage to each creature and each player. addCard(Zone.BATTLEFIELD, playerB, "Magma Phoenix"); - castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Harm's Way", "Magma Phoenix^targetPlayer=PlayerB"/**, - "When Magma Phoenix dies, Magma Phoenix deals 3 damage to each creature and each player"**/); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Harm's Way", playerB); + setChoice(playerA, "Magma Phoenix"); + /** When Magma Phoenix dies, Magma Phoenix deals 3 damage to each creature and each player **/ castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Lightning Bolt", "Magma Phoenix"); setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/rules/WorldEnchantmentsRuleTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/rules/WorldEnchantmentsRuleTest.java new file mode 100644 index 00000000000..4a0784a22d4 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/rules/WorldEnchantmentsRuleTest.java @@ -0,0 +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 org.mage.test.cards.rules; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ + +public class WorldEnchantmentsRuleTest extends CardTestPlayerBase { + + /** + * 704.5m If two or more permanents have the supertype world, all except the one that has had + * the world supertype for the shortest amount of time are put into their owners’ graveyards. + * In the event of a tie for the shortest amount of time, all are put into their owners’ graveyards. + * This is called the “world rule. + * + */ + @Test + public void TestTwoWorldEnchantsments() { + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1); + addCard(Zone.BATTLEFIELD, playerA, "Plains", 5); + addCard(Zone.HAND, playerA, "Nether Void", 1); + addCard(Zone.HAND, playerA, "Silvercoat Lion", 1); + + addCard(Zone.BATTLEFIELD, playerB, "Swamp", 7); + addCard(Zone.HAND, playerB, "Nether Void", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Nether Void"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Silvercoat Lion"); // just needed to get different craete time to second Nether Void + castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Nether Void"); + + setStopAt(2, PhaseStep.END_TURN); + execute(); + + assertPermanentCount(playerA, "Nether Void", 0); + assertPermanentCount(playerB, "Nether Void", 1); + } + +} \ No newline at end of file diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/HavengulLichTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/HavengulLichTest.java index 5ae362a72fb..61e62dd1ea2 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/single/HavengulLichTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/HavengulLichTest.java @@ -19,7 +19,7 @@ public class HavengulLichTest extends CardTestPlayerBase { activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}", "Prodigal Pyromancer"); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Prodigal Pyromancer"); - activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "{T}", playerB); + activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "{T}: {source} deals", playerB); setStopAt(1, PhaseStep.END_TURN); execute(); @@ -53,13 +53,16 @@ public class HavengulLichTest extends CardTestPlayerBase { @Test public void testCard2() { addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4); + // {1}: You may cast target creature card in a graveyard this turn. When you cast that card this turn, Havengul Lich + // gains all activated abilities of that card until end of turn. addCard(Zone.BATTLEFIELD, playerA, "Havengul Lich"); + // {T}: Prodigal Pyromancer deals 1 damage to target creature or player. addCard(Zone.GRAVEYARD, playerA, "Prodigal Pyromancer"); - activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}", "Prodigal Pyromancer"); + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}: You may", "Prodigal Pyromancer"); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Prodigal Pyromancer"); - activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}", playerB); - activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}", playerB); + activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: {source} deals", playerB); + activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: {source} deals", playerB); // only inm turn 1, so Havengul Lich has the abilit ylost now setStopAt(3, PhaseStep.BEGIN_COMBAT); execute(); diff --git a/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java b/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java index 5af22397fb8..bf48c2f8738 100644 --- a/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java +++ b/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java @@ -360,16 +360,24 @@ public class TestPlayer extends ComputerPlayer { MageObject targetObject = game.getObject(targetId); if (targetObject != null) { for (String choose2: choices) { - if (targetObject.getName().equals(choose2)) { - List alreadyTargetted = target.getTargets(); - if (t.canTarget(targetObject.getId(), game)) { - if (alreadyTargetted != null && !alreadyTargetted.contains(targetObject.getId())) { - target.add(targetObject.getId(), game); - choices.remove(choose2); - return true; + String[] targetList = choose2.split("\\^"); + boolean targetFound = false; + for (String targetName: targetList) { + if (targetObject.getName().equals(targetName)) { + List alreadyTargetted = target.getTargets(); + if (t.canTarget(targetObject.getId(), game)) { + if (alreadyTargetted != null && !alreadyTargetted.contains(targetObject.getId())) { + target.add(targetObject.getId(), game); + choices.remove(choose2); + targetFound = true; + } } } } + if (targetFound) { + choices.remove(choose2); + return true; + } } } } diff --git a/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java b/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java index 1b1e73dc944..1a3774626e3 100644 --- a/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java +++ b/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java @@ -448,7 +448,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement @Override public void assertPermanentCount(Player player, String cardName, int count) throws AssertionError { int actualCount = 0; - for (Permanent permanent : currentGame.getBattlefield().getAllPermanents()) { + for (Permanent permanent : currentGame.getBattlefield().getAllActivePermanents()) { if (permanent.getControllerId().equals(player.getId())) { if (permanent.getName().equals(cardName)) { actualCount++; @@ -490,12 +490,32 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement break; } } - Assert.assertNotNull("There is no such permanent on the battlefield, cardName=" + cardName, found); - Assert.assertEquals("(Battlefield) Counter counts are not equal (" + cardName + ":" + type + ")", count, found.getCounters().getCount(type)); } + /** + * Assert counter count on a card in exile + * + * @param cardName Name of the cards that should be counted. + * @param type Type of the counter that should be counted. + * @param count Expected count. + */ + public void assertCounterOnExiledCardCount(String cardName, CounterType type, int count) throws AssertionError { + Card found = null; + if (found == null) { + for (Card card : currentGame.getExile().getAllCards(currentGame)) { + if (card.getName().equals(cardName)) { + found = card; + break; + } + } + + } + Assert.assertNotNull("There is no such card in the exile, cardName=" + cardName, found); + Assert.assertEquals("(Exile) Counter counts are not equal (" + cardName + ":" + type + ")", count, found.getCounters(currentGame).getCount(type)); + } + /** * Assert counter count on a player * diff --git a/Mage.Tests/src/test/java/org/mage/test/utils/ManaOptionsTest.java b/Mage.Tests/src/test/java/org/mage/test/utils/ManaOptionsTest.java index eaf0af7d8b2..b1e78318af3 100644 --- a/Mage.Tests/src/test/java/org/mage/test/utils/ManaOptionsTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/utils/ManaOptionsTest.java @@ -35,7 +35,8 @@ import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBase; /** - * + * This test checks if the calculated possible mana options are correct related to the given mana sources available. + * * @author LevelX2 */ public class ManaOptionsTest extends CardTestPlayerBase { diff --git a/Mage.Tests/src/test/java/org/mage/test/utils/ManaUtilTest.java b/Mage.Tests/src/test/java/org/mage/test/utils/ManaUtilTest.java index af2eac6e4af..07bc006edf3 100644 --- a/Mage.Tests/src/test/java/org/mage/test/utils/ManaUtilTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/utils/ManaUtilTest.java @@ -46,6 +46,8 @@ public class ManaUtilTest extends CardTestPlayerBase { testManaToPayVsLand("{1}{R}", "Cavern of Souls", 2, 2); // can't auto choose to pay testManaToPayVsLand("{2}", "Cavern of Souls", 2, 2); // can't auto choose to pay + testManaToPayVsLand("{2}", "Eldrazi Temple", 2, 2); // can't auto choose to pay + // hybrid mana testManaToPayVsLand("{W/R}{W/R}{W/R}", "Sacred Foundry", 2, 1); // auto choose for hybrid mana: choose any testManaToPayVsLand("{R}{W/R}", "Sacred Foundry", 2, RedManaAbility.class); // auto choose for hybrid mana: we should choose {R} @@ -122,7 +124,7 @@ public class ManaUtilTest extends CardTestPlayerBase { * @return */ private HashMap getManaAbilities(Card card) { - HashMap useableAbilities = new LinkedHashMap(); + HashMap useableAbilities = new LinkedHashMap<>(); for (Ability ability: card.getAbilities()) { if (ability instanceof ManaAbility) { ability.newId(); // we need to assign id manually as we are not in game diff --git a/Mage/src/mage/MageObject.java b/Mage/src/mage/MageObject.java index 2ff921a7c6b..0694e0dfd7f 100644 --- a/Mage/src/mage/MageObject.java +++ b/Mage/src/mage/MageObject.java @@ -13,6 +13,7 @@ import mage.game.Game; public interface MageObject extends MageItem, Serializable { String getName(); + String getIdName(); String getLogName(); String getImageName(); void setName(String name); diff --git a/Mage/src/mage/MageObjectImpl.java b/Mage/src/mage/MageObjectImpl.java index ea8ec877183..075dfe1dc62 100644 --- a/Mage/src/mage/MageObjectImpl.java +++ b/Mage/src/mage/MageObjectImpl.java @@ -40,6 +40,7 @@ import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.keyword.ChangelingAbility; import mage.constants.CardType; import mage.game.Game; +import mage.util.CardUtil; import mage.util.GameLog; public abstract class MageObjectImpl implements MageObject { @@ -96,6 +97,11 @@ public abstract class MageObjectImpl implements MageObject { return name; } + @Override + public String getIdName() { + return getName() + " ["+getId().toString().substring(0,3) +"]"; + } + @Override public String getLogName() { return GameLog.getColoredObjectName(this); @@ -176,17 +182,14 @@ public abstract class MageObjectImpl implements MageObject { } if (this.subtype.contains(value)) { return true; - } - else { // checking for Changeling - // first make sure input parameter is not creature type + } else { // checking for Changeling + // first make sure input parameter is a creature type // if so, then ChangelingAbility doesn't matter - if (value.equals("Mountain") || value.equals("Island") || value.equals("Plains") - || value.equals("Forest") || value.equals("Swamp") || value.equals("Aura") - || value.equals("Equipment") || value.equals("Fortification") || value.equals("Shrine")) { + if (CardUtil.isNonCreatureSubtype(value)) { return false; } // as it is creature subtype, then check the existence of Changeling - return abilities.contains(ChangelingAbility.getInstance()) || this.subtype.contains(ChangelingAbility.ALL_CREATURE_TYPE); + return abilities.contains(ChangelingAbility.getInstance()) || this.subtype.contains(ChangelingAbility.ALL_CREATURE_TYPE); } } diff --git a/Mage/src/mage/abilities/AbilityImpl.java b/Mage/src/mage/abilities/AbilityImpl.java index 2e4a0f8e45c..50f08e26194 100644 --- a/Mage/src/mage/abilities/AbilityImpl.java +++ b/Mage/src/mage/abilities/AbilityImpl.java @@ -334,7 +334,7 @@ public abstract class AbilityImpl implements Ability { } if (getTargets().size() > 0 && getTargets().chooseTargets(getEffects().get(0).getOutcome(), this.controllerId, this, game) == false) { if ((variableManaCost != null || announceString != null) && !game.isSimulation()) { - game.informPlayer(controller, new StringBuilder(sourceObject != null ? sourceObject.getLogName(): "").append(": no valid targets with this value of X").toString()); + game.informPlayer(controller, (sourceObject != null ? sourceObject.getIdName(): "") + ": no valid targets with this value of X"); } return false; // when activation of ability is canceled during target selection } @@ -927,6 +927,9 @@ public abstract class AbilityImpl implements Ability { } } } + if (object instanceof Permanent) { + return ((Permanent) object).isPhasedIn(); + } return true; } diff --git a/Mage/src/mage/abilities/common/DealsCombatDamageToAPlayerTriggeredAbility.java b/Mage/src/mage/abilities/common/DealsCombatDamageToAPlayerTriggeredAbility.java index ea4290e0416..38f3642e8a7 100644 --- a/Mage/src/mage/abilities/common/DealsCombatDamageToAPlayerTriggeredAbility.java +++ b/Mage/src/mage/abilities/common/DealsCombatDamageToAPlayerTriggeredAbility.java @@ -25,7 +25,6 @@ * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package mage.abilities.common; import mage.constants.Zone; @@ -34,7 +33,6 @@ import mage.abilities.effects.Effect; import mage.game.Game; import mage.game.events.DamagedPlayerEvent; import mage.game.events.GameEvent; -import mage.game.events.GameEvent.EventType; import mage.target.targetpointer.FixedTarget; /** @@ -42,6 +40,7 @@ import mage.target.targetpointer.FixedTarget; * @author BetaSteward_at_googlemail.com */ public class DealsCombatDamageToAPlayerTriggeredAbility extends TriggeredAbilityImpl { + private boolean setTargetPointer; public DealsCombatDamageToAPlayerTriggeredAbility(Effect effect, boolean optional) { @@ -70,12 +69,12 @@ public class DealsCombatDamageToAPlayerTriggeredAbility extends TriggeredAbility @Override public boolean checkTrigger(GameEvent event, Game game) { - if (event.getSourceId().equals(this.sourceId) + if (event.getSourceId().equals(getSourceId()) && ((DamagedPlayerEvent) event).isCombatDamage()) { if (setTargetPointer) { for (Effect effect : this.getEffects()) { - effect.setTargetPointer(new FixedTarget(event.getPlayerId())); - effect.setValue("damage", event.getAmount()); + effect.setTargetPointer(new FixedTarget(event.getPlayerId())); + effect.setValue("damage", event.getAmount()); } } return true; diff --git a/Mage/src/mage/abilities/common/DealsDamageAttachedTriggeredAbility.java b/Mage/src/mage/abilities/common/DealsDamageAttachedTriggeredAbility.java new file mode 100644 index 00000000000..dd7e55a5aab --- /dev/null +++ b/Mage/src/mage/abilities/common/DealsDamageAttachedTriggeredAbility.java @@ -0,0 +1,62 @@ +/* + * 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.common; + +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.Effect; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; + +/** + * + * @author LevelX2 + */ + +public class DealsDamageAttachedTriggeredAbility extends TriggeredAbilityImpl { + + public DealsDamageAttachedTriggeredAbility(Zone zone, Effect effect, boolean optional) { + super(zone, effect, optional); + } + + public DealsDamageAttachedTriggeredAbility(final DealsDamageAttachedTriggeredAbility ability) { + super(ability); + } + + @Override + public DealsDamageAttachedTriggeredAbility copy() { + return new DealsDamageAttachedTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType().equals(GameEvent.EventType.DAMAGED_CREATURE) + || event.getType().equals(GameEvent.EventType.DAMAGED_PLAYER) + || event.getType().equals(GameEvent.EventType.DAMAGED_PLANESWALKER); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + Permanent enchantment = game.getPermanent(this.getSourceId()); + if (enchantment == null || enchantment.getAttachedTo() == null) { + return false; + } + Permanent enchanted = game.getPermanent(enchantment.getAttachedTo()); + if (enchanted != null && event.getSourceId().equals(enchanted.getId())) { + for (Effect effect : this.getEffects()) { + effect.setValue("damage", event.getAmount()); + } + return true; + } + return false; + } + + @Override + public String getRule() { + return "Whenever enchanted creature deals damage, " + super.getRule(); + } +} diff --git a/Mage/src/mage/abilities/common/DealsDamageGainLifeSourceTriggeredAbility.java b/Mage/src/mage/abilities/common/DealsDamageGainLifeSourceTriggeredAbility.java index 5da95952afb..026276a1f71 100644 --- a/Mage/src/mage/abilities/common/DealsDamageGainLifeSourceTriggeredAbility.java +++ b/Mage/src/mage/abilities/common/DealsDamageGainLifeSourceTriggeredAbility.java @@ -28,7 +28,6 @@ package mage.abilities.common; -import static javax.xml.bind.JAXBIntrospector.getValue; import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.Effect; diff --git a/Mage/src/mage/abilities/common/DealsDamageToACreatureAttachedTriggeredAbility.java b/Mage/src/mage/abilities/common/DealsDamageToACreatureAttachedTriggeredAbility.java index 9405da194e8..816cee3d4fd 100644 --- a/Mage/src/mage/abilities/common/DealsDamageToACreatureAttachedTriggeredAbility.java +++ b/Mage/src/mage/abilities/common/DealsDamageToACreatureAttachedTriggeredAbility.java @@ -34,7 +34,6 @@ import mage.constants.Zone; import mage.game.Game; import mage.game.events.DamagedCreatureEvent; import mage.game.events.GameEvent; -import mage.game.events.GameEvent.EventType; import mage.game.permanent.Permanent; import mage.target.targetpointer.FixedTarget; diff --git a/Mage/src/mage/abilities/costs/common/RemoveVariableCountersSourceCost.java b/Mage/src/mage/abilities/costs/common/RemoveVariableCountersSourceCost.java index 29cc8447116..49020791d4c 100644 --- a/Mage/src/mage/abilities/costs/common/RemoveVariableCountersSourceCost.java +++ b/Mage/src/mage/abilities/costs/common/RemoveVariableCountersSourceCost.java @@ -54,11 +54,22 @@ public class RemoveVariableCountersSourceCost extends VariableCostImpl { public RemoveVariableCountersSourceCost(Counter counter) { this(counter, 0); } + + public RemoveVariableCountersSourceCost(Counter counter, int minimalCountersToPay, String text) { + this(counter, minimalCountersToPay); + this.text = text; + } + + public RemoveVariableCountersSourceCost(Counter counter, String text) { + this(counter); + this.text = text; + } public RemoveVariableCountersSourceCost(final RemoveVariableCountersSourceCost cost) { super(cost); this.minimalCountersToPay = cost.minimalCountersToPay; this.counterName = cost.counterName; + this.text = cost.text; } @Override diff --git a/Mage/src/mage/abilities/dynamicvalue/common/NumericSetToEffectValues.java b/Mage/src/mage/abilities/dynamicvalue/common/NumericSetToEffectValues.java new file mode 100644 index 00000000000..b9ab0d6d72d --- /dev/null +++ b/Mage/src/mage/abilities/dynamicvalue/common/NumericSetToEffectValues.java @@ -0,0 +1,58 @@ +/* + * 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.dynamicvalue.common; + +import mage.abilities.Ability; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.effects.Effect; +import mage.game.Game; + +/** + * + * @author LevelX2 + */ + +public class NumericSetToEffectValues implements DynamicValue { + + private final String message; + private final String valueKey; + + + public NumericSetToEffectValues(String message, String valueKey) { + this.message = message; + this.valueKey = valueKey; + } + + public NumericSetToEffectValues(final NumericSetToEffectValues dynamicValue) { + super(); + this.message = dynamicValue.message; + this.valueKey = dynamicValue.valueKey; + } + + @Override + public int calculate(Game game, Ability source, Effect effect) { + Object object = effect.getValue(valueKey); + if (object instanceof Integer) { + return (Integer) object; + } + return 0; + } + + @Override + public NumericSetToEffectValues copy() { + return new NumericSetToEffectValues(this); + } + + @Override + public String toString() { + return "X"; + } + + @Override + public String getMessage() { + return message; + } +} diff --git a/Mage/src/mage/abilities/dynamicvalue/common/SignInversionDynamicValue.java b/Mage/src/mage/abilities/dynamicvalue/common/SignInversionDynamicValue.java index 3e927496ed6..2b50242ec4c 100644 --- a/Mage/src/mage/abilities/dynamicvalue/common/SignInversionDynamicValue.java +++ b/Mage/src/mage/abilities/dynamicvalue/common/SignInversionDynamicValue.java @@ -6,7 +6,7 @@ import mage.abilities.effects.Effect; import mage.game.Game; public class SignInversionDynamicValue implements DynamicValue { - private DynamicValue value; + private final DynamicValue value; public SignInversionDynamicValue(DynamicValue value) { this.value = value.copy(); diff --git a/Mage/src/mage/abilities/effects/PlaneswalkerRedirectionEffect.java b/Mage/src/mage/abilities/effects/PlaneswalkerRedirectionEffect.java index 8a1ec5aa8ab..3e4aad2d6e4 100644 --- a/Mage/src/mage/abilities/effects/PlaneswalkerRedirectionEffect.java +++ b/Mage/src/mage/abilities/effects/PlaneswalkerRedirectionEffect.java @@ -64,31 +64,35 @@ public class PlaneswalkerRedirectionEffect extends RedirectionEffect { return new PlaneswalkerRedirectionEffect(this); } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.DAMAGE_PLAYER; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == EventType.DAMAGE_PLAYER) { - DamageEvent damageEvent = (DamageEvent)event; - UUID playerId = getSourceControllerId(event.getSourceId(), game); - if (!damageEvent.isCombatDamage() && game.getOpponents(event.getTargetId()).contains(playerId)) { - Player target = game.getPlayer(event.getTargetId()); - Player player = game.getPlayer(playerId); - if (target != null && player != null) { - int numPlaneswalkers = game.getBattlefield().countAll(filter, target.getId(), game); - if (numPlaneswalkers > 0 && player.chooseUse(outcome, "Redirect damage to planeswalker?", game)) { - redirectTarget = new TargetPermanent(filter); - if (numPlaneswalkers == 1) { - redirectTarget.add(game.getBattlefield().getAllActivePermanents(filter, target.getId(), game).get(0).getId(), game); - } - else { - player.choose(Outcome.Damage, redirectTarget, null, game); - } - if (!game.isSimulation()) - game.informPlayers(new StringBuilder(player.getLogName()).append(" redirects ") + DamageEvent damageEvent = (DamageEvent)event; + UUID playerId = getSourceControllerId(event.getSourceId(), game); + if (!damageEvent.isCombatDamage() && game.getOpponents(event.getTargetId()).contains(playerId)) { + Player target = game.getPlayer(event.getTargetId()); + Player player = game.getPlayer(playerId); + if (target != null && player != null) { + int numPlaneswalkers = game.getBattlefield().countAll(filter, target.getId(), game); + if (numPlaneswalkers > 0 && player.chooseUse(outcome, "Redirect damage to planeswalker?", game)) { + redirectTarget = new TargetPermanent(filter); + if (numPlaneswalkers == 1) { + redirectTarget.add(game.getBattlefield().getAllActivePermanents(filter, target.getId(), game).get(0).getId(), game); + } + else { + player.choose(Outcome.Damage, redirectTarget, null, game); + } + if (!game.isSimulation()) { + game.informPlayers(new StringBuilder(player.getLogName()).append(" redirects ") .append(event.getAmount()) .append(" damage to ") .append(game.getPermanent(redirectTarget.getFirstTarget()).getLogName()).toString()); - return true; } + return true; } } } diff --git a/Mage/src/mage/abilities/effects/ReplacementEffectImpl.java b/Mage/src/mage/abilities/effects/ReplacementEffectImpl.java index 1243f4a3f3b..48b96a68bee 100644 --- a/Mage/src/mage/abilities/effects/ReplacementEffectImpl.java +++ b/Mage/src/mage/abilities/effects/ReplacementEffectImpl.java @@ -79,9 +79,4 @@ public abstract class ReplacementEffectImpl extends ContinuousEffectImpl impleme throw new UnsupportedOperationException("Not used for replacemnt effect."); } - @Override - public boolean checksEventType(GameEvent event, Game game) { - return true; - } - } diff --git a/Mage/src/mage/abilities/effects/common/AddConditionalColorlessManaEffect.java b/Mage/src/mage/abilities/effects/common/AddConditionalColorlessManaEffect.java index 42d9acb1b85..495d234b7a5 100644 --- a/Mage/src/mage/abilities/effects/common/AddConditionalColorlessManaEffect.java +++ b/Mage/src/mage/abilities/effects/common/AddConditionalColorlessManaEffect.java @@ -26,7 +26,7 @@ public class AddConditionalColorlessManaEffect extends ManaEffect { super(); this.amount = amount; this.manaBuilder = manaBuilder; - staticText = "Add " + amount + " to your mana pool. " + manaBuilder.getRule(); + staticText = "Add {" + amount + "} to your mana pool. " + manaBuilder.getRule(); } public AddConditionalColorlessManaEffect(final AddConditionalColorlessManaEffect effect) { diff --git a/Mage/src/mage/abilities/effects/common/AddContinuousEffectToGame.java b/Mage/src/mage/abilities/effects/common/AddContinuousEffectToGame.java index 1cfcdae0e27..a209a9a65b7 100644 --- a/Mage/src/mage/abilities/effects/common/AddContinuousEffectToGame.java +++ b/Mage/src/mage/abilities/effects/common/AddContinuousEffectToGame.java @@ -59,8 +59,7 @@ public class AddContinuousEffectToGame extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - ContinuousEffect effectToAdd = effect.copy(); - game.addEffect(effectToAdd, source); + game.addEffect(effect, source); return true; } } diff --git a/Mage/src/mage/abilities/effects/common/AddManaInAnyCombinationEffect.java b/Mage/src/mage/abilities/effects/common/AddManaInAnyCombinationEffect.java index 2e6ce2a8e41..19f56cfeb80 100644 --- a/Mage/src/mage/abilities/effects/common/AddManaInAnyCombinationEffect.java +++ b/Mage/src/mage/abilities/effects/common/AddManaInAnyCombinationEffect.java @@ -1,107 +1,144 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ - -package mage.abilities.effects.common; - -import java.util.ArrayList; -import java.util.Arrays; -import mage.Mana; -import mage.abilities.Ability; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.dynamicvalue.common.StaticValue; -import mage.constants.ColoredManaSymbol; -import mage.game.Game; -import mage.players.Player; -import mage.util.CardUtil; - -/** - * - * @author LevelX2 - */ -public class AddManaInAnyCombinationEffect extends ManaEffect { - - private ArrayList manaSymbols = new ArrayList<>(); - private final DynamicValue amount; - - public AddManaInAnyCombinationEffect(int amount) { - this(new StaticValue(amount), ColoredManaSymbol.B, ColoredManaSymbol.U, ColoredManaSymbol.R, ColoredManaSymbol.W, ColoredManaSymbol.G); - } - - public AddManaInAnyCombinationEffect(int amount, ColoredManaSymbol... coloredManaSymbols) { - this(new StaticValue(amount), coloredManaSymbols); - } - - public AddManaInAnyCombinationEffect(DynamicValue amount, ColoredManaSymbol... coloredManaSymbols) { - super(); - this.manaSymbols.addAll(Arrays.asList(coloredManaSymbols)); - this.amount = amount; - this.staticText = setText(); - } - - public AddManaInAnyCombinationEffect(final AddManaInAnyCombinationEffect effect) { - super(effect); - this.manaSymbols = effect.manaSymbols; - this.amount = effect.amount; - } - - @Override - public AddManaInAnyCombinationEffect copy() { - return new AddManaInAnyCombinationEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - if (player != null){ - Mana mana = new Mana(); - int amountOfManaLeft = amount.calculate(game, source, this); - - while (amountOfManaLeft > 0 && player.isInGame()) { - for (ColoredManaSymbol coloredManaSymbol: manaSymbols) { - int number = player.getAmount(0, amountOfManaLeft, new StringBuilder("How many ").append(coloredManaSymbol.name()).append(" mana?").toString(), game); - if (number > 0) { - for (int i = 0; i < number; i++) { - mana.add(new Mana(coloredManaSymbol)); - } - amountOfManaLeft -= number; - } - if (amountOfManaLeft == 0) { - break; - } - } - } - checkToFirePossibleEvents(mana, game, source); - player.getManaPool().addMana(mana, game, source); - return true; - } - return false; - } - - @Override - public Mana getMana(Game game, Ability source) { - return null; - } - - private String setText() { - StringBuilder sb = new StringBuilder("Add "); - sb.append(CardUtil.numberToText(amount.toString())); - sb.append(" mana in any combination of "); - if (manaSymbols.size() == 5) { - sb.append("colors"); - } else { - int i = 0; - for (ColoredManaSymbol coloredManaSymbol: manaSymbols) { - i++; - if (i > 1) { - sb.append(" and/or "); - } - sb.append("{").append(coloredManaSymbol.toString()).append("}"); - } - } - sb.append(" to your mana pool"); - return sb.toString(); - } -} +/* + * 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.effects.common; + +import java.util.ArrayList; +import java.util.Arrays; +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.constants.ColoredManaSymbol; +import mage.game.Game; +import mage.players.Player; +import mage.util.CardUtil; + +/** + * + * @author LevelX2 + */ +public class AddManaInAnyCombinationEffect extends ManaEffect { + + private ArrayList manaSymbols = new ArrayList<>(); + private final DynamicValue amount; + + public AddManaInAnyCombinationEffect(int amount) { + this(new StaticValue(amount), ColoredManaSymbol.B, ColoredManaSymbol.U, ColoredManaSymbol.R, ColoredManaSymbol.W, ColoredManaSymbol.G); + } + + public AddManaInAnyCombinationEffect(int amount, ColoredManaSymbol... coloredManaSymbols) { + this(new StaticValue(amount), coloredManaSymbols); + } + + public AddManaInAnyCombinationEffect(DynamicValue amount, ColoredManaSymbol... coloredManaSymbols) { + super(); + this.manaSymbols.addAll(Arrays.asList(coloredManaSymbols)); + this.amount = amount; + this.staticText = setText(); + } + + public AddManaInAnyCombinationEffect(int amount, String text) { + this(amount); + this.staticText = text; + } + + public AddManaInAnyCombinationEffect(int amount, String text, ColoredManaSymbol... coloredManaSymbols) { + this(amount, coloredManaSymbols); + this.staticText = text; + } + + public AddManaInAnyCombinationEffect(DynamicValue amount, String text, ColoredManaSymbol... coloredManaSymbols) { + this(amount, coloredManaSymbols); + this.staticText = text; + } + + public AddManaInAnyCombinationEffect(final AddManaInAnyCombinationEffect effect) { + super(effect); + this.manaSymbols = effect.manaSymbols; + this.amount = effect.amount; + } + + @Override + public AddManaInAnyCombinationEffect copy() { + return new AddManaInAnyCombinationEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player != null){ + Mana mana = new Mana(); + int amountOfManaLeft = amount.calculate(game, source, this); + + while (amountOfManaLeft > 0 && player.isInGame()) { + for (ColoredManaSymbol coloredManaSymbol: manaSymbols) { + int number = player.getAmount(0, amountOfManaLeft, new StringBuilder("How many ").append(coloredManaSymbol.name()).append(" mana?").toString(), game); + if (number > 0) { + for (int i = 0; i < number; i++) { + mana.add(new Mana(coloredManaSymbol)); + } + amountOfManaLeft -= number; + } + if (amountOfManaLeft == 0) { + break; + } + } + } + checkToFirePossibleEvents(mana, game, source); + player.getManaPool().addMana(mana, game, source); + return true; + } + return false; + } + + @Override + public Mana getMana(Game game, Ability source) { + return null; + } + + private String setText() { + StringBuilder sb = new StringBuilder("Add "); + sb.append(CardUtil.numberToText(amount.toString())); + sb.append(" mana in any combination of "); + if (manaSymbols.size() == 5) { + sb.append("colors"); + } else { + int i = 0; + for (ColoredManaSymbol coloredManaSymbol: manaSymbols) { + i++; + if (i > 1) { + sb.append(" and/or "); + } + sb.append("{").append(coloredManaSymbol.toString()).append("}"); + } + } + sb.append(" to your mana pool"); + return sb.toString(); + } +} diff --git a/Mage/src/mage/abilities/effects/common/ExileTargetForSourceEffect.java b/Mage/src/mage/abilities/effects/common/ExileTargetForSourceEffect.java index dd7769ea75c..99b3a1e0bdc 100644 --- a/Mage/src/mage/abilities/effects/common/ExileTargetForSourceEffect.java +++ b/Mage/src/mage/abilities/effects/common/ExileTargetForSourceEffect.java @@ -71,11 +71,11 @@ public class ExileTargetForSourceEffect extends OneShotEffect { Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); UUID exileId = CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter()); if (permanent != null) { - return controller.moveCardToExileWithInfo(permanent, exileId, sourceObject.getName(), source.getSourceId(), game, Zone.BATTLEFIELD, true); + return controller.moveCardToExileWithInfo(permanent, exileId, sourceObject.getIdName(), source.getSourceId(), game, Zone.BATTLEFIELD, true); } else { Card card = game.getCard(getTargetPointer().getFirst(game, source)); if (card != null) { - return controller.moveCardToExileWithInfo(card, exileId, sourceObject.getName(), source.getSourceId(), game, game.getState().getZone(card.getId()), true); + return controller.moveCardToExileWithInfo(card, exileId, sourceObject.getIdName(), source.getSourceId(), game, game.getState().getZone(card.getId()), true); } } } diff --git a/Mage/src/mage/abilities/effects/common/GainLifeEffect.java b/Mage/src/mage/abilities/effects/common/GainLifeEffect.java index 064edd652aa..c01b6923cf2 100644 --- a/Mage/src/mage/abilities/effects/common/GainLifeEffect.java +++ b/Mage/src/mage/abilities/effects/common/GainLifeEffect.java @@ -86,11 +86,13 @@ public class GainLifeEffect extends OneShotEffect { StringBuilder sb = new StringBuilder(); String message = life.getMessage(); sb.append("you gain "); - if (message.isEmpty() || !message.equals("1")) { + if (message.startsWith("that")) { + sb.append(message).append(" "); + } else if (message.isEmpty() || !message.equals("1")) { sb.append(life).append(" "); } sb.append("life"); - if (message.length() > 0) { + if (message.length() > 0 && !message.startsWith("that")) { sb.append(message.equals("1") ? " equal to the number of " : " for each "); sb.append(message); } diff --git a/Mage/src/mage/abilities/effects/common/PutOnLibraryTargetEffect.java b/Mage/src/mage/abilities/effects/common/PutOnLibraryTargetEffect.java index 82e673820dd..a337cfc3d00 100644 --- a/Mage/src/mage/abilities/effects/common/PutOnLibraryTargetEffect.java +++ b/Mage/src/mage/abilities/effects/common/PutOnLibraryTargetEffect.java @@ -144,25 +144,25 @@ public class PutOnLibraryTargetEffect extends OneShotEffect { @Override public String getText(Mode mode) { - StringBuilder sb = new StringBuilder(); if (this.staticText != null && !this.staticText.isEmpty()) { - sb.append(staticText); - } else { - Target target = mode.getTargets().get(0); - sb.append("Put "); - if (target.getMaxNumberOfTargets() == 0) { - sb.append("any number of "); - } else { - if (target.getMaxNumberOfTargets() != 1 || target.getNumberOfTargets() != 1) { - if (target.getMaxNumberOfTargets() > target.getNumberOfTargets()) { - sb.append("up to "); - } - sb.append(CardUtil.numberToText(target.getMaxNumberOfTargets())).append(" "); - } - } - sb.append("target ").append(mode.getTargets().get(0).getTargetName()).append(" on "); - sb.append(onTop ? "top" : "the bottom").append(" of it's owner's library"); + return staticText; } + StringBuilder sb = new StringBuilder(); + Target target = mode.getTargets().get(0); + sb.append("Put "); + if (target.getMaxNumberOfTargets() == 0) { + sb.append("any number of "); + } else { + if (target.getMaxNumberOfTargets() != 1 || target.getNumberOfTargets() != 1) { + if (target.getMaxNumberOfTargets() > target.getNumberOfTargets()) { + sb.append("up to "); + } + sb.append(CardUtil.numberToText(target.getMaxNumberOfTargets())).append(" "); + } + } + sb.append("target ").append(mode.getTargets().get(0).getTargetName()).append(" on "); + sb.append(onTop ? "top" : "the bottom").append(" of it's owner's library"); + return sb.toString(); } diff --git a/Mage/src/mage/abilities/effects/common/SacrificeAllEffect.java b/Mage/src/mage/abilities/effects/common/SacrificeAllEffect.java index 57a93b530df..12ca8a7485a 100644 --- a/Mage/src/mage/abilities/effects/common/SacrificeAllEffect.java +++ b/Mage/src/mage/abilities/effects/common/SacrificeAllEffect.java @@ -31,11 +31,11 @@ package mage.abilities.effects.common; import java.util.ArrayList; import java.util.List; import java.util.UUID; -import mage.constants.Outcome; import mage.abilities.Ability; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.effects.OneShotEffect; +import mage.constants.Outcome; import mage.filter.common.FilterControlledPermanent; import mage.game.Game; import mage.game.permanent.Permanent; @@ -110,7 +110,7 @@ public class SacrificeAllEffect extends OneShotEffect { private void setText() { StringBuilder sb = new StringBuilder(); - sb.append("Each players sacrifices "); + sb.append("Each player sacrifices "); if (amount.toString().equals("X")) { sb.append(amount.toString()); } else { diff --git a/Mage/src/mage/abilities/effects/common/continuous/BecomesCreatureSourceEffect.java b/Mage/src/mage/abilities/effects/common/continuous/BecomesCreatureSourceEffect.java index 74eff7f8a2f..ee60cdf57eb 100644 --- a/Mage/src/mage/abilities/effects/common/continuous/BecomesCreatureSourceEffect.java +++ b/Mage/src/mage/abilities/effects/common/continuous/BecomesCreatureSourceEffect.java @@ -32,7 +32,6 @@ import mage.MageInt; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; -import mage.cards.Card; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Layer; diff --git a/Mage/src/mage/abilities/effects/common/continuous/LoseAbilityOrAnotherAbilityTargetEffect.java b/Mage/src/mage/abilities/effects/common/continuous/LoseAbilityOrAnotherAbilityTargetEffect.java new file mode 100644 index 00000000000..beec0ac0a2b --- /dev/null +++ b/Mage/src/mage/abilities/effects/common/continuous/LoseAbilityOrAnotherAbilityTargetEffect.java @@ -0,0 +1,130 @@ +/* + * 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.effects.common.continuous; + +import java.util.HashSet; +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.choices.ChoiceImpl; +import mage.constants.Duration; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.Target; + +/** + * + * @author a + */ +public class LoseAbilityOrAnotherAbilityTargetEffect extends LoseAbilityTargetEffect { + + protected Ability ability2; + + public LoseAbilityOrAnotherAbilityTargetEffect(Ability ability, Ability ability2) { + this(ability, ability2, Duration.WhileOnBattlefield); + } + + public LoseAbilityOrAnotherAbilityTargetEffect(Ability ability, Ability ability2, Duration duration) { + super(ability, duration); + this.ability2 = ability2; + } + + public LoseAbilityOrAnotherAbilityTargetEffect(final LoseAbilityOrAnotherAbilityTargetEffect effect) { + super(effect); + this.ability2 = effect.ability2.copy(); + } + + @Override + public LoseAbilityOrAnotherAbilityTargetEffect copy() { + return new LoseAbilityOrAnotherAbilityTargetEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(source.getFirstTarget()); + if (permanent != null) { + ChoiceImpl chooseAbility = new ChoiceImpl(); + chooseAbility.setMessage("What ability do you wish to remove?"); + + HashSet choice = new HashSet<>(); + + if (permanent.getAbilities().contains(ability)) { + choice.add(ability.getRule()); + } + + if (permanent.getAbilities().contains(ability2)) { + choice.add(ability2.getRule()); + } + + chooseAbility.setChoices(choice); + + Player player = game.getPlayer(source.getControllerId()); + + if (player.choose(outcome, chooseAbility, game)) { + + String chosenAbility = chooseAbility.getChoice(); + + if (chosenAbility.equals(ability.getRule())) { + while (permanent.getAbilities().contains(ability)) { + permanent.getAbilities().remove(ability); + } + } + else if (chosenAbility.equals(ability2.getRule())) { + while (permanent.getAbilities().contains(ability2)) { + permanent.getAbilities().remove(ability2); + } + } + } + } + return true; + } + + @Override + public String getText(Mode mode) { + if (staticText != null && !staticText.isEmpty()) { + return staticText; + } + StringBuilder sb = new StringBuilder(); + Target target = mode.getTargets().get(0); + if (target.getNumberOfTargets() > 1) { + if (target.getNumberOfTargets() < target.getMaxNumberOfTargets()) { + sb.append("Up to"); + } + sb.append(target.getMaxNumberOfTargets()).append(" target ").append(target.getTargetName()).append(" loses "); + } else { + sb.append("Target ").append(target.getTargetName()).append(" loses "); + } + sb.append(ability.getRule()); + sb.append(" or "); + sb.append(ability2.getRule()); + if (!duration.toString().isEmpty()) { + sb.append(" ").append(duration.toString()); + } + return sb.toString(); + } +} diff --git a/Mage/src/mage/abilities/effects/common/continuous/LoseAbilityTargetEffect.java b/Mage/src/mage/abilities/effects/common/continuous/LoseAbilityTargetEffect.java index e59f10afbd4..d706b7d6b84 100644 --- a/Mage/src/mage/abilities/effects/common/continuous/LoseAbilityTargetEffect.java +++ b/Mage/src/mage/abilities/effects/common/continuous/LoseAbilityTargetEffect.java @@ -1,78 +1,100 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ -package mage.abilities.effects.common.continuous; - -import mage.abilities.Ability; -import mage.abilities.Mode; -import mage.abilities.effects.ContinuousEffectImpl; -import mage.constants.Duration; -import mage.constants.Layer; -import mage.constants.Outcome; -import mage.constants.SubLayer; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.target.Target; - -/** - * - * @author jeffwadsworth - */ -public class LoseAbilityTargetEffect extends ContinuousEffectImpl{ - - protected Ability ability; - - public LoseAbilityTargetEffect(Ability ability){ - this(ability, Duration.WhileOnBattlefield); - } - - public LoseAbilityTargetEffect(Ability ability, Duration duration){ - super(duration, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.LoseAbility); - this.ability = ability; - } - - public LoseAbilityTargetEffect(final LoseAbilityTargetEffect effect){ - super(effect); - this.ability = effect.ability.copy(); - } - - @Override - public LoseAbilityTargetEffect copy(){ - return new LoseAbilityTargetEffect(this); - } - - @Override - public boolean apply(Game game, Ability source){ - Permanent permanent = game.getPermanent(source.getFirstTarget()); - if(permanent != null){ - while(permanent.getAbilities().contains(ability)){ - permanent.getAbilities().remove(ability); - } - } - return true; - } - - @Override - public String getText(Mode mode) { - if (staticText != null && !staticText.isEmpty()) { - return staticText; - } - StringBuilder sb = new StringBuilder(); - Target target = mode.getTargets().get(0); - if(target.getNumberOfTargets() > 1){ - if (target.getNumberOfTargets() < target.getMaxNumberOfTargets()) { - sb.append("Up to"); - } - sb.append(target.getMaxNumberOfTargets()).append(" target ").append(target.getTargetName()).append(" loses "); - } else { - sb.append("Target ").append(target.getTargetName()).append(" loses "); - } - sb.append(ability.getRule()); - if (!duration.toString().isEmpty()) { - sb.append(" ").append(duration.toString()); - } - return sb.toString(); - } -} - +/* + * 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.effects.common.continuous; + +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.constants.Duration; +import mage.constants.Layer; +import mage.constants.Outcome; +import mage.constants.SubLayer; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.Target; + +/** + * + * @author jeffwadsworth + */ +public class LoseAbilityTargetEffect extends ContinuousEffectImpl { + + protected Ability ability; + + public LoseAbilityTargetEffect(Ability ability) { + this(ability, Duration.WhileOnBattlefield); + } + + public LoseAbilityTargetEffect(Ability ability, Duration duration) { + super(duration, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.LoseAbility); + this.ability = ability; + } + + public LoseAbilityTargetEffect(final LoseAbilityTargetEffect effect) { + super(effect); + this.ability = effect.ability.copy(); + } + + @Override + public LoseAbilityTargetEffect copy() { + return new LoseAbilityTargetEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(source.getFirstTarget()); + if (permanent != null) { + while (permanent.getAbilities().contains(ability)) { + permanent.getAbilities().remove(ability); + } + } + return true; + } + + @Override + public String getText(Mode mode) { + if (staticText != null && !staticText.isEmpty()) { + return staticText; + } + StringBuilder sb = new StringBuilder(); + Target target = mode.getTargets().get(0); + if (target.getNumberOfTargets() > 1) { + if (target.getNumberOfTargets() < target.getMaxNumberOfTargets()) { + sb.append("Up to"); + } + sb.append(target.getMaxNumberOfTargets()).append(" target ").append(target.getTargetName()).append(" loses "); + } else { + sb.append("Target ").append(target.getTargetName()).append(" loses "); + } + sb.append(ability.getRule()); + if (!duration.toString().isEmpty()) { + sb.append(" ").append(duration.toString()); + } + return sb.toString(); + } +} diff --git a/Mage/src/mage/abilities/effects/common/counter/RemoveCounterSourceEffect.java b/Mage/src/mage/abilities/effects/common/counter/RemoveCounterSourceEffect.java index cd27ecfe521..6da3bf9cf00 100644 --- a/Mage/src/mage/abilities/effects/common/counter/RemoveCounterSourceEffect.java +++ b/Mage/src/mage/abilities/effects/common/counter/RemoveCounterSourceEffect.java @@ -60,18 +60,20 @@ public class RemoveCounterSourceEffect extends OneShotEffect { Permanent p = game.getPermanent(source.getSourceId()); if (p != null && p.getCounters().getCount(counter.getName()) >= counter.getCount()) { p.removeCounters(counter.getName(), counter.getCount(), game); - if (!game.isSimulation()) + if (!game.isSimulation()) { game.informPlayers(new StringBuilder("Removed ").append(counter.getCount()).append(" ").append(counter.getName()) - .append(" counter from ").append(p.getName()).toString()); + .append(" counter from ").append(p.getName()).toString()); + } return true; } Card c = game.getCard(source.getSourceId()); if (c != null && c.getCounters(game).getCount(counter.getName()) >= counter.getCount()) { c.removeCounters(counter.getName(), counter.getCount(), game); - if (!game.isSimulation()) + if (!game.isSimulation()) { game.informPlayers(new StringBuilder("Removed ").append(counter.getCount()).append(" ").append(counter.getName()) - .append(" counter from ").append(c.getName()) - .append(" (").append(c.getCounters(game).getCount(counter.getName())).append(" left)").toString()); + .append(" counter from ").append(c.getName()) + .append(" (").append(c.getCounters(game).getCount(counter.getName())).append(" left)").toString()); + } return true; } return false; diff --git a/Mage/src/mage/abilities/keyword/BloodthirstAbility.java b/Mage/src/mage/abilities/keyword/BloodthirstAbility.java index 2d768a1a903..f93ca9824d6 100644 --- a/Mage/src/mage/abilities/keyword/BloodthirstAbility.java +++ b/Mage/src/mage/abilities/keyword/BloodthirstAbility.java @@ -48,7 +48,7 @@ public class BloodthirstAbility extends EntersBattlefieldAbility { } class BloodthirstEffect extends OneShotEffect { - private int amount; + private final int amount; BloodthirstEffect(int amount) { super(Outcome.BoostCreature); diff --git a/Mage/src/mage/abilities/keyword/ChampionAbility.java b/Mage/src/mage/abilities/keyword/ChampionAbility.java index fa1bd2c87a5..b020ee46945 100644 --- a/Mage/src/mage/abilities/keyword/ChampionAbility.java +++ b/Mage/src/mage/abilities/keyword/ChampionAbility.java @@ -161,7 +161,7 @@ class ChampionExileCost extends CostImpl { if (permanent == null) { return false; } - paid |= controller.moveCardToExileWithInfo(permanent, exileId, sourceObject.getLogName() + " championed permanents", sourceId, game, Zone.BATTLEFIELD, true); + paid |= controller.moveCardToExileWithInfo(permanent, exileId, sourceObject.getIdName() + " championed permanents", sourceId, game, Zone.BATTLEFIELD, true); } } } diff --git a/Mage/src/mage/abilities/keyword/UnearthAbility.java b/Mage/src/mage/abilities/keyword/UnearthAbility.java index 19e9b4724b0..c8411cfb871 100644 --- a/Mage/src/mage/abilities/keyword/UnearthAbility.java +++ b/Mage/src/mage/abilities/keyword/UnearthAbility.java @@ -45,6 +45,8 @@ import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; import mage.game.events.ZoneChangeEvent; +import mage.game.permanent.Permanent; +import mage.players.Player; /** * @@ -144,10 +146,11 @@ class UnearthLeavesBattlefieldEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (source.getSourceObjectIfItStillExists(game) != null) { + if (event.getTargetId().equals(source.getSourceId())) { ZoneChangeEvent zEvent = (ZoneChangeEvent)event; if (zEvent.getFromZone() == Zone.BATTLEFIELD && zEvent.getToZone() != Zone.EXILED) { - return true; + // started in graveyard goint to battlefield so current zone change counter has to be +1 + return source.getSourceObjectZoneChangeCounter() + 1 == game.getState().getZoneChangeCounter(source.getSourceId()); } } return false; @@ -155,7 +158,11 @@ class UnearthLeavesBattlefieldEffect extends ReplacementEffectImpl { @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { - new ExileSourceEffect().apply(game, source); + Permanent permanent = game.getPermanent(source.getSourceId()); + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null && permanent != null) { + controller.moveCardToExileWithInfo(permanent, null, "", source.getSourceId(), game, Zone.BATTLEFIELD, true); + } return true; } } diff --git a/Mage/src/mage/abilities/mana/ConditionalAnyColorManaAbility.java b/Mage/src/mage/abilities/mana/ConditionalAnyColorManaAbility.java index 5aa3331e23f..70190ef50a0 100644 --- a/Mage/src/mage/abilities/mana/ConditionalAnyColorManaAbility.java +++ b/Mage/src/mage/abilities/mana/ConditionalAnyColorManaAbility.java @@ -77,6 +77,12 @@ public class ConditionalAnyColorManaAbility extends ManaAbility { return super.getNetMana(game); } + @Override + public boolean definesMana() { + return true; + } + + @Override public ConditionalAnyColorManaAbility copy() { return new ConditionalAnyColorManaAbility(this); diff --git a/Mage/src/mage/abilities/mana/ManaAbility.java b/Mage/src/mage/abilities/mana/ManaAbility.java index 7155dd8ea5d..afb90a01d29 100644 --- a/Mage/src/mage/abilities/mana/ManaAbility.java +++ b/Mage/src/mage/abilities/mana/ManaAbility.java @@ -63,6 +63,7 @@ public abstract class ManaAbility extends ActivatedAbilityImpl { public ManaAbility(final ManaAbility ability) { super(ability); this.netMana.addAll(ability.netMana); + this.undoPossible = ability.undoPossible; } @Override diff --git a/Mage/src/mage/cards/repository/CardRepository.java b/Mage/src/mage/cards/repository/CardRepository.java index 07cb0fc3e4b..c9ae81aa612 100644 --- a/Mage/src/mage/cards/repository/CardRepository.java +++ b/Mage/src/mage/cards/repository/CardRepository.java @@ -60,7 +60,7 @@ public enum CardRepository { // raise this if db structure was changed private static final long CARD_DB_VERSION = 38; // raise this if new cards were added to the server - private static final long CARD_CONTENT_VERSION = 15; + private static final long CARD_CONTENT_VERSION = 17; private final Random random = new Random(); private Dao cardDao; diff --git a/Mage/src/mage/cards/repository/ExpansionRepository.java b/Mage/src/mage/cards/repository/ExpansionRepository.java index 134aca215f7..5fb202231b4 100644 --- a/Mage/src/mage/cards/repository/ExpansionRepository.java +++ b/Mage/src/mage/cards/repository/ExpansionRepository.java @@ -27,7 +27,7 @@ public enum ExpansionRepository { private static final String JDBC_URL = "jdbc:h2:file:./db/cards.h2;AUTO_SERVER=TRUE"; private static final String VERSION_ENTITY_NAME = "expansion"; private static final long EXPANSION_DB_VERSION = 4; - private static final long EXPANSION_CONTENT_VERSION = 6; + private static final long EXPANSION_CONTENT_VERSION = 7; private Dao expansionDao; diff --git a/Mage/src/mage/counters/CounterType.java b/Mage/src/mage/counters/CounterType.java index 2dca09468bf..00e2fe3b4bf 100644 --- a/Mage/src/mage/counters/CounterType.java +++ b/Mage/src/mage/counters/CounterType.java @@ -63,6 +63,7 @@ public enum CounterType { LORE("lore"), LUCK("luck"), LOYALTY("loyalty"), + MANNEQUIN("mannequin"), M1M1(new BoostCounter(-1, -1).name), MINING("mining"), P1P1(new BoostCounter(1, 1).name), diff --git a/Mage/src/mage/counters/Counters.java b/Mage/src/mage/counters/Counters.java index d842c335417..6b1aca15edf 100644 --- a/Mage/src/mage/counters/Counters.java +++ b/Mage/src/mage/counters/Counters.java @@ -57,7 +57,7 @@ public class Counters extends HashMap implements Serializable { this.put(name, new Counter(name)); } this.get(name).add(); - } + } public void addCounter(String name, int amount) { if (!this.containsKey(name)) { @@ -75,14 +75,15 @@ public class Counters extends HashMap implements Serializable { } public void removeCounter(String name) { - if (this.containsKey(name)) { - this.get(name).remove(); - } + removeCounter(name, 1); } public void removeCounter(CounterType counterType, int amount) { if (this.containsKey(counterType.getName())) { get(counterType.getName()).remove(amount); + if (get(counterType.getName()).count == 0) { + this.remove(counterType.getName()); + } } } diff --git a/Mage/src/mage/game/GameImpl.java b/Mage/src/mage/game/GameImpl.java index 28c823f6446..8251d6e7adc 100644 --- a/Mage/src/mage/game/GameImpl.java +++ b/Mage/src/mage/game/GameImpl.java @@ -117,7 +117,9 @@ import mage.target.Target; import mage.target.TargetPermanent; import mage.target.TargetPlayer; import mage.util.functions.ApplyToPermanent; +import mage.watchers.Watchers; import mage.watchers.common.BlockedAttackerWatcher; +import mage.watchers.common.BloodthirstWatcher; import mage.watchers.common.CastSpellLastTurnWatcher; import mage.watchers.common.MorbidWatcher; import mage.watchers.common.PlayerDamagedBySourceWatcher; @@ -883,15 +885,17 @@ public abstract class GameImpl implements Game, Serializable { saveState(false); } while (!mulliganPlayers.isEmpty()); getState().setChoosingPlayerId(null); - // add watchers + Watchers watchers = state.getWatchers(); + // add default watchers for (UUID playerId : state.getPlayerList(startingPlayerId)) { - state.getWatchers().add(new PlayerDamagedBySourceWatcher(playerId)); + watchers.add(new PlayerDamagedBySourceWatcher(playerId)); + watchers.add(new BloodthirstWatcher(playerId)); } - state.getWatchers().add(new MorbidWatcher()); - state.getWatchers().add(new CastSpellLastTurnWatcher()); - state.getWatchers().add(new SoulbondWatcher()); - state.getWatchers().add(new PlayerLostLifeWatcher()); - state.getWatchers().add(new BlockedAttackerWatcher()); + watchers.add(new MorbidWatcher()); + watchers.add(new CastSpellLastTurnWatcher()); + watchers.add(new SoulbondWatcher()); + watchers.add(new PlayerLostLifeWatcher()); + watchers.add(new BlockedAttackerWatcher()); //20100716 - 103.5 for (UUID playerId: state.getPlayerList(startingPlayerId)) { @@ -1278,6 +1282,7 @@ public abstract class GameImpl implements Game, Serializable { @Override public void addPermanent(Permanent permanent) { getBattlefield().addPermanent(permanent); + permanent.setCreateOrder(getState().getNextPermanentOrderNumber()); } @Override @@ -1492,6 +1497,7 @@ public abstract class GameImpl implements Game, Serializable { List planeswalkers = new ArrayList<>(); List legendary = new ArrayList<>(); + List worldEnchantment = new ArrayList<>(); for (Permanent perm: getBattlefield().getAllActivePermanents()) { if (perm.getCardType().contains(CardType.CREATURE)) { //20091005 - 704.5f @@ -1539,6 +1545,9 @@ public abstract class GameImpl implements Game, Serializable { } planeswalkers.add(perm); } + if (perm.getSupertype().contains("World")) { + worldEnchantment.add(perm); + } if (filterAura.match(perm, this)) { //20091005 - 704.5n, 702.14c if (perm.getAttachedTo() == null) { @@ -1729,7 +1738,28 @@ public abstract class GameImpl implements Game, Serializable { } } } - + //704.5m - World Enchantments + if (worldEnchantment.size() > 1) { + int newestCard = -1; + Permanent newestPermanent = null; + for (Permanent permanent :worldEnchantment) { + if (newestCard == -1) { + newestCard = permanent.getCreateOrder(); + newestPermanent = permanent; + } else if (newestCard < permanent.getCreateOrder()) { + newestCard = permanent.getCreateOrder(); + newestPermanent = permanent; + } else if(newestCard == permanent.getCreateOrder()) { + newestPermanent = null; + } + } + for (Permanent permanent :worldEnchantment) { + if (newestPermanent != permanent) { + movePermanentToGraveyardWithInfo(permanent); + somethingHappened = true; + } + } + } //TODO: implement the rest return somethingHappened; diff --git a/Mage/src/mage/game/GameState.java b/Mage/src/mage/game/GameState.java index 6f4c02c23cd..332ead3e168 100644 --- a/Mage/src/mage/game/GameState.java +++ b/Mage/src/mage/game/GameState.java @@ -111,6 +111,7 @@ public class GameState implements Serializable, Copyable { private Map cardState = new HashMap<>(); private Map zoneChangeCounter = new HashMap<>(); private Map copiedCards = new HashMap<>(); + private int permanentOrderNumber; public GameState() { players = new Players(); @@ -169,6 +170,7 @@ public class GameState implements Serializable, Copyable { } this.zoneChangeCounter.putAll(state.zoneChangeCounter); this.copiedCards.putAll(state.copiedCards); + this.permanentOrderNumber = state.permanentOrderNumber; } @Override @@ -575,6 +577,7 @@ public class GameState implements Serializable, Copyable { this.cardState = state.cardState; this.zoneChangeCounter = state.zoneChangeCounter; this.copiedCards = state.copiedCards; + this.permanentOrderNumber = state.permanentOrderNumber; } public void addSimultaneousEvent(GameEvent event, Game game) { @@ -837,6 +840,7 @@ public class GameState implements Serializable, Copyable { values.clear(); zones.clear(); simultaneousEvents.clear(); + permanentOrderNumber = 0; } public void pause() { @@ -925,4 +929,8 @@ public class GameState implements Serializable, Copyable { } return copiedCard; } + + public int getNextPermanentOrderNumber() { + return permanentOrderNumber++; } +} diff --git a/Mage/src/mage/game/combat/CombatGroup.java b/Mage/src/mage/game/combat/CombatGroup.java index e5426bb6e2c..3a07906c561 100644 --- a/Mage/src/mage/game/combat/CombatGroup.java +++ b/Mage/src/mage/game/combat/CombatGroup.java @@ -244,7 +244,7 @@ public class CombatGroup implements Serializable, Copyable { } else { Player player = game.getPlayer(attacker.getControllerId()); - int damageAssigned = player.getAmount(lethalDamage, damage, "Assign damage to " + blocker.getLogName(), game); + int damageAssigned = player.getAmount(lethalDamage, damage, "Assign damage to " + blocker.getName(), game); blocker.markDamage(damageAssigned, attacker.getId(), game, true, true); damage -= damageAssigned; if (damage > 0) { @@ -298,7 +298,7 @@ public class CombatGroup implements Serializable, Copyable { damage = 0; break; } - int damageAssigned = player.getAmount(lethalDamage, damage, "Assign damage to " + blocker.getLogName(), game); + int damageAssigned = player.getAmount(lethalDamage, damage, "Assign damage to " + blocker.getName(), game); assigned.put(blockerId, damageAssigned); damage -= damageAssigned; } @@ -380,7 +380,7 @@ public class CombatGroup implements Serializable, Copyable { assigned.put(attackerId, damage); break; } - int damageAssigned = player.getAmount(lethalDamage, damage, "Assign damage to " + attacker.getLogName(), game); + int damageAssigned = player.getAmount(lethalDamage, damage, "Assign damage to " + attacker.getName(), game); assigned.put(attackerId, damageAssigned); damage -= damageAssigned; } diff --git a/Mage/src/mage/game/command/Commander.java b/Mage/src/mage/game/command/Commander.java index f3d7d0859c5..0602bafbec1 100644 --- a/Mage/src/mage/game/command/Commander.java +++ b/Mage/src/mage/game/command/Commander.java @@ -99,6 +99,11 @@ public class Commander implements CommandObject{ return card.getName(); } + @Override + public String getIdName() { + return card.getName() + " ["+card.getId().toString().substring(0,3) +"]"; + } + @Override public String getLogName() { return GameLog.getColoredObjectName(this); diff --git a/Mage/src/mage/game/command/Emblem.java b/Mage/src/mage/game/command/Emblem.java index 7fb4552aa3d..468aa9cc730 100644 --- a/Mage/src/mage/game/command/Emblem.java +++ b/Mage/src/mage/game/command/Emblem.java @@ -99,6 +99,11 @@ public class Emblem implements CommandObject { return name; } + @Override + public String getIdName() { + return getName() + " ["+getId().toString().substring(0,3) +"]"; + } + @Override public String getLogName() { return GameLog.getColoredObjectName(this); diff --git a/Mage/src/mage/game/events/GameEvent.java b/Mage/src/mage/game/events/GameEvent.java index 50e4ab491fd..aae2b81a16b 100644 --- a/Mage/src/mage/game/events/GameEvent.java +++ b/Mage/src/mage/game/events/GameEvent.java @@ -175,7 +175,7 @@ public class GameEvent implements Serializable { SHUFFLE_LIBRARY, LIBRARY_SHUFFLED, ENCHANT_PLAYER, ENCHANTED_PLAYER, CAN_TAKE_MULLIGAN, - FLIP_COIN, SCRY, FATESEAL, + FLIP_COIN, COIN_FLIPPED, SCRY, FATESEAL, //permanent events ENTERS_THE_BATTLEFIELD, diff --git a/Mage/src/mage/game/permanent/Permanent.java b/Mage/src/mage/game/permanent/Permanent.java index 49210d311f0..8e7258301ac 100644 --- a/Mage/src/mage/game/permanent/Permanent.java +++ b/Mage/src/mage/game/permanent/Permanent.java @@ -274,4 +274,8 @@ public interface Permanent extends Card, Controllable { @Override Permanent copy(); + // Simple int counter to set a timewise create order , the lower the number the earlier the object was created + // if objects enter the battlefield at the same time they can get (and should) get the same number. + int getCreateOrder(); + void setCreateOrder(int createOrder); } diff --git a/Mage/src/mage/game/permanent/PermanentImpl.java b/Mage/src/mage/game/permanent/PermanentImpl.java index c443897bc24..098313d6337 100644 --- a/Mage/src/mage/game/permanent/PermanentImpl.java +++ b/Mage/src/mage/game/permanent/PermanentImpl.java @@ -30,6 +30,7 @@ package mage.game.permanent; import java.util.ArrayList; import java.util.Collections; +import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -119,6 +120,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent { protected List markedDamage; protected int timesLoyaltyUsed = 0; protected Map info; + protected int createOrder; private static final List emptyList = Collections.unmodifiableList(new ArrayList()); @@ -126,7 +128,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent { super(ownerId, name); this.originalControllerId = controllerId; this.controllerId = controllerId; - this.counters = new Counters(); + this.counters = new Counters(); } public PermanentImpl(UUID id, UUID ownerId, UUID controllerId, String name) { @@ -179,6 +181,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent { this.morphed = permanent.morphed; this.manifested = permanent.manifested; + this.createOrder = permanent.createOrder; } @Override @@ -1347,4 +1350,15 @@ public abstract class PermanentImpl extends CardImpl implements Permanent { fightTarget.damage(getPower().getValue(), getId(), game, false, true); return true; } + + @Override + public int getCreateOrder() { + return createOrder; } + + @Override + public void setCreateOrder(int createOrder) { + this.createOrder = createOrder; + } + +} diff --git a/Mage/src/mage/game/stack/Spell.java b/Mage/src/mage/game/stack/Spell.java index 5065b9296b5..4676f22cf88 100644 --- a/Mage/src/mage/game/stack/Spell.java +++ b/Mage/src/mage/game/stack/Spell.java @@ -552,6 +552,11 @@ public class Spell implements StackObject, Card { return card.getName(); } + @Override + public String getIdName() { + return getName() + " ["+getId().toString().substring(0,3) +"]"; + } + @Override public String getLogName() { return GameLog.getColoredObjectName(card); diff --git a/Mage/src/mage/game/stack/StackAbility.java b/Mage/src/mage/game/stack/StackAbility.java index f2cc75b1fbe..29804bbf9bc 100644 --- a/Mage/src/mage/game/stack/StackAbility.java +++ b/Mage/src/mage/game/stack/StackAbility.java @@ -130,6 +130,11 @@ public class StackAbility implements StackObject, Ability { return name; } + @Override + public String getIdName() { + return getName() + " ["+getId().toString().substring(0,3) +"]"; + } + @Override public String getLogName() { return GameLog.getColoredObjectName(this); diff --git a/Mage/src/mage/players/PlayerImpl.java b/Mage/src/mage/players/PlayerImpl.java index 20a8e6cd8aa..f5cc42cb979 100644 --- a/Mage/src/mage/players/PlayerImpl.java +++ b/Mage/src/mage/players/PlayerImpl.java @@ -444,7 +444,7 @@ public abstract class PlayerImpl implements Player, Serializable { this.payManaMode = false; this.setLife(game.getLife(), game); this.setReachedNextTurnAfterLeaving(false); - game.getState().getWatchers().add(new BloodthirstWatcher(playerId)); + this.castSourceIdWithAlternateMana = null; this.castSourceIdManaCosts = null; } @@ -932,13 +932,14 @@ public abstract class PlayerImpl implements Player, Serializable { // some effects set sourceId to cast without paying mana costs if (ability.getSourceId().equals(getCastSourceIdWithAlternateMana())) { ManaCosts alternateCosts = getCastSourceIdManaCosts(); + Ability spellAbility = spell.getSpellAbility(); if (alternateCosts == null) { noMana = true; } else { - ability.getManaCosts().clear(); - ability.getManaCosts().add(alternateCosts.copy()); - ability.getManaCostsToPay().clear(); - ability.getManaCostsToPay().add(alternateCosts.copy()); + spellAbility.getManaCosts().clear(); + spellAbility.getManaCosts().add(alternateCosts.copy()); + spellAbility.getManaCostsToPay().clear(); + spellAbility.getManaCostsToPay().add(alternateCosts.copy()); } } setCastSourceIdWithAlternateMana(null, null); @@ -1665,9 +1666,7 @@ public abstract class PlayerImpl implements Player, Serializable { } else if (source instanceof CommandObject){ sourceControllerId = ((CommandObject) source).getControllerId(); sourceAbilities = ((CommandObject) source).getAbilities(); - } else { - source = null; - } + } } else { sourceAbilities = ((Permanent) source).getAbilities(game); sourceControllerId = ((Permanent) source).getControllerId(); @@ -1819,7 +1818,7 @@ public abstract class PlayerImpl implements Player, Serializable { quit = true; timerTimeout = true; this.concede(game); - game.informPlayers(getLogName() + " has run out of time. Loosing the Match."); + game.informPlayers(getLogName() + " has run out of time, losing the match."); } @Override @@ -1827,7 +1826,7 @@ public abstract class PlayerImpl implements Player, Serializable { quit = true; idleTimeout = true; this.concede(game); - game.informPlayers(new StringBuilder(getLogName()).append(" was idle for too long. Loosing the Match.").toString()); + game.informPlayers(new StringBuilder(getLogName()).append(" was idle for too long, losing the Match.").toString()); } @Override @@ -2110,7 +2109,9 @@ public abstract class PlayerImpl implements Player, Serializable { } GameEvent event = new GameEvent(GameEvent.EventType.FLIP_COIN, playerId, null, playerId, 0, result); event.setAppliedEffects(appliedEffects); - game.replaceEvent(event); + if (!game.replaceEvent(event)) { + game.fireEvent(new GameEvent(GameEvent.EventType.COIN_FLIPPED, playerId, null, playerId, 0, event.getFlag())); + } return event.getFlag(); } diff --git a/Mage/src/mage/target/common/TargetControlledPermanent.java b/Mage/src/mage/target/common/TargetControlledPermanent.java index 24f0ddd7253..a7973379eb5 100644 --- a/Mage/src/mage/target/common/TargetControlledPermanent.java +++ b/Mage/src/mage/target/common/TargetControlledPermanent.java @@ -28,7 +28,6 @@ package mage.target.common; -import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledPermanent; import mage.target.TargetPermanent; diff --git a/Mage/src/mage/util/CardUtil.java b/Mage/src/mage/util/CardUtil.java index 32705d881b6..475c3a2c107 100644 --- a/Mage/src/mage/util/CardUtil.java +++ b/Mage/src/mage/util/CardUtil.java @@ -28,6 +28,7 @@ package mage.util; +import java.util.Arrays; import java.util.HashSet; import java.util.Iterator; import java.util.Set; @@ -74,6 +75,12 @@ public class CardUtil { static String numberStrings[] = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "ninteen", "twenty"}; + public static final String[] NON_CHANGELING_SUBTYPES_VALUES = new String[] { "Mountain", "Forest", "Plains", "Swamp", "Island", + "Aura", "Curse", "Shrine", + "Equipment", "Fortification", "Contraption", + "Trap", "Arcane"}; + public static final Set NON_CREATURE_SUBTYPES = new HashSet<>(Arrays.asList(NON_CHANGELING_SUBTYPES_VALUES)); + /** * Checks whether two cards share card types. * @@ -637,5 +644,8 @@ public class CardUtil { } return mana; } - + + public static boolean isNonCreatureSubtype(String subtype) { + return NON_CREATURE_SUBTYPES.contains(subtype); + } } diff --git a/Mage/src/mage/watchers/common/AmountOfDamageAPlayerReceivedThisTurnWatcher.java b/Mage/src/mage/watchers/common/AmountOfDamageAPlayerReceivedThisTurnWatcher.java index 027063ccfaa..803239868ea 100644 --- a/Mage/src/mage/watchers/common/AmountOfDamageAPlayerReceivedThisTurnWatcher.java +++ b/Mage/src/mage/watchers/common/AmountOfDamageAPlayerReceivedThisTurnWatcher.java @@ -65,9 +65,9 @@ public class AmountOfDamageAPlayerReceivedThisTurnWatcher extends Watcher { if (playerId != null) { Integer amount = amountOfDamageReceivedThisTurn.get(playerId); if (amount == null) { - amount = Integer.valueOf(event.getAmount()); + amount = event.getAmount(); } else { - amount = Integer.valueOf(amount + event.getAmount()); + amount = amount + event.getAmount(); } amountOfDamageReceivedThisTurn.put(playerId, amount); } diff --git a/Mage/src/mage/watchers/common/SourceDidDamageWatcher.java b/Mage/src/mage/watchers/common/SourceDidDamageWatcher.java index 94072d1ddb4..cb873e23c8f 100644 --- a/Mage/src/mage/watchers/common/SourceDidDamageWatcher.java +++ b/Mage/src/mage/watchers/common/SourceDidDamageWatcher.java @@ -44,7 +44,7 @@ import java.util.UUID; */ public class SourceDidDamageWatcher extends Watcher { - public List damageSources = new ArrayList(); + public List damageSources = new ArrayList<>(); public SourceDidDamageWatcher() { super("SourceDidDamageWatcher", WatcherScope.GAME); diff --git a/Utils/release/getting_implemented_cards.txt b/Utils/release/getting_implemented_cards.txt index 60d8b392fec..6ef99fa38e8 100644 --- a/Utils/release/getting_implemented_cards.txt +++ b/Utils/release/getting_implemented_cards.txt @@ -126,6 +126,11 @@ git log 00692410273d4c2ff70eec7bfcf6a601fb404bf9..HEAD --diff-filter=A --name-st since 1.4.0.v0 git log fa847e8feb646e94d77fc8abc35e1d9817622f8a..HEAD --diff-filter=A --name-status | sed -ne "s/^A[^u]Mage.Sets\/src\/mage\/sets\///p" | sort > added_cards.txt +since 1.4.0.v1 +git log e8b2e01cd465f6a8ced2c83ec52a698ee093baa4..HEAD --diff-filter=A --name-status | sed -ne "s/^A[^u]Mage.Sets\/src\/mage\/sets\///p" | sort > added_cards.txt +since 1.4.0.v2 +git log eb96b08dfac3de4f78403d6f23e41ce8d41ece6f..HEAD --diff-filter=A --name-status | sed -ne "s/^A[^u]Mage.Sets\/src\/mage\/sets\///p" | sort > added_cards.txt + 3. Copy added_cards.txt to trunk\Utils folder 4. Run script: > perl extract_in_wiki_format.perl diff --git a/readme.md b/readme.md index fd5ae60f810..902013827b2 100644 --- a/readme.md +++ b/readme.md @@ -1,6 +1,6 @@ # XMage - Magic, Another Game Engine -XMage allows you to play magic against one or more online players or computer opponents. It includes full rules enforcement for over **9,500** unique cards (over 17.800 counting all cards from different editions). Starting with Eventide, all regular sets have nearly all the cards implemented ([see here in detail which cards are implemented](http://ct-magefree.rhcloud.com/stats)). +XMage allows you to play magic against one or more online players or computer opponents. It includes full rules enforcement for over **10,000** unique cards (nearly 20.000 counting all cards from different editions). Starting with Eventide, all regular sets have nearly all the cards implemented ([see here in detail which cards are implemented](http://ct-magefree.rhcloud.com/stats)). There are public servers where you can play XMage against other players. Apart from this, you can also host your own server to play against the AI and/or your friends. @@ -11,13 +11,14 @@ You can visit the XMage forum [here](http://www.slightlymagic.net/forum/viewforu * There is a simple computer AI opponent available. * You can play either a two player duel or a multiplayer free-for-all game with up to 10 players. * Commander format(also up to 10 players). +* Tiny Leaders duels. * There are two tournament types supported witch can be played with up to 16 players: - * Elimination or swiss type handling - * Booster (also Cube) draft tournaments (4-16) - * Sealed (also from Cube) tournaments (2-16) +* Elimination or swiss type handling +* Booster (also Cube) draft tournaments (4-16) +* Sealed (also from Cube) tournaments (2-16) ## Installation -Install the XMage Launcher to download and install always the latest XMage release from [here](http://XMage.info). +Install the XMage Launcher to download and install always the latest XMage release from [here](http://XMage.de). You will need to have the [Java Runtime Environment](http://java.com/en/) Version 7 or later. Here you can find a log of the latest changes: [Release changes] (http://github.com/magefree/mage/wiki/Release-changes)