From 7cfe39ae212994b6f18bc246d6e2ef3003f8c3de Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Wed, 29 Jul 2020 16:16:47 +0200 Subject: [PATCH] * Fixed that not all Equip abilities were correctly identified for abilities that changed Equip timig (e.g. Leonin Shikari - fixes #6907). --- .../src/mage/cards/b/BlackbladeReforged.java | 4 +- .../src/mage/cards/g/GolemSkinGauntlets.java | 2 + .../src/mage/cards/s/SteelclawLance.java | 4 +- .../mage/cards/s/SyrGwynHeroOfAshvale.java | 7 ++- .../equipped/GolemSkinGauntletsTest.java | 3 + .../single/eld/SyrGwynHeroOfAshvaleTest.java | 62 +++++++++++++++++++ ...itiesAnyTimeYouCouldCastInstantEffect.java | 4 +- .../mage/abilities/keyword/EquipAbility.java | 12 +++- .../abilities/keyword/EquipFilterAbility.java | 40 ------------ 9 files changed, 87 insertions(+), 51 deletions(-) create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/single/eld/SyrGwynHeroOfAshvaleTest.java delete mode 100644 Mage/src/main/java/mage/abilities/keyword/EquipFilterAbility.java diff --git a/Mage.Sets/src/mage/cards/b/BlackbladeReforged.java b/Mage.Sets/src/mage/cards/b/BlackbladeReforged.java index 5750ed8ae1..884afe2711 100644 --- a/Mage.Sets/src/mage/cards/b/BlackbladeReforged.java +++ b/Mage.Sets/src/mage/cards/b/BlackbladeReforged.java @@ -11,7 +11,6 @@ import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; import mage.abilities.effects.common.continuous.BoostEquippedEffect; import mage.abilities.keyword.EquipAbility; -import mage.abilities.keyword.EquipFilterAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; @@ -19,6 +18,7 @@ import mage.filter.StaticFilters; import mage.filter.common.FilterControlledCreaturePermanent; import java.util.UUID; +import mage.target.common.TargetControlledCreaturePermanent; /** * @author Rystan @@ -43,7 +43,7 @@ public final class BlackbladeReforged extends CardImpl { this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(count, count))); // Equip legendary creature (3) - this.addAbility(new EquipFilterAbility(filter, new GenericManaCost(3))); + this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(3), new TargetControlledCreaturePermanent(filter))); // Equip {7} this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(7))); diff --git a/Mage.Sets/src/mage/cards/g/GolemSkinGauntlets.java b/Mage.Sets/src/mage/cards/g/GolemSkinGauntlets.java index 9c9e80861d..e64712a120 100644 --- a/Mage.Sets/src/mage/cards/g/GolemSkinGauntlets.java +++ b/Mage.Sets/src/mage/cards/g/GolemSkinGauntlets.java @@ -31,6 +31,8 @@ public final class GolemSkinGauntlets extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{1}"); this.subtype.add(SubType.EQUIPMENT); + // Equipped creature gets +1/+0 for each Equipment attached to it. + // Equip 2 (2: Attach to target creature you control. Equip only as a sorcery. This card enters the battlefield unattached and stays on the battlefield if the creature leaves.) this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(new GolemSkinGauntletsAttachedCount(), StaticValue.get(0), Duration.WhileOnBattlefield))); this.addAbility(new EquipAbility(Outcome.BoostCreature, new GenericManaCost(2))); } diff --git a/Mage.Sets/src/mage/cards/s/SteelclawLance.java b/Mage.Sets/src/mage/cards/s/SteelclawLance.java index ace1b7684f..3034642fcd 100644 --- a/Mage.Sets/src/mage/cards/s/SteelclawLance.java +++ b/Mage.Sets/src/mage/cards/s/SteelclawLance.java @@ -4,7 +4,6 @@ import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.common.continuous.BoostEquippedEffect; import mage.abilities.keyword.EquipAbility; -import mage.abilities.keyword.EquipFilterAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -13,6 +12,7 @@ import mage.constants.SubType; import mage.filter.common.FilterControlledCreaturePermanent; import java.util.UUID; +import mage.target.common.TargetControlledCreaturePermanent; /** * @author TheElk801 @@ -31,7 +31,7 @@ public final class SteelclawLance extends CardImpl { this.addAbility(new SimpleStaticAbility(new BoostEquippedEffect(2, 2))); // Equip Knight {1} - this.addAbility(new EquipFilterAbility(filter, new GenericManaCost(1))); + this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(1), new TargetControlledCreaturePermanent(filter))); // Equip {3} this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(3))); diff --git a/Mage.Sets/src/mage/cards/s/SyrGwynHeroOfAshvale.java b/Mage.Sets/src/mage/cards/s/SyrGwynHeroOfAshvale.java index 6034bc8149..14c92435fb 100644 --- a/Mage.Sets/src/mage/cards/s/SyrGwynHeroOfAshvale.java +++ b/Mage.Sets/src/mage/cards/s/SyrGwynHeroOfAshvale.java @@ -8,7 +8,6 @@ import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.LoseLifeSourceControllerEffect; import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; -import mage.abilities.keyword.EquipFilterAbility; import mage.abilities.keyword.MenaceAbility; import mage.abilities.keyword.VigilanceAbility; import mage.cards.CardImpl; @@ -23,6 +22,9 @@ import mage.filter.common.FilterControlledPermanent; import mage.filter.predicate.permanent.EquippedPredicate; import java.util.UUID; +import mage.abilities.keyword.EquipAbility; +import mage.constants.Outcome; +import mage.target.common.TargetControlledCreaturePermanent; /** * @author TheElk801 @@ -64,7 +66,8 @@ public final class SyrGwynHeroOfAshvale extends CardImpl { // Equipment you control have equip Knight {0}. this.addAbility(new SimpleStaticAbility(new GainAbilityControlledEffect( - new EquipFilterAbility(filter3, new GenericManaCost(0)), Duration.WhileOnBattlefield, filter2 + new EquipAbility(Outcome.AddAbility, new GenericManaCost(0), new TargetControlledCreaturePermanent(filter3)), + Duration.WhileOnBattlefield, filter2 ))); } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/equipped/GolemSkinGauntletsTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/equipped/GolemSkinGauntletsTest.java index 8d4772bc3b..0941fb5c26 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/equipped/GolemSkinGauntletsTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/equipped/GolemSkinGauntletsTest.java @@ -19,6 +19,9 @@ public class GolemSkinGauntletsTest extends CardTestPlayerBase { @Test public void testBoostOnEquip() { addCard(Zone.BATTLEFIELD, playerA, "Mountain", 6); + // Equipped creature doesn't untap during its controller's untap step. + // Equipped creature has "{T}: This creature deals 2 damage to any target." + // Equip {4) addCard(Zone.BATTLEFIELD, playerA, "Heavy Arbalest"); addCard(Zone.BATTLEFIELD, playerA, "Golem-Skin Gauntlets"); addCard(Zone.BATTLEFIELD, playerA, "Elite Vanguard"); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/eld/SyrGwynHeroOfAshvaleTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/eld/SyrGwynHeroOfAshvaleTest.java new file mode 100644 index 0000000000..bfeab03b91 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/eld/SyrGwynHeroOfAshvaleTest.java @@ -0,0 +1,62 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.mage.test.cards.single.eld; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ + +public class SyrGwynHeroOfAshvaleTest extends CardTestPlayerBase { + + @Test + public void equipKnightTest() { + // Equipped creature gets +2/+2 and has trample and lifelink. + addCard(Zone.BATTLEFIELD, playerA, "Behemoth Sledge"); // Artifact - Equipment {1}{G}{W} + + // Vigilance, menace + // Whenever an equipped creature you control attacks, you draw a card and you lose 1 life. + // Equipment you control have equip Knight {0}. + addCard(Zone.BATTLEFIELD, playerA, "Syr Gwyn, Hero of Ashvale"); // Legendary Creature {3}{R}{W}{B} 5/5 Human Knight + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Equip Knight", "Syr Gwyn, Hero of Ashvale"); + + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPowerToughness(playerA, "Syr Gwyn, Hero of Ashvale", 7, 7); + + } + + @Test + public void equipKnightTestInstantSpeed() { + // Equipped creature gets +2/+2 and has trample and lifelink. + addCard(Zone.BATTLEFIELD, playerA, "Behemoth Sledge"); // Artifact - Equipment {1}{G}{W} + + // You may activate equip abilities any time you could cast an instant. + addCard(Zone.BATTLEFIELD, playerA, "Leonin Shikari", 2); // Creature 2/2 + + // Vigilance, menace + // Whenever an equipped creature you control attacks, you draw a card and you lose 1 life. + // Equipment you control have equip Knight {0}. + addCard(Zone.BATTLEFIELD, playerA, "Syr Gwyn, Hero of Ashvale"); // Legendary Creature {3}{R}{W}{B} 5/5 Human Knight + + activateAbility(1, PhaseStep.DECLARE_ATTACKERS, playerA, "Equip Knight", "Syr Gwyn, Hero of Ashvale"); + + + setStopAt(1, PhaseStep.END_COMBAT); + execute(); + + assertPowerToughness(playerA, "Syr Gwyn, Hero of Ashvale", 7, 7); + + } +} diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/ActivateAbilitiesAnyTimeYouCouldCastInstantEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/ActivateAbilitiesAnyTimeYouCouldCastInstantEffect.java index d15adb8048..5a19776e0d 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/ActivateAbilitiesAnyTimeYouCouldCastInstantEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/ActivateAbilitiesAnyTimeYouCouldCastInstantEffect.java @@ -19,7 +19,7 @@ import mage.game.Game; */ public class ActivateAbilitiesAnyTimeYouCouldCastInstantEffect extends AsThoughEffectImpl { - private Class activatedAbility; + private final Class activatedAbility; public ActivateAbilitiesAnyTimeYouCouldCastInstantEffect(Class activatedAbility, String activatedAbilityName) { super(AsThoughEffectType.ACTIVATE_AS_INSTANT, Duration.EndOfGame, Outcome.Benefit); @@ -45,7 +45,7 @@ public class ActivateAbilitiesAnyTimeYouCouldCastInstantEffect extends AsThoughE @Override public boolean applies(UUID objectId, Ability affectedAbility, Ability source, Game game, UUID playerId) { return affectedAbility.isControlledBy(source.getControllerId()) - && activatedAbility.isInstance(affectedAbility); + && activatedAbility.isAssignableFrom(affectedAbility.getClass()); } @Override diff --git a/Mage/src/main/java/mage/abilities/keyword/EquipAbility.java b/Mage/src/main/java/mage/abilities/keyword/EquipAbility.java index ccb08800bb..aad2d3ae72 100644 --- a/Mage/src/main/java/mage/abilities/keyword/EquipAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/EquipAbility.java @@ -14,7 +14,7 @@ import mage.target.common.TargetControlledCreaturePermanent; * @author BetaSteward_at_googlemail.com */ public class EquipAbility extends ActivatedAbilityImpl { - + public EquipAbility(int cost) { this(Outcome.AddAbility, new GenericManaCost(cost)); } @@ -26,7 +26,7 @@ public class EquipAbility extends ActivatedAbilityImpl { public EquipAbility(Outcome outcome, Cost cost, Target target) { super(Zone.BATTLEFIELD, new EquipEffect(outcome), cost); this.addTarget(target); - this.timing = TimingRule.SORCERY; + this.timing = TimingRule.SORCERY; } public EquipAbility(final EquipAbility ability) { @@ -40,7 +40,13 @@ public class EquipAbility extends ActivatedAbilityImpl { @Override public String getRule() { - return "Equip " + costs.getText() + manaCosts.getText() + " (" + manaCosts.getText() + ": Attach to target creature you control. Equip only as a sorcery.)"; + String targetText = getTargets().get(0) != null ? getTargets().get(0).getFilter().getMessage() : "creature"; + + return "Equip " + + (targetText.equals("creature you control") ? "" : targetText + " ") + + costs.getText() + + manaCosts.getText() + + " (" + manaCosts.getText() + ": Attach to target " + targetText + " you control. Equip only as a sorcery. This card enters the battlefield unattached and stays on the battlefield if the creature leaves.)"; } } diff --git a/Mage/src/main/java/mage/abilities/keyword/EquipFilterAbility.java b/Mage/src/main/java/mage/abilities/keyword/EquipFilterAbility.java deleted file mode 100644 index 9941068604..0000000000 --- a/Mage/src/main/java/mage/abilities/keyword/EquipFilterAbility.java +++ /dev/null @@ -1,40 +0,0 @@ -package mage.abilities.keyword; - -import mage.abilities.ActivatedAbilityImpl; -import mage.abilities.costs.Cost; -import mage.abilities.effects.common.AttachEffect; -import mage.constants.Outcome; -import mage.constants.TimingRule; -import mage.constants.Zone; -import mage.filter.common.FilterControlledCreaturePermanent; -import mage.target.common.TargetControlledCreaturePermanent; - -/** - * @author TheElk801 - */ -public class EquipFilterAbility extends ActivatedAbilityImpl { - - private final FilterControlledCreaturePermanent filter; - - public EquipFilterAbility(FilterControlledCreaturePermanent filter, Cost cost) { - super(Zone.BATTLEFIELD, new AttachEffect(Outcome.AddAbility, "Equip"), cost); - this.addTarget(new TargetControlledCreaturePermanent(filter)); - this.filter = filter; - this.timing = TimingRule.SORCERY; - } - - private EquipFilterAbility(final EquipFilterAbility ability) { - super(ability); - this.filter = ability.filter; - } - - @Override - public EquipFilterAbility copy() { - return new EquipFilterAbility(this); - } - - @Override - public String getRule() { - return "Equip " + filter.getMessage() + costs.getText() + manaCosts.getText(); - } -}