refactor: add FilterSource to match TargetSource (#13703)

Small fix of enabling TargetSource to choose/target a Command Object
This commit is contained in:
Susucre 2025-06-01 15:52:51 +02:00 committed by Failure
parent 65bc705c0e
commit e26d0c1bb9
42 changed files with 522 additions and 278 deletions

View file

@ -2,40 +2,52 @@
package mage.target;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.cards.Card;
import mage.constants.Zone;
import mage.filter.FilterObject;
import mage.filter.FilterSource;
import mage.game.Game;
import mage.game.command.CommandObject;
import mage.game.permanent.Permanent;
import mage.game.stack.StackObject;
import mage.players.Player;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
/**
* 609.7a. If an effect requires a player to choose a source of damage, they may choose a permanent;
* a spell on the stack (including a permanent spell); any object referred to by an object on the stack,
* by a replacement or prevention effect that's waiting to apply, or by a delayed triggered ability
* that's waiting to trigger (even if that object is no longer in the zone it used to be in); or a
* face-up object in the command zone. A source doesn't need to be capable of dealing damage to be
* a legal choice. The source is chosen when the effect is created. If the player chooses a permanent,
* the effect will apply to the next damage dealt by that permanent, regardless of whether it's combat
* damage or damage dealt as the result of a spell or ability. If the player chooses a permanent spell,
* the effect will apply to any damage dealt by that spell and any damage dealt by the permanent that
* spell becomes when it resolves.
*
* @author BetaSteward_at_googlemail.com
*/
public class TargetSource extends TargetObject {
protected final FilterObject filter;
protected final FilterSource filter;
public TargetSource() {
this(1, 1, new FilterObject("source of your choice"));
this(1, 1, new FilterSource("source of your choice"));
}
public TargetSource(FilterObject filter) {
public TargetSource(FilterSource filter) {
this(1, 1, filter);
}
public TargetSource(int numTargets, FilterObject filter) {
public TargetSource(int numTargets, FilterSource filter) {
this(numTargets, numTargets, filter);
}
public TargetSource(int minNumTargets, int maxNumTargets, FilterObject filter) {
public TargetSource(int minNumTargets, int maxNumTargets, FilterSource filter) {
super(minNumTargets, maxNumTargets, Zone.ALL, true);
this.filter = filter;
this.targetName = filter.getMessage();
@ -47,7 +59,7 @@ public class TargetSource extends TargetObject {
}
@Override
public FilterObject getFilter() {
public FilterSource getFilter() {
return filter;
}
@ -78,15 +90,16 @@ public class TargetSource extends TargetObject {
}
@Override
public boolean canChoose(UUID sourceControllerId, Ability source, Game game) {
return canChoose(sourceControllerId, game);
public boolean canChoose(UUID sourceControllerId, Game game) {
return canChoose(sourceControllerId, (Ability) null, game);
}
@Override
public boolean canChoose(UUID sourceControllerId, Game game) {
public boolean canChoose(UUID sourceControllerId, Ability source, Game game) {
int count = 0;
for (StackObject stackObject : game.getStack()) {
if (game.getState().getPlayersInRange(sourceControllerId, game).contains(stackObject.getControllerId()) && filter.match(stackObject, game)) {
if (game.getState().getPlayersInRange(sourceControllerId, game).contains(stackObject.getControllerId())
&& filter.match(stackObject, sourceControllerId, source, game)) {
count++;
if (count >= this.minNumberOfTargets) {
return true;
@ -94,7 +107,7 @@ public class TargetSource extends TargetObject {
}
}
for (Permanent permanent : game.getBattlefield().getActivePermanents(sourceControllerId, game)) {
if (filter.match(permanent, game)) {
if (filter.match(permanent, sourceControllerId, source, game)) {
count++;
if (count >= this.minNumberOfTargets) {
return true;
@ -103,7 +116,7 @@ public class TargetSource extends TargetObject {
}
for (Player player : game.getPlayers().values()) {
for (Card card : player.getGraveyard().getCards(game)) {
if (filter.match(card, game)) {
if (filter.match(card, sourceControllerId, source, game)) {
count++;
if (count >= this.minNumberOfTargets) {
return true;
@ -112,7 +125,15 @@ public class TargetSource extends TargetObject {
}
}
for (Card card : game.getExile().getAllCards(game)) {
if (filter.match(card, game)) {
if (filter.match(card, sourceControllerId, source, game)) {
count++;
if (count >= this.minNumberOfTargets) {
return true;
}
}
}
for (CommandObject commandObject : game.getState().getCommand()) {
if (filter.match(commandObject, sourceControllerId, source, game)) {
count++;
if (count >= this.minNumberOfTargets) {
return true;
@ -123,35 +144,41 @@ public class TargetSource extends TargetObject {
}
@Override
public Set<UUID> possibleTargets(UUID sourceControllerId, Ability source, Game game) {
return possibleTargets(sourceControllerId, game);
public Set<UUID> possibleTargets(UUID sourceControllerId, Game game) {
return possibleTargets(sourceControllerId, (Ability) null, game);
}
@Override
public Set<UUID> possibleTargets(UUID sourceControllerId, Game game) {
public Set<UUID> possibleTargets(UUID sourceControllerId, Ability source, Game game) {
Set<UUID> possibleTargets = new HashSet<>();
for (StackObject stackObject : game.getStack()) {
if (game.getState().getPlayersInRange(sourceControllerId, game).contains(stackObject.getControllerId()) && filter.match(stackObject, game)) {
if (game.getState().getPlayersInRange(sourceControllerId, game).contains(stackObject.getControllerId())
&& filter.match(stackObject, sourceControllerId, source, game)) {
possibleTargets.add(stackObject.getId());
}
}
for (Permanent permanent : game.getBattlefield().getActivePermanents(sourceControllerId, game)) {
if (filter.match(permanent, game)) {
if (filter.match(permanent, sourceControllerId, source, game)) {
possibleTargets.add(permanent.getId());
}
}
for (Player player : game.getPlayers().values()) {
for (Card card : player.getGraveyard().getCards(game)) {
if (filter.match(card, game)) {
if (filter.match(card, sourceControllerId, source, game)) {
possibleTargets.add(card.getId());
}
}
}
for (Card card : game.getExile().getAllCards(game)) {
if (filter.match(card, game)) {
if (filter.match(card, sourceControllerId, source, game)) {
possibleTargets.add(card.getId());
}
}
for (CommandObject commandObject : game.getState().getCommand()) {
if (filter.match(commandObject, sourceControllerId, source, game)) {
possibleTargets.add(commandObject.getId());
}
}
return possibleTargets;
}