From 0c1f58be9d6391f5258e33fe0d7c60a883685ff5 Mon Sep 17 00:00:00 2001 From: Grath <1895280+Grath@users.noreply.github.com> Date: Tue, 22 Oct 2024 14:30:04 -0400 Subject: [PATCH 1/5] [SLD] Implement Captain America, First Avenger I made assumptions that WotC is going to fix the rules by adding "choose the equipment you're unattaching with Throw..." to rule 601.2b so that this card actually functions since you have to choose a TargetAnyTargetAmount in steps 601.2c/601.2d long before you actually pay the unattach cost in 601.2h; the way I implemented it, you're technically choosing the equipment at the beginning of 601.2c instead of during 601.2b but it's functionally identical. --- .../cards/c/CaptainAmericaFirstAvenger.java | 225 ++++++++++++++++++ Mage.Sets/src/mage/sets/SecretLairDrop.java | 1 + .../effects/common/DamageMultiEffect.java | 6 +- .../src/main/java/mage/constants/SubType.java | 1 + 4 files changed, 232 insertions(+), 1 deletion(-) create mode 100644 Mage.Sets/src/mage/cards/c/CaptainAmericaFirstAvenger.java diff --git a/Mage.Sets/src/mage/cards/c/CaptainAmericaFirstAvenger.java b/Mage.Sets/src/mage/cards/c/CaptainAmericaFirstAvenger.java new file mode 100644 index 000000000000..2c33dc341106 --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/CaptainAmericaFirstAvenger.java @@ -0,0 +1,225 @@ +package mage.cards.c; + +import java.util.UUID; +import mage.MageInt; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfCombatTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.Cost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.costs.UseAttachedCost; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DamageMultiEffect; +import mage.constants.*; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.common.FilterEquipmentPermanent; +import mage.filter.predicate.ObjectSourcePlayer; +import mage.filter.predicate.ObjectSourcePlayerPredicate; +import mage.filter.predicate.permanent.AttachedToPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.TargetPermanent; +import mage.target.common.TargetAnyTargetAmount; + +/** + * + * @author Grath + */ +public final class CaptainAmericaFirstAvenger extends CardImpl { + + private static final FilterPermanent filter = new FilterEquipmentPermanent("equipment attached to this creature"); + private static final FilterPermanent subfilter = new FilterControlledPermanent("{this}"); + private static final FilterPermanent filter2 = new FilterEquipmentPermanent("equipment you control"); + + static { + subfilter.add(CaptainAmericaPredicate.instance); + filter.add(new AttachedToPredicate(subfilter)); + filter2.add(TargetController.YOU.getControllerPredicate()); + } + + public CaptainAmericaFirstAvenger(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{R}{W}{U}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.SOLDIER); + this.subtype.add(SubType.HERO); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // Throw ... — {3}, Unattach an Equipment from Captain America: He deals damage equal to that Equipment’s mana value divided as you choose among one, two, or three targets. + Ability ability = new SimpleActivatedAbility(new CaptainAmericaFirstAvengerThrowEffect(), new GenericManaCost(3)); + ability.addCost(new CaptainAmericaFirstAvengerUnattachCost()); + // 2024-10-22: It isn't in rule 601.2b yet, but you will have to choose the equipment before the actual targets to comply with rules 601.2c/601.2d + // This is technically happening in step 601.2c, but it's still in time for the following TargetAnyTargetAmount to work properly. + ability.addTarget(new TargetPermanent(1, 1, filter, true)); + ability.addTarget(new TargetAnyTargetAmount(CaptainAmericaFirstAvengerValue.instance, 3)); + this.addAbility(ability.withFlavorWord("Throw ...")); + + // ... Catch — At the beginning of combat on your turn, attach up to one target Equipment you control to Captain America. + ability = new BeginningOfCombatTriggeredAbility( + new CaptainAmericaFirstAvengerCatchEffect(), TargetController.YOU, false + ); + ability.addTarget(new TargetPermanent(0, 1, filter2)); + this.addAbility(ability.withFlavorWord("... Catch")); + } + + private CaptainAmericaFirstAvenger(final CaptainAmericaFirstAvenger card) { + super(card); + } + + @Override + public CaptainAmericaFirstAvenger copy() { + return new CaptainAmericaFirstAvenger(this); + } +} + +enum CaptainAmericaPredicate implements ObjectSourcePlayerPredicate { + instance; + + @Override + public boolean apply(ObjectSourcePlayer input, Game game) { + if (!input.getObject().getId().equals(input.getSourceId())) { + return false; + } + int zcc = input.getSource().getSourceObjectZoneChangeCounter(); + return zcc == input.getObject().getZoneChangeCounter(game); + } + + @Override + public String toString() { + return "Another"; + } +} + +enum CaptainAmericaFirstAvengerValue implements DynamicValue { + instance; + + @Override + public int calculate(Game game, Ability sourceAbility, Effect effect) { + int amount = 0; + UUID chosenEquipment = sourceAbility.getFirstTarget(); + if (chosenEquipment != null) { + Permanent equipment = game.getPermanentOrLKIBattlefield(chosenEquipment); + if (equipment != null) { + amount = equipment.getManaValue(); + } + } + return amount; + } + + @Override + public DynamicValue copy() { + return instance; + } + + @Override + public String toString() { + return "X"; + } + + @Override + public String getMessage() { + return "that Equipment's mana value"; + } +} + +class CaptainAmericaFirstAvengerUnattachCost extends UseAttachedCost { + + public CaptainAmericaFirstAvengerUnattachCost() { + super(); + } + + protected CaptainAmericaFirstAvengerUnattachCost(final CaptainAmericaFirstAvengerUnattachCost cost) { + super(cost); + } + + @Override + public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) { + Permanent permanent = game.getPermanent(source.getSourceId()); + return permanent != null + && !permanent.getAttachments().isEmpty(); + } + + @Override + public boolean pay(Ability ability, Game game, Ability source, UUID controllerId, boolean noMana, Cost costToPay) { + Player player = game.getPlayer(source.getControllerId()); + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent == null) { + return paid; + } + Permanent equipment = game.getPermanentOrLKIBattlefield(source.getFirstTarget()); + if (!permanent.getAttachments().contains(source.getFirstTarget()) || + !player.chooseUse(Outcome.Benefit, "Unattach " + equipment.getName() + "?", source, game)) { + return false; + } + paid = permanent.removeAttachment(source.getFirstTarget(), source, game); + + return paid; + } + + @Override + public CaptainAmericaFirstAvengerUnattachCost copy() { + return new CaptainAmericaFirstAvengerUnattachCost(this); + } + + @Override + public String getText() { + return "Unattach an Equipment from " + this.name; + } +} + +class CaptainAmericaFirstAvengerThrowEffect extends DamageMultiEffect { + CaptainAmericaFirstAvengerThrowEffect() { + super(CaptainAmericaFirstAvengerValue.instance, "he"); + staticText = "he deals damage equal to that Equipment's mana value divided as you choose among one, two, or three targets."; + } + + private CaptainAmericaFirstAvengerThrowEffect(final CaptainAmericaFirstAvengerThrowEffect effect) { + super(effect); + } + + @Override + public CaptainAmericaFirstAvengerThrowEffect copy() { + return new CaptainAmericaFirstAvengerThrowEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + // The first target is the no-longer-needed choice of equipment attached to Captain America. + // The second target is the TargetAnyTargetAmount which DamageMultEffect uses to assign the proper damage. + source.getTargets().remove(0); + return super.apply(game, source); + } +} + +class CaptainAmericaFirstAvengerCatchEffect extends OneShotEffect { + + CaptainAmericaFirstAvengerCatchEffect() { + super(Outcome.Benefit); + staticText = "attach target Equipment you control to {this}"; + } + + private CaptainAmericaFirstAvengerCatchEffect(final CaptainAmericaFirstAvengerCatchEffect effect) { + super(effect); + } + + @Override + public CaptainAmericaFirstAvengerCatchEffect copy() { + return new CaptainAmericaFirstAvengerCatchEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent equipment = game.getPermanent(this.getTargetPointer().getFirst(game, source)); + Permanent creature = source.getSourcePermanentIfItStillExists(game); + return equipment != null && creature != null && creature.addAttachment(equipment.getId(), source, game); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/SecretLairDrop.java b/Mage.Sets/src/mage/sets/SecretLairDrop.java index 2dee778e1c99..16ba5b4590a6 100644 --- a/Mage.Sets/src/mage/sets/SecretLairDrop.java +++ b/Mage.Sets/src/mage/sets/SecretLairDrop.java @@ -1380,6 +1380,7 @@ private SecretLairDrop() { cards.add(new SetCardInfo("Mayhem Devil", 1715, Rarity.RARE, mage.cards.m.MayhemDevil.class)); cards.add(new SetCardInfo("Moldervine Reclamation", 1716, Rarity.RARE, mage.cards.m.MoldervineReclamation.class)); cards.add(new SetCardInfo("Prossh, Skyraider of Kher", 1717, Rarity.MYTHIC, mage.cards.p.ProsshSkyraiderOfKher.class)); + cards.add(new SetCardInfo("Captain America, First Avenger", 1726, Rarity.MYTHIC, mage.cards.c.CaptainAmericaFirstAvenger.class)); cards.add(new SetCardInfo("Jace, the Mind Sculptor", 8001, Rarity.MYTHIC, mage.cards.j.JaceTheMindSculptor.class)); cards.add(new SetCardInfo("Doom Blade", 9990, Rarity.RARE, mage.cards.d.DoomBlade.class)); cards.add(new SetCardInfo("Massacre", 9991, Rarity.RARE, mage.cards.m.Massacre.class)); diff --git a/Mage/src/main/java/mage/abilities/effects/common/DamageMultiEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DamageMultiEffect.java index 57cb0c4dc137..653be78f3e77 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/DamageMultiEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/DamageMultiEffect.java @@ -28,7 +28,11 @@ public DamageMultiEffect(int amount) { } public DamageMultiEffect(int amount, String whoDealDamageName) { - this(StaticValue.get(amount)); + this(StaticValue.get(amount), whoDealDamageName); + } + + public DamageMultiEffect(DynamicValue amount, String whoDealDamageName) { + this(amount); this.sourceName = whoDealDamageName; } diff --git a/Mage/src/main/java/mage/constants/SubType.java b/Mage/src/main/java/mage/constants/SubType.java index 952aa8b3b1d3..6a439c8c0ed9 100644 --- a/Mage/src/main/java/mage/constants/SubType.java +++ b/Mage/src/main/java/mage/constants/SubType.java @@ -209,6 +209,7 @@ public enum SubType { HAMSTER("Hamster", SubTypeSet.CreatureType), HARPY("Harpy", SubTypeSet.CreatureType), HELLION("Hellion", SubTypeSet.CreatureType), + HERO("Hero", SubTypeSet.CreatureType), HIPPO("Hippo", SubTypeSet.CreatureType), HIPPOGRIFF("Hippogriff", SubTypeSet.CreatureType), HOMARID("Homarid", SubTypeSet.CreatureType), From 05be239e427bcb6d322b96017d0c43fbf09d3647 Mon Sep 17 00:00:00 2001 From: Grath <1895280+Grath@users.noreply.github.com> Date: Tue, 22 Oct 2024 17:56:05 -0400 Subject: [PATCH 2/5] Remove Target workaround, add proper 601.2b handling for choosing cost targets early using inheritance to avoid having a horrific brittle list of 'these costs must be paid early'. --- .../cards/c/CaptainAmericaFirstAvenger.java | 74 ++++++++----------- .../main/java/mage/abilities/AbilityImpl.java | 16 ++++ .../mage/abilities/costs/EarlyTargetCost.java | 25 +++++++ 3 files changed, 73 insertions(+), 42 deletions(-) create mode 100644 Mage/src/main/java/mage/abilities/costs/EarlyTargetCost.java diff --git a/Mage.Sets/src/mage/cards/c/CaptainAmericaFirstAvenger.java b/Mage.Sets/src/mage/cards/c/CaptainAmericaFirstAvenger.java index 2c33dc341106..927298bf04bd 100644 --- a/Mage.Sets/src/mage/cards/c/CaptainAmericaFirstAvenger.java +++ b/Mage.Sets/src/mage/cards/c/CaptainAmericaFirstAvenger.java @@ -7,8 +7,8 @@ import mage.abilities.common.BeginningOfCombatTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.Cost; +import mage.abilities.costs.EarlyTargetCost; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.costs.UseAttachedCost; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; @@ -25,6 +25,7 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.Target; import mage.target.TargetPermanent; import mage.target.common.TargetAnyTargetAmount; @@ -34,13 +35,9 @@ */ public final class CaptainAmericaFirstAvenger extends CardImpl { - private static final FilterPermanent filter = new FilterEquipmentPermanent("equipment attached to this creature"); - private static final FilterPermanent subfilter = new FilterControlledPermanent("{this}"); private static final FilterPermanent filter2 = new FilterEquipmentPermanent("equipment you control"); static { - subfilter.add(CaptainAmericaPredicate.instance); - filter.add(new AttachedToPredicate(subfilter)); filter2.add(TargetController.YOU.getControllerPredicate()); } @@ -55,11 +52,11 @@ public CaptainAmericaFirstAvenger(UUID ownerId, CardSetInfo setInfo) { this.toughness = new MageInt(4); // Throw ... — {3}, Unattach an Equipment from Captain America: He deals damage equal to that Equipment’s mana value divided as you choose among one, two, or three targets. - Ability ability = new SimpleActivatedAbility(new CaptainAmericaFirstAvengerThrowEffect(), new GenericManaCost(3)); + Ability ability = new SimpleActivatedAbility( + new DamageMultiEffect(CaptainAmericaFirstAvengerValue.instance).setText( + "he deals damage equal to that Equipment's mana value divided as you choose among one, two, or three targets."), + new GenericManaCost(3)); ability.addCost(new CaptainAmericaFirstAvengerUnattachCost()); - // 2024-10-22: It isn't in rule 601.2b yet, but you will have to choose the equipment before the actual targets to comply with rules 601.2c/601.2d - // This is technically happening in step 601.2c, but it's still in time for the following TargetAnyTargetAmount to work properly. - ability.addTarget(new TargetPermanent(1, 1, filter, true)); ability.addTarget(new TargetAnyTargetAmount(CaptainAmericaFirstAvengerValue.instance, 3)); this.addAbility(ability.withFlavorWord("Throw ...")); @@ -84,6 +81,7 @@ public CaptainAmericaFirstAvenger copy() { enum CaptainAmericaPredicate implements ObjectSourcePlayerPredicate { instance; + // Functional negation of AnotherPredicate. @Override public boolean apply(ObjectSourcePlayer input, Game game) { if (!input.getObject().getId().equals(input.getSourceId())) { @@ -95,7 +93,7 @@ public boolean apply(ObjectSourcePlayer input, Game game) { @Override public String toString() { - return "Another"; + return "{this}"; } } @@ -105,11 +103,12 @@ enum CaptainAmericaFirstAvengerValue implements DynamicValue { @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { int amount = 0; - UUID chosenEquipment = sourceAbility.getFirstTarget(); - if (chosenEquipment != null) { - Permanent equipment = game.getPermanentOrLKIBattlefield(chosenEquipment); - if (equipment != null) { - amount = equipment.getManaValue(); + for (Cost cost : sourceAbility.getCosts()) { + if (cost instanceof CaptainAmericaFirstAvengerUnattachCost && !cost.getTargets().isEmpty()) { + Permanent equipment = game.getPermanentOrLKIBattlefield(cost.getTargets().getFirstTarget()); + if (equipment != null) { + amount = equipment.getManaValue(); + } } } return amount; @@ -131,7 +130,15 @@ public String getMessage() { } } -class CaptainAmericaFirstAvengerUnattachCost extends UseAttachedCost { +class CaptainAmericaFirstAvengerUnattachCost extends EarlyTargetCost { + + private static final FilterPermanent filter = new FilterEquipmentPermanent("equipment attached to this creature"); + private static final FilterPermanent subfilter = new FilterControlledPermanent("{this}"); + + static { + subfilter.add(CaptainAmericaPredicate.instance); + filter.add(new AttachedToPredicate(subfilter)); + } public CaptainAmericaFirstAvengerUnattachCost() { super(); @@ -155,12 +162,12 @@ public boolean pay(Ability ability, Game game, Ability source, UUID controllerId if (permanent == null) { return paid; } - Permanent equipment = game.getPermanentOrLKIBattlefield(source.getFirstTarget()); - if (!permanent.getAttachments().contains(source.getFirstTarget()) || + Permanent equipment = game.getPermanentOrLKIBattlefield(getTargets().getFirstTarget()); + if (equipment == null || !permanent.getAttachments().contains(getTargets().getFirstTarget()) || !player.chooseUse(Outcome.Benefit, "Unattach " + equipment.getName() + "?", source, game)) { return false; } - paid = permanent.removeAttachment(source.getFirstTarget(), source, game); + paid = permanent.removeAttachment(getTargets().getFirstTarget(), source, game); return paid; } @@ -171,32 +178,15 @@ public CaptainAmericaFirstAvengerUnattachCost copy() { } @Override - public String getText() { - return "Unattach an Equipment from " + this.name; - } -} - -class CaptainAmericaFirstAvengerThrowEffect extends DamageMultiEffect { - CaptainAmericaFirstAvengerThrowEffect() { - super(CaptainAmericaFirstAvengerValue.instance, "he"); - staticText = "he deals damage equal to that Equipment's mana value divided as you choose among one, two, or three targets."; - } - - private CaptainAmericaFirstAvengerThrowEffect(final CaptainAmericaFirstAvengerThrowEffect effect) { - super(effect); - } - - @Override - public CaptainAmericaFirstAvengerThrowEffect copy() { - return new CaptainAmericaFirstAvengerThrowEffect(this); + public void chooseTarget(Game game, Ability source, Player controller) { + Target chosenEquipment = new TargetPermanent(1, 1, filter, true); + controller.choose(Outcome.Benefit, chosenEquipment, source, game); + addTarget(chosenEquipment); } @Override - public boolean apply(Game game, Ability source) { - // The first target is the no-longer-needed choice of equipment attached to Captain America. - // The second target is the TargetAnyTargetAmount which DamageMultEffect uses to assign the proper damage. - source.getTargets().remove(0); - return super.apply(game, source); + public String getText() { + return "Unattach an Equipment from {this}"; } } diff --git a/Mage/src/main/java/mage/abilities/AbilityImpl.java b/Mage/src/main/java/mage/abilities/AbilityImpl.java index 6da0269961c0..3acf3dcff259 100644 --- a/Mage/src/main/java/mage/abilities/AbilityImpl.java +++ b/Mage/src/main/java/mage/abilities/AbilityImpl.java @@ -6,6 +6,7 @@ import mage.abilities.condition.Condition; import mage.abilities.costs.*; import mage.abilities.costs.common.PayLifeCost; +import mage.abilities.costs.common.SacrificeTargetCost; import mage.abilities.costs.mana.ManaCost; import mage.abilities.costs.mana.ManaCosts; import mage.abilities.costs.mana.ManaCostsImpl; @@ -330,6 +331,10 @@ public boolean activate(Game game, Set allowedIdentifiers, boole handlePhyrexianManaCosts(game, controller); + // 20241022 - 601.2b + // Not yet included in 601.2b but this is where it will be + handleChooseCostTargets(game, controller); + /* 20130201 - 601.2b * If the spell is modal the player announces the mode choice (see rule 700.2). */ @@ -649,6 +654,17 @@ private void handlePhyrexianManaCosts(Game game, Player controller) { } } + /** + * 601.2b Choose targets for costs that have to be chosen early. + */ + private void handleChooseCostTargets(Game game, Player controller) { + for (Cost cost : getCosts()) { + if (cost instanceof EarlyTargetCost && cost.getTargets().isEmpty()) { + ((EarlyTargetCost) cost).chooseTarget(game, this, controller); + } + } + } + /** * Handles X mana costs and sets manaCostsToPay. * diff --git a/Mage/src/main/java/mage/abilities/costs/EarlyTargetCost.java b/Mage/src/main/java/mage/abilities/costs/EarlyTargetCost.java new file mode 100644 index 000000000000..359188f7fdc3 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/costs/EarlyTargetCost.java @@ -0,0 +1,25 @@ +package mage.abilities.costs; + +import mage.abilities.Ability; +import mage.game.Game; +import mage.players.Player; + +/** + * @author Grath + * Costs which extend this class need to have targets chosen, and those targets must be chosen during 601.2b step. + */ +public abstract class EarlyTargetCost extends CostImpl { + + protected EarlyTargetCost() { + super(); + } + + protected EarlyTargetCost(final EarlyTargetCost cost) { + super(cost); + } + + @Override + public abstract EarlyTargetCost copy(); + + public abstract void chooseTarget(Game game, Ability source, Player controller); +} From 2e1e64c3e4dfcb58fcff733a043644df1c8bbbf0 Mon Sep 17 00:00:00 2001 From: Grath <1895280+Grath@users.noreply.github.com> Date: Tue, 22 Oct 2024 18:04:35 -0400 Subject: [PATCH 3/5] Add comment that EarlyTargetCost only functions with Abilities, not Spells. --- Mage/src/main/java/mage/abilities/costs/EarlyTargetCost.java | 1 + 1 file changed, 1 insertion(+) diff --git a/Mage/src/main/java/mage/abilities/costs/EarlyTargetCost.java b/Mage/src/main/java/mage/abilities/costs/EarlyTargetCost.java index 359188f7fdc3..06dd2565cac0 100644 --- a/Mage/src/main/java/mage/abilities/costs/EarlyTargetCost.java +++ b/Mage/src/main/java/mage/abilities/costs/EarlyTargetCost.java @@ -7,6 +7,7 @@ /** * @author Grath * Costs which extend this class need to have targets chosen, and those targets must be chosen during 601.2b step. + * 20241022 - This currently is only implemented when paying for Abilities, not Spells. */ public abstract class EarlyTargetCost extends CostImpl { From d2e2b122de01b2ca7b6ea371e5baf259de596d88 Mon Sep 17 00:00:00 2001 From: Grath <1895280+Grath@users.noreply.github.com> Date: Tue, 22 Oct 2024 20:40:36 -0400 Subject: [PATCH 4/5] Fix comment, since Spells are SpellAbility and use the same code path. --- Mage/src/main/java/mage/abilities/costs/EarlyTargetCost.java | 1 - 1 file changed, 1 deletion(-) diff --git a/Mage/src/main/java/mage/abilities/costs/EarlyTargetCost.java b/Mage/src/main/java/mage/abilities/costs/EarlyTargetCost.java index 06dd2565cac0..359188f7fdc3 100644 --- a/Mage/src/main/java/mage/abilities/costs/EarlyTargetCost.java +++ b/Mage/src/main/java/mage/abilities/costs/EarlyTargetCost.java @@ -7,7 +7,6 @@ /** * @author Grath * Costs which extend this class need to have targets chosen, and those targets must be chosen during 601.2b step. - * 20241022 - This currently is only implemented when paying for Abilities, not Spells. */ public abstract class EarlyTargetCost extends CostImpl { From 451a7ebdfa008f1e8d561b72e900e94d219bebe7 Mon Sep 17 00:00:00 2001 From: Grath <1895280+Grath@users.noreply.github.com> Date: Tue, 22 Oct 2024 22:47:55 -0400 Subject: [PATCH 5/5] Fix miscellaneous issues. --- .../mage/cards/c/CaptainAmericaFirstAvenger.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Mage.Sets/src/mage/cards/c/CaptainAmericaFirstAvenger.java b/Mage.Sets/src/mage/cards/c/CaptainAmericaFirstAvenger.java index 927298bf04bd..86ada3c4358d 100644 --- a/Mage.Sets/src/mage/cards/c/CaptainAmericaFirstAvenger.java +++ b/Mage.Sets/src/mage/cards/c/CaptainAmericaFirstAvenger.java @@ -35,10 +35,10 @@ */ public final class CaptainAmericaFirstAvenger extends CardImpl { - private static final FilterPermanent filter2 = new FilterEquipmentPermanent("equipment you control"); + private static final FilterPermanent filter = new FilterEquipmentPermanent("Equipment you control"); static { - filter2.add(TargetController.YOU.getControllerPredicate()); + filter.add(TargetController.YOU.getControllerPredicate()); } public CaptainAmericaFirstAvenger(UUID ownerId, CardSetInfo setInfo) { @@ -64,7 +64,7 @@ public CaptainAmericaFirstAvenger(UUID ownerId, CardSetInfo setInfo) { ability = new BeginningOfCombatTriggeredAbility( new CaptainAmericaFirstAvengerCatchEffect(), TargetController.YOU, false ); - ability.addTarget(new TargetPermanent(0, 1, filter2)); + ability.addTarget(new TargetPermanent(0, 1, filter)); this.addAbility(ability.withFlavorWord("... Catch")); } @@ -140,7 +140,7 @@ class CaptainAmericaFirstAvengerUnattachCost extends EarlyTargetCost { filter.add(new AttachedToPredicate(subfilter)); } - public CaptainAmericaFirstAvengerUnattachCost() { + CaptainAmericaFirstAvengerUnattachCost() { super(); } @@ -159,15 +159,15 @@ public boolean canPay(Ability ability, Ability source, UUID controllerId, Game g public boolean pay(Ability ability, Game game, Ability source, UUID controllerId, boolean noMana, Cost costToPay) { Player player = game.getPlayer(source.getControllerId()); Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent == null) { + if (permanent == null || player == null) { return paid; } Permanent equipment = game.getPermanentOrLKIBattlefield(getTargets().getFirstTarget()); - if (equipment == null || !permanent.getAttachments().contains(getTargets().getFirstTarget()) || - !player.chooseUse(Outcome.Benefit, "Unattach " + equipment.getName() + "?", source, game)) { + if (equipment == null || !permanent.getAttachments().contains(equipment.getId()) || + !player.chooseUse(Outcome.Benefit, "Unattach " + equipment.getIdName() + "?", source, game)) { return false; } - paid = permanent.removeAttachment(getTargets().getFirstTarget(), source, game); + paid = permanent.removeAttachment(equipment.getId(), source, game); return paid; }