diff --git a/Mage.Sets/src/mage/cards/a/AshiokSculptorOfFears.java b/Mage.Sets/src/mage/cards/a/AshiokSculptorOfFears.java index 361f63b61e9..22e3f5583b8 100644 --- a/Mage.Sets/src/mage/cards/a/AshiokSculptorOfFears.java +++ b/Mage.Sets/src/mage/cards/a/AshiokSculptorOfFears.java @@ -2,19 +2,17 @@ package mage.cards.a; import mage.abilities.Ability; import mage.abilities.LoyaltyAbility; -import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.MillCardsEachPlayerEffect; import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; -import mage.abilities.effects.common.continuous.GainControlAllEffect; +import mage.abilities.effects.common.continuous.GainControlAllControlledTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; -import mage.filter.FilterPermanent; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.constants.TargetController; import mage.filter.StaticFilters; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.permanent.ControllerIdPredicate; -import mage.game.Game; import mage.target.common.TargetCardInGraveyard; import mage.target.common.TargetOpponent; @@ -46,7 +44,7 @@ public final class AshiokSculptorOfFears extends CardImpl { this.addAbility(ability); // −11: Gain control of all creatures target opponent controls. - ability = new LoyaltyAbility(new AshiokSculptorOfFearsEffect(), -11); + ability = new LoyaltyAbility(new GainControlAllControlledTargetEffect(StaticFilters.FILTER_PERMANENT_CREATURES), -11); ability.addTarget(new TargetOpponent()); this.addAbility(ability); } @@ -59,30 +57,4 @@ public final class AshiokSculptorOfFears extends CardImpl { public AshiokSculptorOfFears copy() { return new AshiokSculptorOfFears(this); } -} - -class AshiokSculptorOfFearsEffect extends OneShotEffect { - - AshiokSculptorOfFearsEffect() { - super(Outcome.Benefit); - staticText = "gain control of all creatures target opponent controls"; - } - - private AshiokSculptorOfFearsEffect(final AshiokSculptorOfFearsEffect effect) { - super(effect); - } - - @Override - public AshiokSculptorOfFearsEffect copy() { - return new AshiokSculptorOfFearsEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - FilterPermanent filter = new FilterCreaturePermanent(); - filter.add(new ControllerIdPredicate(source.getFirstTarget())); - - new GainControlAllEffect(Duration.Custom, filter).apply(game, source); - return true; - } -} +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/g/GiltLeafArchdruid.java b/Mage.Sets/src/mage/cards/g/GiltLeafArchdruid.java index 857208cbb1a..243a72d4d0a 100644 --- a/Mage.Sets/src/mage/cards/g/GiltLeafArchdruid.java +++ b/Mage.Sets/src/mage/cards/g/GiltLeafArchdruid.java @@ -5,26 +5,18 @@ import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SpellCastControllerTriggeredAbility; import mage.abilities.costs.common.TapTargetCost; -import mage.abilities.effects.ContinuousEffect; -import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; -import mage.abilities.effects.common.continuous.GainControlTargetEffect; +import mage.abilities.effects.common.continuous.GainControlAllControlledTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Outcome; import mage.constants.SubType; import mage.filter.FilterSpell; import mage.filter.StaticFilters; import mage.filter.common.FilterControlledPermanent; import mage.filter.predicate.permanent.TappedPredicate; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.players.Player; import mage.target.TargetPlayer; import mage.target.common.TargetControlledPermanent; -import mage.target.targetpointer.FixedTarget; import java.util.UUID; @@ -57,7 +49,7 @@ public final class GiltLeafArchdruid extends CardImpl { // Tap seven untapped Druids you control: Gain control of all lands target player controls. Ability ability = new SimpleActivatedAbility( - new GiltLeafArchdruidEffect(), + new GainControlAllControlledTargetEffect(StaticFilters.FILTER_LANDS), new TapTargetCost(new TargetControlledPermanent(7, filter2)) ); ability.addTarget(new TargetPlayer()); @@ -72,38 +64,4 @@ public final class GiltLeafArchdruid extends CardImpl { public GiltLeafArchdruid copy() { return new GiltLeafArchdruid(this); } -} - -class GiltLeafArchdruidEffect extends OneShotEffect { - - GiltLeafArchdruidEffect() { - super(Outcome.GainControl); - this.staticText = "gain control of all lands target player controls"; - } - - private GiltLeafArchdruidEffect(final GiltLeafArchdruidEffect effect) { - super(effect); - } - - @Override - public GiltLeafArchdruidEffect copy() { - return new GiltLeafArchdruidEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - Player targetPlayer = game.getPlayer(getTargetPointer().getFirst(game, source)); - if (controller != null && targetPlayer != null) { - for (Permanent permanent : game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_LANDS, targetPlayer.getId(), game)) { - if (permanent != null) { - ContinuousEffect effect = new GainControlTargetEffect(Duration.Custom, true); - effect.setTargetPointer(new FixedTarget(permanent, game)); - game.addEffect(effect, source); - } - } - return true; - } - return false; - } -} +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/h/HellkiteTyrant.java b/Mage.Sets/src/mage/cards/h/HellkiteTyrant.java index 62afc71eb41..ea8c460e82b 100644 --- a/Mage.Sets/src/mage/cards/h/HellkiteTyrant.java +++ b/Mage.Sets/src/mage/cards/h/HellkiteTyrant.java @@ -1,50 +1,36 @@ package mage.cards.h; -import java.util.List; -import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; -import mage.abilities.effects.ContinuousEffect; -import mage.abilities.effects.ContinuousEffectImpl; -import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.WinGameSourceControllerEffect; +import mage.abilities.effects.common.continuous.GainControlAllControlledTargetEffect; import mage.abilities.hint.ValueHint; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.TrampleAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.ComparisonType; -import mage.constants.Duration; -import mage.constants.Layer; -import mage.constants.Outcome; -import mage.constants.SubLayer; +import mage.constants.SubType; import mage.constants.TargetController; -import mage.filter.FilterPermanent; import mage.filter.StaticFilters; import mage.filter.common.FilterArtifactPermanent; -import mage.filter.predicate.permanent.ControllerIdPredicate; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.players.Player; -import mage.target.targetpointer.FixedTarget; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class HellkiteTyrant extends CardImpl { public HellkiteTyrant(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{R}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{R}{R}"); this.subtype.add(SubType.DRAGON); this.power = new MageInt(6); @@ -55,7 +41,10 @@ public final class HellkiteTyrant extends CardImpl { // Trample this.addAbility(TrampleAbility.getInstance()); // Whenever Hellkite Tyrant deals combat damage to a player, gain control of all artifacts that player controls. - this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new HellkiteTyrantEffect(), false, true)); + this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility( + new GainControlAllControlledTargetEffect(StaticFilters.FILTER_PERMANENT_ARTIFACTS) + .setText("gain control of all artifacts that player controls"), + false, true)); // At the beginning of your upkeep, if you control twenty or more artifacts, you win the game. TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new WinGameSourceControllerEffect(), TargetController.YOU, false); @@ -74,70 +63,4 @@ public final class HellkiteTyrant extends CardImpl { public HellkiteTyrant copy() { return new HellkiteTyrant(this); } -} - -class HellkiteTyrantEffect extends OneShotEffect { - - HellkiteTyrantEffect() { - super(Outcome.GainControl); - this.staticText = "gain control of all artifacts that player controls"; - } - - private HellkiteTyrantEffect(final HellkiteTyrantEffect effect) { - super(effect); - } - - @Override - public HellkiteTyrantEffect copy() { - return new HellkiteTyrantEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(getTargetPointer().getFirst(game, source)); - if (player == null) { - return false; - } - FilterPermanent filter = new FilterArtifactPermanent(); - filter.add(new ControllerIdPredicate(player.getId())); - - List permanents = game.getBattlefield().getActivePermanents(filter, source.getControllerId(), game); - for (Permanent permanent : permanents) { - ContinuousEffect effect = new HellkiteTyrantControlEffect(source.getControllerId()); - effect.setTargetPointer(new FixedTarget(permanent, game)); - game.addEffect(effect, source); - } - return true; - } -} - -class HellkiteTyrantControlEffect extends ContinuousEffectImpl { - - private final UUID controllerId; - - public HellkiteTyrantControlEffect(UUID controllerId) { - super(Duration.EndOfGame, Layer.ControlChangingEffects_2, SubLayer.NA, Outcome.GainControl); - this.controllerId = controllerId; - } - - private HellkiteTyrantControlEffect(final HellkiteTyrantControlEffect effect) { - super(effect); - this.controllerId = effect.controllerId; - } - - @Override - public HellkiteTyrantControlEffect copy() { - return new HellkiteTyrantControlEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); - if (permanent != null && controllerId != null) { - return permanent.changeControllerId(controllerId, game, source); - } - // Permanent is no longer on the battlefield, the effect can be discarded. - discard(); - return false; - } -} +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/t/TezzeretMasterOfMetal.java b/Mage.Sets/src/mage/cards/t/TezzeretMasterOfMetal.java index 0f397d961bc..fb7d3332afb 100644 --- a/Mage.Sets/src/mage/cards/t/TezzeretMasterOfMetal.java +++ b/Mage.Sets/src/mage/cards/t/TezzeretMasterOfMetal.java @@ -3,24 +3,21 @@ package mage.cards.t; import mage.abilities.Ability; import mage.abilities.LoyaltyAbility; import mage.abilities.dynamicvalue.common.ArtifactYouControlCount; -import mage.abilities.effects.ContinuousEffect; -import mage.abilities.effects.ContinuousEffectImpl; -import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.LoseLifeTargetEffect; import mage.abilities.effects.common.RevealCardsFromLibraryUntilEffect; +import mage.abilities.effects.common.continuous.GainControlAllControlledTargetEffect; import mage.abilities.hint.common.ArtifactYouControlHint; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.PutCards; +import mage.constants.SubType; +import mage.constants.SuperType; import mage.filter.FilterPermanent; import mage.filter.StaticFilters; import mage.filter.predicate.Predicates; -import mage.game.Game; -import mage.game.permanent.Permanent; import mage.target.common.TargetOpponent; -import mage.target.targetpointer.FixedTarget; -import java.util.List; import java.util.UUID; /** @@ -28,6 +25,12 @@ import java.util.UUID; */ public final class TezzeretMasterOfMetal extends CardImpl { + private static final FilterPermanent filter = new FilterPermanent("artifacts and creatures"); + + static { + filter.add(Predicates.or(CardType.ARTIFACT.getPredicate(), CardType.CREATURE.getPredicate())); + } + public TezzeretMasterOfMetal(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{4}{U}{B}"); this.supertype.add(SuperType.LEGENDARY); @@ -45,7 +48,7 @@ public final class TezzeretMasterOfMetal extends CardImpl { this.addAbility(ability); // -8: Gain control of all artifacts and creatures target opponent controls. - ability = new LoyaltyAbility(new TezzeretMasterOfMetalEffect(), -8); + ability = new LoyaltyAbility(new GainControlAllControlledTargetEffect(filter), -8); ability.addTarget(new TargetOpponent()); this.addAbility(ability); } @@ -58,67 +61,4 @@ public final class TezzeretMasterOfMetal extends CardImpl { public TezzeretMasterOfMetal copy() { return new TezzeretMasterOfMetal(this); } -} - -class TezzeretMasterOfMetalEffect extends OneShotEffect { - - private static final FilterPermanent filter = new FilterPermanent("artifacts and creatures"); - - static { - filter.add(Predicates.or(CardType.CREATURE.getPredicate(), CardType.ARTIFACT.getPredicate())); - } - - public TezzeretMasterOfMetalEffect() { - super(Outcome.GainControl); - this.staticText = "Gain control of all artifacts and creatures target opponent controls"; - } - - private TezzeretMasterOfMetalEffect(final TezzeretMasterOfMetalEffect effect) { - super(effect); - } - - @Override - public TezzeretMasterOfMetalEffect copy() { - return new TezzeretMasterOfMetalEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - List permanents = game.getBattlefield().getAllActivePermanents(filter, getTargetPointer().getFirst(game, source), game); - for (Permanent permanent : permanents) { - ContinuousEffect effect = new TezzeretMasterOfMetalControlEffect(source.getControllerId()); - effect.setTargetPointer(new FixedTarget(permanent, game)); - game.addEffect(effect, source); - } - return true; - } -} - -class TezzeretMasterOfMetalControlEffect extends ContinuousEffectImpl { - - private final UUID controllerId; - - public TezzeretMasterOfMetalControlEffect(UUID controllerId) { - super(Duration.EndOfGame, Layer.ControlChangingEffects_2, SubLayer.NA, Outcome.GainControl); - this.controllerId = controllerId; - } - - private TezzeretMasterOfMetalControlEffect(final TezzeretMasterOfMetalControlEffect effect) { - super(effect); - this.controllerId = effect.controllerId; - } - - @Override - public TezzeretMasterOfMetalControlEffect copy() { - return new TezzeretMasterOfMetalControlEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); - if (permanent != null && controllerId != null) { - return permanent.changeControllerId(controllerId, game, source); - } - return false; - } -} +} \ No newline at end of file diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/gtc/HellkiteTyranTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/gtc/HellkiteTyranTest.java new file mode 100644 index 00000000000..15c7b517c6d --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/gtc/HellkiteTyranTest.java @@ -0,0 +1,58 @@ +package org.mage.test.cards.single.gtc; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestCommander4Players; + +/** + * @author Susucr + */ +public class HellkiteTyranTest extends CardTestCommander4Players { + + /** + * {@link mage.cards.h.HellkiteTyrant Hellkite Tyrant} {4}{R}{R} + * Creature — Dragon + * Flying, trample + * Whenever Hellkite Tyrant deals combat damage to a player, gain control of all artifacts that player controls. + * At the beginning of your upkeep, if you control twenty or more artifacts, you win the game. + * 6/5 + */ + private static final String tyrant = "Hellkite Tyrant"; + + @Test + public void test_BothTriggers() { + setStrictChooseMode(true); + + addCard(Zone.BATTLEFIELD, playerA, tyrant, 1); + + // Will gain controll of all of those + addCard(Zone.BATTLEFIELD, playerB, "Mox Sapphire", 10); + addCard(Zone.BATTLEFIELD, playerB, "Memnite", 10); + + // Will not gain control of all of those: + addCard(Zone.BATTLEFIELD, playerB, "Plains", 2); + addCard(Zone.BATTLEFIELD, playerB, "Elite Vanguard", 2); + addCard(Zone.BATTLEFIELD, playerC, "Plains", 2); + addCard(Zone.BATTLEFIELD, playerD, "Mox Ruby", 2); + addCard(Zone.BATTLEFIELD, playerD, "Elite Vanguard", 2); + + checkPermanentCount("A: 1 Hellikite Tyran", 5, PhaseStep.UPKEEP, playerA, "Hellkite Tyrant", 1); + checkPermanentCount("A: 10 Mox Sapphire", 5, PhaseStep.UPKEEP, playerA, "Mox Sapphire", 10); + checkPermanentCount("A: 10 Memnite", 5, PhaseStep.UPKEEP, playerA, "Memnite", 10); + checkPermanentCount("B: 0 Mox Sapphire", 5, PhaseStep.UPKEEP, playerB, "Mox Sapphire", 0); + checkPermanentCount("B: 0 Memnite", 5, PhaseStep.UPKEEP, playerB, "Memnite", 0); + checkPermanentCount("B: 2 Plains", 5, PhaseStep.UPKEEP, playerB, "Plains", 2); + checkPermanentCount("B: 2 Elite Vanguard", 5, PhaseStep.UPKEEP, playerB, "Elite Vanguard", 2); + checkPermanentCount("C: 2 Plains", 5, PhaseStep.UPKEEP, playerC, "Plains", 2); + checkPermanentCount("D: 2 Mox Ruby", 5, PhaseStep.UPKEEP, playerD, "Mox Ruby", 2); + checkPermanentCount("D: 2 Mox Ruby", 5, PhaseStep.UPKEEP, playerD, "Elite Vanguard", 2); + + attack(1, playerA, tyrant, playerB); + + setStopAt(5, PhaseStep.PRECOMBAT_MAIN); + execute(); + + assertWonTheGame(playerA); + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/thb/AshiokSculptorOfFearsTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/thb/AshiokSculptorOfFearsTest.java new file mode 100644 index 00000000000..0640b123954 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/thb/AshiokSculptorOfFearsTest.java @@ -0,0 +1,55 @@ +package org.mage.test.cards.single.thb; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestMultiPlayerBase; + +/** + * @author Susucr + */ +public class AshiokSculptorOfFearsTest extends CardTestMultiPlayerBase { + + /** + * {@link mage.cards.a.AshiokSculptorOfFears Ashiok, Sculptor of Fears} {4}{U}{B} + * Legendary Planeswalker — Ashiok + * +2: Draw a card. Each player mills two cards. + * −5: Put target creature card from a graveyard onto the battlefield under your control. + * −11: Gain control of all creatures target opponent controls. + * Loyalty: 4 + */ + private static final String ashiok = "Ashiok, Sculptor of Fears"; + + @Test + public void test_Minus11() { + setStrictChooseMode(true); + + addCard(Zone.HAND, playerA, ashiok); + addCard(Zone.BATTLEFIELD, playerA, "Doubling Season", 2); // To have 16 Loyalty at first + addCard(Zone.BATTLEFIELD, playerA, "Underground Sea", 6); + + // Will take control of those: + addCard(Zone.BATTLEFIELD, playerB, "Grizzly Bears", 2); + + // Will not take control of those: + addCard(Zone.BATTLEFIELD, playerB, "Taiga", 2); + addCard(Zone.BATTLEFIELD, playerB, "Grist, the Hunger Tide", 1); + addCard(Zone.BATTLEFIELD, playerC, "Grizzly Bears", 2); + addCard(Zone.BATTLEFIELD, playerD, "Grizzly Bears", 2); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, ashiok, true); + setChoice(playerA, "Doubling Season"); // ordering replacement effects + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "-11", playerB); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPermanentCount(playerA, 9 + 2); + assertPermanentCount(playerA, "Grizzly Bears", 2); + assertPermanentCount(playerB, 5 - 2); + assertPermanentCount(playerB, "Grizzly Bears", 0); + assertPermanentCount(playerC, "Grizzly Bears", 2); + assertPermanentCount(playerD, "Grizzly Bears", 2); + } +} diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/GainControlAllControlledTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/GainControlAllControlledTargetEffect.java new file mode 100644 index 00000000000..ecc0a387134 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/GainControlAllControlledTargetEffect.java @@ -0,0 +1,57 @@ +package mage.abilities.effects.common.continuous; + +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.effects.OneShotEffect; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.filter.FilterPermanent; +import mage.filter.predicate.permanent.ControllerIdPredicate; +import mage.game.Game; +import mage.players.Player; + +/** + * @author Susucr + */ +public class GainControlAllControlledTargetEffect extends OneShotEffect { + + private final FilterPermanent filter; + + public GainControlAllControlledTargetEffect(FilterPermanent filter) { + super(Outcome.GainControl); + this.filter = filter; + } + + protected GainControlAllControlledTargetEffect(final GainControlAllControlledTargetEffect effect) { + super(effect); + this.filter = effect.filter; + } + + @Override + public GainControlAllControlledTargetEffect copy() { + return new GainControlAllControlledTargetEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(getTargetPointer().getFirst(game, source)); + if (player == null) { + return false; + } + FilterPermanent filterForPlayer = this.filter.copy(); + filterForPlayer.add(new ControllerIdPredicate(player.getId())); + return new GainControlAllEffect(Duration.EndOfGame, filterForPlayer, source.getControllerId()) + .apply(game, source); + } + + @Override + public String getText(Mode mode) { + if (staticText != null && !staticText.isEmpty()) { + return staticText; + } + String text = "gain control of all " + filter.getMessage() + " "; + text += getTargetPointer().describeTargets(mode.getTargets(), "target player"); + text += " controls"; + return text; + } +}