diff --git a/Mage.Sets/src/mage/sets/avacynrestored/ArcaneMelee.java b/Mage.Sets/src/mage/sets/avacynrestored/ArcaneMelee.java index 83605b77b65..98adf18c308 100644 --- a/Mage.Sets/src/mage/sets/avacynrestored/ArcaneMelee.java +++ b/Mage.Sets/src/mage/sets/avacynrestored/ArcaneMelee.java @@ -33,7 +33,6 @@ import mage.abilities.SpellAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.cost.CostModificationEffectImpl; import mage.abilities.keyword.FlashbackAbility; -import mage.abilities.keyword.RetraceAbility; import mage.cards.Card; import mage.cards.CardImpl; import mage.game.Game; @@ -51,8 +50,6 @@ public class ArcaneMelee extends CardImpl { super(ownerId, 44, "Arcane Melee", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{4}{U}"); this.expansionSetCode = "AVR"; - this.color.setBlue(true); - // Instant and sorcery spells cost {2} less to cast. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ArcaneMeleeCostReductionEffect())); } @@ -87,7 +84,7 @@ class ArcaneMeleeCostReductionEffect extends CostModificationEffectImpl { @Override public boolean applies(Ability abilityToModify, Ability source, Game game) { - if ( abilityToModify instanceof SpellAbility || abilityToModify instanceof FlashbackAbility || abilityToModify instanceof RetraceAbility) { + if ( abilityToModify instanceof SpellAbility || abilityToModify instanceof FlashbackAbility) { Card sourceCard = game.getCard(((SpellAbility)abilityToModify).getSourceId()); if ( sourceCard != null && (sourceCard.getCardType().contains(CardType.INSTANT) || sourceCard.getCardType().contains(CardType.SORCERY))) { return true; diff --git a/Mage.Sets/src/mage/sets/avacynrestored/HeraldOfWar.java b/Mage.Sets/src/mage/sets/avacynrestored/HeraldOfWar.java index a4b8b09d863..30e25ad36b8 100644 --- a/Mage.Sets/src/mage/sets/avacynrestored/HeraldOfWar.java +++ b/Mage.Sets/src/mage/sets/avacynrestored/HeraldOfWar.java @@ -37,7 +37,6 @@ import mage.abilities.effects.common.cost.CostModificationEffectImpl; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.keyword.FlashbackAbility; import mage.abilities.keyword.FlyingAbility; -import mage.abilities.keyword.RetraceAbility; import mage.cards.Card; import mage.cards.CardImpl; import mage.counters.CounterType; @@ -57,7 +56,6 @@ public class HeraldOfWar extends CardImpl { this.expansionSetCode = "AVR"; this.subtype.add("Angel"); - this.color.setWhite(true); this.power = new MageInt(3); this.toughness = new MageInt(3); @@ -107,7 +105,7 @@ class HeraldOfWarCostReductionEffect extends CostModificationEffectImpl { @Override public boolean applies(Ability abilityToModify, Ability source, Game game) { - if (abilityToModify instanceof SpellAbility || abilityToModify instanceof FlashbackAbility || abilityToModify instanceof RetraceAbility) { + if (abilityToModify instanceof SpellAbility || abilityToModify instanceof FlashbackAbility) { Card sourceCard = game.getCard(abilityToModify.getSourceId()); if (sourceCard != null && abilityToModify.getControllerId().equals(source.getControllerId()) && (sourceCard.hasSubtype("Angel") || sourceCard.hasSubtype("Human"))) { return true; diff --git a/Mage.Sets/src/mage/sets/commander/AnimarSoulOfElements.java b/Mage.Sets/src/mage/sets/commander/AnimarSoulOfElements.java index ea891aa902c..f22a8ccd02b 100644 --- a/Mage.Sets/src/mage/sets/commander/AnimarSoulOfElements.java +++ b/Mage.Sets/src/mage/sets/commander/AnimarSoulOfElements.java @@ -38,7 +38,6 @@ import mage.abilities.effects.common.cost.CostModificationEffectImpl; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.keyword.FlashbackAbility; import mage.abilities.keyword.ProtectionAbility; -import mage.abilities.keyword.RetraceAbility; import mage.cards.Card; import mage.cards.CardImpl; import mage.constants.CardType; @@ -78,9 +77,6 @@ public class AnimarSoulOfElements extends CardImpl { this.supertype.add("Legendary"); this.subtype.add("Elemental"); - this.color.setRed(true); - this.color.setBlue(true); - this.color.setGreen(true); this.power = new MageInt(1); this.toughness = new MageInt(1); @@ -132,7 +128,7 @@ class AnimarCostReductionEffect extends CostModificationEffectImpl { @Override public boolean applies(Ability abilityToModify, Ability source, Game game) { - if (abilityToModify instanceof SpellAbility || abilityToModify instanceof FlashbackAbility || abilityToModify instanceof RetraceAbility) { + if (abilityToModify instanceof SpellAbility || abilityToModify instanceof FlashbackAbility) { Card sourceCard = game.getCard(abilityToModify.getSourceId()); if (sourceCard != null && abilityToModify.getControllerId().equals(source.getControllerId()) && (sourceCard.getCardType().contains(CardType.CREATURE))) { return true; diff --git a/Mage.Sets/src/mage/sets/commander/CallTheSkybreaker.java b/Mage.Sets/src/mage/sets/commander/CallTheSkybreaker.java index 95694235f7b..3c4906036ca 100644 --- a/Mage.Sets/src/mage/sets/commander/CallTheSkybreaker.java +++ b/Mage.Sets/src/mage/sets/commander/CallTheSkybreaker.java @@ -29,17 +29,13 @@ package mage.sets.commander; import java.util.UUID; import mage.MageInt; -import mage.abilities.costs.common.DiscardTargetCost; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.RetraceAbility; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Rarity; -import mage.constants.TimingRule; -import mage.filter.common.FilterLandCard; import mage.game.permanent.token.Token; -import mage.target.common.TargetCardInHand; /** * @@ -52,14 +48,11 @@ public class CallTheSkybreaker extends CardImpl { super(ownerId, 188, "Call the Skybreaker", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{5}{U/R}{U/R}"); this.expansionSetCode = "CMD"; - this.color.setRed(true); - this.color.setBlue(true); - // Put a 5/5 blue and red Elemental creature token with flying onto the battlefield. this.getSpellAbility().addEffect(new CreateTokenEffect(new ElementalToken())); // Retrace - this.addAbility(new RetraceAbility(getSpellAbility().getManaCosts(), TimingRule.SORCERY)); + this.addAbility(new RetraceAbility(this)); } diff --git a/Mage.Sets/src/mage/sets/commander/KaradorGhostChieftain.java b/Mage.Sets/src/mage/sets/commander/KaradorGhostChieftain.java index 742bec871bb..d466c65ca49 100644 --- a/Mage.Sets/src/mage/sets/commander/KaradorGhostChieftain.java +++ b/Mage.Sets/src/mage/sets/commander/KaradorGhostChieftain.java @@ -36,8 +36,6 @@ import mage.abilities.effects.AsThoughEffectImpl; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.common.cost.CostModificationEffectImpl; -import mage.abilities.keyword.FlashbackAbility; -import mage.abilities.keyword.RetraceAbility; import mage.cards.Card; import mage.cards.CardImpl; import mage.constants.AsThoughEffectType; @@ -72,9 +70,6 @@ public class KaradorGhostChieftain extends CardImpl { this.subtype.add("Centaur"); this.subtype.add("Spirit"); - this.color.setWhite(true); - this.color.setGreen(true); - this.color.setBlack(true); this.power = new MageInt(3); this.toughness = new MageInt(4); diff --git a/Mage.Sets/src/mage/sets/darkascension/ThaliaGuardianOfThraben.java b/Mage.Sets/src/mage/sets/darkascension/ThaliaGuardianOfThraben.java index 4385c9cbdec..0e8cd3bc8e3 100644 --- a/Mage.Sets/src/mage/sets/darkascension/ThaliaGuardianOfThraben.java +++ b/Mage.Sets/src/mage/sets/darkascension/ThaliaGuardianOfThraben.java @@ -27,7 +27,7 @@ */ package mage.sets.darkascension; -import mage.constants.*; +import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.SpellAbility; @@ -35,14 +35,17 @@ import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.cost.CostModificationEffectImpl; import mage.abilities.keyword.FirstStrikeAbility; import mage.abilities.keyword.FlashbackAbility; -import mage.abilities.keyword.RetraceAbility; import mage.cards.Card; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.CostModificationType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; import mage.game.Game; import mage.util.CardUtil; -import java.util.UUID; - /** * * @author BetaSteward @@ -56,7 +59,6 @@ public class ThaliaGuardianOfThraben extends CardImpl { this.subtype.add("Human"); this.subtype.add("Soldier"); - this.color.setWhite(true); this.power = new MageInt(2); this.toughness = new MageInt(1); @@ -96,7 +98,7 @@ class ThaliaGuardianOfThrabenCostReductionEffect extends CostModificationEffectI @Override public boolean applies(Ability abilityToModify, Ability source, Game game) { - if (abilityToModify instanceof SpellAbility || abilityToModify instanceof FlashbackAbility || abilityToModify instanceof RetraceAbility) { + if (abilityToModify instanceof SpellAbility || abilityToModify instanceof FlashbackAbility) { Card card = game.getCard(abilityToModify.getSourceId()); if (card != null && !card.getCardType().contains(CardType.CREATURE)) { return true; diff --git a/Mage.Sets/src/mage/sets/eventide/CennsEnlistment.java b/Mage.Sets/src/mage/sets/eventide/CennsEnlistment.java index 59821a9b6cf..3bbb84df53c 100644 --- a/Mage.Sets/src/mage/sets/eventide/CennsEnlistment.java +++ b/Mage.Sets/src/mage/sets/eventide/CennsEnlistment.java @@ -48,12 +48,11 @@ public class CennsEnlistment extends CardImpl { super(ownerId, 3, "Cenn's Enlistment", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{3}{W}"); this.expansionSetCode = "EVE"; - this.color.setWhite(true); - // Put two 1/1 white Kithkin Soldier creature tokens onto the battlefield. this.getSpellAbility().addEffect(new CreateTokenEffect(new KithkinToken(), 2)); + // Retrace - this.addAbility(new RetraceAbility(new ManaCostsImpl("{3}{W}"), TimingRule.SORCERY)); + this.addAbility(new RetraceAbility(this)); } public CennsEnlistment(final CennsEnlistment card) { diff --git a/Mage.Sets/src/mage/sets/eventide/FlameJab.java b/Mage.Sets/src/mage/sets/eventide/FlameJab.java index c6fc890c2be..46ffe6acefc 100644 --- a/Mage.Sets/src/mage/sets/eventide/FlameJab.java +++ b/Mage.Sets/src/mage/sets/eventide/FlameJab.java @@ -31,11 +31,9 @@ import java.util.UUID; import mage.constants.CardType; import mage.constants.Rarity; -import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.keyword.RetraceAbility; import mage.cards.CardImpl; -import mage.constants.TimingRule; import mage.target.common.TargetCreatureOrPlayer; /** @@ -48,13 +46,11 @@ public class FlameJab extends CardImpl { super(ownerId, 53, "Flame Jab", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{R}"); this.expansionSetCode = "EVE"; - this.color.setRed(true); - // Flame Jab deals 1 damage to target creature or player. this.getSpellAbility().addEffect(new DamageTargetEffect(1)); this.getSpellAbility().addTarget(new TargetCreatureOrPlayer()); // Retrace - this.addAbility(new RetraceAbility(new ManaCostsImpl("{R}"), TimingRule.SORCERY)); + this.addAbility(new RetraceAbility(this)); } public FlameJab(final FlameJab card) { diff --git a/Mage.Sets/src/mage/sets/eventide/Monstrify.java b/Mage.Sets/src/mage/sets/eventide/Monstrify.java index b8f9690d0f6..d8ab5208db2 100644 --- a/Mage.Sets/src/mage/sets/eventide/Monstrify.java +++ b/Mage.Sets/src/mage/sets/eventide/Monstrify.java @@ -31,12 +31,10 @@ import java.util.UUID; import mage.constants.CardType; import mage.constants.Rarity; -import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.abilities.keyword.RetraceAbility; import mage.cards.CardImpl; import mage.constants.Duration; -import mage.constants.TimingRule; import mage.target.common.TargetCreaturePermanent; /** @@ -49,13 +47,11 @@ public class Monstrify extends CardImpl { super(ownerId, 70, "Monstrify", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{3}{G}"); this.expansionSetCode = "EVE"; - this.color.setGreen(true); - // Target creature gets +4/+4 until end of turn. this.getSpellAbility().addEffect(new BoostTargetEffect(4, 4, Duration.EndOfTurn)); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); // Retrace - this.addAbility(new RetraceAbility(new ManaCostsImpl("{3}{G}"), TimingRule.SORCERY)); + this.addAbility(new RetraceAbility(this)); } public Monstrify(final Monstrify card) { diff --git a/Mage.Sets/src/mage/sets/eventide/OonasGrace.java b/Mage.Sets/src/mage/sets/eventide/OonasGrace.java index 4ea53ad7c3a..5b598ef3f3d 100644 --- a/Mage.Sets/src/mage/sets/eventide/OonasGrace.java +++ b/Mage.Sets/src/mage/sets/eventide/OonasGrace.java @@ -31,11 +31,9 @@ import java.util.UUID; import mage.constants.CardType; import mage.constants.Rarity; -import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.common.DrawCardTargetEffect; import mage.abilities.keyword.RetraceAbility; import mage.cards.CardImpl; -import mage.constants.TimingRule; import mage.target.TargetPlayer; /** @@ -48,13 +46,11 @@ public class OonasGrace extends CardImpl { super(ownerId, 27, "Oona's Grace", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{2}{U}"); this.expansionSetCode = "EVE"; - this.color.setBlue(true); - // Target player draws a card. this.getSpellAbility().addEffect(new DrawCardTargetEffect(1)); this.getSpellAbility().addTarget(new TargetPlayer()); // Retrace - this.addAbility(new RetraceAbility(new ManaCostsImpl("{2}{U}"), TimingRule.INSTANT)); + this.addAbility(new RetraceAbility(this)); } public OonasGrace(final OonasGrace card) { diff --git a/Mage.Sets/src/mage/sets/eventide/RavensCrime.java b/Mage.Sets/src/mage/sets/eventide/RavensCrime.java index 44f5357bd9a..ebf73bba3e8 100644 --- a/Mage.Sets/src/mage/sets/eventide/RavensCrime.java +++ b/Mage.Sets/src/mage/sets/eventide/RavensCrime.java @@ -31,11 +31,9 @@ import java.util.UUID; import mage.constants.CardType; import mage.constants.Rarity; -import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.common.discard.DiscardTargetEffect; import mage.abilities.keyword.RetraceAbility; import mage.cards.CardImpl; -import mage.constants.TimingRule; import mage.target.TargetPlayer; /** @@ -48,13 +46,12 @@ public class RavensCrime extends CardImpl { super(ownerId, 41, "Raven's Crime", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{B}"); this.expansionSetCode = "EVE"; - this.color.setBlack(true); - // Target player discards a card. this.getSpellAbility().getEffects().add(new DiscardTargetEffect(1)); this.getSpellAbility().getTargets().add(new TargetPlayer()); + // Retrace - this.addAbility(new RetraceAbility(new ManaCostsImpl("{B}"), TimingRule.SORCERY)); + this.addAbility(new RetraceAbility(this)); } public RavensCrime(final RavensCrime card) { diff --git a/Mage.Sets/src/mage/sets/eventide/SavageConception.java b/Mage.Sets/src/mage/sets/eventide/SavageConception.java index 401dd904b39..edeff47740c 100644 --- a/Mage.Sets/src/mage/sets/eventide/SavageConception.java +++ b/Mage.Sets/src/mage/sets/eventide/SavageConception.java @@ -31,11 +31,9 @@ import java.util.UUID; import mage.constants.CardType; import mage.constants.Rarity; -import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.keyword.RetraceAbility; import mage.cards.CardImpl; -import mage.constants.TimingRule; import mage.game.permanent.token.BeastToken; /** @@ -48,12 +46,10 @@ public class SavageConception extends CardImpl { super(ownerId, 75, "Savage Conception", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{3}{G}{G}"); this.expansionSetCode = "EVE"; - this.color.setGreen(true); - // Put a 3/3 green Beast creature token onto the battlefield. this.getSpellAbility().addEffect(new CreateTokenEffect(new BeastToken())); // Retrace - this.addAbility(new RetraceAbility(new ManaCostsImpl("{3}{G}{G}"), TimingRule.SORCERY)); + this.addAbility(new RetraceAbility(this)); } public SavageConception(final SavageConception card) { diff --git a/Mage.Sets/src/mage/sets/eventide/SpittingImage.java b/Mage.Sets/src/mage/sets/eventide/SpittingImage.java index 3bc14b66be1..a9eda3c7deb 100644 --- a/Mage.Sets/src/mage/sets/eventide/SpittingImage.java +++ b/Mage.Sets/src/mage/sets/eventide/SpittingImage.java @@ -29,21 +29,16 @@ package mage.sets.eventide; import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.costs.common.DiscardTargetCost; -import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.OneShotEffect; import mage.abilities.keyword.RetraceAbility; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.Rarity; -import mage.constants.TimingRule; import mage.constants.Zone; -import mage.filter.common.FilterLandCard; import mage.game.Game; import mage.game.permanent.Permanent; import mage.game.permanent.token.EmptyToken; -import mage.target.common.TargetCardInHand; import mage.target.common.TargetCreaturePermanent; import mage.util.CardUtil; @@ -58,15 +53,12 @@ public class SpittingImage extends CardImpl { super(ownerId, 162, "Spitting Image", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{4}{G/U}{G/U}"); this.expansionSetCode = "EVE"; - this.color.setBlue(true); - this.color.setGreen(true); - // Put a token that's a copy of target creature onto the battlefield. this.getSpellAbility().addEffect(new SpittingImageEffect()); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); // Retrace (You may cast this card from your graveyard by discarding a land card in addition to paying its other costs.) - this.addAbility(new RetraceAbility(getSpellAbility().getManaCosts(), TimingRule.SORCERY)); + this.addAbility(new RetraceAbility(this)); } diff --git a/Mage.Sets/src/mage/sets/eventide/SyphonLife.java b/Mage.Sets/src/mage/sets/eventide/SyphonLife.java index 2f465218597..1b0c65a53f2 100644 --- a/Mage.Sets/src/mage/sets/eventide/SyphonLife.java +++ b/Mage.Sets/src/mage/sets/eventide/SyphonLife.java @@ -56,7 +56,7 @@ public class SyphonLife extends CardImpl { this.getSpellAbility().addTarget(new TargetPlayer()); this.getSpellAbility().addEffect(new GainLifeEffect(2)); // Retrace - this.addAbility(new RetraceAbility(new ManaCostsImpl("{1}{B}{B}"), TimingRule.SORCERY)); + this.addAbility(new RetraceAbility(this)); } public SyphonLife(final SyphonLife card) { diff --git a/Mage.Sets/src/mage/sets/eventide/WavesOfAggression.java b/Mage.Sets/src/mage/sets/eventide/WavesOfAggression.java index 8e1380b2827..c41dc5fdfa7 100644 --- a/Mage.Sets/src/mage/sets/eventide/WavesOfAggression.java +++ b/Mage.Sets/src/mage/sets/eventide/WavesOfAggression.java @@ -31,7 +31,6 @@ import java.util.Set; import java.util.UUID; import mage.abilities.Ability; import mage.abilities.DelayedTriggeredAbility; -import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.OneShotEffect; import mage.abilities.keyword.RetraceAbility; import mage.cards.CardImpl; @@ -39,7 +38,6 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Outcome; import mage.constants.Rarity; -import mage.constants.TimingRule; import mage.constants.TurnPhase; import mage.game.Game; import mage.game.events.GameEvent; @@ -58,15 +56,12 @@ public class WavesOfAggression extends CardImpl { super(ownerId, 148, "Waves of Aggression", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{3}{R/W}{R/W}"); this.expansionSetCode = "EVE"; - this.color.setRed(true); - this.color.setWhite(true); - // Untap all creatures that attacked this turn. After this main phase, there is an additional combat phase followed by an additional main phase. this.getSpellAbility().addWatcher(new AttackedThisTurnWatcher()); this.getSpellAbility().addEffect(new WavesOfAggressionUntapEffect()); this.getSpellAbility().addEffect(new WavesOfAggressionAddPhasesEffect()); // Retrace - this.addAbility(new RetraceAbility(new ManaCostsImpl("{3}{R/W}{R/W}"), TimingRule.SORCERY)); + this.addAbility(new RetraceAbility(this)); } public WavesOfAggression(final WavesOfAggression card) { diff --git a/Mage.Sets/src/mage/sets/eventide/WormHarvest.java b/Mage.Sets/src/mage/sets/eventide/WormHarvest.java index 3356d30e0fe..c8b69d3e8ac 100644 --- a/Mage.Sets/src/mage/sets/eventide/WormHarvest.java +++ b/Mage.Sets/src/mage/sets/eventide/WormHarvest.java @@ -29,14 +29,12 @@ package mage.sets.eventide; import java.util.UUID; import mage.MageInt; -import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.keyword.RetraceAbility; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Rarity; -import mage.constants.TimingRule; import mage.filter.common.FilterLandCard; import mage.game.permanent.token.Token; @@ -50,15 +48,12 @@ public class WormHarvest extends CardImpl { super(ownerId, 131, "Worm Harvest", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{2}{B/G}{B/G}{B/G}"); this.expansionSetCode = "EVE"; - this.color.setGreen(true); - this.color.setBlack(true); - // Put a 1/1 black and green Worm creature token onto the battlefield for each land card in your graveyard. CardsInControllerGraveyardCount value = new CardsInControllerGraveyardCount(new FilterLandCard()); this.getSpellAbility().addEffect(new CreateTokenEffect(new WormHarvestToken(), value)); // Retrace - this.addAbility(new RetraceAbility(new ManaCostsImpl("{2}{B/G}{B/G}{B/G}"), TimingRule.SORCERY)); + this.addAbility(new RetraceAbility(this)); } public WormHarvest(final WormHarvest card) { diff --git a/Mage.Sets/src/mage/sets/innistrad/BlasphemousAct.java b/Mage.Sets/src/mage/sets/innistrad/BlasphemousAct.java index 4c39dbfe48e..b5e4ec63f31 100644 --- a/Mage.Sets/src/mage/sets/innistrad/BlasphemousAct.java +++ b/Mage.Sets/src/mage/sets/innistrad/BlasphemousAct.java @@ -36,8 +36,6 @@ import mage.abilities.SpellAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.DamageAllEffect; import mage.abilities.effects.common.cost.CostModificationEffectImpl; -import mage.abilities.keyword.FlashbackAbility; -import mage.abilities.keyword.RetraceAbility; import mage.cards.CardImpl; import mage.constants.CostModificationType; import mage.constants.Duration; diff --git a/Mage.Sets/src/mage/sets/innistrad/RooftopStorm.java b/Mage.Sets/src/mage/sets/innistrad/RooftopStorm.java index 5ebe0a57873..d68c3e38571 100644 --- a/Mage.Sets/src/mage/sets/innistrad/RooftopStorm.java +++ b/Mage.Sets/src/mage/sets/innistrad/RooftopStorm.java @@ -34,7 +34,6 @@ import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.common.cost.CostModificationEffectImpl; import mage.abilities.keyword.FlashbackAbility; -import mage.abilities.keyword.RetraceAbility; import mage.cards.Card; import mage.cards.CardImpl; import mage.game.Game; @@ -42,7 +41,6 @@ import mage.players.Player; import mage.util.CardUtil; import java.util.UUID; -import mage.abilities.ActivatedAbility; /** * @@ -54,8 +52,6 @@ public class RooftopStorm extends CardImpl { super(ownerId, 71, "Rooftop Storm", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{5}{U}"); this.expansionSetCode = "ISD"; - this.color.setBlue(true); - // You may pay {0} rather than pay the mana cost for Zombie creature spells you cast. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new RooftopStormCostReductionEffect())); @@ -95,7 +91,7 @@ class RooftopStormCostReductionEffect extends CostModificationEffectImpl { @Override public boolean applies(Ability abilityToModify, Ability source, Game game) { - if (abilityToModify instanceof SpellAbility || abilityToModify instanceof FlashbackAbility || abilityToModify instanceof RetraceAbility) { + if (abilityToModify instanceof SpellAbility || abilityToModify instanceof FlashbackAbility) { Ability spell = abilityToModify; if (spell.getControllerId().equals(source.getControllerId())) { Card sourceCard = game.getCard(spell.getSourceId()); diff --git a/Mage.Sets/src/mage/sets/ninthedition/DefenseGrid.java b/Mage.Sets/src/mage/sets/ninthedition/DefenseGrid.java index 5163ce36c46..29520e32b07 100644 --- a/Mage.Sets/src/mage/sets/ninthedition/DefenseGrid.java +++ b/Mage.Sets/src/mage/sets/ninthedition/DefenseGrid.java @@ -34,7 +34,6 @@ import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.common.cost.CostModificationEffectImpl; import mage.abilities.keyword.FlashbackAbility; -import mage.abilities.keyword.RetraceAbility; import mage.cards.CardImpl; import mage.game.Game; @@ -85,7 +84,7 @@ class DefenseGridCostModificationEffect extends CostModificationEffectImpl { @Override public boolean applies(Ability abilityToModify, Ability source, Game game) { - if (abilityToModify instanceof SpellAbility || abilityToModify instanceof FlashbackAbility || abilityToModify instanceof RetraceAbility) { + if (abilityToModify instanceof SpellAbility || abilityToModify instanceof FlashbackAbility) { if(!abilityToModify.getControllerId().equals(game.getActivePlayerId())) { return true; } diff --git a/Mage.Sets/src/mage/sets/planechase2012/ElderwoodScion.java b/Mage.Sets/src/mage/sets/planechase2012/ElderwoodScion.java index 8b6f9cb1d6b..b1821c235af 100644 --- a/Mage.Sets/src/mage/sets/planechase2012/ElderwoodScion.java +++ b/Mage.Sets/src/mage/sets/planechase2012/ElderwoodScion.java @@ -37,7 +37,6 @@ import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.cost.CostModificationEffectImpl; import mage.abilities.keyword.FlashbackAbility; import mage.abilities.keyword.LifelinkAbility; -import mage.abilities.keyword.RetraceAbility; import mage.abilities.keyword.TrampleAbility; import mage.cards.CardImpl; import mage.constants.Duration; @@ -60,8 +59,6 @@ public class ElderwoodScion extends CardImpl { this.expansionSetCode = "PC2"; this.subtype.add("Elemental"); - this.color.setGreen(true); - this.color.setWhite(true); this.power = new MageInt(4); this.toughness = new MageInt(4); @@ -107,7 +104,7 @@ class ElderwoodScionCostReductionEffect extends CostModificationEffectImpl { @Override public boolean applies(Ability abilityToModify, Ability source, Game game) { - if (abilityToModify instanceof SpellAbility || abilityToModify instanceof FlashbackAbility || abilityToModify instanceof RetraceAbility) { + if (abilityToModify instanceof SpellAbility || abilityToModify instanceof FlashbackAbility) { if (abilityToModify.getControllerId().equals(source.getControllerId())) { for (Target target :abilityToModify.getTargets()) { for (UUID targetUUID :target.getTargets()) { diff --git a/Mage.Sets/src/mage/sets/prophecy/AvatarOfHope.java b/Mage.Sets/src/mage/sets/prophecy/AvatarOfHope.java index 4910c80aa17..13716f9a91c 100644 --- a/Mage.Sets/src/mage/sets/prophecy/AvatarOfHope.java +++ b/Mage.Sets/src/mage/sets/prophecy/AvatarOfHope.java @@ -40,7 +40,6 @@ import mage.abilities.effects.common.cost.CostModificationEffectImpl; import mage.abilities.effects.common.combat.CanBlockAdditionalCreatureEffect; import mage.abilities.keyword.FlashbackAbility; import mage.abilities.keyword.FlyingAbility; -import mage.abilities.keyword.RetraceAbility; import mage.cards.CardImpl; import mage.constants.Duration; import mage.constants.Outcome; @@ -63,7 +62,6 @@ public class AvatarOfHope extends CardImpl { this.expansionSetCode = "PCY"; this.subtype.add("Avatar"); - this.color.setWhite(true); this.power = new MageInt(4); this.toughness = new MageInt(9); @@ -146,7 +144,7 @@ class AdjustingCostsEffect extends CostModificationEffectImpl { @Override public boolean applies(Ability abilityToModify, Ability source, Game game) { - if ((abilityToModify instanceof SpellAbility || abilityToModify instanceof FlashbackAbility || abilityToModify instanceof RetraceAbility) + if ((abilityToModify instanceof SpellAbility || abilityToModify instanceof FlashbackAbility) && abilityToModify.getSourceId().equals(source.getSourceId())) { return true; } diff --git a/Mage.Sets/src/mage/sets/returntoravnica/RakdosLordOfRiots.java b/Mage.Sets/src/mage/sets/returntoravnica/RakdosLordOfRiots.java index fdf73f6d5e2..91f26ae1ab5 100644 --- a/Mage.Sets/src/mage/sets/returntoravnica/RakdosLordOfRiots.java +++ b/Mage.Sets/src/mage/sets/returntoravnica/RakdosLordOfRiots.java @@ -37,7 +37,6 @@ import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; import mage.abilities.effects.common.cost.CostModificationEffectImpl; import mage.abilities.keyword.FlashbackAbility; import mage.abilities.keyword.FlyingAbility; -import mage.abilities.keyword.RetraceAbility; import mage.abilities.keyword.TrampleAbility; import mage.cards.Card; import mage.cards.CardImpl; @@ -63,8 +62,7 @@ public class RakdosLordOfRiots extends CardImpl { this.expansionSetCode = "RTR"; this.supertype.add("Legendary"); this.subtype.add("Demon"); - this.color.setBlack(true); - this.color.setRed(true); + this.power = new MageInt(6); this.toughness = new MageInt(6); @@ -153,7 +151,7 @@ class RakdosLordOfRiotsCostReductionEffect extends CostModificationEffectImpl { @Override public boolean applies(Ability abilityToModify, Ability source, Game game) { - if (abilityToModify instanceof SpellAbility || abilityToModify instanceof FlashbackAbility || abilityToModify instanceof RetraceAbility) { + if (abilityToModify instanceof SpellAbility || abilityToModify instanceof FlashbackAbility) { Card sourceCard = game.getCard(abilityToModify.getSourceId()); if (sourceCard != null && abilityToModify.getControllerId().equals(source.getControllerId()) && (sourceCard.getCardType().contains(CardType.CREATURE))) { return true; diff --git a/Mage.Sets/src/mage/sets/scarsofmirrodin/SemblanceAnvil.java b/Mage.Sets/src/mage/sets/scarsofmirrodin/SemblanceAnvil.java index c7a05c7f746..779e53a1cc9 100644 --- a/Mage.Sets/src/mage/sets/scarsofmirrodin/SemblanceAnvil.java +++ b/Mage.Sets/src/mage/sets/scarsofmirrodin/SemblanceAnvil.java @@ -35,7 +35,6 @@ import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.cost.CostModificationEffectImpl; import mage.abilities.effects.OneShotEffect; import mage.abilities.keyword.FlashbackAbility; -import mage.abilities.keyword.RetraceAbility; import mage.cards.Card; import mage.cards.CardImpl; import mage.filter.FilterCard; @@ -136,7 +135,7 @@ class SemblanceAnvilCostReductionEffect extends CostModificationEffectImpl { @Override public boolean applies(Ability abilityToModify, Ability source, Game game) { - if (abilityToModify instanceof SpellAbility || abilityToModify instanceof FlashbackAbility || abilityToModify instanceof RetraceAbility) { + if (abilityToModify instanceof SpellAbility || abilityToModify instanceof FlashbackAbility) { Card sourceCard = game.getCard(abilityToModify.getSourceId()); if (sourceCard != null && sourceCard.getOwnerId().equals(source.getControllerId())) { Permanent permanent = game.getPermanent(source.getSourceId()); diff --git a/Mage.Sets/src/mage/sets/timespiral/LocketOfYesterdays.java b/Mage.Sets/src/mage/sets/timespiral/LocketOfYesterdays.java index f58d010281e..75b0398abf0 100644 --- a/Mage.Sets/src/mage/sets/timespiral/LocketOfYesterdays.java +++ b/Mage.Sets/src/mage/sets/timespiral/LocketOfYesterdays.java @@ -36,7 +36,6 @@ import mage.abilities.SpellAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.cost.CostModificationEffectImpl; import mage.abilities.keyword.FlashbackAbility; -import mage.abilities.keyword.RetraceAbility; import mage.cards.Card; import mage.cards.CardImpl; import mage.game.Game; @@ -100,7 +99,7 @@ class LocketOfYesterdaysCostReductionEffect extends CostModificationEffectImpl { @Override public boolean applies(Ability abilityToModify, Ability source, Game game) { if (abilityToModify.getControllerId().equals(source.getControllerId()) && - (abilityToModify instanceof SpellAbility || abilityToModify instanceof FlashbackAbility || abilityToModify instanceof RetraceAbility)) { + (abilityToModify instanceof SpellAbility || abilityToModify instanceof FlashbackAbility)) { return true; } return false; diff --git a/Mage.Sets/src/mage/sets/worldwake/LodestoneGolem.java b/Mage.Sets/src/mage/sets/worldwake/LodestoneGolem.java index d749047a133..f94ee11bf3c 100644 --- a/Mage.Sets/src/mage/sets/worldwake/LodestoneGolem.java +++ b/Mage.Sets/src/mage/sets/worldwake/LodestoneGolem.java @@ -27,7 +27,7 @@ */ package mage.sets.worldwake; -import mage.constants.*; +import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.SpellAbility; @@ -35,13 +35,16 @@ import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.common.cost.CostModificationEffectImpl; import mage.abilities.keyword.FlashbackAbility; -import mage.abilities.keyword.RetraceAbility; import mage.cards.Card; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.CostModificationType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; import mage.game.Game; -import java.util.UUID; - /** * * @author jeffwadsworth @@ -90,7 +93,7 @@ class LodestoneGolemCostReductionEffect extends CostModificationEffectImpl { @Override public boolean applies(Ability abilityToModify, Ability source, Game game) { - if (abilityToModify instanceof SpellAbility || abilityToModify instanceof FlashbackAbility || abilityToModify instanceof RetraceAbility) { + if (abilityToModify instanceof SpellAbility || abilityToModify instanceof FlashbackAbility) { Card card = game.getCard(abilityToModify.getSourceId()); if (card != null && !card.getCardType().contains(CardType.ARTIFACT)) { return true; diff --git a/Mage.Sets/src/mage/sets/worldwake/StoneIdolTrap.java b/Mage.Sets/src/mage/sets/worldwake/StoneIdolTrap.java index bc6f9e86912..2bab309e9cc 100644 --- a/Mage.Sets/src/mage/sets/worldwake/StoneIdolTrap.java +++ b/Mage.Sets/src/mage/sets/worldwake/StoneIdolTrap.java @@ -37,8 +37,6 @@ import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbil import mage.abilities.effects.common.cost.CostModificationEffectImpl; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.ExileTargetEffect; -import mage.abilities.keyword.FlashbackAbility; -import mage.abilities.keyword.RetraceAbility; import mage.abilities.keyword.TrampleAbility; import mage.cards.CardImpl; import mage.filter.common.FilterCreaturePermanent; diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/RetraceTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/RetraceTest.java new file mode 100644 index 00000000000..8a056cbecfd --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/RetraceTest.java @@ -0,0 +1,125 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package org.mage.test.cards.abilities.keywords; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ + +public class RetraceTest extends CardTestPlayerBase { + + /** + * 702.78. Retrace + * 702.78a Retrace appears on some instants and sorceries. It represents a static ability + * that functions while the card is in a player's graveyard. "Retrace" means "You may cast + * this card from your graveyard by discarding a land card as an additional cost to cast it." + * Casting a spell using its retrace ability follows the rules for paying additional costs + * in rules 601.2b and 601.2e-g. + */ + + + @Test + public void SimpleRetrace() { + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1); + // Target player discards a card. + // Retrace + addCard(Zone.GRAVEYARD, playerA, "Raven's Crime"); + addCard(Zone.HAND, playerA, "Swamp"); + + addCard(Zone.HAND, playerB, "Silvercoat Lion", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Raven's Crime", playerB); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertGraveyardCount(playerA,"Raven's Crime", 1); + assertGraveyardCount(playerA,"Swamp", 1); + + assertGraveyardCount(playerB,"Silvercoat Lion", 1); + } + + /** + * Test that it does cost {B}{1} + land discard + */ + @Test + public void RetraceCostIncreaseCantPay() { + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1); + // Target player discards a card. + // Retrace + addCard(Zone.GRAVEYARD, playerA, "Raven's Crime"); + addCard(Zone.HAND, playerA, "Swamp"); + + // // Noncreature spells cost {1} more to cast. + addCard(Zone.BATTLEFIELD, playerB, "Thalia, Guardian of Thraben", 1); + addCard(Zone.HAND, playerB, "Silvercoat Lion", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Raven's Crime", playerB); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertGraveyardCount(playerA,"Raven's Crime", 1); + assertGraveyardCount(playerA,"Swamp", 0); // because not enough mana + + assertGraveyardCount(playerB,"Silvercoat Lion", 0); // because not enough mana + } + + /** + * Test that it does cost {B}{1} + land discard + */ + @Test + public void RetraceCostIncreaseCanPay() { + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2); + // Target player discards a card. + // Retrace + addCard(Zone.GRAVEYARD, playerA, "Raven's Crime"); + addCard(Zone.HAND, playerA, "Swamp"); + + // // Noncreature spells cost {1} more to cast. + addCard(Zone.BATTLEFIELD, playerB, "Thalia, Guardian of Thraben", 1); + addCard(Zone.HAND, playerB, "Silvercoat Lion", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Raven's Crime", playerB); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertGraveyardCount(playerA,"Raven's Crime", 1); + assertGraveyardCount(playerA,"Swamp", 1); + + assertGraveyardCount(playerB,"Silvercoat Lion", 1); + } + +} diff --git a/Mage/src/mage/abilities/keyword/RetraceAbility.java b/Mage/src/mage/abilities/keyword/RetraceAbility.java index 22a1fe7f538..4c26c31b6cd 100644 --- a/Mage/src/mage/abilities/keyword/RetraceAbility.java +++ b/Mage/src/mage/abilities/keyword/RetraceAbility.java @@ -27,32 +27,31 @@ */ package mage.abilities.keyword; -import mage.abilities.Ability; -import mage.abilities.ActivatedAbilityImpl; -import mage.abilities.costs.Cost; +import mage.abilities.SpellAbility; import mage.abilities.costs.common.DiscardTargetCost; -import mage.abilities.effects.OneShotEffect; import mage.cards.Card; -import mage.constants.Outcome; -import mage.constants.TimingRule; +import mage.constants.SpellAbilityType; import mage.constants.Zone; import mage.filter.common.FilterLandCard; -import mage.game.Game; -import mage.players.Player; import mage.target.common.TargetCardInHand; - /** * - * @author Plopman + * @author LevelX2 */ -public class RetraceAbility extends ActivatedAbilityImpl { - public RetraceAbility(Cost cost, TimingRule timingRule) { - super(Zone.GRAVEYARD, new RetraceEffect(), cost); - super.addCost(new DiscardTargetCost(new TargetCardInHand(new FilterLandCard()))); - this.timing = timingRule; - this.usesStack = false; +public class RetraceAbility extends SpellAbility { + + public RetraceAbility(Card card) { + super(card.getManaCost(), card.getName() + " with retrace", Zone.GRAVEYARD, SpellAbilityType.BASE_ALTERNATE); + this.getCosts().addAll(card.getSpellAbility().getCosts().copy()); + this.addCost(new DiscardTargetCost(new TargetCardInHand(new FilterLandCard()))); + this.getEffects().addAll(card.getSpellAbility().getEffects().copy()); + this.getTargets().addAll(card.getSpellAbility().getTargets().copy()); + this.getChoices().addAll(card.getSpellAbility().getChoices().copy()); + this.spellAbilityType = SpellAbilityType.BASE_ALTERNATE; + this.timing = card.getSpellAbility().getTiming(); + } public RetraceAbility(final RetraceAbility ability) { @@ -64,41 +63,13 @@ public class RetraceAbility extends ActivatedAbilityImpl { return new RetraceAbility(this); } + @Override + public String getRule(boolean all) { + return getRule(); + } + @Override public String getRule() { return "Retrace (You may cast this card from your graveyard by discarding a land card in addition to paying its other costs.)"; } } - -class RetraceEffect extends OneShotEffect { - - public RetraceEffect() { - super(Outcome.Benefit); - staticText = ""; - } - - public RetraceEffect(final RetraceEffect effect) { - super(effect); - } - - @Override - public RetraceEffect copy() { - return new RetraceEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Card card = (Card) game.getObject(source.getSourceId()); - if (card != null) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - card.getSpellAbility().clear(); - int amount = source.getManaCostsToPay().getX(); - card.getSpellAbility().getManaCostsToPay().setX(amount); - return controller.cast(card.getSpellAbility(), game, true); - } - } - return false; - } -} -