diff --git a/Mage.Sets/src/mage/sets/futuresight/ArcBlade.java b/Mage.Sets/src/mage/sets/futuresight/ArcBlade.java new file mode 100644 index 00000000000..dd51113b362 --- /dev/null +++ b/Mage.Sets/src/mage/sets/futuresight/ArcBlade.java @@ -0,0 +1,76 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.futuresight; + +import java.util.UUID; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.ExileSpellEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.keyword.SuspendAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.counters.CounterType; +import mage.target.common.TargetCreatureOrPlayer; + +/** + * + * @author emerald000 + */ +public class ArcBlade extends CardImpl { + + public ArcBlade(UUID ownerId) { + super(ownerId, 94, "Arc Blade", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{3}{R}{R}"); + this.expansionSetCode = "FUT"; + + // Arc Blade deals 2 damage to target creature or player. + this.getSpellAbility().addEffect(new DamageTargetEffect(2)); + // Exile Arc Blade + this.getSpellAbility().addEffect(ExileSpellEffect.getInstance()); + // with three time counters on it. + Effect effect = new AddCountersSourceEffect(CounterType.TIME.createInstance(), new StaticValue(3), false, true); + effect.setText("with 3 time counters on it"); + this.getSpellAbility().addEffect(effect); + this.getSpellAbility().addTarget(new TargetCreatureOrPlayer()); + + // Suspend 3-{2}{R} + this.addAbility(new SuspendAbility(3, new ManaCostsImpl<>("{2}{R}"), this)); + } + + public ArcBlade(final ArcBlade card) { + super(card); + } + + @Override + public ArcBlade copy() { + return new ArcBlade(this); + } +} diff --git a/Mage.Sets/src/mage/sets/morningtide/BattletideAlchemist.java b/Mage.Sets/src/mage/sets/morningtide/BattletideAlchemist.java new file mode 100644 index 00000000000..2d921f04e9c --- /dev/null +++ b/Mage.Sets/src/mage/sets/morningtide/BattletideAlchemist.java @@ -0,0 +1,134 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.morningtide; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.effects.PreventionEffectImpl; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; +import mage.players.Player; + +/** + * + * @author emerald000 + */ +public class BattletideAlchemist extends CardImpl { + + public BattletideAlchemist(UUID ownerId) { + super(ownerId, 2, "Battletide Alchemist", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{3}{W}{W}"); + this.expansionSetCode = "MOR"; + this.subtype.add("Kithkin"); + this.subtype.add("Cleric"); + this.power = new MageInt(3); + this.toughness = new MageInt(4); + + // If a source would deal damage to a player, you may prevent X of that damage, where X is the number of Clerics you control. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BattletideAlchemistEffect())); + } + + public BattletideAlchemist(final BattletideAlchemist card) { + super(card); + } + + @Override + public BattletideAlchemist copy() { + return new BattletideAlchemist(this); + } +} + +class BattletideAlchemistEffect extends PreventionEffectImpl { + + BattletideAlchemistEffect() { + super(Duration.WhileOnBattlefield); + this.staticText = "If a source would deal damage to a player, you may prevent X of that damage, where X is the number of Clerics you control"; + } + + BattletideAlchemistEffect(final BattletideAlchemistEffect effect) { + super(effect); + } + + @Override + public BattletideAlchemistEffect copy() { + return new BattletideAlchemistEffect(this); + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + boolean result = false; + Player controller = game.getPlayer(source.getControllerId()); + Player targetPlayer = game.getPlayer(event.getTargetId()); + if (controller != null) { + int numberOfClericsControlled = new PermanentsOnBattlefieldCount(new FilterControlledCreaturePermanent("Cleric", "Clerics")).calculate(game, source, this); + int toPrevent = Math.min(numberOfClericsControlled, event.getAmount()); + if (toPrevent > 0 && controller.chooseUse(Outcome.PreventDamage, "Prevent " + toPrevent + " damage to " + targetPlayer.getName() + "?", source, game)) { + GameEvent preventEvent = new GameEvent(GameEvent.EventType.PREVENT_DAMAGE, targetPlayer.getId(), source.getSourceId(), source.getControllerId(), toPrevent, false); + if (!game.replaceEvent(preventEvent)) { + if (event.getAmount() >= toPrevent) { + event.setAmount(event.getAmount() - toPrevent); + } + else { + event.setAmount(0); + result = true; + } + if (toPrevent > 0) { + game.informPlayers("Battletide Alchemist prevented " + toPrevent + " damage to " + targetPlayer.getName()); + game.fireEvent(GameEvent.getEvent( + GameEvent.EventType.PREVENTED_DAMAGE, + targetPlayer.getId(), + source.getSourceId(), + source.getControllerId(), + toPrevent)); + } + } + } + } + return result; + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.DAMAGE_PLAYER; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + return super.applies(event, source, game); + } +} diff --git a/Mage.Sets/src/mage/sets/morningtide/BoldwyrHeavyweights.java b/Mage.Sets/src/mage/sets/morningtide/BoldwyrHeavyweights.java new file mode 100644 index 00000000000..bae6ee9a48b --- /dev/null +++ b/Mage.Sets/src/mage/sets/morningtide/BoldwyrHeavyweights.java @@ -0,0 +1,117 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.morningtide; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterCreatureCard; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetCardInLibrary; + +/** + * + * @author emerald000 + */ +public class BoldwyrHeavyweights extends CardImpl { + + public BoldwyrHeavyweights(UUID ownerId) { + super(ownerId, 85, "Boldwyr Heavyweights", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{2}{R}{R}"); + this.expansionSetCode = "MOR"; + this.subtype.add("Giant"); + this.subtype.add("Warrior"); + this.power = new MageInt(8); + this.toughness = new MageInt(8); + + // Trample + this.addAbility(TrampleAbility.getInstance()); + + // When Boldwyr Heavyweights enters the battlefield, each opponent may search his or her library for a creature card and put it onto the battlefield. Then each player who searched his or her library this way shuffles it. + this.addAbility(new EntersBattlefieldTriggeredAbility(new BoldwyrHeavyweightsEffect())); + } + + public BoldwyrHeavyweights(final BoldwyrHeavyweights card) { + super(card); + } + + @Override + public BoldwyrHeavyweights copy() { + return new BoldwyrHeavyweights(this); + } +} + +class BoldwyrHeavyweightsEffect extends OneShotEffect { + + BoldwyrHeavyweightsEffect() { + super(Outcome.Detriment); + this.staticText = "each opponent may search his or her library for a creature card and put it onto the battlefield. Then each player who searched his or her library this way shuffles it"; + } + + BoldwyrHeavyweightsEffect(final BoldwyrHeavyweightsEffect effect) { + super(effect); + } + + @Override + public BoldwyrHeavyweightsEffect copy() { + return new BoldwyrHeavyweightsEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Set playersThatSearched = new HashSet<>(1); + for (UUID opponentId : game.getOpponents(source.getControllerId())) { + Player opponent = game.getPlayer(opponentId); + if (opponent != null && opponent.chooseUse(Outcome.PutCreatureInPlay, "Search your library for a creature card and put it onto the battlefield?", source, game)) { + TargetCardInLibrary target = new TargetCardInLibrary(new FilterCreatureCard()); + if (opponent.searchLibrary(target, game)) { + Card targetCard = opponent.getLibrary().getCard(target.getFirstTarget(), game); + if (targetCard != null) { + opponent.moveCards(targetCard, Zone.BATTLEFIELD, source, game); + playersThatSearched.add(opponent); + } + } + } + } + for (Player opponent : playersThatSearched) { + opponent.shuffleLibrary(source, game); + } + return true; + } +} diff --git a/Mage.Sets/src/mage/sets/morningtide/CoordinatedBarrage.java b/Mage.Sets/src/mage/sets/morningtide/CoordinatedBarrage.java new file mode 100644 index 00000000000..34f7fd93d39 --- /dev/null +++ b/Mage.Sets/src/mage/sets/morningtide/CoordinatedBarrage.java @@ -0,0 +1,109 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.morningtide; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.cards.CardImpl; +import mage.cards.repository.CardRepository; +import mage.choices.Choice; +import mage.choices.ChoiceImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetAttackingOrBlockingCreature; + +/** + * + * @author emerald000 + */ +public class CoordinatedBarrage extends CardImpl { + + public CoordinatedBarrage(UUID ownerId) { + super(ownerId, 7, "Coordinated Barrage", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{W}"); + this.expansionSetCode = "MOR"; + + // Choose a creature type. Coordinated Barrage deals damage to target attacking or blocking creature equal to the number of permanents you control of the chosen type. + this.getSpellAbility().addEffect(new CoordinatedBarrageEffect()); + this.getSpellAbility().addTarget(new TargetAttackingOrBlockingCreature()); + } + + public CoordinatedBarrage(final CoordinatedBarrage card) { + super(card); + } + + @Override + public CoordinatedBarrage copy() { + return new CoordinatedBarrage(this); + } +} + +class CoordinatedBarrageEffect extends OneShotEffect { + + CoordinatedBarrageEffect() { + super(Outcome.Damage); + this.staticText = "Choose a creature type. Coordinated Barrage deals damage to target attacking or blocking creature equal to the number of permanents you control of the chosen type"; + } + + CoordinatedBarrageEffect(final CoordinatedBarrageEffect effect) { + super(effect); + } + + @Override + public CoordinatedBarrageEffect copy() { + return new CoordinatedBarrageEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + Choice choice = new ChoiceImpl(true); + choice.setMessage("Choose a creature type"); + choice.setChoices(CardRepository.instance.getCreatureTypes()); + if (controller.choose(Outcome.Damage, choice, game)) { + String chosenType = choice.getChoice(); + FilterControlledPermanent filter = new FilterControlledPermanent(); + filter.add(new SubtypePredicate(chosenType)); + int damageDealt = game.getBattlefield().count(filter, source.getSourceId(), source.getControllerId(), game); + Permanent permanent = game.getPermanent(this.getTargetPointer().getFirst(game, source)); + if (permanent != null) { + permanent.damage(damageDealt, source.getSourceId(), game, false, true); + } + return true; + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/morningtide/HostileRealm.java b/Mage.Sets/src/mage/sets/morningtide/HostileRealm.java new file mode 100644 index 00000000000..5f093b2e74c --- /dev/null +++ b/Mage.Sets/src/mage/sets/morningtide/HostileRealm.java @@ -0,0 +1,85 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.morningtide; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.combat.CantBlockTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.cards.CardImpl; +import mage.constants.AttachmentType; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; +import mage.target.common.TargetLandPermanent; + +/** + * + * @author emerald000 + */ +public class HostileRealm extends CardImpl { + + public HostileRealm(UUID ownerId) { + super(ownerId, 91, "Hostile Realm", Rarity.COMMON, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}"); + this.expansionSetCode = "MOR"; + this.subtype.add("Aura"); + + // Enchant land + TargetPermanent auraTarget = new TargetLandPermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.AddAbility)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + + // Enchanted land has "{T}: Target creature can't block this turn." + Ability gainedAbility = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CantBlockTargetEffect(Duration.EndOfTurn), new TapSourceCost()); + gainedAbility.addTarget(new TargetCreaturePermanent()); + Effect effect = new GainAbilityAttachedEffect(gainedAbility, AttachmentType.AURA); + effect.setText("Enchanted land has \"{T}: Target creature can't block this turn.\""); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); + } + + public HostileRealm(final HostileRealm card) { + super(card); + } + + @Override + public HostileRealm copy() { + return new HostileRealm(this); + } +} diff --git a/Mage.Sets/src/mage/sets/morningtide/Stenchskipper.java b/Mage.Sets/src/mage/sets/morningtide/Stenchskipper.java new file mode 100644 index 00000000000..2874c65dbe2 --- /dev/null +++ b/Mage.Sets/src/mage/sets/morningtide/Stenchskipper.java @@ -0,0 +1,79 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.morningtide; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.BeginningOfEndStepTriggeredAbility; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.effects.common.SacrificeSourceEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.filter.common.FilterControlledCreaturePermanent; + +/** + * + * @author emerald000 + */ +public class Stenchskipper extends CardImpl { + + public Stenchskipper(UUID ownerId) { + super(ownerId, 79, "Stenchskipper", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{3}{B}"); + this.expansionSetCode = "MOR"; + this.subtype.add("Elemental"); + this.power = new MageInt(6); + this.toughness = new MageInt(5); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // At the beginning of the end step, if you control no Goblins, sacrifice Stenchskipper. + this.addAbility(new BeginningOfEndStepTriggeredAbility( + Zone.BATTLEFIELD, + new SacrificeSourceEffect(), + TargetController.ANY, + new PermanentsOnTheBattlefieldCondition( + new FilterControlledCreaturePermanent("Goblin", "if you control no Goblins"), + PermanentsOnTheBattlefieldCondition.CountType.FEWER_THAN, + 1), + false)); + } + + public Stenchskipper(final Stenchskipper card) { + super(card); + } + + @Override + public Stenchskipper copy() { + return new Stenchskipper(this); + } +} diff --git a/Mage.Sets/src/mage/sets/morningtide/WeightOfConscience.java b/Mage.Sets/src/mage/sets/morningtide/WeightOfConscience.java new file mode 100644 index 00000000000..f0094a0335b --- /dev/null +++ b/Mage.Sets/src/mage/sets/morningtide/WeightOfConscience.java @@ -0,0 +1,214 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.morningtide; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.common.TapTargetCost; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.combat.CantAttackAttachedEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.cards.CardImpl; +import mage.constants.AttachmentType; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.permanent.TappedPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.TargetPermanent; +import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.common.TargetCreaturePermanent; +import mage.util.CardUtil; + +/** + * + * @author emerald000 + */ +public class WeightOfConscience extends CardImpl { + + public WeightOfConscience(UUID ownerId) { + super(ownerId, 28, "Weight of Conscience", Rarity.COMMON, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}"); + this.expansionSetCode = "MOR"; + this.subtype.add("Aura"); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.Detriment)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + + // Enchanted creature can't attack. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantAttackAttachedEffect(AttachmentType.AURA))); + + // Tap two untapped creatures you control that share a creature type: Exile enchanted creature. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new WeightOfConscienceEffect(), new TapTargetCost(new WeightOfConscienceTarget()))); + } + + public WeightOfConscience(final WeightOfConscience card) { + super(card); + } + + @Override + public WeightOfConscience copy() { + return new WeightOfConscience(this); + } +} + +class WeightOfConscienceEffect extends OneShotEffect { + + WeightOfConscienceEffect() { + super(Outcome.Exile); + staticText = "Exile enchanted creature"; + } + + WeightOfConscienceEffect(final WeightOfConscienceEffect effect) { + super(effect); + } + + @Override + public WeightOfConscienceEffect copy() { + return new WeightOfConscienceEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Permanent enchantment = game.getPermanentOrLKIBattlefield(source.getSourceId()); + if (controller != null && enchantment != null && enchantment.getAttachedTo() != null) { + Permanent creature = game.getPermanent(enchantment.getAttachedTo()); + if (creature != null) { + controller.moveCardsToExile(creature, source, game, true, null, ""); + } + } + return false; + } +} + +class WeightOfConscienceTarget extends TargetControlledCreaturePermanent { + + private static final FilterControlledCreaturePermanent filterUntapped = new FilterControlledCreaturePermanent("untapped creatures you control that share a creature type"); + static { + filterUntapped.add(Predicates.not(new TappedPredicate())); + } + + WeightOfConscienceTarget() { + super(2, 2, filterUntapped, true); + } + + WeightOfConscienceTarget(final WeightOfConscienceTarget target) { + super(target); + } + + @Override + public Set possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) { + Player player = game.getPlayer(sourceControllerId); + Set possibleTargets = new HashSet<>(0); + if (player != null) { + // Choosing first target + if (this.getTargets().isEmpty()) { + for (Permanent permanent : game.getBattlefield().getActivePermanents(filterUntapped, sourceControllerId, game)) { + for (String subtype : permanent.getSubtype()) { + if (!CardUtil.isNonCreatureSubtype(subtype)) { + if (game.getBattlefield().contains(new FilterControlledCreaturePermanent(subtype, subtype), sourceControllerId, game, 2)) { + possibleTargets.add(permanent.getId()); + } + } + } + } + } + // Choosing second target + else { + UUID firstTargetId = this.getTargets().get(0); + Permanent firstTargetCreature = game.getPermanent(firstTargetId); + if (firstTargetCreature != null) { + for (Permanent permanent : game.getBattlefield().getActivePermanents(filterUntapped, sourceControllerId, game)) { + if (!permanent.getId().equals(firstTargetId) && CardUtil.shareSubtypes(firstTargetCreature, permanent)) { + possibleTargets.add(permanent.getId()); + } + } + } + } + } + return possibleTargets; + } + + @Override + public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) { + for (Permanent permanent1 : game.getBattlefield().getActivePermanents(filterUntapped, sourceControllerId, game)) { + for (Permanent permanent2 : game.getBattlefield().getActivePermanents(filterUntapped, sourceControllerId, game)) { + if (permanent1 != permanent2 && CardUtil.shareSubtypes(permanent1, permanent2)) { + return true; + } + } + } + return false; + } + + @Override + public boolean canTarget(UUID id, Ability source, Game game) { + if (super.canTarget(id, game)) { + Permanent targetPermanent = game.getPermanent(id); + if (targetPermanent != null) { + if (this.getTargets().isEmpty()) { + for (Permanent permanent : game.getBattlefield().getActivePermanents(filterUntapped, source.getControllerId(), game)) { + for (String subtype : permanent.getSubtype()) { + if (!CardUtil.isNonCreatureSubtype(subtype)) { + if (game.getBattlefield().contains(new FilterControlledCreaturePermanent(subtype, subtype), source.getControllerId(), game, 2)) { + return true; + } + } + } + } + } + else { + Permanent firstTarget = game.getPermanent(this.getTargets().get(0)); + if (firstTarget != null && CardUtil.shareSubtypes(firstTarget, targetPermanent)) { + return true; + } + } + } + } + return false; + } + + @Override + public WeightOfConscienceTarget copy() { + return new WeightOfConscienceTarget(this); + } +} diff --git a/Mage.Sets/src/mage/sets/planarchaos/Torchling.java b/Mage.Sets/src/mage/sets/planarchaos/Torchling.java new file mode 100644 index 00000000000..97f0d073c55 --- /dev/null +++ b/Mage.Sets/src/mage/sets/planarchaos/Torchling.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.planarchaos; + +import java.util.UUID; + +/** + * + * @author emerald000 + */ +public class Torchling extends mage.sets.venservskoth.Torchling { + + public Torchling(UUID ownerId) { + super(ownerId); + this.cardNumber = 110; + this.expansionSetCode = "PLC"; + } + + public Torchling(final Torchling card) { + super(card); + } + + @Override + public Torchling copy() { + return new Torchling(this); + } +} diff --git a/Mage.Sets/src/mage/sets/venservskoth/Torchling.java b/Mage.Sets/src/mage/sets/venservskoth/Torchling.java new file mode 100644 index 00000000000..28f400a5f57 --- /dev/null +++ b/Mage.Sets/src/mage/sets/venservskoth/Torchling.java @@ -0,0 +1,138 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.venservskoth; + +import java.util.UUID; +import mage.MageInt; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.SpellAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ColoredManaCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.ChooseNewTargetsTargetEffect; +import mage.abilities.effects.common.UntapSourceEffect; +import mage.abilities.effects.common.combat.MustBeBlockedByTargetSourceEffect; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.ColoredManaSymbol; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.FilterSpell; +import mage.filter.predicate.Predicate; +import mage.game.Game; +import mage.game.stack.Spell; +import mage.target.Target; +import mage.target.TargetSpell; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author emerald000 + */ +public class Torchling extends CardImpl { + + public Torchling(UUID ownerId) { + super(ownerId, 58, "Torchling", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{3}{R}{R}"); + this.expansionSetCode = "DDI"; + this.subtype.add("Shapeshifter"); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // {R}: Untap Torchling. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new UntapSourceEffect(), new ColoredManaCost(ColoredManaSymbol.R))); + + // {R}: Target creature blocks Torchling this turn if able. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new MustBeBlockedByTargetSourceEffect(), new ColoredManaCost(ColoredManaSymbol.R)); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + + // {R}: Change the target of target spell that targets only Torchling. + ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ChooseNewTargetsTargetEffect(true, true), new ColoredManaCost(ColoredManaSymbol.R)); + FilterSpell filter = new FilterSpell("spell that targets only " + this.getName()); + filter.add(new TorchlingTargetPredicate(this.getId())); + ability.addTarget(new TargetSpell(filter)); + this.addAbility(ability); + + // {1}: Torchling gets +1/-1 until end of turn. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostSourceEffect(1, -1, Duration.EndOfTurn), new GenericManaCost(1))); + + // {1}: Torchling gets -1/+1 until end of turn. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostSourceEffect(-1, 1, Duration.EndOfTurn), new GenericManaCost(1))); + } + + public Torchling(final Torchling card) { + super(card); + } + + @Override + public Torchling copy() { + return new Torchling(this); + } +} + +class TorchlingTargetPredicate implements Predicate { + + private final UUID sourceId; + + TorchlingTargetPredicate(UUID sourceId) { + this.sourceId = sourceId; + } + + @Override + public boolean apply(MageObject input, Game game) { + Spell spell = game.getStack().getSpell(input.getId()); + if (spell != null) { + int numberOfTargets = 0; + for (SpellAbility spellAbility : spell.getSpellAbilities()) { + for (Mode mode : spellAbility.getModes().getSelectedModes()) { + for (Target target : mode.getTargets()) { + for (UUID targetId : target.getTargets()) { + if (!targetId.equals(sourceId)) { + return false; + } + else { + numberOfTargets++; + } + } + } + } + } + return numberOfTargets > 0; + } + return false; + } + + @Override + public String toString() { + return "target spell that targets only {this}"; + } +}