From ba1fb775b2efd63d4de60786ab9d7857e00c3a57 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Thu, 12 Feb 2015 15:54:41 +0100 Subject: [PATCH] * Fixed that manifested or morphed creatures did wrongly trigger "enters the battlefield" abilities with their card attributes (e.g red card manifested triggered Foundry Street Denizens boost ability). --- .../fatereforged/GhastlyConscription.java | 21 +++++----- .../sets/fatereforged/JeskaiInfiltrator.java | 27 ++++++------- .../abilities/keywords/ManifestTest.java | 38 +++++++++++++++++++ Mage/src/mage/MageObjectReference.java | 13 +++++++ .../BecomesFaceDownCreatureEffect.java | 23 +++++------ .../effects/keyword/ManifestEffect.java | 20 +++++----- .../keyword/ManifestTargetPlayerEffect.java | 23 +++++------ .../mage/abilities/keyword/MorphAbility.java | 2 +- .../mage/game/permanent/PermanentImpl.java | 5 +++ 9 files changed, 113 insertions(+), 59 deletions(-) diff --git a/Mage.Sets/src/mage/sets/fatereforged/GhastlyConscription.java b/Mage.Sets/src/mage/sets/fatereforged/GhastlyConscription.java index 667318aa6d7..4cfac2a5037 100644 --- a/Mage.Sets/src/mage/sets/fatereforged/GhastlyConscription.java +++ b/Mage.Sets/src/mage/sets/fatereforged/GhastlyConscription.java @@ -30,6 +30,7 @@ package mage.sets.fatereforged; import java.util.ArrayList; import java.util.Collections; import java.util.UUID; +import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.costs.mana.ManaCost; import mage.abilities.costs.mana.ManaCosts; @@ -110,19 +111,19 @@ class GhastlyConscriptionEffect extends OneShotEffect { Ability newSource = source.copy(); newSource.setWorksFaceDown(true); for (Card card: cardsToManifest) { + card.setFaceDown(true); + ManaCosts manaCosts = null; + if (card.getCardType().contains(CardType.CREATURE)) { + manaCosts = card.getSpellAbility().getManaCosts(); + if (manaCosts == null) { + manaCosts = new ManaCostsImpl("{0}"); + } + } + MageObjectReference objectReference= new MageObjectReference(card.getId(), card.getZoneChangeCounter() +1, game); + game.addEffect(new BecomesFaceDownCreatureEffect(manaCosts, objectReference, Duration.Custom, FaceDownType.MANIFESTED), newSource); if (card.moveToZone(Zone.BATTLEFIELD, newSource.getSourceId(), game, false)) { game.informPlayers(new StringBuilder(controller.getName()) .append(" puts facedown card from exile onto the battlefield").toString()); - ManaCosts manaCosts = null; - if (card.getCardType().contains(CardType.CREATURE)) { - manaCosts = card.getSpellAbility().getManaCosts(); - if (manaCosts == null) { - manaCosts = new ManaCostsImpl<>("{0}"); - } - } - ContinuousEffect effect = new BecomesFaceDownCreatureEffect(manaCosts, true, Duration.Custom, FaceDownType.MANIFESTED); - effect.setTargetPointer(new FixedTarget(card.getId())); - game.addEffect(effect, newSource); } } return true; diff --git a/Mage.Sets/src/mage/sets/fatereforged/JeskaiInfiltrator.java b/Mage.Sets/src/mage/sets/fatereforged/JeskaiInfiltrator.java index 38edb88f163..f0b5bff1bec 100644 --- a/Mage.Sets/src/mage/sets/fatereforged/JeskaiInfiltrator.java +++ b/Mage.Sets/src/mage/sets/fatereforged/JeskaiInfiltrator.java @@ -32,6 +32,7 @@ import java.util.Collections; import java.util.List; import java.util.UUID; import mage.MageInt; +import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; @@ -130,25 +131,19 @@ class JeskaiInfiltratorEffect extends OneShotEffect { Ability newSource = source.copy(); newSource.setWorksFaceDown(true); for (Card card : cardsToManifest) { + card.setFaceDown(true); + ManaCosts manaCosts = null; + if (card.getCardType().contains(CardType.CREATURE)) { + manaCosts = card.getSpellAbility().getManaCosts(); + if (manaCosts == null) { + manaCosts = new ManaCostsImpl("{0}"); + } + } + MageObjectReference objectReference= new MageObjectReference(card.getId(), card.getZoneChangeCounter() +1, game); + game.addEffect(new BecomesFaceDownCreatureEffect(manaCosts, objectReference, Duration.Custom, FaceDownType.MANIFESTED), newSource); if (card.moveToZone(Zone.BATTLEFIELD, newSource.getSourceId(), game, false)) { game.informPlayers(new StringBuilder(player.getName()) .append(" puts facedown card from exile onto the battlefield").toString()); - ManaCosts manaCosts = null; - if (card.getCardType().contains(CardType.CREATURE)) { - manaCosts = card.getSpellAbility().getManaCosts(); - if (manaCosts == null) { - manaCosts = new ManaCostsImpl<>("{0}"); - } - } - ContinuousEffect effect = new BecomesFaceDownCreatureEffect( - manaCosts, - true, - Duration.Custom, - FaceDownType.MANIFESTED - ); - effect.setTargetPointer(new FixedTarget(card.getId())); - game.addEffect(effect, newSource); - } } return true; diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ManifestTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ManifestTest.java index 817fcf053fc..e83d866c42d 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ManifestTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ManifestTest.java @@ -167,4 +167,42 @@ public class ManifestTest extends CardTestPlayerBase { assertPowerToughness(playerA, "face down creature", 2, 2); } + + /* + Had a Foundry Street Denizen and another creature out. + Opponent Reality Shift'ed the other creature, manifested card was a red creature. This pumped the foundry street denizen even though it shouldn't. + */ + @Test + public void testColorOfManifestedCardDoesNotCount() { + addCard(Zone.BATTLEFIELD, playerB, "Island", 2); + // Exile target creature. Its controller manifests the top card of his or her library {1}{U} + addCard(Zone.HAND, playerB, "Reality Shift"); + + // Gore Swine {2}{R} + // 4/1 + addCard(Zone.LIBRARY, playerA, "Gore Swine"); + + // Whenever another red creature enters the battlefield under your control, Foundry Street Denizen gets +1/+0 until end of turn. + addCard(Zone.BATTLEFIELD, playerA, "Foundry Street Denizen"); + addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion"); + + skipInitShuffling(); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Reality Shift", "Silvercoat Lion"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + // no life gain + assertLife(playerA, 20); + assertLife(playerB, 20); + assertGraveyardCount(playerB, "Reality Shift", 1); + assertExileCount("Silvercoat Lion" , 1); + // a facedown creature is on the battlefield + assertPermanentCount(playerA, "face down creature", 1); + assertPowerToughness(playerA, "face down creature", 2, 2); + assertPowerToughness(playerA, "Foundry Street Denizen", 1, 1); + + } + } diff --git a/Mage/src/mage/MageObjectReference.java b/Mage/src/mage/MageObjectReference.java index e7ea3f1d86e..5573e784a7c 100644 --- a/Mage/src/mage/MageObjectReference.java +++ b/Mage/src/mage/MageObjectReference.java @@ -55,6 +55,19 @@ public class MageObjectReference implements Comparable { this.zoneChangeCounter = card.getZoneChangeCounter(); } + /** + * That values manually (can be used to let it reference to a Permanent + * that is not yet on the battlefield. + * + * @param sourceId + * @param zoneChangeCounter + * @param game + */ + public MageObjectReference(UUID sourceId, int zoneChangeCounter, Game game) { + this.sourceId = sourceId; + this.zoneChangeCounter = zoneChangeCounter; + } + public MageObjectReference(UUID sourceId, Game game) { MageObject mageObject = game.getObject(sourceId); this.sourceId = sourceId; diff --git a/Mage/src/mage/abilities/effects/common/continious/BecomesFaceDownCreatureEffect.java b/Mage/src/mage/abilities/effects/common/continious/BecomesFaceDownCreatureEffect.java index 24d81a422ee..6d308affad5 100644 --- a/Mage/src/mage/abilities/effects/common/continious/BecomesFaceDownCreatureEffect.java +++ b/Mage/src/mage/abilities/effects/common/continious/BecomesFaceDownCreatureEffect.java @@ -29,6 +29,7 @@ package mage.abilities.effects.common.continious; import java.util.ArrayList; import java.util.List; +import mage.MageObjectReference; import mage.ObjectColor; import mage.abilities.Ability; import mage.abilities.common.TurnFaceUpAbility; @@ -66,26 +67,26 @@ public class BecomesFaceDownCreatureEffect extends ContinuousEffectImpl implemen protected int zoneChangeCounter; protected Ability turnFaceUpAbility = null; - protected boolean useTargetPointer; + protected MageObjectReference objectReference= null; protected boolean foundPermanent; protected FaceDownType faceDownType; public BecomesFaceDownCreatureEffect(Costs turnFaceUpCosts, FaceDownType faceDownType){ - this(turnFaceUpCosts, false, faceDownType); + this(turnFaceUpCosts, null, faceDownType); } - public BecomesFaceDownCreatureEffect(Costs turnFaceUpCosts, boolean useTargetPointer, FaceDownType faceDownType) { - this(turnFaceUpCosts, useTargetPointer, Duration.WhileOnBattlefield, faceDownType); + public BecomesFaceDownCreatureEffect(Costs turnFaceUpCosts, MageObjectReference objectReference, FaceDownType faceDownType) { + this(turnFaceUpCosts, objectReference, Duration.WhileOnBattlefield, faceDownType); } - public BecomesFaceDownCreatureEffect(Cost cost, boolean useTargetPointer, Duration duration, FaceDownType faceDownType) { - this(createCosts(cost), useTargetPointer, duration, faceDownType); + public BecomesFaceDownCreatureEffect(Cost cost, MageObjectReference objectReference, Duration duration, FaceDownType faceDownType) { + this(createCosts(cost), objectReference, duration, faceDownType); } - public BecomesFaceDownCreatureEffect(Costs turnFaceUpCosts, boolean useTargetPointer, Duration duration, FaceDownType faceDownType) { + public BecomesFaceDownCreatureEffect(Costs turnFaceUpCosts, MageObjectReference objectReference, Duration duration, FaceDownType faceDownType) { super(duration, Outcome.BecomeCreature); - this.useTargetPointer = useTargetPointer; + this.objectReference = objectReference; this.zoneChangeCounter = Integer.MIN_VALUE; if (turnFaceUpCosts != null) { this.turnFaceUpAbility = new TurnFaceUpAbility(turnFaceUpCosts); @@ -102,7 +103,7 @@ public class BecomesFaceDownCreatureEffect extends ContinuousEffectImpl implemen if (effect.turnFaceUpAbility != null) { this.turnFaceUpAbility = effect.turnFaceUpAbility.copy(); } - this.useTargetPointer = effect.useTargetPointer; + this.objectReference = effect.objectReference; this.foundPermanent = effect.foundPermanent; this.faceDownType = effect.faceDownType; } @@ -124,8 +125,8 @@ public class BecomesFaceDownCreatureEffect extends ContinuousEffectImpl implemen @Override public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { Permanent permanent; - if (useTargetPointer) { - permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); + if (objectReference != null) { + permanent = objectReference.getPermanent(game); } else { permanent = game.getPermanent(source.getSourceId()); } diff --git a/Mage/src/mage/abilities/effects/keyword/ManifestEffect.java b/Mage/src/mage/abilities/effects/keyword/ManifestEffect.java index db40f3b4b68..5d74c46e6ed 100644 --- a/Mage/src/mage/abilities/effects/keyword/ManifestEffect.java +++ b/Mage/src/mage/abilities/effects/keyword/ManifestEffect.java @@ -28,6 +28,7 @@ package mage.abilities.effects.keyword; import java.util.List; +import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.costs.mana.ManaCosts; import mage.abilities.costs.mana.ManaCostsImpl; @@ -79,20 +80,19 @@ public class ManifestEffect extends OneShotEffect { List cards = controller.getLibrary().getTopCards(game, amount); for (Card card: cards) { card.setFaceDown(true); + ManaCosts manaCosts = null; + if (card.getCardType().contains(CardType.CREATURE)) { + manaCosts = card.getSpellAbility().getManaCosts(); + if (manaCosts == null) { + manaCosts = new ManaCostsImpl("{0}"); + } + } + MageObjectReference objectReference= new MageObjectReference(card.getId(), card.getZoneChangeCounter() +1, game); + game.addEffect(new BecomesFaceDownCreatureEffect(manaCosts, objectReference, Duration.Custom, FaceDownType.MANIFESTED), newSource); controller.putOntoBattlefieldWithInfo(card, game, Zone.LIBRARY, newSource.getSourceId()); Permanent permanent = game.getPermanent(card.getId()); if (permanent != null) { permanent.setManifested(true); - ManaCosts manaCosts = null; - if (card.getCardType().contains(CardType.CREATURE)) { - manaCosts = card.getSpellAbility().getManaCosts(); - if (manaCosts == null) { - manaCosts = new ManaCostsImpl("{0}"); - } - } - ContinuousEffect effect = new BecomesFaceDownCreatureEffect(manaCosts, true, Duration.Custom, FaceDownType.MANIFESTED); - effect.setTargetPointer(new FixedTarget(card.getId())); - game.addEffect(effect, newSource); } } game.applyEffects(); // to apply before ETB triggered or replace Effects are executed diff --git a/Mage/src/mage/abilities/effects/keyword/ManifestTargetPlayerEffect.java b/Mage/src/mage/abilities/effects/keyword/ManifestTargetPlayerEffect.java index 1432f39a98e..822d45b8913 100644 --- a/Mage/src/mage/abilities/effects/keyword/ManifestTargetPlayerEffect.java +++ b/Mage/src/mage/abilities/effects/keyword/ManifestTargetPlayerEffect.java @@ -28,6 +28,7 @@ package mage.abilities.effects.keyword; import java.util.List; +import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.costs.mana.ManaCosts; import mage.abilities.costs.mana.ManaCostsImpl; @@ -83,21 +84,21 @@ public class ManifestTargetPlayerEffect extends OneShotEffect { List cards = targetPlayer.getLibrary().getTopCards(game, amount); for (Card card: cards) { card.setFaceDown(true); + ManaCosts manaCosts = null; + if (card.getCardType().contains(CardType.CREATURE)) { + manaCosts = card.getSpellAbility().getManaCosts(); + if (manaCosts == null) { + manaCosts = new ManaCostsImpl("{0}"); + } + } + MageObjectReference objectReference= new MageObjectReference(card.getId(), card.getZoneChangeCounter() +1, game); + game.addEffect(new BecomesFaceDownCreatureEffect(manaCosts, objectReference, Duration.Custom, FaceDownType.MANIFESTED), newSource); targetPlayer.putOntoBattlefieldWithInfo(card, game, Zone.LIBRARY, newSource.getSourceId()); Permanent permanent = game.getPermanent(card.getId()); if (permanent != null) { permanent.setManifested(true); - ManaCosts manaCosts = null; - if (card.getCardType().contains(CardType.CREATURE)) { - manaCosts = card.getSpellAbility().getManaCosts(); - if (manaCosts == null) { - manaCosts = new ManaCostsImpl("{0}"); - } - } - ContinuousEffect effect = new BecomesFaceDownCreatureEffect(manaCosts, true, Duration.Custom, FaceDownType.MANIFESTED); - effect.setTargetPointer(new FixedTarget(card.getId())); - game.addEffect(effect, newSource); - } } + } + } return true; } return false; diff --git a/Mage/src/mage/abilities/keyword/MorphAbility.java b/Mage/src/mage/abilities/keyword/MorphAbility.java index 7ea4aedb550..2260efe6d68 100644 --- a/Mage/src/mage/abilities/keyword/MorphAbility.java +++ b/Mage/src/mage/abilities/keyword/MorphAbility.java @@ -282,7 +282,7 @@ public class MorphAbility extends StaticAbility implements AlternativeSourceCost permanent.getSubtype().clear(); permanent.getSupertype().clear(); permanent.getManaCost().clear(); - permanent.setExpansionSetCode("KTK"); +// permanent.setExpansionSetCode("KTK"); permanent.setRarity(Rarity.NA); } diff --git a/Mage/src/mage/game/permanent/PermanentImpl.java b/Mage/src/mage/game/permanent/PermanentImpl.java index f872022738d..eda0e401083 100644 --- a/Mage/src/mage/game/permanent/PermanentImpl.java +++ b/Mage/src/mage/game/permanent/PermanentImpl.java @@ -48,6 +48,7 @@ import mage.abilities.keyword.HexproofAbility; import mage.abilities.keyword.IndestructibleAbility; import mage.abilities.keyword.InfectAbility; import mage.abilities.keyword.LifelinkAbility; +import mage.abilities.keyword.MorphAbility; import mage.abilities.keyword.ProtectionAbility; import mage.abilities.keyword.ShroudAbility; import mage.abilities.keyword.WitherAbility; @@ -762,6 +763,10 @@ public abstract class PermanentImpl extends CardImpl implements Permanent { @Override public void entersBattlefield(UUID sourceId, Game game, Zone fromZone, boolean fireEvent) { controlledFromStartOfControllerTurn = false; + if (this.isFaceDown()) { + // remove some attributes here, bceause first apply effects comes later otherwise abilities (e.g. color related) will unintended trigger + MorphAbility.setPermanentToFaceDownCreature(this); + } EntersTheBattlefieldEvent event = new EntersTheBattlefieldEvent(this, sourceId, getControllerId(), fromZone); if (!game.replaceEvent(event)) { if (fireEvent) {