finished the last few refactors for card.moveToZone

This commit is contained in:
Evan Kranzler 2021-02-27 09:57:45 -05:00
parent ffd5f68220
commit bb04962144
7 changed files with 91 additions and 279 deletions

View file

@ -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<Permanent> {
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<UUID> possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) {
Set<UUID> availablePossibleTargets = super.possibleTargets(sourceId, sourceControllerId, game);
Set<UUID> 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);
}
}

View file

@ -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<Permanent>{
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;
}
@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<UUID> possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) {
Set<UUID> availablePossibleTargets = super.possibleTargets(sourceId, sourceControllerId, game);
Set<UUID> 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);
public boolean apply(Permanent input, Game game) {
SourceDidDamageWatcher watcher=game.getState().getWatcher(SourceDidDamageWatcher.class);
return watcher!=null&&watcher.checkSource(input,game);
}
}

View file

@ -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);
}
}

View file

@ -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<Permanent> {
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);
}
}

View file

@ -1,23 +1,17 @@
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 {
@ -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;
}
}

View file

@ -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,27 +41,28 @@ 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;
}
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
public RiversRebukeReturnToHandEffect copy() {

View file

@ -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<UUID> damageSources = new HashSet<>();
private final Set<MageObjectReference> 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();