diff --git a/Mage.Sets/src/mage/cards/e/EarwigSquad.java b/Mage.Sets/src/mage/cards/e/EarwigSquad.java index 006d6bf757..d132407b99 100644 --- a/Mage.Sets/src/mage/cards/e/EarwigSquad.java +++ b/Mage.Sets/src/mage/cards/e/EarwigSquad.java @@ -1,21 +1,19 @@ - package mage.cards.e; -import java.util.List; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.condition.common.ProwlCondition; +import mage.abilities.condition.common.ProwlCostWasPaidCondition; import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; +import mage.abilities.hint.common.ProwlCostWasPaidHint; import mage.abilities.keyword.ProwlAbility; 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.constants.Zone; import mage.filter.FilterCard; import mage.game.Game; @@ -23,14 +21,16 @@ import mage.players.Player; import mage.target.common.TargetCardInLibrary; import mage.target.common.TargetOpponent; +import java.util.List; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class EarwigSquad extends CardImpl { public EarwigSquad(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{B}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{B}"); this.subtype.add(SubType.GOBLIN); this.subtype.add(SubType.ROGUE); @@ -39,11 +39,13 @@ public final class EarwigSquad extends CardImpl { // Prowl {2}{B} this.addAbility(new ProwlAbility(this, "{2}{B}")); + // When Earwig Squad enters the battlefield, if its prowl cost was paid, search target opponent's library for three cards and exile them. Then that player shuffles their library. EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new EarwigSquadEffect(), false); ability.addTarget(new TargetOpponent()); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, ProwlCondition.instance, - "When {this} enters the battlefield, if its prowl cost was paid, search target opponent's library for three cards and exile them. Then that player shuffles their library.")); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, ProwlCostWasPaidCondition.instance, + "When {this} enters the battlefield, if its prowl cost was paid, search target opponent's library for three cards and exile them. Then that player shuffles their library.") + .addHint(ProwlCostWasPaidHint.instance)); } @@ -78,7 +80,7 @@ class EarwigSquadEffect extends OneShotEffect { Player opponent = game.getPlayer(source.getFirstTarget()); Player player = game.getPlayer(source.getControllerId()); if (player != null && opponent != null) { - TargetCardInLibrary target = new TargetCardInLibrary(0, 3, new FilterCard("cards from opponents library to exile")); + TargetCardInLibrary target = new TargetCardInLibrary(0, 3, new FilterCard("cards from opponents library to exile")); if (player.searchLibrary(target, source, game, opponent.getId())) { List targets = target.getTargets(); for (UUID targetId : targets) { diff --git a/Mage.Sets/src/mage/cards/l/LatchkeyFaerie.java b/Mage.Sets/src/mage/cards/l/LatchkeyFaerie.java index ca664a65f4..aab8921435 100644 --- a/Mage.Sets/src/mage/cards/l/LatchkeyFaerie.java +++ b/Mage.Sets/src/mage/cards/l/LatchkeyFaerie.java @@ -1,12 +1,11 @@ - package mage.cards.l; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.condition.common.ProwlCondition; +import mage.abilities.condition.common.ProwlCostWasPaidCondition; import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.hint.common.ProwlCostWasPaidHint; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.ProwlAbility; import mage.cards.CardImpl; @@ -14,14 +13,15 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class LatchkeyFaerie extends CardImpl { public LatchkeyFaerie(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}"); this.subtype.add(SubType.FAERIE); this.subtype.add(SubType.ROGUE); @@ -36,8 +36,9 @@ public final class LatchkeyFaerie extends CardImpl { // When Latchkey Faerie enters the battlefield, if its prowl cost was paid, draw a card. EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1), false); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, ProwlCondition.instance, - "When {this} enters the battlefield, if its prowl cost was paid, draw a card.")); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, ProwlCostWasPaidCondition.instance, + "When {this} enters the battlefield, if its prowl cost was paid, draw a card.") + .addHint(ProwlCostWasPaidHint.instance)); } diff --git a/Mage.Sets/src/mage/cards/m/MorselTheft.java b/Mage.Sets/src/mage/cards/m/MorselTheft.java index 4573e94d4a..d56a4e25dc 100644 --- a/Mage.Sets/src/mage/cards/m/MorselTheft.java +++ b/Mage.Sets/src/mage/cards/m/MorselTheft.java @@ -1,13 +1,12 @@ - package mage.cards.m; -import java.util.UUID; -import mage.abilities.condition.common.ProwlCondition; +import mage.abilities.condition.common.ProwlCostWasPaidCondition; import mage.abilities.decorator.ConditionalOneShotEffect; import mage.abilities.effects.Effect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.LoseLifeTargetEffect; +import mage.abilities.hint.common.ProwlCostWasPaidHint; import mage.abilities.keyword.ProwlAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -15,14 +14,15 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.target.TargetPlayer; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class MorselTheft extends CardImpl { public MorselTheft(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.TRIBAL,CardType.SORCERY},"{2}{B}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.TRIBAL, CardType.SORCERY}, "{2}{B}{B}"); this.subtype.add(SubType.ROGUE); // Prowl {1}{B} @@ -34,7 +34,8 @@ public final class MorselTheft extends CardImpl { effect.setText("and you gain 3 life"); getSpellAbility().addEffect(effect); getSpellAbility().addTarget(new TargetPlayer()); - getSpellAbility().addEffect(new ConditionalOneShotEffect(new DrawCardSourceControllerEffect(1), ProwlCondition.instance)); + getSpellAbility().addEffect(new ConditionalOneShotEffect(new DrawCardSourceControllerEffect(1), ProwlCostWasPaidCondition.instance)); + getSpellAbility().addHint(ProwlCostWasPaidHint.instance); } diff --git a/Mage.Sets/src/mage/cards/n/NotoriousThrong.java b/Mage.Sets/src/mage/cards/n/NotoriousThrong.java index cb553b3b77..a7fa06a59b 100644 --- a/Mage.Sets/src/mage/cards/n/NotoriousThrong.java +++ b/Mage.Sets/src/mage/cards/n/NotoriousThrong.java @@ -1,44 +1,47 @@ - package mage.cards.n; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.condition.common.ProwlCondition; +import mage.abilities.condition.common.ProwlCostWasPaidCondition; import mage.abilities.decorator.ConditionalOneShotEffect; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.turn.AddExtraTurnControllerEffect; +import mage.abilities.hint.common.ProwlCostWasPaidHint; import mage.abilities.keyword.ProwlAbility; 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.game.Game; import mage.game.permanent.token.FaerieRogueToken; import mage.players.Player; import mage.watchers.common.AmountOfDamageAPlayerReceivedThisTurnWatcher; +import java.util.UUID; + /** - * * @author LoneFox */ public final class NotoriousThrong extends CardImpl { public NotoriousThrong(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.TRIBAL,CardType.SORCERY},"{3}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.TRIBAL, CardType.SORCERY}, "{3}{U}"); this.subtype.add(SubType.ROGUE); // Prowl {5}{U} this.addAbility(new ProwlAbility(this, "{5}{U}")); + // create X 1/1 black Faerie Rogue creature tokens with flying, where X is the damage dealt to your opponents this turn. this.getSpellAbility().addEffect(new NotoriousThrongEffect()); this.getSpellAbility().addWatcher(new AmountOfDamageAPlayerReceivedThisTurnWatcher()); + // If Notorious Throng's prowl cost was paid, take an extra turn after this one. - Effect effect = new ConditionalOneShotEffect(new AddExtraTurnControllerEffect(), ProwlCondition.instance); + Effect effect = new ConditionalOneShotEffect(new AddExtraTurnControllerEffect(), ProwlCostWasPaidCondition.instance); effect.setText("If {this}'s prowl cost was paid, take an extra turn after this one."); this.getSpellAbility().addEffect(effect); + this.getSpellAbility().addHint(ProwlCostWasPaidHint.instance); } public NotoriousThrong(final NotoriousThrong card) { @@ -71,12 +74,12 @@ class NotoriousThrongEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); AmountOfDamageAPlayerReceivedThisTurnWatcher watcher = game.getState().getWatcher(AmountOfDamageAPlayerReceivedThisTurnWatcher.class); - if(controller != null && watcher != null) { + if (controller != null && watcher != null) { int numTokens = 0; - for(UUID opponentId: game.getOpponents(controller.getId())) { + for (UUID opponentId : game.getOpponents(controller.getId())) { numTokens += watcher.getAmountOfDamageReceivedThisTurn(opponentId); } - if(numTokens > 0) { + if (numTokens > 0) { new CreateTokenEffect(new FaerieRogueToken(), numTokens).apply(game, source); } return true; diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ProwlTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ProwlTest.java index 894073777c..38db073ae3 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ProwlTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ProwlTest.java @@ -1,75 +1,77 @@ -/* - * 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.abilities.keywords; import mage.constants.PhaseStep; import mage.constants.Zone; -import org.junit.Ignore; import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBase; /** - * * @author escplan9 (Derek Monturo - dmontur1 at gmail dot com) */ public class ProwlTest extends CardTestPlayerBase { - - @Ignore // have not figured out how to have the test API cast a card using Prowl yet + @Test - public void testBasicProwlCasting() { + public void test_ProwlNormal() { // Auntie's Snitch {2}{B} Creature — Goblin Rogue (3/1) // Auntie's Snitch can't block. // Prowl {1}{B} (You may cast this for its prowl cost if you dealt combat damage to a player this turn with a Goblin or Rogue.) // Whenever a Goblin or Rogue you control deals combat damage to a player, if Auntie's Snitch is in your graveyard, you may return Auntie's Snitch to your hand. addCard(Zone.HAND, playerA, "Auntie's Snitch"); - + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2); + // // {1}{R} Creature — Goblin Warrior 1/1 // Red creatures you control have first strike. - addCard(Zone.BATTLEFIELD, playerA, "Bloodmark Mentor"); - addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2); - + addCard(Zone.BATTLEFIELD, playerA, "Bloodmark Mentor"); + + // prepare prowl condition + checkPlayableAbility("can't", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Auntie's Snitch", false); attack(1, playerA, "Bloodmark Mentor"); - - castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Auntie's Snitch using prowl"); + + checkPlayableAbility("must play", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Cast Auntie's Snitch", true); + castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Auntie's Snitch"); setChoice(playerA, "Yes"); // choosing to pay prowl cost + + setStrictChooseMode(true); setStopAt(1, PhaseStep.END_TURN); execute(); - + assertAllCommandsUsed(); + assertLife(playerB, 19); assertPermanentCount(playerA, "Bloodmark Mentor", 1); assertPermanentCount(playerA, "Auntie's Snitch", 1); } - + /* * Reported bug: Prowl is not taking into consideration other cost reducing effects. For instance Goblin Warchief * does not reduce the Prowl cost of other Goblin cards with Prowl ability. - */ - @Ignore // have not figured out how to have the test API cast a card using Prowl yet + */ @Test - public void testProwlWithCostDiscount() { - + public void test_ProwlWithCostReduce() { // Auntie's Snitch {2}{B} Creature — Goblin Rogue (3/1) // Auntie's Snitch can't block. // Prowl {1}{B} (You may cast this for its prowl cost if you dealt combat damage to a player this turn with a Goblin or Rogue.) // Whenever a Goblin or Rogue you control deals combat damage to a player, if Auntie's Snitch is in your graveyard, you may return Auntie's Snitch to your hand. - addCard(Zone.HAND, playerA, "Auntie's Snitch"); - + addCard(Zone.HAND, playerA, "Auntie's Snitch"); + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1); + // Goblin Warchief {1}{R}{R} Creature — Goblin Warrior (2/2) // Goblin spells you cast cost 1 less to cast. // Goblin creatures you control have haste. addCard(Zone.BATTLEFIELD, playerA, "Goblin Warchief"); - addCard(Zone.BATTLEFIELD, playerA, "Swamp"); - + + // prepare prowl condition + checkPlayableAbility("can't", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Auntie's Snitch", false); attack(1, playerA, "Goblin Warchief"); - - castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Auntie's Snitch using prowl"); // should only cost {B} with Warchief discount + + checkPlayableAbility("must play", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Cast Auntie's Snitch", true); + castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Auntie's Snitch"); // should only cost {B} with Warchief discount setChoice(playerA, "Yes"); // choosing to pay prowl cost + + setStrictChooseMode(true); setStopAt(1, PhaseStep.END_TURN); execute(); - + assertAllCommandsUsed(); + assertLife(playerB, 18); assertPermanentCount(playerA, "Goblin Warchief", 1); assertPermanentCount(playerA, "Auntie's Snitch", 1); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/asthough/PlayFromNonHandZoneTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/asthough/PlayFromNonHandZoneTest.java index 1e145efc24..1de3041893 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/asthough/PlayFromNonHandZoneTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/asthough/PlayFromNonHandZoneTest.java @@ -129,10 +129,15 @@ public class PlayFromNonHandZoneTest extends CardTestPlayerBase { attack(2, playerB, "Narset, Enlightened Master"); + checkPlayableAbility("must play", 2, PhaseStep.POSTCOMBAT_MAIN, playerB, "Cast Cathartic Reunion", true); castSpell(2, PhaseStep.POSTCOMBAT_MAIN, playerB, "Cathartic Reunion"); setChoice(playerB, "Swamp^Forest"); + + setStrictChooseMode(true); setStopAt(2, PhaseStep.END_TURN); execute(); + assertAllCommandsUsed(); + assertHandCount(playerB, 3); assertGraveyardCount(playerB, "Forest", 1); diff --git a/Mage/src/main/java/mage/abilities/condition/common/ProwlCondition.java b/Mage/src/main/java/mage/abilities/condition/common/ProwlCondition.java index 638dbbf33b..053e17e777 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/ProwlCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/ProwlCondition.java @@ -1,16 +1,16 @@ - package mage.abilities.condition.common; import mage.abilities.Ability; import mage.abilities.condition.Condition; -import mage.abilities.keyword.ProwlAbility; import mage.cards.Card; +import mage.constants.SubType; import mage.game.Game; +import mage.watchers.common.ProwlWatcher; /** - * Checks if a the spell was cast with the alternate prowl costs + * Is it able to activate prowl cost (damage was made) * - * @author LevelX2 + * @author JayDi85 */ public enum ProwlCondition implements Condition { @@ -18,22 +18,15 @@ public enum ProwlCondition implements Condition { @Override public boolean apply(Game game, Ability source) { + ProwlWatcher watcher = game.getState().getWatcher(ProwlWatcher.class); Card card = game.getCard(source.getSourceId()); - if (card != null) { - for (Ability ability : card.getAbilities()) { - if (ability instanceof ProwlAbility) { - if (((ProwlAbility) ability).isActivated(source, game)) { - return true; - } + if (watcher != null && card != null) { + for (SubType subtype : card.getSubtype(game)) { + if (watcher.hasSubtypeMadeCombatDamage(source.getControllerId(), subtype)) { + return true; } } } return false; } - - @Override - public String toString() { - return "{source}'s prowl cost was paid"; - } - } diff --git a/Mage/src/main/java/mage/abilities/condition/common/ProwlCostWasPaidCondition.java b/Mage/src/main/java/mage/abilities/condition/common/ProwlCostWasPaidCondition.java new file mode 100644 index 0000000000..5b6879fcbf --- /dev/null +++ b/Mage/src/main/java/mage/abilities/condition/common/ProwlCostWasPaidCondition.java @@ -0,0 +1,38 @@ +package mage.abilities.condition.common; + +import mage.abilities.Ability; +import mage.abilities.condition.Condition; +import mage.abilities.keyword.ProwlAbility; +import mage.cards.Card; +import mage.game.Game; + +/** + * Checks if a the spell was cast with the alternate prowl costs + * + * @author LevelX2 + */ +public enum ProwlCostWasPaidCondition implements Condition { + + instance; + + @Override + public boolean apply(Game game, Ability source) { + Card card = game.getCard(source.getSourceId()); + if (card != null) { + for (Ability ability : card.getAbilities()) { + if (ability instanceof ProwlAbility) { + if (((ProwlAbility) ability).isActivated(source, game)) { + return true; + } + } + } + } + return false; + } + + @Override + public String toString() { + return "{source}'s prowl cost was paid"; + } + +} diff --git a/Mage/src/main/java/mage/abilities/hint/common/ProwlCostWasPaidHint.java b/Mage/src/main/java/mage/abilities/hint/common/ProwlCostWasPaidHint.java new file mode 100644 index 0000000000..d1e3ae8d07 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/hint/common/ProwlCostWasPaidHint.java @@ -0,0 +1,26 @@ +package mage.abilities.hint.common; + +import mage.abilities.Ability; +import mage.abilities.condition.common.ProwlCostWasPaidCondition; +import mage.abilities.hint.ConditionHint; +import mage.abilities.hint.Hint; +import mage.game.Game; + +/** + * @author JayDi85 + */ +public enum ProwlCostWasPaidHint implements Hint { + + instance; + private static final ConditionHint hint = new ConditionHint(ProwlCostWasPaidCondition.instance, "Prowl cost was paid"); + + @Override + public String getText(Game game, Ability ability) { + return hint.getText(game, ability); + } + + @Override + public Hint copy() { + return instance; + } +} diff --git a/Mage/src/main/java/mage/abilities/hint/common/ProwlHint.java b/Mage/src/main/java/mage/abilities/hint/common/ProwlHint.java new file mode 100644 index 0000000000..27e78ad13b --- /dev/null +++ b/Mage/src/main/java/mage/abilities/hint/common/ProwlHint.java @@ -0,0 +1,26 @@ +package mage.abilities.hint.common; + +import mage.abilities.Ability; +import mage.abilities.condition.common.ProwlCondition; +import mage.abilities.hint.ConditionHint; +import mage.abilities.hint.Hint; +import mage.game.Game; + +/** + * @author JayDi85 + */ +public enum ProwlHint implements Hint { + + instance; + private static final ConditionHint hint = new ConditionHint(ProwlCondition.instance, "Prowl cost can be activated"); + + @Override + public String getText(Game game, Ability ability) { + return hint.getText(game, ability); + } + + @Override + public Hint copy() { + return instance; + } +} diff --git a/Mage/src/main/java/mage/abilities/keyword/ProwlAbility.java b/Mage/src/main/java/mage/abilities/keyword/ProwlAbility.java index 3e3ff1ca3c..df8d198945 100644 --- a/Mage/src/main/java/mage/abilities/keyword/ProwlAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/ProwlAbility.java @@ -1,30 +1,26 @@ - package mage.abilities.keyword; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; import mage.abilities.Ability; import mage.abilities.SpellAbility; import mage.abilities.StaticAbility; -import mage.abilities.costs.AlternativeCost2; -import mage.abilities.costs.AlternativeCost2Impl; -import mage.abilities.costs.AlternativeSourceCosts; -import mage.abilities.costs.Cost; -import mage.abilities.costs.Costs; -import mage.abilities.costs.CostsImpl; +import mage.abilities.condition.common.ProwlCondition; +import mage.abilities.costs.*; import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.hint.common.ProwlHint; import mage.cards.Card; import mage.constants.Outcome; -import mage.constants.SubType; import mage.constants.Zone; import mage.game.Game; import mage.players.Player; import mage.watchers.common.ProwlWatcher; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; + /** * 702.74. Prowl # - * + *

* 702.74a Prowl is a static ability that functions on the stack. "Prowl [cost]" * means "You may pay [cost] rather than pay this spell's mana cost if a player * was dealt combat damage this turn by a source that, at the time it dealt that @@ -41,13 +37,13 @@ public class ProwlAbility extends StaticAbility implements AlternativeSourceCost private String reminderText; public ProwlAbility(Card card, String manaString) { - super(Zone.STACK, null); - setRuleAtTheTop(true); - name = PROWL_KEYWORD; - setReminderText(card); + super(Zone.ALL, null); + this.setRuleAtTheTop(true); + this.name = PROWL_KEYWORD; + this.setReminderText(card); this.addProwlCost(manaString); - addWatcher(new ProwlWatcher()); - + this.addWatcher(new ProwlWatcher()); + this.addHint(ProwlHint.instance); } public ProwlAbility(final ProwlAbility ability) { @@ -85,26 +81,17 @@ public class ProwlAbility extends StaticAbility implements AlternativeSourceCost @Override public boolean isAvailable(Ability source, Game game) { - return true; + return ProwlCondition.instance.apply(game, source); } @Override public boolean askToActivateAlternativeCosts(Ability ability, Game game) { if (ability instanceof SpellAbility) { Player player = game.getPlayer(controllerId); - ProwlWatcher prowlWatcher = game.getState().getWatcher(ProwlWatcher.class); - Card card = game.getCard(ability.getSourceId()); - if (player == null || prowlWatcher == null || card == null) { - throw new IllegalArgumentException("Params can't be null"); + if (player == null) { + return false; } - boolean canProwl = false; - for (SubType subtype : card.getSubtype(game)) { - if (prowlWatcher.hasSubtypeMadeCombatDamage(ability.getControllerId(), subtype)) { - canProwl = true; - break; - } - } - if (canProwl) { + if (ProwlCondition.instance.apply(game, ability)) { this.resetProwl(); for (AlternativeCost2 prowlCost : prowlCosts) { if (prowlCost.canPay(ability, sourceId, controllerId, game) @@ -112,7 +99,7 @@ public class ProwlAbility extends StaticAbility implements AlternativeSourceCost prowlCost.activate(); ability.getManaCostsToPay().clear(); ability.getCosts().clear(); - for (Iterator it = ((Costs) prowlCost).iterator(); it.hasNext();) { + for (Iterator it = ((Costs) prowlCost).iterator(); it.hasNext(); ) { Cost cost = (Cost) it.next(); if (cost instanceof ManaCostsImpl) { ability.getManaCostsToPay().add((ManaCostsImpl) cost.copy()); @@ -162,7 +149,7 @@ public class ProwlAbility extends StaticAbility implements AlternativeSourceCost } private void setReminderText(Card card) { - reminderText = + reminderText = "(You may cast this for its prowl cost if you dealt combat damage to a player this turn with a creature that shared a creature type with {this}"; } @@ -174,4 +161,4 @@ public class ProwlAbility extends StaticAbility implements AlternativeSourceCost } return alterCosts; } -} +} \ No newline at end of file diff --git a/Mage/src/main/java/mage/players/PlayerImpl.java b/Mage/src/main/java/mage/players/PlayerImpl.java index e04b3e408f..697c201fe5 100644 --- a/Mage/src/main/java/mage/players/PlayerImpl.java +++ b/Mage/src/main/java/mage/players/PlayerImpl.java @@ -3046,6 +3046,7 @@ public abstract class PlayerImpl implements Player, Serializable { protected boolean canPlayCardByAlternateCost(Card sourceObject, ManaOptions availableMana, Ability ability, Game game) { if (sourceObject != null && !(sourceObject instanceof Permanent)) { + Ability copyAbility; // for alternative cost and reduce tries for (Ability alternateSourceCostsAbility : sourceObject.getAbilities()) { // if cast for noMana no Alternative costs are allowed if (alternateSourceCostsAbility instanceof AlternativeSourceCosts) { @@ -3064,7 +3065,15 @@ public abstract class PlayerImpl implements Player, Serializable { if (availableMana == null) { return true; } - for (Mana mana : manaCosts.getOptions()) { + + // alternative cost reduce + copyAbility = ability.copy(); + copyAbility.getManaCostsToPay().clear(); + copyAbility.getManaCostsToPay().addAll(manaCosts.copy()); + sourceObject.adjustCosts(copyAbility, game); + game.getContinuousEffects().costModification(copyAbility, game); + + for (Mana mana : copyAbility.getManaCostsToPay().getOptions()) { for (Mana avail : availableMana) { if (mana.enough(avail)) { return true; @@ -3092,7 +3101,18 @@ public abstract class PlayerImpl implements Player, Serializable { if (manaCosts.isEmpty()) { return true; } else { - for (Mana mana : manaCosts.getOptions()) { + if (availableMana == null) { + return true; + } + + // alternative cost reduce + copyAbility = ability.copy(); + copyAbility.getManaCostsToPay().clear(); + copyAbility.getManaCostsToPay().addAll(manaCosts.copy()); + sourceObject.adjustCosts(copyAbility, game); + game.getContinuousEffects().costModification(copyAbility, game); + + for (Mana mana : copyAbility.getManaCostsToPay().getOptions()) { for (Mana avail : availableMana) { if (mana.enough(avail)) { return true;