diff --git a/Mage.Sets/src/mage/sets/khansoftarkir/CleverImpersonator.java b/Mage.Sets/src/mage/sets/khansoftarkir/CleverImpersonator.java new file mode 100644 index 0000000000..fdc6412b1e --- /dev/null +++ b/Mage.Sets/src/mage/sets/khansoftarkir/CleverImpersonator.java @@ -0,0 +1,71 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.khansoftarkir; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.EntersBattlefieldEffect; +import mage.abilities.effects.common.CopyPermanentEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterNonlandPermanent; + +/** + * + * @author emerald000 + */ +public class CleverImpersonator extends CardImpl { + + public CleverImpersonator(UUID ownerId) { + super(ownerId, 34, "Clever Impersonator", Rarity.MYTHIC, new CardType[]{CardType.CREATURE}, "{2}{U}{U}"); + this.expansionSetCode = "KTK"; + this.subtype.add("Shapeshifter"); + + this.color.setBlue(true); + this.power = new MageInt(0); + this.toughness = new MageInt(0); + + // You have may Clever Impersonator enter the battlefield as a copy of any nonland permanent on the battlefield. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, + new EntersBattlefieldEffect(new CopyPermanentEffect(new FilterNonlandPermanent()), + "You may have {this} enter the battlefield as a copy of any nonland permanent on the battlefield", + true))); + } + + public CleverImpersonator(final CleverImpersonator card) { + super(card); + } + + @Override + public CleverImpersonator copy() { + return new CleverImpersonator(this); + } +} diff --git a/Mage.Sets/src/mage/sets/khansoftarkir/DragonsEyeSavants.java b/Mage.Sets/src/mage/sets/khansoftarkir/DragonsEyeSavants.java new file mode 100644 index 0000000000..e6511d1397 --- /dev/null +++ b/Mage.Sets/src/mage/sets/khansoftarkir/DragonsEyeSavants.java @@ -0,0 +1,87 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.khansoftarkir; + +import java.util.UUID; +import mage.MageInt; +import mage.ObjectColor; +import mage.abilities.Ability; +import mage.abilities.common.TurnedFaceUpTriggeredAbility; +import mage.abilities.costs.common.RevealTargetFromHandCost; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.LookAtTargetPlayerHandEffect; +import mage.abilities.keyword.MorphAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.FilterCard; +import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.common.TargetCardInHand; +import mage.target.common.TargetOpponent; + +/** + * + * @author emerald000 + */ +public class DragonsEyeSavants extends CardImpl { + + private final static FilterCard filter = new FilterCard("a blue card in your hand"); + static { + filter.add(new ColorPredicate(ObjectColor.BLUE)); + } + + public DragonsEyeSavants(UUID ownerId) { + super(ownerId, 38, "Dragon's Eye Savants", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{1}{U}"); + this.expansionSetCode = "KTK"; + this.subtype.add("Human"); + this.subtype.add("Wizard"); + + this.color.setBlue(true); + this.power = new MageInt(0); + this.toughness = new MageInt(6); + + // Morph - Reveal a blue card in your hand. + this.addAbility(new MorphAbility(this, new RevealTargetFromHandCost(new TargetCardInHand(filter)))); + + // When Dragon's Eye Savants is turned face up, look at target opponent's hand. + Effect effect = new LookAtTargetPlayerHandEffect(); + effect.setText("look at target opponent's hand"); + Ability ability = new TurnedFaceUpTriggeredAbility(effect); + ability.addTarget(new TargetOpponent()); + this.addAbility(ability); + } + + public DragonsEyeSavants(final DragonsEyeSavants card) { + super(card); + } + + @Override + public DragonsEyeSavants copy() { + return new DragonsEyeSavants(this); + } +} diff --git a/Mage.Sets/src/mage/sets/khansoftarkir/IcyBlast.java b/Mage.Sets/src/mage/sets/khansoftarkir/IcyBlast.java new file mode 100644 index 0000000000..e934363185 --- /dev/null +++ b/Mage.Sets/src/mage/sets/khansoftarkir/IcyBlast.java @@ -0,0 +1,87 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.khansoftarkir; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.SpellAbility; +import mage.abilities.condition.common.FerociousCondition; +import mage.abilities.decorator.ConditionalContinuousRuleModifyingEffect; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.SkipNextUntapTargetEffect; +import mage.abilities.effects.common.TapTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.common.FilterCreaturePermanent; +import mage.game.Game; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author emerald000 + */ +public class IcyBlast extends CardImpl { + + public IcyBlast(UUID ownerId) { + super(ownerId, 42, "Icy Blast", Rarity.RARE, new CardType[]{CardType.INSTANT}, "{X}{U}"); + this.expansionSetCode = "KTK"; + + this.color.setBlue(true); + + // Tap X target creatures. + this.getSpellAbility().addEffect(new TapTargetEffect("X target creatures")); + this.getSpellAbility().addTarget(new TargetCreaturePermanent(0, 1, new FilterCreaturePermanent(), false)); + + // Ferocious - If you control a creature with power 4 or greater, those creatures don't untap during their controllers' next untap steps. + Effect effect = new ConditionalContinuousRuleModifyingEffect( + new SkipNextUntapTargetEffect(), + FerociousCondition.getInstance()); + effect.setText("

Ferocious - If you control a creature with power 4 or greater, those creatures don't untap during their controllers' next untap steps"); + this.getSpellAbility().addEffect(effect); + } + + public IcyBlast(final IcyBlast card) { + super(card); + } + + @Override + public void adjustTargets(Ability ability, Game game) { + if (ability instanceof SpellAbility) { + ability.getTargets().clear(); + int numberToTap = ability.getManaCostsToPay().getX(); + numberToTap = Math.min(game.getBattlefield().count(new FilterCreaturePermanent(), ability.getSourceId(), ability.getControllerId(), game), numberToTap); + ability.addTarget(new TargetCreaturePermanent(numberToTap)); + } + } + + @Override + public IcyBlast copy() { + return new IcyBlast(this); + } +} diff --git a/Mage.Sets/src/mage/sets/khansoftarkir/KheruSpellsnatcher.java b/Mage.Sets/src/mage/sets/khansoftarkir/KheruSpellsnatcher.java new file mode 100644 index 0000000000..39aa519fcb --- /dev/null +++ b/Mage.Sets/src/mage/sets/khansoftarkir/KheruSpellsnatcher.java @@ -0,0 +1,170 @@ +/* + * 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.khansoftarkir; + +import java.util.UUID; +import mage.MageInt; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.common.TurnedFaceUpTriggeredAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.AsThoughEffectImpl; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.MorphAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.constants.AsThoughEffectType; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.stack.Spell; +import mage.game.stack.StackObject; +import mage.players.Player; +import mage.target.TargetSpell; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author emerald000 + */ +public class KheruSpellsnatcher extends CardImpl { + + public KheruSpellsnatcher(UUID ownerId) { + super(ownerId, 45, "Kheru Spellsnatcher", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{3}{U}"); + this.expansionSetCode = "KTK"; + this.subtype.add("Naga"); + this.subtype.add("Wizard"); + + this.color.setBlue(true); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Morph {4}{U}{U} + this.addAbility(new MorphAbility(this, new ManaCostsImpl<>("{4}{U}{U}"))); + + // When Kheru Spellthief is turned face up, counter target spell. If that spell is countered this way, exile it instead of putting it into its owner's graveyard. You may cast that card without paying its mana cost as long as it remains exiled. + Ability ability = new TurnedFaceUpTriggeredAbility(new KheruSpellsnatcherEffect()); + ability.addTarget(new TargetSpell()); + this.addAbility(ability); + } + + public KheruSpellsnatcher(final KheruSpellsnatcher card) { + super(card); + } + + @Override + public KheruSpellsnatcher copy() { + return new KheruSpellsnatcher(this); + } +} + +class KheruSpellsnatcherEffect extends OneShotEffect { + + KheruSpellsnatcherEffect() { + super(Outcome.Benefit); + this.staticText = "counter target spell. If that spell is countered this way, exile it instead of putting it into its owner's graveyard. You may cast that card without paying its mana cost as long as it remains exiled"; + } + + KheruSpellsnatcherEffect(final KheruSpellsnatcherEffect effect) { + super(effect); + } + + @Override + public KheruSpellsnatcherEffect copy() { + return new KheruSpellsnatcherEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + UUID objectId = targetPointer.getFirst(game, source); + UUID sourceId = source.getSourceId(); + + StackObject stackObject = game.getStack().getStackObject(objectId); + if (stackObject != null && !game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.COUNTER, objectId, sourceId, stackObject.getControllerId()))) { + game.rememberLKI(objectId, Zone.STACK, stackObject); + game.getStack().remove(stackObject); + if (!((Spell) stackObject).isCopiedSpell()) { + MageObject card = game.getObject(stackObject.getSourceId()); + if (card instanceof Card) { + ((Card) card).moveToZone(Zone.EXILED, sourceId, game, true); + ContinuousEffect effect = new KheruSpellsnatcherCastFromExileEffect(); + effect.setTargetPointer(new FixedTarget(card.getId())); + game.addEffect(effect, source); + } + } + game.fireEvent(GameEvent.getEvent(GameEvent.EventType.COUNTERED, objectId, sourceId, stackObject.getControllerId())); + return true; + } + return false; + } +} + +class KheruSpellsnatcherCastFromExileEffect extends AsThoughEffectImpl { + + KheruSpellsnatcherCastFromExileEffect() { + super(AsThoughEffectType.CAST_FROM_NON_HAND_ZONE, Duration.Custom, Outcome.Benefit); + staticText = "You may cast that card without paying its mana cost as long as it remains exiled"; + } + + KheruSpellsnatcherCastFromExileEffect(final KheruSpellsnatcherCastFromExileEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public KheruSpellsnatcherCastFromExileEffect copy() { + return new KheruSpellsnatcherCastFromExileEffect(this); + } + + @Override + public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) { + if (getTargetPointer().getFirst(game, source).equals(sourceId) && affectedControllerId.equals(source.getControllerId())) { + Card card = game.getCard(sourceId); + if (card != null) { + if (game.getState().getZone(sourceId) == Zone.EXILED) { + Player player = game.getPlayer(affectedControllerId); + player.setCastSourceIdWithoutMana(sourceId); + return true; + } + else { + this.discard(); + } + } + } + return false; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/khansoftarkir/SuspensionField.java b/Mage.Sets/src/mage/sets/khansoftarkir/SuspensionField.java new file mode 100644 index 0000000000..cf72a4def9 --- /dev/null +++ b/Mage.Sets/src/mage/sets/khansoftarkir/SuspensionField.java @@ -0,0 +1,181 @@ +/* + * 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.khansoftarkir; + +import java.util.LinkedList; +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ExileTargetEffect; +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.Filter.ComparisonType; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.ToughnessPredicate; +import mage.game.ExileZone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.ZoneChangeEvent; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author emerald000 + */ +public class SuspensionField extends CardImpl { + + private final static FilterCreaturePermanent filter = new FilterCreaturePermanent("creature with toughness 3 or greater"); + static { + filter.add(new ToughnessPredicate(ComparisonType.GreaterThan, 2)); + } + + public SuspensionField(UUID ownerId) { + super(ownerId, 25, "Suspension Field", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}"); + this.expansionSetCode = "KTK"; + + this.color.setWhite(true); + + // When Suspension Field enters the battlefield, you may exile target creature with toughness 3 or greater until Suspension Field leaves the battlefield. + Ability ability = new EntersBattlefieldTriggeredAbility(new SuspensionFieldExileEffect()); + ability.addTarget(new TargetCreaturePermanent(filter)); + this.addAbility(ability); + // Implemented as triggered effect that doesn't uses the stack (implementation with watcher does not work correctly because if the returned creature + // has a DiesTriggeredAll ability it triggers for the dying / battlefield leaving source object, what shouldn't happen) + this.addAbility(new SuspensionFieldReturnExiledAbility()); + } + + public SuspensionField(final SuspensionField card) { + super(card); + } + + @Override + public SuspensionField copy() { + return new SuspensionField(this); + } +} + +class SuspensionFieldExileEffect extends OneShotEffect { + + SuspensionFieldExileEffect() { + super(Outcome.Exile); + this.staticText = "you may exile target creature with toughness 3 or greater until {this} leaves the battlefield. (That creature returns under its owner's control.)"; + } + + SuspensionFieldExileEffect(final SuspensionFieldExileEffect effect) { + super(effect); + } + + @Override + public SuspensionFieldExileEffect copy() { + return new SuspensionFieldExileEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent sourcePermanent = game.getPermanent(source.getSourceId()); + // If Suspension Field leaves the battlefield before its triggered ability resolves, the target won't be exiled. + if (sourcePermanent != null) { + return new ExileTargetEffect(source.getSourceId(), sourcePermanent.getName()).apply(game, source); + } + return false; + } +} + +class SuspensionFieldReturnExiledAbility extends TriggeredAbilityImpl { + + SuspensionFieldReturnExiledAbility() { + super(Zone.BATTLEFIELD, new SuspensionFieldReturnExiledCreatureEffect()); + this.usesStack = false; + this.setRuleVisible(false); + } + + SuspensionFieldReturnExiledAbility(final SuspensionFieldReturnExiledAbility ability) { + super(ability); + } + + @Override + public SuspensionFieldReturnExiledAbility copy() { + return new SuspensionFieldReturnExiledAbility(this); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getType() == GameEvent.EventType.ZONE_CHANGE && event.getTargetId().equals(this.getSourceId())) { + ZoneChangeEvent zEvent = (ZoneChangeEvent) event; + if (zEvent.getFromZone() == Zone.BATTLEFIELD) { + return true; + } + } + return false; + } +} + +class SuspensionFieldReturnExiledCreatureEffect extends OneShotEffect { + + SuspensionFieldReturnExiledCreatureEffect() { + super(Outcome.Benefit); + this.staticText = "Return exiled permanent"; + } + + SuspensionFieldReturnExiledCreatureEffect(final SuspensionFieldReturnExiledCreatureEffect effect) { + super(effect); + } + + @Override + public SuspensionFieldReturnExiledCreatureEffect copy() { + return new SuspensionFieldReturnExiledCreatureEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + ExileZone exile = game.getExile().getExileZone(source.getSourceId()); + Card sourceCard = game.getCard(source.getSourceId()); + if (exile != null && sourceCard != null) { + LinkedList cards = new LinkedList<>(exile); + for (UUID cardId : cards) { + Card card = game.getCard(cardId); + card.moveToZone(Zone.BATTLEFIELD, source.getSourceId(), game, false); + game.informPlayers(new StringBuilder(sourceCard.getName()).append(": ").append(card.getName()).append(" returns to battlefield from exile").toString()); + } + exile.clear(); + return true; + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/khansoftarkir/WatcherOfTheRoost.java b/Mage.Sets/src/mage/sets/khansoftarkir/WatcherOfTheRoost.java new file mode 100644 index 0000000000..9544fedc03 --- /dev/null +++ b/Mage.Sets/src/mage/sets/khansoftarkir/WatcherOfTheRoost.java @@ -0,0 +1,87 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.khansoftarkir; + +import java.util.UUID; +import mage.MageInt; +import mage.ObjectColor; +import mage.abilities.common.TurnedFaceUpTriggeredAbility; +import mage.abilities.costs.common.RevealTargetFromHandCost; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.MorphAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.FilterCard; +import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.common.TargetCardInHand; + +/** + * + * @author emerald000 + */ +public class WatcherOfTheRoost extends CardImpl { + + private final static FilterCard filter = new FilterCard("a white card in your hand"); + static { + filter.add(new ColorPredicate(ObjectColor.WHITE)); + } + + public WatcherOfTheRoost(UUID ownerId) { + super(ownerId, 30, "Watcher of the Roost", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{2}{W}"); + this.expansionSetCode = "KTK"; + this.subtype.add("Bird"); + this.subtype.add("Soldier"); + + this.color.setWhite(true); + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Morph - Reveal a white card in your hand + this.addAbility(new MorphAbility(this, new RevealTargetFromHandCost(new TargetCardInHand(filter)))); + + // When Watcher of the Roost is turned face up, you gain 2 life. + Effect effect = new GainLifeEffect(2); + effect.setText("you gain 2 life"); + this.addAbility(new TurnedFaceUpTriggeredAbility(effect)); + } + + public WatcherOfTheRoost(final WatcherOfTheRoost card) { + super(card); + } + + @Override + public WatcherOfTheRoost copy() { + return new WatcherOfTheRoost(this); + } +} diff --git a/Mage.Sets/src/mage/sets/khansoftarkir/WingmateRoc.java b/Mage.Sets/src/mage/sets/khansoftarkir/WingmateRoc.java new file mode 100644 index 0000000000..156cc933b8 --- /dev/null +++ b/Mage.Sets/src/mage/sets/khansoftarkir/WingmateRoc.java @@ -0,0 +1,92 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.khansoftarkir; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.abilityword.RaidAbility; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.dynamicvalue.common.AttackingCreatureCount; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.game.permanent.token.Token; + +/** + * + * @author emerald000 + */ +public class WingmateRoc extends CardImpl { + + public WingmateRoc(UUID ownerId) { + super(ownerId, 31, "Wingmate Roc", Rarity.MYTHIC, new CardType[]{CardType.CREATURE}, "{3}{W}{W}"); + this.expansionSetCode = "KTK"; + this.subtype.add("Bird"); + + this.color.setWhite(true); + this.power = new MageInt(3); + this.toughness = new MageInt(4); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Raid - When Wingmate Roc enters the battlefield, if you attacked with a creature this turn, put a 3/4 white Bird creature token with flying onto the battlefield. + this.addAbility(new RaidAbility(this, new CreateTokenEffect(new WingmateRocToken()))); + + // Whenever Wingmate Roc attacks, you gain 1 life for each attacking creature. + Effect effect = new GainLifeEffect(new AttackingCreatureCount()); + effect.setText("you gain 1 life for each attacking creature"); + this.addAbility(new AttacksTriggeredAbility(effect, false)); + } + + public WingmateRoc(final WingmateRoc card) { + super(card); + } + + @Override + public WingmateRoc copy() { + return new WingmateRoc(this); + } +} + +class WingmateRocToken extends Token { + + WingmateRocToken() { + super("Bird", "3/4 white Bird creature token with flying"); + cardType.add(CardType.CREATURE); + subtype.add("Bird"); + color.setWhite(true); + power = new MageInt(3); + toughness = new MageInt(4); + addAbility(FlyingAbility.getInstance()); + } +} diff --git a/Mage/src/mage/abilities/effects/common/CounterTargetWithReplacementEffect.java b/Mage/src/mage/abilities/effects/common/CounterTargetWithReplacementEffect.java index e33d8b7511..2931b7114b 100644 --- a/Mage/src/mage/abilities/effects/common/CounterTargetWithReplacementEffect.java +++ b/Mage/src/mage/abilities/effects/common/CounterTargetWithReplacementEffect.java @@ -27,20 +27,18 @@ */ package mage.abilities.effects.common; -import mage.abilities.Mode; -import mage.game.stack.Spell; +import java.util.UUID; import mage.MageObject; import mage.abilities.Ability; +import mage.abilities.Mode; import mage.abilities.effects.OneShotEffect; import mage.cards.Card; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.stack.StackObject; - -import java.util.UUID; - import mage.constants.Outcome; import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.stack.Spell; +import mage.game.stack.StackObject; /** * @author nantuko, North @@ -83,9 +81,9 @@ public class CounterTargetWithReplacementEffect extends OneShotEffect { StackObject stackObject = game.getStack().getStackObject(objectId); if (stackObject != null && !game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.COUNTER, objectId, sourceId, stackObject.getControllerId()))) { - boolean spell =false; + boolean spell = false; if (stackObject instanceof Spell) { - game.rememberLKI(objectId, Zone.STACK, (Spell) stackObject); + game.rememberLKI(objectId, Zone.STACK, stackObject); spell = true; } game.getStack().remove(stackObject);