From f9a22291d46802048dec832887c040d0b67abb02 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Tue, 15 Apr 2014 17:39:21 +0200 Subject: [PATCH] [JOU] Added 6 cards. --- .../sets/journeyintonyx/AegisOfTheGods.java | 69 ++++++ .../BattlefieldThaumaturge.java | 133 +++++++++++ .../journeyintonyx/BearerOfTheHeavens.java | 73 ++++++ .../mage/sets/journeyintonyx/DaringThief.java | 208 ++++++++++++++++++ .../journeyintonyx/EidolonOfRhetoric.java | 149 +++++++++++++ .../EidolonOfTheGreatRevel.java | 4 +- .../sets/journeyintonyx/ForgebornOreads.java | 2 +- .../sets/journeyintonyx/NyxFleeceRam.java | 66 ++++++ .../journeyintonyx/SilenceTheBelievers.java | 2 +- .../sets/journeyintonyx/SpiteOfMogis.java | 2 +- .../CreateDelayedTriggeredAbilityEffect.java | 5 +- .../ExchangeControlTargetEffect.java | 132 +++++------ Mage/src/mage/target/TargetPermanent.java | 4 +- .../common/TargetControlledPermanent.java | 1 + Mage/src/mage/util/CardUtil.java | 9 +- Utils/mtg-cards-data.txt | 18 +- 16 files changed, 790 insertions(+), 87 deletions(-) create mode 100644 Mage.Sets/src/mage/sets/journeyintonyx/AegisOfTheGods.java create mode 100644 Mage.Sets/src/mage/sets/journeyintonyx/BattlefieldThaumaturge.java create mode 100644 Mage.Sets/src/mage/sets/journeyintonyx/BearerOfTheHeavens.java create mode 100644 Mage.Sets/src/mage/sets/journeyintonyx/DaringThief.java create mode 100644 Mage.Sets/src/mage/sets/journeyintonyx/EidolonOfRhetoric.java create mode 100644 Mage.Sets/src/mage/sets/journeyintonyx/NyxFleeceRam.java diff --git a/Mage.Sets/src/mage/sets/journeyintonyx/AegisOfTheGods.java b/Mage.Sets/src/mage/sets/journeyintonyx/AegisOfTheGods.java new file mode 100644 index 00000000000..63a020329e5 --- /dev/null +++ b/Mage.Sets/src/mage/sets/journeyintonyx/AegisOfTheGods.java @@ -0,0 +1,69 @@ +/* + * 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.journeyintonyx; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.continious.GainAbilityControllerEffect; +import mage.abilities.keyword.HexproofAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; + +/** + * + * @author LevelX2 + */ +public class AegisOfTheGods extends CardImpl { + + public AegisOfTheGods(UUID ownerId) { + super(ownerId, 1, "Aegis of the Gods", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT, CardType.CREATURE}, "{1}{W}"); + this.expansionSetCode = "JOU"; + this.subtype.add("Human"); + this.subtype.add("Soldier"); + + this.color.setWhite(true); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // You have hexproof. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityControllerEffect(HexproofAbility.getInstance(), Duration.WhileOnBattlefield))); + } + + public AegisOfTheGods(final AegisOfTheGods card) { + super(card); + } + + @Override + public AegisOfTheGods copy() { + return new AegisOfTheGods(this); + } +} diff --git a/Mage.Sets/src/mage/sets/journeyintonyx/BattlefieldThaumaturge.java b/Mage.Sets/src/mage/sets/journeyintonyx/BattlefieldThaumaturge.java new file mode 100644 index 00000000000..748ac233aa8 --- /dev/null +++ b/Mage.Sets/src/mage/sets/journeyintonyx/BattlefieldThaumaturge.java @@ -0,0 +1,133 @@ +/* + * 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.journeyintonyx; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.SpellAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.CostModificationEffectImpl; +import mage.abilities.effects.common.continious.GainAbilitySourceEffect; +import mage.abilities.keyword.HeroicAbility; +import mage.abilities.keyword.HexproofAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.CostModificationType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.FilterSpell; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.game.stack.Spell; +import mage.target.Target; +import mage.util.CardUtil; + +/** + * + * @author LevelX2 + */ +public class BattlefieldThaumaturge extends CardImpl { + + public BattlefieldThaumaturge(UUID ownerId) { + super(ownerId, 32, "Battlefield Thaumaturge", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{1}{U}"); + this.expansionSetCode = "JOU"; + this.subtype.add("Human"); + this.subtype.add("Wizard"); + + this.color.setBlue(true); + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + // Each instant and sorcery spell you cast costs 1 less to cast for each creature it targets. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BattlefieldThaumaturgeSpellsCostReductionEffect())); + // Heroic - Whenever you cast a spell that targets Battlefield Thaumaturge, Battlefield Thaumaturge gains hexproof until end of turn. + this.addAbility(new HeroicAbility(new GainAbilitySourceEffect(HexproofAbility.getInstance(), Duration.EndOfTurn))); + } + + public BattlefieldThaumaturge(final BattlefieldThaumaturge card) { + super(card); + } + + @Override + public BattlefieldThaumaturge copy() { + return new BattlefieldThaumaturge(this); + } +} + +class BattlefieldThaumaturgeSpellsCostReductionEffect extends CostModificationEffectImpl { + + private static final FilterSpell filter = new FilterSpell("instant and sorcery spell"); + + static { + filter.add(Predicates.or(new CardTypePredicate(CardType.INSTANT), new CardTypePredicate(CardType.SORCERY))); + } + + public BattlefieldThaumaturgeSpellsCostReductionEffect() { + super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.REDUCE_COST); + this.staticText = "Each instant and sorcery spell you cast costs 1 less to cast for each creature it targets"; + } + + protected BattlefieldThaumaturgeSpellsCostReductionEffect(BattlefieldThaumaturgeSpellsCostReductionEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source, Ability abilityToModify) { + int creatureTargets = 0; + for (Target target: abilityToModify.getTargets()) { + for (UUID uuid: target.getTargets()) { + Permanent permanent = game.getPermanent(uuid); + if (permanent != null && permanent.getCardType().contains(CardType.CREATURE)) { + creatureTargets++; + } + } + } + CardUtil.reduceCost(abilityToModify, creatureTargets); + return true; + } + + @Override + public boolean applies(Ability abilityToModify, Ability source, Game game) { + if ((abilityToModify instanceof SpellAbility) + && abilityToModify.getControllerId().equals(source.getControllerId())) { + Spell spell = (Spell) game.getStack().getStackObject(abilityToModify.getId()); + return spell != null && this.filter.match(spell, game); + } + return false; + } + + @Override + public BattlefieldThaumaturgeSpellsCostReductionEffect copy() { + return new BattlefieldThaumaturgeSpellsCostReductionEffect(this); + } +} diff --git a/Mage.Sets/src/mage/sets/journeyintonyx/BearerOfTheHeavens.java b/Mage.Sets/src/mage/sets/journeyintonyx/BearerOfTheHeavens.java new file mode 100644 index 00000000000..1db82a74e0f --- /dev/null +++ b/Mage.Sets/src/mage/sets/journeyintonyx/BearerOfTheHeavens.java @@ -0,0 +1,73 @@ +/* + * 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.journeyintonyx; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.DelayedTriggeredAbility; +import mage.abilities.common.DiesTriggeredAbility; +import mage.abilities.common.delayed.AtEndOfTurnDelayedTriggeredAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; +import mage.abilities.effects.common.DestroyAllEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.FilterPermanent; + +/** + * + * @author LevelX2 + */ +public class BearerOfTheHeavens extends CardImpl { + + public BearerOfTheHeavens(UUID ownerId) { + super(ownerId, 9991, "Bearer of the Heavens", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{7}{R}"); + this.expansionSetCode = "JOU"; + this.subtype.add("Giant"); + + this.color.setRed(true); + this.power = new MageInt(10); + this.toughness = new MageInt(10); + + // When Bearer of the Heavens dies, destroy all permanents at the beginning of the next end step. + DelayedTriggeredAbility delayedAbility = new AtEndOfTurnDelayedTriggeredAbility(new DestroyAllEffect(new FilterPermanent("permanents"))); + Effect effect = new CreateDelayedTriggeredAbilityEffect(delayedAbility); + effect.setText("destroy all permanents at the beginning of the next end step"); + this.addAbility(new DiesTriggeredAbility(effect, false)); + } + + public BearerOfTheHeavens(final BearerOfTheHeavens card) { + super(card); + } + + @Override + public BearerOfTheHeavens copy() { + return new BearerOfTheHeavens(this); + } +} diff --git a/Mage.Sets/src/mage/sets/journeyintonyx/DaringThief.java b/Mage.Sets/src/mage/sets/journeyintonyx/DaringThief.java new file mode 100644 index 00000000000..e962547376e --- /dev/null +++ b/Mage.Sets/src/mage/sets/journeyintonyx/DaringThief.java @@ -0,0 +1,208 @@ +/* + * 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.journeyintonyx; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; +import mage.MageInt; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.effects.common.continious.ExchangeControlTargetEffect; +import mage.abilities.keyword.InspiredAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.TargetPermanent; +import mage.target.common.TargetControlledPermanent; +import mage.util.CardUtil; + +/** + * + * @author LevelX2 + */ +public class DaringThief extends CardImpl { + + public DaringThief(UUID ownerId) { + super(ownerId, 36, "Daring Thief", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{2}{U}"); + this.expansionSetCode = "JOU"; + this.subtype.add("Human"); + this.subtype.add("Rogue"); + + this.color.setBlue(true); + this.power = new MageInt(2); + this.toughness = new MageInt(3); + + // Inspired - Whenever Daring Thief becomes untapped, you may exchange control of target nonland permanent you control and target permanent an opponent controls that shares a card type with it. + Ability ability = new InspiredAbility(new ExchangeControlTargetEffect(Duration.EndOfGame, + "you may exchange control of target nonland permanent you control and target permanent an opponent controls that shares a card type with it", false, true), true); + ability.addTarget(new TargetControlledPermanentSharingOpponentPermanentCardType()); + ability.addTarget(new DaringThiefSecondTarget()); + this.addAbility(ability); + } + + public DaringThief(final DaringThief card) { + super(card); + } + + @Override + public DaringThief copy() { + return new DaringThief(this); + } +} + +class TargetControlledPermanentSharingOpponentPermanentCardType extends TargetControlledPermanent { + + public TargetControlledPermanentSharingOpponentPermanentCardType() { + super(); + filter.add(Predicates.not(new CardTypePredicate(CardType.LAND))); + setTargetName("nonland permanent you control"); + setRequired(true); + } + + public TargetControlledPermanentSharingOpponentPermanentCardType(final TargetControlledPermanentSharingOpponentPermanentCardType target) { + super(target); + } + + @Override + public boolean canTarget(UUID controllerId, UUID id, Ability source, Game game) { + if (super.canTarget(controllerId, id, source, game)) { + Set cardTypes = getOpponentPermanentCardTypes(source.getSourceId(), controllerId, game); + Permanent permanent = game.getPermanent(id); + for (CardType type : permanent.getCardType()) { + if (cardTypes.contains(type)) { + return true; + } + } + } + return false; + } + + @Override + public Set possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) { + // get all cardtypes from opponents permanents + Set cardTypes = getOpponentPermanentCardTypes(sourceId, sourceControllerId, game); + Set possibleTargets = new HashSet<>(); + MageObject targetSource = game.getObject(sourceId); + for (Permanent permanent: game.getBattlefield().getActivePermanents(filter, sourceControllerId, sourceId, game)) { + if (!targets.containsKey(permanent.getId()) && permanent.canBeTargetedBy(targetSource, sourceControllerId, game)) { + for (CardType type : permanent.getCardType()) { + if (cardTypes.contains(type)) { + possibleTargets.add(permanent.getId()); + break; + } + } + } + } + return possibleTargets; + } + + @Override + public TargetControlledPermanentSharingOpponentPermanentCardType copy() { + return new TargetControlledPermanentSharingOpponentPermanentCardType(this); + } + + private Set getOpponentPermanentCardTypes(UUID sourceId, UUID sourceControllerId, Game game) { + Player controller = game.getPlayer(sourceControllerId); + Set cardTypes = new HashSet<>(); + if (controller != null) { + for (Permanent permanent: game.getBattlefield().getActivePermanents(sourceId, game)) { + if (controller.hasOpponent(permanent.getControllerId(), game)) { + cardTypes.addAll(permanent.getCardType()); + } + } + } + return cardTypes; + } +} + + +class DaringThiefSecondTarget extends TargetPermanent { + + private Permanent firstTarget = null; + + public DaringThiefSecondTarget() { + super(); + filter.add(new ControllerPredicate(TargetController.OPPONENT)); + setTargetName("permanent an opponent controls that shares a card type with it"); + } + + public DaringThiefSecondTarget(final DaringThiefSecondTarget target) { + super(target); + this.firstTarget = target.firstTarget; + } + + + @Override + public boolean canTarget(UUID id, Ability source, Game game) { + if (super.canTarget(id, source, game)) { + Permanent target1 = game.getPermanent(source.getFirstTarget()); + Permanent opponentPermanent = game.getPermanent(id); + if (target1 != null && opponentPermanent != null) { + return CardUtil.shareTypes(target1, opponentPermanent); + } + } + return false; + } + + @Override + public Set possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) { + Set possibleTargets = new HashSet<>(); + if (firstTarget != null) { + MageObject targetSource = game.getObject(sourceId); + for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, sourceId, game)) { + if (!targets.containsKey(permanent.getId()) && permanent.canBeTargetedBy(targetSource, sourceControllerId, game)) { + if (CardUtil.shareTypes(permanent, firstTarget)) { + possibleTargets.add(permanent.getId()); + } + } + } + } + return possibleTargets; + } + + @Override + public boolean chooseTarget(Outcome outcome, UUID playerId, Ability source, Game game) { + firstTarget = game.getPermanent(source.getFirstTarget()); + return super.chooseTarget(Outcome.Damage, playerId, source, game); + } + + @Override + public DaringThiefSecondTarget copy() { + return new DaringThiefSecondTarget(this); + } +} diff --git a/Mage.Sets/src/mage/sets/journeyintonyx/EidolonOfRhetoric.java b/Mage.Sets/src/mage/sets/journeyintonyx/EidolonOfRhetoric.java new file mode 100644 index 00000000000..1fd348c97bc --- /dev/null +++ b/Mage.Sets/src/mage/sets/journeyintonyx/EidolonOfRhetoric.java @@ -0,0 +1,149 @@ +/* + * 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.journeyintonyx; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.WatcherScope; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.watchers.Watcher; +import mage.watchers.WatcherImpl; + +/** + * + * @author LevelX2 + */ +public class EidolonOfRhetoric extends CardImpl { + + public EidolonOfRhetoric(UUID ownerId) { + super(ownerId, 10, "Eidolon of Rhetoric", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT, CardType.CREATURE}, "{2}{W}"); + this.expansionSetCode = "JOU"; + this.subtype.add("Spirit"); + + this.color.setWhite(true); + this.power = new MageInt(1); + this.toughness = new MageInt(4); + + // Each player can't cast more than one spell each turn. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new EidolonOfRhetoricEffect())); + this.addWatcher(new EidolonOfRhetoricWatcher()); + } + + public EidolonOfRhetoric(final EidolonOfRhetoric card) { + super(card); + } + + @Override + public EidolonOfRhetoric copy() { + return new EidolonOfRhetoric(this); + } +} + +class EidolonOfRhetoricWatcher extends WatcherImpl { + + public EidolonOfRhetoricWatcher() { + super("SpellCast", WatcherScope.PLAYER); + } + + public EidolonOfRhetoricWatcher(final EidolonOfRhetoricWatcher watcher) { + super(watcher); + } + + @Override + public EidolonOfRhetoricWatcher copy() { + return new EidolonOfRhetoricWatcher(this); + } + + @Override + public void watch(GameEvent event, Game game) { + if (condition == true) {//no need to check - condition has already occured + return; + } + if (event.getType() == GameEvent.EventType.SPELL_CAST ) { + Permanent enchantment = game.getPermanent(this.sourceId); + if (enchantment != null && enchantment.getAttachedTo() != null) { + Player player = game.getPlayer(enchantment.getAttachedTo()); + if (player != null && event.getPlayerId().equals(player.getId())) { + condition = true; + } + } + } + } + +} + +class EidolonOfRhetoricEffect extends ReplacementEffectImpl { + + public EidolonOfRhetoricEffect() { + super(Duration.WhileOnBattlefield, Outcome.Detriment); + staticText = "Each player can't cast more than one spell each turn"; + } + + public EidolonOfRhetoricEffect(final EidolonOfRhetoricEffect effect) { + super(effect); + } + + @Override + public EidolonOfRhetoricEffect copy() { + return new EidolonOfRhetoricEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + return true; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (event.getType() == GameEvent.EventType.CAST_SPELL) { + Watcher watcher = game.getState().getWatchers().get("SpellCast", event.getPlayerId()); + if (watcher != null && watcher.conditionMet()) { + return true; + } + } + return false; + } + +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/journeyintonyx/EidolonOfTheGreatRevel.java b/Mage.Sets/src/mage/sets/journeyintonyx/EidolonOfTheGreatRevel.java index fe108bfa303..7be2707ccb8 100644 --- a/Mage.Sets/src/mage/sets/journeyintonyx/EidolonOfTheGreatRevel.java +++ b/Mage.Sets/src/mage/sets/journeyintonyx/EidolonOfTheGreatRevel.java @@ -36,10 +36,8 @@ import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Rarity; import mage.constants.Zone; -import mage.counters.CounterType; import mage.game.Game; import mage.game.events.GameEvent; -import mage.game.permanent.Permanent; import mage.game.stack.Spell; import mage.target.targetpointer.FixedTarget; @@ -50,7 +48,7 @@ import mage.target.targetpointer.FixedTarget; public class EidolonOfTheGreatRevel extends CardImpl { public EidolonOfTheGreatRevel(UUID ownerId) { - super(ownerId, 999, "Eidolon of the Great Revel", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT, CardType.CREATURE}, "{R}{R}"); + super(ownerId, 9992, "Eidolon of the Great Revel", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT, CardType.CREATURE}, "{R}{R}"); this.expansionSetCode = "JOU"; this.subtype.add("Spirit"); diff --git a/Mage.Sets/src/mage/sets/journeyintonyx/ForgebornOreads.java b/Mage.Sets/src/mage/sets/journeyintonyx/ForgebornOreads.java index 5d37669b052..7a697516976 100644 --- a/Mage.Sets/src/mage/sets/journeyintonyx/ForgebornOreads.java +++ b/Mage.Sets/src/mage/sets/journeyintonyx/ForgebornOreads.java @@ -43,7 +43,7 @@ import mage.target.common.TargetCreatureOrPlayer; public class ForgebornOreads extends CardImpl { public ForgebornOreads(UUID ownerId) { - super(ownerId, 999, "Forgeborn Oreads", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT, CardType.CREATURE}, "{2}{R}{R}"); + super(ownerId, 98, "Forgeborn Oreads", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT, CardType.CREATURE}, "{2}{R}{R}"); this.expansionSetCode = "JOU"; this.subtype.add("Nymph"); diff --git a/Mage.Sets/src/mage/sets/journeyintonyx/NyxFleeceRam.java b/Mage.Sets/src/mage/sets/journeyintonyx/NyxFleeceRam.java new file mode 100644 index 00000000000..03b111d9831 --- /dev/null +++ b/Mage.Sets/src/mage/sets/journeyintonyx/NyxFleeceRam.java @@ -0,0 +1,66 @@ +/* + * 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.journeyintonyx; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.effects.common.GainLifeEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.TargetController; + +/** + * + * @author LevelX2 + */ +public class NyxFleeceRam extends CardImpl { + + public NyxFleeceRam(UUID ownerId) { + super(ownerId, 18, "Nyx-Fleece Ram", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT, CardType.CREATURE}, "{1}{W}"); + this.expansionSetCode = "JOU"; + this.subtype.add("Sheep"); + + this.color.setWhite(true); + this.power = new MageInt(0); + this.toughness = new MageInt(5); + + // At the beginning of your upkeep, you gain 1 life. + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new GainLifeEffect(1), TargetController.YOU, false)); + } + + public NyxFleeceRam(final NyxFleeceRam card) { + super(card); + } + + @Override + public NyxFleeceRam copy() { + return new NyxFleeceRam(this); + } +} diff --git a/Mage.Sets/src/mage/sets/journeyintonyx/SilenceTheBelievers.java b/Mage.Sets/src/mage/sets/journeyintonyx/SilenceTheBelievers.java index 835561af359..54b60586efd 100644 --- a/Mage.Sets/src/mage/sets/journeyintonyx/SilenceTheBelievers.java +++ b/Mage.Sets/src/mage/sets/journeyintonyx/SilenceTheBelievers.java @@ -50,7 +50,7 @@ import mage.target.common.TargetCreaturePermanent; public class SilenceTheBelievers extends CardImpl { public SilenceTheBelievers(UUID ownerId) { - super(ownerId, 999, "Silence the Believers", Rarity.RARE, new CardType[]{CardType.INSTANT}, "{2}{B}{B}"); + super(ownerId, 82, "Silence the Believers", Rarity.RARE, new CardType[]{CardType.INSTANT}, "{2}{B}{B}"); this.expansionSetCode = "JOU"; this.color.setBlack(true); diff --git a/Mage.Sets/src/mage/sets/journeyintonyx/SpiteOfMogis.java b/Mage.Sets/src/mage/sets/journeyintonyx/SpiteOfMogis.java index 2771cd8552b..0b763ab4040 100644 --- a/Mage.Sets/src/mage/sets/journeyintonyx/SpiteOfMogis.java +++ b/Mage.Sets/src/mage/sets/journeyintonyx/SpiteOfMogis.java @@ -44,7 +44,7 @@ import mage.target.common.TargetCreaturePermanent; public class SpiteOfMogis extends CardImpl { public SpiteOfMogis(UUID ownerId) { - super(ownerId, 999, "Spite of Mogis", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{R}"); + super(ownerId, 113, "Spite of Mogis", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{R}"); this.expansionSetCode = "JOU"; this.color.setRed(true); diff --git a/Mage/src/mage/abilities/effects/common/CreateDelayedTriggeredAbilityEffect.java b/Mage/src/mage/abilities/effects/common/CreateDelayedTriggeredAbilityEffect.java index ea507494391..4324e0df7a7 100644 --- a/Mage/src/mage/abilities/effects/common/CreateDelayedTriggeredAbilityEffect.java +++ b/Mage/src/mage/abilities/effects/common/CreateDelayedTriggeredAbilityEffect.java @@ -67,7 +67,7 @@ public class CreateDelayedTriggeredAbilityEffect extends OneShotEffect { private String rule; - private Boolean withSource; - private Map lockedControllers; + private boolean withSource; + private boolean withSecondTarget; + private Map zoneChangeCounter = new HashMap<>(); + private Map lockedControllers = new HashMap<>(); public ExchangeControlTargetEffect(Duration duration, String rule) { this(duration, rule, false); } - public ExchangeControlTargetEffect(Duration duration, String rule, Boolean withSource) { + public ExchangeControlTargetEffect(Duration duration, String rule, boolean withSource) { + this(duration, rule, withSource, false); + } + + public ExchangeControlTargetEffect(Duration duration, String rule, boolean withSource, boolean withSecondTarget) { super(duration, Layer.ControlChangingEffects_2, SubLayer.NA, Outcome.GainControl); this.withSource = withSource; + this.withSecondTarget = withSecondTarget; this.rule = rule; } @@ -62,7 +69,9 @@ public class ExchangeControlTargetEffect extends ContinuousEffectImpl 0; + return isDiscarded(); } @Override public void init(Ability source, Game game) { - Set controllers = new HashSet(); - for (UUID permanentId : targetPointer.getTargets(game, source)) { - Permanent permanent = game.getPermanent(permanentId); - if (permanent != null) { - controllers.add(permanent.getControllerId()); - } - } + Permanent permanent1 = null; + Permanent permanent2 = null; + if (withSource) { - controllers.add(source.getControllerId()); - } - // exchange works only for two different controllers - if (controllers.size() != 2) { - // discard effect - this.discarded = true; - return; - } - - this.lockedControllers = new HashMap(); - - Iterator it = controllers.iterator(); - UUID firstController = it.next(); - UUID secondController = it.next(); - - if (withSource) { - Permanent targetPermanent = game.getPermanent(targetPointer.getFirst(game, source)); - Permanent sourcePermanent = game.getPermanent(source.getSourceId()); - if (targetPermanent != null && sourcePermanent != null) { - this.lockedControllers.put(targetPermanent.getId(), sourcePermanent.getControllerId()); - this.lockedControllers.put(sourcePermanent.getId(), targetPermanent.getControllerId()); - } - } - else { + permanent1 = game.getPermanent(targetPointer.getFirst(game, source)); + permanent2 = game.getPermanent(source.getSourceId()); + } else { for (UUID permanentId : targetPointer.getTargets(game, source)) { - Permanent permanent = game.getPermanent(permanentId); - if (permanent != null) { - this.lockedControllers.put(permanent.getId(), permanent.getControllerId().equals(firstController) ? secondController : firstController); + if (permanent1 == null) { + permanent1 = game.getPermanent(permanentId); + } + if (permanent2 == null) { + permanent2 = game.getPermanent(permanentId); } } + if (withSecondTarget) { + UUID uuid = source.getTargets().get(1).getFirstTarget(); + permanent2 = game.getPermanent(uuid); + } + } + if (permanent1 != null && permanent2 != null) { + // exchange works only for two different controllers + if (permanent1.getControllerId().equals(permanent2.getControllerId())) { + // discard effect if controller of both permanents is the same + discard(); + return; + } + this.lockedControllers.put(permanent1.getId(), permanent2.getControllerId()); + this.zoneChangeCounter.put(permanent1.getId(), permanent1.getZoneChangeCounter()); + this.lockedControllers.put(permanent2.getId(), permanent1.getControllerId()); + this.zoneChangeCounter.put(permanent2.getId(), permanent2.getZoneChangeCounter()); + } else { + // discard if there are less than 2 permanents + discard(); } } @Override public boolean apply(Game game, Ability source) { - int countChangeControl = 0; - Map remainingLockedControllers = new HashMap(); - if (this.lockedControllers != null) { - for (UUID permanentId : targetPointer.getTargets(game, source)) { - Permanent permanent = game.getPermanent(permanentId); - if (permanent != null) { - UUID controllerId = this.lockedControllers.get(permanent.getId()); - if (controllerId != null) { - if(permanent.changeControllerId(controllerId, game)) { - remainingLockedControllers.put(permanentId, controllerId); - ++countChangeControl; - } - } - } + Set toDelete = new HashSet<>(); + for (Map.Entry entry: zoneChangeCounter.entrySet()) { + Permanent permanent = game.getPermanent(entry.getKey()); + if (permanent == null || permanent.getZoneChangeCounter() != entry.getValue()) { + // controll effect cease if the same permanent is no longer on the battlefield + toDelete.add(entry.getKey()); + continue; } - if (withSource) { - Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent != null) { - UUID controllerId = this.lockedControllers.get(permanent.getId()); - if (controllerId != null) { - if (permanent.changeControllerId(controllerId, game)) { - remainingLockedControllers.put(source.getSourceId(), controllerId); - ++countChangeControl; - } - } - } + permanent.changeControllerId(lockedControllers.get(permanent.getId()), game); + } + if (!toDelete.isEmpty()) { + for(UUID uuid: toDelete) { + zoneChangeCounter.remove(uuid); + } + if (zoneChangeCounter.isEmpty()) { + discard(); + return false; } } - // if the permanent is not existent (card in hand or graveyard) the control changing effect has to end - // else a previous controlled card that will be enter the battlefield again will be immediately be affected - this.lockedControllers = remainingLockedControllers; - if (countChangeControl > 0) { - return true; - } - return false; - + return true; } @Override diff --git a/Mage/src/mage/target/TargetPermanent.java b/Mage/src/mage/target/TargetPermanent.java index 4079f0d1a7c..00f39dd0079 100644 --- a/Mage/src/mage/target/TargetPermanent.java +++ b/Mage/src/mage/target/TargetPermanent.java @@ -182,7 +182,7 @@ public class TargetPermanent> extends TargetObject< @Override public Set possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) { - Set possibleTargets = new HashSet(); + Set possibleTargets = new HashSet<>(); MageObject targetSource = game.getObject(sourceId); for (Permanent permanent: game.getBattlefield().getActivePermanents(filter, sourceControllerId, sourceId, game)) { if (!targets.containsKey(permanent.getId()) && permanent.canBeTargetedBy(targetSource, sourceControllerId, game)) { @@ -194,7 +194,7 @@ public class TargetPermanent> extends TargetObject< @Override public Set possibleTargets(UUID sourceControllerId, Game game) { - Set possibleTargets = new HashSet(); + Set possibleTargets = new HashSet<>(); for (Permanent permanent: game.getBattlefield().getActivePermanents(filter, sourceControllerId, game)) { if (!targets.containsKey(permanent.getId())) { possibleTargets.add(permanent.getId()); diff --git a/Mage/src/mage/target/common/TargetControlledPermanent.java b/Mage/src/mage/target/common/TargetControlledPermanent.java index 8596a38c0e5..558ed587f4e 100644 --- a/Mage/src/mage/target/common/TargetControlledPermanent.java +++ b/Mage/src/mage/target/common/TargetControlledPermanent.java @@ -35,6 +35,7 @@ import mage.target.TargetPermanent; /** * * @author BetaSteward_at_googlemail.com + * @param */ public class TargetControlledPermanent> extends TargetPermanent> { diff --git a/Mage/src/mage/util/CardUtil.java b/Mage/src/mage/util/CardUtil.java index 3101d6c03ce..5cc5fcede38 100644 --- a/Mage/src/mage/util/CardUtil.java +++ b/Mage/src/mage/util/CardUtil.java @@ -178,16 +178,19 @@ public class CardUtil { * @param reduceCount */ private static void adjustCost(Ability ability, int reduceCount) { + int restToReduce = reduceCount; ManaCosts previousCost = ability.getManaCostsToPay(); - ManaCosts adjustedCost = new ManaCostsImpl(); + ManaCosts adjustedCost = new ManaCostsImpl<>(); boolean updated = false; for (ManaCost manaCost : previousCost) { Mana mana = manaCost.getOptions().get(0); int colorless = mana != null ? mana.getColorless() : 0; if (!updated && colorless > 0) { - if ((colorless - reduceCount) > 0) { - int newColorless = colorless - reduceCount; + if ((colorless - restToReduce) > 0) { + int newColorless = colorless - restToReduce; adjustedCost.add(new GenericManaCost(newColorless)); + } else { + restToReduce =- colorless; } updated = true; } else { diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index 6355421b815..d496c880485 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -23185,9 +23185,9 @@ Sightless Brawler|Journey into Nyx|24|U|{1}{W}|Enchantment Creature - Human Warr Spirespine|Journey into Nyx|142|U|{2}{G}|Enchantment Creature - Beast|4|1|Bestow 4G (If you cast this card for its bestow cost, it's an Aura spell with enchant creature. It becomes a creature again if it's not attached to a creature.)$Spirespine blocks each turn if able.$Enchanted creature gets +4/+1 and blocks each turn if able.| Setessan Tactics|Journey into Nyx|140|R|{1}{G}|Instant|||Strive — Setessan Tactics costs G more to cast for each target beyond the first.$Until end of turn, any number of target creatures each get +1/+1 and gain "T: This creature fights another target creature."| Eidolon of the Great Revel|Journey into Nyx|999|R|{R}{R}|Enchantment Creature - Spirit|2|2|Whenever a player casts a spell with converted mana cost 3 or less, Eidolon of the Great Revel deals 2 damage to that player.| -Spite of Mogis|Journey into Nyx|999|U|{R}|Sorcery|||Spite of Mogis deals damage to target creature equal to the number of instant and sorcery cards in your graveyard. Scry 1.| +Spite of Mogis|Journey into Nyx|113|U|{R}|Sorcery|||Spite of Mogis deals damage to target creature equal to the number of instant and sorcery cards in your graveyard. Scry 1.| Kruphix, God of Horizons|Journey into Nyx|152|M|{3}{G}{U}|Legendary Enchantment Creature - God|4|7|Indestructible$As long as your devotion to green and blue is less than seven, Kruhpix isn't a creature.$You have no maximum hand size.$If unused mana would empty from your mana pool, that mana becomes colorless instead.| -Silence the Believers|Journey into Nyx|999|R|{2}{B}{B}|Instant|||Strive — Silence the Believers costs 2B more to cast for each target beyond the first.$Exile any number of target creatures and all Auras attached to them.| +Silence the Believers|Journey into Nyx|82|R|{2}{B}{B}|Instant|||Strive — Silence the Believers costs 2B more to cast for each target beyond the first.$Exile any number of target creatures and all Auras attached to them.| Interpret the Signs|Journey into Nyx|43|U|{5}{U}|Sorcery|||Scry 3, then reveal the top card of your library. Draw cards equal to that card's converted mana cost.| Kruphix's Insight|Journey into Nyx|129|C|{2}{G}|Sorcery|||Reveal the top six cards of your library. Put up to three enchantment cards from among them into your hand and the rest of the revealed cards into your graveyard.| Launch the Fleet|Journey into Nyx|15|R|{W}|Sorcery|||Strive — Launch the Fleet costs 1 more to cast for each target beyond the first.$Until end of turn, any number of target creatures each gain "Whenever this creature attacks, put a 1/1 white Soldier token onto the battlefield tapped and attacking."| @@ -23202,4 +23202,16 @@ Athreos, God of Passage|Journey into Nyx|146|M|{1}{W}{B}|Legendary Enchantment C Hydra Broodmaster|Journey into Nyx|126|R|{4}{G}{G}|Creature - Hydra|7|7|{X}{X}{G}: Monstrosity X$When Hydra Broodmaster becomes monstrous, put X X/X green Hydra creature tokens onto the battlefield.| King Macar, the Gold-Cursed|Journey into Nyx|74|R|{2}{B}{B}|Legendary Creature - Human|2|3|Inspired — Whenever King Macar, the Gold-Cursed becomes untapped, you may exile target creature. If you do, put a colorless artifact token named Gold onto the battlefield. It has "Sacrifice this artifact: Add one mana of any color to your mana pool."| Polymorphous Rush|Journey into Nyx|46|R|{2}{U}|Instant|||Strive — Polymorphous Rush costs 1U more to cast for each target beyond the first.$Choose a creature on the battlefield. Any number of target creatures you control each become a copy of that creature until end of turn.| -Forgeborn Oreads|Journey into Nyx|999|U|{2}{R}{R}|Enchantment Creature - Nymph|||Constellation — Whenever Forgeborn Oreads or another enchantment enters the battlefield under your control, Forgeborn Oreads deals 1 damage to target creature or player.| +Forgeborn Oreads|Journey into Nyx|98|U|{2}{R}{R}|Enchantment Creature - Nymph|||Constellation — Whenever Forgeborn Oreads or another enchantment enters the battlefield under your control, Forgeborn Oreads deals 1 damage to target creature or player.| +Prophetic Flamespeaker|Journey into Nyx|165|M|{1}{R}{R}|Creature - Human Shaman|1|3|Double strike, trample$Whenever Prophetic Flamespeaker deals combat damage to a player, exile the top card of your library. You may play it this turn.| +Twinflame|Journey into Nyx|115|R|{1}{R}|Sorcery|||Strive - Twinflame costs 2R more to cast for each target beyond the first.$Choose any number of target creatures you control. For each of them, put a token that's a copy of that creature onto the battlefield. Those tokens have haste. Exile them at the beginning of the next end step.| +Master of the Feast|Journey into Nyx|75|R|{1}{B}{B}|Enchantment Creature - Demon|5|5|Flying$At the beginning of your upkeep, each opponent draws a card.| +Pharika, God of Affliction|Journey into Nyx|154|M|{1}{B}{G}|Legendary Enchantment Creature - God|5|5|Indestructible$As long as your devotion to black and green is less than seven, Pharika isn't a creature.$BG: Exile target creature card from a graveyard. It's owner puts a 1/1 black and green Snake enchantment creature token with deathtouch onto the battlefield.| +Riddle of Lightning|Journey into Nyx|107|U|{3}{R}{R}|Instant|||Choose target creature or player. Scry 3, then reveal the top card of your library. Riddle of Lightning deals damage equal to that card's converted mana cost to that creature or player.| +Riptide Chimera|Journey into Nyx|999|U|{2}{U}|Enchantment Creature - Chimera|3|4|Flying$At the beginning of your upkeep, return an enchanment you control to its owner's hand.| +Nyx-Fleece Ram|Journey into Nyx|18|U|{1}{W}|Enchantment Creature - Sheep|0|5|At the beginning of your upkeep, you gain 1 life.| +Daring Thief|Journey into Nyx|36|R|{2}{U}|Creature - Human Rogue|2|3|Inspired - Whenever Daring Thief becomes untapped, you may exchange control of target nonland permanent you control and target permanent an opponent controls that shares a card type with it.| +Battlefield Thaumaturge|Journey into Nyx|32|R|{1}{U}|Creature - Human Wizard|2|1|Each instant and sorcery spell you cast costs 1 less to cast for each creature it targets.$Heroic - Whenever you cast a spell that targets Battlefield Thaumaturge, Battlefield Thaumaturge gains hexproof until end of turn.| +Eidolon of Rhetoric|Journey into Nyx|10|U|{2}{W}|Enchantment Creature - Spirit|1|4|Each player can't cast more than one spell each turn.| +Aegis of the Gods|Journey into Nyx|1|R|{1}{W}|Enchantment Creature - Human Soldier|2|2|You have hexproof.| +Bearer of the Heavens|Journey into Nyx|999|R|{7}{R}|Creature - Giant|10|10|When Bearer of the Heavens dies, destroy all permanents at the beginning of the next end step.|