diff --git a/Mage.Sets/src/mage/cards/h/HammerOfNazahn.java b/Mage.Sets/src/mage/cards/h/HammerOfNazahn.java new file mode 100644 index 0000000000..126584955d --- /dev/null +++ b/Mage.Sets/src/mage/cards/h/HammerOfNazahn.java @@ -0,0 +1,125 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.h; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.BoostEquippedEffect; +import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; +import mage.abilities.keyword.EquipAbility; +import mage.abilities.keyword.IndestructibleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.AttachmentType; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SetTargetPointer; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.constants.Zone; +import mage.filter.common.FilterEquipmentPermanent; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetControlledCreaturePermanent; + +/** + * + * @author Saga + */ +public class HammerOfNazahn extends CardImpl { + + private final static FilterEquipmentPermanent filter = new FilterEquipmentPermanent("{this} or another Equipment"); + + public HammerOfNazahn(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}"); + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.EQUIPMENT); + + // Whenever Hammer of Nazahn or another Equipment enters the battlefiend under your control, you may attach that Equipment to target creature you control. + Ability ability = new EntersBattlefieldControlledTriggeredAbility(Zone.BATTLEFIELD, new HammerOfNazahnEffect(), filter, true, SetTargetPointer.PERMANENT, ""); + ability.addTarget(new TargetControlledCreaturePermanent()); + this.addAbility(ability); + + // Equipped creature gets +2/+0 and has indestructible. + Ability abilityEquipped = new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(2, 0)); + Effect effect = new GainAbilityAttachedEffect(IndestructibleAbility.getInstance(), AttachmentType.EQUIPMENT); + effect.setText("and has indestructible"); + abilityEquipped.addEffect(effect); + this.addAbility(abilityEquipped); + + // Equip {4} + this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(4))); + + } + + public HammerOfNazahn(final HammerOfNazahn card) { + super(card); + } + + @Override + public HammerOfNazahn copy() { + return new HammerOfNazahn(this); + } +} + +class HammerOfNazahnEffect extends OneShotEffect { + + public HammerOfNazahnEffect() { + super(Outcome.Benefit); + this.staticText = "you may attach that Equipment to target creature you control"; + } + + public HammerOfNazahnEffect(final HammerOfNazahnEffect effect) { + super(effect); + } + + @Override + public HammerOfNazahnEffect copy() { + return new HammerOfNazahnEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + Permanent equipment = game.getPermanent(getTargetPointer().getFirst(game, source)); + Permanent targetCreature = game.getPermanent(source.getTargets().getFirstTarget()); + if (equipment != null && targetCreature != null) { + targetCreature.addAttachment(equipment.getId(), game); + } + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/h/HeirloomBlade.java b/Mage.Sets/src/mage/cards/h/HeirloomBlade.java new file mode 100644 index 0000000000..d268f73c28 --- /dev/null +++ b/Mage.Sets/src/mage/cards/h/HeirloomBlade.java @@ -0,0 +1,126 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.h; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.DiesAttachedTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.BoostEquippedEffect; +import mage.abilities.keyword.EquipAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.cards.Cards; +import mage.cards.CardsImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; + +/** + * + * @author Saga + */ +public class HeirloomBlade extends CardImpl { + + public HeirloomBlade(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); + this.subtype.add(SubType.EQUIPMENT); + + // Equipped creature gets +3/+1. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(3, 1))); + + // Whenever equipped creature dies, you may reveal cards from the top of your library until you reveal a creature card that shares a creature type with it. + // Put that card into your hand and the rest on the bottom of your library in a random order. + this.addAbility(new DiesAttachedTriggeredAbility(new HeirloomBladeEffect(), "equipped creature", true)); + + // Equip {1} + this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(1))); + + } + + public HeirloomBlade(final HeirloomBlade card) { + super(card); + } + + @Override + public HeirloomBlade copy() { + return new HeirloomBlade(this); + } +} + +class HeirloomBladeEffect extends OneShotEffect { + + public HeirloomBladeEffect() { + super(Outcome.PutCreatureInPlay); + this.staticText = "reveal cards from the top of your library until you reveal a creature card that shares a creature type with it. " + + "Put that card into your hand and the rest on the bottom of your library in a random order"; + } + + public HeirloomBladeEffect(final HeirloomBladeEffect effect) { + super(effect); + } + + @Override + public HeirloomBladeEffect copy() { + return new HeirloomBladeEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Permanent equipment = game.getPermanentOrLKIBattlefield(source.getSourceId()); + if (controller != null && equipment != null) { + Permanent equipped = (Permanent) getValue("attachedTo"); + if (equipped != null) { + Cards revealed = new CardsImpl(); + Cards otherCards = new CardsImpl(); + while (controller.getLibrary().hasCards()) { + Card card = controller.getLibrary().removeFromTop(game); + revealed.add(card); + if (card != null && card.isCreature() && equipped.shareSubtypes(card, game)) { + controller.moveCardToHandWithInfo(card, source.getSourceId(), game, true); + break; + } else { + otherCards.add(card); + } + } + controller.revealCards(equipment.getIdName(), revealed, game); + controller.putCardsOnBottomOfLibrary(otherCards, game, source, false); + return true; + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/s/ShiftingShadow.java b/Mage.Sets/src/mage/cards/s/ShiftingShadow.java new file mode 100644 index 0000000000..8a0e0bfc9a --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/ShiftingShadow.java @@ -0,0 +1,165 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.s; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.abilities.keyword.HasteAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.cards.Cards; +import mage.cards.CardsImpl; +import mage.constants.AttachmentType; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.permanent.PermanentIdPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.Target; +import mage.target.TargetPermanent; +import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author Saga + */ +public class ShiftingShadow extends CardImpl { + + public ShiftingShadow(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}"); + this.subtype.add(SubType.AURA); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.AddAbility)); + this.addAbility(new EnchantAbility(auraTarget.getTargetName())); + + // Enchanted creature has haste and “At the beginning of your upkeep, destroy this creature. Reveal cards from the top of your library until you reveal a creature card. + // Put that card onto the battlefield and attach Shifting Shadow to it, then put all other cards revealed this way on the bottom of your library in a random order.” + Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(HasteAbility.getInstance(), AttachmentType.AURA)); + Effect effect = new GainAbilityAttachedEffect(new BeginningOfUpkeepTriggeredAbility( + new ShiftingShadowEffect(this.getId()), TargetController.YOU, false), AttachmentType.AURA); + effect.setText("and \"At the beginning of your upkeep, destroy this creature. Reveal cards from the top of your library until you reveal a creature card. " + + "Put that card onto the battlefield and attach {this} to it, then put all other cards revealed this way on the bottom of your library in a random order.\""); + ability.addEffect(effect); + this.addAbility(ability); + } + + public ShiftingShadow(final ShiftingShadow card) { + super(card); + } + + @Override + public ShiftingShadow copy() { + return new ShiftingShadow(this); + } +} + +class ShiftingShadowEffect extends OneShotEffect { + + private UUID auraId; + + public ShiftingShadowEffect(UUID auraId) { + super(Outcome.PutCreatureInPlay); + this.staticText = "destroy this creature. Reveal cards from the top of your library until you reveal a creature card. " + + "Put that card onto the battlefield and attach Shifting Shadow to it, then put all other cards revealed this way on the bottom of your library in a random order"; + this.auraId = auraId; + } + + public ShiftingShadowEffect(final ShiftingShadowEffect effect, UUID auraId) { + super(effect); + this.auraId = auraId; + } + + @Override + public ShiftingShadowEffect copy() { + return new ShiftingShadowEffect(this, auraId); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Permanent enchanted = game.getPermanentOrLKIBattlefield(source.getSourceId()); + if (controller != null && enchanted != null) { + Permanent aura = null; + int index = 0; + while (aura == null && index < enchanted.getAttachments().size()) { + UUID attached = enchanted.getAttachments().get(index); + if (attached.equals(auraId)) { + aura = game.getPermanentOrLKIBattlefield(attached); + } else { + index += 1; + } + } + if (aura != null) { + enchanted.destroy(source.getSourceId(), game, false); + Cards revealed = new CardsImpl(); + Cards otherCards = new CardsImpl(); + while (controller.getLibrary().hasCards()) { + Card card = controller.getLibrary().removeFromTop(game); + revealed.add(card); + if (card != null && card.isCreature()) { + card.putOntoBattlefield(game, Zone.LIBRARY, source.getSourceId(), controller.getId()); + Permanent newEnchanted = game.getPermanent(card.getId()); + FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(); + filter.add(new PermanentIdPredicate(card.getId())); + Target target = new TargetControlledCreaturePermanent(filter); + if (newEnchanted != null) { + target.addTarget(newEnchanted.getId(), source, game); + aura.getSpellAbility().getTargets().clear(); + aura.getSpellAbility().getTargets().add(target); + newEnchanted.addAttachment(aura.getId(), game); + } + break; + } else { + otherCards.add(card); + } + } + controller.revealCards(enchanted.getIdName(), revealed, game); + controller.putCardsOnBottomOfLibrary(otherCards, game, source, false); + return true; + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/Commander2017.java b/Mage.Sets/src/mage/sets/Commander2017.java index fa523546c8..65065e1549 100644 --- a/Mage.Sets/src/mage/sets/Commander2017.java +++ b/Mage.Sets/src/mage/sets/Commander2017.java @@ -64,7 +64,9 @@ public class Commander2017 extends ExpansionSet { cards.add(new SetCardInfo("Fortunate Few", 4, Rarity.RARE, mage.cards.f.FortunateFew.class)); cards.add(new SetCardInfo("Fractured Identity", 37, Rarity.RARE, mage.cards.f.FracturedIdentity.class)); cards.add(new SetCardInfo("Galecaster Colossus", 10, Rarity.RARE, mage.cards.g.GalecasterColossus.class)); + cards.add(new SetCardInfo("Hammer of Nazahn", 51, Rarity.RARE, mage.cards.h.HammerOfNazahn.class)); cards.add(new SetCardInfo("Herald's Horn", 53, Rarity.UNCOMMON, mage.cards.h.HeraldsHorn.class)); + cards.add(new SetCardInfo("Heirloom Blade", 52, Rarity.UNCOMMON, mage.cards.h.HeirloomBlade.class)); cards.add(new SetCardInfo("Hungry Lynx", 31, Rarity.RARE, mage.cards.h.HungryLynx.class)); cards.add(new SetCardInfo("Inalla, Archmage Ritualist", 38, Rarity.MYTHIC, mage.cards.i.InallaArchmageRitualist.class)); cards.add(new SetCardInfo("Izzet Chemister", 26, Rarity.RARE, mage.cards.i.IzzetChemister.class)); @@ -87,6 +89,7 @@ public class Commander2017 extends ExpansionSet { cards.add(new SetCardInfo("Qasali Slingers", 33, Rarity.RARE, mage.cards.q.QasaliSlingers.class)); cards.add(new SetCardInfo("Ramos, Dragon Engine", 55, Rarity.MYTHIC, mage.cards.r.RamosDragonEngine.class)); cards.add(new SetCardInfo("Scalelord Reckoner", 6, Rarity.RARE, mage.cards.s.ScalelordReckoner.class)); + cards.add(new SetCardInfo("Shifting Shadow", 28, Rarity.RARE, mage.cards.s.ShiftingShadow.class)); cards.add(new SetCardInfo("Taigam, Ojutai Master", 46, Rarity.MYTHIC, mage.cards.t.TaigamOjutaiMaster.class)); cards.add(new SetCardInfo("Taigam, Sidisi's Hand", 47, Rarity.RARE, mage.cards.t.TaigamSidisisHand.class)); cards.add(new SetCardInfo("Teferi's Protection", 8, Rarity.RARE, mage.cards.t.TeferisProtection.class));