diff --git a/Mage.Sets/src/mage/cards/a/AvengingArrow.java b/Mage.Sets/src/mage/cards/a/AvengingArrow.java index a3a667d2ff..236599d79a 100644 --- a/Mage.Sets/src/mage/cards/a/AvengingArrow.java +++ b/Mage.Sets/src/mage/cards/a/AvengingArrow.java @@ -1,32 +1,33 @@ - package mage.cards.a; -import java.util.HashSet; -import java.util.Set; -import java.util.UUID; -import mage.abilities.Ability; import mage.abilities.effects.common.DestroyTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.filter.StaticFilters; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.TargetPermanent; import mage.watchers.common.SourceDidDamageWatcher; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class AvengingArrow extends CardImpl { + private static final FilterPermanent filter + = new FilterCreaturePermanent("creature that dealt damage this turn"); + public AvengingArrow(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{W}"); // Destroy target creature that dealt damage this turn. this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addTarget(new AvengingArrowTarget()); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addWatcher(new SourceDidDamageWatcher()); } @@ -40,46 +41,12 @@ public final class AvengingArrow extends CardImpl { } } -class AvengingArrowTarget extends TargetPermanent { - - public AvengingArrowTarget() { - super(1, 1, StaticFilters.FILTER_PERMANENT_CREATURE, false); - targetName = "creature that dealt damage this turn"; - } - - public AvengingArrowTarget(final AvengingArrowTarget target) { - super(target); - } +enum AvengingArrowPredicate implements Predicate { + instance; @Override - public boolean canTarget(UUID id, Ability source, Game game) { + public boolean apply(Permanent input, Game game) { SourceDidDamageWatcher watcher = game.getState().getWatcher(SourceDidDamageWatcher.class); - if (watcher != null) { - if (watcher.damageSources.contains(id)) { - return super.canTarget(id, source, game); - } - } - return false; - } - - @Override - public Set possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) { - Set availablePossibleTargets = super.possibleTargets(sourceId, sourceControllerId, game); - Set possibleTargets = new HashSet<>(); - SourceDidDamageWatcher watcher = game.getState().getWatcher(SourceDidDamageWatcher.class); - if (watcher != null) { - for (UUID targetId : availablePossibleTargets) { - Permanent permanent = game.getPermanent(targetId); - if (permanent != null && watcher.damageSources.contains(targetId)) { - possibleTargets.add(targetId); - } - } - } - return possibleTargets; - } - - @Override - public AvengingArrowTarget copy() { - return new AvengingArrowTarget(this); + return watcher != null && watcher.checkSource(input, game); } } diff --git a/Mage.Sets/src/mage/cards/e/ExecutionersSwing.java b/Mage.Sets/src/mage/cards/e/ExecutionersSwing.java index d2c400be81..48a2482ea5 100644 --- a/Mage.Sets/src/mage/cards/e/ExecutionersSwing.java +++ b/Mage.Sets/src/mage/cards/e/ExecutionersSwing.java @@ -1,4 +1,3 @@ - package mage.cards.e; import java.util.HashSet; @@ -11,7 +10,10 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; +import mage.filter.FilterPermanent; import mage.filter.StaticFilters; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.TargetPermanent; @@ -23,12 +25,13 @@ import mage.watchers.common.SourceDidDamageWatcher; */ public final class ExecutionersSwing extends CardImpl { + private static final FilterPermanent filter=new FilterCreaturePermanent("creature that dealt damage this turn");static {filter.add(ExecutionersSwingPredicate.instance);} public ExecutionersSwing(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{W}{B}"); // Target creature that dealt damage this turn gets -5/-5 until end of turn. this.getSpellAbility().addEffect(new BoostTargetEffect(-5, -5, Duration.EndOfTurn)); - this.getSpellAbility().addTarget(new TargetCreaturePermanentThatDealtDamageThisTurn()); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addWatcher(new SourceDidDamageWatcher()); } @@ -42,71 +45,12 @@ public final class ExecutionersSwing extends CardImpl { return new ExecutionersSwing(this); } } - -class TargetCreaturePermanentThatDealtDamageThisTurn extends TargetPermanent { - - public TargetCreaturePermanentThatDealtDamageThisTurn() { - super(1, 1, StaticFilters.FILTER_PERMANENT_CREATURE, false); - targetName = "creature that dealt damage this turn"; - } - - public TargetCreaturePermanentThatDealtDamageThisTurn(final TargetCreaturePermanentThatDealtDamageThisTurn target) { - super(target); - } +enum ExecutionersSwingPredicate implements Predicate{ + instance ; @Override - public boolean canTarget(UUID id, Ability source, Game game) { - SourceDidDamageWatcher watcher = game.getState().getWatcher(SourceDidDamageWatcher.class); - if (watcher != null) { - if (watcher.damageSources.contains(id)) { - return super.canTarget(id, source, game); - } - } - return false; + public boolean apply(Permanent input, Game game) { + SourceDidDamageWatcher watcher=game.getState().getWatcher(SourceDidDamageWatcher.class); + return watcher!=null&&watcher.checkSource(input,game); } - - @Override - public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) { - int remainingTargets = this.minNumberOfTargets - targets.size(); - if (remainingTargets <= 0) { - return true; - } - int count = 0; - MageObject targetSource = game.getObject(sourceId); - SourceDidDamageWatcher watcher = game.getState().getWatcher(SourceDidDamageWatcher.class); - if (watcher != null && targetSource != null) { - for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, sourceId, game)) { - if (!targets.containsKey(permanent.getId()) && watcher.damageSources.contains(permanent.getId())) { - if (!notTarget || permanent.canBeTargetedBy(targetSource, sourceControllerId, game)) { - count++; - if (count >= remainingTargets) { - return true; - } - } - } - } - } - return false; - } - - @Override - public Set possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) { - Set availablePossibleTargets = super.possibleTargets(sourceId, sourceControllerId, game); - Set possibleTargets = new HashSet<>(); - SourceDidDamageWatcher watcher = game.getState().getWatcher(SourceDidDamageWatcher.class); - if (watcher != null) { - for (UUID targetId : availablePossibleTargets) { - Permanent permanent = game.getPermanent(targetId); - if (permanent != null && !targets.containsKey(permanent.getId()) && watcher.damageSources.contains(targetId)) { - possibleTargets.add(targetId); - } - } - } - return possibleTargets; - } - - @Override - public TargetCreaturePermanentThatDealtDamageThisTurn copy() { - return new TargetCreaturePermanentThatDealtDamageThisTurn(this); - } -} +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/q/Quickling.java b/Mage.Sets/src/mage/cards/q/Quickling.java index 75eb3ff90a..55dab052ad 100644 --- a/Mage.Sets/src/mage/cards/q/Quickling.java +++ b/Mage.Sets/src/mage/cards/q/Quickling.java @@ -1,35 +1,27 @@ - package mage.cards.q; -import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.SacrificeSourceEffect; +import mage.abilities.costs.common.ReturnToHandChosenControlledPermanentCost; +import mage.abilities.effects.common.SacrificeSourceUnlessPaysEffect; import mage.abilities.keyword.FlashAbility; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Outcome; -import mage.constants.Zone; -import mage.filter.common.FilterControlledCreaturePermanent; -import mage.filter.predicate.mageobject.AnotherPredicate; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.players.Player; -import mage.target.TargetPermanent; +import mage.filter.StaticFilters; +import mage.target.common.TargetControlledPermanent; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class Quickling extends CardImpl { public Quickling(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}"); this.subtype.add(SubType.FAERIE); this.subtype.add(SubType.ROGUE); @@ -38,10 +30,16 @@ public final class Quickling extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); + // Flash this.addAbility(FlashAbility.getInstance()); + // When Quickling enters the battlefield, sacrifice it unless you return another creature you control to its owner's hand. - this.addAbility(new EntersBattlefieldTriggeredAbility(new QuicklingEffect())); + this.addAbility(new EntersBattlefieldTriggeredAbility(new SacrificeSourceUnlessPaysEffect( + new ReturnToHandChosenControlledPermanentCost( + new TargetControlledPermanent(StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE) + ) + ).setText("sacrifice it unless you return another creature you control to its owner's hand"))); } private Quickling(final Quickling card) { @@ -53,51 +51,3 @@ public final class Quickling extends CardImpl { return new Quickling(this); } } - -class QuicklingEffect extends OneShotEffect { - - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another creature you control"); - private static final String effectText = "sacrifice it unless you return another creature you control to its owner's hand"; - - static { - filter.add(AnotherPredicate.instance); - } - - QuicklingEffect() { - super(Outcome.ReturnToHand); - staticText = effectText; - } - - QuicklingEffect(QuicklingEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - boolean targetChosen = false; - TargetPermanent target = new TargetPermanent(1, 1, filter, true); - if (target.canChoose(source.getSourceId(), controller.getId(), game) && controller.chooseUse(outcome, "Return another creature you control to its owner's hand?", source, game)) { - controller.chooseTarget(Outcome.ReturnToHand, target, source, game); - Permanent permanent = game.getPermanent(target.getFirstTarget()); - if (permanent != null) { - targetChosen = true; - permanent.moveToZone(Zone.HAND, source, game, false); - } - } - - if (!targetChosen) { - new SacrificeSourceEffect().apply(game, source); - } - return true; - } - return false; - } - - @Override - public QuicklingEffect copy() { - return new QuicklingEffect(this); - } - -} diff --git a/Mage.Sets/src/mage/cards/r/RestoreThePeace.java b/Mage.Sets/src/mage/cards/r/RestoreThePeace.java index f5da33b947..051ed9835c 100644 --- a/Mage.Sets/src/mage/cards/r/RestoreThePeace.java +++ b/Mage.Sets/src/mage/cards/r/RestoreThePeace.java @@ -1,31 +1,36 @@ - package mage.cards.r; -import java.util.UUID; -import mage.abilities.Ability; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ReturnToHandFromBattlefieldAllEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.Zone; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.watchers.common.SourceDidDamageWatcher; +import java.util.UUID; + /** * @author LevelX2 */ public final class RestoreThePeace extends CardImpl { + private static final FilterPermanent filter = new FilterCreaturePermanent(); + + static { + filter.add(RestoreThePeacePredicate.instance); + } + public RestoreThePeace(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}{U}"); - // Return each creature that dealt damage this turn to its owner's hand. - this.getSpellAbility().addEffect(new RestoreThePeaceEffect()); + this.getSpellAbility().addEffect(new ReturnToHandFromBattlefieldAllEffect(filter) + .setText("return each creature that dealt damage this turn to its owner's hand")); this.getSpellAbility().addWatcher(new SourceDidDamageWatcher()); - } private RestoreThePeace(final RestoreThePeace card) { @@ -38,34 +43,12 @@ public final class RestoreThePeace extends CardImpl { } } -class RestoreThePeaceEffect extends OneShotEffect { - - public RestoreThePeaceEffect() { - super(Outcome.ReturnToHand); - this.staticText = "Return each creature that dealt damage this turn to its owner's hand"; - } - - public RestoreThePeaceEffect(final RestoreThePeaceEffect effect) { - super(effect); - } +enum RestoreThePeacePredicate implements Predicate { + instance; @Override - public RestoreThePeaceEffect copy() { - return new RestoreThePeaceEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { + public boolean apply(Permanent input, Game game) { SourceDidDamageWatcher watcher = game.getState().getWatcher(SourceDidDamageWatcher.class); - if (watcher != null) { - for (UUID permId : watcher.damageSources) { - Permanent perm = game.getPermanent(permId); - if (perm != null) { - perm.moveToZone(Zone.HAND, source, game, true); - } - } - return true; - } - return false; + return watcher != null && watcher.checkSource(input, game); } } diff --git a/Mage.Sets/src/mage/cards/r/RiteOfUndoing.java b/Mage.Sets/src/mage/cards/r/RiteOfUndoing.java index 2ad6d22785..afdc5c0fc3 100644 --- a/Mage.Sets/src/mage/cards/r/RiteOfUndoing.java +++ b/Mage.Sets/src/mage/cards/r/RiteOfUndoing.java @@ -1,27 +1,21 @@ - package mage.cards.r; -import java.util.UUID; -import mage.abilities.Ability; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ReturnToHandTargetEffect; import mage.abilities.keyword.DelveAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.TargetController; -import mage.constants.Zone; import mage.filter.common.FilterNonlandPermanent; -import mage.game.Game; -import mage.game.permanent.Permanent; import mage.target.common.TargetNonlandPermanent; +import java.util.UUID; + /** - * * @author fireshoes */ public final class RiteOfUndoing extends CardImpl { - + private static final FilterNonlandPermanent filterControlled = new FilterNonlandPermanent("nonland permanent you control"); private static final FilterNonlandPermanent filterNotControlled = new FilterNonlandPermanent("nonland permanent you don't control"); @@ -31,13 +25,14 @@ public final class RiteOfUndoing extends CardImpl { } public RiteOfUndoing(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{4}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{4}{U}"); // Delve this.addAbility(new DelveAbility()); - + // Return target nonland permanent you control and target nonland permanent you don't control to their owners' hands. - this.getSpellAbility().addEffect(new RiteOfUndoingEffect()); + this.getSpellAbility().addEffect(new ReturnToHandTargetEffect(true) + .setText("return target nonland permanent you control and target nonland permanent you don't control to their owners' hands")); this.getSpellAbility().addTarget(new TargetNonlandPermanent(filterControlled)); this.getSpellAbility().addTarget(new TargetNonlandPermanent(filterNotControlled)); } @@ -51,36 +46,3 @@ public final class RiteOfUndoing extends CardImpl { return new RiteOfUndoing(this); } } - -class RiteOfUndoingEffect extends OneShotEffect { - - public RiteOfUndoingEffect() { - super(Outcome.ReturnToHand); - this.staticText = "Return target nonland permanent you control and target nonland permanent you don't control to their owners' hands"; - } - - public RiteOfUndoingEffect(final RiteOfUndoingEffect effect) { - super(effect); - } - - @Override - public RiteOfUndoingEffect copy() { - return new RiteOfUndoingEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - boolean result = false; - - Permanent permanent = game.getPermanent(source.getFirstTarget()); - if (permanent != null) { - result |= permanent.moveToZone(Zone.HAND, source, game, false); - } - permanent = game.getPermanent(source.getTargets().get(1).getFirstTarget()); - if (permanent != null) { - result |= permanent.moveToZone(Zone.HAND, source, game, false); - } - - return result; - } -} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/r/RiversRebuke.java b/Mage.Sets/src/mage/cards/r/RiversRebuke.java index c9afc755b7..bbce02913d 100644 --- a/Mage.Sets/src/mage/cards/r/RiversRebuke.java +++ b/Mage.Sets/src/mage/cards/r/RiversRebuke.java @@ -1,22 +1,22 @@ - package mage.cards.r; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.cards.Cards; +import mage.cards.CardsImpl; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.Zone; -import mage.filter.common.FilterNonlandPermanent; -import mage.filter.predicate.permanent.ControllerIdPredicate; +import mage.filter.StaticFilters; import mage.game.Game; -import mage.game.permanent.Permanent; +import mage.players.Player; import mage.target.TargetPlayer; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class RiversRebuke extends CardImpl { @@ -41,26 +41,27 @@ public final class RiversRebuke extends CardImpl { class RiversRebukeReturnToHandEffect extends OneShotEffect { - public RiversRebukeReturnToHandEffect() { + RiversRebukeReturnToHandEffect() { super(Outcome.ReturnToHand); staticText = "Return all nonland permanents target player controls to their owner's hand"; } - public RiversRebukeReturnToHandEffect(final RiversRebukeReturnToHandEffect effect) { + private RiversRebukeReturnToHandEffect(final RiversRebukeReturnToHandEffect effect) { super(effect); } @Override public boolean apply(Game game, Ability source) { - if (targetPointer.getFirst(game, source) != null) { - FilterNonlandPermanent filter = new FilterNonlandPermanent(); - filter.add(new ControllerIdPredicate(targetPointer.getFirst(game, source))); - for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) { - permanent.moveToZone(Zone.HAND, source, game, true); - } - return true; + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return false; } - return false; + Cards cards = new CardsImpl(); + game.getBattlefield().getActivePermanents( + StaticFilters.FILTER_CONTROLLED_PERMANENT_NON_LAND, + source.getFirstTarget(), source.getSourceId(), game + ).stream().forEach(cards::add); + return player.moveCards(cards, Zone.HAND, source, game); } @Override diff --git a/Mage/src/main/java/mage/watchers/common/SourceDidDamageWatcher.java b/Mage/src/main/java/mage/watchers/common/SourceDidDamageWatcher.java index b76308bf59..b6399529b3 100644 --- a/Mage/src/main/java/mage/watchers/common/SourceDidDamageWatcher.java +++ b/Mage/src/main/java/mage/watchers/common/SourceDidDamageWatcher.java @@ -1,13 +1,14 @@ - package mage.watchers.common; +import mage.MageObject; +import mage.MageObjectReference; import mage.constants.WatcherScope; import mage.game.Game; import mage.game.events.GameEvent; -import mage.game.events.GameEvent.EventType; import mage.watchers.Watcher; -import java.util.*; +import java.util.HashSet; +import java.util.Set; /** * Watcher stores which sources did damage to anything. @@ -16,7 +17,7 @@ import java.util.*; */ public class SourceDidDamageWatcher extends Watcher { - public final Set damageSources = new HashSet<>(); + private final Set damageSources = new HashSet<>(); public SourceDidDamageWatcher() { super(WatcherScope.GAME); @@ -26,10 +27,14 @@ public class SourceDidDamageWatcher extends Watcher { public void watch(GameEvent event, Game game) { if (event.getType() == GameEvent.EventType.DAMAGED_PERMANENT || event.getType() == GameEvent.EventType.DAMAGED_PLAYER) { - damageSources.add(event.getSourceId()); + damageSources.add(new MageObjectReference(event.getSourceId(), game)); } } + public boolean checkSource(MageObject mageObject, Game game) { + return damageSources.stream().anyMatch(mor -> mor.refersTo(mageObject, game)); + } + @Override public void reset() { super.reset();