diff --git a/Mage.Sets/src/mage/cards/c/ChandraAcolyteOfFlame.java b/Mage.Sets/src/mage/cards/c/ChandraAcolyteOfFlame.java index ff193396c61..96c88da3de7 100644 --- a/Mage.Sets/src/mage/cards/c/ChandraAcolyteOfFlame.java +++ b/Mage.Sets/src/mage/cards/c/ChandraAcolyteOfFlame.java @@ -8,7 +8,7 @@ import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.InfoEffect; -import mage.abilities.effects.common.MayCastTargetThenExileEffect; +import mage.abilities.effects.common.MayCastTargetCardEffect; import mage.abilities.effects.common.SacrificeTargetEffect; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; import mage.abilities.effects.common.counter.AddCountersAllEffect; @@ -61,7 +61,7 @@ public final class ChandraAcolyteOfFlame extends CardImpl { this.addAbility(new LoyaltyAbility(new ChandraAcolyteOfFlameEffect(), 0)); // -2: You may cast target instant or sorcery card with converted mana cost 3 or less from your graveyard. If that card would be put into your graveyard this turn, exile it instead. - Ability ability = new LoyaltyAbility(new MayCastTargetThenExileEffect(false), -2); + Ability ability = new LoyaltyAbility(new MayCastTargetCardEffect(true), -2); ability.addTarget(new TargetCardInYourGraveyard(filter2)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/c/ChandraFlamesCatalyst.java b/Mage.Sets/src/mage/cards/c/ChandraFlamesCatalyst.java index 187f7aaa400..f747637bca2 100644 --- a/Mage.Sets/src/mage/cards/c/ChandraFlamesCatalyst.java +++ b/Mage.Sets/src/mage/cards/c/ChandraFlamesCatalyst.java @@ -6,7 +6,7 @@ import mage.abilities.LoyaltyAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.common.DamagePlayersEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; -import mage.abilities.effects.common.MayCastTargetThenExileEffect; +import mage.abilities.effects.common.MayCastTargetCardEffect; import mage.abilities.effects.common.continuous.CastFromHandWithoutPayingManaCostEffect; import mage.abilities.effects.common.discard.DiscardHandControllerEffect; import mage.cards.CardImpl; @@ -33,7 +33,7 @@ public final class ChandraFlamesCatalyst extends CardImpl { public ChandraFlamesCatalyst(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{4}{R}{R}"); - + this.supertype.add(SuperType.LEGENDARY); this.subtype.add(SubType.CHANDRA); this.setStartingLoyalty(5); @@ -42,7 +42,7 @@ public final class ChandraFlamesCatalyst extends CardImpl { this.addAbility(new LoyaltyAbility(new DamagePlayersEffect(3, TargetController.OPPONENT), 1)); // −2: You may cast target red instant or sorcery card from your graveyard. If that spell would be put into your graveyard this turn, exile it instead. - Ability ability = new LoyaltyAbility(new MayCastTargetThenExileEffect(false), -2); + Ability ability = new LoyaltyAbility(new MayCastTargetCardEffect(true), -2); ability.addTarget(new TargetCardInYourGraveyard(filter)); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/d/DeluxeDragster.java b/Mage.Sets/src/mage/cards/d/DeluxeDragster.java index c9ec81a50ab..fc787d555a3 100644 --- a/Mage.Sets/src/mage/cards/d/DeluxeDragster.java +++ b/Mage.Sets/src/mage/cards/d/DeluxeDragster.java @@ -3,7 +3,7 @@ package mage.cards.d; import mage.MageInt; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.SimpleEvasionAbility; -import mage.abilities.effects.common.MayCastTargetThenExileEffect; +import mage.abilities.effects.common.MayCastTargetCardEffect; import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesSourceEffect; import mage.abilities.effects.common.replacement.ThatSpellGraveyardExileReplacementEffect; import mage.abilities.keyword.CrewAbility; @@ -65,7 +65,7 @@ public final class DeluxeDragster extends CardImpl { class DeluxeDragsterTriggeredAbility extends TriggeredAbilityImpl { DeluxeDragsterTriggeredAbility() { - super(Zone.BATTLEFIELD, new MayCastTargetThenExileEffect(true) + super(Zone.BATTLEFIELD, new MayCastTargetCardEffect(CastManaAdjustment.WITHOUT_PAYING_MANA_COST, true) .setText("you may cast target instant or sorcery card from " + "that player's graveyard without paying its mana cost. " + ThatSpellGraveyardExileReplacementEffect.RULE_A), false); diff --git a/Mage.Sets/src/mage/cards/d/DiluvianPrimordial.java b/Mage.Sets/src/mage/cards/d/DiluvianPrimordial.java index 50c8139adc6..61f8053ed07 100644 --- a/Mage.Sets/src/mage/cards/d/DiluvianPrimordial.java +++ b/Mage.Sets/src/mage/cards/d/DiluvianPrimordial.java @@ -4,12 +4,13 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.MayCastTargetThenExileEffect; +import mage.abilities.effects.common.MayCastTargetCardEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.CastManaAdjustment; import mage.constants.Outcome; import mage.constants.SubType; import mage.filter.FilterCard; @@ -106,7 +107,8 @@ class DiluvianPrimordialEffect extends OneShotEffect { if (target instanceof TargetCardInOpponentsGraveyard) { Card targetCard = game.getCard(target.getFirstTarget()); if (targetCard != null) { - new MayCastTargetThenExileEffect(true).setTargetPointer(new FixedTarget(targetCard, game)).apply(game, source); + new MayCastTargetCardEffect(CastManaAdjustment.WITHOUT_PAYING_MANA_COST, true) + .setTargetPointer(new FixedTarget(targetCard, game)).apply(game, source); } } } diff --git a/Mage.Sets/src/mage/cards/d/DreadhordeArcanist.java b/Mage.Sets/src/mage/cards/d/DreadhordeArcanist.java index 417a5628ae6..9ba2da0ef49 100644 --- a/Mage.Sets/src/mage/cards/d/DreadhordeArcanist.java +++ b/Mage.Sets/src/mage/cards/d/DreadhordeArcanist.java @@ -3,11 +3,12 @@ package mage.cards.d; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; -import mage.abilities.effects.common.MayCastTargetThenExileEffect; +import mage.abilities.effects.common.MayCastTargetCardEffect; import mage.abilities.keyword.TrampleAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.CastManaAdjustment; import mage.constants.SubType; import mage.filter.FilterCard; import mage.filter.common.FilterInstantOrSorceryCard; @@ -42,7 +43,7 @@ public final class DreadhordeArcanist extends CardImpl { // Whenever Dreadhorde Arcanist attacks, you may cast target instant or sorcery card with converted mana cost less than or equal to Dreadhorde Arcanist's power from your graveyard without paying its mana cost. // If that card would be put into your graveyard this turn, exile it instead. - Ability ability = new AttacksTriggeredAbility(new MayCastTargetThenExileEffect(true), false); + Ability ability = new AttacksTriggeredAbility(new MayCastTargetCardEffect(CastManaAdjustment.WITHOUT_PAYING_MANA_COST, true), false); ability.addTarget(new TargetCardInYourGraveyard(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/e/EfreetFlamepainter.java b/Mage.Sets/src/mage/cards/e/EfreetFlamepainter.java index cd08bc3c776..429a6e36cf8 100644 --- a/Mage.Sets/src/mage/cards/e/EfreetFlamepainter.java +++ b/Mage.Sets/src/mage/cards/e/EfreetFlamepainter.java @@ -3,11 +3,12 @@ package mage.cards.e; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; -import mage.abilities.effects.common.MayCastTargetThenExileEffect; +import mage.abilities.effects.common.MayCastTargetCardEffect; import mage.abilities.keyword.DoubleStrikeAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.CastManaAdjustment; import mage.constants.SubType; import mage.filter.StaticFilters; import mage.target.common.TargetCardInYourGraveyard; @@ -21,7 +22,7 @@ public final class EfreetFlamepainter extends CardImpl { public EfreetFlamepainter(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}"); - + this.subtype.add(SubType.EFREET); this.subtype.add(SubType.SHAMAN); this.power = new MageInt(1); @@ -31,7 +32,7 @@ public final class EfreetFlamepainter extends CardImpl { this.addAbility(DoubleStrikeAbility.getInstance()); // Whenever Efreet Flamepainter deals combat damage to a player, you may cast target instant or sorcery card from your graveyard without paying its mana cost. If that spell would be put into your graveyard, exile it instead. - Ability ability = new DealsCombatDamageToAPlayerTriggeredAbility(new MayCastTargetThenExileEffect(true), false); + Ability ability = new DealsCombatDamageToAPlayerTriggeredAbility(new MayCastTargetCardEffect(CastManaAdjustment.WITHOUT_PAYING_MANA_COST, true), false); ability.addTarget(new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY_FROM_YOUR_GRAVEYARD)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/f/FinaleOfPromise.java b/Mage.Sets/src/mage/cards/f/FinaleOfPromise.java index e14d072a3cd..9ee7b94bf0f 100644 --- a/Mage.Sets/src/mage/cards/f/FinaleOfPromise.java +++ b/Mage.Sets/src/mage/cards/f/FinaleOfPromise.java @@ -3,11 +3,12 @@ package mage.cards.f; import mage.abilities.Ability; import mage.abilities.dynamicvalue.common.ManacostVariableValue; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.MayCastTargetThenExileEffect; +import mage.abilities.effects.common.MayCastTargetCardEffect; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.CastManaAdjustment; import mage.constants.ComparisonType; import mage.constants.Outcome; import mage.filter.FilterCard; @@ -133,7 +134,8 @@ class FinaleOfPromiseEffect extends OneShotEffect { for (UUID id : cardsToCast) { Card card = game.getCard(id); if (card != null) { - new MayCastTargetThenExileEffect(true).setTargetPointer(new FixedTarget(card, game)).apply(game, source); + new MayCastTargetCardEffect(CastManaAdjustment.WITHOUT_PAYING_MANA_COST, true) + .setTargetPointer(new FixedTarget(card, game)).apply(game, source); } } diff --git a/Mage.Sets/src/mage/cards/g/GoblinDarkDwellers.java b/Mage.Sets/src/mage/cards/g/GoblinDarkDwellers.java index 62e324b7b27..08edcffffa9 100644 --- a/Mage.Sets/src/mage/cards/g/GoblinDarkDwellers.java +++ b/Mage.Sets/src/mage/cards/g/GoblinDarkDwellers.java @@ -3,11 +3,12 @@ package mage.cards.g; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.effects.common.MayCastTargetThenExileEffect; +import mage.abilities.effects.common.MayCastTargetCardEffect; import mage.abilities.keyword.MenaceAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.CastManaAdjustment; import mage.constants.ComparisonType; import mage.constants.SubType; import mage.filter.common.FilterInstantOrSorceryCard; @@ -39,7 +40,7 @@ public final class GoblinDarkDwellers extends CardImpl { // When Goblin Dark-Dwellers enters the battlefield, you may cast target instant or sorcery card with converted mana cost 3 or less from your graveyard without paying its mana cost. // If that card would be put into your graveyard this turn, exile it instead. - Ability ability = new EntersBattlefieldTriggeredAbility(new MayCastTargetThenExileEffect(true)); + Ability ability = new EntersBattlefieldTriggeredAbility(new MayCastTargetCardEffect(CastManaAdjustment.WITHOUT_PAYING_MANA_COST, true)); ability.addTarget(new TargetCardInYourGraveyard(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/h/HaloForager.java b/Mage.Sets/src/mage/cards/h/HaloForager.java index 5f6caabba64..53602eb6b58 100644 --- a/Mage.Sets/src/mage/cards/h/HaloForager.java +++ b/Mage.Sets/src/mage/cards/h/HaloForager.java @@ -8,15 +8,12 @@ import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.costs.mana.ManaCosts; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.MayCastTargetThenExileEffect; +import mage.abilities.effects.common.MayCastTargetCardEffect; import mage.abilities.effects.common.replacement.ThatSpellGraveyardExileReplacementEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.ComparisonType; -import mage.constants.Outcome; -import mage.constants.SubType; +import mage.constants.*; import mage.filter.FilterCard; import mage.filter.common.FilterInstantOrSorceryCard; import mage.filter.predicate.mageobject.ManaValuePredicate; @@ -90,7 +87,10 @@ class HaloForagerPayEffect extends OneShotEffect { "instant or sorcery card with mana value " + costX + " from a graveyard" ); filter.add(new ManaValuePredicate(ComparisonType.EQUAL_TO, costX)); - ReflexiveTriggeredAbility ability = new ReflexiveTriggeredAbility(new MayCastTargetThenExileEffect(true), false); + ReflexiveTriggeredAbility ability = new ReflexiveTriggeredAbility( + new MayCastTargetCardEffect(CastManaAdjustment.WITHOUT_PAYING_MANA_COST, true), + false + ); ability.addTarget(new TargetCardInGraveyard(filter)); game.fireReflexiveTriggeredAbility(ability, source); return true; diff --git a/Mage.Sets/src/mage/cards/j/JaceTelepathUnbound.java b/Mage.Sets/src/mage/cards/j/JaceTelepathUnbound.java index baac701e358..bcf3a7cd88e 100644 --- a/Mage.Sets/src/mage/cards/j/JaceTelepathUnbound.java +++ b/Mage.Sets/src/mage/cards/j/JaceTelepathUnbound.java @@ -1,11 +1,10 @@ package mage.cards.j; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.LoyaltyAbility; -import mage.abilities.effects.*; +import mage.abilities.effects.Effect; import mage.abilities.effects.common.GetEmblemEffect; -import mage.abilities.effects.common.MayCastTargetThenExileEffect; +import mage.abilities.effects.common.MayCastTargetCardEffect; import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -18,8 +17,9 @@ import mage.game.command.emblems.JaceTelepathUnboundEmblem; import mage.target.common.TargetCardInYourGraveyard; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class JaceTelepathUnbound extends CardImpl { @@ -42,7 +42,7 @@ public final class JaceTelepathUnbound extends CardImpl { this.addAbility(ability); // -3: You may cast target instant or sorcery card from your graveyard this turn. If that card would be put into your graveyard this turn, exile it instead. - ability = new LoyaltyAbility(new MayCastTargetThenExileEffect(Duration.EndOfTurn), -3); + ability = new LoyaltyAbility(new MayCastTargetCardEffect(Duration.EndOfTurn, true), -3); ability.addTarget(new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY_FROM_YOUR_GRAVEYARD)); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/m/MavindaStudentsAdvocate.java b/Mage.Sets/src/mage/cards/m/MavindaStudentsAdvocate.java index 4b1cd54c2a6..0d2b2510f0f 100644 --- a/Mage.Sets/src/mage/cards/m/MavindaStudentsAdvocate.java +++ b/Mage.Sets/src/mage/cards/m/MavindaStudentsAdvocate.java @@ -6,7 +6,7 @@ import mage.abilities.Ability; import mage.abilities.SpellAbility; import mage.abilities.common.LimitedTimesPerTurnActivatedAbility; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.effects.common.MayCastTargetThenExileEffect; +import mage.abilities.effects.common.MayCastTargetCardEffect; import mage.abilities.effects.common.cost.CostModificationEffectImpl; import mage.abilities.keyword.FlyingAbility; import mage.cards.Card; @@ -61,10 +61,10 @@ public final class MavindaStudentsAdvocate extends CardImpl { } } -class MavindaStudentsAdvocateEffect extends MayCastTargetThenExileEffect { +class MavindaStudentsAdvocateEffect extends MayCastTargetCardEffect { MavindaStudentsAdvocateEffect() { - super(Duration.EndOfTurn); + super(Duration.EndOfTurn, true); staticText = "you may cast target instant or sorcery card from your graveyard this turn. " + "If that spell doesn't target a creature you control, it costs {8} more to cast this way. " + "If that spell would be put into your graveyard, exile it instead"; diff --git a/Mage.Sets/src/mage/cards/m/MissionBriefing.java b/Mage.Sets/src/mage/cards/m/MissionBriefing.java index be75e483896..02779e71b0e 100644 --- a/Mage.Sets/src/mage/cards/m/MissionBriefing.java +++ b/Mage.Sets/src/mage/cards/m/MissionBriefing.java @@ -2,7 +2,7 @@ package mage.cards.m; import mage.abilities.Ability; import mage.abilities.effects.Effect; -import mage.abilities.effects.common.MayCastTargetThenExileEffect; +import mage.abilities.effects.common.MayCastTargetCardEffect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.replacement.ThatSpellGraveyardExileReplacementEffect; import mage.cards.CardImpl; @@ -68,7 +68,7 @@ class MissionBriefingEffect extends OneShotEffect { player.surveil(2, source, game); Target target = new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY_FROM_YOUR_GRAVEYARD); player.choose(outcome, target, source, game); - Effect effect = new MayCastTargetThenExileEffect(Duration.EndOfTurn); + Effect effect = new MayCastTargetCardEffect(Duration.EndOfTurn, true); effect.setTargetPointer(new FixedTarget(target.getFirstTarget(), game)); effect.apply(game, source); return true; diff --git a/Mage.Sets/src/mage/cards/s/SinsOfThePast.java b/Mage.Sets/src/mage/cards/s/SinsOfThePast.java index 8d0aac8ccfe..66436ab12f2 100644 --- a/Mage.Sets/src/mage/cards/s/SinsOfThePast.java +++ b/Mage.Sets/src/mage/cards/s/SinsOfThePast.java @@ -1,11 +1,12 @@ package mage.cards.s; import mage.abilities.effects.common.ExileSpellEffect; -import mage.abilities.effects.common.MayCastTargetThenExileEffect; +import mage.abilities.effects.common.MayCastTargetCardEffect; import mage.abilities.effects.common.replacement.ThatSpellGraveyardExileReplacementEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.CastManaAdjustment; import mage.filter.StaticFilters; import mage.target.common.TargetCardInYourGraveyard; @@ -20,7 +21,7 @@ public final class SinsOfThePast extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{B}{B}"); // Until end of turn, you may cast target instant or sorcery card from your graveyard without paying its mana cost. If that card would be put into your graveyard this turn, exile it instead. Exile Sins of the Past. - this.getSpellAbility().addEffect(new MayCastTargetThenExileEffect(true) + this.getSpellAbility().addEffect(new MayCastTargetCardEffect(CastManaAdjustment.WITHOUT_PAYING_MANA_COST, true) .setText("Until end of turn, you may cast target instant or sorcery card from your graveyard without paying its mana cost. " + ThatSpellGraveyardExileReplacementEffect.RULE_YOUR)); this.getSpellAbility().addEffect(new ExileSpellEffect()); diff --git a/Mage.Sets/src/mage/cards/s/SorcerousSquall.java b/Mage.Sets/src/mage/cards/s/SorcerousSquall.java index 9fc9aeb1a79..398c10c4d73 100644 --- a/Mage.Sets/src/mage/cards/s/SorcerousSquall.java +++ b/Mage.Sets/src/mage/cards/s/SorcerousSquall.java @@ -3,13 +3,14 @@ package mage.cards.s; import mage.abilities.Ability; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.MayCastTargetThenExileEffect; +import mage.abilities.effects.common.MayCastTargetCardEffect; import mage.abilities.effects.common.MillCardsTargetEffect; import mage.abilities.effects.common.replacement.ThatSpellGraveyardExileReplacementEffect; import mage.abilities.keyword.DelveAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.CastManaAdjustment; import mage.constants.Outcome; import mage.filter.FilterCard; import mage.filter.common.FilterInstantOrSorceryCard; @@ -24,7 +25,6 @@ import mage.target.targetpointer.FixedTarget; import java.util.UUID; /** - * * @author notgreat */ public final class SorcerousSquall extends CardImpl { @@ -57,7 +57,7 @@ class SorcerousSquallEffect extends OneShotEffect { SorcerousSquallEffect() { super(Outcome.Detriment); - setText("you may cast an instant or sorcery spell from that player's graveyard without paying its mana cost. "+ ThatSpellGraveyardExileReplacementEffect.RULE_A); + setText("you may cast an instant or sorcery spell from that player's graveyard without paying its mana cost. " + ThatSpellGraveyardExileReplacementEffect.RULE_A); } private SorcerousSquallEffect(final SorcerousSquallEffect effect) { @@ -79,7 +79,7 @@ class SorcerousSquallEffect extends OneShotEffect { filter.add(new OwnerIdPredicate(source.getFirstTarget())); Target target = new TargetCardInGraveyard(1, 1, filter, true); player.choose(outcome, target, source, game); - Effect effect = new MayCastTargetThenExileEffect(true); + Effect effect = new MayCastTargetCardEffect(CastManaAdjustment.WITHOUT_PAYING_MANA_COST, true); effect.setTargetPointer(new FixedTarget(target.getFirstTarget(), game)); effect.apply(game, source); return true; diff --git a/Mage.Sets/src/mage/cards/t/TinybonesThePickpocket.java b/Mage.Sets/src/mage/cards/t/TinybonesThePickpocket.java new file mode 100644 index 00000000000..735802e6a5c --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TinybonesThePickpocket.java @@ -0,0 +1,101 @@ +package mage.cards.t; + +import mage.MageInt; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.common.MayCastTargetCardEffect; +import mage.abilities.keyword.DeathtouchAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.filter.FilterCard; +import mage.filter.common.FilterPermanentCard; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.card.OwnerIdPredicate; +import mage.game.Game; +import mage.game.events.DamagedPlayerEvent; +import mage.game.events.GameEvent; +import mage.players.Player; +import mage.target.Target; +import mage.target.common.TargetCardInGraveyard; + +import java.util.UUID; + +/** + * @author Susucr + */ +public final class TinybonesThePickpocket extends CardImpl { + + public TinybonesThePickpocket(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.SKELETON); + this.subtype.add(SubType.ROGUE); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Deathtouch + this.addAbility(DeathtouchAbility.getInstance()); + + // Whenever Tinybones, the Pickpocket deals combat damage to a player, you may cast target nonland permanent card from that player's graveyard, and mana of any type can be spent to cast that spell. + this.addAbility(new TinybonesThePickpocketTriggeredAbility()); + } + + private TinybonesThePickpocket(final TinybonesThePickpocket card) { + super(card); + } + + @Override + public TinybonesThePickpocket copy() { + return new TinybonesThePickpocket(this); + } +} + +/** + * Similar to {@link mage.cards.w.WrexialTheRisenDeep} + */ +class TinybonesThePickpocketTriggeredAbility extends TriggeredAbilityImpl { + + TinybonesThePickpocketTriggeredAbility() { + super( + Zone.BATTLEFIELD, + new MayCastTargetCardEffect(CastManaAdjustment.AS_THOUGH_ANY_MANA_TYPE, false) + .setText("you may cast target nonland permanent card from " + + "that player's graveyard, and mana of any type can be spent to cast that spell"), + false + ); + setTriggerPhrase("Whenever {this} deals combat damage to a player, "); + } + + private TinybonesThePickpocketTriggeredAbility(final TinybonesThePickpocketTriggeredAbility ability) { + super(ability); + } + + @Override + public TinybonesThePickpocketTriggeredAbility copy() { + return new TinybonesThePickpocketTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DAMAGED_PLAYER; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (!event.getSourceId().equals(this.sourceId) || !((DamagedPlayerEvent) event).isCombatDamage()) { + return false; + } + Player damagedPlayer = game.getPlayer(event.getTargetId()); + if (damagedPlayer == null) { + return false; + } + FilterCard filter = new FilterPermanentCard("nonland permanent card from " + damagedPlayer.getName() + "'s graveyard"); + filter.add(new OwnerIdPredicate(damagedPlayer.getId())); + filter.add(Predicates.not(CardType.LAND.getPredicate())); + Target target = new TargetCardInGraveyard(filter); + this.getTargets().clear(); + this.addTarget(target); + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/t/TorrentialGearhulk.java b/Mage.Sets/src/mage/cards/t/TorrentialGearhulk.java index 6f8ace7ed88..4c9efb10884 100644 --- a/Mage.Sets/src/mage/cards/t/TorrentialGearhulk.java +++ b/Mage.Sets/src/mage/cards/t/TorrentialGearhulk.java @@ -3,11 +3,12 @@ package mage.cards.t; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.effects.common.MayCastTargetThenExileEffect; +import mage.abilities.effects.common.MayCastTargetCardEffect; import mage.abilities.keyword.FlashAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.CastManaAdjustment; import mage.constants.SubType; import mage.filter.FilterCard; import mage.target.common.TargetCardInYourGraveyard; @@ -37,7 +38,7 @@ public final class TorrentialGearhulk extends CardImpl { // When Torrential Gearhulk enters the battlefield, you may cast target // instant card from your graveyard without paying its mana cost. // If that card would be put into your graveyard this turn, exile it instead. - Ability ability = new EntersBattlefieldTriggeredAbility(new MayCastTargetThenExileEffect(true)); + Ability ability = new EntersBattlefieldTriggeredAbility(new MayCastTargetCardEffect(CastManaAdjustment.WITHOUT_PAYING_MANA_COST, true)); ability.addTarget(new TargetCardInYourGraveyard(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/t/ToshiroUmezawa.java b/Mage.Sets/src/mage/cards/t/ToshiroUmezawa.java index 6b36c491924..feeca4e9760 100644 --- a/Mage.Sets/src/mage/cards/t/ToshiroUmezawa.java +++ b/Mage.Sets/src/mage/cards/t/ToshiroUmezawa.java @@ -3,7 +3,7 @@ package mage.cards.t; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.DiesCreatureTriggeredAbility; -import mage.abilities.effects.common.MayCastTargetThenExileEffect; +import mage.abilities.effects.common.MayCastTargetCardEffect; import mage.abilities.effects.common.replacement.ThatSpellGraveyardExileReplacementEffect; import mage.abilities.keyword.BushidoAbility; import mage.cards.CardImpl; @@ -39,7 +39,7 @@ public final class ToshiroUmezawa extends CardImpl { // Bushido 1 this.addAbility(new BushidoAbility(1)); // Whenever a creature an opponent controls dies, you may cast target instant card from your graveyard. If that card would be put into a graveyard this turn, exile it instead. - Ability ability = new DiesCreatureTriggeredAbility(new MayCastTargetThenExileEffect(false) + Ability ability = new DiesCreatureTriggeredAbility(new MayCastTargetCardEffect(true) .setText("you may cast target instant card from your graveyard. " + ThatSpellGraveyardExileReplacementEffect.RULE_A), true, StaticFilters.FILTER_OPPONENTS_PERMANENT_A_CREATURE); diff --git a/Mage.Sets/src/mage/cards/v/VoharVodalianDesecrator.java b/Mage.Sets/src/mage/cards/v/VoharVodalianDesecrator.java index 6a32cb79806..3fd8800045a 100644 --- a/Mage.Sets/src/mage/cards/v/VoharVodalianDesecrator.java +++ b/Mage.Sets/src/mage/cards/v/VoharVodalianDesecrator.java @@ -1,6 +1,5 @@ package mage.cards.v; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.ActivateAsSorceryActivatedAbility; @@ -8,19 +7,20 @@ import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.effects.common.MayCastTargetThenExileEffect; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.MayCastTargetCardEffect; import mage.cards.Card; -import mage.constants.*; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.*; import mage.filter.StaticFilters; import mage.game.Game; import mage.players.Player; import mage.target.common.TargetCardInYourGraveyard; +import java.util.UUID; + /** - * * @author weirddan455 */ public final class VoharVodalianDesecrator extends CardImpl { @@ -40,7 +40,7 @@ public final class VoharVodalianDesecrator extends CardImpl { // {2}, Sacrifice Vohar, Vodalian Desecrator: You may cast target instant or sorcery card from your graveyard this turn. If that spell would be put into your graveyard, exile it instead. Activate only as a sorcery. Ability ability = new ActivateAsSorceryActivatedAbility( - new MayCastTargetThenExileEffect(Duration.EndOfTurn), new GenericManaCost(2) + new MayCastTargetCardEffect(Duration.EndOfTurn, true), new GenericManaCost(2) ); ability.addCost(new SacrificeSourceCost()); ability.addTarget(new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY_FROM_YOUR_GRAVEYARD)); diff --git a/Mage.Sets/src/mage/cards/w/WrexialTheRisenDeep.java b/Mage.Sets/src/mage/cards/w/WrexialTheRisenDeep.java index 20e474b4de9..5cfca700972 100644 --- a/Mage.Sets/src/mage/cards/w/WrexialTheRisenDeep.java +++ b/Mage.Sets/src/mage/cards/w/WrexialTheRisenDeep.java @@ -2,7 +2,7 @@ package mage.cards.w; import mage.MageInt; import mage.abilities.TriggeredAbilityImpl; -import mage.abilities.effects.common.MayCastTargetThenExileEffect; +import mage.abilities.effects.common.MayCastTargetCardEffect; import mage.abilities.effects.common.replacement.ThatSpellGraveyardExileReplacementEffect; import mage.abilities.keyword.IslandwalkAbility; import mage.abilities.keyword.SwampwalkAbility; @@ -57,7 +57,7 @@ public final class WrexialTheRisenDeep extends CardImpl { class WrexialTheRisenDeepTriggeredAbility extends TriggeredAbilityImpl { WrexialTheRisenDeepTriggeredAbility() { - super(Zone.BATTLEFIELD, new MayCastTargetThenExileEffect(true) + super(Zone.BATTLEFIELD, new MayCastTargetCardEffect(CastManaAdjustment.WITHOUT_PAYING_MANA_COST, true) .setText("you may cast target instant or sorcery card from " + "that player's graveyard without paying its mana cost. " + ThatSpellGraveyardExileReplacementEffect.RULE_A), false); @@ -92,7 +92,7 @@ class WrexialTheRisenDeepTriggeredAbility extends TriggeredAbilityImpl { filter.add(Predicates.or( CardType.INSTANT.getPredicate(), CardType.SORCERY.getPredicate() - )); + )); Target target = new TargetCardInGraveyard(filter); this.getTargets().clear(); this.addTarget(target); diff --git a/Mage.Sets/src/mage/sets/OutlawsOfThunderJunction.java b/Mage.Sets/src/mage/sets/OutlawsOfThunderJunction.java index af3aa085f73..b2a6deacd0f 100644 --- a/Mage.Sets/src/mage/sets/OutlawsOfThunderJunction.java +++ b/Mage.Sets/src/mage/sets/OutlawsOfThunderJunction.java @@ -283,6 +283,7 @@ public final class OutlawsOfThunderJunction extends ExpansionSet { cards.add(new SetCardInfo("Thunder Lasso", 35, Rarity.UNCOMMON, mage.cards.t.ThunderLasso.class)); cards.add(new SetCardInfo("Thunder Salvo", 150, Rarity.COMMON, mage.cards.t.ThunderSalvo.class)); cards.add(new SetCardInfo("Tinybones Joins Up", 108, Rarity.RARE, mage.cards.t.TinybonesJoinsUp.class)); + cards.add(new SetCardInfo("Tinybones, the Pickpocket", 109, Rarity.MYTHIC, mage.cards.t.TinybonesThePickpocket.class)); cards.add(new SetCardInfo("Tomb Trawler", 250, Rarity.UNCOMMON, mage.cards.t.TombTrawler.class)); cards.add(new SetCardInfo("Trained Arynx", 36, Rarity.COMMON, mage.cards.t.TrainedArynx.class)); cards.add(new SetCardInfo("Trash the Town", 186, Rarity.UNCOMMON, mage.cards.t.TrashTheTown.class)); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/otj/TinybonesThePickpocketTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/otj/TinybonesThePickpocketTest.java new file mode 100644 index 00000000000..8358fb6a770 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/otj/TinybonesThePickpocketTest.java @@ -0,0 +1,59 @@ +package org.mage.test.cards.single.otj; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * @author Susucr + */ +public class TinybonesThePickpocketTest extends CardTestPlayerBase { + + /** + * {@link mage.cards.t.TinybonesThePickpocket Tinybones, the Pickpocket} {B} + * Legendary Creature — Skeleton Rogue + * Deathtouch + * Whenever Tinybones, the Pickpocket deals combat damage to a player, you may cast target nonland permanent card from that player's graveyard, and mana of any type can be spent to cast that spell. + * 1/1 + */ + private static final String tinybones = "Tinybones, the Pickpocket"; + + @Test + public void test_CastPermanent_WithOtherType() { + setStrictChooseMode(true); + + addCard(Zone.BATTLEFIELD, playerA, tinybones); + addCard(Zone.GRAVEYARD, playerB, "Raging Goblin"); + addCard(Zone.BATTLEFIELD, playerA, "Swamp"); + + attack(1, playerA, tinybones, playerB); + addTarget(playerA, "Raging Goblin"); // target card for the trigger + setChoice(playerA, true); // yes to "you may cast" + + setStopAt(1, PhaseStep.END_COMBAT); + execute(); + + assertPermanentCount(playerA, "Raging Goblin", 1); + assertTapped("Swamp", true); // It did cost 1 mana + } + + @Test + public void test_NoToCast() { + setStrictChooseMode(true); + + addCard(Zone.BATTLEFIELD, playerA, tinybones); + addCard(Zone.GRAVEYARD, playerB, "Raging Goblin"); + addCard(Zone.BATTLEFIELD, playerA, "Swamp"); + + attack(1, playerA, tinybones, playerB); + addTarget(playerA, "Raging Goblin"); // target card for the trigger + setChoice(playerA, false); // no to "you may cast" + + setStopAt(1, PhaseStep.END_COMBAT); + execute(); + + assertGraveyardCount(playerB, "Raging Goblin", 1); // card did not move. + assertTapped("Swamp", false); + } +} diff --git a/Mage/src/main/java/mage/abilities/effects/common/MayCastTargetCardEffect.java b/Mage/src/main/java/mage/abilities/effects/common/MayCastTargetCardEffect.java new file mode 100644 index 00000000000..19d7c536f66 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/MayCastTargetCardEffect.java @@ -0,0 +1,158 @@ +package mage.abilities.effects.common; + +import mage.ApprovingObject; +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.asthought.YouMaySpendManaAsAnyColorToCastTargetEffect; +import mage.abilities.effects.common.replacement.ThatSpellGraveyardExileReplacementEffect; +import mage.cards.Card; +import mage.constants.CastManaAdjustment; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.game.Game; +import mage.players.Player; +import mage.target.targetpointer.FixedTarget; +import mage.util.CardUtil; + +/** + * @author xenohedron, Susucr + */ +public class MayCastTargetCardEffect extends OneShotEffect { + + private final Duration duration; + + private final CastManaAdjustment manaAdjustment; + + private final boolean thenExile; // Should the spell be exiled by a replacement effect if cast and it resolves? + + /** + * Allows to cast the target card immediately, for its manacost. + */ + public MayCastTargetCardEffect(boolean exileOnResolve) { + this(CastManaAdjustment.NONE, exileOnResolve); + } + + /** + * Allows to cast the target card immediately, either for its cost or with a modifier (like for free, or mana as any type). + */ + public MayCastTargetCardEffect(CastManaAdjustment manaAdjustment, boolean exileOnResolve) { + this(Duration.OneUse, manaAdjustment, exileOnResolve); + } + + /** + * Makes the target card playable for the specified duration as long as it remains in that zone. + */ + public MayCastTargetCardEffect(Duration duration, boolean exileOnResolve) { + this(duration, CastManaAdjustment.NONE, exileOnResolve); + } + + protected MayCastTargetCardEffect(Duration duration, CastManaAdjustment manaAdjustment, boolean thenExile) { + super(Outcome.Benefit); + this.duration = duration; + this.manaAdjustment = manaAdjustment; + this.thenExile = thenExile; + + // TODO: support the non-yet-supported combinations. + // for now the constructor chains won't allow those. + if (duration != Duration.OneUse && manaAdjustment != CastManaAdjustment.NONE) { + throw new IllegalStateException( + "Wrong code usage, not yet supported " + + "duration={" + duration.name() + "}, " + + "manaAdjustment={" + manaAdjustment.name() + "}" + ); + } + } + + protected MayCastTargetCardEffect(final MayCastTargetCardEffect effect) { + super(effect); + this.duration = effect.duration; + this.manaAdjustment = effect.manaAdjustment; + this.thenExile = effect.thenExile; + } + + @Override + public MayCastTargetCardEffect copy() { + return new MayCastTargetCardEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Card card = game.getCard(getTargetPointer().getFirst(game, source)); + if (card == null) { + return false; + } + if (duration == Duration.OneUse) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null || !controller.chooseUse(outcome, "Cast " + card.getLogName() + '?', source, game)) { + return false; + } + + switch (manaAdjustment) { + case NONE: + case WITHOUT_PAYING_MANA_COST: + break; + case AS_THOUGH_ANY_MANA_COLOR: + case AS_THOUGH_ANY_MANA_TYPE: + // TODO: untangle why there is a confusion between the two. + ContinuousEffect effect = + new YouMaySpendManaAsAnyColorToCastTargetEffect(Duration.Custom, controller.getId(), null); + effect.setTargetPointer(new FixedTarget(card, game)); + game.addEffect(effect, source); + break; + default: + throw new IllegalArgumentException("Wrong code usage, manaAdjustment is not yet supported: " + manaAdjustment); + } + + game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE); + boolean noMana = manaAdjustment == CastManaAdjustment.WITHOUT_PAYING_MANA_COST; + controller.cast(controller.chooseAbilityForCast(card, game, noMana), + game, noMana, new ApprovingObject(source, game)); + game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null); + } else { + // TODO: support (and add tests!) for the non-NONE manaAdjustment + CardUtil.makeCardPlayable(game, source, card, duration, false); + } + if (thenExile) { + ContinuousEffect effect = new ThatSpellGraveyardExileReplacementEffect(true); + effect.setTargetPointer(new FixedTarget(card, game)); + game.addEffect(effect, source); + } + return true; + } + + @Override + public String getText(Mode mode) { + if (staticText != null && !staticText.isEmpty()) { + return staticText; + } + String text = "you may cast " + getTargetPointer().describeTargets(mode.getTargets(), "it"); + if (duration == Duration.EndOfTurn) { + text += " this turn"; + } else if (!duration.toString().isEmpty()) { + text += duration.toString(); + } + switch (manaAdjustment) { + case NONE: + break; + case WITHOUT_PAYING_MANA_COST: + text += " without paying its mana cost"; + break; + case AS_THOUGH_ANY_MANA_COLOR: + text += ", and mana of any color can be spent to cast that spell"; + break; + case AS_THOUGH_ANY_MANA_TYPE: + text += ", and mana of any type can be spent to cast that spell"; + break; + default: + throw new IllegalArgumentException("Wrong code usage, manaAdjustment is not yet supported: " + manaAdjustment); + } + text += "."; + if (thenExile) { + text += " " + ThatSpellGraveyardExileReplacementEffect.RULE_YOUR; + } + return text; + } + +} diff --git a/Mage/src/main/java/mage/abilities/effects/common/MayCastTargetThenExileEffect.java b/Mage/src/main/java/mage/abilities/effects/common/MayCastTargetThenExileEffect.java deleted file mode 100644 index cd65e9d8a60..00000000000 --- a/Mage/src/main/java/mage/abilities/effects/common/MayCastTargetThenExileEffect.java +++ /dev/null @@ -1,98 +0,0 @@ -package mage.abilities.effects.common; - -import mage.ApprovingObject; -import mage.abilities.Ability; -import mage.abilities.Mode; -import mage.abilities.effects.ContinuousEffect; -import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.replacement.ThatSpellGraveyardExileReplacementEffect; -import mage.cards.Card; -import mage.constants.Duration; -import mage.constants.Outcome; -import mage.game.Game; -import mage.players.Player; -import mage.target.targetpointer.FixedTarget; -import mage.util.CardUtil; - -/** - * @author xenohedron - */ -public class MayCastTargetThenExileEffect extends OneShotEffect { - - private final Duration duration; - private final boolean noMana; - - /** - * Allows to cast the target card immediately, either for its cost or for free. - * If resulting spell would be put into graveyard, exiles it instead. - */ - public MayCastTargetThenExileEffect(boolean noMana) { - super(Outcome.Benefit); - this.duration = Duration.OneUse; - this.noMana = noMana; - } - - /** - * Makes the target card playable for the specified duration as long as it remains in that zone. - * If resulting spell would be put into graveyard, exiles it instead. - */ - public MayCastTargetThenExileEffect(Duration duration) { - super(Outcome.Benefit); - this.duration = duration; - this.noMana = false; - } - - protected MayCastTargetThenExileEffect(final MayCastTargetThenExileEffect effect) { - super(effect); - this.duration = effect.duration; - this.noMana = effect.noMana; - } - - @Override - public MayCastTargetThenExileEffect copy() { - return new MayCastTargetThenExileEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Card card = game.getCard(getTargetPointer().getFirst(game, source)); - if (card == null) { - return false; - } - FixedTarget fixedTarget = new FixedTarget(card, game); - if (duration == Duration.OneUse) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller == null || !controller.chooseUse(outcome, "Cast " + card.getLogName() + '?', source, game)) { - return false; - } - game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE); - controller.cast(controller.chooseAbilityForCast(card, game, noMana), - game, noMana, new ApprovingObject(source, game)); - game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null); - } else { - CardUtil.makeCardPlayable(game, source, card, duration, false); - } - ContinuousEffect effect = new ThatSpellGraveyardExileReplacementEffect(true); - effect.setTargetPointer(fixedTarget); - game.addEffect(effect, source); - return true; - } - - @Override - public String getText(Mode mode) { - if (staticText != null && !staticText.isEmpty()) { - return staticText; - } - String text = "you may cast " + getTargetPointer().describeTargets(mode.getTargets(), "it"); - if (duration == Duration.EndOfTurn) { - text += " this turn"; - } else if (!duration.toString().isEmpty()) { - text += duration.toString(); - } - if (noMana) { - text += " without paying its mana cost"; - } - return text + ". " + ThatSpellGraveyardExileReplacementEffect.RULE_YOUR; - } - -} diff --git a/Mage/src/main/java/mage/abilities/effects/common/asthought/YouMaySpendManaAsAnyColorToCastTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/asthought/YouMaySpendManaAsAnyColorToCastTargetEffect.java index b79eee13fcc..ddeb2dbc71a 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/asthought/YouMaySpendManaAsAnyColorToCastTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/asthought/YouMaySpendManaAsAnyColorToCastTargetEffect.java @@ -16,6 +16,7 @@ import java.util.UUID; /** * Spend mana as any color to cast targeted card. Will not affected after any card movements or blinks. * Affects to all card's parts + * TODO: AnyType and AnyColor are confused there. * * @author JayDi85 */ diff --git a/Mage/src/main/java/mage/constants/CastManaAdjustment.java b/Mage/src/main/java/mage/constants/CastManaAdjustment.java new file mode 100644 index 00000000000..ab094c16ab4 --- /dev/null +++ b/Mage/src/main/java/mage/constants/CastManaAdjustment.java @@ -0,0 +1,29 @@ +package mage.constants; + +/** + * Groups together the most usual ways a card's payment is adjusted + * by card effects that allow play or cast. + *

+ * Effects should attempt to support those for all the various ways + * to play/cast cards/spells in Effects + * + * @author Susucr + */ +public enum CastManaAdjustment { + /** + * No adjustment to play/cast + */ + NONE, + /** + * Mana can be used as any mana type to pay for the mana cost + */ + AS_THOUGH_ANY_MANA_TYPE, + /** + * Mana can be used as any mana color to pay for the mana cost + */ + AS_THOUGH_ANY_MANA_COLOR, + /** + * The card is play/cast without paying for its mana cost + */ + WITHOUT_PAYING_MANA_COST, +} \ No newline at end of file diff --git a/Mage/src/main/java/mage/util/CardUtil.java b/Mage/src/main/java/mage/util/CardUtil.java index c5f32b6620b..97820c04195 100644 --- a/Mage/src/main/java/mage/util/CardUtil.java +++ b/Mage/src/main/java/mage/util/CardUtil.java @@ -1280,6 +1280,7 @@ public final class CardUtil { } } + // TODO: use CastManaAdjustment instead of boolean anyColor public static void makeCardPlayable(Game game, Ability source, Card card, Duration duration, boolean anyColor) { makeCardPlayable(game, source, card, duration, anyColor, null, null); } @@ -1296,6 +1297,7 @@ public final class CardUtil { * @param anyColor * @param condition can be null */ + // TODO: use CastManaAdjustment instead of boolean anyColor public static void makeCardPlayable(Game game, Ability source, Card card, Duration duration, boolean anyColor, UUID playerId, Condition condition) { // Effect can be used for cards in zones and permanents on battlefield // PermanentCard's ZCC is static, but we need updated ZCC from the card (after moved to another zone)