refactor: cleanup TargetCardInExile (#12218)

This commit is contained in:
Susucre 2024-05-04 04:15:13 +02:00 committed by GitHub
parent 82069ef2e8
commit 2522f712e9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 79 additions and 86 deletions

View file

@ -83,7 +83,7 @@ class BindingNegotiationEffect extends OneShotEffect {
FilterCard filter = new FilterCard("face-up exiled card owned by " + player.getName());
filter.add(Predicates.not(FaceDownPredicate.instance));
filter.add(new OwnerIdPredicate(player.getId()));
TargetCard targetExiled = new TargetCardInExile(0, 1, filter, null);
TargetCard targetExiled = new TargetCardInExile(0, 1, filter);
controller.choose(outcome, targetExiled, source, game);
Set<Card> chosenExiledCard = targetExiled
.getTargets()

View file

@ -1,7 +1,6 @@
package mage.cards.b;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
@ -19,14 +18,15 @@ import mage.players.Player;
import mage.target.Target;
import mage.target.common.TargetCardInExile;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public final class BlightHerder extends CardImpl {
public BlightHerder(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{5}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}");
this.subtype.add(SubType.ELDRAZI, SubType.PROCESSOR);
this.power = new MageInt(4);
this.toughness = new MageInt(5);
@ -71,7 +71,7 @@ class BlightHerderEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
Target target = new TargetCardInExile(2, 2, filter, null);
Target target = new TargetCardInExile(2, 2, filter);
if (target.canChoose(source.getControllerId(), source, game)) {
if (controller.chooseTarget(outcome, target, source, game)) {
Cards cardsToGraveyard = new CardsImpl(target.getTargets());

View file

@ -138,9 +138,7 @@ class DauthiVoidwalkerPlayEffect extends OneShotEffect {
if (player == null) {
return false;
}
TargetCardInExile target = new TargetCardInExile(
0, 1, filter, null, true
);
TargetCardInExile target = new TargetCardInExile(0, 1, filter);
player.choose(outcome, target, source, game);
Card card = game.getCard(target.getFirstTarget());
if (card == null) {

View file

@ -83,7 +83,7 @@ class EtherealForagerEffect extends OneShotEffect {
if (delvedCards == null || delvedCards.count(StaticFilters.FILTER_CARD_INSTANT_AND_SORCERY, game) < 1) {
return false;
}
TargetCard targetCard = new TargetCardInExile(0, 1, StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY, null, true);
TargetCard targetCard = new TargetCardInExile(0, 1, StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY);
;
player.choose(Outcome.DrawCard, delvedCards, targetCard, source, game);
Card card = game.getCard(targetCard.getFirstTarget());

View file

@ -94,7 +94,7 @@ class JourneyToTheLostCityEffect extends RollDieWithResultTableEffect {
return false;
}
if (amount <= 9) {
TargetCard target = new TargetCardInExile(0, 1, StaticFilters.FILTER_CARD_LAND, null);
TargetCard target = new TargetCardInExile(0, 1, StaticFilters.FILTER_CARD_LAND);
target.withNotTarget(true);
player.choose(outcome, cards, target, source, game);
Card card = game.getCard(target.getFirstTarget());

View file

@ -1,11 +1,5 @@
package mage.cards.k;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
@ -16,17 +10,8 @@ import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.ExileTargetEffect;
import mage.abilities.effects.keyword.SurveilEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.Card;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Zone;
import mage.cards.*;
import mage.constants.*;
import mage.filter.FilterPermanent;
import mage.filter.StaticFilters;
import mage.filter.common.FilterCreaturePermanent;
@ -49,8 +34,13 @@ import mage.target.targetpointer.FixedTargets;
import mage.util.CardUtil;
import mage.util.functions.CopyApplier;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
/**
*
* @author DominionSpy
*/
public final class KayaSpiritsJustice extends CardImpl {
@ -183,7 +173,7 @@ class KayaSpiritsJusticeCopyEffect extends OneShotEffect {
return false;
}
TargetCard target = new TargetCardInExile(0, 1, StaticFilters.FILTER_CARD_CREATURE, null);
TargetCard target = new TargetCardInExile(0, 1, StaticFilters.FILTER_CARD_CREATURE);
if (!controller.chooseTarget(outcome, exiledCards, target, source, game)) {
return false;
}

View file

@ -211,7 +211,7 @@ class ImbrahamDeanOfTheoryEffect extends OneShotEffect {
}
card.addCounters(CounterType.STUDY.createInstance(), source.getControllerId(), source, game);
}
TargetCard targetCard = new TargetCardInExile(0, 1, filter, null);
TargetCard targetCard = new TargetCardInExile(0, 1, filter);
targetCard.withNotTarget(true);
player.choose(outcome, targetCard, source, game);
Card card = game.getCard(targetCard.getFirstTarget());

View file

@ -100,7 +100,7 @@ class MagmaticChannelerExileEffect extends OneShotEffect {
} else if (cards.size() == 1) {
card = cards.getRandom(game);
} else {
TargetCard targetCard = new TargetCardInExile(StaticFilters.FILTER_CARD, null);
TargetCard targetCard = new TargetCardInExile(StaticFilters.FILTER_CARD);
player.choose(outcome, cards, targetCard, source, game);
card = game.getCard(targetCard.getFirstTarget());
}

View file

@ -75,7 +75,7 @@ class MemoryTheftEffect extends OneShotEffect {
FilterCard filter = new FilterCard("card owned by " + player.getName() + " that has an Adventure");
filter.add(AdventurePredicate.instance);
filter.add(new OwnerIdPredicate(player.getId()));
TargetCard target = new TargetCardInExile(0, 1, filter, null, true);
TargetCard target = new TargetCardInExile(0, 1, filter);
if (!target.canChoose(source.getControllerId(), source, game)
|| !controller.choose(outcome, target, source, game)) {
return false;

View file

@ -1,7 +1,6 @@
package mage.cards.m;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.SacrificeSourceCost;
@ -21,14 +20,15 @@ import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetCardInExile;
import java.util.UUID;
/**
*
* @author North
*/
public final class MirrorOfFate extends CardImpl {
public MirrorOfFate(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{5}");
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{5}");
// {tap}, Sacrifice Mirror of Fate: Choose up to seven face-up exiled cards you own. Exile all the cards from your library, then put the chosen cards on top of your library.
SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD,
@ -96,10 +96,11 @@ class FaceUpPredicate implements Predicate<Card> {
}
}
// TODO: cleanup. there should be no need for custom Target there.
class MirrorOfFateTarget extends TargetCardInExile {
public MirrorOfFateTarget() {
super(0, 7, new FilterCard(), null);
super(0, 7, new FilterCard());
filter.add(new FaceUpPredicate());
this.targetName = "face-up exiled cards you own";
}

View file

@ -1,9 +1,5 @@
package mage.cards.m;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.ActivateAsSorceryActivatedAbility;
@ -26,15 +22,18 @@ import mage.target.common.TargetCardInExile;
import mage.target.common.TargetCardInHand;
import mage.util.CardUtil;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
/**
*
* @author noahg
*/
public final class MuseVessel extends CardImpl {
public MuseVessel(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}");
// {3}, {tap}: Target player exiles a card from their hand. Activate this ability only any time you could cast a sorcery.
ActivateAsSorceryActivatedAbility tapAbility = new ActivateAsSorceryActivatedAbility(Zone.BATTLEFIELD, new MuseVesselExileEffect(), new TapSourceCost());
@ -124,10 +123,11 @@ class MuseVesselMayPlayExiledEffect extends AsThoughEffectImpl {
}
// TODO: cleanup. there should be no need for custom Target there.
class TargetCardInMuseVesselExile extends TargetCardInExile {
public TargetCardInMuseVesselExile() {
super(1, 1, new FilterCard("card exiled with Muse Vessel"), null);
super(new FilterCard("card exiled with Muse Vessel"));
}
private TargetCardInMuseVesselExile(final TargetCardInMuseVesselExile target) {

View file

@ -1,7 +1,6 @@
package mage.cards.p;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
@ -17,8 +16,9 @@ import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetCardInExile;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public final class PullFromEternity extends CardImpl {
@ -30,12 +30,12 @@ public final class PullFromEternity extends CardImpl {
}
public PullFromEternity(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{W}");
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{W}");
// Put target face-up exiled card into its owner's graveyard.
this.getSpellAbility().addEffect(new PullFromEternityEffect());
this.getSpellAbility().addTarget(new TargetCardInExile(1,1,filter, null, true));
this.getSpellAbility().addTarget(new TargetCardInExile(filter));
}

View file

@ -1,6 +1,5 @@
package mage.cards.r;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
@ -9,8 +8,8 @@ import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.filter.FilterCard;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.card.FaceDownPredicate;
@ -18,8 +17,9 @@ import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetCardInExile;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public final class Riftsweeper extends CardImpl {
@ -40,7 +40,7 @@ public final class Riftsweeper extends CardImpl {
// When Riftsweeper enters the battlefield, choose target face-up exiled card. Its owner shuffles it into their library.
Ability ability = new EntersBattlefieldTriggeredAbility(new RiftsweeperEffect(), false);
ability.addTarget(new TargetCardInExile(1, 1, filter, null, true));
ability.addTarget(new TargetCardInExile(filter));
this.addAbility(ability);
}

View file

@ -117,7 +117,7 @@ class SmirkingSpelljackerEffect extends OneShotEffect {
return false;
}
FilterCard filter = new FilterCard("card exiled with " + CardUtil.getSourceLogName(game, source));
TargetCard target = new TargetCardInExile(1, 1, filter, CardUtil.getExileZoneId(game, source));
TargetCard target = new TargetCardInExile(filter, CardUtil.getExileZoneId(game, source));
target.withNotTarget(true);
controller.choose(Outcome.PlayForFree, target, source, game);
new MayCastTargetCardEffect(CastManaAdjustment.WITHOUT_PAYING_MANA_COST)

View file

@ -69,7 +69,7 @@ class SplitTheSpoilsEffect extends OneShotEffect {
return false;
}
player.moveCards(cards, Zone.EXILED, source, game);
TargetCard target = new TargetCardInExile(0, 5, StaticFilters.FILTER_CARD, null);
TargetCard target = new TargetCardInExile(0, 5, StaticFilters.FILTER_CARD);
target.withChooseHint("To put in pile 1").withNotTarget(true);
player.choose(outcome, cards, target, source, game);
List<Card> pile1 = new ArrayList<>();

View file

@ -1,7 +1,6 @@
package mage.cards.u;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldAbility;
@ -11,11 +10,7 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Outcome;
import mage.constants.TargetController;
import mage.constants.Zone;
import mage.constants.*;
import mage.counters.CounterType;
import mage.filter.FilterCard;
import mage.game.Game;
@ -23,14 +18,15 @@ import mage.players.Player;
import mage.target.Target;
import mage.target.common.TargetCardInExile;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public final class UlamogsDespoiler extends CardImpl {
public UlamogsDespoiler(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{6}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{6}");
this.subtype.add(SubType.ELDRAZI);
this.subtype.add(SubType.PROCESSOR);
this.power = new MageInt(5);
@ -77,7 +73,7 @@ class UlamogsDespoilerEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
Target target = new TargetCardInExile(2, 2, filter, null);
Target target = new TargetCardInExile(2, 2, filter);
if (target.canChoose(source.getControllerId(), source, game)) {
if (controller.chooseTarget(outcome, target, source, game)) {
Cards cardsToGraveyard = new CardsImpl(target.getTargets());

View file

@ -2,6 +2,7 @@
package mage.cards.u;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
@ -27,13 +28,12 @@ import mage.target.TargetSpell;
import mage.target.common.TargetCardInExile;
/**
*
* @author fireshoes
*/
public final class UlamogsNullifier extends CardImpl {
public UlamogsNullifier(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{U}{B}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}{B}");
this.subtype.add(SubType.ELDRAZI);
this.subtype.add(SubType.PROCESSOR);
this.power = new MageInt(2);
@ -92,7 +92,7 @@ class UlamogsNullifierEffect extends OneShotEffect {
Player controller = game.getPlayer(source.getControllerId());
Spell spell = game.getStack().getSpell(source.getFirstTarget());
if (controller != null && spell != null) {
Target target = new TargetCardInExile(2, 2, filter, null);
Target target = new TargetCardInExile(2, 2, filter);
if (target.canChoose(source.getControllerId(), source, game)) {
if (controller.chooseTarget(outcome, target, source, game)) {
Cards cardsToGraveyard = new CardsImpl(target.getTargets());

View file

@ -112,7 +112,7 @@ class Vault112SadisticSimulationChapterEffect extends OneShotEffect {
return true;
}
// Choose one, you may cast it without paying its mana cost.
TargetCardInExile target = new TargetCardInExile(0, 1, StaticFilters.FILTER_CARD_CARDS, null);
TargetCardInExile target = new TargetCardInExile(0, 1, StaticFilters.FILTER_CARD_CARDS);
controller.choose(Outcome.PlayForFree, cards, target, source, game);
Card card = game.getCard(target.getFirstTarget());
if (card == null) {

View file

@ -137,7 +137,7 @@ class CascadeEffect extends OneShotEffect {
GameEvent event = GameEvent.getEvent(GameEvent.EventType.CASCADE_LAND, source.getSourceId(), source, source.getControllerId(), 0);
game.replaceEvent(event);
if (event.getAmount() > 0) {
TargetCardInExile target = new TargetCardInExile(0, event.getAmount(), StaticFilters.FILTER_CARD_LAND, null, true);
TargetCardInExile target = new TargetCardInExile(0, event.getAmount(), StaticFilters.FILTER_CARD_LAND);
target.withChooseHint("land to put onto battlefield tapped");
controller.choose(Outcome.PutCardInPlay, cardsToExile, target, source, game);
controller.moveCards(

View file

@ -18,41 +18,54 @@ import java.util.UUID;
*/
public class TargetCardInExile extends TargetCard {
// If null, can target any card in exile matching [filter]
// If non-null, can only target
private final UUID zoneId;
private final boolean allExileZones;
/**
* @param filter filter for the card to be a target
*/
public TargetCardInExile(FilterCard filter) {
this(1, 1, filter, null);
this(1, 1, filter);
}
/**
* @param filter
* @param zoneId - if null card can be in ever exile zone
* @param minNumTargets minimum number of targets
* @param maxNumTargets maximum number of targets
* @param filter filter for the card to be a target
*/
public TargetCardInExile(int minNumTargets, int maxNumTargets, FilterCard filter) {
this(minNumTargets, maxNumTargets, filter, null);
}
/**
* @param filter filter for the card to be a target
* @param zoneId if non-null can only target cards in that exileZone. if null card can be in ever exile zone.
*/
public TargetCardInExile(FilterCard filter, UUID zoneId) {
this(1, 1, filter, zoneId);
}
/**
* @param minNumTargets minimum number of targets
* @param maxNumTargets maximum number of targets
* @param filter filter for the card to be a target
* @param zoneId if non-null can only target cards in that exileZone. if null card can be in ever exile zone.
*/
public TargetCardInExile(int minNumTargets, int maxNumTargets, FilterCard filter, UUID zoneId) {
this(minNumTargets, maxNumTargets, filter, zoneId, zoneId == null);
}
public TargetCardInExile(int minNumTargets, int maxNumTargets, FilterCard filter, UUID zoneId, boolean allExileZones) {
super(minNumTargets, maxNumTargets, Zone.EXILED, filter);
this.zoneId = zoneId;
this.allExileZones = zoneId == null || allExileZones;
}
protected TargetCardInExile(final TargetCardInExile target) {
super(target);
this.zoneId = target.zoneId;
this.allExileZones = target.allExileZones;
}
@Override
public Set<UUID> possibleTargets(UUID sourceControllerId, Ability source, Game game) {
Set<UUID> possibleTargets = new HashSet<>();
if (allExileZones) {
if (zoneId == null) { // no specific exile zone
for (Card card : game.getExile().getAllCardsByRange(game, sourceControllerId)) {
if (filter.match(card, sourceControllerId, source, game)) {
possibleTargets.add(card.getId());
@ -73,7 +86,7 @@ public class TargetCardInExile extends TargetCard {
@Override
public boolean canChoose(UUID sourceControllerId, Ability source, Game game) {
if (allExileZones) {
if (zoneId == null) { // no specific exile zone
int numberTargets = 0;
for (ExileZone exileZone : game.getExile().getExileZones()) {
numberTargets += exileZone.count(filter, sourceControllerId, source, game);
@ -96,15 +109,10 @@ public class TargetCardInExile extends TargetCard {
public boolean canTarget(UUID id, Ability source, Game game) {
Card card = game.getCard(id);
if (card != null && game.getState().getZone(card.getId()) == Zone.EXILED) {
if (allExileZones) {
if (zoneId == null) { // no specific exile zone
return filter.match(card, source.getControllerId(), source, game);
}
ExileZone exile;
if (zoneId != null) {
exile = game.getExile().getExileZone(zoneId);
} else {
exile = game.getExile().getPermanentExile();
}
ExileZone exile = game.getExile().getExileZone(zoneId);
if (exile != null && exile.contains(id)) {
return filter.match(card, source.getControllerId(), source, game);
}