From a164dad83f23b0d1b40c39770babdfa317521671 Mon Sep 17 00:00:00 2001 From: Samuel Sandeen Date: Sun, 29 Jul 2018 07:40:48 -0400 Subject: [PATCH] Fix issues with Clone and Metallic Mimic (#5160) Fix bugs with Metallic Mimic and Adaptive Automaton and clone effects. Metallic Mimic and Adaptive Automaton were both using the technically correct EnterEventType specifier for their as enters the battlefield abilities. Despite it being technically correct this meant that their ability didn't trigger if they were cloned. Additionally EnterAttributeAddChosenSubtypeEffect changed the subtype of the base object which meant that clones entered in with the chosen subtype of the original. --- .../src/mage/cards/a/AdaptiveAutomaton.java | 35 +----------------- Mage.Sets/src/mage/cards/m/MetallicMimic.java | 2 + .../org/mage/test/cards/copy/CloneTest.java | 31 +++++++++++++++- .../continuous/AddChosenSubtypeEffect.java | 37 +++++++++++++++++++ .../EnterAttributeAddChosenSubtypeEffect.java | 10 ++--- 5 files changed, 75 insertions(+), 40 deletions(-) create mode 100644 Mage/src/main/java/mage/abilities/effects/common/continuous/AddChosenSubtypeEffect.java diff --git a/Mage.Sets/src/mage/cards/a/AdaptiveAutomaton.java b/Mage.Sets/src/mage/cards/a/AdaptiveAutomaton.java index cb47c035047..1e1341a51e9 100644 --- a/Mage.Sets/src/mage/cards/a/AdaptiveAutomaton.java +++ b/Mage.Sets/src/mage/cards/a/AdaptiveAutomaton.java @@ -3,10 +3,9 @@ package mage.cards.a; import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; +import mage.abilities.effects.common.continuous.AddChosenSubtypeEffect; import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.common.ChooseCreatureTypeEffect; import mage.abilities.effects.common.continuous.BoostAllOfChosenSubtypeEffect; import mage.abilities.effects.common.enterAttribute.EnterAttributeAddChosenSubtypeEffect; @@ -15,8 +14,6 @@ import mage.cards.CardSetInfo; import mage.constants.*; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.ControllerPredicate; -import mage.game.Game; -import mage.game.permanent.Permanent; /** * @author nantuko @@ -42,7 +39,7 @@ public final class AdaptiveAutomaton extends CardImpl { ability.addEffect(new EnterAttributeAddChosenSubtypeEffect()); this.addAbility(ability); - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new AdaptiveAutomatonAddSubtypeEffect())); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new AddChosenSubtypeEffect())); // Other creatures you control of the chosen type get +1/+1. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostAllOfChosenSubtypeEffect(1, 1, Duration.WhileOnBattlefield, filter, true))); } @@ -57,31 +54,3 @@ public final class AdaptiveAutomaton extends CardImpl { } } -class AdaptiveAutomatonAddSubtypeEffect extends ContinuousEffectImpl { - - public AdaptiveAutomatonAddSubtypeEffect() { - super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Benefit); - staticText = "{this} is the chosen type in addition to its other types"; - } - - public AdaptiveAutomatonAddSubtypeEffect(final AdaptiveAutomatonAddSubtypeEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent != null) { - SubType subType = ChooseCreatureTypeEffect.getChoosenCreatureType(permanent.getId(), game); - if (subType != null && !permanent.hasSubtype(subType, game)) { - permanent.getSubtype(game).add(subType); - } - } - return true; - } - - @Override - public AdaptiveAutomatonAddSubtypeEffect copy() { - return new AdaptiveAutomatonAddSubtypeEffect(this); - } -} diff --git a/Mage.Sets/src/mage/cards/m/MetallicMimic.java b/Mage.Sets/src/mage/cards/m/MetallicMimic.java index 58c8282e391..9dfcca6887d 100644 --- a/Mage.Sets/src/mage/cards/m/MetallicMimic.java +++ b/Mage.Sets/src/mage/cards/m/MetallicMimic.java @@ -4,6 +4,7 @@ package mage.cards.m; import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; +import mage.abilities.effects.common.continuous.AddChosenSubtypeEffect; import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ReplacementEffectImpl; @@ -36,6 +37,7 @@ public final class MetallicMimic extends CardImpl { // Metallic Mimic is the chosen type in addition to its other types. ability.addEffect(new EnterAttributeAddChosenSubtypeEffect()); this.addAbility(ability); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new AddChosenSubtypeEffect())); // Each other creature you control of the chosen type enters the battlefield with an additional +1/+1 counter on it. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new MetallicMimicReplacementEffect())); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/copy/CloneTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/copy/CloneTest.java index 2bb567fbbd5..202b360e987 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/copy/CloneTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/copy/CloneTest.java @@ -4,6 +4,7 @@ import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousEffectsList; import mage.cards.Card; import mage.constants.PhaseStep; +import mage.constants.SubType; import mage.constants.Zone; import mage.filter.FilterCard; import mage.filter.StaticFilters; @@ -89,7 +90,7 @@ public class CloneTest extends CardTestPlayerBase { addCard(Zone.BATTLEFIELD, playerB, "Llanowar Elves"); addCard(Zone.BATTLEFIELD, playerB, "Craw Wurm"); - castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Public Executio", "Llanowar Elves"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Public Execution", "Llanowar Elves"); castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Clone"); setStopAt(1, PhaseStep.END_TURN); @@ -199,4 +200,32 @@ public class CloneTest extends CardTestPlayerBase { Assert.assertTrue("There should be a white and a blue Silvercoat Lion be on the battlefield", blueLion && whiteLion); } + @Test + public void testAdaptiveAutomaton() { + addCard(Zone.BATTLEFIELD, playerA, "Island", 3); + addCard(Zone.HAND, playerA, "Adaptive Automaton"); + + addCard(Zone.BATTLEFIELD, playerB, "Island", 4); + addCard(Zone.HAND, playerB, "Clone"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Adaptive Automaton"); + setChoice(playerA, "Elf"); + + castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Clone"); + setChoice(playerB, "Adaptive Automaton"); + setChoice(playerB, "Goblin"); + + setStopAt(2, PhaseStep.END_COMBAT); + execute(); + + assertPermanentCount(playerA, "Adaptive Automaton", 1); + Permanent original = getPermanent("Adaptive Automaton", playerA); + Assert.assertTrue("The original Adaptive Automaton should be an Elf", original.hasSubtype(SubType.ELF, currentGame)); + + assertPermanentCount(playerB, "Adaptive Automaton", 1); + Permanent clone = getPermanent("Adaptive Automaton", playerB); + Assert.assertFalse("The cloned Adaptive Automaton should not be as Elf", clone.hasSubtype(SubType.ELF, currentGame)); + Assert.assertTrue("The cloned Adaptive Automaton should be a Goblin", clone.hasSubtype(SubType.GOBLIN, currentGame)); + } + } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddChosenSubtypeEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddChosenSubtypeEffect.java new file mode 100644 index 00000000000..bb86dce4a5d --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddChosenSubtypeEffect.java @@ -0,0 +1,37 @@ +package mage.abilities.effects.common.continuous; + +import mage.abilities.Ability; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.common.ChooseCreatureTypeEffect; +import mage.constants.*; +import mage.game.Game; +import mage.game.permanent.Permanent; + +public class AddChosenSubtypeEffect extends ContinuousEffectImpl { + + public AddChosenSubtypeEffect() { + super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Benefit); + staticText = "{this} is the chosen type in addition to its other types"; + } + + public AddChosenSubtypeEffect(final AddChosenSubtypeEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent != null) { + SubType subType = ChooseCreatureTypeEffect.getChoosenCreatureType(permanent.getId(), game); + if (subType != null && !permanent.hasSubtype(subType, game)) { + permanent.getSubtype(game).add(subType); + } + } + return true; + } + + @Override + public AddChosenSubtypeEffect copy() { + return new AddChosenSubtypeEffect(this); + } +} diff --git a/Mage/src/main/java/mage/abilities/effects/common/enterAttribute/EnterAttributeAddChosenSubtypeEffect.java b/Mage/src/main/java/mage/abilities/effects/common/enterAttribute/EnterAttributeAddChosenSubtypeEffect.java index edf8f95a1ed..b70c8bb1815 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/enterAttribute/EnterAttributeAddChosenSubtypeEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/enterAttribute/EnterAttributeAddChosenSubtypeEffect.java @@ -11,6 +11,8 @@ import mage.game.permanent.Permanent; /** * + * IMPORTANT: This only adds the chosen subtype while the source permanent is entering the battlefield. + * You should also use @link{mage.abilities.effects.common.continuous.AddChosenSubtypeEffect} to make the subtype persist. * @author LevelX2 */ public class EnterAttributeAddChosenSubtypeEffect extends OneShotEffect { @@ -34,12 +36,8 @@ public class EnterAttributeAddChosenSubtypeEffect extends OneShotEffect { Permanent permanent = game.getPermanentEntering(source.getSourceId()); SubType subtype = (SubType) game.getState().getValue(source.getSourceId() + "_type"); if (permanent != null && subtype != null) { - MageObject mageObject = permanent.getBasicMageObject(game); - if (!mageObject.getSubtype(null).contains(subtype)) { - mageObject.getSubtype(null).add(subtype); - } - if (!permanent.getSubtype(null).contains(subtype)) { - permanent.getSubtype(null).add(subtype); + if (!permanent.getSubtype(game).contains(subtype)) { + permanent.getSubtype(game).add(subtype); } return true; }