From 6cc2ac0e707f73d63338811c49cac264660c66ed Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Mon, 28 Sep 2015 19:27:51 +0200 Subject: [PATCH 1/5] * Zada, Hedron Grinder - Fixed a bug with checking and copying modal spells. --- .../battleforzendikar/ZadaHedronGrinder.java | 42 +++++++++----- .../mage/test/cards/copy/CopySpellTest.java | 58 +++++++++++++++++++ 2 files changed, 85 insertions(+), 15 deletions(-) diff --git a/Mage.Sets/src/mage/sets/battleforzendikar/ZadaHedronGrinder.java b/Mage.Sets/src/mage/sets/battleforzendikar/ZadaHedronGrinder.java index 2e2648a2024..e34ac40666b 100644 --- a/Mage.Sets/src/mage/sets/battleforzendikar/ZadaHedronGrinder.java +++ b/Mage.Sets/src/mage/sets/battleforzendikar/ZadaHedronGrinder.java @@ -102,12 +102,15 @@ class ZadaHedronGrinderTriggeredAbility extends TriggeredAbilityImpl { Spell spell = game.getStack().getSpell(event.getTargetId()); if (isControlledInstantOrSorcery(spell)) { boolean targetsSource = false; - for (Target target : spell.getSpellAbility().getTargets()) { - for (UUID targetId : target.getTargets()) { - if (targetId.equals(getSourceId())) { - targetsSource = true; - } else { - return false; + for (UUID modeId : spell.getSpellAbility().getModes().getSelectedModes()) { + spell.getSpellAbility().getModes().setActiveMode(modeId); + for (Target target : spell.getSpellAbility().getTargets()) { + for (UUID targetId : target.getTargets()) { + if (targetId.equals(getSourceId())) { + targetsSource = true; + } else { + return false; + } } } } @@ -157,10 +160,15 @@ class ZadaHedronGrinderEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); if (spell != null && controller != null) { Target usedTarget = null; - for (Target target : spell.getSpellAbility().getTargets()) { - if (target.getFirstTarget().equals(source.getSourceId())) { - usedTarget = target.copy(); - usedTarget.clearChosen(); + setUsedTarget: + for (UUID modeId : spell.getSpellAbility().getModes().getSelectedModes()) { + spell.getSpellAbility().getModes().setActiveMode(modeId); + for (Target target : spell.getSpellAbility().getTargets()) { + if (target.getFirstTarget().equals(source.getSourceId())) { + usedTarget = target.copy(); + usedTarget.clearChosen(); + break setUsedTarget; + } } } if (usedTarget == null) { @@ -169,11 +177,15 @@ class ZadaHedronGrinderEffect extends OneShotEffect { for (Permanent creature : game.getState().getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), source.getControllerId(), game)) { if (!creature.getId().equals(source.getSourceId()) && usedTarget.canTarget(source.getControllerId(), creature.getId(), source, game)) { Spell copy = spell.copySpell(); - for (Target target : spell.getSpellAbility().getTargets()) { - if (target.getClass().equals(usedTarget.getClass()) && target.getMessage().equals(usedTarget.getMessage())) { - target.clearChosen(); - target.add(creature.getId(), game); - break; + setTarget: + for (UUID modeId : spell.getSpellAbility().getModes().getSelectedModes()) { + copy.getSpellAbility().getModes().setActiveMode(modeId); + for (Target target : copy.getSpellAbility().getTargets()) { + if (target.getClass().equals(usedTarget.getClass()) && target.getMessage().equals(usedTarget.getMessage())) { + target.clearChosen(); + target.add(creature.getId(), game); + break setTarget; + } } } copy.setControllerId(source.getControllerId()); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/copy/CopySpellTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/copy/CopySpellTest.java index c9736f2aa00..e3701dd6a48 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/copy/CopySpellTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/copy/CopySpellTest.java @@ -27,6 +27,7 @@ */ package org.mage.test.cards.copy; +import mage.abilities.keyword.FlyingAbility; import mage.constants.PhaseStep; import mage.constants.Zone; import org.junit.Test; @@ -61,4 +62,61 @@ public class CopySpellTest extends CardTestPlayerBase { assertHandCount(playerA, "Silvercoat Lion", 1); } + @Test + public void ZadaHedronGrinderBoost() { + // Target creature gets +3/+3 and gains flying until end of turn. + addCard(Zone.HAND, playerA, "Angelic Blessing", 1); // {2}{W} + addCard(Zone.BATTLEFIELD, playerA, "Plains", 3); + + // Whenever you cast an instant or sorcery spell that targets only Zada, Hedron Grinder, copy that spell for each other creature you control that the spell could target. Each copy targets a different one of those creatures. + addCard(Zone.BATTLEFIELD, playerA, "Zada, Hedron Grinder", 1); + addCard(Zone.BATTLEFIELD, playerA, "Pillarfield Ox", 1); + + addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Angelic Blessing", "Zada, Hedron Grinder"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertGraveyardCount(playerA, "Angelic Blessing", 1); + assertPowerToughness(playerA, "Pillarfield Ox", 5, 7); + assertAbility(playerA, "Pillarfield Ox", FlyingAbility.getInstance(), true); + assertPowerToughness(playerA, "Zada, Hedron Grinder", 6, 6); + assertAbility(playerA, "Zada, Hedron Grinder", FlyingAbility.getInstance(), true); + + assertPowerToughness(playerB, "Silvercoat Lion", 2, 2); + assertAbility(playerB, "Silvercoat Lion", FlyingAbility.getInstance(), false); + } + + @Test + public void ZadaHedronGrinderBoostWithCharm() { + // Choose two - + // • Counter target spell. + // • Return target permanent to its owner's hand. + // • Tap all creatures your opponents control. + // • Draw a card. + addCard(Zone.HAND, playerA, "Cryptic Command", 1); // {2}{U}{U}{U} + addCard(Zone.BATTLEFIELD, playerA, "Island", 4); + + // Whenever you cast an instant or sorcery spell that targets only Zada, Hedron Grinder, copy that spell for each other creature you control that the spell could target. Each copy targets a different one of those creatures. + addCard(Zone.BATTLEFIELD, playerA, "Zada, Hedron Grinder", 1); + addCard(Zone.BATTLEFIELD, playerA, "Pillarfield Ox", 1); + + addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cryptic Command", "mode=2Zada, Hedron Grinder"); + setModeChoice(playerA, "2"); // Return target permanent to its owner's hand + setModeChoice(playerA, "4"); // Draw a card + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPowerToughness(playerB, "Silvercoat Lion", 2, 2); + + assertGraveyardCount(playerA, "Cryptic Command", 1); + assertPermanentCount(playerA, "Zada, Hedron Grinder", 0); + assertPermanentCount(playerA, "Pillarfield Ox", 0); + assertHandCount(playerA, 4); // 2 draw + 2 creatures returned to hand + } } From 8108894da1116c5270f3ea2569057e45edd2ba83 Mon Sep 17 00:00:00 2001 From: fireshoes Date: Mon, 28 Sep 2015 15:54:05 -0500 Subject: [PATCH 2/5] Updated Legacy, Vintage, and Duel Commander banlists --- .../Mage.Deck.Constructed/src/mage/deck/DuelCommander.java | 3 ++- .../Mage.Deck.Constructed/src/mage/deck/Legacy.java | 4 ++-- .../Mage.Deck.Constructed/src/mage/deck/Vintage.java | 5 +++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/DuelCommander.java b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/DuelCommander.java index feb71b5e85a..a380531598e 100644 --- a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/DuelCommander.java +++ b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/DuelCommander.java @@ -64,11 +64,12 @@ public class DuelCommander extends Commander { banned.add("Mox Pearl"); banned.add("Mox Ruby"); banned.add("Mox Sapphire"); - banned.add("Mystical Tutor"); // banned effective July 17, 2015 + banned.add("Mystical Tutor"); banned.add("Natural Order"); banned.add("Necropotence"); banned.add("Oath of Druids"); banned.add("Protean Hulk"); + banned.add("Sensei's Divining Top"); banned.add("Serra Ascendant"); banned.add("Shahrazad"); banned.add("Sol Ring"); diff --git a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Legacy.java b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Legacy.java index f06a58d238f..f8c24589b7b 100644 --- a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Legacy.java +++ b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Legacy.java @@ -46,7 +46,6 @@ public class Legacy extends Constructed { banned.add("Balance"); banned.add("Bazaar of Baghdad"); banned.add("Black Lotus"); - banned.add("Black Vise"); banned.add("Brago's Favor"); banned.add("Bronze Tablet"); banned.add("Channel"); @@ -56,6 +55,7 @@ public class Legacy extends Constructed { banned.add("Demonic Attorney"); banned.add("Demonic Consultation"); banned.add("Demonic Tutor"); + banned.add("Dig Through Time"); banned.add("Double Stroke"); banned.add("Earthcraft"); banned.add("Falling Star"); @@ -104,7 +104,7 @@ public class Legacy extends Constructed { banned.add("Timmerian Fiends"); banned.add("Tinker"); banned.add("Tolarian Academy"); - banned.add("Treasure Cruise"); // banned effective January 23, 2015 + banned.add("Treasure Cruise"); banned.add("Unexpected Potential"); banned.add("Vampiric Tutor"); banned.add("Wheel of Fortune"); diff --git a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Vintage.java b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Vintage.java index c329a3accac..ef3efea54f2 100644 --- a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Vintage.java +++ b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Vintage.java @@ -70,8 +70,10 @@ public class Vintage extends Constructed { restricted.add("Black Lotus"); restricted.add("Brainstorm"); restricted.add("Channel"); + restricted.add("Chalice of the Void"); restricted.add("Demonic Consultation"); restricted.add("Demonic Tutor"); + restricted.add("Dig Through Time"); restricted.add("Fastbond"); restricted.add("Flash"); restricted.add("Imperial Seal"); @@ -93,13 +95,12 @@ public class Vintage extends Constructed { restricted.add("Ponder"); restricted.add("Sol Ring"); restricted.add("Strip Mine"); - restricted.add("Thirst for Knowledge"); restricted.add("Time Vault"); restricted.add("Time Walk"); restricted.add("Timetwister"); restricted.add("Tinker"); restricted.add("Tolarian Academy"); - restricted.add("Treasure Cruise"); // banned effective January 23, 2015 + restricted.add("Treasure Cruise"); restricted.add("Trinisphere"); restricted.add("Vampiric Tutor"); restricted.add("Wheel of Fortune"); From 707358f875c6e8d64b4118dc02d3f767ad3fad7d Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Tue, 29 Sep 2015 00:36:08 +0200 Subject: [PATCH 3/5] Fixed a bug that effects forcing creatures to block an attacker forced also creatures of players not attacked (multiplayer games) to block, locking the game UI. --- Mage/src/mage/game/combat/Combat.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Mage/src/mage/game/combat/Combat.java b/Mage/src/mage/game/combat/Combat.java index d8d815e94e9..b07f052ff3c 100644 --- a/Mage/src/mage/game/combat/Combat.java +++ b/Mage/src/mage/game/combat/Combat.java @@ -525,6 +525,10 @@ public class Combat implements Serializable, Copyable { // has cost to block to pay so remove this attacker continue; } + if (!getDefendingPlayerId(attackingCreatureId, game).equals(possibleBlocker.getControllerId())) { + // Creature can't block if not the controller or a planeswalker of the controller of the possible blocker is attacked + continue; + } if (creatureMustBlockAttackers.containsKey(possibleBlocker.getId())) { creatureMustBlockAttackers.get(possibleBlocker.getId()).add(attackingCreatureId); } else { @@ -729,6 +733,10 @@ public class Combat implements Serializable, Copyable { if (creatureForcedToBlock == null) { break; } + if (!creatureForcedToBlock.getControllerId().equals(player.getId())) { + // ignore creatures controlled by other players + continue; + } // // check if creature has to pay a cost to block so it's not mandatory to block // boolean removedAttacker = false; @@ -1133,10 +1141,10 @@ public class Combat implements Serializable, Copyable { return defenderId; } - public UUID getDefendingPlayerId(UUID attackerId, Game game) { + public UUID getDefendingPlayerId(UUID attackingCreatureId, Game game) { UUID defenderId = null; for (CombatGroup group : groups) { - if (group.getAttackers().contains(attackerId)) { + if (group.getAttackers().contains(attackingCreatureId)) { defenderId = group.getDefenderId(); if (group.defenderIsPlaneswalker) { Permanent permanent = game.getPermanent(defenderId); From 8f086c8c7e2a7d9f131a8a0d423cbccab65f135f Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Tue, 29 Sep 2015 00:37:52 +0200 Subject: [PATCH 4/5] * Maelstrom Nexus - Fixed that the compared casting cost was always 5 instead of the casting cost of the spell that got Cascade. --- .../mage/sets/alarareborn/MaelstromNexus.java | 121 +++++++++--------- .../abilities/keyword/CascadeAbility.java | 85 ++++++------ Mage/src/mage/players/PlayerImpl.java | 4 +- 3 files changed, 102 insertions(+), 108 deletions(-) diff --git a/Mage.Sets/src/mage/sets/alarareborn/MaelstromNexus.java b/Mage.Sets/src/mage/sets/alarareborn/MaelstromNexus.java index 6a4f024517a..655dea82e26 100644 --- a/Mage.Sets/src/mage/sets/alarareborn/MaelstromNexus.java +++ b/Mage.Sets/src/mage/sets/alarareborn/MaelstromNexus.java @@ -27,21 +27,28 @@ */ package mage.sets.alarareborn; +import java.util.HashMap; +import java.util.Map; import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.TriggeredAbilityImpl; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.keyword.CascadeAbility; import mage.cards.CardImpl; 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.WatcherScope; import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; import mage.game.stack.Spell; -import mage.target.targetpointer.FixedTarget; +import mage.game.stack.StackObject; +import mage.players.Player; import mage.watchers.Watcher; /** @@ -55,7 +62,7 @@ public class MaelstromNexus extends CardImpl { this.expansionSetCode = "ARB"; // The first spell you cast each turn has cascade. - this.addAbility(new MaelstromNexusTriggeredAbility(), new FirstSpellCastThisTurnWatcher()); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new MaelstromNexusGainCascadeFirstSpellEffect()), new FirstSpellCastThisTurnWatcher()); } @@ -69,52 +76,51 @@ public class MaelstromNexus extends CardImpl { } } -class MaelstromNexusTriggeredAbility extends TriggeredAbilityImpl { +class MaelstromNexusGainCascadeFirstSpellEffect extends ContinuousEffectImpl { - public MaelstromNexusTriggeredAbility() { - super(Zone.BATTLEFIELD, new CascadeEffect()); + private Ability cascadeAbility = new CascadeAbility(); + + public MaelstromNexusGainCascadeFirstSpellEffect() { + super(Duration.WhileOnBattlefield, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility); + staticText = "The first spell you cast each turn has cascade"; } - public MaelstromNexusTriggeredAbility(MaelstromNexusTriggeredAbility ability) { - super(ability); + public MaelstromNexusGainCascadeFirstSpellEffect(final MaelstromNexusGainCascadeFirstSpellEffect effect) { + super(effect); } @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.SPELL_CAST; + public MaelstromNexusGainCascadeFirstSpellEffect copy() { + return new MaelstromNexusGainCascadeFirstSpellEffect(this); } - @Override - public boolean checkTrigger(GameEvent event, Game game) { - Spell spell = game.getStack().getSpell(event.getTargetId()); - FirstSpellCastThisTurnWatcher watcher = (FirstSpellCastThisTurnWatcher) game.getState().getWatchers().get("FirstSpellCastThisTurn", this.getSourceId()); - if (spell != null - && watcher != null - && watcher.conditionMet()) { - this.getEffects().get(0).setTargetPointer(new FixedTarget(spell.getSourceId())); + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + for (StackObject stackObject : game.getStack()) { + // only spells cast, so no copies of spells + if ((stackObject instanceof Spell) && !stackObject.isCopy() && stackObject.getControllerId().equals(source.getControllerId())) { + Spell spell = (Spell) stackObject; + FirstSpellCastThisTurnWatcher watcher = (FirstSpellCastThisTurnWatcher) game.getState().getWatchers().get("FirstSpellCastThisTurn"); + if (watcher != null && spell.getId().equals(watcher.getIdOfFirstCastSpell(source.getControllerId()))) { + game.getState().addOtherAbility(spell.getCard(), cascadeAbility); + } + } + } return true; } return false; } - - @Override - public MaelstromNexusTriggeredAbility copy() { - return new MaelstromNexusTriggeredAbility(this); - } - - @Override - public String getRule() { - return "The first spell you cast each turn has cascade."; - } } class FirstSpellCastThisTurnWatcher extends Watcher { - int spellCount = 0; + Map playerFirstSpellCast = new HashMap<>(); + Map playerFirstCastSpell = new HashMap<>(); public FirstSpellCastThisTurnWatcher() { - super("FirstSpellCastThisTurn", WatcherScope.CARD); + super("FirstSpellCastThisTurn", WatcherScope.GAME); } public FirstSpellCastThisTurnWatcher(final FirstSpellCastThisTurnWatcher watcher) { @@ -123,16 +129,18 @@ class FirstSpellCastThisTurnWatcher extends Watcher { @Override public void watch(GameEvent event, Game game) { - if (event.getType() == GameEvent.EventType.SPELL_CAST && event.getPlayerId() == controllerId) { - Spell spell = (Spell) game.getObject(event.getTargetId()); - if (spell != null) { - spellCount++; - if (spellCount == 1) { - condition = true; - } else { - condition = false; + switch (event.getType()) { + case SPELL_CAST: + case CAST_SPELL: + Spell spell = (Spell) game.getObject(event.getTargetId()); + if (spell != null && !playerFirstSpellCast.containsKey(spell.getControllerId())) { + if (event.getType().equals(EventType.SPELL_CAST)) { + playerFirstSpellCast.put(spell.getControllerId(), spell.getId()); + } else if (event.getType().equals(EventType.CAST_SPELL)) { + playerFirstCastSpell.put(spell.getControllerId(), spell.getId()); + } + } - } } } @@ -144,28 +152,15 @@ class FirstSpellCastThisTurnWatcher extends Watcher { @Override public void reset() { super.reset(); - spellCount = 0; + playerFirstSpellCast.clear(); + playerFirstCastSpell.clear(); + } + + public UUID getIdOfFirstCastSpell(UUID playerId) { + if (playerFirstSpellCast.get(playerId) == null) { + return playerFirstCastSpell.get(playerId); + } else { + return playerFirstSpellCast.get(playerId); + } } } - -class CascadeEffect extends OneShotEffect { - - public CascadeEffect() { - super(Outcome.PutCardInPlay); - } - - public CascadeEffect(CascadeEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - return CascadeAbility.applyCascade(outcome, game, source); - } - - @Override - public CascadeEffect copy() { - return new CascadeEffect(this); - } - -} diff --git a/Mage/src/mage/abilities/keyword/CascadeAbility.java b/Mage/src/mage/abilities/keyword/CascadeAbility.java index c4b6318f83b..5895bc79d71 100644 --- a/Mage/src/mage/abilities/keyword/CascadeAbility.java +++ b/Mage/src/mage/abilities/keyword/CascadeAbility.java @@ -1,37 +1,38 @@ /* -* 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. -*/ - + * 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.abilities.keyword; import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.OneShotEffect; import mage.cards.Card; +import mage.cards.Cards; +import mage.cards.CardsImpl; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.Zone; @@ -74,10 +75,7 @@ public class CascadeAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { Spell spell = game.getStack().getSpell(event.getTargetId()); - if (spell != null && spell.getSourceId().equals(this.getSourceId())) { - return true; - } - return false; + return spell != null && spell.getSourceId().equals(this.getSourceId()); } @Override @@ -95,7 +93,6 @@ public class CascadeAbility extends TriggeredAbilityImpl { } // moved to static method because it's called also from class {link} MaelstromNexus - public static boolean applyCascade(Outcome outcome, Game game, Ability source) { Card card; Player player = game.getPlayer(source.getControllerId()); @@ -109,31 +106,33 @@ public class CascadeAbility extends TriggeredAbilityImpl { if (card == null) { break; } - player.moveCardToExileWithInfo(card, exile.getId(), exile.getName(), source.getSourceId(), game, Zone.LIBRARY, true); + player.moveCardsToExile(card, source, game, true, exile.getId(), exile.getName()); } while (player.isInGame() && card.getCardType().contains(CardType.LAND) || card.getManaCost().convertedManaCost() >= sourceCost); player.getLibrary().reset(); if (card != null) { - if (player.chooseUse(outcome, "Use cascade effect on " + card.getName() + "?", source, game)) { - if(player.cast(card.getSpellAbility(), game, true)){ + if (player.chooseUse(outcome, "Use cascade effect on " + card.getLogName() + "?", source, game)) { + if (player.cast(card.getSpellAbility(), game, true)) { exile.remove(card.getId()); } } } - - while (exile.size() > 0) { - card = exile.getRandom(game); - exile.remove(card.getId()); - player.moveCardToLibraryWithInfo(card, source.getSourceId(), game, Zone.EXILED, false, false); + // Mobe the remaining cards to the buttom of the libraray in a random order + Cards cardsFromExile = new CardsImpl(); + Cards cardsToLibrary = new CardsImpl(); + cardsFromExile.addAll(exile); + while (cardsFromExile.size() > 0) { + card = cardsFromExile.getRandom(game); + cardsFromExile.remove(card.getId()); + cardsToLibrary.add(card); } - + player.putCardsOnBottomOfLibrary(cardsToLibrary, game, source, true); return true; } } // !!! Changes to the cascade effect here have to be copied to the cascadeEffect of Maelstrom Nexus card eventually. // There is a functional copy of this effect - class CascadeEffect extends OneShotEffect { public CascadeEffect() { @@ -185,5 +184,3 @@ class CascadeEffect extends OneShotEffect { } } - - diff --git a/Mage/src/mage/players/PlayerImpl.java b/Mage/src/mage/players/PlayerImpl.java index eb175ea8a29..d52568421d5 100644 --- a/Mage/src/mage/players/PlayerImpl.java +++ b/Mage/src/mage/players/PlayerImpl.java @@ -962,8 +962,10 @@ public abstract class PlayerImpl implements Player, Serializable { } } setCastSourceIdWithAlternateMana(null, null); + GameEvent event = GameEvent.getEvent(GameEvent.EventType.CAST_SPELL, spell.getSpellAbility().getId(), spell.getSpellAbility().getSourceId(), playerId); + game.fireEvent(event); if (spell.activate(game, noMana)) { - GameEvent event = GameEvent.getEvent(GameEvent.EventType.SPELL_CAST, spell.getSpellAbility().getId(), spell.getSpellAbility().getSourceId(), playerId); + event = GameEvent.getEvent(GameEvent.EventType.SPELL_CAST, spell.getSpellAbility().getId(), spell.getSpellAbility().getSourceId(), playerId); event.setZone(fromZone); game.fireEvent(event); if (!game.isSimulation()) { From e9dbfba7466f4c00bfe231dec99cb5f1f575ca71 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Tue, 29 Sep 2015 01:07:56 +0200 Subject: [PATCH 5/5] * Into the Core - Fixed that only the first target was exiled. --- .../sets/mirrodinbesieged/IntoTheCore.java | 23 ++++++++----------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/Mage.Sets/src/mage/sets/mirrodinbesieged/IntoTheCore.java b/Mage.Sets/src/mage/sets/mirrodinbesieged/IntoTheCore.java index ef3159e90c3..a66f5038a55 100644 --- a/Mage.Sets/src/mage/sets/mirrodinbesieged/IntoTheCore.java +++ b/Mage.Sets/src/mage/sets/mirrodinbesieged/IntoTheCore.java @@ -28,12 +28,12 @@ package mage.sets.mirrodinbesieged; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.Rarity; +import mage.abilities.effects.Effect; import mage.abilities.effects.common.ExileTargetEffect; import mage.cards.CardImpl; -import mage.filter.FilterPermanent; -import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.common.FilterArtifactPermanent; import mage.target.TargetPermanent; /** @@ -42,20 +42,15 @@ import mage.target.TargetPermanent; */ public class IntoTheCore extends CardImpl { - private static final FilterPermanent filter = new FilterPermanent("artifact"); - - static { - filter.add(new CardTypePredicate(CardType.ARTIFACT)); - } - public IntoTheCore(UUID ownerId) { super(ownerId, 67, "Into the Core", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{2}{R}{R}"); this.expansionSetCode = "MBS"; - - this.getSpellAbility().addTarget(new TargetPermanent(filter)); - this.getSpellAbility().addTarget(new TargetPermanent(filter)); - this.getSpellAbility().addEffect(new ExileTargetEffect()); + // Exile two target artifacts. + this.getSpellAbility().addTarget(new TargetPermanent(2, 2, new FilterArtifactPermanent("artifacts"), false)); + Effect effect = new ExileTargetEffect(); + effect.setText("Exile two target artifacts"); + this.getSpellAbility().addEffect(effect); } public IntoTheCore(final IntoTheCore card) {