diff --git a/Mage.Sets/src/mage/sets/magicorigins/NissaSageAnimist.java b/Mage.Sets/src/mage/sets/magicorigins/NissaSageAnimist.java new file mode 100644 index 00000000000..ff93fac4615 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/NissaSageAnimist.java @@ -0,0 +1,198 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.LoyaltyAbility; +import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.UntapTargetEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardsImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Layer; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.SubLayer; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.filter.common.FilterLandPermanent; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.game.permanent.token.Token; +import mage.players.Player; +import mage.target.common.TargetLandPermanent; + +/** + * + * @author emerald000 + */ +public class NissaSageAnimist extends CardImpl { + + public NissaSageAnimist(UUID ownerId) { + super(ownerId, 189, "Nissa, Sage Animist", Rarity.MYTHIC, new CardType[]{CardType.PLANESWALKER}, ""); + this.expansionSetCode = "ORI"; + this.subtype.add("Nissa"); + this.color.setGreen(true); + + this.nightCard = true; + this.canTransform = true; + + this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.LOYALTY.createInstance(3)), false)); + + // +1: Reveal the top card of your library. If it's a land card, put it onto the battlefield. Otherwise, put it into your hand. + this.addAbility(new LoyaltyAbility(new NissaSageAnimistPlusOneEffect(), 1)); + + // -2: Put a legendary 4/4 green Elemental creature token named Ashaya, the Awoken World onto the battlefield. + this.addAbility(new LoyaltyAbility(new CreateTokenEffect(new NissaSageAnimistToken()), -2)); + + // -7: Untap up to six target lands. They become 6/6 Elemental creatures. They're still lands. + Ability ability = new LoyaltyAbility(new UntapTargetEffect(), -7); + ability.addTarget(new TargetLandPermanent(0, 6, new FilterLandPermanent("lands"), false)); + ability.addEffect(new NissaSageAnimistMinusSevenEffect()); + this.addAbility(ability); + } + + public NissaSageAnimist(final NissaSageAnimist card) { + super(card); + } + + @Override + public NissaSageAnimist copy() { + return new NissaSageAnimist(this); + } +} + +class NissaSageAnimistPlusOneEffect extends OneShotEffect { + + NissaSageAnimistPlusOneEffect() { + super(Outcome.Benefit); + this.staticText = "Reveal the top card of your library. If it's a land card, put it onto the battlefield. Otherwise, put it into your hand."; + } + + NissaSageAnimistPlusOneEffect(final NissaSageAnimistPlusOneEffect effect) { + super(effect); + } + + @Override + public NissaSageAnimistPlusOneEffect copy() { + return new NissaSageAnimistPlusOneEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null && controller.getLibrary().size() > 0) { + Card card = controller.getLibrary().getFromTop(game); + if (card == null) { + return false; + } + CardsImpl cards = new CardsImpl(); + cards.add(card); + controller.revealCards("Nissa, Sage Animist", cards, game); + if (card.getCardType().contains(CardType.LAND)) { + return controller.putOntoBattlefieldWithInfo(card, game, Zone.LIBRARY, source.getSourceId()); + } else { + return controller.moveCards(card, Zone.LIBRARY, Zone.HAND, source, game); + } + } + return true; + } +} + +class NissaSageAnimistToken extends Token { + + NissaSageAnimistToken() { + super("Ashaya, the Awoken World", "legendary 4/4 green Elemental creature token named Ashaya, the Awoken World"); + this.setOriginalExpansionSetCode("ORI"); + this.getSupertype().add("Legendary"); + this.getPower().initValue(4); + this.getToughness().initValue(4); + this.color.setGreen(true); + this.getSubtype().add("Elemental"); + this.getCardType().add(CardType.CREATURE); + } +} + +class NissaSageAnimistMinusSevenEffect extends ContinuousEffectImpl { + + NissaSageAnimistMinusSevenEffect() { + super(Duration.EndOfGame, Outcome.BecomeCreature); + this.staticText = "They become 6/6 Elemental creatures. They're still lands"; + } + + NissaSageAnimistMinusSevenEffect(final NissaSageAnimistMinusSevenEffect effect) { + super(effect); + } + + @Override + public NissaSageAnimistMinusSevenEffect copy() { + return new NissaSageAnimistMinusSevenEffect(this); + } + + @Override + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + for (UUID permanentId : this.getTargetPointer().getTargets(game, source)) { + Permanent permanent = game.getPermanent(permanentId); + if (permanent != null) { + switch (layer) { + case TypeChangingEffects_4: + if (!permanent.getCardType().contains(CardType.CREATURE)) { + permanent.getCardType().add(CardType.CREATURE); + } + if (!permanent.getSubtype().contains("Elemental")) { + permanent.getSubtype().add("Elemental"); + } + break; + case PTChangingEffects_7: + if (sublayer == SubLayer.SetPT_7b) { + permanent.getToughness().setValue(6); + permanent.getPower().setValue(6); + } + } + } + } + return true; + } + + @Override + public boolean apply(Game game, Ability source) { + return false; + } + + @Override + public boolean hasLayer(Layer layer) { + return layer == Layer.TypeChangingEffects_4 || layer == Layer.PTChangingEffects_7; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/magicorigins/NissaVastwoodSeer.java b/Mage.Sets/src/mage/sets/magicorigins/NissaVastwoodSeer.java new file mode 100644 index 00000000000..22ef98bc763 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/NissaVastwoodSeer.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.sets.magicorigins; + +import java.util.UUID; +import mage.MageInt; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition.CountType; +import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect; +import mage.abilities.keyword.TransformAbility; +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.FilterCard; +import mage.filter.common.FilterLandPermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.filter.predicate.mageobject.SupertypePredicate; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetCardInLibrary; + +/** + * + * @author emerald000 + */ +public class NissaVastwoodSeer extends CardImpl { + + private static final FilterCard filter = new FilterCard("basic Forest card"); + static { + filter.add(new SupertypePredicate("Basic")); + filter.add(new SubtypePredicate("Forest")); + } + + public NissaVastwoodSeer(UUID ownerId) { + super(ownerId, 189, "Nissa, Vastwood Seer", Rarity.MYTHIC, new CardType[]{CardType.CREATURE}, "{2}{G}"); + this.expansionSetCode = "ORI"; + this.supertype.add("Legendary"); + this.subtype.add("Elf"); + this.subtype.add("Scout"); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + this.canTransform = true; + this.secondSideCard = new NissaSageAnimist(ownerId); + + // When Nissa, Vastwood Seer enters the battlefield, you may search your library for a basic Forest card, reveal it, put it into your hand, then shuffle your library. + this.addAbility(new EntersBattlefieldTriggeredAbility(new SearchLibraryPutInHandEffect(new TargetCardInLibrary(0, 1, filter), true, true), true)); + + // Whenever a land enters the battlefield under your control, if you control seven or more lands, exile Nissa, then return her to the battlefield transformed under her owner's control. + this.addAbility(new TransformAbility()); + this.addAbility(new ConditionalTriggeredAbility( + new EntersBattlefieldControlledTriggeredAbility(new NissaVastwoodSeerTransformEffect(), new FilterLandPermanent()), + new PermanentsOnTheBattlefieldCondition(new FilterLandPermanent(), CountType.MORE_THAN, 6, true), + "Whenever a land enters the battlefield under your control, if you control seven or more lands, exile {this}, then return her to the battlefield transformed under her owner's control.")); + } + + public NissaVastwoodSeer(final NissaVastwoodSeer card) { + super(card); + } + + @Override + public NissaVastwoodSeer copy() { + return new NissaVastwoodSeer(this); + } +} + +class NissaVastwoodSeerTransformEffect extends OneShotEffect { + + NissaVastwoodSeerTransformEffect() { + super(Outcome.Benefit); + this.staticText = "exile {this}, then return her to the battlefield transformed under her owner's control"; + } + + NissaVastwoodSeerTransformEffect(final NissaVastwoodSeerTransformEffect effect) { + super(effect); + } + + @Override + public NissaVastwoodSeerTransformEffect copy() { + return new NissaVastwoodSeerTransformEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + MageObject sourceObject = source.getSourceObjectIfItStillExists(game); + Player controller = game.getPlayer(source.getControllerId()); + if (sourceObject != null && controller != null) { + Card card = (Card) sourceObject; + if (controller.moveCards(card, Zone.BATTLEFIELD, Zone.EXILED, source, game)) { + game.getState().setValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + source.getSourceId(), Boolean.TRUE); + controller.putOntoBattlefieldWithInfo(card, game, Zone.EXILED, source.getSourceId()); + } + } + return true; + } +} \ No newline at end of file diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/TransformTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/TransformTest.java new file mode 100644 index 00000000000..1aa83fc7929 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/TransformTest.java @@ -0,0 +1,68 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package org.mage.test.cards.abilities.keywords; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import mage.counters.CounterType; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ + +public class TransformTest extends CardTestPlayerBase{ + + @Test + public void NissaVastwoodSeerTest() { + + addCard(Zone.LIBRARY, playerA, "Forest"); + + addCard(Zone.BATTLEFIELD, playerA, "Forest", 6); + // When Nissa, Vastwood Seer enters the battlefield, you may search your library for a basic Forest card, reveal it, put it into your hand, then shuffle your library. + // Whenever a land enters the battlefield under your control, if you control seven or more lands, exile Nissa, then return her to the battlefield transformed under her owner's control. + + addCard(Zone.HAND, playerA, "Nissa, Vastwood Seer"); + + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Nissa, Vastwood Seer"); + playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Forest"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPermanentCount(playerA, "Forest", 7); + + assertPermanentCount(playerA, "Nissa, Vastwood Seer", 0); + assertPermanentCount(playerA, "Nissa, Sage Animist", 1); + assertCounterCount("Nissa, Sage Animist", CounterType.LOYALTY, 3); + } + +} \ No newline at end of file