From 8123987e5bb403a3e329cd8090ecc95cd9c89a27 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Mon, 19 Jan 2026 15:15:47 -0500 Subject: [PATCH] [FIC] fix Squall, Gunblade Duelist (fixes #14245) --- .../mage/cards/s/SquallGunbladeDuelist.java | 53 +++++++++++-------- ...ksPlayerWithCreaturesTriggeredAbility.java | 18 ++++--- 2 files changed, 41 insertions(+), 30 deletions(-) diff --git a/Mage.Sets/src/mage/cards/s/SquallGunbladeDuelist.java b/Mage.Sets/src/mage/cards/s/SquallGunbladeDuelist.java index b0534bc5c43..ea37aaa169e 100644 --- a/Mage.Sets/src/mage/cards/s/SquallGunbladeDuelist.java +++ b/Mage.Sets/src/mage/cards/s/SquallGunbladeDuelist.java @@ -4,20 +4,21 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.AttacksPlayerWithCreaturesTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.effects.OneShotEffect; import mage.abilities.keyword.FirstStrikeAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; -import mage.filter.FilterPermanent; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.ObjectSourcePlayer; -import mage.filter.predicate.ObjectSourcePlayerPredicate; +import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.util.CardUtil; +import java.util.Collection; +import java.util.Objects; +import java.util.Set; import java.util.UUID; /** @@ -25,12 +26,6 @@ import java.util.UUID; */ public final class SquallGunbladeDuelist extends CardImpl { - private static final FilterPermanent filter = new FilterCreaturePermanent(); - - static { - filter.add(SquallGunbladeDuelistPredicate.instance); - } - public SquallGunbladeDuelist(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{R}{W}{B}"); @@ -49,9 +44,9 @@ public final class SquallGunbladeDuelist extends CardImpl { // Whenever one or more creatures attack one of your opponents, if any of those creatures have power or toughness equal to the chosen number, Squall deals damage equal to its power to defending player. this.addAbility(new AttacksPlayerWithCreaturesTriggeredAbility( new SquallGunbladeDuelistDamageEffect(), 1, - filter, SetTargetPointer.PLAYER, true - ).setTriggerPhrase("Whenever one or more creatures attack one of your opponents, " + - "if any of those creatures have power or toughness equal to the chosen number, ")); + StaticFilters.FILTER_PERMANENT_CREATURE, SetTargetPointer.PLAYER, true + ).withInterveningIf(SquallGunbladeDuelistCondition.instance) + .setTriggerPhrase("Whenever one or more creatures attack one of your opponents, ")); } private SquallGunbladeDuelist(final SquallGunbladeDuelist card) { @@ -64,20 +59,34 @@ public final class SquallGunbladeDuelist extends CardImpl { } } -enum SquallGunbladeDuelistPredicate implements ObjectSourcePlayerPredicate { +enum SquallGunbladeDuelistCondition implements Condition { instance; @Override - public boolean apply(ObjectSourcePlayer input, Game game) { + public boolean apply(Game game, Ability source) { Integer number = (Integer) game .getState() .getValue(CardUtil.getObjectZoneString( - "chosenNumber", input.getSource().getId(), game, - input.getSource().getStackMomentSourceZCC(), true + "chosenNumber", source.getSourceId(), game, + game.getState().getZoneChangeCounter(source.getSourceId()), true )); - return number != null - && (input.getObject().getPower().getValue() == number - || input.getObject().getToughness().getValue() == number); + return source + .getAllEffects() + .stream() + .map(effect -> (Set) effect.getValue("attackingCreatures")) + .filter(Objects::nonNull) + .findFirst() + .map(Collection::stream) + .filter(stream -> stream.anyMatch( + permanent -> permanent.getPower().getValue() == number + || permanent.getToughness().getValue() == number + )) + .isPresent(); + } + + @Override + public String toString() { + return "any of those creatures have power or toughness equal to the chosen number"; } } @@ -105,8 +114,8 @@ class SquallGunbladeDuelistChooseEffect extends OneShotEffect { } int number = player.getAmount(0, Integer.MAX_VALUE, "Choose a number", source, game); game.getState().setValue(CardUtil.getObjectZoneString( - "chosenNumber", source.getId(), game, - source.getStackMomentSourceZCC(), false + "chosenNumber", source.getSourceId(), game, + game.getState().getZoneChangeCounter(source.getSourceId()), false ), number); Permanent permanent = game.getPermanentEntering(source.getSourceId()); if (permanent != null) { diff --git a/Mage/src/main/java/mage/abilities/common/AttacksPlayerWithCreaturesTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/AttacksPlayerWithCreaturesTriggeredAbility.java index 1264c40f4cd..ea4992433a1 100644 --- a/Mage/src/main/java/mage/abilities/common/AttacksPlayerWithCreaturesTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/AttacksPlayerWithCreaturesTriggeredAbility.java @@ -15,13 +15,13 @@ import mage.target.targetpointer.FixedTarget; import mage.target.targetpointer.FixedTargets; import mage.util.CardUtil; -import java.util.ArrayList; -import java.util.List; +import java.util.Set; import java.util.UUID; import java.util.stream.Collectors; /** * based heavily on AttacksWithCreaturesTriggeredAbility + * * @author notgreat */ public class AttacksPlayerWithCreaturesTriggeredAbility extends TriggeredAbilityImpl { @@ -82,26 +82,28 @@ public class AttacksPlayerWithCreaturesTriggeredAbility extends TriggeredAbility return false; } DefenderAttackedEvent attackedEvent = (DefenderAttackedEvent) event; - List attackers = attackedEvent.getAttackers(game).stream() + Set attackers = attackedEvent + .getAttackers(game) + .stream() .filter(permanent -> filter.match(permanent, controllerId, this, game)) - .collect(Collectors.toList()); + .collect(Collectors.toSet()); if (attackers.size() < minAttackers || (onlyOpponents && !game.isOpponent(player, attackedId))) { return false; } - switch (setTargetPointer){ + switch (setTargetPointer) { case NONE: break; case PLAYER: getEffects().setTargetPointer(new FixedTarget(attackedId)); break; case PERMANENT: - getEffects().setTargetPointer(new FixedTargets(new ArrayList<>(attackers), game)); + getEffects().setTargetPointer(new FixedTargets(attackers, game)); break; default: throw new UnsupportedOperationException("Unexpected setTargetPointer in AttacksPlayerWithCreaturesTriggeredAbility: " + setTargetPointer); - } - this.getEffects().setValue("playerAttacked",attackedId); + this.getAllEffects().setValue("attackingCreatures", attackers); + this.getAllEffects().setValue("playerAttacked", attackedId); return true; } }