diff --git a/Mage.Server.Plugins/Mage.Game.MomirGame/pom.xml b/Mage.Server.Plugins/Mage.Game.MomirGame/pom.xml new file mode 100644 index 0000000000..209ffd70c3 --- /dev/null +++ b/Mage.Server.Plugins/Mage.Game.MomirGame/pom.xml @@ -0,0 +1,55 @@ + + + + 4.0.0 + + + org.mage + mage-server-plugins + 1.4.26 + + + mage-game-momirfreeforall + jar + Mage Game Momir Basic Free for All + + + + ${project.groupId} + mage + ${project.version} + + + ${project.groupId} + mage-game-freeforall + ${project.version} + + + + + src + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.7 + 1.7 + + + + maven-resources-plugin + + UTF-8 + + + + + + mage-game-momir + + + + + diff --git a/Mage.Server.Plugins/Mage.Game.MomirGame/src/mage/game/MomirFreeForAllMatch.java b/Mage.Server.Plugins/Mage.Game.MomirGame/src/mage/game/MomirFreeForAllMatch.java new file mode 100644 index 0000000000..a46aa486ca --- /dev/null +++ b/Mage.Server.Plugins/Mage.Game.MomirGame/src/mage/game/MomirFreeForAllMatch.java @@ -0,0 +1,55 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.game; + +import mage.game.match.MatchImpl; +import mage.game.match.MatchOptions; + +/** + * + * @author nigelzor + */ +public class MomirFreeForAllMatch extends MatchImpl { + + public MomirFreeForAllMatch(MatchOptions options) { + super(options); + } + + @Override + public void startGame() throws GameException { + // Momir Vig, Simic Visionary gives +4 starting life + int startLife = 24; + + MomirGame game = new MomirGame(options.getAttackOption(), options.getRange(), options.getFreeMulligans(), startLife); + game.setStartMessage(this.createGameStartMessage()); + + this.initGame(game); + games.add(game); + } + +} diff --git a/Mage.Server.Plugins/Mage.Game.MomirGame/src/mage/game/MomirFreeForAllType.java b/Mage.Server.Plugins/Mage.Game.MomirGame/src/mage/game/MomirFreeForAllType.java new file mode 100644 index 0000000000..5eb6c30170 --- /dev/null +++ b/Mage.Server.Plugins/Mage.Game.MomirGame/src/mage/game/MomirFreeForAllType.java @@ -0,0 +1,57 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.game; + +import mage.game.match.MatchType; + +/** + * + * @author nigelzor + */ +public class MomirFreeForAllType extends MatchType { + + public MomirFreeForAllType() { + this.name = "Momir Basic Free For All"; + this.maxPlayers = 10; + this.minPlayers = 2; + this.numTeams = 0; + this.useAttackOption = true; + this.useRange = true; + this.sideboardingAllowed = false; + } + + protected MomirFreeForAllType(final MomirFreeForAllType matchType){ + super(matchType); + } + + @Override + public MomirFreeForAllType copy() { + return new MomirFreeForAllType(this); + } + +} diff --git a/Mage.Server.Plugins/Mage.Game.MomirGame/src/mage/game/MomirGame.java b/Mage.Server.Plugins/Mage.Game.MomirGame/src/mage/game/MomirGame.java new file mode 100644 index 0000000000..5627da1695 --- /dev/null +++ b/Mage.Server.Plugins/Mage.Game.MomirGame/src/mage/game/MomirGame.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.game; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.InfoEffect; +import mage.cards.repository.CardInfo; +import mage.cards.repository.CardRepository; +import mage.constants.MultiplayerAttackOption; +import mage.constants.PhaseStep; +import mage.constants.RangeOfInfluence; +import mage.constants.Zone; +import mage.game.command.emblems.MomirEmblem; +import mage.game.match.MatchType; +import mage.game.turn.TurnMod; +import mage.players.Player; + + +/** + * + * @author nigelzor + */ +public class MomirGame extends FreeForAll { + + private int numPlayers; + + public MomirGame(MultiplayerAttackOption attackOption, RangeOfInfluence range, int freeMulligans, int startLife) { + super(attackOption, range, freeMulligans, startLife); + } + + public MomirGame(final MomirGame game) { + super(game); + } + + @Override + public MatchType getGameType() { + return new MomirFreeForAllType(); + } + + @Override + public int getNumPlayers() { + return numPlayers; + } + + @Override + protected void init(UUID choosingPlayerId) { + Ability ability = new SimpleStaticAbility(Zone.COMMAND, new InfoEffect("Vanguard effects")); + for (UUID playerId : state.getPlayerList(startingPlayerId)) { + Player player = getPlayer(playerId); + if (player != null) { + CardInfo cardInfo = CardRepository.instance.findCard("Momir Vig, Simic Visionary"); + addEmblem(new MomirEmblem(), cardInfo.getCard(), playerId); + } + } + getState().addAbility(ability, null); + super.init(choosingPlayerId); + state.getTurnMods().add(new TurnMod(startingPlayerId, PhaseStep.DRAW)); + } + + @Override + public Set getOpponents(UUID playerId) { + Set opponents = new HashSet<>(); + for (UUID opponentId : this.getPlayer(playerId).getInRange()) { + if (!opponentId.equals(playerId)) { + opponents.add(opponentId); + } + } + return opponents; + } + + @Override + public MomirGame copy() { + return new MomirGame(this); + } + +} diff --git a/Mage.Server.Plugins/pom.xml b/Mage.Server.Plugins/pom.xml index 4f23171181..6088bbe80d 100644 --- a/Mage.Server.Plugins/pom.xml +++ b/Mage.Server.Plugins/pom.xml @@ -21,6 +21,7 @@ Mage.Game.CommanderFreeForAll Mage.Game.FreeForAll Mage.Game.MomirDuel + Mage.Game.MomirGame Mage.Game.TinyLeadersDuel Mage.Game.CanadianHighlanderDuel Mage.Game.PennyDreadfulCommanderFreeForAll diff --git a/Mage.Server/config/config.xml b/Mage.Server/config/config.xml index 877f1756e3..ba16d20cc3 100644 --- a/Mage.Server/config/config.xml +++ b/Mage.Server/config/config.xml @@ -77,6 +77,7 @@ + diff --git a/Mage.Server/pom.xml b/Mage.Server/pom.xml index eb547da404..364875c081 100644 --- a/Mage.Server/pom.xml +++ b/Mage.Server/pom.xml @@ -160,6 +160,12 @@ ${project.version} runtime + + ${project.groupId} + mage-game-momirfreeforall + ${project.version} + runtime + org.apache.shiro shiro-core diff --git a/Mage.Sets/src/mage/cards/b/BrutalHordechief.java b/Mage.Sets/src/mage/cards/b/BrutalHordechief.java index 108280010f..e9068ea94b 100644 --- a/Mage.Sets/src/mage/cards/b/BrutalHordechief.java +++ b/Mage.Sets/src/mage/cards/b/BrutalHordechief.java @@ -34,6 +34,7 @@ import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; +import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.LoseLifeTargetEffect; import mage.abilities.effects.common.combat.BlocksIfAbleAllEffect; @@ -47,6 +48,7 @@ import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.targetpointer.FixedTarget; +import mage.watchers.common.ChooseBlockersRedundancyWatcher; /** * @@ -72,6 +74,8 @@ public class BrutalHordechief extends CardImpl { // {3}{R/W}{R/W}: Creatures your opponents control block this turn if able, and you choose how those creatures block. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BlocksIfAbleAllEffect(filter, Duration.EndOfTurn), new ManaCostsImpl("{3}{R/W}{R/W}")); ability.addEffect(new BrutalHordechiefChooseBlockersEffect()); + ability.addWatcher(new ChooseBlockersRedundancyWatcher()); + ability.addEffect(new ChooseBlockersRedundancyWatcherIncrementEffect()); this.addAbility(ability); } @@ -83,6 +87,32 @@ public class BrutalHordechief extends CardImpl { public BrutalHordechief copy() { return new BrutalHordechief(this); } + + private class ChooseBlockersRedundancyWatcherIncrementEffect extends OneShotEffect { + + ChooseBlockersRedundancyWatcherIncrementEffect() { + super(Outcome.Neutral); + } + + ChooseBlockersRedundancyWatcherIncrementEffect(final ChooseBlockersRedundancyWatcherIncrementEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + ChooseBlockersRedundancyWatcher watcher = (ChooseBlockersRedundancyWatcher) game.getState().getWatchers().get(ChooseBlockersRedundancyWatcher.class.getSimpleName()); + if (watcher != null) { + watcher.increment(); + return true; + } + return false; + } + + @Override + public ChooseBlockersRedundancyWatcherIncrementEffect copy() { + return new ChooseBlockersRedundancyWatcherIncrementEffect(this); + } + } } class BrutalHordechiefTriggeredAbility extends TriggeredAbilityImpl { @@ -123,11 +153,11 @@ class BrutalHordechiefTriggeredAbility extends TriggeredAbilityImpl { } } -class BrutalHordechiefChooseBlockersEffect extends ContinuousRuleModifyingEffectImpl { // TODO: reverse the resolution order in case of effect multiples +class BrutalHordechiefChooseBlockersEffect extends ContinuousRuleModifyingEffectImpl { public BrutalHordechiefChooseBlockersEffect() { super(Duration.EndOfTurn, Outcome.Benefit, false, false); - staticText = ", and you choose how those creatures block"; + staticText = "You choose which creatures block this turn and how those creatures block"; } public BrutalHordechiefChooseBlockersEffect(final BrutalHordechiefChooseBlockersEffect effect) { @@ -151,6 +181,13 @@ class BrutalHordechiefChooseBlockersEffect extends ContinuousRuleModifyingEffect @Override public boolean applies(GameEvent event, Ability source, Game game) { + ChooseBlockersRedundancyWatcher watcher = (ChooseBlockersRedundancyWatcher) game.getState().getWatchers().get(ChooseBlockersRedundancyWatcher.class.getSimpleName()); + watcher.decrement(); + if (watcher.copyCountApply > 0) { + game.informPlayers(source.getSourceObject(game).getIdName() + " didn't apply"); + return false; + } + watcher.copyCountApply = watcher.copyCount; Player blockController = game.getPlayer(source.getControllerId()); if (blockController != null) { game.getCombat().selectBlockers(blockController, game); diff --git a/Mage.Sets/src/mage/cards/c/ChaliceOfTheVoid.java b/Mage.Sets/src/mage/cards/c/ChaliceOfTheVoid.java index d6b829d2be..cc53c2feb4 100644 --- a/Mage.Sets/src/mage/cards/c/ChaliceOfTheVoid.java +++ b/Mage.Sets/src/mage/cards/c/ChaliceOfTheVoid.java @@ -28,16 +28,14 @@ package mage.cards.c; import java.util.UUID; -import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.effects.Effect; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CounterTargetEffect; import mage.abilities.effects.common.EntersBattlefieldWithXCountersEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.Zone; import mage.counters.CounterType; import mage.game.Game; @@ -53,7 +51,7 @@ import mage.target.targetpointer.FixedTarget; public class ChaliceOfTheVoid extends CardImpl { public ChaliceOfTheVoid(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{X}{X}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{X}{X}"); // Chalice of the Void enters the battlefield with X charge counters on it. this.addAbility(new EntersBattlefieldAbility(new EntersBattlefieldWithXCountersEffect(CounterType.CHARGE.createInstance()))); @@ -75,7 +73,7 @@ public class ChaliceOfTheVoid extends CardImpl { class ChaliceOfTheVoidTriggeredAbility extends TriggeredAbilityImpl { public ChaliceOfTheVoidTriggeredAbility() { - super(Zone.BATTLEFIELD, new CounterEffect()); + super(Zone.BATTLEFIELD, new CounterTargetEffect()); } public ChaliceOfTheVoidTriggeredAbility(final ChaliceOfTheVoidTriggeredAbility abiltity) { @@ -110,25 +108,3 @@ class ChaliceOfTheVoidTriggeredAbility extends TriggeredAbilityImpl { return "Whenever a player casts a spell with converted mana cost equal to the number of charge counters on {this}, counter that spell."; } } - -class CounterEffect extends OneShotEffect { - - public CounterEffect() { - super(Outcome.Detriment); - } - - public CounterEffect(final CounterEffect effect) { - super(effect); - } - - @Override - public CounterEffect copy() { - return new CounterEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - return game.getStack().counter(this.getTargetPointer().getFirst(game, source), source.getSourceId(), game); - } - -} diff --git a/Mage.Sets/src/mage/cards/c/ConsumeStrength.java b/Mage.Sets/src/mage/cards/c/ConsumeStrength.java index 1bf9ca987f..15654f0fce 100644 --- a/Mage.Sets/src/mage/cards/c/ConsumeStrength.java +++ b/Mage.Sets/src/mage/cards/c/ConsumeStrength.java @@ -29,7 +29,9 @@ package mage.cards.c; import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; @@ -38,6 +40,7 @@ import mage.filter.predicate.mageobject.AnotherTargetPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetpointer.FixedTarget; /** * @@ -46,17 +49,16 @@ import mage.target.common.TargetCreaturePermanent; public class ConsumeStrength extends CardImpl { public ConsumeStrength(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{B}{G}"); - + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{B}{G}"); // Target creature gets +2/+2 until end of turn. Another target creature gets -2/-2 until end of turn. this.getSpellAbility().addEffect(new ConsumeStrengthEffect()); - + FilterCreaturePermanent filter1 = new FilterCreaturePermanent("creature to get +2/+2"); TargetCreaturePermanent target1 = new TargetCreaturePermanent(filter1); target1.setTargetTag(1); this.getSpellAbility().addTarget(target1); - + FilterCreaturePermanent filter2 = new FilterCreaturePermanent("another creature to get -2/-2"); filter2.add(new AnotherTargetPredicate(2)); TargetCreaturePermanent target2 = new TargetCreaturePermanent(filter2); @@ -74,10 +76,10 @@ public class ConsumeStrength extends CardImpl { } } -class ConsumeStrengthEffect extends ContinuousEffectImpl { +class ConsumeStrengthEffect extends OneShotEffect { public ConsumeStrengthEffect() { - super(Duration.EndOfTurn, Layer.PTChangingEffects_7, SubLayer.ModifyPT_7c, Outcome.BoostCreature); + super(Outcome.BoostCreature); this.staticText = "Target creature gets +2/+2 until end of turn. Another target creature gets -2/-2 until end of turn"; } @@ -94,14 +96,16 @@ class ConsumeStrengthEffect extends ContinuousEffectImpl { public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanent(source.getFirstTarget()); if (permanent != null) { - permanent.addPower(2); - permanent.addToughness(2); + ContinuousEffect effect = new BoostTargetEffect(2, 2, Duration.EndOfTurn); + effect.setTargetPointer(new FixedTarget(permanent, game)); + game.addEffect(effect, source); } permanent = game.getPermanent(source.getTargets().get(1).getFirstTarget()); if (permanent != null) { - permanent.addPower(-2); - permanent.addToughness(-2); + ContinuousEffect effect = new BoostTargetEffect(-2, -2, Duration.EndOfTurn); + effect.setTargetPointer(new FixedTarget(permanent, game)); + game.addEffect(effect, source); } return true; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/c/ConundrumSphinx.java b/Mage.Sets/src/mage/cards/c/ConundrumSphinx.java index 2c13d773f7..5b1080aba7 100644 --- a/Mage.Sets/src/mage/cards/c/ConundrumSphinx.java +++ b/Mage.Sets/src/mage/cards/c/ConundrumSphinx.java @@ -101,6 +101,7 @@ class ConundrumSphinxEffect extends OneShotEffect { if (player != null) { if (player.getLibrary().hasCards()) { cardChoice.clearChoice(); + cardChoice.setMessage("Name a card"); while (!player.choose(Outcome.DrawCard, cardChoice, game) && player.canRespond()) { if (!player.canRespond()) { continue Players; diff --git a/Mage.Sets/src/mage/cards/c/CustodiSoulcaller.java b/Mage.Sets/src/mage/cards/c/CustodiSoulcaller.java new file mode 100644 index 0000000000..eb5a9756df --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/CustodiSoulcaller.java @@ -0,0 +1,136 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.c; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; +import mage.abilities.keyword.MeleeAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.filter.FilterCard; +import mage.filter.common.FilterCreatureCard; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.predicate.mageobject.ConvertedManaCostPredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; +import mage.game.permanent.Permanent; +import mage.target.common.TargetCardInYourGraveyard; +import mage.watchers.Watcher; + +/** + * + * @author L_J + */ +public class CustodiSoulcaller extends CardImpl { + + public CustodiSoulcaller(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{W}{W}"); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.CLERIC); + this.power = new MageInt(1); + this.toughness = new MageInt(2); + + // Melee + this.addAbility(new MeleeAbility()); + + // Whenever Custodi Soulcaller attacks, return target creature card with converted mana cost X or less from your graveyard to the battlefield, where X is the number of players you attacked with a creature this combat. + Ability ability = new AttacksTriggeredAbility(new ReturnFromGraveyardToBattlefieldTargetEffect(), false); + ability.addWatcher(new CustodiSoulcallerWatcher()); + ability.addTarget(new TargetCardInYourGraveyard(new FilterCreatureCard("creature card with converted mana cost X or less from your graveyard, where X is the number of players you attacked with a creature this combat"))); + this.addAbility(ability); + } + + @Override + public void adjustTargets(Ability ability, Game game) { + if (ability.getClass().equals(AttacksTriggeredAbility.class)) { + ability.getTargets().clear(); + CustodiSoulcallerWatcher watcher = (CustodiSoulcallerWatcher) game.getState().getWatchers().get(CustodiSoulcallerWatcher.class.getSimpleName()); + Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(ability.getSourceId()); + if (watcher != null && watcher.playersAttacked != null) { + int xValue = watcher.getNumberOfAttackedPlayers(sourcePermanent.getControllerId()); + FilterCard filter = new FilterCard("creature card with converted mana cost " + xValue + " or less"); + filter.add(new CardTypePredicate(CardType.CREATURE)); + filter.add(Predicates.or(new ConvertedManaCostPredicate(ComparisonType.EQUAL_TO, xValue), new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, xValue))); + ability.getTargets().add(new TargetCardInYourGraveyard(filter)); + } + } + } + + public CustodiSoulcaller(final CustodiSoulcaller card) { + super(card); + } + + @Override + public CustodiSoulcaller copy() { + return new CustodiSoulcaller(this); + } +} + +class CustodiSoulcallerWatcher extends Watcher { + + protected final HashMap> playersAttacked = new HashMap<>(0); + + CustodiSoulcallerWatcher() { + super("CustodiSoulcallerWatcher", WatcherScope.GAME); + } + + CustodiSoulcallerWatcher(final CustodiSoulcallerWatcher watcher) { + super(watcher); + this.playersAttacked.putAll(watcher.playersAttacked); + } + + @Override + public void watch(GameEvent event, Game game) { + if (event.getType() == EventType.BEGIN_COMBAT_STEP_PRE) { + this.playersAttacked.clear(); + } + else if (event.getType() == EventType.ATTACKER_DECLARED) { + Set attackedPlayers = this.playersAttacked.getOrDefault(event.getPlayerId(), new HashSet<>(1)); + attackedPlayers.add(event.getTargetId()); + this.playersAttacked.put(event.getPlayerId(), attackedPlayers); + } + } + + public int getNumberOfAttackedPlayers(UUID attackerId) { + return this.playersAttacked.get(attackerId).size(); + } + + @Override + public CustodiSoulcallerWatcher copy() { + return new CustodiSoulcallerWatcher(this); + } +} diff --git a/Mage.Sets/src/mage/cards/d/DazzlingBeauty.java b/Mage.Sets/src/mage/cards/d/DazzlingBeauty.java new file mode 100644 index 0000000000..02cbf8dcfd --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DazzlingBeauty.java @@ -0,0 +1,118 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.d; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.CastOnlyDuringPhaseStepSourceAbility; +import mage.abilities.common.delayed.AtTheBeginOfNextUpkeepDelayedTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.PhaseStep; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.permanent.AttackingPredicate; +import mage.filter.predicate.permanent.BlockedPredicate; +import mage.game.Game; +import mage.game.combat.CombatGroup; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LevelX2 & L_J + */ +public class DazzlingBeauty extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("unblocked attacking creature"); + + static { + filter.add(new AttackingPredicate()); + filter.add(Predicates.not(new BlockedPredicate())); + } + + public DazzlingBeauty(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{W}"); + + // Cast Dazzling Beauty only during the declare blockers step. + this.addAbility(new CastOnlyDuringPhaseStepSourceAbility(null, PhaseStep.DECLARE_BLOCKERS, null, "Cast Dazzling Beauty only during the declare blockers step")); + + // Target unblocked attacking creature becomes blocked. + this.getSpellAbility().addEffect(new DazzlingBeautyEffect()); + this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + + // Draw a card at the beginning of the next turn's upkeep. + this.getSpellAbility().addEffect(new CreateDelayedTriggeredAbilityEffect(new AtTheBeginOfNextUpkeepDelayedTriggeredAbility(new DrawCardSourceControllerEffect(1)), false)); + } + + public DazzlingBeauty(final DazzlingBeauty card) { + super(card); + } + + @Override + public DazzlingBeauty copy() { + return new DazzlingBeauty(this); + } +} + +class DazzlingBeautyEffect extends OneShotEffect { + + public DazzlingBeautyEffect() { + super(Outcome.Benefit); + this.staticText = "Target unblocked attacking creature becomes blocked"; + } + + public DazzlingBeautyEffect(final DazzlingBeautyEffect effect) { + super(effect); + } + + @Override + public DazzlingBeautyEffect copy() { + return new DazzlingBeautyEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); + if (controller != null && permanent != null) { + CombatGroup combatGroup = game.getCombat().findGroup(permanent.getId()); + if (combatGroup != null) { + combatGroup.setBlocked(true); + return true; + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/d/DereviEmpyrialTactician.java b/Mage.Sets/src/mage/cards/d/DereviEmpyrialTactician.java index 38fd233b3a..2ac726055c 100644 --- a/Mage.Sets/src/mage/cards/d/DereviEmpyrialTactician.java +++ b/Mage.Sets/src/mage/cards/d/DereviEmpyrialTactician.java @@ -60,7 +60,7 @@ import mage.target.TargetPermanent; public class DereviEmpyrialTactician extends CardImpl { public DereviEmpyrialTactician(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{G}{W}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}{W}{U}"); addSuperType(SuperType.LEGENDARY); this.subtype.add(SubType.BIRD); this.subtype.add(SubType.WIZARD); @@ -74,7 +74,7 @@ public class DereviEmpyrialTactician extends CardImpl { Ability ability = new DereviEmpyrialTacticianTriggeredAbility(new MayTapOrUntapTargetEffect()); ability.addTarget(new TargetPermanent()); this.addAbility(ability); - + // {1}{G}{W}{U}: Put Derevi onto the battlefield from the command zone. this.addAbility(new DereviEmpyrialTacticianAbility()); } @@ -132,7 +132,7 @@ class DereviEmpyrialTacticianTriggeredAbility extends TriggeredAbilityImpl { } } - class DereviEmpyrialTacticianAbility extends ActivatedAbilityImpl { +class DereviEmpyrialTacticianAbility extends ActivatedAbilityImpl { public DereviEmpyrialTacticianAbility() { super(Zone.COMMAND, new PutCommanderOnBattlefieldEffect(), new ManaCostsImpl("{1}{G}{W}{U}")); @@ -182,7 +182,7 @@ class PutCommanderOnBattlefieldEffect extends OneShotEffect { } Card card = game.getCard(source.getSourceId()); if (card != null) { - card.putOntoBattlefield(game, Zone.COMMAND, source.getSourceId(), source.getControllerId()); + player.moveCards(card, Zone.BATTLEFIELD, source, game); return true; } return false; diff --git a/Mage.Sets/src/mage/cards/d/DreamTides.java b/Mage.Sets/src/mage/cards/d/DreamTides.java new file mode 100644 index 0000000000..c47b8dc3d4 --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DreamTides.java @@ -0,0 +1,128 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.d; + +import java.util.UUID; +import mage.ObjectColor; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DontUntapInControllersUntapStepAllEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.ColorPredicate; +import mage.filter.predicate.permanent.TappedPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.Target; +import mage.target.common.TargetControlledCreaturePermanent; + +/** + * + * @author spjspj & L_J + */ +public class DreamTides extends CardImpl { + + public DreamTides(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}{U}"); + + // Creatures don't untap during their controllers' untap steps. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new DontUntapInControllersUntapStepAllEffect(Duration.WhileOnBattlefield, TargetController.ANY, new FilterCreaturePermanent("Creatures")))); + + // At the beginning of each player's upkeep, that player may choose any number of tapped nongreen creatures he or she controls and pay {2} for each creature chosen this way. If the player does, untap those creatures. + this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new DreamTidesEffect(), TargetController.ANY, false)); + } + + public DreamTides(final DreamTides card) { + super(card); + } + + @Override + public DreamTides copy() { + return new DreamTides(this); + } +} + +class DreamTidesEffect extends OneShotEffect { + + private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("tapped nongreen creature"); + + static { + filter.add(Predicates.not(new ColorPredicate(ObjectColor.GREEN))); + filter.add(new TappedPredicate()); + } + + DreamTidesEffect() { + super(Outcome.Benefit); + staticText = "that player may choose any number of tapped nongreen creatures he or she controls and pay {2} for each creature chosen this way. If the player does, untap those creatures"; + } + + DreamTidesEffect(DreamTidesEffect effect) { + super(effect); + } + + @Override + public DreamTidesEffect copy() { + return new DreamTidesEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + + Player player = game.getPlayer(targetPointer.getFirst(game, source)); + Permanent sourcePermanent = game.getPermanent(source.getSourceId()); + if (player != null && sourcePermanent != null) { + int countBattlefield = game.getBattlefield().getAllActivePermanents(filter, game.getActivePlayerId(), game).size(); + while (player.canRespond() && countBattlefield > 0 && player.chooseUse(Outcome.AIDontUseIt, "Pay {2} and untap a tapped nongreen creature under your control?", source, game)) { + Target tappedCreatureTarget = new TargetControlledCreaturePermanent(1, 1, filter, true); + if (player.choose(Outcome.Detriment, tappedCreatureTarget, source.getSourceId(), game)) { + GenericManaCost cost = new GenericManaCost(2); + Permanent tappedCreature = game.getPermanent(tappedCreatureTarget.getFirstTarget()); + + if (cost.pay(source, game, source.getSourceId(), player.getId(), false)) { + tappedCreature.untap(game); + } + } + countBattlefield = game.getBattlefield().getAllActivePermanents(filter, game.getActivePlayerId(), game).size(); + } + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/f/ForcemageAdvocate.java b/Mage.Sets/src/mage/cards/f/ForcemageAdvocate.java new file mode 100644 index 0000000000..71579beb72 --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/ForcemageAdvocate.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.cards.f; + +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.common.counter.AddCountersTargetEffect; +import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.filter.FilterCard; +import mage.filter.StaticFilters; +import mage.target.common.TargetCardInOpponentsGraveyard; +import mage.target.common.TargetCreaturePermanent; +import mage.target.targetpointer.SecondTargetPointer; + +/** + * + * @author L_J + */ +public class ForcemageAdvocate extends CardImpl { + + public ForcemageAdvocate(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}"); + this.subtype.add(SubType.CENTAUR); + this.subtype.add(SubType.SHAMAN); + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + // {tap}: Return target card from an opponent's graveyard to his or her hand. Put a +1/+1 counter on target creature. + Effect effect = new ReturnFromGraveyardToHandTargetEffect(); + effect.setText("Return target card from an opponent's graveyard to his or her hand"); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new TapSourceCost()); + + effect = new AddCountersTargetEffect(CounterType.P1P1.createInstance()); + effect.setText("Put a +1/+1 counter on target creature"); + effect.setTargetPointer(new SecondTargetPointer()); + ability.addEffect(effect); + ability.addTarget(new TargetCardInOpponentsGraveyard(1, 1, new FilterCard(), true)); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + public ForcemageAdvocate(final ForcemageAdvocate card) { + super(card); + } + + @Override + public ForcemageAdvocate copy() { + return new ForcemageAdvocate(this); + } +} diff --git a/Mage.Sets/src/mage/cards/g/GeneralsRegalia.java b/Mage.Sets/src/mage/cards/g/GeneralsRegalia.java new file mode 100644 index 0000000000..e3c90b0b6c --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GeneralsRegalia.java @@ -0,0 +1,126 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.g; + +import java.util.UUID; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.RedirectionEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.game.stack.Spell; +import mage.players.Player; +import mage.target.TargetSource; +import mage.target.common.TargetControlledCreaturePermanent; + +/** + * + * @author L_J + */ +public class GeneralsRegalia extends CardImpl { + + public GeneralsRegalia(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{3}"); + + // {3}: The next time a source of your choice would deal damage to you this turn, that damage is dealt to target creature you control instead. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new GeneralsRegaliaEffect(), new GenericManaCost(3)); + ability.addTarget(new TargetControlledCreaturePermanent()); + this.addAbility(ability); + } + + public GeneralsRegalia(final GeneralsRegalia card) { + super(card); + } + + @Override + public GeneralsRegalia copy() { + return new GeneralsRegalia(this); + } +} + +class GeneralsRegaliaEffect extends RedirectionEffect { + + private final TargetSource damageSource; + + public GeneralsRegaliaEffect() { + super(Duration.EndOfTurn, Integer.MAX_VALUE, true); + staticText = "The next time a source of your choice would deal damage to you this turn, that damage is dealt to target creature you control instead"; + this.damageSource = new TargetSource(); + } + + public GeneralsRegaliaEffect(final GeneralsRegaliaEffect effect) { + super(effect); + this.damageSource = effect.damageSource.copy(); + } + + @Override + public GeneralsRegaliaEffect copy() { + return new GeneralsRegaliaEffect(this); + } + + @Override + public void init(Ability source, Game game) { + this.damageSource.choose(Outcome.PreventDamage, source.getControllerId(), source.getSourceId(), game); + super.init(source, game); + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + // check source + MageObject object = game.getObject(event.getSourceId()); + if (object == null) { + game.informPlayers("Couldn't find source of damage"); + return false; + } + + if (!object.getId().equals(damageSource.getFirstTarget()) + && (!(object instanceof Spell) || !((Spell) object).getSourceId().equals(damageSource.getFirstTarget()))) { + return false; + } + this.redirectTarget = source.getTargets().get(0); + + // check player + Player player = game.getPlayer(event.getTargetId()); + if (player != null) { + if (player.getId().equals(source.getControllerId())) { + return true; + } + } + return false; + } + +} diff --git a/Mage.Sets/src/mage/cards/g/GoblinMachinist.java b/Mage.Sets/src/mage/cards/g/GoblinMachinist.java new file mode 100644 index 0000000000..4253d92c1b --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GoblinMachinist.java @@ -0,0 +1,122 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.g; + +import java.util.UUID; +import mage.MageInt; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.cards.Card; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.cards.CardsImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.game.Game; +import mage.players.Library; +import mage.players.Player; + +/** + * + * @author TheElk801 + */ +public class GoblinMachinist extends CardImpl { + + public GoblinMachinist(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{R}"); + + this.subtype.add(SubType.GOBLIN); + this.power = new MageInt(0); + this.toughness = new MageInt(5); + + // {2}{R}: Reveal cards from the top of your library until you reveal a nonland card. Goblin Machinist gets +X/+0 until end of turn, where X is that card's converted mana cost. Put the revealed cards on the bottom of your library in any order. + this.addAbility(new SimpleActivatedAbility(new GoblinMachinistEffect(), new ManaCostsImpl("{2}{R}"))); + } + + public GoblinMachinist(final GoblinMachinist card) { + super(card); + } + + @Override + public GoblinMachinist copy() { + return new GoblinMachinist(this); + } +} + +class GoblinMachinistEffect extends OneShotEffect { + + public GoblinMachinistEffect() { + super(Outcome.DrawCard); + this.staticText = "Reveal cards from the top of your library until you reveal a nonland card. {this} gets +X/+0 until end of turn, where X is that card's converted mana cost. Put the revealed cards on the bottom of your library in any order"; + } + + public GoblinMachinistEffect(final GoblinMachinistEffect effect) { + super(effect); + } + + @Override + public GoblinMachinistEffect copy() { + return new GoblinMachinistEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + MageObject sourceObject = source.getSourceObject(game); + if (controller != null && sourceObject != null) { + if (controller.getLibrary().hasCards()) { + + CardsImpl cards = new CardsImpl(); + Library library = controller.getLibrary(); + Card card = null; + do { + card = library.removeFromTop(game); + if (card != null) { + cards.add(card); + } + } while (library.hasCards() && card != null && card.isLand()); + if (!cards.isEmpty()) { + controller.revealCards(sourceObject.getIdName(), cards, game); + } + boolean retVal = false; + if (card != null) { + retVal = new BoostSourceEffect(card.getConvertedManaCost(), 0, Duration.EndOfTurn).apply(game, source); + } + return controller.putCardsOnBottomOfLibrary(cards, game, source, true) && retVal; + } + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/j/Johan.java b/Mage.Sets/src/mage/cards/j/Johan.java new file mode 100644 index 0000000000..4affd49c26 --- /dev/null +++ b/Mage.Sets/src/mage/cards/j/Johan.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.cards.j; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.DelayedTriggeredAbility; +import mage.abilities.common.BeginningOfCombatTriggeredAbility; +import mage.abilities.condition.CompoundCondition; +import mage.abilities.condition.Condition; +import mage.abilities.condition.InvertCondition; +import mage.abilities.condition.common.SourceOnBattlefieldCondition; +import mage.abilities.condition.common.SourceTappedCondition; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.effects.common.combat.CantAttackSourceEffect; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.abilities.keyword.special.JohanVigilanceAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.Duration; +import mage.constants.SuperType; +import mage.constants.TargetController; +import mage.filter.common.FilterControlledCreaturePermanent; + +/** + * + * @author L_J + */ +public class Johan extends CardImpl { + + public Johan(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}{G}{W}"); + addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.WIZARD); + this.power = new MageInt(5); + this.toughness = new MageInt(4); + + // At the beginning of combat on your turn, you may have Johan gain "Johan can't attack" until end of combat. If you do, attacking doesn't cause creatures you control to tap this combat if Johan is untapped. + Condition condition = new CompoundCondition("if {this} is untapped", + new InvertCondition(SourceTappedCondition.instance), + SourceOnBattlefieldCondition.instance); + Ability ability = new BeginningOfCombatTriggeredAbility(new CantAttackSourceEffect(Duration.EndOfCombat).setText("you may have {this} gain \"{this} can't attack\" until end of combat"), TargetController.YOU, true); + ability.addEffect(new ConditionalContinuousEffect( + new GainAbilityControlledEffect(JohanVigilanceAbility.getInstance(), Duration.EndOfCombat, new FilterControlledCreaturePermanent("creatures")), + condition, + "If you do, attacking doesn't cause creatures you control to tap this combat if {this} is untapped")); + this.addAbility(ability); + } + + public Johan(final Johan card) { + super(card); + } + + @Override + public Johan copy() { + return new Johan(this); + } +} diff --git a/Mage.Sets/src/mage/cards/l/LeylineOfSingularity.java b/Mage.Sets/src/mage/cards/l/LeylineOfSingularity.java index 91c380d368..4c30b1554f 100644 --- a/Mage.Sets/src/mage/cards/l/LeylineOfSingularity.java +++ b/Mage.Sets/src/mage/cards/l/LeylineOfSingularity.java @@ -36,9 +36,7 @@ import mage.abilities.keyword.LeylineAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; -import mage.filter.FilterPermanent; -import mage.filter.predicate.Predicates; -import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.common.FilterNonlandPermanent; import mage.game.Game; import mage.game.permanent.Permanent; @@ -48,21 +46,14 @@ import mage.game.permanent.Permanent; */ public class LeylineOfSingularity extends CardImpl { - private static final FilterPermanent filter = new FilterPermanent("nonland permanents"); - - static { - filter.add(Predicates.not(new CardTypePredicate(CardType.LAND))); - } - public LeylineOfSingularity(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{U}{U}"); - + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}{U}"); + // If Leyline of Singularity is in your opening hand, you may begin the game with it on the battlefield. this.addAbility(LeylineAbility.getInstance()); // All nonland permanents are legendary. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SetSupertypeAllEffect(Duration.WhileOnBattlefield, filter))); - + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SetSupertypeAllEffect())); } public LeylineOfSingularity(final LeylineOfSingularity card) { @@ -75,19 +66,16 @@ public class LeylineOfSingularity extends CardImpl { } } - class SetSupertypeAllEffect extends ContinuousEffectImpl { - private final FilterPermanent filter; + private static final FilterNonlandPermanent filter = new FilterNonlandPermanent(); - public SetSupertypeAllEffect(Duration duration, FilterPermanent filter) { - super(duration, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Detriment); - this.filter = filter; + public SetSupertypeAllEffect() { + super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Detriment); } public SetSupertypeAllEffect(final SetSupertypeAllEffect effect) { super(effect); - this.filter = effect.filter; } @Override @@ -97,9 +85,8 @@ class SetSupertypeAllEffect extends ContinuousEffectImpl { @Override public boolean apply(Game game, Ability source) { - for (Permanent permanent: game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) { - permanent.addSuperType(SuperType.LEGENDARY); - + for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) { + permanent.addSuperType(SuperType.LEGENDARY); } return true; } diff --git a/Mage.Sets/src/mage/cards/m/ManaweftSliver.java b/Mage.Sets/src/mage/cards/m/ManaweftSliver.java index f26076952d..ff16a2ed6a 100644 --- a/Mage.Sets/src/mage/cards/m/ManaweftSliver.java +++ b/Mage.Sets/src/mage/cards/m/ManaweftSliver.java @@ -29,9 +29,8 @@ package mage.cards.m; import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.common.continuous.GainAbilityAllEffect; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; import mage.abilities.mana.AnyColorManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -39,7 +38,7 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Duration; import mage.constants.Zone; -import mage.filter.StaticFilters; +import mage.filter.common.FilterCreaturePermanent; /** * @@ -47,6 +46,8 @@ import mage.filter.StaticFilters; */ public class ManaweftSliver extends CardImpl { + public static final FilterCreaturePermanent filter = new FilterCreaturePermanent(SubType.SLIVER, "Sliver creatures"); + public ManaweftSliver(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}"); this.subtype.add(SubType.SLIVER); @@ -55,11 +56,11 @@ public class ManaweftSliver extends CardImpl { this.toughness = new MageInt(1); // Sliver creatures you control have "{T}: Add one mana of any color to your mana pool." - Ability ability = new AnyColorManaAbility(); - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, - new GainAbilityAllEffect(ability, - Duration.WhileOnBattlefield, StaticFilters.FILTER_PERMANENT_CREATURE_SLIVERS, - "Sliver creatures you control have \"{T}: Add one mana of any color to your mana pool.\""))); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityControlledEffect( + new AnyColorManaAbility(), + Duration.WhileOnBattlefield, + filter + ))); } public ManaweftSliver(final ManaweftSliver card) { diff --git a/Mage.Sets/src/mage/cards/m/MasterWarcraft.java b/Mage.Sets/src/mage/cards/m/MasterWarcraft.java index 7bac539453..a825bbebd2 100644 --- a/Mage.Sets/src/mage/cards/m/MasterWarcraft.java +++ b/Mage.Sets/src/mage/cards/m/MasterWarcraft.java @@ -56,6 +56,7 @@ import mage.target.common.TargetCreaturePermanent; import mage.filter.predicate.permanent.ControllerPredicate; import mage.target.targetpointer.FixedTarget; import mage.watchers.Watcher; +import mage.watchers.common.ChooseBlockersRedundancyWatcher; /** * @@ -67,7 +68,7 @@ public class MasterWarcraft extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{R/W}{R/W}"); // Cast Master Warcraft only before attackers are declared. - this.addAbility(new CastOnlyDuringPhaseStepSourceAbility(null, null, BeforeAttackersAreDeclaredCondition.instance, "Cast Master Warcraft only before attackers are declared")); + this.addAbility(new CastOnlyDuringPhaseStepSourceAbility(null, null, BeforeAttackersAreDeclaredCondition.instance, "Cast {this} only before attackers are declared")); // You choose which creatures attack this turn. this.getSpellAbility().addEffect(new MasterWarcraftChooseAttackersEffect()); @@ -79,6 +80,8 @@ public class MasterWarcraft extends CardImpl { // (only the last resolved Master Warcraft spell's effects apply) this.getSpellAbility().addWatcher(new MasterWarcraftCastWatcher()); this.getSpellAbility().addEffect(new MasterWarcraftCastWatcherIncrementEffect()); + this.getSpellAbility().addWatcher(new ChooseBlockersRedundancyWatcher()); + this.getSpellAbility().addEffect(new ChooseBlockersRedundancyWatcherIncrementEffect()); } public MasterWarcraft(final MasterWarcraft card) { @@ -89,6 +92,58 @@ public class MasterWarcraft extends CardImpl { public MasterWarcraft copy() { return new MasterWarcraft(this); } + + private class MasterWarcraftCastWatcherIncrementEffect extends OneShotEffect { + + MasterWarcraftCastWatcherIncrementEffect() { + super(Outcome.Neutral); + } + + MasterWarcraftCastWatcherIncrementEffect(final MasterWarcraftCastWatcherIncrementEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + MasterWarcraftCastWatcher watcher = (MasterWarcraftCastWatcher) game.getState().getWatchers().get(MasterWarcraftCastWatcher.class.getSimpleName()); + if (watcher != null) { + watcher.increment(); + return true; + } + return false; + } + + @Override + public MasterWarcraftCastWatcherIncrementEffect copy() { + return new MasterWarcraftCastWatcherIncrementEffect(this); + } + } + + private class ChooseBlockersRedundancyWatcherIncrementEffect extends OneShotEffect { + + ChooseBlockersRedundancyWatcherIncrementEffect() { + super(Outcome.Neutral); + } + + ChooseBlockersRedundancyWatcherIncrementEffect(final ChooseBlockersRedundancyWatcherIncrementEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + ChooseBlockersRedundancyWatcher watcher = (ChooseBlockersRedundancyWatcher) game.getState().getWatchers().get(ChooseBlockersRedundancyWatcher.class.getSimpleName()); + if (watcher != null) { + watcher.increment(); + return true; + } + return false; + } + + @Override + public ChooseBlockersRedundancyWatcherIncrementEffect copy() { + return new ChooseBlockersRedundancyWatcherIncrementEffect(this); + } + } } class MasterWarcraftChooseAttackersEffect extends ContinuousRuleModifyingEffectImpl { @@ -197,7 +252,7 @@ class MasterWarcraftChooseBlockersEffect extends ContinuousRuleModifyingEffectIm @Override public boolean applies(GameEvent event, Ability source, Game game) { - MasterWarcraftCastWatcher watcher = (MasterWarcraftCastWatcher) game.getState().getWatchers().get(MasterWarcraftCastWatcher.class.getSimpleName()); + ChooseBlockersRedundancyWatcher watcher = (ChooseBlockersRedundancyWatcher) game.getState().getWatchers().get(ChooseBlockersRedundancyWatcher.class.getSimpleName()); watcher.decrement(); if (watcher.copyCountApply > 0) { game.informPlayers(source.getSourceObject(game).getIdName() + " didn't apply"); @@ -249,34 +304,8 @@ class MasterWarcraftCastWatcher extends Watcher { } public void decrement() { - if (copyCountApply > 0); { + if (copyCountApply > 0) { copyCountApply--; } } } - -class MasterWarcraftCastWatcherIncrementEffect extends OneShotEffect { - - MasterWarcraftCastWatcherIncrementEffect() { - super(Outcome.Neutral); - } - - MasterWarcraftCastWatcherIncrementEffect(final MasterWarcraftCastWatcherIncrementEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - MasterWarcraftCastWatcher watcher = (MasterWarcraftCastWatcher) game.getState().getWatchers().get(MasterWarcraftCastWatcher.class.getSimpleName()); - if (watcher != null) { - watcher.increment(); - return true; - } - return false; - } - - @Override - public MasterWarcraftCastWatcherIncrementEffect copy() { - return new MasterWarcraftCastWatcherIncrementEffect(this); - } -} diff --git a/Mage.Sets/src/mage/cards/m/Melee.java b/Mage.Sets/src/mage/cards/m/Melee.java new file mode 100644 index 0000000000..ac152d93f0 --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/Melee.java @@ -0,0 +1,204 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.m; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.DelayedTriggeredAbility; +import mage.abilities.common.CastOnlyDuringPhaseStepSourceAbility; +import mage.abilities.condition.CompoundCondition; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.BeforeBlockersAreDeclaredCondition; +import mage.abilities.condition.common.IsPhaseCondition; +import mage.abilities.condition.common.MyTurnCondition; +import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; +import mage.abilities.effects.common.RemoveFromCombatTargetEffect; +import mage.abilities.effects.common.UntapTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.game.Game; +import mage.game.combat.CombatGroup; +import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.targetpointer.FixedTarget; +import mage.watchers.Watcher; +import mage.watchers.common.ChooseBlockersRedundancyWatcher; + +/** + * + * @author L_J + */ +public class Melee extends CardImpl { + + public Melee(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{4}{R}"); + + // Cast Melee only during your turn and only during combat before blockers are declared. + Condition condition = new CompoundCondition(BeforeBlockersAreDeclaredCondition.instance, + new IsPhaseCondition(TurnPhase.COMBAT), + MyTurnCondition.instance); + this.addAbility(new CastOnlyDuringPhaseStepSourceAbility(null, null, condition, "Cast {this} only during your turn and only during combat before blockers are declared")); + + // You choose which creatures block this combat and how those creatures block. + // (only the last resolved Melee spell's blocking effect applies) + this.getSpellAbility().addEffect(new MeleeChooseBlockersEffect()); + this.getSpellAbility().addWatcher(new ChooseBlockersRedundancyWatcher()); + this.getSpellAbility().addEffect(new ChooseBlockersRedundancyWatcherIncrementEffect()); + + // Whenever a creature attacks and isn't blocked this combat, untap it and remove it from combat. + this.getSpellAbility().addEffect(new CreateDelayedTriggeredAbilityEffect(new MeleeTriggeredAbility())); + } + + public Melee(final Melee card) { + super(card); + } + + @Override + public Melee copy() { + return new Melee(this); + } + + private class ChooseBlockersRedundancyWatcherIncrementEffect extends OneShotEffect { + + ChooseBlockersRedundancyWatcherIncrementEffect() { + super(Outcome.Neutral); + } + + ChooseBlockersRedundancyWatcherIncrementEffect(final ChooseBlockersRedundancyWatcherIncrementEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + ChooseBlockersRedundancyWatcher watcher = (ChooseBlockersRedundancyWatcher) game.getState().getWatchers().get(ChooseBlockersRedundancyWatcher.class.getSimpleName()); + if (watcher != null) { + watcher.increment(); + return true; + } + return false; + } + + @Override + public ChooseBlockersRedundancyWatcherIncrementEffect copy() { + return new ChooseBlockersRedundancyWatcherIncrementEffect(this); + } + } +} + +class MeleeChooseBlockersEffect extends ContinuousRuleModifyingEffectImpl { + + public MeleeChooseBlockersEffect() { + super(Duration.EndOfCombat, Outcome.Benefit, false, false); + staticText = "You choose which creatures block this combat and how those creatures block"; + } + + public MeleeChooseBlockersEffect(final MeleeChooseBlockersEffect effect) { + super(effect); + } + + @Override + public MeleeChooseBlockersEffect copy() { + return new MeleeChooseBlockersEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + return false; + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DECLARING_BLOCKERS; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + ChooseBlockersRedundancyWatcher watcher = (ChooseBlockersRedundancyWatcher) game.getState().getWatchers().get(ChooseBlockersRedundancyWatcher.class.getSimpleName()); + watcher.decrement(); + watcher.copyCount--; + if (watcher.copyCountApply > 0) { + game.informPlayers(source.getSourceObject(game).getIdName() + " didn't apply"); + this.discard(); + return false; + } + watcher.copyCountApply = watcher.copyCount; + Player blockController = game.getPlayer(source.getControllerId()); + if (blockController != null) { + game.getCombat().selectBlockers(blockController, game); + return true; + } + this.discard(); + return false; + } +} + +class MeleeTriggeredAbility extends DelayedTriggeredAbility { + + public MeleeTriggeredAbility() { + super(new UntapTargetEffect(), Duration.EndOfCombat, false); + this.addEffect(new RemoveFromCombatTargetEffect()); + } + + public MeleeTriggeredAbility(MeleeTriggeredAbility ability) { + super(ability); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.UNBLOCKED_ATTACKER; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + Permanent permanent = game.getPermanent(event.getTargetId()); + if (permanent != null) { + for (CombatGroup combatGroup : game.getCombat().getGroups()) { + if (combatGroup.getBlockers().isEmpty() && combatGroup.getAttackers().contains(event.getTargetId())) { + this.getEffects().setTargetPointer(new FixedTarget(permanent, game)); + return true; + } + } + } + return false; + } + + @Override + public MeleeTriggeredAbility copy() { + return new MeleeTriggeredAbility(this); + } + + @Override + public String getRule() { + return "Whenever a creature attacks and isn't blocked this combat, untap it and remove it from combat."; + } +} diff --git a/Mage.Sets/src/mage/cards/m/Melting.java b/Mage.Sets/src/mage/cards/m/Melting.java new file mode 100644 index 0000000000..c10d6610fa --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/Melting.java @@ -0,0 +1,100 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.m; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Layer; +import mage.constants.Outcome; +import mage.constants.SubLayer; +import mage.constants.SuperType; +import mage.constants.Zone; +import mage.filter.common.FilterLandPermanent; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * + * @author TheElk801 + */ +public class Melting extends CardImpl { + + public Melting(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{R}"); + + // All lands are no longer snow. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new MeltingEffect())); + } + + public Melting(final Melting card) { + super(card); + } + + @Override + public Melting copy() { + return new Melting(this); + } +} + +class MeltingEffect extends ContinuousEffectImpl { + + private static final FilterLandPermanent filter = new FilterLandPermanent(); + + public MeltingEffect() { + super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Detriment); + } + + public MeltingEffect(final MeltingEffect effect) { + super(effect); + } + + @Override + public MeltingEffect copy() { + return new MeltingEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) { + permanent.getSuperType().remove(SuperType.SNOW); + } + return true; + } + + @Override + public String getText(Mode mode) { + return "All lands are no longer snow"; + } +} diff --git a/Mage.Sets/src/mage/cards/m/Misinformation.java b/Mage.Sets/src/mage/cards/m/Misinformation.java new file mode 100644 index 0000000000..b146b7d17d --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/Misinformation.java @@ -0,0 +1,95 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.m; + +import java.util.List; +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.cards.*; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.filter.FilterCard; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetCardInOpponentsGraveyard; + +/** + * + * @author L_J + */ +public class Misinformation extends CardImpl { + + public Misinformation(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{B}"); + + // Put up to three target cards from an opponent's graveyard on top of his or her library in any order. + this.getSpellAbility().addTarget(new TargetCardInOpponentsGraveyard(0, 3, new FilterCard("cards from an opponent's graveyard"), true)); + this.getSpellAbility().addEffect(new MisinformationEffect()); + } + + public Misinformation(final Misinformation card) { + super(card); + } + + @Override + public Misinformation copy() { + return new Misinformation(this); + } +} + +class MisinformationEffect extends OneShotEffect { + + MisinformationEffect() { + super(Outcome.Detriment); + this.staticText = "Put up to three target cards from an opponent's graveyard on top of his or her library in any order"; + } + + MisinformationEffect(final MisinformationEffect effect) { + super(effect); + } + + @Override + public MisinformationEffect copy() { + return new MisinformationEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + List targets = this.getTargetPointer().getTargets(game, source); + if (targets != null) { + Cards cards = new CardsImpl(targets); + controller.putCardsOnTopOfLibrary(cards, game, source, true); + return true; + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/m/MuragandaPetroglyphs.java b/Mage.Sets/src/mage/cards/m/MuragandaPetroglyphs.java index 9721414ce6..8a9471676d 100644 --- a/Mage.Sets/src/mage/cards/m/MuragandaPetroglyphs.java +++ b/Mage.Sets/src/mage/cards/m/MuragandaPetroglyphs.java @@ -35,6 +35,7 @@ import mage.abilities.Ability; import mage.abilities.SpellAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.continuous.BoostAllEffect; +import mage.abilities.keyword.special.JohanVigilanceAbility; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -91,7 +92,7 @@ class NoAbilityPredicate implements Predicate { } if (isFaceDown) { for (Ability ability : abilities) { - if (!ability.getSourceId().equals(input.getId())) { + if (!ability.getSourceId().equals(input.getId()) && !ability.getClass().equals(JohanVigilanceAbility.class)) { return false; } } @@ -99,8 +100,7 @@ class NoAbilityPredicate implements Predicate { } for (Ability ability : abilities) { - if (!Objects.equals(ability.getClass(), SpellAbility.class)) { - + if (!Objects.equals(ability.getClass(), SpellAbility.class) && !ability.getClass().equals(JohanVigilanceAbility.class)) { return false; } } diff --git a/Mage.Sets/src/mage/cards/n/NissaGenesisMage.java b/Mage.Sets/src/mage/cards/n/NissaGenesisMage.java index f06bd347c3..9322cd16cb 100644 --- a/Mage.Sets/src/mage/cards/n/NissaGenesisMage.java +++ b/Mage.Sets/src/mage/cards/n/NissaGenesisMage.java @@ -42,8 +42,7 @@ import mage.constants.SubType; import mage.constants.SuperType; import mage.constants.Zone; import mage.filter.FilterCard; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.common.FilterLandPermanent; +import mage.filter.StaticFilters; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.CardTypePredicate; import mage.target.common.TargetCreaturePermanent; @@ -55,6 +54,15 @@ import mage.target.common.TargetLandPermanent; */ public class NissaGenesisMage extends CardImpl { + private static final FilterCard filter = new FilterCard("any number of creature and/or land cards"); + + static { + filter.add(Predicates.or( + new CardTypePredicate(CardType.CREATURE), + new CardTypePredicate(CardType.LAND) + )); + } + public NissaGenesisMage(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{5}{G}{G}"); this.addSuperType(SuperType.LEGENDARY); @@ -64,8 +72,8 @@ public class NissaGenesisMage extends CardImpl { //+2: Untap up to two target creatures and up to two target lands. Ability ability = new LoyaltyAbility(new UntapTargetEffect(false).setText("Untap up to two target creatures and up to two target lands"), +2); - ability.addTarget(new TargetCreaturePermanent(0, 2, new FilterCreaturePermanent("target creatures"), false)); - ability.addTarget(new TargetLandPermanent(0, 2, new FilterLandPermanent("target land"), false)); + ability.addTarget(new TargetCreaturePermanent(0, 2, StaticFilters.FILTER_PERMANENT_CREATURES, false)); + ability.addTarget(new TargetLandPermanent(0, 2, StaticFilters.FILTER_LANDS, false)); this.addAbility(ability); //-3: Target creature gets +5/+5 until end of turn. @@ -74,10 +82,8 @@ public class NissaGenesisMage extends CardImpl { this.addAbility(ability); //-10: Look at the top ten cards of your library. You may put any number of creature and/or land cards from among them onto the battlefield. Put the rest on the bottom of your library in a random order.); - FilterCard filter = new FilterCard("creature and/or land cards"); - filter.add(Predicates.or(new CardTypePredicate(CardType.CREATURE), new CardTypePredicate(CardType.LAND))); this.addAbility(new LoyaltyAbility( - new LookLibraryAndPickControllerEffect(10, 10, filter, false, false, Zone.BATTLEFIELD, true).setBackInRandomOrder(true), + new LookLibraryAndPickControllerEffect(10, 10, filter, false, true, Zone.BATTLEFIELD, false).setBackInRandomOrder(true), -10)); } diff --git a/Mage.Sets/src/mage/cards/n/NovaPentacle.java b/Mage.Sets/src/mage/cards/n/NovaPentacle.java new file mode 100644 index 0000000000..e6571a1a87 --- /dev/null +++ b/Mage.Sets/src/mage/cards/n/NovaPentacle.java @@ -0,0 +1,129 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.n; + +import java.util.UUID; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.RedirectionEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.game.stack.Spell; +import mage.players.Player; +import mage.target.TargetSource; +import mage.target.common.TargetOpponentsChoicePermanent; + +/** + * + * @author L_J + */ +public class NovaPentacle extends CardImpl { + + public NovaPentacle(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{4}"); + + // {3}, {tap}: The next time a source of your choice would deal damage to you this turn, that damage is dealt to target creature of an opponent's choice instead + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new NovaPentacleEffect(), new GenericManaCost(3)); + ability.addCost(new TapSourceCost()); + ability.addTarget(new TargetOpponentsChoicePermanent(1, 1, new FilterCreaturePermanent(), false, true)); + this.addAbility(ability); + } + + public NovaPentacle(final NovaPentacle card) { + super(card); + } + + @Override + public NovaPentacle copy() { + return new NovaPentacle(this); + } +} + +class NovaPentacleEffect extends RedirectionEffect { + + private final TargetSource damageSource; + + public NovaPentacleEffect() { + super(Duration.EndOfTurn, Integer.MAX_VALUE, true); + staticText = "The next time a source of your choice would deal damage to you this turn, that damage is dealt to target creature of an opponent's choice instead"; + this.damageSource = new TargetSource(); + } + + public NovaPentacleEffect(final NovaPentacleEffect effect) { + super(effect); + this.damageSource = effect.damageSource.copy(); + } + + @Override + public NovaPentacleEffect copy() { + return new NovaPentacleEffect(this); + } + + @Override + public void init(Ability source, Game game) { + this.damageSource.choose(Outcome.PreventDamage, source.getControllerId(), source.getSourceId(), game); + super.init(source, game); + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + // check source + MageObject object = game.getObject(event.getSourceId()); + if (object == null) { + game.informPlayers("Couldn't find source of damage"); + return false; + } + + if (!object.getId().equals(damageSource.getFirstTarget()) + && (!(object instanceof Spell) || !((Spell) object).getSourceId().equals(damageSource.getFirstTarget()))) { + return false; + } + this.redirectTarget = source.getTargets().get(0); + + // check player + Player player = game.getPlayer(event.getTargetId()); + if (player != null) { + if (player.getId().equals(source.getControllerId())) { + return true; + } + } + return false; + } + +} diff --git a/Mage.Sets/src/mage/cards/o/OdricMasterTactician.java b/Mage.Sets/src/mage/cards/o/OdricMasterTactician.java index ecdb3e6d79..69b5f7aa66 100644 --- a/Mage.Sets/src/mage/cards/o/OdricMasterTactician.java +++ b/Mage.Sets/src/mage/cards/o/OdricMasterTactician.java @@ -31,7 +31,8 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; -import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; +import mage.abilities.effects.OneShotEffect; import mage.abilities.keyword.FirstStrikeAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -40,6 +41,7 @@ import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; import mage.players.Player; +import mage.watchers.common.ChooseBlockersRedundancyWatcher; /** * @author noxx @@ -75,7 +77,9 @@ public class OdricMasterTactician extends CardImpl { class OdricMasterTacticianTriggeredAbility extends TriggeredAbilityImpl { public OdricMasterTacticianTriggeredAbility() { - super(Zone.BATTLEFIELD, new OdricMasterTacticianEffect()); + super(Zone.BATTLEFIELD, new OdricMasterTacticianChooseBlockersEffect()); + this.addWatcher(new ChooseBlockersRedundancyWatcher()); + this.addEffect(new ChooseBlockersRedundancyWatcherIncrementEffect()); } public OdricMasterTacticianTriggeredAbility(final OdricMasterTacticianTriggeredAbility ability) { @@ -89,52 +93,55 @@ class OdricMasterTacticianTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == EventType.DECLARED_ATTACKERS; + return event.getType() == GameEvent.EventType.DECLARED_ATTACKERS; } @Override public boolean checkTrigger(GameEvent event, Game game) { - resetEffect(); - if (game.getCombat().getAttackers().size() >= 4 && game.getCombat().getAttackers().contains(this.sourceId)) { - enableEffect(); - return true; + return game.getCombat().getAttackers().size() >= 4 && game.getCombat().getAttackers().contains(this.sourceId); + } + + private class ChooseBlockersRedundancyWatcherIncrementEffect extends OneShotEffect { + + ChooseBlockersRedundancyWatcherIncrementEffect() { + super(Outcome.Neutral); + } + + ChooseBlockersRedundancyWatcherIncrementEffect(final ChooseBlockersRedundancyWatcherIncrementEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + ChooseBlockersRedundancyWatcher watcher = (ChooseBlockersRedundancyWatcher) game.getState().getWatchers().get(ChooseBlockersRedundancyWatcher.class.getSimpleName()); + if (watcher != null) { + watcher.increment(); + return true; + } + return false; + } + + @Override + public ChooseBlockersRedundancyWatcherIncrementEffect copy() { + return new ChooseBlockersRedundancyWatcherIncrementEffect(this); } - return false; } - - @Override - public void reset(Game game) { - resetEffect(); - } - - private void resetEffect() { - getEffects().get(0).setValue("apply_" + sourceId, false); - } - - private void enableEffect() { - getEffects().get(0).setValue("apply_" + sourceId, true); - } - - @Override - public String getRule() { - return "Whenever {this} and at least three other creatures attack, you choose which creatures block this combat and how those creatures block."; - } - } -class OdricMasterTacticianEffect extends ReplacementEffectImpl { +class OdricMasterTacticianChooseBlockersEffect extends ContinuousRuleModifyingEffectImpl { - public OdricMasterTacticianEffect() { - super(Duration.EndOfCombat, Outcome.Benefit); + public OdricMasterTacticianChooseBlockersEffect() { + super(Duration.EndOfCombat, Outcome.Benefit, false, false); + staticText = "Whenever {this} and at least three other creatures attack, you choose which creatures block this combat and how those creatures block"; } - public OdricMasterTacticianEffect(final OdricMasterTacticianEffect effect) { + public OdricMasterTacticianChooseBlockersEffect(final OdricMasterTacticianChooseBlockersEffect effect) { super(effect); } @Override - public OdricMasterTacticianEffect copy() { - return new OdricMasterTacticianEffect(this); + public OdricMasterTacticianChooseBlockersEffect copy() { + return new OdricMasterTacticianChooseBlockersEffect(this); } @Override @@ -142,16 +149,6 @@ class OdricMasterTacticianEffect extends ReplacementEffectImpl { return false; } - @Override - public boolean replaceEvent(GameEvent event, Ability source, Game game) { - Player blockController = game.getPlayer(source.getControllerId()); - if (blockController != null) { - game.getCombat().selectBlockers(blockController, game); - return true; - } - return false; - } - @Override public boolean checksEventType(GameEvent event, Game game) { return event.getType() == GameEvent.EventType.DECLARING_BLOCKERS; @@ -159,12 +156,21 @@ class OdricMasterTacticianEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { - Object object = getValue("apply_" + source.getSourceId()); - if (object != null && object instanceof Boolean) { - if ((Boolean)object) { - return true; // replace event - } + ChooseBlockersRedundancyWatcher watcher = (ChooseBlockersRedundancyWatcher) game.getState().getWatchers().get(ChooseBlockersRedundancyWatcher.class.getSimpleName()); + watcher.decrement(); + watcher.copyCount--; + if (watcher.copyCountApply > 0) { + game.informPlayers(source.getSourceObject(game).getIdName() + " didn't apply"); + this.discard(); + return false; } + watcher.copyCountApply = watcher.copyCount; + Player blockController = game.getPlayer(source.getControllerId()); + if (blockController != null) { + game.getCombat().selectBlockers(blockController, game); + return true; + } + this.discard(); return false; } } diff --git a/Mage.Sets/src/mage/cards/p/PetraSphinx.java b/Mage.Sets/src/mage/cards/p/PetraSphinx.java new file mode 100644 index 0000000000..a1292fd7d0 --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PetraSphinx.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.cards.p; + +import java.util.UUID; +import mage.MageInt; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.OneShotEffect; +import mage.cards.*; +import mage.cards.repository.CardRepository; +import mage.choices.Choice; +import mage.choices.ChoiceImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.game.Game; +import mage.players.Player; +import mage.target.TargetPlayer; + +/** + * + * @author BetaSteward_at_googlemail.com & L_J + */ +public class PetraSphinx extends CardImpl { + + public PetraSphinx(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}{W}{W}"); + this.subtype.add(SubType.SPHINX); + + this.power = new MageInt(3); + this.toughness = new MageInt(4); + + // {tap}: Target player chooses a card name, then reveals the top card of his or her library. If that card has the chosen name, that player puts it into his or her hand. If it doesn't, the player puts it into his or her graveyard. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new PetraSphinxEffect(), new TapSourceCost()); + ability.addTarget(new TargetPlayer()); + this.addAbility(ability); + } + + public PetraSphinx(final PetraSphinx card) { + super(card); + } + + @Override + public PetraSphinx copy() { + return new PetraSphinx(this); + } + +} + +class PetraSphinxEffect extends OneShotEffect { + + public PetraSphinxEffect() { + super(Outcome.DrawCard); + staticText = "Target player chooses a card name, then reveals the top card of his or her library. If that card has the chosen name, that player puts it into his or her hand. If it doesn't, the player puts it into his or her graveyard"; + } + + public PetraSphinxEffect(final PetraSphinxEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + MageObject sourceObject = source.getSourceObject(game); + Player controller = game.getPlayer(source.getControllerId()); + Player player = game.getPlayer(targetPointer.getFirst(game, source)); + if (controller != null && sourceObject != null && player != null) { + + + if (player.getLibrary().hasCards()) { + Choice cardChoice = new ChoiceImpl(); + cardChoice.setChoices(CardRepository.instance.getNames()); + cardChoice.setMessage("Name a card"); + while (!player.choose(Outcome.DrawCard, cardChoice, game)) { + if (!player.canRespond()) { + return false; + } + } + String cardName = cardChoice.getChoice(); + game.informPlayers(sourceObject.getLogName() + ", player: " + player.getLogName() + ", named: [" + cardName + ']'); + Card card = player.getLibrary().removeFromTop(game); + if (card != null) { + Cards cards = new CardsImpl(card); + player.revealCards(sourceObject.getIdName(), cards, game); + if (card.getName().equals(cardName)) { + player.moveCards(cards, Zone.HAND, source, game); + } else { + player.moveCards(cards, Zone.GRAVEYARD, source, game); + } + } + } + return true; + } + return false; + } + + @Override + public PetraSphinxEffect copy() { + return new PetraSphinxEffect(this); + } + +} diff --git a/Mage.Sets/src/mage/cards/p/PrismaticWard.java b/Mage.Sets/src/mage/cards/p/PrismaticWard.java new file mode 100644 index 0000000000..3d5c31ec3b --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PrismaticWard.java @@ -0,0 +1,129 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.p; + +import java.util.UUID; +import mage.MageObject; +import mage.ObjectColor; +import mage.constants.SubType; +import mage.target.common.TargetCreaturePermanent; +import mage.abilities.Ability; +import mage.abilities.common.AsEntersBattlefieldAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.PreventionEffectImpl; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.ChooseColorEffect; +import mage.constants.Outcome; +import mage.target.TargetPermanent; +import mage.abilities.keyword.EnchantAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; + +/** + * + * @author TheElk801 + */ +public class PrismaticWard extends CardImpl { + + public PrismaticWard(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}"); + + this.subtype.add(SubType.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); + + // As Prismatic Ward enters the battlefield, choose a color. + this.addAbility(new AsEntersBattlefieldAbility(new ChooseColorEffect(Outcome.Benefit))); + + // Prevent all damage that would be dealt to enchanted creature by sources of the chosen color. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new PrismaticWardPreventDamageEffect())); + } + + public PrismaticWard(final PrismaticWard card) { + super(card); + } + + @Override + public PrismaticWard copy() { + return new PrismaticWard(this); + } +} + +class PrismaticWardPreventDamageEffect extends PreventionEffectImpl { + + public PrismaticWardPreventDamageEffect() { + super(Duration.WhileOnBattlefield, Integer.MAX_VALUE, false); + staticText = "Prevent all damage that would be dealt to enchanted creature by sources of the chosen color."; + } + + public PrismaticWardPreventDamageEffect(final PrismaticWardPreventDamageEffect effect) { + super(effect); + } + + @Override + public PrismaticWardPreventDamageEffect copy() { + return new PrismaticWardPreventDamageEffect(this); + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (!super.applies(event, source, game)) { + return false; + } + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent == null) { + return false; + } + ObjectColor color = (ObjectColor) game.getState().getValue(permanent.getId() + "_color"); + if (color == null) { + return false; + } + MageObject sourceObject = game.getObject(event.getSourceId()); + if (sourceObject == null || !sourceObject.getColor(game).shares(color)) { + return false; + } + Permanent attachment = game.getPermanent(source.getSourceId()); + if (attachment != null + && attachment.getAttachedTo() != null + && event.getTargetId().equals(attachment.getAttachedTo())) { + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/s/ShadesBreath.java b/Mage.Sets/src/mage/cards/s/ShadesBreath.java new file mode 100644 index 0000000000..c3580f87f4 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/ShadesBreath.java @@ -0,0 +1,143 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.s; + +import java.util.List; +import java.util.UUID; +import mage.ObjectColor; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Layer; +import mage.constants.Outcome; +import mage.constants.SubLayer; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.util.SubTypeList; + +/** + * + * @author TheElk801 + */ +public class ShadesBreath extends CardImpl { + + public ShadesBreath(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{B}"); + + // Until end of turn, each creature you control becomes a black Shade and gains "{B}: This creature gets +1/+1 until end of turn." + this.getSpellAbility().addEffect(new ShadesBreathSetColorEffect()); + this.getSpellAbility().addEffect(new ShadesBreathSetSubtypeEffect()); + this.getSpellAbility().addEffect( + new GainAbilityControlledEffect(new SimpleActivatedAbility( + Zone.BATTLEFIELD, + new BoostSourceEffect(1, 1, Duration.EndOfTurn).setText("this creature gets +1/+1 until end of turn"), + new ManaCostsImpl("{B}") + ), Duration.EndOfTurn, StaticFilters.FILTER_CONTROLLED_A_CREATURE) + .setText("and gains \"{B}: This creature gets +1/+1 until end of turn.\"") + ); + } + + public ShadesBreath(final ShadesBreath card) { + super(card); + } + + @Override + public ShadesBreath copy() { + return new ShadesBreath(this); + } +} + +class ShadesBreathSetColorEffect extends ContinuousEffectImpl { + + public ShadesBreathSetColorEffect() { + super(Duration.EndOfTurn, Layer.ColorChangingEffects_5, SubLayer.NA, Outcome.Benefit); + staticText = "Until end of turn, each creature you control becomes a black"; + } + + public ShadesBreathSetColorEffect(final ShadesBreathSetColorEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + List permanents = game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), game); + for (Permanent permanent : permanents) { + if (permanent != null) { + permanent.getColor(game).setColor(ObjectColor.BLACK); + } + } + return true; + } + + @Override + public ShadesBreathSetColorEffect copy() { + return new ShadesBreathSetColorEffect(this); + } +} + +class ShadesBreathSetSubtypeEffect extends ContinuousEffectImpl { + + public ShadesBreathSetSubtypeEffect() { + super(Duration.EndOfTurn, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Benefit); + staticText = "Shade"; + } + + public ShadesBreathSetSubtypeEffect(final ShadesBreathSetSubtypeEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + List permanents = game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), game); + for (Permanent permanent : permanents) { + if (permanent != null) { + SubTypeList subtype = permanent.getSubtype(game); + if (subtype != null && subtype.size() != 1 || !subtype.contains(SubType.SHADE)) { + subtype.removeAll(SubType.getCreatureTypes(false)); + subtype.add(SubType.SHADE); + } + } + } + return true; + } + + @Override + public ShadesBreathSetSubtypeEffect copy() { + return new ShadesBreathSetSubtypeEffect(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/ShieldmageAdvocate.java b/Mage.Sets/src/mage/cards/s/ShieldmageAdvocate.java new file mode 100644 index 0000000000..15022713e9 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/ShieldmageAdvocate.java @@ -0,0 +1,132 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.s; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.Effect; +import mage.abilities.effects.PreventionEffectImpl; +import mage.abilities.effects.common.PreventDamageToTargetEffect; +import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.target.TargetSource; +import mage.target.common.TargetCardInOpponentsGraveyard; +import mage.target.common.TargetCreatureOrPlayer; +import mage.target.targetpointer.SecondTargetPointer; + +/** + * + * @author L_J + */ +public class ShieldmageAdvocate extends CardImpl { + + public ShieldmageAdvocate(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}"); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.CLERIC); + this.power = new MageInt(1); + this.toughness = new MageInt(3); + + // {tap}: Return target card from an opponent's graveyard to his or her hand. Prevent all damage that would be dealt to target creature or player this turn by a source of your choice. + Effect effect = new ReturnFromGraveyardToHandTargetEffect(); + effect.setText("Return target card from an opponent's graveyard to his or her hand"); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new TapSourceCost()); + + effect = new ShieldmageAdvocateEffect(); + effect.setTargetPointer(new SecondTargetPointer()); + ability.addEffect(effect); + ability.addTarget(new TargetCardInOpponentsGraveyard(1, 1, new FilterCard(), true)); + ability.addTarget(new TargetCreatureOrPlayer()); + this.addAbility(ability); + } + + public ShieldmageAdvocate(final ShieldmageAdvocate card) { + super(card); + } + + @Override + public ShieldmageAdvocate copy() { + return new ShieldmageAdvocate(this); + } +} + +class ShieldmageAdvocateEffect extends PreventionEffectImpl { + + protected final TargetSource targetSource; + + public ShieldmageAdvocateEffect() { + super(Duration.EndOfTurn, Integer.MAX_VALUE, false); + staticText = "Prevent all damage that would be dealt to target creature or player this turn by a source of your choice"; + this.targetSource = new TargetSource(); + } + + public ShieldmageAdvocateEffect(final ShieldmageAdvocateEffect effect) { + super(effect); + this.targetSource = effect.targetSource.copy(); + } + + @Override + public ShieldmageAdvocateEffect copy() { + return new ShieldmageAdvocateEffect(this); + } + + @Override + public void init(Ability source, Game game) { + this.targetSource.choose(Outcome.PreventDamage, source.getControllerId(), source.getSourceId(), game); + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + preventDamageAction(event, source, game); + return false; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (super.applies(event, source, game)) { + if (event.getTargetId().equals(targetPointer.getFirst(game, source)) && event.getSourceId().equals(targetSource.getFirstTarget())) { + return true; + } + } + return false; + } + +} diff --git a/Mage.Sets/src/mage/cards/s/Skulduggery.java b/Mage.Sets/src/mage/cards/s/Skulduggery.java index 7690f8944c..b3d4dbf328 100644 --- a/Mage.Sets/src/mage/cards/s/Skulduggery.java +++ b/Mage.Sets/src/mage/cards/s/Skulduggery.java @@ -29,14 +29,14 @@ package mage.cards.s; import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; -import mage.constants.Layer; import mage.constants.Outcome; -import mage.constants.SubLayer; import mage.constants.TargetController; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.ControllerPredicate; @@ -44,6 +44,7 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetpointer.FixedTarget; /** * @@ -76,10 +77,10 @@ public class Skulduggery extends CardImpl { } } -class SkulduggeryEffect extends ContinuousEffectImpl { +class SkulduggeryEffect extends OneShotEffect { public SkulduggeryEffect() { - super(Duration.EndOfTurn, Layer.PTChangingEffects_7, SubLayer.ModifyPT_7c, Outcome.BoostCreature); + super(Outcome.BoostCreature); this.staticText = "Until end of turn, target creature you control gets +1/+1 and target creature an opponent controls gets -1/-1"; } @@ -96,13 +97,15 @@ class SkulduggeryEffect extends ContinuousEffectImpl { public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanent(source.getFirstTarget()); if (permanent != null) { - permanent.addPower(1); - permanent.addToughness(1); + ContinuousEffect effect = new BoostTargetEffect(1, 1, Duration.EndOfTurn); + effect.setTargetPointer(new FixedTarget(permanent, game)); + game.addEffect(effect, source); } permanent = game.getPermanent(source.getTargets().get(1).getFirstTarget()); if (permanent != null) { - permanent.addPower(-1); - permanent.addToughness(-1); + ContinuousEffect effect = new BoostTargetEffect(-1, -1, Duration.EndOfTurn); + effect.setTargetPointer(new FixedTarget(permanent, game)); + game.addEffect(effect, source); } return true; } diff --git a/Mage.Sets/src/mage/cards/s/SporeCloud.java b/Mage.Sets/src/mage/cards/s/SporeCloud.java new file mode 100644 index 0000000000..38dbaaf8c7 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SporeCloud.java @@ -0,0 +1,123 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.s; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DontUntapInControllersNextUntapStepTargetEffect; +import mage.abilities.effects.common.PreventAllDamageByAllPermanentsEffect; +import mage.abilities.effects.common.TapAllEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.permanent.AttackingPredicate; +import mage.filter.predicate.permanent.BlockingPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.targetpointer.FixedTargets; + +/** + * + * @author L_J + */ +public class SporeCloud extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("blocking creatures"); + static { + filter.add(new BlockingPredicate()); + } + + public SporeCloud(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{G}{G}"); + + // Tap all blocking creatures. + this.getSpellAbility().addEffect(new TapAllEffect(filter)); + // Prevent all combat damage that would be dealt this turn. + this.getSpellAbility().addEffect(new PreventAllDamageByAllPermanentsEffect(Duration.EndOfTurn, true)); + // Each attacking creature and each blocking creature doesn't untap during its controller's next untap step. + this.getSpellAbility().addEffect(new SporeCloudEffect()); + } + + public SporeCloud(final SporeCloud card) { + super(card); + } + + @Override + public SporeCloud copy() { + return new SporeCloud(this); + } +} + +class SporeCloudEffect extends OneShotEffect { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Each attacking creature and each blocking creature"); + static { + filter.add(Predicates.or(new AttackingPredicate(), new BlockingPredicate())); + } + + public SporeCloudEffect() { + super(Outcome.Benefit); + this.staticText = "Each attacking creature and each blocking creature doesn't untap during its controller's next untap step"; + } + + public SporeCloudEffect(final SporeCloudEffect effect) { + super(effect); + } + + @Override + public SporeCloudEffect copy() { + return new SporeCloudEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + List doNotUntapNextUntapStep = new ArrayList<>(); + for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) { + doNotUntapNextUntapStep.add(permanent); + } + if (!doNotUntapNextUntapStep.isEmpty()) { + ContinuousEffect effect = new DontUntapInControllersNextUntapStepTargetEffect("This creature"); + effect.setTargetPointer(new FixedTargets(doNotUntapNextUntapStep, game)); + game.addEffect(effect, source); + } + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/t/Teleport.java b/Mage.Sets/src/mage/cards/t/Teleport.java new file mode 100644 index 0000000000..3fea5398ba --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/Teleport.java @@ -0,0 +1,64 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.t; + +import java.util.UUID; +import mage.abilities.common.CastOnlyDuringPhaseStepSourceAbility; +import mage.abilities.effects.common.combat.CantBeBlockedTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.PhaseStep; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author L_J + */ +public class Teleport extends CardImpl { + + public Teleport(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{U}{U}{U}"); + + // Cast Teleport only during the declare attackers step. + this.addAbility(new CastOnlyDuringPhaseStepSourceAbility(null, PhaseStep.DECLARE_ATTACKERS, null, "Cast Teleport only during the declare attackers step")); + + // Target creature can't be blocked this turn. + this.getSpellAbility().addEffect(new CantBeBlockedTargetEffect()); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + } + + public Teleport(final Teleport card) { + super(card); + } + + @Override + public Teleport copy() { + return new Teleport(this); + } +} diff --git a/Mage.Sets/src/mage/cards/t/TimeElemental.java b/Mage.Sets/src/mage/cards/t/TimeElemental.java new file mode 100644 index 0000000000..62dc23201d --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TimeElemental.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.cards.t; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.DelayedTriggeredAbility; +import mage.abilities.common.AttacksOrBlocksTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.delayed.AtTheEndOfCombatDelayedTriggeredAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; +import mage.abilities.effects.common.DamageControllerEffect; +import mage.abilities.effects.common.ReturnToHandTargetEffect; +import mage.abilities.effects.common.SacrificeSourceEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.filter.FilterPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.permanent.EnchantedPredicate; +import mage.target.TargetPermanent; + +/** + * + * @author L_J + */ +public class TimeElemental extends CardImpl { + + private static final FilterPermanent filter = new FilterPermanent("permanent that isn't enchanted"); + + static { + filter.add(Predicates.not(new EnchantedPredicate())); + } + + public TimeElemental(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}"); + this.subtype.add(SubType.ELEMENTAL); + this.power = new MageInt(0); + this.toughness = new MageInt(2); + + // When Time Elemental attacks or blocks, at end of combat, sacrifice it and it deals 5 damage to you. + DelayedTriggeredAbility ability = new AtTheEndOfCombatDelayedTriggeredAbility(new SacrificeSourceEffect().setText("at end of combat, sacrifice it")); + ability.addEffect(new DamageControllerEffect(5).setText("and it deals 5 damage to you")); + this.addAbility(new AttacksOrBlocksTriggeredAbility(new CreateDelayedTriggeredAbilityEffect(ability, true), false)); + + // {2}{U}{U}, {tap}: Return target permanent that isn't enchanted to its owner's hand. + Ability ability2 = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ReturnToHandTargetEffect(), new ManaCostsImpl("{2}{U}{U}")); + ability2.addCost(new TapSourceCost()); + ability2.addTarget(new TargetPermanent(filter)); + this.addAbility(ability2); + } + + public TimeElemental(final TimeElemental card) { + super(card); + } + + @Override + public TimeElemental copy() { + return new TimeElemental(this); + } +} diff --git a/Mage.Sets/src/mage/cards/t/TourachsGate.java b/Mage.Sets/src/mage/cards/t/TourachsGate.java new file mode 100644 index 0000000000..f298c2a9ff --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TourachsGate.java @@ -0,0 +1,164 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.t; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.ActivateIfConditionActivatedAbility; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.condition.common.AttachedToMatchesFilterCondition; +import mage.abilities.costs.Cost; +import mage.abilities.costs.common.TapAttachedCost; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.continuous.BoostAllEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.keyword.EnchantAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.Outcome; +import mage.constants.Duration; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.filter.predicate.permanent.AttackingPredicate; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.filter.predicate.permanent.TappedPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; +import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.common.TargetControlledPermanent; + +/** + * + * @author L_J + */ +public class TourachsGate extends CardImpl { + + private static final FilterControlledPermanent filterLand = new FilterControlledPermanent("land you control"); + static { + filterLand.add(new CardTypePredicate(CardType.LAND)); + } + + private static final FilterPermanent filterUntapped = new FilterPermanent("enchanted land is untapped"); + static { + filterUntapped.add(Predicates.not(new TappedPredicate())); + } + + private static final FilterCreaturePermanent filterAttackingCreatures = new FilterCreaturePermanent("attacking creatures you control"); + static { + filterAttackingCreatures.add(new AttackingPredicate()); + filterAttackingCreatures.add(new ControllerPredicate(TargetController.YOU)); + } + + private static final FilterControlledCreaturePermanent filterThrull = new FilterControlledCreaturePermanent("a Thrull"); + static { + filterThrull.add(new SubtypePredicate(SubType.THRULL)); + } + + public TourachsGate(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{B}{B}"); + this.subtype.add(SubType.AURA); + + // Enchant land you control + TargetPermanent auraTarget = new TargetControlledPermanent(filterLand); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.AddAbility)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + + // Sacrifice a Thrull: Put three time counters on Tourach's Gate. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.TIME.createInstance(3)), + new SacrificeTargetCost(new TargetControlledCreaturePermanent(1,1, filterThrull, true)))); + + // At the beginning of your upkeep, remove a time counter from Tourach's Gate. If there are no time counters on Tourach's Gate, sacrifice it. + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new TourachsGateUpkeepEffect(), TargetController.YOU, false)); + + // Tap enchanted land: Attacking creatures you control get +2/-1 until end of turn. Activate this ability only if enchanted land is untapped. + Cost cost = new TapAttachedCost(); + cost.setText("Tap enchanted land"); + this.addAbility(new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, new BoostAllEffect(2, -1, Duration.EndOfTurn, filterAttackingCreatures, false), + cost, new AttachedToMatchesFilterCondition(filterUntapped))); + } + + public TourachsGate(final TourachsGate card) { + super(card); + } + + @Override + public TourachsGate copy() { + return new TourachsGate(this); + } +} + +class TourachsGateUpkeepEffect extends OneShotEffect { + + TourachsGateUpkeepEffect() { + super(Outcome.Sacrifice); + staticText = "remove a time counter from {this}. If there are no time counters on {this}, sacrifice it"; + } + + TourachsGateUpkeepEffect(final TourachsGateUpkeepEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent != null) { + int amount = permanent.getCounters(game).getCount(CounterType.TIME); + if (amount > 0) { + permanent.removeCounters(CounterType.TIME.createInstance(), game); + } + // is supposed to function similar to Vanishing + amount = permanent.getCounters(game).getCount(CounterType.TIME); + if (amount == 0) { + permanent.sacrifice(source.getSourceId(), game); + } + return true; + } + return false; + } + + @Override + public TourachsGateUpkeepEffect copy() { + return new TourachsGateUpkeepEffect(this); + } +} diff --git a/Mage.Sets/src/mage/cards/v/VeteransVoice.java b/Mage.Sets/src/mage/cards/v/VeteransVoice.java new file mode 100644 index 0000000000..880bc071ee --- /dev/null +++ b/Mage.Sets/src/mage/cards/v/VeteransVoice.java @@ -0,0 +1,114 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.v; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.ActivateIfConditionActivatedAbility; +import mage.abilities.condition.common.AttachedToMatchesFilterCondition; +import mage.abilities.costs.common.TapAttachedCost; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.Outcome; +import mage.constants.Duration; +import mage.constants.Zone; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicate; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.permanent.TappedPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; +import mage.target.common.TargetControlledCreaturePermanent; + +/** + * + * @author L_J + */ +public class VeteransVoice extends CardImpl { + + private static final FilterCreaturePermanent filterUntapped = new FilterCreaturePermanent("enchanted creature is untapped"); + + static { + filterUntapped.add(Predicates.not(new TappedPredicate())); + } + + public VeteransVoice(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{R}"); + this.subtype.add(SubType.AURA); + + // Enchant creature you control + TargetPermanent auraTarget = new TargetControlledCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + + // Tap enchanted creature: Target creature other than the creature tapped this way gets +2/+1 until end of turn. Activate this ability only if enchanted creature is untapped. + FilterPermanent filterTarget = new FilterCreaturePermanent("creature other than the creature tapped this way"); + filterTarget.add(Predicates.not(new AttachmentByUUIDPredicate(this.getId()))); + Ability ability2 = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, + new BoostTargetEffect(2, 1, Duration.EndOfTurn), new TapAttachedCost(), new AttachedToMatchesFilterCondition(filterUntapped)); + ability2.addTarget(new TargetPermanent(filterTarget)); + this.addAbility(ability2); + } + + public VeteransVoice(final VeteransVoice card) { + super(card); + } + + @Override + public VeteransVoice copy() { + return new VeteransVoice(this); + } +} + +class AttachmentByUUIDPredicate implements Predicate { + + private final UUID id; + + public AttachmentByUUIDPredicate(UUID id) { + this.id = id; + } + + @Override + public boolean apply(Permanent input, Game game) { + return input.getAttachments().contains(id); + } + + @Override + public String toString() { + return "AttachmentUUID(" + id + ')'; + } +} diff --git a/Mage.Sets/src/mage/cards/v/VexingArcanix.java b/Mage.Sets/src/mage/cards/v/VexingArcanix.java new file mode 100644 index 0000000000..5278c1626b --- /dev/null +++ b/Mage.Sets/src/mage/cards/v/VexingArcanix.java @@ -0,0 +1,127 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.v; + +import java.util.UUID; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.OneShotEffect; +import mage.cards.*; +import mage.cards.repository.CardRepository; +import mage.choices.Choice; +import mage.choices.ChoiceImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.game.Game; +import mage.players.Player; +import mage.target.TargetPlayer; + +/** + * + * @author BetaSteward_at_googlemail.com & L_J + */ +public class VexingArcanix extends CardImpl { + + public VexingArcanix(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}"); + + // {3}, {tap}: Target player chooses a card name, then reveals the top card of his or her library. If that card has the chosen name, the player puts it into his or her hand. Otherwise, the player puts it into his or her graveyard and Vexing Arcanix deals 2 damage to him or her. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new VexingArcanixEffect(), new GenericManaCost(3)); + ability.addCost(new TapSourceCost()); + ability.addTarget(new TargetPlayer()); + this.addAbility(ability); + } + + public VexingArcanix(final VexingArcanix card) { + super(card); + } + + @Override + public VexingArcanix copy() { + return new VexingArcanix(this); + } + +} + +class VexingArcanixEffect extends OneShotEffect { + + public VexingArcanixEffect() { + super(Outcome.DrawCard); + staticText = "Target player chooses a card name, then reveals the top card of his or her library. If that card has the chosen name, the player puts it into his or her hand. Otherwise, the player puts it into his or her graveyard and {this} deals 2 damage to him or her"; + } + + public VexingArcanixEffect(final VexingArcanixEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + MageObject sourceObject = source.getSourceObject(game); + Player controller = game.getPlayer(source.getControllerId()); + Player player = game.getPlayer(targetPointer.getFirst(game, source)); + if (controller != null && sourceObject != null && player != null) { + + + if (player.getLibrary().hasCards()) { + Choice cardChoice = new ChoiceImpl(); + cardChoice.setChoices(CardRepository.instance.getNames()); + cardChoice.setMessage("Name a card"); + while (!player.choose(Outcome.DrawCard, cardChoice, game)) { + if (!player.canRespond()) { + return false; + } + } + String cardName = cardChoice.getChoice(); + game.informPlayers(sourceObject.getLogName() + ", player: " + player.getLogName() + ", named: [" + cardName + ']'); + Card card = player.getLibrary().removeFromTop(game); + if (card != null) { + Cards cards = new CardsImpl(card); + player.revealCards(sourceObject.getIdName(), cards, game); + if (card.getName().equals(cardName)) { + player.moveCards(cards, Zone.HAND, source, game); + } else { + player.moveCards(cards, Zone.GRAVEYARD, source, game); + player.damage(2, source.getSourceId(), game, false, true); + } + } + } + return true; + } + return false; + } + + @Override + public VexingArcanixEffect copy() { + return new VexingArcanixEffect(this); + } + +} diff --git a/Mage.Sets/src/mage/sets/Alliances.java b/Mage.Sets/src/mage/sets/Alliances.java index 4147a07003..1a67bc92be 100644 --- a/Mage.Sets/src/mage/sets/Alliances.java +++ b/Mage.Sets/src/mage/sets/Alliances.java @@ -104,7 +104,7 @@ public class Alliances extends ExpansionSet { cards.add(new SetCardInfo("Keeper of Tresserhorn", 14, Rarity.RARE, mage.cards.k.KeeperOfTresserhorn.class)); cards.add(new SetCardInfo("Kjeldoran Home Guard", 135, Rarity.UNCOMMON, mage.cards.k.KjeldoranHomeGuard.class)); cards.add(new SetCardInfo("Kjeldoran Outpost", 184, Rarity.RARE, mage.cards.k.KjeldoranOutpost.class)); - cards.add(new SetCardInfo("Krovikan Horror", 15, Rarity.RARE, mage.cards.k.KrovikanHorror.class)); + cards.add(new SetCardInfo("Krovikan Horror", 15, Rarity.RARE, mage.cards.k.KrovikanHorror.class)); cards.add(new SetCardInfo("Krovikan Plague", 16, Rarity.UNCOMMON, mage.cards.k.KrovikanPlague.class)); cards.add(new SetCardInfo("Lake of the Dead", 185, Rarity.RARE, mage.cards.l.LakeOfTheDead.class)); cards.add(new SetCardInfo("Library of Lat-Nam", 47, Rarity.RARE, mage.cards.l.LibraryOfLatNam.class)); @@ -114,6 +114,7 @@ public class Alliances extends ExpansionSet { cards.add(new SetCardInfo("Lim-Dul's Vault", 192, Rarity.UNCOMMON, mage.cards.l.LimDulsVault.class)); cards.add(new SetCardInfo("Lord of Tresserhorn", 193, Rarity.RARE, mage.cards.l.LordOfTresserhorn.class)); cards.add(new SetCardInfo("Mishra's Groundbreaker", 165, Rarity.UNCOMMON, mage.cards.m.MishrasGroundbreaker.class)); + cards.add(new SetCardInfo("Misinformation", 19, Rarity.UNCOMMON, mage.cards.m.Misinformation.class)); cards.add(new SetCardInfo("Mystic Compass", 166, Rarity.UNCOMMON, mage.cards.m.MysticCompass.class)); cards.add(new SetCardInfo("Nature's Chosen", 81, Rarity.UNCOMMON, mage.cards.n.NaturesChosen.class)); cards.add(new SetCardInfo("Nature's Wrath", 82, Rarity.RARE, mage.cards.n.NaturesWrath.class)); @@ -171,6 +172,8 @@ public class Alliances extends ExpansionSet { cards.add(new SetCardInfo("Varchild's Crusader", 120, Rarity.COMMON, mage.cards.v.VarchildsCrusader.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Varchild's Crusader", 121, Rarity.COMMON, mage.cards.v.VarchildsCrusader.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Varchild's War-Riders", 122, Rarity.RARE, mage.cards.v.VarchildsWarRiders.class)); + cards.add(new SetCardInfo("Veteran's Voice", 123, Rarity.COMMON, mage.cards.v.VeteransVoice.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Veteran's Voice", 124, Rarity.COMMON, mage.cards.v.VeteransVoice.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Viscerid Armor", 60, Rarity.COMMON, mage.cards.v.VisceridArmor.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Viscerid Armor", 61, Rarity.COMMON, mage.cards.v.VisceridArmor.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Viscerid Drone", 62, Rarity.UNCOMMON, mage.cards.v.VisceridDrone.class)); diff --git a/Mage.Sets/src/mage/sets/Chronicles.java b/Mage.Sets/src/mage/sets/Chronicles.java index add6a9345f..fac22fcc4f 100644 --- a/Mage.Sets/src/mage/sets/Chronicles.java +++ b/Mage.Sets/src/mage/sets/Chronicles.java @@ -57,7 +57,7 @@ public class Chronicles extends ExpansionSet { cards.add(new SetCardInfo("Active Volcano", 43, Rarity.COMMON, mage.cards.a.ActiveVolcano.class)); cards.add(new SetCardInfo("Akron Legionnaire", 58, Rarity.RARE, mage.cards.a.AkronLegionnaire.class)); cards.add(new SetCardInfo("Aladdin", 44, Rarity.RARE, mage.cards.a.Aladdin.class)); - cards.add(new SetCardInfo("Angelic Voices", 59, Rarity.RARE, mage.cards.a.AngelicVoices.class)); + cards.add(new SetCardInfo("Angelic Voices", 59, Rarity.RARE, mage.cards.a.AngelicVoices.class)); cards.add(new SetCardInfo("Arcades Sabboth", 106, Rarity.RARE, mage.cards.a.ArcadesSabboth.class)); cards.add(new SetCardInfo("Arena of the Ancients", 71, Rarity.RARE, mage.cards.a.ArenaOfTheAncients.class)); cards.add(new SetCardInfo("Argothian Pixies", 29, Rarity.COMMON, mage.cards.a.ArgothianPixies.class)); @@ -98,9 +98,10 @@ public class Chronicles extends ExpansionSet { cards.add(new SetCardInfo("Hasran Ogress", 6, Rarity.COMMON, mage.cards.h.HasranOgress.class)); cards.add(new SetCardInfo("Hell's Caretaker", 7, Rarity.RARE, mage.cards.h.HellsCaretaker.class)); cards.add(new SetCardInfo("Horn of Deafening", 80, Rarity.RARE, mage.cards.h.HornOfDeafening.class)); - cards.add(new SetCardInfo("Indestructible Aura", 63, Rarity.COMMON, mage.cards.i.IndestructibleAura.class)); + cards.add(new SetCardInfo("Indestructible Aura", 63, Rarity.COMMON, mage.cards.i.IndestructibleAura.class)); cards.add(new SetCardInfo("Ivory Guardians", 64, Rarity.UNCOMMON, mage.cards.i.IvoryGuardians.class)); cards.add(new SetCardInfo("Jalum Tome", 81, Rarity.RARE, mage.cards.j.JalumTome.class)); + cards.add(new SetCardInfo("Johan", 112, Rarity.RARE, mage.cards.j.Johan.class)); cards.add(new SetCardInfo("Juxtapose", 22, Rarity.RARE, mage.cards.j.Juxtapose.class)); cards.add(new SetCardInfo("Keepers of the Faith", 65, Rarity.COMMON, mage.cards.k.KeepersOfTheFaith.class)); cards.add(new SetCardInfo("Kei Takahashi", 113, Rarity.UNCOMMON, mage.cards.k.KeiTakahashi.class)); @@ -112,6 +113,7 @@ public class Chronicles extends ExpansionSet { cards.add(new SetCardInfo("Nicol Bolas", 116, Rarity.RARE, mage.cards.n.NicolBolas.class)); cards.add(new SetCardInfo("Obelisk of Undoing", 84, Rarity.RARE, mage.cards.o.ObeliskOfUndoing.class)); cards.add(new SetCardInfo("Palladia-Mors", 117, Rarity.RARE, mage.cards.p.PalladiaMors.class)); + cards.add(new SetCardInfo("Petra Sphinx", 66, Rarity.RARE, mage.cards.p.PetraSphinx.class)); cards.add(new SetCardInfo("Rabid Wombat", 39, Rarity.UNCOMMON, mage.cards.r.RabidWombat.class)); cards.add(new SetCardInfo("Rakalite", 85, Rarity.RARE, mage.cards.r.Rakalite.class)); cards.add(new SetCardInfo("Recall", 24, Rarity.UNCOMMON, mage.cards.r.Recall.class)); @@ -127,6 +129,7 @@ public class Chronicles extends ExpansionSet { cards.add(new SetCardInfo("Sivitri Scarzam", 119, Rarity.UNCOMMON, mage.cards.s.SivitriScarzam.class)); cards.add(new SetCardInfo("Sol'kanar the Swamp King", 120, Rarity.RARE, mage.cards.s.SolkanarTheSwampKing.class)); cards.add(new SetCardInfo("Storm Seeker", 42, Rarity.UNCOMMON, mage.cards.s.StormSeeker.class)); + cards.add(new SetCardInfo("Teleport", 26, Rarity.RARE, mage.cards.t.Teleport.class)); cards.add(new SetCardInfo("The Wretched", 11, Rarity.RARE, mage.cards.t.TheWretched.class)); cards.add(new SetCardInfo("Tobias Andrion", 122, Rarity.UNCOMMON, mage.cards.t.TobiasAndrion.class)); cards.add(new SetCardInfo("Tormod's Crypt", 89, Rarity.COMMON, mage.cards.t.TormodsCrypt.class)); diff --git a/Mage.Sets/src/mage/sets/ConspiracyTakeTheCrown.java b/Mage.Sets/src/mage/sets/ConspiracyTakeTheCrown.java index 0cda5865fd..630eca1b6c 100644 --- a/Mage.Sets/src/mage/sets/ConspiracyTakeTheCrown.java +++ b/Mage.Sets/src/mage/sets/ConspiracyTakeTheCrown.java @@ -86,6 +86,7 @@ public class ConspiracyTakeTheCrown extends ExpansionSet { cards.add(new SetCardInfo("Coveted Peacock", 29, Rarity.UNCOMMON, mage.cards.c.CovetedPeacock.class)); cards.add(new SetCardInfo("Crown-Hunter Hireling", 50, Rarity.COMMON, mage.cards.c.CrownHunterHireling.class)); cards.add(new SetCardInfo("Custodi Lich", 41, Rarity.RARE, mage.cards.c.CustodiLich.class)); + cards.add(new SetCardInfo("Custodi Soulcaller", 15, Rarity.UNCOMMON, mage.cards.c.CustodiSoulcaller.class)); cards.add(new SetCardInfo("Daretti, Ingenious Iconoclast", 74, Rarity.MYTHIC, mage.cards.d.DarettiIngeniousIconoclast.class)); cards.add(new SetCardInfo("Deadly Designs", 42, Rarity.UNCOMMON, mage.cards.d.DeadlyDesigns.class)); cards.add(new SetCardInfo("Death Wind", 131, Rarity.COMMON, mage.cards.d.DeathWind.class)); diff --git a/Mage.Sets/src/mage/sets/EighthEdition.java b/Mage.Sets/src/mage/sets/EighthEdition.java index 1d6c7f307a..e9d4a733f6 100644 --- a/Mage.Sets/src/mage/sets/EighthEdition.java +++ b/Mage.Sets/src/mage/sets/EighthEdition.java @@ -350,6 +350,7 @@ public class EighthEdition extends ExpansionSet { cards.add(new SetCardInfo("Venerable Monk", 55, Rarity.COMMON, mage.cards.v.VenerableMonk.class)); cards.add(new SetCardInfo("Verduran Enchantress", 285, Rarity.RARE, mage.cards.v.VerduranEnchantress.class)); cards.add(new SetCardInfo("Vernal Bloom", 286, Rarity.RARE, mage.cards.v.VernalBloom.class)); + cards.add(new SetCardInfo("Vexing Arcanix", 319, Rarity.RARE, mage.cards.v.VexingArcanix.class)); cards.add(new SetCardInfo("Viashino Sandstalker", 230, Rarity.UNCOMMON, mage.cards.v.ViashinoSandstalker.class)); cards.add(new SetCardInfo("Vicious Hunger", 171, Rarity.COMMON, mage.cards.v.ViciousHunger.class)); cards.add(new SetCardInfo("Vine Trellis", 287, Rarity.COMMON, mage.cards.v.VineTrellis.class)); diff --git a/Mage.Sets/src/mage/sets/FallenEmpires.java b/Mage.Sets/src/mage/sets/FallenEmpires.java index aa73229d50..bbfed14790 100644 --- a/Mage.Sets/src/mage/sets/FallenEmpires.java +++ b/Mage.Sets/src/mage/sets/FallenEmpires.java @@ -219,6 +219,9 @@ public class FallenEmpires extends ExpansionSet { cards.add(new SetCardInfo("Seasinger", 52, Rarity.UNCOMMON, mage.cards.s.Seasinger.class)); cards.add(new SetCardInfo("Soul Exchange", 28, Rarity.UNCOMMON, mage.cards.s.SoulExchange.class)); cards.add(new SetCardInfo("Spirit Shield", 175, Rarity.RARE, mage.cards.s.SpiritShield.class)); + cards.add(new SetCardInfo("Spore Cloud", 83, Rarity.COMMON, mage.cards.s.SporeCloud.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Spore Cloud", 84, Rarity.COMMON, mage.cards.s.SporeCloud.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Spore Cloud", 85, Rarity.COMMON, mage.cards.s.SporeCloud.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Spore Flower", 86, Rarity.UNCOMMON, mage.cards.s.SporeFlower.class)); cards.add(new SetCardInfo("Svyelunite Priest", 53, Rarity.UNCOMMON, mage.cards.s.SvyelunitePriest.class)); cards.add(new SetCardInfo("Svyelunite Temple", 187, Rarity.UNCOMMON, mage.cards.s.SvyeluniteTemple.class)); @@ -237,6 +240,7 @@ public class FallenEmpires extends ExpansionSet { cards.add(new SetCardInfo("Thrull Retainer", 30, Rarity.UNCOMMON, mage.cards.t.ThrullRetainer.class)); cards.add(new SetCardInfo("Thrull Wizard", 31, Rarity.UNCOMMON, mage.cards.t.ThrullWizard.class)); cards.add(new SetCardInfo("Tidal Influence", 57, Rarity.UNCOMMON, mage.cards.t.TidalInfluence.class)); + cards.add(new SetCardInfo("Tourach's Gate", 33, Rarity.RARE, mage.cards.t.TourachsGate.class)); cards.add(new SetCardInfo("Vodalian Knights", 58, Rarity.RARE, mage.cards.v.VodalianKnights.class)); cards.add(new SetCardInfo("Vodalian Mage", 59, Rarity.COMMON, VodalianMage.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Vodalian Mage", 60, Rarity.COMMON, VodalianMage.class, NON_FULL_USE_VARIOUS)); diff --git a/Mage.Sets/src/mage/sets/FifthEdition.java b/Mage.Sets/src/mage/sets/FifthEdition.java index 58f3d4975c..0ba5e924b3 100644 --- a/Mage.Sets/src/mage/sets/FifthEdition.java +++ b/Mage.Sets/src/mage/sets/FifthEdition.java @@ -217,7 +217,7 @@ public class FifthEdition extends ExpansionSet { cards.add(new SetCardInfo("Icatian Scout", 313, Rarity.COMMON, IcatianScout.class)); cards.add(new SetCardInfo("Icatian Store", 423, Rarity.RARE, mage.cards.i.IcatianStore.class)); cards.add(new SetCardInfo("Icatian Town", 314, Rarity.RARE, mage.cards.i.IcatianTown.class)); - cards.add(new SetCardInfo("Ice Floe", 424, Rarity.UNCOMMON, mage.cards.i.IceFloe.class)); + cards.add(new SetCardInfo("Ice Floe", 424, Rarity.UNCOMMON, mage.cards.i.IceFloe.class)); cards.add(new SetCardInfo("Imposing Visage", 241, Rarity.COMMON, mage.cards.i.ImposingVisage.class)); cards.add(new SetCardInfo("Incinerate", 242, Rarity.COMMON, mage.cards.i.Incinerate.class)); cards.add(new SetCardInfo("Inferno", 243, Rarity.RARE, mage.cards.i.Inferno.class)); @@ -253,7 +253,7 @@ public class FifthEdition extends ExpansionSet { cards.add(new SetCardInfo("Knight of Stromgald", 33, Rarity.UNCOMMON, mage.cards.k.KnightOfStromgald.class)); cards.add(new SetCardInfo("Krovikan Fetish", 34, Rarity.COMMON, mage.cards.k.KrovikanFetish.class)); cards.add(new SetCardInfo("Krovikan Sorcerer", 96, Rarity.COMMON, mage.cards.k.KrovikanSorcerer.class)); - cards.add(new SetCardInfo("Labyrinth Minotaur", 97, Rarity.COMMON, mage.cards.l.LabyrinthMinotaur.class)); + cards.add(new SetCardInfo("Labyrinth Minotaur", 97, Rarity.COMMON, mage.cards.l.LabyrinthMinotaur.class)); cards.add(new SetCardInfo("Leshrac's Rite", 35, Rarity.UNCOMMON, mage.cards.l.LeshracsRite.class)); cards.add(new SetCardInfo("Leviathan", 98, Rarity.RARE, mage.cards.l.Leviathan.class)); cards.add(new SetCardInfo("Ley Druid", 170, Rarity.COMMON, mage.cards.l.LeyDruid.class)); @@ -301,7 +301,7 @@ public class FifthEdition extends ExpansionSet { cards.add(new SetCardInfo("Orcish Artillery", 253, Rarity.UNCOMMON, mage.cards.o.OrcishArtillery.class)); cards.add(new SetCardInfo("Orcish Captain", 254, Rarity.UNCOMMON, mage.cards.o.OrcishCaptain.class)); cards.add(new SetCardInfo("Orcish Oriflamme", 257, Rarity.UNCOMMON, mage.cards.o.OrcishOriflamme.class)); - cards.add(new SetCardInfo("Orcish Squatters", 258, Rarity.RARE, mage.cards.o.OrcishSquatters.class)); + cards.add(new SetCardInfo("Orcish Squatters", 258, Rarity.RARE, mage.cards.o.OrcishSquatters.class)); cards.add(new SetCardInfo("Order of the Sacred Torch", 324, Rarity.RARE, mage.cards.o.OrderOfTheSacredTorch.class)); cards.add(new SetCardInfo("Order of the White Shield", 325, Rarity.UNCOMMON, mage.cards.o.OrderOfTheWhiteShield.class)); cards.add(new SetCardInfo("Orgg", 259, Rarity.RARE, mage.cards.o.Orgg.class)); @@ -328,6 +328,7 @@ public class FifthEdition extends ExpansionSet { cards.add(new SetCardInfo("Pradesh Gypsies", 179, Rarity.COMMON, mage.cards.p.PradeshGypsies.class)); cards.add(new SetCardInfo("Primal Clay", 395, Rarity.RARE, mage.cards.p.PrimalClay.class)); cards.add(new SetCardInfo("Primal Order", 180, Rarity.RARE, mage.cards.p.PrimalOrder.class)); + cards.add(new SetCardInfo("Prismatic Ward", 329, Rarity.COMMON, mage.cards.p.PrismaticWard.class)); cards.add(new SetCardInfo("Prodigal Sorcerer", 112, Rarity.COMMON, mage.cards.p.ProdigalSorcerer.class)); cards.add(new SetCardInfo("Psychic Venom", 113, Rarity.COMMON, mage.cards.p.PsychicVenom.class)); cards.add(new SetCardInfo("Pyroblast", 262, Rarity.UNCOMMON, mage.cards.p.Pyroblast.class)); @@ -401,6 +402,7 @@ public class FifthEdition extends ExpansionSet { cards.add(new SetCardInfo("Throne of Bone", 403, Rarity.UNCOMMON, mage.cards.t.ThroneOfBone.class)); cards.add(new SetCardInfo("Thrull Retainer", 60, Rarity.UNCOMMON, mage.cards.t.ThrullRetainer.class)); cards.add(new SetCardInfo("Time Bomb", 404, Rarity.RARE, mage.cards.t.TimeBomb.class)); + cards.add(new SetCardInfo("Time Elemental", 129, Rarity.RARE, mage.cards.t.TimeElemental.class)); cards.add(new SetCardInfo("Titania's Song", 194, Rarity.RARE, mage.cards.t.TitaniasSong.class)); cards.add(new SetCardInfo("Torture", 61, Rarity.COMMON, Torture.class)); cards.add(new SetCardInfo("Touch of Death", 62, Rarity.COMMON, mage.cards.t.TouchOfDeath.class)); @@ -438,7 +440,7 @@ public class FifthEdition extends ExpansionSet { cards.add(new SetCardInfo("Wild Growth", 204, Rarity.COMMON, mage.cards.w.WildGrowth.class)); cards.add(new SetCardInfo("Winds of Change", 275, Rarity.RARE, mage.cards.w.WindsOfChange.class)); cards.add(new SetCardInfo("Wind Spirit", 136, Rarity.UNCOMMON, mage.cards.w.WindSpirit.class)); - cards.add(new SetCardInfo("Winter Blast", 205, Rarity.UNCOMMON, mage.cards.w.WinterBlast.class)); + cards.add(new SetCardInfo("Winter Blast", 205, Rarity.UNCOMMON, mage.cards.w.WinterBlast.class)); cards.add(new SetCardInfo("Winter Orb", 408, Rarity.RARE, mage.cards.w.WinterOrb.class)); cards.add(new SetCardInfo("Wolverine Pack", 206, Rarity.UNCOMMON, mage.cards.w.WolverinePack.class)); cards.add(new SetCardInfo("Wooden Sphere", 409, Rarity.UNCOMMON, mage.cards.w.WoodenSphere.class)); diff --git a/Mage.Sets/src/mage/sets/FourthEdition.java b/Mage.Sets/src/mage/sets/FourthEdition.java index f44d101070..263ec33b0d 100644 --- a/Mage.Sets/src/mage/sets/FourthEdition.java +++ b/Mage.Sets/src/mage/sets/FourthEdition.java @@ -359,6 +359,7 @@ public class FourthEdition extends ExpansionSet { cards.add(new SetCardInfo("Thicket Basilisk", 158, Rarity.UNCOMMON, mage.cards.t.ThicketBasilisk.class)); cards.add(new SetCardInfo("Thoughtlace", 107, Rarity.RARE, mage.cards.t.Thoughtlace.class)); cards.add(new SetCardInfo("Throne of Bone", 371, Rarity.UNCOMMON, mage.cards.t.ThroneOfBone.class)); + cards.add(new SetCardInfo("Time Elemental", 108, Rarity.RARE, mage.cards.t.TimeElemental.class)); cards.add(new SetCardInfo("Titania's Song", 160, Rarity.RARE, mage.cards.t.TitaniasSong.class)); cards.add(new SetCardInfo("Tranquility", 161, Rarity.COMMON, mage.cards.t.Tranquility.class)); cards.add(new SetCardInfo("Triskelion", 372, Rarity.RARE, mage.cards.t.Triskelion.class)); diff --git a/Mage.Sets/src/mage/sets/IceAge.java b/Mage.Sets/src/mage/sets/IceAge.java index ae41e2d5b8..277e614b3b 100644 --- a/Mage.Sets/src/mage/sets/IceAge.java +++ b/Mage.Sets/src/mage/sets/IceAge.java @@ -167,7 +167,7 @@ public class IceAge extends ExpansionSet { cards.add(new SetCardInfo("Hyalopterous Lemure", 21, Rarity.UNCOMMON, mage.cards.h.HyalopterousLemure.class)); cards.add(new SetCardInfo("Hydroblast", 72, Rarity.COMMON, mage.cards.h.Hydroblast.class)); cards.add(new SetCardInfo("Hymn of Rebirth", 373, Rarity.UNCOMMON, mage.cards.h.HymnOfRebirth.class)); - cards.add(new SetCardInfo("Ice Floe", 333, Rarity.UNCOMMON, mage.cards.i.IceFloe.class)); + cards.add(new SetCardInfo("Ice Floe", 333, Rarity.UNCOMMON, mage.cards.i.IceFloe.class)); cards.add(new SetCardInfo("Iceberg", 73, Rarity.UNCOMMON, mage.cards.i.Iceberg.class)); cards.add(new SetCardInfo("Icequake", 22, Rarity.UNCOMMON, mage.cards.i.Icequake.class)); cards.add(new SetCardInfo("Icy Manipulator", 297, Rarity.UNCOMMON, mage.cards.i.IcyManipulator.class)); @@ -212,6 +212,8 @@ public class IceAge extends ExpansionSet { cards.add(new SetCardInfo("Magus of the Unseen", 82, Rarity.RARE, mage.cards.m.MagusOfTheUnseen.class)); cards.add(new SetCardInfo("Malachite Talisman", 303, Rarity.UNCOMMON, mage.cards.m.MalachiteTalisman.class)); cards.add(new SetCardInfo("Marton Stromgald", 199, Rarity.RARE, mage.cards.m.MartonStromgald.class)); + cards.add(new SetCardInfo("Melee", 200, Rarity.UNCOMMON, mage.cards.m.Melee.class)); + cards.add(new SetCardInfo("Melting", 201, Rarity.UNCOMMON, mage.cards.m.Melting.class)); cards.add(new SetCardInfo("Merieke Ri Berit", 375, Rarity.RARE, mage.cards.m.MeriekeRiBerit.class)); cards.add(new SetCardInfo("Mesmeric Trance", 83, Rarity.RARE, mage.cards.m.MesmericTrance.class)); cards.add(new SetCardInfo("Meteor Shower", 202, Rarity.COMMON, mage.cards.m.MeteorShower.class)); @@ -252,6 +254,7 @@ public class IceAge extends ExpansionSet { cards.add(new SetCardInfo("Portent", 90, Rarity.COMMON, mage.cards.p.Portent.class)); cards.add(new SetCardInfo("Power Sink", 91, Rarity.COMMON, mage.cards.p.PowerSink.class)); cards.add(new SetCardInfo("Pox", 46, Rarity.RARE, mage.cards.p.Pox.class)); + cards.add(new SetCardInfo("Prismatic Ward", 271, Rarity.COMMON, mage.cards.p.PrismaticWard.class)); cards.add(new SetCardInfo("Pygmy Allosaurus", 145, Rarity.RARE, mage.cards.p.PygmyAllosaurus.class)); cards.add(new SetCardInfo("Pyknite", 146, Rarity.COMMON, mage.cards.p.Pyknite.class)); cards.add(new SetCardInfo("Pyroblast", 213, Rarity.COMMON, mage.cards.p.Pyroblast.class)); @@ -273,7 +276,7 @@ public class IceAge extends ExpansionSet { cards.add(new SetCardInfo("Shambling Strider", 151, Rarity.COMMON, mage.cards.s.ShamblingStrider.class)); cards.add(new SetCardInfo("Shatter", 216, Rarity.COMMON, mage.cards.s.Shatter.class)); cards.add(new SetCardInfo("Shield of the Ages", 310, Rarity.UNCOMMON, mage.cards.s.ShieldOfTheAges.class)); - cards.add(new SetCardInfo("Shyft", 96, Rarity.RARE, mage.cards.s.Shyft.class)); + cards.add(new SetCardInfo("Shyft", 96, Rarity.RARE, mage.cards.s.Shyft.class)); cards.add(new SetCardInfo("Sibilant Spirit", 97, Rarity.RARE, mage.cards.s.SibilantSpirit.class)); cards.add(new SetCardInfo("Silver Erne", 98, Rarity.UNCOMMON, mage.cards.s.SilverErne.class)); cards.add(new SetCardInfo("Skeleton Ship", 379, Rarity.RARE, mage.cards.s.SkeletonShip.class)); @@ -322,6 +325,7 @@ public class IceAge extends ExpansionSet { cards.add(new SetCardInfo("Urza's Bauble", 318, Rarity.UNCOMMON, mage.cards.u.UrzasBauble.class)); cards.add(new SetCardInfo("Veldt", 358, Rarity.RARE, mage.cards.v.Veldt.class)); cards.add(new SetCardInfo("Vertigo", 222, Rarity.UNCOMMON, mage.cards.v.Vertigo.class)); + cards.add(new SetCardInfo("Vexing Arcanix", 319, Rarity.RARE, mage.cards.v.VexingArcanix.class)); cards.add(new SetCardInfo("Vibrating Sphere", 320, Rarity.RARE, mage.cards.v.VibratingSphere.class)); cards.add(new SetCardInfo("Walking Wall", 321, Rarity.UNCOMMON, mage.cards.w.WalkingWall.class)); cards.add(new SetCardInfo("Wall of Lava", 223, Rarity.UNCOMMON, mage.cards.w.WallOfLava.class)); diff --git a/Mage.Sets/src/mage/sets/Judgment.java b/Mage.Sets/src/mage/sets/Judgment.java index 4f46a7b417..9007e49c9e 100644 --- a/Mage.Sets/src/mage/sets/Judgment.java +++ b/Mage.Sets/src/mage/sets/Judgment.java @@ -100,6 +100,7 @@ public class Judgment extends ExpansionSet { cards.add(new SetCardInfo("Flash of Insight", 40, Rarity.UNCOMMON, mage.cards.f.FlashOfInsight.class)); cards.add(new SetCardInfo("Fledgling Dragon", 90, Rarity.RARE, mage.cards.f.FledglingDragon.class)); cards.add(new SetCardInfo("Folk Medicine", 115, Rarity.COMMON, mage.cards.f.FolkMedicine.class)); + cards.add(new SetCardInfo("Forcemage Advocate", 116, Rarity.UNCOMMON, mage.cards.f.ForcemageAdvocate.class)); cards.add(new SetCardInfo("Funeral Pyre", 10, Rarity.COMMON, mage.cards.f.FuneralPyre.class)); cards.add(new SetCardInfo("Genesis", 117, Rarity.RARE, mage.cards.g.Genesis.class)); cards.add(new SetCardInfo("Giant Warthog", 118, Rarity.COMMON, mage.cards.g.GiantWarthog.class)); @@ -118,7 +119,7 @@ public class Judgment extends ExpansionSet { cards.add(new SetCardInfo("Krosan Reclamation", 122, Rarity.UNCOMMON, mage.cards.k.KrosanReclamation.class)); cards.add(new SetCardInfo("Krosan Verge", 141, Rarity.UNCOMMON, mage.cards.k.KrosanVerge.class)); cards.add(new SetCardInfo("Krosan Wayfarer", 123, Rarity.COMMON, mage.cards.k.KrosanWayfarer.class)); - cards.add(new SetCardInfo("Laquatus's Disdain", 44, Rarity.UNCOMMON, mage.cards.l.LaquatussDisdain.class)); + cards.add(new SetCardInfo("Laquatus's Disdain", 44, Rarity.UNCOMMON, mage.cards.l.LaquatussDisdain.class)); cards.add(new SetCardInfo("Lava Dart", 94, Rarity.COMMON, mage.cards.l.LavaDart.class)); cards.add(new SetCardInfo("Lead Astray", 14, Rarity.COMMON, mage.cards.l.LeadAstray.class)); cards.add(new SetCardInfo("Liberated Dwarf", 95, Rarity.COMMON, mage.cards.l.LiberatedDwarf.class)); @@ -147,6 +148,7 @@ public class Judgment extends ExpansionSet { cards.add(new SetCardInfo("Riftstone Portal", 143, Rarity.UNCOMMON, mage.cards.r.RiftstonePortal.class)); cards.add(new SetCardInfo("Scalpelexis", 50, Rarity.RARE, mage.cards.s.Scalpelexis.class)); cards.add(new SetCardInfo("Seedtime", 130, Rarity.RARE, mage.cards.s.Seedtime.class)); + cards.add(new SetCardInfo("Shieldmage Advocate", 22, Rarity.COMMON, mage.cards.s.ShieldmageAdvocate.class)); cards.add(new SetCardInfo("Silver Seraph", 23, Rarity.RARE, mage.cards.s.SilverSeraph.class)); cards.add(new SetCardInfo("Solitary Confinement", 24, Rarity.RARE, mage.cards.s.SolitaryConfinement.class)); cards.add(new SetCardInfo("Soulcatchers' Aerie", 25, Rarity.UNCOMMON, mage.cards.s.SoulcatchersAerie.class)); @@ -164,8 +166,8 @@ public class Judgment extends ExpansionSet { cards.add(new SetCardInfo("Test of Endurance", 29, Rarity.RARE, mage.cards.t.TestOfEndurance.class)); cards.add(new SetCardInfo("Thriss, Nantuko Primus", 134, Rarity.RARE, mage.cards.t.ThrissNantukoPrimus.class)); cards.add(new SetCardInfo("Toxic Stench", 74, Rarity.COMMON, mage.cards.t.ToxicStench.class)); - cards.add(new SetCardInfo("Treacherous Vampire", 75, Rarity.UNCOMMON, mage.cards.t.TreacherousVampire.class)); - cards.add(new SetCardInfo("Treacherous Werewolf", 76, Rarity.COMMON, mage.cards.t.TreacherousWerewolf.class)); + cards.add(new SetCardInfo("Treacherous Vampire", 75, Rarity.UNCOMMON, mage.cards.t.TreacherousVampire.class)); + cards.add(new SetCardInfo("Treacherous Werewolf", 76, Rarity.COMMON, mage.cards.t.TreacherousWerewolf.class)); cards.add(new SetCardInfo("Tunneler Wurm", 135, Rarity.UNCOMMON, mage.cards.t.TunnelerWurm.class)); cards.add(new SetCardInfo("Unquestioned Authority", 31, Rarity.UNCOMMON, mage.cards.u.UnquestionedAuthority.class)); cards.add(new SetCardInfo("Valor", 32, Rarity.UNCOMMON, mage.cards.v.Valor.class)); diff --git a/Mage.Sets/src/mage/sets/Legends.java b/Mage.Sets/src/mage/sets/Legends.java index 62385b2f40..5b74674e2a 100644 --- a/Mage.Sets/src/mage/sets/Legends.java +++ b/Mage.Sets/src/mage/sets/Legends.java @@ -101,13 +101,13 @@ public class Legends extends ExpansionSet { cards.add(new SetCardInfo("D'Avenant Archer", 176, Rarity.COMMON, mage.cards.d.DAvenantArcher.class)); cards.add(new SetCardInfo("Demonic Torment", 9, Rarity.UNCOMMON, mage.cards.d.DemonicTorment.class)); cards.add(new SetCardInfo("Devouring Deep", 50, Rarity.COMMON, mage.cards.d.DevouringDeep.class)); - cards.add(new SetCardInfo("Disharmony", 140, Rarity.RARE, mage.cards.d.Disharmony.class)); + cards.add(new SetCardInfo("Disharmony", 140, Rarity.RARE, mage.cards.d.Disharmony.class)); cards.add(new SetCardInfo("Divine Intervention", 177, Rarity.RARE, mage.cards.d.DivineIntervention.class)); cards.add(new SetCardInfo("Divine Offering", 178, Rarity.COMMON, mage.cards.d.DivineOffering.class)); cards.add(new SetCardInfo("Divine Transformation", 179, Rarity.RARE, mage.cards.d.DivineTransformation.class)); cards.add(new SetCardInfo("Durkwood Boars", 96, Rarity.COMMON, mage.cards.d.DurkwoodBoars.class)); cards.add(new SetCardInfo("Dwarven Song", 141, Rarity.UNCOMMON, mage.cards.d.DwarvenSong.class)); - cards.add(new SetCardInfo("Elder Land Wurm", 180, Rarity.RARE, mage.cards.e.ElderLandWurm.class)); + cards.add(new SetCardInfo("Elder Land Wurm", 180, Rarity.RARE, mage.cards.e.ElderLandWurm.class)); cards.add(new SetCardInfo("Elven Riders", 97, Rarity.RARE, mage.cards.e.ElvenRiders.class)); cards.add(new SetCardInfo("Emerald Dragonfly", 98, Rarity.COMMON, mage.cards.e.EmeraldDragonfly.class)); cards.add(new SetCardInfo("Energy Tap", 54, Rarity.COMMON, mage.cards.e.EnergyTap.class)); @@ -119,20 +119,20 @@ public class Legends extends ExpansionSet { cards.add(new SetCardInfo("Fire Sprites", 100, Rarity.COMMON, mage.cards.f.FireSprites.class)); cards.add(new SetCardInfo("Flash Counter", 56, Rarity.COMMON, mage.cards.f.FlashCounter.class)); cards.add(new SetCardInfo("Flash Flood", 57, Rarity.COMMON, mage.cards.f.FlashFlood.class)); - cards.add(new SetCardInfo("Floral Spuzzem", 101, Rarity.UNCOMMON, mage.cards.f.FloralSpuzzem.class)); + cards.add(new SetCardInfo("Floral Spuzzem", 101, Rarity.UNCOMMON, mage.cards.f.FloralSpuzzem.class)); cards.add(new SetCardInfo("Force Spike", 58, Rarity.COMMON, mage.cards.f.ForceSpike.class)); cards.add(new SetCardInfo("Frost Giant", 146, Rarity.UNCOMMON, mage.cards.f.FrostGiant.class)); cards.add(new SetCardInfo("Gaseous Form", 59, Rarity.COMMON, mage.cards.g.GaseousForm.class)); cards.add(new SetCardInfo("Ghosts of the Damned", 12, Rarity.COMMON, mage.cards.g.GhostsOfTheDamned.class)); cards.add(new SetCardInfo("Giant Strength", 147, Rarity.COMMON, mage.cards.g.GiantStrength.class)); - cards.add(new SetCardInfo("Giant Turtle", 102, Rarity.COMMON, mage.cards.g.GiantTurtle.class)); + cards.add(new SetCardInfo("Giant Turtle", 102, Rarity.COMMON, mage.cards.g.GiantTurtle.class)); cards.add(new SetCardInfo("Gravity Sphere", 149, Rarity.RARE, mage.cards.g.GravitySphere.class)); cards.add(new SetCardInfo("Great Defender", 185, Rarity.UNCOMMON, mage.cards.g.GreatDefender.class)); cards.add(new SetCardInfo("Greater Realm of Preservation", 187, Rarity.UNCOMMON, mage.cards.g.GreaterRealmOfPreservation.class)); cards.add(new SetCardInfo("Greed", 15, Rarity.RARE, mage.cards.g.Greed.class)); cards.add(new SetCardInfo("Green Mana Battery", 223, Rarity.UNCOMMON, mage.cards.g.GreenManaBattery.class)); cards.add(new SetCardInfo("Gwendlyn Di Corci", 268, Rarity.RARE, mage.cards.g.GwendlynDiCorci.class)); - cards.add(new SetCardInfo("Hammerheim", 247, Rarity.UNCOMMON, mage.cards.h.Hammerheim.class)); + cards.add(new SetCardInfo("Hammerheim", 247, Rarity.UNCOMMON, mage.cards.h.Hammerheim.class)); cards.add(new SetCardInfo("Hazezon Tamar", 270, Rarity.RARE, mage.cards.h.HazezonTamar.class)); cards.add(new SetCardInfo("Headless Horseman", 16, Rarity.COMMON, mage.cards.h.HeadlessHorseman.class)); cards.add(new SetCardInfo("Heaven's Gate", 188, Rarity.UNCOMMON, mage.cards.h.HeavensGate.class)); @@ -147,13 +147,14 @@ public class Legends extends ExpansionSet { cards.add(new SetCardInfo("Hyperion Blacksmith", 150, Rarity.UNCOMMON, mage.cards.h.HyperionBlacksmith.class)); cards.add(new SetCardInfo("Immolation", 151, Rarity.COMMON, mage.cards.i.Immolation.class)); cards.add(new SetCardInfo("In the Eye of Chaos", 61, Rarity.RARE, mage.cards.i.InTheEyeOfChaos.class)); - cards.add(new SetCardInfo("Indestructible Aura", 190, Rarity.COMMON, mage.cards.i.IndestructibleAura.class)); + cards.add(new SetCardInfo("Indestructible Aura", 190, Rarity.COMMON, mage.cards.i.IndestructibleAura.class)); cards.add(new SetCardInfo("Invoke Prejudice", 62, Rarity.RARE, mage.cards.i.InvokePrejudice.class)); cards.add(new SetCardInfo("Ivory Guardians", 192, Rarity.UNCOMMON, mage.cards.i.IvoryGuardians.class)); cards.add(new SetCardInfo("Jacques le Vert", 272, Rarity.RARE, mage.cards.j.JacquesLeVert.class)); cards.add(new SetCardInfo("Jasmine Boreal", 273, Rarity.UNCOMMON, mage.cards.j.JasmineBoreal.class)); cards.add(new SetCardInfo("Jedit Ojanen", 274, Rarity.UNCOMMON, mage.cards.j.JeditOjanen.class)); cards.add(new SetCardInfo("Jerrard of the Closed Fist", 275, Rarity.UNCOMMON, mage.cards.j.JerrardOfTheClosedFist.class)); + cards.add(new SetCardInfo("Johan", 276, Rarity.RARE, mage.cards.j.Johan.class)); cards.add(new SetCardInfo("Juxtapose", 63, Rarity.RARE, mage.cards.j.Juxtapose.class)); cards.add(new SetCardInfo("Karakas", 248, Rarity.UNCOMMON, mage.cards.k.Karakas.class)); cards.add(new SetCardInfo("Kasimir the Lone Wolf", 277, Rarity.UNCOMMON, mage.cards.k.KasimirTheLoneWolf.class)); @@ -186,11 +187,13 @@ public class Legends extends ExpansionSet { cards.add(new SetCardInfo("Mountain Yeti", 156, Rarity.UNCOMMON, mage.cards.m.MountainYeti.class)); cards.add(new SetCardInfo("Nether Void", 27, Rarity.RARE, mage.cards.n.NetherVoid.class)); cards.add(new SetCardInfo("Nicol Bolas", 286, Rarity.RARE, mage.cards.n.NicolBolas.class)); + cards.add(new SetCardInfo("Nova Pentacle", 234, Rarity.RARE, mage.cards.n.NovaPentacle.class)); cards.add(new SetCardInfo("Osai Vultures", 198, Rarity.COMMON, mage.cards.o.OsaiVultures.class)); cards.add(new SetCardInfo("Palladia-Mors", 287, Rarity.RARE, mage.cards.p.PalladiaMors.class)); cards.add(new SetCardInfo("Part Water", 66, Rarity.UNCOMMON, mage.cards.p.PartWater.class)); cards.add(new SetCardInfo("Pavel Maliki", 288, Rarity.UNCOMMON, mage.cards.p.PavelMaliki.class)); cards.add(new SetCardInfo("Pendelhaven", 250, Rarity.UNCOMMON, mage.cards.p.Pendelhaven.class)); + cards.add(new SetCardInfo("Petra Sphinx", 199, Rarity.RARE, mage.cards.p.PetraSphinx.class)); cards.add(new SetCardInfo("Pit Scorpion", 28, Rarity.COMMON, mage.cards.p.PitScorpion.class)); cards.add(new SetCardInfo("Pixie Queen", 110, Rarity.RARE, mage.cards.p.PixieQueen.class)); cards.add(new SetCardInfo("Planar Gate", 235, Rarity.RARE, mage.cards.p.PlanarGate.class)); @@ -216,7 +219,7 @@ public class Legends extends ExpansionSet { cards.add(new SetCardInfo("Righteous Avengers", 203, Rarity.UNCOMMON, mage.cards.r.RighteousAvengers.class)); cards.add(new SetCardInfo("Ring of Immortals", 238, Rarity.RARE, mage.cards.r.RingOfImmortals.class)); cards.add(new SetCardInfo("Riven Turnbull", 294, Rarity.UNCOMMON, mage.cards.r.RivenTurnbull.class)); - cards.add(new SetCardInfo("Rohgahh of Kher Keep", 295, Rarity.RARE, mage.cards.r.RohgahhOfKherKeep.class)); + cards.add(new SetCardInfo("Rohgahh of Kher Keep", 295, Rarity.RARE, mage.cards.r.RohgahhOfKherKeep.class)); cards.add(new SetCardInfo("Rubinia Soulsinger", 296, Rarity.RARE, mage.cards.r.RubiniaSoulsinger.class)); cards.add(new SetCardInfo("Rust", 49, Rarity.COMMON, mage.cards.r.Rust.class)); cards.add(new SetCardInfo("Sea Kings' Blessing", 75, Rarity.UNCOMMON, mage.cards.s.SeaKingsBlessing.class)); @@ -227,7 +230,7 @@ public class Legends extends ExpansionSet { cards.add(new SetCardInfo("Sir Shandlar of Eberyn", 297, Rarity.UNCOMMON, mage.cards.s.SirShandlarOfEberyn.class)); cards.add(new SetCardInfo("Sivitri Scarzam", 298, Rarity.UNCOMMON, mage.cards.s.SivitriScarzam.class)); cards.add(new SetCardInfo("Sol'kanar the Swamp King", 299, Rarity.RARE, mage.cards.s.SolkanarTheSwampKing.class)); - cards.add(new SetCardInfo("Spectral Cloak", 78, Rarity.UNCOMMON, mage.cards.s.SpectralCloak.class)); + cards.add(new SetCardInfo("Spectral Cloak", 78, Rarity.UNCOMMON, mage.cards.s.SpectralCloak.class)); cards.add(new SetCardInfo("Spinal Villain", 161, Rarity.RARE, mage.cards.s.SpinalVillain.class)); cards.add(new SetCardInfo("Spirit Link", 206, Rarity.UNCOMMON, mage.cards.s.SpiritLink.class)); cards.add(new SetCardInfo("Spirit Shackle", 31, Rarity.COMMON, mage.cards.s.SpiritShackle.class)); @@ -237,6 +240,7 @@ public class Legends extends ExpansionSet { cards.add(new SetCardInfo("Sylvan Library", 121, Rarity.UNCOMMON, mage.cards.s.SylvanLibrary.class)); cards.add(new SetCardInfo("Sylvan Paradise", 122, Rarity.UNCOMMON, mage.cards.s.SylvanParadise.class)); cards.add(new SetCardInfo("Syphon Soul", 32, Rarity.COMMON, mage.cards.s.SyphonSoul.class)); + cards.add(new SetCardInfo("Teleport", 80, Rarity.RARE, mage.cards.t.Teleport.class)); cards.add(new SetCardInfo("Tetsuo Umezawa", 302, Rarity.RARE, mage.cards.t.TetsuoUmezawa.class)); cards.add(new SetCardInfo("The Abyss", 34, Rarity.RARE, mage.cards.t.TheAbyss.class)); cards.add(new SetCardInfo("The Brute", 164, Rarity.COMMON, mage.cards.t.TheBrute.class)); @@ -244,6 +248,7 @@ public class Legends extends ExpansionSet { cards.add(new SetCardInfo("The Tabernacle at Pendrell Vale", 252, Rarity.RARE, mage.cards.t.TheTabernacleAtPendrellVale.class)); cards.add(new SetCardInfo("The Wretched", 35, Rarity.RARE, mage.cards.t.TheWretched.class)); cards.add(new SetCardInfo("Thunder Spirit", 208, Rarity.RARE, mage.cards.t.ThunderSpirit.class)); + cards.add(new SetCardInfo("Time Elemental", 81, Rarity.RARE, mage.cards.t.TimeElemental.class)); cards.add(new SetCardInfo("Tobias Andrion", 304, Rarity.UNCOMMON, mage.cards.t.TobiasAndrion.class)); cards.add(new SetCardInfo("Torsten Von Ursus", 306, Rarity.UNCOMMON, mage.cards.t.TorstenVonUrsus.class)); cards.add(new SetCardInfo("Tor Wauki", 305, Rarity.UNCOMMON, mage.cards.t.TorWauki.class)); @@ -268,7 +273,7 @@ public class Legends extends ExpansionSet { cards.add(new SetCardInfo("White Mana Battery", 244, Rarity.UNCOMMON, mage.cards.w.WhiteManaBattery.class)); cards.add(new SetCardInfo("Willow Satyr", 126, Rarity.RARE, mage.cards.w.WillowSatyr.class)); cards.add(new SetCardInfo("Winds of Change", 169, Rarity.UNCOMMON, mage.cards.w.WindsOfChange.class)); - cards.add(new SetCardInfo("Winter Blast", 127, Rarity.RARE, mage.cards.w.WinterBlast.class)); + cards.add(new SetCardInfo("Winter Blast", 127, Rarity.RARE, mage.cards.w.WinterBlast.class)); cards.add(new SetCardInfo("Wolverine Pack", 128, Rarity.COMMON, mage.cards.w.WolverinePack.class)); cards.add(new SetCardInfo("Xira Arien", 310, Rarity.RARE, mage.cards.x.XiraArien.class)); cards.add(new SetCardInfo("Zephyr Falcon", 86, Rarity.COMMON, mage.cards.z.ZephyrFalcon.class)); diff --git a/Mage.Sets/src/mage/sets/MastersEdition.java b/Mage.Sets/src/mage/sets/MastersEdition.java index 5adcbf72ba..a6029ef856 100644 --- a/Mage.Sets/src/mage/sets/MastersEdition.java +++ b/Mage.Sets/src/mage/sets/MastersEdition.java @@ -108,7 +108,7 @@ public class MastersEdition extends ExpansionSet { cards.add(new SetCardInfo("Dwarven Catapult", 91, Rarity.UNCOMMON, mage.cards.d.DwarvenCatapult.class)); cards.add(new SetCardInfo("Dwarven Soldier", 92, Rarity.COMMON, DwarvenSoldier.class)); cards.add(new SetCardInfo("Eater of the Dead", 67, Rarity.UNCOMMON, mage.cards.e.EaterOfTheDead.class)); - cards.add(new SetCardInfo("Elder Land Wurm", 11, Rarity.UNCOMMON, mage.cards.e.ElderLandWurm.class)); + cards.add(new SetCardInfo("Elder Land Wurm", 11, Rarity.UNCOMMON, mage.cards.e.ElderLandWurm.class)); cards.add(new SetCardInfo("Erg Raiders", 68, Rarity.COMMON, mage.cards.e.ErgRaiders.class)); cards.add(new SetCardInfo("Eureka", 117, Rarity.RARE, mage.cards.e.Eureka.class)); cards.add(new SetCardInfo("Exile", 12, Rarity.COMMON, mage.cards.e.Exile.class)); @@ -183,9 +183,10 @@ public class MastersEdition extends ExpansionSet { cards.add(new SetCardInfo("Order of the Ebon Hand", 78, Rarity.COMMON, OrderOfTheEbonHand.class)); cards.add(new SetCardInfo("Oubliette", 79, Rarity.COMMON, Oubliette.class)); cards.add(new SetCardInfo("Paralyze", 80, Rarity.COMMON, mage.cards.p.Paralyze.class)); + cards.add(new SetCardInfo("Petra Sphinx", 23, Rarity.RARE, mage.cards.p.PetraSphinx.class)); cards.add(new SetCardInfo("Phantom Monster", 43, Rarity.COMMON, mage.cards.p.PhantomMonster.class)); cards.add(new SetCardInfo("Phelddagrif", 150, Rarity.RARE, mage.cards.p.Phelddagrif.class)); - cards.add(new SetCardInfo("Phyrexian Boon", 81, Rarity.COMMON, mage.cards.p.PhyrexianBoon.class)); + cards.add(new SetCardInfo("Phyrexian Boon", 81, Rarity.COMMON, mage.cards.p.PhyrexianBoon.class)); cards.add(new SetCardInfo("Phyrexian War Beast", 162, Rarity.UNCOMMON, PhyrexianWarBeast.class)); cards.add(new SetCardInfo("Plains", 181, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Plains", 182, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); @@ -229,6 +230,7 @@ public class MastersEdition extends ExpansionSet { cards.add(new SetCardInfo("Thrull Champion", 83, Rarity.RARE, mage.cards.t.ThrullChampion.class)); cards.add(new SetCardInfo("Thrull Retainer", 84, Rarity.COMMON, mage.cards.t.ThrullRetainer.class)); cards.add(new SetCardInfo("Thunder Spirit", 27, Rarity.UNCOMMON, mage.cards.t.ThunderSpirit.class)); + cards.add(new SetCardInfo("Time Elemental", 53, Rarity.RARE, mage.cards.t.TimeElemental.class)); cards.add(new SetCardInfo("Tivadar's Crusade", 28, Rarity.UNCOMMON, mage.cards.t.TivadarsCrusade.class)); cards.add(new SetCardInfo("Tornado", 136, Rarity.RARE, mage.cards.t.Tornado.class)); cards.add(new SetCardInfo("Urza's Bauble", 170, Rarity.UNCOMMON, mage.cards.u.UrzasBauble.class)); @@ -239,7 +241,7 @@ public class MastersEdition extends ExpansionSet { cards.add(new SetCardInfo("Walking Wall", 172, Rarity.UNCOMMON, mage.cards.w.WalkingWall.class)); cards.add(new SetCardInfo("Wanderlust", 137, Rarity.COMMON, mage.cards.w.Wanderlust.class)); cards.add(new SetCardInfo("Winds of Change", 111, Rarity.UNCOMMON, mage.cards.w.WindsOfChange.class)); - cards.add(new SetCardInfo("Winter Blast", 138, Rarity.UNCOMMON, mage.cards.w.WinterBlast.class)); + cards.add(new SetCardInfo("Winter Blast", 138, Rarity.UNCOMMON, mage.cards.w.WinterBlast.class)); cards.add(new SetCardInfo("Winter Orb", 173, Rarity.RARE, mage.cards.w.WinterOrb.class)); cards.add(new SetCardInfo("Wyluli Wolf", 139, Rarity.COMMON, mage.cards.w.WyluliWolf.class)); cards.add(new SetCardInfo("Yavimaya Ants", 140, Rarity.UNCOMMON, mage.cards.y.YavimayaAnts.class)); diff --git a/Mage.Sets/src/mage/sets/MastersEditionII.java b/Mage.Sets/src/mage/sets/MastersEditionII.java index f93ecf7023..f7fbf2feaa 100644 --- a/Mage.Sets/src/mage/sets/MastersEditionII.java +++ b/Mage.Sets/src/mage/sets/MastersEditionII.java @@ -148,7 +148,7 @@ public class MastersEditionII extends ExpansionSet { cards.add(new SetCardInfo("Helm of Obedience", 210, Rarity.RARE, mage.cards.h.HelmOfObedience.class)); cards.add(new SetCardInfo("Icatian Javelineers", 15, Rarity.COMMON, IcatianJavelineers.class)); cards.add(new SetCardInfo("Icatian Scout", 17, Rarity.COMMON, IcatianScout.class)); - cards.add(new SetCardInfo("Ice Floe", 232, Rarity.UNCOMMON, mage.cards.i.IceFloe.class)); + cards.add(new SetCardInfo("Ice Floe", 232, Rarity.UNCOMMON, mage.cards.i.IceFloe.class)); cards.add(new SetCardInfo("Iceberg", 49, Rarity.UNCOMMON, mage.cards.i.Iceberg.class)); cards.add(new SetCardInfo("Icequake", 94, Rarity.COMMON, mage.cards.i.Icequake.class)); cards.add(new SetCardInfo("Icy Prison", 50, Rarity.COMMON, mage.cards.i.IcyPrison.class)); @@ -170,7 +170,7 @@ public class MastersEditionII extends ExpansionSet { cards.add(new SetCardInfo("Kjeldoran Outpost", 233, Rarity.RARE, mage.cards.k.KjeldoranOutpost.class)); cards.add(new SetCardInfo("Knight of Stromgald", 99, Rarity.UNCOMMON, mage.cards.k.KnightOfStromgald.class)); cards.add(new SetCardInfo("Krovikan Fetish", 100, Rarity.COMMON, mage.cards.k.KrovikanFetish.class)); - cards.add(new SetCardInfo("Krovikan Horror", 101, Rarity.RARE, mage.cards.k.KrovikanHorror.class)); + cards.add(new SetCardInfo("Krovikan Horror", 101, Rarity.RARE, mage.cards.k.KrovikanHorror.class)); cards.add(new SetCardInfo("Krovikan Sorcerer", 51, Rarity.COMMON, mage.cards.k.KrovikanSorcerer.class)); cards.add(new SetCardInfo("Leaping Lizard", 171, Rarity.COMMON, mage.cards.l.LeapingLizard.class)); cards.add(new SetCardInfo("Lim-Dul's High Guard", 103, Rarity.UNCOMMON, LimDulsHighGuard.class)); @@ -180,6 +180,7 @@ public class MastersEditionII extends ExpansionSet { cards.add(new SetCardInfo("Mesmeric Trance", 55, Rarity.RARE, mage.cards.m.MesmericTrance.class)); cards.add(new SetCardInfo("Meteor Shower", 135, Rarity.COMMON, mage.cards.m.MeteorShower.class)); cards.add(new SetCardInfo("Minion of Leshrac", 104, Rarity.RARE, mage.cards.m.MinionOfLeshrac.class)); + cards.add(new SetCardInfo("Misinformation", 105, Rarity.UNCOMMON, mage.cards.m.Misinformation.class)); cards.add(new SetCardInfo("Mudslide", 136, Rarity.RARE, mage.cards.m.Mudslide.class)); cards.add(new SetCardInfo("Narwhal", 57, Rarity.UNCOMMON, mage.cards.n.Narwhal.class)); cards.add(new SetCardInfo("Nature's Wrath", 172, Rarity.RARE, mage.cards.n.NaturesWrath.class)); @@ -217,7 +218,7 @@ public class MastersEditionII extends ExpansionSet { cards.add(new SetCardInfo("Sea Drake", 64, Rarity.RARE, mage.cards.s.SeaDrake.class)); cards.add(new SetCardInfo("Sea Spirit", 65, Rarity.UNCOMMON, mage.cards.s.SeaSpirit.class)); cards.add(new SetCardInfo("Shrink", 175, Rarity.COMMON, mage.cards.s.Shrink.class)); - cards.add(new SetCardInfo("Shyft", 66, Rarity.COMMON, mage.cards.s.Shyft.class)); + cards.add(new SetCardInfo("Shyft", 66, Rarity.COMMON, mage.cards.s.Shyft.class)); cards.add(new SetCardInfo("Sibilant Spirit", 67, Rarity.RARE, mage.cards.s.SibilantSpirit.class)); cards.add(new SetCardInfo("Skeleton Ship", 197, Rarity.RARE, mage.cards.s.SkeletonShip.class)); cards.add(new SetCardInfo("Skull Catapult", 219, Rarity.UNCOMMON, mage.cards.s.SkullCatapult.class)); @@ -233,6 +234,7 @@ public class MastersEditionII extends ExpansionSet { cards.add(new SetCardInfo("Songs of the Damned", 110, Rarity.COMMON, mage.cards.s.SongsOfTheDamned.class)); cards.add(new SetCardInfo("Soul Exchange", 111, Rarity.UNCOMMON, mage.cards.s.SoulExchange.class)); cards.add(new SetCardInfo("Soul Kiss", 112, Rarity.UNCOMMON, mage.cards.s.SoulKiss.class)); + cards.add(new SetCardInfo("Spore Cloud", 176, Rarity.UNCOMMON, mage.cards.s.SporeCloud.class)); cards.add(new SetCardInfo("Spore Flower", 177, Rarity.UNCOMMON, mage.cards.s.SporeFlower.class)); cards.add(new SetCardInfo("Stampede", 178, Rarity.UNCOMMON, mage.cards.s.Stampede.class)); cards.add(new SetCardInfo("Stonehands", 151, Rarity.COMMON, mage.cards.s.Stonehands.class)); diff --git a/Mage.Sets/src/mage/sets/MastersEditionIII.java b/Mage.Sets/src/mage/sets/MastersEditionIII.java index a9a8ee82a1..4289a33168 100644 --- a/Mage.Sets/src/mage/sets/MastersEditionIII.java +++ b/Mage.Sets/src/mage/sets/MastersEditionIII.java @@ -100,10 +100,10 @@ public class MastersEditionIII extends ExpansionSet { cards.add(new SetCardInfo("Desperate Charge", 63, Rarity.COMMON, mage.cards.d.DesperateCharge.class)); cards.add(new SetCardInfo("Didgeridoo", 194, Rarity.UNCOMMON, mage.cards.d.Didgeridoo.class)); cards.add(new SetCardInfo("Disenchant", 7, Rarity.COMMON, mage.cards.d.Disenchant.class)); - cards.add(new SetCardInfo("Disharmony", 95, Rarity.UNCOMMON, mage.cards.d.Disharmony.class)); + cards.add(new SetCardInfo("Disharmony", 95, Rarity.UNCOMMON, mage.cards.d.Disharmony.class)); cards.add(new SetCardInfo("Divine Intervention", 8, Rarity.RARE, mage.cards.d.DivineIntervention.class)); cards.add(new SetCardInfo("Dong Zhou, the Tyrant", 96, Rarity.RARE, mage.cards.d.DongZhouTheTyrant.class)); - cards.add(new SetCardInfo("Eightfold Maze", 9, Rarity.UNCOMMON, mage.cards.e.EightfoldMaze.class)); + cards.add(new SetCardInfo("Eightfold Maze", 9, Rarity.UNCOMMON, mage.cards.e.EightfoldMaze.class)); cards.add(new SetCardInfo("Elves of Deep Shadow", 116, Rarity.COMMON, mage.cards.e.ElvesOfDeepShadow.class)); cards.add(new SetCardInfo("Evil Presence", 64, Rarity.COMMON, mage.cards.e.EvilPresence.class)); cards.add(new SetCardInfo("Exorcist", 10, Rarity.UNCOMMON, mage.cards.e.Exorcist.class)); @@ -130,7 +130,7 @@ public class MastersEditionIII extends ExpansionSet { cards.add(new SetCardInfo("Guan Yu's 1,000-Li March", 13, Rarity.RARE, mage.cards.g.GuanYus1000LiMarch.class)); cards.add(new SetCardInfo("Guan Yu, Sainted Warrior", 12, Rarity.UNCOMMON, mage.cards.g.GuanYuSaintedWarrior.class)); cards.add(new SetCardInfo("Gwendlyn Di Corci", 149, Rarity.RARE, mage.cards.g.GwendlynDiCorci.class)); - cards.add(new SetCardInfo("Hammerheim", 207, Rarity.UNCOMMON, mage.cards.h.Hammerheim.class)); + cards.add(new SetCardInfo("Hammerheim", 207, Rarity.UNCOMMON, mage.cards.h.Hammerheim.class)); cards.add(new SetCardInfo("Hazezon Tamar", 151, Rarity.RARE, mage.cards.h.HazezonTamar.class)); cards.add(new SetCardInfo("Heal", 14, Rarity.COMMON, mage.cards.h.Heal.class)); cards.add(new SetCardInfo("Hellfire", 70, Rarity.RARE, mage.cards.h.Hellfire.class)); @@ -156,7 +156,7 @@ public class MastersEditionIII extends ExpansionSet { cards.add(new SetCardInfo("Kobolds of Kher Keep", 107, Rarity.COMMON, mage.cards.k.KoboldsOfKherKeep.class)); cards.add(new SetCardInfo("Kobold Taskmaster", 106, Rarity.COMMON, mage.cards.k.KoboldTaskmaster.class)); cards.add(new SetCardInfo("Kongming, 'Sleeping Dragon'", 16, Rarity.RARE, mage.cards.k.KongmingSleepingDragon.class)); - cards.add(new SetCardInfo("Labyrinth Minotaur", 39, Rarity.COMMON, mage.cards.l.LabyrinthMinotaur.class)); + cards.add(new SetCardInfo("Labyrinth Minotaur", 39, Rarity.COMMON, mage.cards.l.LabyrinthMinotaur.class)); cards.add(new SetCardInfo("Lady Caleria", 157, Rarity.UNCOMMON, mage.cards.l.LadyCaleria.class)); cards.add(new SetCardInfo("Lady Evangela", 158, Rarity.UNCOMMON, mage.cards.l.LadyEvangela.class)); cards.add(new SetCardInfo("Lady Orca", 159, Rarity.COMMON, mage.cards.l.LadyOrca.class)); @@ -183,6 +183,7 @@ public class MastersEditionIII extends ExpansionSet { cards.add(new SetCardInfo("Mountain", 227, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Nether Void", 73, Rarity.RARE, mage.cards.n.NetherVoid.class)); cards.add(new SetCardInfo("Nicol Bolas", 163, Rarity.RARE, mage.cards.n.NicolBolas.class)); + cards.add(new SetCardInfo("Nova Pentacle", 200, Rarity.RARE, mage.cards.n.NovaPentacle.class)); cards.add(new SetCardInfo("Old Man of the Sea", 45, Rarity.RARE, mage.cards.o.OldManOfTheSea.class)); cards.add(new SetCardInfo("Palladia-Mors", 164, Rarity.RARE, mage.cards.p.PalladiaMors.class)); cards.add(new SetCardInfo("Pavel Maliki", 165, Rarity.UNCOMMON, mage.cards.p.PavelMaliki.class)); @@ -204,7 +205,7 @@ public class MastersEditionIII extends ExpansionSet { cards.add(new SetCardInfo("Reveka, Wizard Savant", 49, Rarity.UNCOMMON, mage.cards.r.RevekaWizardSavant.class)); cards.add(new SetCardInfo("Riding the Dilu Horse", 131, Rarity.UNCOMMON, mage.cards.r.RidingTheDiluHorse.class)); cards.add(new SetCardInfo("Riven Turnbull", 171, Rarity.UNCOMMON, mage.cards.r.RivenTurnbull.class)); - cards.add(new SetCardInfo("Rohgahh of Kher Keep", 172, Rarity.RARE, mage.cards.r.RohgahhOfKherKeep.class)); + cards.add(new SetCardInfo("Rohgahh of Kher Keep", 172, Rarity.RARE, mage.cards.r.RohgahhOfKherKeep.class)); cards.add(new SetCardInfo("Rolling Earthquake", 110, Rarity.RARE, mage.cards.r.RollingEarthquake.class)); cards.add(new SetCardInfo("Rubinia Soulsinger", 173, Rarity.RARE, mage.cards.r.RubiniaSoulsinger.class)); cards.add(new SetCardInfo("Scrubland", 210, Rarity.RARE, mage.cards.s.Scrubland.class)); diff --git a/Mage.Sets/src/mage/sets/MercadianMasques.java b/Mage.Sets/src/mage/sets/MercadianMasques.java index d8ceae0219..c0bde8f6e1 100644 --- a/Mage.Sets/src/mage/sets/MercadianMasques.java +++ b/Mage.Sets/src/mage/sets/MercadianMasques.java @@ -158,6 +158,7 @@ public class MercadianMasques extends ExpansionSet { cards.add(new SetCardInfo("Fresh Volunteers", 20, Rarity.COMMON, mage.cards.f.FreshVolunteers.class)); cards.add(new SetCardInfo("Furious Assault", 191, Rarity.COMMON, mage.cards.f.FuriousAssault.class)); cards.add(new SetCardInfo("Game Preserve", 248, Rarity.RARE, mage.cards.g.GamePreserve.class)); + cards.add(new SetCardInfo("General's Regalia", 295, Rarity.RARE, mage.cards.g.GeneralsRegalia.class)); cards.add(new SetCardInfo("Gerrard's Irregulars", 192, Rarity.COMMON, mage.cards.g.GerrardsIrregulars.class)); cards.add(new SetCardInfo("Ghoul's Feast", 137, Rarity.UNCOMMON, mage.cards.g.GhoulsFeast.class)); cards.add(new SetCardInfo("Giant Caterpillar", 249, Rarity.COMMON, mage.cards.g.GiantCaterpillar.class)); @@ -329,7 +330,7 @@ public class MercadianMasques extends ExpansionSet { cards.add(new SetCardInfo("Tidal Bore", 109, Rarity.COMMON, mage.cards.t.TidalBore.class)); cards.add(new SetCardInfo("Tidal Kraken", 110, Rarity.RARE, mage.cards.t.TidalKraken.class)); cards.add(new SetCardInfo("Tiger Claws", 279, Rarity.COMMON, mage.cards.t.TigerClaws.class)); - cards.add(new SetCardInfo("Timid Drake", 111, Rarity.UNCOMMON, mage.cards.t.TimidDrake.class)); + cards.add(new SetCardInfo("Timid Drake", 111, Rarity.UNCOMMON, mage.cards.t.TimidDrake.class)); cards.add(new SetCardInfo("Tonic Peddler", 54, Rarity.UNCOMMON, mage.cards.t.TonicPeddler.class)); cards.add(new SetCardInfo("Tooth of Ramos", 313, Rarity.RARE, mage.cards.t.ToothOfRamos.class)); cards.add(new SetCardInfo("Tower of the Magistrate", 330, Rarity.RARE, mage.cards.t.TowerOfTheMagistrate.class)); diff --git a/Mage.Sets/src/mage/sets/Mirage.java b/Mage.Sets/src/mage/sets/Mirage.java index 2100e30fab..e16c401dca 100644 --- a/Mage.Sets/src/mage/sets/Mirage.java +++ b/Mage.Sets/src/mage/sets/Mirage.java @@ -105,6 +105,7 @@ public class Mirage extends ExpansionSet { cards.add(new SetCardInfo("Daring Apprentice", 60, Rarity.RARE, mage.cards.d.DaringApprentice.class)); cards.add(new SetCardInfo("Dark Banishing", 13, Rarity.COMMON, mage.cards.d.DarkBanishing.class)); cards.add(new SetCardInfo("Dark Ritual", 14, Rarity.COMMON, mage.cards.d.DarkRitual.class)); + cards.add(new SetCardInfo("Dazzling Beauty", 212, Rarity.COMMON, mage.cards.d.DazzlingBeauty.class)); cards.add(new SetCardInfo("Dirtwater Wraith", 15, Rarity.COMMON, mage.cards.d.DirtwaterWraith.class)); cards.add(new SetCardInfo("Disempower", 213, Rarity.COMMON, mage.cards.d.Disempower.class)); cards.add(new SetCardInfo("Disenchant", 214, Rarity.COMMON, mage.cards.d.Disenchant.class)); diff --git a/Mage.Sets/src/mage/sets/Onslaught.java b/Mage.Sets/src/mage/sets/Onslaught.java index f8311aadc5..335a165dbd 100644 --- a/Mage.Sets/src/mage/sets/Onslaught.java +++ b/Mage.Sets/src/mage/sets/Onslaught.java @@ -145,6 +145,7 @@ public class Onslaught extends ExpansionSet { cards.add(new SetCardInfo("Glory Seeker", 31, Rarity.COMMON, mage.cards.g.GlorySeeker.class)); cards.add(new SetCardInfo("Gluttonous Zombie", 151, Rarity.UNCOMMON, mage.cards.g.GluttonousZombie.class)); cards.add(new SetCardInfo("Goblin Burrows", 318, Rarity.UNCOMMON, mage.cards.g.GoblinBurrows.class)); + cards.add(new SetCardInfo("Goblin Machinist", 204, Rarity.UNCOMMON, mage.cards.g.GoblinMachinist.class)); cards.add(new SetCardInfo("Goblin Piledriver", 205, Rarity.RARE, mage.cards.g.GoblinPiledriver.class)); cards.add(new SetCardInfo("Goblin Pyromancer", 206, Rarity.RARE, mage.cards.g.GoblinPyromancer.class)); cards.add(new SetCardInfo("Goblin Sharpshooter", 207, Rarity.RARE, mage.cards.g.GoblinSharpshooter.class)); @@ -260,6 +261,7 @@ public class Onslaught extends ExpansionSet { cards.add(new SetCardInfo("Secluded Steppe", 324, Rarity.COMMON, mage.cards.s.SecludedSteppe.class)); cards.add(new SetCardInfo("Serpentine Basilisk", 280, Rarity.UNCOMMON, mage.cards.s.SerpentineBasilisk.class)); cards.add(new SetCardInfo("Severed Legion", 166, Rarity.COMMON, mage.cards.s.SeveredLegion.class)); + cards.add(new SetCardInfo("Shade's Breath", 167, Rarity.UNCOMMON, mage.cards.s.ShadesBreath.class)); cards.add(new SetCardInfo("Shaleskin Bruiser", 226, Rarity.UNCOMMON, mage.cards.s.ShaleskinBruiser.class)); cards.add(new SetCardInfo("Shared Triumph", 53, Rarity.RARE, mage.cards.s.SharedTriumph.class)); cards.add(new SetCardInfo("Shepherd of Rot", 168, Rarity.COMMON, mage.cards.s.ShepherdOfRot.class)); diff --git a/Mage.Sets/src/mage/sets/Visions.java b/Mage.Sets/src/mage/sets/Visions.java index 7f7d25ed48..e016bce9fa 100644 --- a/Mage.Sets/src/mage/sets/Visions.java +++ b/Mage.Sets/src/mage/sets/Visions.java @@ -78,6 +78,7 @@ public class Visions extends ExpansionSet { cards.add(new SetCardInfo("Diamond Kaleidoscope", 143, Rarity.RARE, mage.cards.d.DiamondKaleidoscope.class)); cards.add(new SetCardInfo("Dormant Volcano", 161, Rarity.UNCOMMON, mage.cards.d.DormantVolcano.class)); cards.add(new SetCardInfo("Dragon Mask", 144, Rarity.UNCOMMON, mage.cards.d.DragonMask.class)); + cards.add(new SetCardInfo("Dream Tides", 31, Rarity.UNCOMMON, mage.cards.d.DreamTides.class)); cards.add(new SetCardInfo("Dwarven Vigilantes", 77, Rarity.COMMON, mage.cards.d.DwarvenVigilantes.class)); cards.add(new SetCardInfo("Elephant Grass", 54, Rarity.UNCOMMON, mage.cards.e.ElephantGrass.class)); cards.add(new SetCardInfo("Elven Cache", 55, Rarity.COMMON, mage.cards.e.ElvenCache.class)); @@ -147,7 +148,7 @@ public class Visions extends ExpansionSet { cards.add(new SetCardInfo("Resistance Fighter", 118, Rarity.COMMON, mage.cards.r.ResistanceFighter.class)); cards.add(new SetCardInfo("Retribution of the Meek", 119, Rarity.RARE, mage.cards.r.RetributionOfTheMeek.class)); cards.add(new SetCardInfo("Righteous Aura", 120, Rarity.COMMON, mage.cards.r.RighteousAura.class)); - cards.add(new SetCardInfo("Righteous War", 134, Rarity.RARE, mage.cards.r.RighteousWar.class)); + cards.add(new SetCardInfo("Righteous War", 134, Rarity.RARE, mage.cards.r.RighteousWar.class)); cards.add(new SetCardInfo("River Boa", 68, Rarity.COMMON, mage.cards.r.RiverBoa.class)); cards.add(new SetCardInfo("Rock Slide", 92, Rarity.COMMON, mage.cards.r.RockSlide.class)); cards.add(new SetCardInfo("Rowen", 69, Rarity.RARE, mage.cards.r.Rowen.class)); @@ -162,7 +163,7 @@ public class Visions extends ExpansionSet { cards.add(new SetCardInfo("Spitting Drake", 95, Rarity.UNCOMMON, mage.cards.s.SpittingDrake.class)); cards.add(new SetCardInfo("Squandered Resources", 137, Rarity.RARE, mage.cards.s.SquanderedResources.class)); cards.add(new SetCardInfo("Stampeding Wildebeests", 71, Rarity.UNCOMMON, mage.cards.s.StampedingWildebeests.class)); - cards.add(new SetCardInfo("Suleiman's Legacy", 138, Rarity.RARE, mage.cards.s.SuleimansLegacy.class)); + cards.add(new SetCardInfo("Suleiman's Legacy", 138, Rarity.RARE, mage.cards.s.SuleimansLegacy.class)); cards.add(new SetCardInfo("Summer Bloom", 72, Rarity.UNCOMMON, mage.cards.s.SummerBloom.class)); cards.add(new SetCardInfo("Sun Clasp", 121, Rarity.COMMON, mage.cards.s.SunClasp.class)); cards.add(new SetCardInfo("Suq'Ata Assassin", 19, Rarity.UNCOMMON, mage.cards.s.SuqAtaAssassin.class)); diff --git a/Mage/src/main/java/mage/abilities/condition/common/YouGainedLifeCondition.java b/Mage/src/main/java/mage/abilities/condition/common/YouGainedLifeCondition.java index f19ff14b8e..a33a4d9bd0 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/YouGainedLifeCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/YouGainedLifeCondition.java @@ -27,7 +27,6 @@ public class YouGainedLifeCondition extends IntCompareCondition { @Override public String toString() { - return String.format("if you gained %s or more life this turn ", value); + return String.format("if you gained %s or more life this turn ", value + 1); } } - diff --git a/Mage/src/main/java/mage/abilities/effects/common/LookLibraryAndPickControllerEffect.java b/Mage/src/main/java/mage/abilities/effects/common/LookLibraryAndPickControllerEffect.java index 5a93cbae46..99958198d3 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/LookLibraryAndPickControllerEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/LookLibraryAndPickControllerEffect.java @@ -270,7 +270,7 @@ public class LookLibraryAndPickControllerEffect extends LookLibraryControllerEff } else { sb.append('P'); } - sb.append("put ").append(filter.getMessage()).append(" from among them onto the "); + sb.append("ut ").append(filter.getMessage()).append(" from among them onto the "); } else { sb.append(". Put "); if (numberToPick.calculate(null, null, this) > 1) { diff --git a/Mage/src/main/java/mage/abilities/effects/common/combat/CantAttackSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/combat/CantAttackSourceEffect.java new file mode 100644 index 0000000000..c84508d18a --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/combat/CantAttackSourceEffect.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 mage.abilities.effects.common.combat; + +import mage.constants.Duration; +import mage.abilities.Ability; +import mage.abilities.effects.RestrictionEffect; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * + * @author BetaSteward_at_googlemail.com & L_J + */ +public class CantAttackSourceEffect extends RestrictionEffect { + + public CantAttackSourceEffect(Duration duration) { + super(duration); + this.staticText = "{this} can't attack"; + } + + public CantAttackSourceEffect(final CantAttackSourceEffect effect) { + super(effect); + } + + @Override + public boolean applies(Permanent permanent, Ability source, Game game) { + if (permanent.getId().equals(source.getSourceId())) { + return true; + } + return false; + } + + @Override + public boolean canAttack(Game game) { + return false; + } + + @Override + public CantAttackSourceEffect copy() { + return new CantAttackSourceEffect(this); + } + +} diff --git a/Mage/src/main/java/mage/abilities/keyword/special/JohanVigilanceAbility.java b/Mage/src/main/java/mage/abilities/keyword/special/JohanVigilanceAbility.java new file mode 100644 index 0000000000..2232b4739e --- /dev/null +++ b/Mage/src/main/java/mage/abilities/keyword/special/JohanVigilanceAbility.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 mage.abilities.keyword.special; + +import mage.constants.Zone; +import mage.abilities.MageSingleton; +import mage.abilities.StaticAbility; + +import java.io.ObjectStreamException; + +/** + * + * @author BetaSteward_at_googlemail.com & L_J + */ +public class JohanVigilanceAbility extends StaticAbility implements MageSingleton { // special instance of "attacking doesn't cause this to tap" granted by Johan's ability + + private static final JohanVigilanceAbility instance = new JohanVigilanceAbility(); + + private Object readResolve() throws ObjectStreamException { + return instance; + } + + public static JohanVigilanceAbility getInstance() { + return instance; + } + + private JohanVigilanceAbility() { + super(Zone.BATTLEFIELD, null); + } + + @Override + public String getRule() { + return ""; + } + + @Override + public JohanVigilanceAbility copy() { + return instance; + } + +} diff --git a/Mage/src/main/java/mage/game/combat/Combat.java b/Mage/src/main/java/mage/game/combat/Combat.java index 135919b8ab..df50deaf89 100644 --- a/Mage/src/main/java/mage/game/combat/Combat.java +++ b/Mage/src/main/java/mage/game/combat/Combat.java @@ -34,6 +34,7 @@ import mage.abilities.Ability; import mage.abilities.effects.RequirementEffect; import mage.abilities.effects.RestrictionEffect; import mage.abilities.keyword.VigilanceAbility; +import mage.abilities.keyword.special.JohanVigilanceAbility; import mage.constants.Outcome; import mage.constants.Zone; import mage.filter.StaticFilters; @@ -1091,7 +1092,7 @@ public class Combat implements Serializable, Copyable { @SuppressWarnings("deprecation") public boolean declareAttacker(UUID creatureId, UUID defenderId, UUID playerId, Game game) { Permanent attacker = game.getPermanent(creatureId); - if (!attacker.getAbilities().containsKey(VigilanceAbility.getInstance().getId())) { + if (!attacker.getAbilities().containsKey(VigilanceAbility.getInstance().getId()) && !attacker.getAbilities().containsKey(JohanVigilanceAbility.getInstance().getId())) { if (!attacker.isTapped()) { attacker.setTapped(true); attackersTappedByAttack.add(attacker.getId()); diff --git a/Mage/src/main/java/mage/watchers/common/ChooseBlockersRedundancyWatcher.java b/Mage/src/main/java/mage/watchers/common/ChooseBlockersRedundancyWatcher.java new file mode 100644 index 0000000000..f39cbb2c00 --- /dev/null +++ b/Mage/src/main/java/mage/watchers/common/ChooseBlockersRedundancyWatcher.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.watchers.common; + +import mage.constants.WatcherScope; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.watchers.Watcher; + +/** + * + * @author L_J + */ + +public class ChooseBlockersRedundancyWatcher extends Watcher { // workaround for solving timestamp issues regarding "you choose which creatures block and how those creatures block" effects + + public int copyCount = 0; + public int copyCountApply = 0; + + public ChooseBlockersRedundancyWatcher() { + super(ChooseBlockersRedundancyWatcher.class.getSimpleName(), WatcherScope.GAME); + } + + public ChooseBlockersRedundancyWatcher(final ChooseBlockersRedundancyWatcher watcher) { + super(watcher); + this.copyCount = watcher.copyCount; + this.copyCountApply = watcher.copyCountApply; + } + + @Override + public void reset() { + copyCount = 0; + copyCountApply = 0; + } + + @Override + public ChooseBlockersRedundancyWatcher copy() { + return new ChooseBlockersRedundancyWatcher(this); + } + + @Override + public void watch(GameEvent event, Game game) { + } + + public void increment() { + copyCount++; + copyCountApply = copyCount; + } + + public void decrement() { + if (copyCountApply > 0) { + copyCountApply--; + } + } +}