diff --git a/Mage.Sets/src/mage/cards/l/LocusOfEnlightenment.java b/Mage.Sets/src/mage/cards/l/LocusOfEnlightenment.java new file mode 100644 index 00000000000..62652921057 --- /dev/null +++ b/Mage.Sets/src/mage/cards/l/LocusOfEnlightenment.java @@ -0,0 +1,130 @@ +package mage.cards.l; + +import mage.abilities.Ability; +import mage.abilities.ActivatedAbility; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.common.CopyStackObjectEffect; +import mage.abilities.mana.ActivatedManaAbilityImpl; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.game.ExileZone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.game.stack.StackAbility; +import mage.util.CardUtil; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class LocusOfEnlightenment extends CardImpl { + + public LocusOfEnlightenment(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, ""); + + this.supertype.add(SuperType.LEGENDARY); + this.nightCard = true; + this.color.setBlue(true); + + // Locus of Enlightenment has each activated ability of the exiled cards used to craft it. You may activate each of those abilities only once each turn. + this.addAbility(new SimpleStaticAbility(new LocusOfEnlightenmentEffect())); + + // Whenever you activate an ability that isn't a mana ability, copy it. You may choose new targets for the copy. + this.addAbility(new LocusOfEnlightenmentTriggeredAbility()); + } + + private LocusOfEnlightenment(final LocusOfEnlightenment card) { + super(card); + } + + @Override + public LocusOfEnlightenment copy() { + return new LocusOfEnlightenment(this); + } +} + +class LocusOfEnlightenmentEffect extends ContinuousEffectImpl { + + LocusOfEnlightenmentEffect() { + super(Duration.WhileOnBattlefield, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.Benefit); + staticText = "{this} has each activated ability of the exiled cards " + + "used to craft it. You may activate each of those abilities only once each turn"; + } + + private LocusOfEnlightenmentEffect(final LocusOfEnlightenmentEffect effect) { + super(effect); + } + + @Override + public LocusOfEnlightenmentEffect copy() { + return new LocusOfEnlightenmentEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = source.getSourcePermanentIfItStillExists(game); + if (permanent == null) { + return false; + } + ExileZone exileZone = game + .getExile() + .getExileZone(CardUtil.getExileZoneId( + game, permanent.getId(), permanent.getZoneChangeCounter(game) - 2 + )); + if (exileZone == null) { + return false; + } + for (Card card : exileZone.getCards(game)) { + for (Ability ability : card.getAbilities(game)) { + if (!(ability instanceof ActivatedAbility)) { + continue; + } + ActivatedAbility copyAbility = (ActivatedAbility) ability.copy(); + copyAbility.setMaxActivationsPerTurn(1); + permanent.addAbility(copyAbility, source.getSourceId(), game); + } + } + return true; + } +} + +class LocusOfEnlightenmentTriggeredAbility extends TriggeredAbilityImpl { + + LocusOfEnlightenmentTriggeredAbility() { + super(Zone.BATTLEFIELD, new CopyStackObjectEffect().setText("copy it. You may choose new targets for the copy")); + this.setTriggerPhrase("Whenever you activate an ability that isn't a mana ability, "); + } + + private LocusOfEnlightenmentTriggeredAbility(final LocusOfEnlightenmentTriggeredAbility ability) { + super(ability); + } + + @Override + public LocusOfEnlightenmentTriggeredAbility copy() { + return new LocusOfEnlightenmentTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.ACTIVATED_ABILITY; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (!event.getPlayerId().equals(getControllerId())) { + return false; + } + StackAbility stackAbility = (StackAbility) game.getStack().getStackObject(event.getSourceId()); + if (stackAbility == null || stackAbility.getStackAbility() instanceof ActivatedManaAbilityImpl) { + return false; + } + this.getEffects().setValue("stackObject", stackAbility); + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/t/TheEnigmaJewel.java b/Mage.Sets/src/mage/cards/t/TheEnigmaJewel.java new file mode 100644 index 00000000000..4e38195731e --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TheEnigmaJewel.java @@ -0,0 +1,122 @@ +package mage.cards.t; + +import mage.ConditionalMana; +import mage.MageObject; +import mage.Mana; +import mage.abilities.Abilities; +import mage.abilities.Ability; +import mage.abilities.ActivatedAbilityImpl; +import mage.abilities.common.EntersBattlefieldTappedAbility; +import mage.abilities.condition.Condition; +import mage.abilities.costs.Cost; +import mage.abilities.keyword.CraftAbility; +import mage.abilities.mana.ConditionalColorlessManaAbility; +import mage.abilities.mana.builder.ConditionalManaBuilder; +import mage.abilities.mana.conditional.ManaCondition; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.AbilityType; +import mage.constants.CardType; +import mage.constants.SuperType; +import mage.filter.predicate.Predicate; +import mage.game.Game; +import mage.game.permanent.Permanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class TheEnigmaJewel extends CardImpl { + + public TheEnigmaJewel(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{U}"); + + this.supertype.add(SuperType.LEGENDARY); + this.secondSideCardClazz = mage.cards.l.LocusOfEnlightenment.class; + + // The Enigma Jewel enters the battlefield tapped. + this.addAbility(new EntersBattlefieldTappedAbility()); + + // {T}: Add {C}{C}. Spend this mana only to activate abilities. + this.addAbility(new ConditionalColorlessManaAbility(2, new TheEnigmaJewelManaBuilder())); + + // Craft with four or more nonlands with activated abilities {8}{U} + this.addAbility(new CraftAbility( + "{8}{U}", "four or more nonlands with activated abilities", "other " + + "nonland permanents you control with activated abilities and/or nonland cards in your " + + "graveyard with activated abilities", 4, Integer.MAX_VALUE, TheEnigmaJewelPredicate.instance + )); + } + + private TheEnigmaJewel(final TheEnigmaJewel card) { + super(card); + } + + @Override + public TheEnigmaJewel copy() { + return new TheEnigmaJewel(this); + } +} + +enum TheEnigmaJewelPredicate implements Predicate { + instance; + + @Override + public boolean apply(MageObject input, Game game) { + return !input.isLand(game) + && getAbilities(input, game) + .stream() + .anyMatch(ActivatedAbilityImpl.class::isInstance); + } + + private static Abilities getAbilities(MageObject input, Game game) { + if (input instanceof Permanent) { + return ((Permanent) input).getAbilities(game); + } else if (input instanceof Card) { + return ((Card) input).getAbilities(game); + } else { + throw new UnsupportedOperationException("there shouldn't be a nonpermanent, noncard object here"); + } + } +} + +class TheEnigmaJewelManaBuilder extends ConditionalManaBuilder { + + @Override + public ConditionalMana build(Object... options) { + return new TheEnigmaJewelConditionalMana(this.mana); + } + + @Override + public String getRule() { + return "Spend this mana only to activate abilities"; + } +} + +class TheEnigmaJewelConditionalMana extends ConditionalMana { + + TheEnigmaJewelConditionalMana(Mana mana) { + super(mana); + staticText = "Spend this mana only to activate abilities"; + addCondition(new TheEnigmaJewelManaCondition()); + } +} + +class TheEnigmaJewelManaCondition extends ManaCondition implements Condition { + + @Override + public boolean apply(Game game, Ability source) { + if (source != null) { + return source.getAbilityType() == AbilityType.MANA + || source.getAbilityType() == AbilityType.ACTIVATED; + } + return false; + } + + @Override + public boolean apply(Game game, Ability source, UUID originalId, Cost costsToPay) { + return apply(game, source); + } +} diff --git a/Mage.Sets/src/mage/sets/TheLostCavernsOfIxalan.java b/Mage.Sets/src/mage/sets/TheLostCavernsOfIxalan.java index 77f51d1d849..7e0e8dd9db6 100644 --- a/Mage.Sets/src/mage/sets/TheLostCavernsOfIxalan.java +++ b/Mage.Sets/src/mage/sets/TheLostCavernsOfIxalan.java @@ -188,6 +188,7 @@ public final class TheLostCavernsOfIxalan extends ExpansionSet { cards.add(new SetCardInfo("Kinjalli's Dawnrunner", 19, Rarity.UNCOMMON, mage.cards.k.KinjallisDawnrunner.class)); cards.add(new SetCardInfo("Kitesail Larcenist", 61, Rarity.RARE, mage.cards.k.KitesailLarcenist.class)); cards.add(new SetCardInfo("Kutzil's Flanker", 20, Rarity.RARE, mage.cards.k.KutzilsFlanker.class)); + cards.add(new SetCardInfo("Locus of Enlightenment", 55, Rarity.MYTHIC, mage.cards.l.LocusOfEnlightenment.class)); cards.add(new SetCardInfo("Lodestone Needle", 62, Rarity.UNCOMMON, mage.cards.l.LodestoneNeedle.class)); cards.add(new SetCardInfo("Malamet Brawler", 199, Rarity.COMMON, mage.cards.m.MalametBrawler.class)); cards.add(new SetCardInfo("Malamet Scythe", 200, Rarity.COMMON, mage.cards.m.MalametScythe.class)); @@ -311,6 +312,7 @@ public final class TheLostCavernsOfIxalan extends ExpansionSet { cards.add(new SetCardInfo("The Ancient One", 222, Rarity.MYTHIC, mage.cards.t.TheAncientOne.class)); cards.add(new SetCardInfo("The Belligerent", 225, Rarity.RARE, mage.cards.t.TheBelligerent.class)); cards.add(new SetCardInfo("The Core", 256, Rarity.RARE, mage.cards.t.TheCore.class)); + cards.add(new SetCardInfo("The Enigma Jewel", 55, Rarity.MYTHIC, mage.cards.t.TheEnigmaJewel.class)); cards.add(new SetCardInfo("The Grim Captain", 266, Rarity.RARE, mage.cards.t.TheGrimCaptain.class)); cards.add(new SetCardInfo("The Millennium Calendar", 257, Rarity.MYTHIC, mage.cards.t.TheMillenniumCalendar.class)); cards.add(new SetCardInfo("The Mycotyrant", 235, Rarity.MYTHIC, mage.cards.t.TheMycotyrant.class));