diff --git a/Mage.Client/src/main/java/mage/client/util/layout/CardLayoutStrategy.java b/Mage.Client/src/main/java/mage/client/util/layout/CardLayoutStrategy.java
index 42fbd09e2b2..9e3615f6f69 100644
--- a/Mage.Client/src/main/java/mage/client/util/layout/CardLayoutStrategy.java
+++ b/Mage.Client/src/main/java/mage/client/util/layout/CardLayoutStrategy.java
@@ -1,6 +1,6 @@
package mage.client.util.layout;
-import javax.swing.*;
+import javax.swing.JLayeredPane;
/**
* Interface for operations that modify cards' layout
diff --git a/Mage.Client/src/main/java/mage/client/util/layout/impl/OldCardLayoutStrategy.java b/Mage.Client/src/main/java/mage/client/util/layout/impl/OldCardLayoutStrategy.java
index bcfef896a4d..47cd0d30e87 100644
--- a/Mage.Client/src/main/java/mage/client/util/layout/impl/OldCardLayoutStrategy.java
+++ b/Mage.Client/src/main/java/mage/client/util/layout/impl/OldCardLayoutStrategy.java
@@ -1,16 +1,16 @@
package mage.client.util.layout.impl;
+import java.awt.Dimension;
+import java.awt.Rectangle;
+import java.util.Map;
+import java.util.UUID;
+import javax.swing.JLayeredPane;
import mage.cards.MagePermanent;
import mage.client.game.BattlefieldPanel;
import mage.client.plugins.impl.Plugins;
import mage.client.util.layout.CardLayoutStrategy;
import mage.view.PermanentView;
-import javax.swing.*;
-import java.awt.*;
-import java.util.Map;
-import java.util.UUID;
-
/**
* Card layout for client version 1.3.0 and earlier.
*
@@ -54,14 +54,14 @@ public class OldCardLayoutStrategy implements CardLayoutStrategy {
}
int position = jLayeredPane.getPosition(perm);
perm.getLinks().clear();
- Rectangle r = perm.getBounds();
+ Rectangle rectangleBaseCard = perm.getBounds();
if (!Plugins.getInstance().isCardPluginLoaded()) {
for (UUID attachmentId: permanent.getAttachments()) {
MagePermanent link = permanents.get(attachmentId);
if (link != null) {
perm.getLinks().add(link);
- r.translate(20, 20);
- link.setBounds(r);
+ rectangleBaseCard.translate(20, 20);
+ link.setBounds(rectangleBaseCard);
jLayeredPane.setPosition(link, ++position);
}
}
@@ -70,14 +70,14 @@ public class OldCardLayoutStrategy implements CardLayoutStrategy {
for (UUID attachmentId: permanent.getAttachments()) {
MagePermanent link = permanents.get(attachmentId);
if (link != null) {
- link.setBounds(r);
+ link.setBounds(rectangleBaseCard);
perm.getLinks().add(link);
if (index == 1) {
- r.translate(ATTACHMENTS_DX_OFFSET, ATTACHMENT_DY_OFFSET); // do it once
+ rectangleBaseCard.translate(ATTACHMENTS_DX_OFFSET, ATTACHMENT_DY_OFFSET); // do it once
} else {
- r.translate(ATTACHMENT_DX_OFFSET, ATTACHMENT_DY_OFFSET);
+ rectangleBaseCard.translate(ATTACHMENT_DX_OFFSET, ATTACHMENT_DY_OFFSET);
}
- perm.setBounds(r);
+ perm.setBounds(rectangleBaseCard);
jLayeredPane.moveToFront(link);
jLayeredPane.moveToFront(perm);
jPanel.setComponentZOrder(link, index);
diff --git a/Mage.Sets/src/mage/sets/magic2012/AngelicDestiny.java b/Mage.Sets/src/mage/sets/magic2012/AngelicDestiny.java
index dd6e5e7e4aa..f9604ea6f25 100644
--- a/Mage.Sets/src/mage/sets/magic2012/AngelicDestiny.java
+++ b/Mage.Sets/src/mage/sets/magic2012/AngelicDestiny.java
@@ -28,11 +28,10 @@
package mage.sets.magic2012;
import java.util.UUID;
-
-import mage.constants.*;
import mage.abilities.Ability;
import mage.abilities.common.DiesAttachedTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.effects.Effect;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.ReturnToHandSourceEffect;
import mage.abilities.effects.common.continuous.AddCardSubtypeAttachedEffect;
@@ -42,6 +41,12 @@ import mage.abilities.keyword.EnchantAbility;
import mage.abilities.keyword.FirstStrikeAbility;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
+import mage.constants.AttachmentType;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.Outcome;
+import mage.constants.Rarity;
+import mage.constants.Zone;
import mage.target.TargetPermanent;
import mage.target.common.TargetCreaturePermanent;
@@ -56,19 +61,27 @@ public class AngelicDestiny extends CardImpl {
this.expansionSetCode = "M12";
this.subtype.add("Aura");
- this.color.setWhite(true);
-
+ // Enchant creature
TargetPermanent auraTarget = new TargetCreaturePermanent();
this.getSpellAbility().addTarget(auraTarget);
this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature));
Ability ability = new EnchantAbility(auraTarget.getTargetName());
this.addAbility(ability);
- this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEnchantedEffect(4, 4, Duration.WhileOnBattlefield)));
- this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(FlyingAbility.getInstance(), AttachmentType.AURA)));
- this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(FirstStrikeAbility.getInstance(), AttachmentType.AURA)));
- this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new AddCardSubtypeAttachedEffect("Angel", Duration.WhileOnBattlefield, AttachmentType.AURA)));
+ // Enchanted creature gets +4/+4, has flying and first strike, and is an Angel in addition to its other types.
+ ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEnchantedEffect(4, 4, Duration.WhileOnBattlefield));
+ Effect effect = new GainAbilityAttachedEffect(FlyingAbility.getInstance(), AttachmentType.AURA);
+ effect.setText(", has flying");
+ ability.addEffect(effect);
+ effect = new GainAbilityAttachedEffect(FirstStrikeAbility.getInstance(), AttachmentType.AURA);
+ effect.setText("and first strike");
+ ability.addEffect(effect);
+ effect = new AddCardSubtypeAttachedEffect("Angel", Duration.WhileOnBattlefield, AttachmentType.AURA);
+ effect.setText(", and is an Angel in addition to its other types");
+ ability.addEffect(effect);
+ this.addAbility(ability);
+ // When enchanted creature dies, return Angelic Destiny to its owner's hand.
this.addAbility(new DiesAttachedTriggeredAbility(new ReturnToHandSourceEffect(), "enchanted creature"));
}
diff --git a/Mage.Sets/src/mage/sets/mirrodin/IsochronScepter.java b/Mage.Sets/src/mage/sets/mirrodin/IsochronScepter.java
index b798db5fdf4..9ba91ef89fe 100644
--- a/Mage.Sets/src/mage/sets/mirrodin/IsochronScepter.java
+++ b/Mage.Sets/src/mage/sets/mirrodin/IsochronScepter.java
@@ -62,7 +62,7 @@ public class IsochronScepter extends CardImpl {
this.expansionSetCode = "MRD";
// Imprint - When Isochron Scepter enters the battlefield, you may exile an instant card with converted mana cost 2 or less from your hand.
- this.addAbility(new EntersBattlefieldTriggeredAbility(new IsochronScepterImprintEffect(), true, "Imprint - "));
+ this.addAbility(new EntersBattlefieldTriggeredAbility(new IsochronScepterImprintEffect(), true, "Imprint — "));
// {2}, {tap}: You may copy the exiled card. If you do, you may cast the copy without paying its mana cost.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new IsochronScepterCopyEffect(), new GenericManaCost(2));
diff --git a/Mage.Sets/src/mage/sets/returntoravnica/SoulTithe.java b/Mage.Sets/src/mage/sets/returntoravnica/SoulTithe.java
index aaefaae0b33..3c429990008 100644
--- a/Mage.Sets/src/mage/sets/returntoravnica/SoulTithe.java
+++ b/Mage.Sets/src/mage/sets/returntoravnica/SoulTithe.java
@@ -29,6 +29,7 @@
package mage.sets.returntoravnica;
import java.util.UUID;
+import mage.MageObject;
import mage.constants.AttachmentType;
import mage.constants.CardType;
import mage.constants.Duration;
@@ -64,7 +65,6 @@ public class SoulTithe extends CardImpl {
super(ownerId, 23, "Soul Tithe", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}");
this.expansionSetCode = "RTR";
this.subtype.add("Aura");
- this.color.setWhite(true);
// Enchant nonland permanent
TargetPermanent auraTarget = new TargetNonlandPermanent();
@@ -106,12 +106,12 @@ class SoulTitheSacrificeSourceUnlessPaysEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
Permanent permanent = game.getPermanent(source.getSourceId());
- if (player != null && permanent != null) {
+ MageObject sourceObject = source.getSourceObject(game);
+ if (player != null && permanent != null && sourceObject != null) {
int cmc = permanent.getManaCost().convertedManaCost();
- if (player.chooseUse(Outcome.Benefit, "Pay {" + cmc + "} for " + permanent.getName() + "?", game)) {
+ if (player.chooseUse(Outcome.Benefit, "Pay {" + cmc + "} for " + permanent.getName() + "? (otherwise you sacrifice it)", game)) {
Cost cost = new GenericManaCost(cmc);
- if (cost.pay(source, game, source.getSourceId(), source.getControllerId(), false))
- {
+ if (cost.pay(source, game, source.getSourceId(), source.getControllerId(), false)) {
return true;
}
}
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/copy/IsochronScepterTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/copy/IsochronScepterTest.java
index 8ca4ed754fa..a5b1a67587b 100644
--- a/Mage.Tests/src/test/java/org/mage/test/cards/copy/IsochronScepterTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/copy/IsochronScepterTest.java
@@ -111,4 +111,35 @@ public class IsochronScepterTest extends CardTestPlayerBase {
}
+ @Test
+ public void testAngelsGrace() {
+ addCard(Zone.BATTLEFIELD, playerA, "Plains", 4);
+ addCard(Zone.HAND, playerA, "Isochron Scepter");
+ addCard(Zone.HAND, playerA, "Angel's Grace");
+
+ addCard(Zone.BATTLEFIELD, playerB, "Dross Crocodile", 4);
+
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Isochron Scepter");
+ addTarget(playerA, "Angel's Grace");
+
+ attack(2, playerB, "Dross Crocodile");
+ attack(2, playerB, "Dross Crocodile");
+ attack(2, playerB, "Dross Crocodile");
+ attack(2, playerB, "Dross Crocodile");
+
+ activateAbility(2, PhaseStep.DECLARE_BLOCKERS, playerA, "{2},{T}:");
+ setChoice(playerA, "Yes");
+ setChoice(playerA, "Yes");
+
+ setStopAt(2, PhaseStep.END_COMBAT);
+ execute();
+
+ assertPermanentCount(playerA, "Isochron Scepter", 1);
+ assertExileCount("Angel's Grace", 1);
+ assertGraveyardCount(playerA, "Angel's Grace", 0);
+
+ assertLife(playerA, 1);
+ assertLife(playerB, 20);
+
+ }
}
diff --git a/Mage/src/mage/abilities/common/PutIntoGraveFromAnywhereSourceAbility.java b/Mage/src/mage/abilities/common/PutIntoGraveFromAnywhereSourceAbility.java
index 7571abf6262..f0f56848cb8 100644
--- a/Mage/src/mage/abilities/common/PutIntoGraveFromAnywhereSourceAbility.java
+++ b/Mage/src/mage/abilities/common/PutIntoGraveFromAnywhereSourceAbility.java
@@ -127,10 +127,8 @@ class PutIntoGraveFromAnywhereEffect extends ReplacementEffectImpl {
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (((ZoneChangeEvent)event).getToZone() == Zone.GRAVEYARD
- && event.getTargetId().equals(source.getSourceId()))
- {
- if (condition == null || condition.apply(game, source))
- {
+ && event.getTargetId().equals(source.getSourceId())) {
+ if (condition == null || condition.apply(game, source)) {
return true;
}
}
diff --git a/Mage/src/mage/abilities/effects/ContinuousEffects.java b/Mage/src/mage/abilities/effects/ContinuousEffects.java
index 4407e7b854a..ef6367aace6 100644
--- a/Mage/src/mage/abilities/effects/ContinuousEffects.java
+++ b/Mage/src/mage/abilities/effects/ContinuousEffects.java
@@ -351,10 +351,8 @@ public class ContinuousEffects implements Serializable {
if (ability.getAbilityType() != AbilityType.STATIC || ability.isInUseableZone(game, null, event)) {
if (effect.getDuration() != Duration.OneUse || !effect.isUsed()) {
if (!game.getScopeRelevant() || effect.hasSelfScope() || !event.getTargetId().equals(ability.getSourceId())) {
- if (checkAbilityStillExists(ability, effect, event, game)) { // TODO: This is really needed???
- if (effect.applies(event, ability, game)) {
- applicableAbilities.add(ability);
- }
+ if (effect.applies(event, ability, game)) {
+ applicableAbilities.add(ability);
}
}
}
diff --git a/Mage/src/mage/abilities/effects/ContinuousEffectsList.java b/Mage/src/mage/abilities/effects/ContinuousEffectsList.java
index f56ce23d94f..55e1a4e62d9 100644
--- a/Mage/src/mage/abilities/effects/ContinuousEffectsList.java
+++ b/Mage/src/mage/abilities/effects/ContinuousEffectsList.java
@@ -117,10 +117,15 @@ public class ContinuousEffectsList extends ArrayList
return false;
} else if (effect.isDiscarded()) {
it.remove();
- } else if (ability.getSourceId() != null && game.getObject(ability.getSourceId()) == null) { // Commander effects have no sourceId
- it.remove(); // if the related source object does no longer exist the effect has to be removed
} else {
switch(effect.getDuration()) {
+ case WhileOnBattlefield:
+ case WhileInGraveyard:
+ case WhileOnStack:
+ if (ability.getSourceId() != null && game.getObject(ability.getSourceId()) == null) { // Commander effects have no sourceId
+ it.remove(); // if the related source object does no longer exist in game - the effect has to be removed
+ }
+ break;
case OneUse:
if (effect.isUsed()) {
it.remove();
diff --git a/Mage/src/mage/game/GameImpl.java b/Mage/src/mage/game/GameImpl.java
index e532957cef5..997c93f8554 100644
--- a/Mage/src/mage/game/GameImpl.java
+++ b/Mage/src/mage/game/GameImpl.java
@@ -1424,6 +1424,35 @@ public abstract class GameImpl implements Game, Serializable {
Card card = copiedCards.next();
Zone zone = state.getZone(card.getId());
if (zone != Zone.BATTLEFIELD && zone != Zone.STACK) {
+ switch (zone) {
+ case GRAVEYARD:
+ for(Player player: getPlayers().values()) {
+ if (player.getGraveyard().contains(card.getId())) {
+ player.getGraveyard().remove(card);
+ break;
+ }
+ }
+ break;
+ case HAND:
+ for(Player player: getPlayers().values()) {
+ if (player.getHand().contains(card.getId())) {
+ player.getHand().remove(card);
+ break;
+ }
+ }
+ break;
+ case LIBRARY:
+ for(Player player: getPlayers().values()) {
+ if (player.getLibrary().getCard(card.getId(), this) != null) {
+ player.getLibrary().remove(card.getId(), this);
+ break;
+ }
+ }
+ break;
+ case EXILED:
+ getExile().removeCard(card, this);
+ break;
+ }
copiedCards.remove();
}
}
diff --git a/Mage/src/mage/game/permanent/PermanentCard.java b/Mage/src/mage/game/permanent/PermanentCard.java
index 0975fb681ff..220905b133e 100644
--- a/Mage/src/mage/game/permanent/PermanentCard.java
+++ b/Mage/src/mage/game/permanent/PermanentCard.java
@@ -136,9 +136,10 @@ public class PermanentCard extends PermanentImpl {
public boolean moveToZone(Zone toZone, UUID sourceId, Game game, boolean flag, ArrayList appliedEffects) {
Zone fromZone = game.getState().getZone(objectId);
Player controller = game.getPlayer(controllerId);
- if (controller != null && controller.removeFromBattlefield(this, game)) {
+ if (controller != null) {
ZoneChangeEvent event = new ZoneChangeEvent(this, sourceId, controllerId, fromZone, toZone, appliedEffects);
if (!game.replaceEvent(event)) {
+ controller.removeFromBattlefield(this, game);
Player owner = game.getPlayer(ownerId);
game.rememberLKI(objectId, Zone.BATTLEFIELD, this);
if (owner != null) {