1
0
Fork 0
mirror of https://github.com/correl/mage.git synced 2025-04-02 03:18:09 -09:00

Fixed some put into graveyard effects that were implemented wrongly as triggered effects to replacment effects (LegacyWeapon, Progenitus, Darksteel Colossus, Blightsteel Colossus).

This commit is contained in:
LevelX2 2014-08-21 15:13:29 +02:00
parent cc676b2258
commit b094df2a52
11 changed files with 424 additions and 186 deletions
Mage.Sets/src/mage/sets
Mage.Tests/src/test/java/org/mage/test/cards/replacement
Mage/src/mage

View file

@ -29,21 +29,14 @@ package mage.sets.apocalypse;
import java.util.UUID;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.abilities.Ability;
import mage.abilities.common.PutIntoGraveFromAnywhereTriggeredAbility;
import mage.abilities.common.PutIntoGraveFromAnywhereAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ExileTargetEffect;
import mage.cards.Card;
import mage.abilities.effects.common.RevealAndShuffleIntoLibrarySourceEffect;
import mage.cards.CardImpl;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetPermanent;
/**
@ -64,7 +57,7 @@ public class LegacyWeapon extends CardImpl {
ability.addTarget(new TargetPermanent());
this.addAbility(ability);
// If Legacy Weapon would be put into a graveyard from anywhere, reveal Legacy Weapon and shuffle it into its owner's library instead.
this.addAbility(new PutIntoGraveFromAnywhereTriggeredAbility(new LegacyWeaponEffect()));
this.addAbility(new PutIntoGraveFromAnywhereAbility(new RevealAndShuffleIntoLibrarySourceEffect()));
}
public LegacyWeapon(final LegacyWeapon card) {
@ -76,37 +69,3 @@ public class LegacyWeapon extends CardImpl {
return new LegacyWeapon(this);
}
}
class LegacyWeaponEffect extends OneShotEffect {
public LegacyWeaponEffect() {
super(Outcome.Benefit);
this.staticText = "reveal {this} and shuffle it into its owner's library instead";
}
public LegacyWeaponEffect(final LegacyWeaponEffect effect) {
super(effect);
}
@Override
public LegacyWeaponEffect copy() {
return new LegacyWeaponEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Card card = game.getCard(source.getSourceId());
if (card != null) {
Player player = game.getPlayer(card.getOwnerId());
if (player != null) {
Cards cards = new CardsImpl();
cards.add(card);
player.revealCards("Legacy Weapon", cards, game);
card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);
player.shuffleLibrary(game);
return true;
}
}
return false;
}
}

View file

@ -30,21 +30,14 @@ package mage.sets.conflux;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.PutIntoGraveFromAnywhereTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.common.PutIntoGraveFromAnywhereAbility;
import mage.abilities.effects.common.RevealAndShuffleIntoLibrarySourceEffect;
import mage.abilities.keyword.ProtectionAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.game.Game;
import mage.players.Player;
/**
*
@ -72,10 +65,11 @@ public class Progenitus extends CardImpl {
// spells or abilities, and all damage that would be dealt to Progenitus is prevented.
// 2/1/2009: Progenitus can still be affected by effects that don't target it or deal damage
// to it (such as Day of Judgment).
// Protection from everything
this.addAbility(new ProgenitusProtectionAbility());
// If Progenitus would be put into a graveyard from anywhere, reveal Progenitus and shuffle it into its owner's library instead.
this.addAbility(new PutIntoGraveFromAnywhereTriggeredAbility(new ProgenitusEffect()));
this.addAbility(new PutIntoGraveFromAnywhereAbility(new RevealAndShuffleIntoLibrarySourceEffect()));
}
public Progenitus(final Progenitus card) {
@ -113,37 +107,3 @@ class ProgenitusProtectionAbility extends ProtectionAbility {
return false;
}
}
class ProgenitusEffect extends OneShotEffect {
public ProgenitusEffect() {
super(Outcome.Benefit);
this.staticText = "reveal {this} and shuffle it into its owner's library instead";
}
public ProgenitusEffect(final ProgenitusEffect effect) {
super(effect);
}
@Override
public ProgenitusEffect copy() {
return new ProgenitusEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Card card = game.getCard(source.getSourceId());
if (card != null) {
Player player = game.getPlayer(card.getOwnerId());
if (player != null) {
Cards cards = new CardsImpl();
cards.add(card);
player.revealCards("Progenitus", cards, game);
card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);
player.shuffleLibrary(game);
return true;
}
}
return false;
}
}

View file

@ -33,19 +33,11 @@ import java.util.UUID;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.PutIntoGraveFromAnywhereTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.common.PutIntoGraveFromAnywhereAbility;
import mage.abilities.effects.common.RevealAndShuffleIntoLibrarySourceEffect;
import mage.abilities.keyword.IndestructibleAbility;
import mage.abilities.keyword.TrampleAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
/**
* @author Loki
@ -58,9 +50,15 @@ public class DarksteelColossus extends CardImpl {
this.subtype.add("Golem");
this.power = new MageInt(11);
this.toughness = new MageInt(11);
// Trample
this.addAbility(TrampleAbility.getInstance());
// Darksteel Colossus is indestructible.
this.addAbility(IndestructibleAbility.getInstance());
this.addAbility(new PutIntoGraveFromAnywhereTriggeredAbility(new DarksteelColossusEffect(), false));
// If Darksteel Colossus would be put into a graveyard from anywhere, reveal Darksteel Colossus and shuffle it into its owner's library instead.
this.addAbility(new PutIntoGraveFromAnywhereAbility(new RevealAndShuffleIntoLibrarySourceEffect()));
}
public DarksteelColossus(final DarksteelColossus card) {
@ -73,37 +71,3 @@ public class DarksteelColossus extends CardImpl {
}
}
class DarksteelColossusEffect extends OneShotEffect {
DarksteelColossusEffect() {
super(Outcome.Benefit);
staticText = "reveal {this} and shuffle it into its owner's library instead";
}
DarksteelColossusEffect(final DarksteelColossusEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Card c = game.getCard(source.getSourceId());
if (c != null) {
Player player = game.getPlayer(c.getOwnerId());
if (player != null) {
Cards cards = new CardsImpl();
cards.add(c);
player.revealCards("Blightsteel Colossus", cards, game);
c.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);
player.shuffleLibrary(game);
return true;
}
}
return false;
}
@Override
public DarksteelColossusEffect copy() {
return new DarksteelColossusEffect(this);
}
}

View file

@ -68,10 +68,12 @@ public class LilianaOfTheVeil extends CardImpl {
// +1: Each player discards a card.
this.addAbility(new LoyaltyAbility(new DiscardEachPlayerEffect(), 1));
// -2: Target player sacrifices a creature.
LoyaltyAbility ability = new LoyaltyAbility(new SacrificeEffect(new FilterCreaturePermanent(), 1, "Target player"), -2);
ability.addTarget(new TargetPlayer());
this.addAbility(ability);
// -6: Separate all permanents target player controls into two piles. That player sacrifices all permanents in the pile of his or her choice.
ability = new LoyaltyAbility(new LilianaOfTheVeilEffect(), -6);
ability.addTarget(new TargetPlayer());

View file

@ -33,20 +33,12 @@ import java.util.UUID;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.PutIntoGraveFromAnywhereTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.common.PutIntoGraveFromAnywhereAbility;
import mage.abilities.effects.common.RevealAndShuffleIntoLibrarySourceEffect;
import mage.abilities.keyword.IndestructibleAbility;
import mage.abilities.keyword.InfectAbility;
import mage.abilities.keyword.TrampleAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
/**
* @author Loki
@ -59,10 +51,16 @@ public class BlightsteelColossus extends CardImpl {
this.subtype.add("Golem");
this.power = new MageInt(11);
this.toughness = new MageInt(11);
// Trample, infect
this.addAbility(TrampleAbility.getInstance());
this.addAbility(InfectAbility.getInstance());
// Blightsteel Colossus is indestructible.
this.addAbility(IndestructibleAbility.getInstance());
this.addAbility(new PutIntoGraveFromAnywhereTriggeredAbility(new BlightsteelColossusEffect(), false));
// If Blightsteel Colossus would be put into a graveyard from anywhere, reveal Blightsteel Colossus and shuffle it into its owner's library instead.
this.addAbility(new PutIntoGraveFromAnywhereAbility(new RevealAndShuffleIntoLibrarySourceEffect()));
}
public BlightsteelColossus(final BlightsteelColossus card) {
@ -75,37 +73,3 @@ public class BlightsteelColossus extends CardImpl {
}
}
class BlightsteelColossusEffect extends OneShotEffect {
BlightsteelColossusEffect() {
super(Outcome.Benefit);
staticText = "reveal {this} and shuffle it into its owner's library";
}
BlightsteelColossusEffect(final BlightsteelColossusEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Card c = game.getCard(source.getSourceId());
if (c != null) {
Player player = game.getPlayer(c.getOwnerId());
if (player != null) {
Cards cards = new CardsImpl();
cards.add(c);
player.revealCards("Blightsteel Colossus", cards, game);
c.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);
player.shuffleLibrary(game);
return true;
}
}
return false;
}
@Override
public BlightsteelColossusEffect copy() {
return new BlightsteelColossusEffect(this);
}
}

View file

@ -104,7 +104,7 @@ class DryadMilitantReplacementEffect extends ReplacementEffectImpl {
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (event.getType() == GameEvent.EventType.ZONE_CHANGE && ((ZoneChangeEvent)event).getToZone() == Zone.GRAVEYARD) {
Card card = (Card) game.getCard(event.getTargetId());
Card card = game.getCard(event.getTargetId());
if (card != null && (card.getCardType().contains(CardType.SORCERY) || card.getCardType().contains(CardType.INSTANT))) {
return true;
}

View file

@ -165,10 +165,7 @@ class RestInPeaceReplacementEffect extends ReplacementEffectImpl {
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (event.getType() == GameEvent.EventType.ZONE_CHANGE && ((ZoneChangeEvent)event).getToZone() == Zone.GRAVEYARD) {
return true;
}
return false;
return event.getType() == GameEvent.EventType.ZONE_CHANGE && ((ZoneChangeEvent)event).getToZone() == Zone.GRAVEYARD;
}
}

View file

@ -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 org.mage.test.cards.replacement;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
* Checks if change zone replacement effects work as intended
*
* @author LevelX2
*/
public class ZoneChangeReplacementTest extends CardTestPlayerBase {
// If Darksteel Colossus would be put into a graveyard from anywhere,
// reveal Darksteel Colossus and shuffle it into its owner's library instead.
@Test
public void testFromLibraryZoneChange() {
addCard(Zone.LIBRARY, playerA, "Darksteel Colossus");
// Tome Scour - Sorcery - {U}
// Target player puts the top five cards of his or her library into his or her graveyard.
addCard(Zone.HAND, playerA, "Tome Scour");
addCard(Zone.BATTLEFIELD, playerA, "Island", 1);
skipInitShuffling();
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Tome Scour", playerA);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertGraveyardCount(playerA, "Darksteel Colossus", 0);
assertGraveyardCount(playerA, 5); // 4 + Tome Scour
}
@Test
public void testFromHandZoneChange() {
addCard(Zone.HAND, playerA, "Progenitus");
// Distress - Sorcery - {B}{B}
// Target player reveals his or her hand. You choose a nonland card from it. That player discards that card.
addCard(Zone.HAND, playerA, "Distress");
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Distress", playerA);
setChoice(playerA, "Progenitus");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertGraveyardCount(playerA, "Progenitus", 0);
assertGraveyardCount(playerA, 1); // Distress
assertHandCount(playerA, "Progenitus", 0);
}
@Test
public void checkBridgeDoesWork() {
addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion");
// Diabolic Edict - Instant - {1}{B}
// Target player sacrifices a creature.
addCard(Zone.HAND, playerA, "Diabolic Edict");
// Whenever a nontoken creature is put into your graveyard from the battlefield, if Bridge from
// Below is in your graveyard, put a 2/2 black Zombie creature token onto the battlefield.
addCard(Zone.GRAVEYARD, playerA, "Bridge from Below");
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Diabolic Edict", playerA);
setChoice(playerA, "Silvercoat Lion");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertGraveyardCount(playerA, "Silvercoat Lion", 1);
assertGraveyardCount(playerA, 3); // Diabolic Edict + Bridge from Below + Silvercoat Lion
assertPermanentCount(playerA, "Zombie", 1); // Silvercoat Lion goes to graveyard so a Zombie tokes is created
}
@Test
public void testDoesntTriggerDiesTriggeredAbilities() {
addCard(Zone.BATTLEFIELD, playerA, "Progenitus");
// Diabolic Edict - Instant - {1}{B}
// Target player sacrifices a creature.
addCard(Zone.HAND, playerA, "Diabolic Edict");
// Whenever a nontoken creature is put into your graveyard from the battlefield, if Bridge from
// Below is in your graveyard, put a 2/2 black Zombie creature token onto the battlefield.
addCard(Zone.GRAVEYARD, playerA, "Bridge from Below");
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Diabolic Edict", playerA);
setChoice(playerA, "Progenitus");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertGraveyardCount(playerA, "Progenitus", 0);
assertGraveyardCount(playerA, 2); // Diabolic Edict + Bridge from Below
assertPermanentCount(playerA, "Zombie", 0); // Progenitus never touches graveyard - so no Zombie tokes is created
}
}

View file

@ -0,0 +1,176 @@
/*
* 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.common;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.condition.Condition;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.Effect;
import mage.abilities.effects.Effects;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.constants.Duration;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.ZoneChangeEvent;
import mage.game.stack.Spell;
import mage.players.Player;
/**
*
* @author LevelX2
*/
public class PutIntoGraveFromAnywhereAbility extends SimpleStaticAbility {
public PutIntoGraveFromAnywhereAbility(Effect baseEffect) {
this(baseEffect, null, "", true, false);
}
public PutIntoGraveFromAnywhereAbility(Effect baseEffect, Condition condition, String text, boolean selfScope, boolean optional) {
super(Zone.ALL, new PutIntoGraveFromAnywhereEffect(baseEffect, condition, text, selfScope, optional));
}
public PutIntoGraveFromAnywhereAbility(final PutIntoGraveFromAnywhereAbility ability) {
super(ability);
}
@Override
public SimpleStaticAbility copy() {
return new PutIntoGraveFromAnywhereAbility(this);
}
@Override
public String getRule() {
return "If {this} would be put into a graveyard from anywhere, " + super.getRule();
}
}
class PutIntoGraveFromAnywhereEffect extends ReplacementEffectImpl {
protected Effects baseEffects = new Effects();
protected String text;
protected Condition condition;
protected boolean optional;
public static final String SOURCE_CAST_SPELL_ABILITY = "sourceCastSpellAbility";
public PutIntoGraveFromAnywhereEffect(Effect baseEffect) {
this(baseEffect, "");
}
public PutIntoGraveFromAnywhereEffect(Effect baseEffect, String text) {
this(baseEffect, null, text, true, false);
}
public PutIntoGraveFromAnywhereEffect(Effect baseEffect, String text, boolean optional) {
this(baseEffect, null, text, true, optional);
}
public PutIntoGraveFromAnywhereEffect(Effect baseEffect, Condition condition, String text) {
this(baseEffect, condition, text, true, false);
}
public PutIntoGraveFromAnywhereEffect(Effect baseEffect, Condition condition, String text, boolean selfScope, boolean optional) {
super(Duration.EndOfGame, baseEffect.getOutcome(), selfScope);
this.baseEffects.add(baseEffect);
this.text = text;
this.condition = condition;
this.optional = optional;
}
public PutIntoGraveFromAnywhereEffect(PutIntoGraveFromAnywhereEffect effect) {
super(effect);
this.baseEffects = effect.baseEffects.copy();
this.text = effect.text;
this.condition = effect.condition;
this.optional = effect.optional;
}
public void addEffect(Effect effect) {
baseEffects.add(effect);
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (GameEvent.EventType.ZONE_CHANGE.equals(event.getType())
&& ((ZoneChangeEvent)event).getToZone() == Zone.GRAVEYARD
&& event.getTargetId().equals(source.getSourceId())) {
if (condition == null || condition.apply(game, source)) {
return true;
}
}
return false;
}
@Override
public boolean apply(Game game, Ability source) {
return false;
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
if (optional) {
Player controller = game.getPlayer(source.getControllerId());
MageObject object = game.getObject(source.getSourceId());
if (controller == null || object == null) {
return false;
}
if (!controller.chooseUse(outcome, new StringBuilder("Use effect of ").append(object.getLogName()).append("?").toString(), game)) {
return false;
}
}
Spell spell = game.getStack().getSpell(event.getSourceId());
for (Effect effect: baseEffects) {
if (effect instanceof ContinuousEffect) {
game.addEffect((ContinuousEffect) effect, source);
}
else {
if (spell != null) {
effect.setValue(SOURCE_CAST_SPELL_ABILITY, spell.getSpellAbility());
}
effect.apply(game, source);
}
}
return true;
}
@Override
public String getText(Mode mode) {
return (text == null || text.isEmpty()) ? baseEffects.getText(mode) : text;
}
@Override
public PutIntoGraveFromAnywhereEffect copy() {
return new PutIntoGraveFromAnywhereEffect(this);
}
}

View file

@ -0,0 +1,82 @@
/*
* 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.effects.common;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
/**
*
* @author LevelX2
*/
public class RevealAndShuffleIntoLibrarySourceEffect extends OneShotEffect {
public RevealAndShuffleIntoLibrarySourceEffect() {
super(Outcome.Neutral);
staticText = "reveal {this} and shuffle it into its owner's library instead";
}
public RevealAndShuffleIntoLibrarySourceEffect(final RevealAndShuffleIntoLibrarySourceEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Card sourceCard = game.getCard(source.getSourceId());
MageObject sourceObject = game.getObject(source.getSourceId());
if (sourceCard != null) {
Player player = game.getPlayer(sourceCard.getOwnerId());
if (player != null) {
Zone fromZone = game.getState().getZone(sourceCard.getId());
Cards cards = new CardsImpl();
cards.add(sourceCard);
player.revealCards(sourceObject.getLogName(), cards, game);
player.moveCardToLibraryWithInfo(sourceCard, source.getSourceId(), game, fromZone, true, true);
player.shuffleLibrary(game);
return true;
}
}
return false;
}
@Override
public RevealAndShuffleIntoLibrarySourceEffect copy() {
return new RevealAndShuffleIntoLibrarySourceEffect(this);
}
}

View file

@ -631,13 +631,14 @@ public abstract class PlayerImpl implements Player, Serializable {
the moment before the cost was paid (see rule 717, "Handling Illegal Actions").
*/
if (card != null) {
// write info to game log first so game log infos from triggered or replacement effects follow in the game log
game.informPlayers(new StringBuilder(name).append(" discards ").append(card.getName()).toString());
/* If a card is discarded while Rest in Peace is on the battlefield, abilities that function
* when a card is discarded (such as madness) still work, even though that card never reaches
* a graveyard. In addition, spells or abilities that check the characteristics of a discarded
* card (such as Chandra Ablaze's first ability) can find that card in exile. */
* card (such as Chandra Ablaze's first ability) can find that card in exile. */
card.moveToZone(Zone.GRAVEYARD, source==null?null:source.getSourceId(), game, false);
// So discard is also successful if card is moved to another zone by replacement effect!
card.moveToZone(Zone.GRAVEYARD, source==null?null:source.getSourceId(), game, false);
game.informPlayers(new StringBuilder(name).append(" discards ").append(card.getName()).toString());
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.DISCARDED_CARD, card.getId(), source==null?null:source.getSourceId(), playerId));
return true;
}