From 14520097a5601d3eb2e7fd3f4cfb3e40e9f83125 Mon Sep 17 00:00:00 2001 From: Samuel Sandeen Date: Sun, 29 Jul 2018 07:44:19 -0400 Subject: [PATCH] Fix issues with the ChosenSubtypePredicate and clone effects. (#5164) Update ChosenSubtypePredicate to be an ObjectPlayer predicate. This fixes how cards that use it act when cloned. Fixes https://github.com/magefree/mage/issues/5136 --- Mage.Sets/src/mage/cards/b/BelbesPortal.java | 2 +- Mage.Sets/src/mage/cards/b/BrassHerald.java | 2 +- .../src/mage/cards/c/CallerOfTheHunt.java | 2 +- Mage.Sets/src/mage/cards/h/HeraldsHorn.java | 2 +- Mage.Sets/src/mage/cards/k/KindredBoon.java | 2 +- .../src/mage/cards/k/KindredDiscovery.java | 2 +- .../mage/cards/m/MirrorOfTheForebears.java | 2 +- .../src/mage/cards/t/TravelersCloak.java | 2 +- .../cards/copy/CleverImpersonatorTest.java | 30 +++++++++++++++++++ .../mageobject/ChosenSubtypePredicate.java | 17 +++++------ 10 files changed, 45 insertions(+), 18 deletions(-) diff --git a/Mage.Sets/src/mage/cards/b/BelbesPortal.java b/Mage.Sets/src/mage/cards/b/BelbesPortal.java index 99433187af5..3364c22b2b6 100644 --- a/Mage.Sets/src/mage/cards/b/BelbesPortal.java +++ b/Mage.Sets/src/mage/cards/b/BelbesPortal.java @@ -30,7 +30,7 @@ public final class BelbesPortal extends CardImpl { this.addAbility(new AsEntersBattlefieldAbility(new ChooseCreatureTypeEffect(Outcome.PutCreatureInPlay))); // {3}, {tap}: You may put a creature card of the chosen type from your hand onto the battlefield. FilterCreatureCard filter = new FilterCreatureCard("a creature card of the chosen type"); - filter.add(new ChosenSubtypePredicate(this.getId())); + filter.add(new ChosenSubtypePredicate()); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new PutCardFromHandOntoBattlefieldEffect(filter), new ManaCostsImpl("{3}")); diff --git a/Mage.Sets/src/mage/cards/b/BrassHerald.java b/Mage.Sets/src/mage/cards/b/BrassHerald.java index 86d57ee69ba..870ccda042a 100644 --- a/Mage.Sets/src/mage/cards/b/BrassHerald.java +++ b/Mage.Sets/src/mage/cards/b/BrassHerald.java @@ -69,7 +69,7 @@ class BrassHeraldEntersEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { FilterCard filter = new FilterCard("creature cards of the chosen type"); - filter.add(new ChosenSubtypePredicate(source.getSourceId())); + filter.add(new ChosenSubtypePredicate()); return new RevealLibraryPutIntoHandEffect(4, filter, Zone.LIBRARY).apply(game, source); } } diff --git a/Mage.Sets/src/mage/cards/c/CallerOfTheHunt.java b/Mage.Sets/src/mage/cards/c/CallerOfTheHunt.java index d27e9069319..f05249eeac4 100644 --- a/Mage.Sets/src/mage/cards/c/CallerOfTheHunt.java +++ b/Mage.Sets/src/mage/cards/c/CallerOfTheHunt.java @@ -49,7 +49,7 @@ public final class CallerOfTheHunt extends CardImpl { if (mageObject != null && effect.apply(game, ability)) { FilterPermanent filter = new FilterPermanent(); - filter.add(new ChosenSubtypePredicate(mageObject.getId())); + filter.add(new ChosenSubtypePredicate()); ContinuousEffect effectPower = new SetPowerSourceEffect(new PermanentsOnBattlefieldCount(filter), Duration.Custom); ContinuousEffect effectToughness = new SetToughnessSourceEffect(new PermanentsOnBattlefieldCount(filter), Duration.Custom); game.addEffect(effectPower, ability); diff --git a/Mage.Sets/src/mage/cards/h/HeraldsHorn.java b/Mage.Sets/src/mage/cards/h/HeraldsHorn.java index 7172601b325..1dfbd2b6ec3 100644 --- a/Mage.Sets/src/mage/cards/h/HeraldsHorn.java +++ b/Mage.Sets/src/mage/cards/h/HeraldsHorn.java @@ -79,7 +79,7 @@ class HeraldsHornEffect extends OneShotEffect { // If it's a creature card of the chosen type, you may reveal it and put it into your hand. FilterCreatureCard filter = new FilterCreatureCard("creature card of the chosen type"); - filter.add(new ChosenSubtypePredicate(source.getSourceId())); + filter.add(new ChosenSubtypePredicate()); String message = "Reveal the top card of your library and put that card into your hand?"; if (card != null) { if (filter.match(card, game) && controller.chooseUse(Outcome.Benefit, message, source, game)) { diff --git a/Mage.Sets/src/mage/cards/k/KindredBoon.java b/Mage.Sets/src/mage/cards/k/KindredBoon.java index a61037e021e..979ade1ccf8 100644 --- a/Mage.Sets/src/mage/cards/k/KindredBoon.java +++ b/Mage.Sets/src/mage/cards/k/KindredBoon.java @@ -42,7 +42,7 @@ public final class KindredBoon extends CardImpl { // {1}{W}: Put a divinity counter on target creature you control of the chosen type. FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("creature you control of the chosen type"); - filter.add(new ChosenSubtypePredicate(this.getId())); + filter.add(new ChosenSubtypePredicate()); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddCountersTargetEffect(CounterType.DIVINITY.createInstance()), new ManaCostsImpl("{1}{W}")); ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/k/KindredDiscovery.java b/Mage.Sets/src/mage/cards/k/KindredDiscovery.java index 34ddc649653..9dc8464b32d 100644 --- a/Mage.Sets/src/mage/cards/k/KindredDiscovery.java +++ b/Mage.Sets/src/mage/cards/k/KindredDiscovery.java @@ -27,7 +27,7 @@ public final class KindredDiscovery extends CardImpl { // Whenever a creature you control of the chosen type enters the battlefield or attacks, draw a card. FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("a creature you control of the chosen type"); - filter.add(new ChosenSubtypePredicate(this.getId())); + filter.add(new ChosenSubtypePredicate()); this.addAbility(new EntersBattlefieldOrAttacksAllTriggeredAbility(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), filter, false)); } diff --git a/Mage.Sets/src/mage/cards/m/MirrorOfTheForebears.java b/Mage.Sets/src/mage/cards/m/MirrorOfTheForebears.java index 165770358e9..737385b8fef 100644 --- a/Mage.Sets/src/mage/cards/m/MirrorOfTheForebears.java +++ b/Mage.Sets/src/mage/cards/m/MirrorOfTheForebears.java @@ -38,7 +38,7 @@ public final class MirrorOfTheForebears extends CardImpl { // 1: Until end of turn, Mirror of the Forebears becomes a copy of target creature you control of the chosen type, except it's an artifact in addition to its other types. FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(); - filter.add(new ChosenSubtypePredicate(this.getId())); + filter.add(new ChosenSubtypePredicate()); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new MirrorOfTheForebearsCopyEffect(), new ManaCostsImpl("{1}")); ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/t/TravelersCloak.java b/Mage.Sets/src/mage/cards/t/TravelersCloak.java index 02f4ef13dcc..9145af115df 100644 --- a/Mage.Sets/src/mage/cards/t/TravelersCloak.java +++ b/Mage.Sets/src/mage/cards/t/TravelersCloak.java @@ -50,7 +50,7 @@ public final class TravelersCloak extends CardImpl { // Enchanted creature has landwalk of the chosen type. FilterLandPermanent filter = new FilterLandPermanent("Landwalk of the chosen type"); - filter.add(new ChosenSubtypePredicate(this.getId())); + filter.add(new ChosenSubtypePredicate()); Ability landwalkAbility = new LandwalkAbility(filter); Effect effect = new GainAbilityAttachedEffect(landwalkAbility, AttachmentType.AURA); effect.setText("Enchanted creature has landwalk of the chosen type"); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/copy/CleverImpersonatorTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/copy/CleverImpersonatorTest.java index 4f3e24dc01f..1cb16170ab4 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/copy/CleverImpersonatorTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/copy/CleverImpersonatorTest.java @@ -191,4 +191,34 @@ public class CleverImpersonatorTest extends CardTestPlayerBase { assertType(dReflection, CardType.ENCHANTMENT, true); } + @Test + public void testKindredDiscovery() { + addCard(Zone.BATTLEFIELD, playerA, "Island", 5); + addCard(Zone.HAND, playerA, "Kindred Discovery"); + + + addCard(Zone.BATTLEFIELD, playerB, "Island", 5); + // Skip your draw step. + addCard(Zone.BATTLEFIELD, playerB, "Dragon Appeasement"); + addCard(Zone.HAND, playerB, "Clever Impersonator"); + addCard(Zone.HAND, playerB, "Ornithopter", 2); + addCard(Zone.HAND, playerB, "Memnite"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Kindred Discovery"); + setChoice(playerA, "Construct"); + + castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Clever Impersonator"); + setChoice(playerB, "Kindred Discovery"); + setChoice(playerB, "Thopter"); + + castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Ornithopter"); + castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Ornithopter"); + castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Memnite"); + + setStopAt(2, PhaseStep.END_COMBAT); + execute(); + + assertHandCount(playerB, 2); + } + } diff --git a/Mage/src/main/java/mage/filter/predicate/mageobject/ChosenSubtypePredicate.java b/Mage/src/main/java/mage/filter/predicate/mageobject/ChosenSubtypePredicate.java index dd122607790..21a8c11bf8b 100644 --- a/Mage/src/main/java/mage/filter/predicate/mageobject/ChosenSubtypePredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/mageobject/ChosenSubtypePredicate.java @@ -1,29 +1,26 @@ package mage.filter.predicate.mageobject; -import java.util.UUID; import mage.MageObject; import mage.abilities.effects.common.ChooseCreatureTypeEffect; import mage.constants.SubType; -import mage.filter.predicate.Predicate; +import mage.filter.predicate.ObjectPlayerPredicate; +import mage.filter.predicate.ObjectSourcePlayer; import mage.game.Game; /** * * @author LoneFox */ -public class ChosenSubtypePredicate implements Predicate { +public class ChosenSubtypePredicate implements ObjectPlayerPredicate> { - private final UUID cardID; - - public ChosenSubtypePredicate(UUID cardID) { - this.cardID = cardID; + public ChosenSubtypePredicate() { } @Override - public boolean apply(MageObject input, Game game) { - SubType subType = ChooseCreatureTypeEffect.getChoosenCreatureType(cardID, game); - return input.hasSubtype(subType, game); + public boolean apply(ObjectSourcePlayer input, Game game) { + SubType subType = ChooseCreatureTypeEffect.getChoosenCreatureType(input.getSourceId(), game); + return input.getObject().hasSubtype(subType, game); } @Override