diff --git a/Mage.Sets/src/mage/cards/c/ChandraTheFirebrand.java b/Mage.Sets/src/mage/cards/c/ChandraTheFirebrand.java index aa85c501d1..3138d8f780 100644 --- a/Mage.Sets/src/mage/cards/c/ChandraTheFirebrand.java +++ b/Mage.Sets/src/mage/cards/c/ChandraTheFirebrand.java @@ -1,27 +1,19 @@ - package mage.cards.c; -import java.util.UUID; -import mage.abilities.DelayedTriggeredAbility; import mage.abilities.LoyaltyAbility; -import mage.abilities.effects.Effect; -import mage.abilities.effects.common.CopyTargetSpellEffect; +import mage.abilities.common.delayed.CopyNextSpellDelayedTriggeredAbility; import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; import mage.abilities.effects.common.DamageTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Duration; import mage.constants.SuperType; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.stack.Spell; import mage.target.common.TargetAnyTarget; -import mage.target.targetpointer.FixedTarget; + +import java.util.UUID; /** - * * @author Loki */ public final class ChandraTheFirebrand extends CardImpl { @@ -39,9 +31,9 @@ public final class ChandraTheFirebrand extends CardImpl { this.addAbility(ability1); // -2: When you cast your next instant or sorcery spell this turn, copy that spell. You may choose new targets for the copy. - Effect effect = new CreateDelayedTriggeredAbilityEffect(new ChandraTheFirebrandAbility()); - effect.setText("When you cast your next instant or sorcery spell this turn, copy that spell. You may choose new targets for the copy"); - this.addAbility(new LoyaltyAbility(effect, -2)); + this.addAbility(new LoyaltyAbility( + new CreateDelayedTriggeredAbilityEffect(new CopyNextSpellDelayedTriggeredAbility()), -2 + )); // -6: Chandra, the Firebrand deals 6 damage to each of up to six target creatures and/or players LoyaltyAbility ability2 = new LoyaltyAbility(new DamageTargetEffect(6, true, "each of up to six targets"), -6); @@ -57,45 +49,4 @@ public final class ChandraTheFirebrand extends CardImpl { public ChandraTheFirebrand copy() { return new ChandraTheFirebrand(this); } - -} - -class ChandraTheFirebrandAbility extends DelayedTriggeredAbility { - - ChandraTheFirebrandAbility() { - super(new CopyTargetSpellEffect(true), Duration.EndOfTurn); - } - - ChandraTheFirebrandAbility(final ChandraTheFirebrandAbility ability) { - super(ability); - } - - @Override - public ChandraTheFirebrandAbility copy() { - return new ChandraTheFirebrandAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.SPELL_CAST; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (event.getPlayerId().equals(this.getControllerId())) { - Spell spell = game.getStack().getSpell(event.getTargetId()); - if (spell != null && spell.isInstantOrSorcery(game)) { - for (Effect effect : this.getEffects()) { - effect.setTargetPointer(new FixedTarget(event.getTargetId())); - } - return true; - } - } - return false; - } - - @Override - public String getRule() { - return "When you cast your next instant or sorcery spell this turn, copy that spell. You may choose new targets for the copy."; - } } diff --git a/Mage.Sets/src/mage/cards/d/Doublecast.java b/Mage.Sets/src/mage/cards/d/Doublecast.java index 3ed707541c..bc1e8171f2 100644 --- a/Mage.Sets/src/mage/cards/d/Doublecast.java +++ b/Mage.Sets/src/mage/cards/d/Doublecast.java @@ -1,16 +1,10 @@ package mage.cards.d; -import mage.abilities.DelayedTriggeredAbility; -import mage.abilities.effects.common.CopyTargetSpellEffect; +import mage.abilities.common.delayed.CopyNextSpellDelayedTriggeredAbility; import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Duration; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.stack.Spell; -import mage.target.targetpointer.FixedTarget; import java.util.UUID; @@ -23,11 +17,7 @@ public final class Doublecast extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{R}{R}"); // When you cast your next instant or sorcery spell this turn, copy that spell. You may choose new targets for the copy. - this.getSpellAbility().addEffect( - new CreateDelayedTriggeredAbilityEffect(new DoublecastAbility()) - .setText("When you cast your next instant or sorcery spell this turn, " - + "copy that spell. You may choose new targets for the copy") - ); + this.getSpellAbility().addEffect(new CreateDelayedTriggeredAbilityEffect(new CopyNextSpellDelayedTriggeredAbility())); } private Doublecast(final Doublecast card) { @@ -39,43 +29,3 @@ public final class Doublecast extends CardImpl { return new Doublecast(this); } } - -class DoublecastAbility extends DelayedTriggeredAbility { - - DoublecastAbility() { - super(new CopyTargetSpellEffect(true), Duration.EndOfTurn); - } - - private DoublecastAbility(final DoublecastAbility ability) { - super(ability); - } - - @Override - public DoublecastAbility copy() { - return new DoublecastAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.SPELL_CAST; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (!isControlledBy(event.getPlayerId())) { - return false; - } - Spell spell = game.getStack().getSpell(event.getTargetId()); - if (spell == null || !spell.isInstantOrSorcery(game)) { - return false; - } - this.getEffects().setTargetPointer(new FixedTarget(event.getTargetId())); - return true; - } - - @Override - public String getRule() { - return "When you cast your next instant or sorcery spell this turn, " - + "copy that spell. You may choose new targets for the copy."; - } -} diff --git a/Mage.Sets/src/mage/cards/d/DualStrike.java b/Mage.Sets/src/mage/cards/d/DualStrike.java index 0423b5e31d..2c15ac1ab3 100644 --- a/Mage.Sets/src/mage/cards/d/DualStrike.java +++ b/Mage.Sets/src/mage/cards/d/DualStrike.java @@ -1,17 +1,15 @@ package mage.cards.d; -import mage.abilities.DelayedTriggeredAbility; -import mage.abilities.effects.common.CopyTargetSpellEffect; +import mage.abilities.common.delayed.CopyNextSpellDelayedTriggeredAbility; import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; import mage.abilities.keyword.ForetellAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Duration; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.stack.Spell; -import mage.target.targetpointer.FixedTarget; +import mage.constants.ComparisonType; +import mage.filter.FilterSpell; +import mage.filter.common.FilterInstantOrSorcerySpell; +import mage.filter.predicate.mageobject.ManaValuePredicate; import java.util.UUID; @@ -20,11 +18,20 @@ import java.util.UUID; */ public final class DualStrike extends CardImpl { + private static final FilterSpell filter + = new FilterInstantOrSorcerySpell("instant or sorcery spell with mana value 4 or less"); + + static { + filter.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, 5)); + } + public DualStrike(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{R}{R}"); // When you cast your next instant or sorcery spell with converted mana cost 4 or less this turn, copy that spell. You may choose new targets for the copy. - this.getSpellAbility().addEffect(new CreateDelayedTriggeredAbilityEffect(new DualStrikeAbility())); + this.getSpellAbility().addEffect(new CreateDelayedTriggeredAbilityEffect( + new CopyNextSpellDelayedTriggeredAbility(filter) + )); // Foretell {R} this.addAbility(new ForetellAbility(this, "{R}")); @@ -39,46 +46,3 @@ public final class DualStrike extends CardImpl { return new DualStrike(this); } } - -class DualStrikeAbility extends DelayedTriggeredAbility { - - DualStrikeAbility() { - super(new CopyTargetSpellEffect(true), Duration.EndOfTurn); - } - - private DualStrikeAbility(final DualStrikeAbility ability) { - super(ability); - } - - @Override - public DualStrikeAbility copy() { - return new DualStrikeAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.SPELL_CAST; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (!this.isControlledBy(event.getPlayerId())) { - return false; - } - Spell spell = game.getStack().getSpell(event.getTargetId()); - if (spell == null - || !spell.isInstantOrSorcery(game) - || spell.getManaValue() > 4) { - return false; - } - this.getEffects().setTargetPointer(new FixedTarget(event.getTargetId())); - return true; - } - - @Override - public String getRule() { - return "When you cast your next instant or sorcery spell " + - "with mana value 4 or less this turn, " + - "copy that spell. You may choose new targets for the copy."; - } -} diff --git a/Mage.Sets/src/mage/cards/g/GalvanicIteration.java b/Mage.Sets/src/mage/cards/g/GalvanicIteration.java index 892dbebc04..e175f31b8c 100644 --- a/Mage.Sets/src/mage/cards/g/GalvanicIteration.java +++ b/Mage.Sets/src/mage/cards/g/GalvanicIteration.java @@ -1,19 +1,12 @@ package mage.cards.g; -import mage.abilities.DelayedTriggeredAbility; +import mage.abilities.common.delayed.CopyNextSpellDelayedTriggeredAbility; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.common.CopyTargetSpellEffect; import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; import mage.abilities.keyword.FlashbackAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.TimingRule; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.stack.Spell; -import mage.target.targetpointer.FixedTarget; import java.util.UUID; @@ -26,7 +19,7 @@ public final class GalvanicIteration extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{U}{R}"); // When you cast your next instant or sorcery spell this turn, copy that spell. You may choose new targets for the copy. - this.getSpellAbility().addEffect(new CreateDelayedTriggeredAbilityEffect(new GalvanicIterationAbility())); + this.getSpellAbility().addEffect(new CreateDelayedTriggeredAbilityEffect(new CopyNextSpellDelayedTriggeredAbility())); // Flashback {1}{U}{R} this.addAbility(new FlashbackAbility(this, new ManaCostsImpl<>("{1}{U}{R}"))); @@ -41,43 +34,3 @@ public final class GalvanicIteration extends CardImpl { return new GalvanicIteration(this); } } - -class GalvanicIterationAbility extends DelayedTriggeredAbility { - - GalvanicIterationAbility() { - super(new CopyTargetSpellEffect(true), Duration.EndOfTurn); - } - - private GalvanicIterationAbility(final GalvanicIterationAbility ability) { - super(ability); - } - - @Override - public GalvanicIterationAbility copy() { - return new GalvanicIterationAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.SPELL_CAST; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (!isControlledBy(event.getPlayerId())) { - return false; - } - Spell spell = game.getStack().getSpell(event.getTargetId()); - if (spell == null || !spell.isInstantOrSorcery(game)) { - return false; - } - this.getEffects().setTargetPointer(new FixedTarget(event.getTargetId())); - return true; - } - - @Override - public String getRule() { - return "When you cast your next instant or sorcery spell this turn, " - + "copy that spell. You may choose new targets for the copy."; - } -} diff --git a/Mage.Sets/src/mage/cards/r/RalStormConduit.java b/Mage.Sets/src/mage/cards/r/RalStormConduit.java index caa6a54e3d..06ead5f08d 100644 --- a/Mage.Sets/src/mage/cards/r/RalStormConduit.java +++ b/Mage.Sets/src/mage/cards/r/RalStormConduit.java @@ -1,21 +1,21 @@ package mage.cards.r; -import mage.abilities.DelayedTriggeredAbility; import mage.abilities.LoyaltyAbility; import mage.abilities.TriggeredAbilityImpl; -import mage.abilities.effects.Effect; -import mage.abilities.effects.common.CopyTargetSpellEffect; +import mage.abilities.common.delayed.CopyNextSpellDelayedTriggeredAbility; import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.keyword.ScryEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.stack.Spell; import mage.target.common.TargetOpponentOrPlaneswalker; -import mage.target.targetpointer.FixedTarget; import java.util.UUID; @@ -38,11 +38,7 @@ public final class RalStormConduit extends CardImpl { this.addAbility(new LoyaltyAbility(new ScryEffect(1, false), 2)); // -2: When you cast your next instant or sorcery spell this turn, copy that spell. You may choose new targets for the copy. - this.addAbility(new LoyaltyAbility(new CreateDelayedTriggeredAbilityEffect( - new RalStormConduitDelayedTriggeredAbility() - ).setText("When you cast your next instant or sorcery spell this turn, " + - "copy that spell. You may choose new targets for the copy" - ), -2)); + this.addAbility(new LoyaltyAbility(new CreateDelayedTriggeredAbilityEffect(new CopyNextSpellDelayedTriggeredAbility()), -2)); } private RalStormConduit(final RalStormConduit card) { @@ -94,44 +90,3 @@ class RalStormConduitTriggeredAbility extends TriggeredAbilityImpl { "{this} deals 1 damage to target opponent or planeswalker."; } } - -class RalStormConduitDelayedTriggeredAbility extends DelayedTriggeredAbility { - - RalStormConduitDelayedTriggeredAbility() { - super(new CopyTargetSpellEffect(true), Duration.EndOfTurn); - } - - private RalStormConduitDelayedTriggeredAbility(final RalStormConduitDelayedTriggeredAbility ability) { - super(ability); - } - - @Override - public RalStormConduitDelayedTriggeredAbility copy() { - return new RalStormConduitDelayedTriggeredAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.SPELL_CAST; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (event.getPlayerId().equals(this.getControllerId())) { - Spell spell = game.getStack().getSpell(event.getTargetId()); - if (spell != null && spell.isInstantOrSorcery(game)) { - for (Effect effect : this.getEffects()) { - effect.setTargetPointer(new FixedTarget(event.getTargetId())); - } - return true; - } - } - return false; - } - - @Override - public String getRule() { - return "When you cast your next instant or sorcery spell this turn, " + - "copy that spell. You may choose new targets for the copy."; - } -} diff --git a/Mage.Sets/src/mage/cards/t/TeachByExample.java b/Mage.Sets/src/mage/cards/t/TeachByExample.java index 2783df7c27..9eb9a5602d 100644 --- a/Mage.Sets/src/mage/cards/t/TeachByExample.java +++ b/Mage.Sets/src/mage/cards/t/TeachByExample.java @@ -1,16 +1,10 @@ package mage.cards.t; -import mage.abilities.DelayedTriggeredAbility; -import mage.abilities.effects.common.CopyTargetSpellEffect; +import mage.abilities.common.delayed.CopyNextSpellDelayedTriggeredAbility; import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Duration; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.stack.Spell; -import mage.target.targetpointer.FixedTarget; import java.util.UUID; @@ -23,11 +17,7 @@ public final class TeachByExample extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{U/R}{U/R}"); // When you cast your next instant or sorcery spell this turn, copy that spell. You may choose new targets for the copy. - this.getSpellAbility().addEffect( - new CreateDelayedTriggeredAbilityEffect(new TeachByExampleAbility()) - .setText("When you cast your next instant or sorcery spell this turn, " - + "copy that spell. You may choose new targets for the copy") - ); + this.getSpellAbility().addEffect(new CreateDelayedTriggeredAbilityEffect(new CopyNextSpellDelayedTriggeredAbility())); } private TeachByExample(final TeachByExample card) { @@ -39,43 +29,3 @@ public final class TeachByExample extends CardImpl { return new TeachByExample(this); } } - -class TeachByExampleAbility extends DelayedTriggeredAbility { - - TeachByExampleAbility() { - super(new CopyTargetSpellEffect(true), Duration.EndOfTurn); - } - - private TeachByExampleAbility(final TeachByExampleAbility ability) { - super(ability); - } - - @Override - public TeachByExampleAbility copy() { - return new TeachByExampleAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.SPELL_CAST; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (!isControlledBy(event.getPlayerId())) { - return false; - } - Spell spell = game.getStack().getSpell(event.getTargetId()); - if (spell == null || !spell.isInstantOrSorcery(game)) { - return false; - } - this.getEffects().setTargetPointer(new FixedTarget(event.getTargetId())); - return true; - } - - @Override - public String getRule() { - return "When you cast your next instant or sorcery spell this turn, " - + "copy that spell. You may choose new targets for the copy."; - } -} diff --git a/Mage.Sets/src/mage/cards/t/Twinferno.java b/Mage.Sets/src/mage/cards/t/Twinferno.java new file mode 100644 index 0000000000..b47f50fea1 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/Twinferno.java @@ -0,0 +1,39 @@ +package mage.cards.t; + +import mage.abilities.Mode; +import mage.abilities.common.delayed.CopyNextSpellDelayedTriggeredAbility; +import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.DoubleStrikeAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.target.common.TargetControlledCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class Twinferno extends CardImpl { + + public Twinferno(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{R}"); + + // Choose one -- + // * When you cast your next instant or sorcery spell this turn, copy that spell. You may choose new targets for the copy. + this.getSpellAbility().addEffect(new CreateDelayedTriggeredAbilityEffect(new CopyNextSpellDelayedTriggeredAbility())); + + // * Target creature you control gains double strike until end of turn. + this.getSpellAbility().addMode(new Mode(new GainAbilityTargetEffect(DoubleStrikeAbility.getInstance())).addTarget(new TargetControlledCreaturePermanent())); + } + + private Twinferno(final Twinferno card) { + super(card); + } + + @Override + public Twinferno copy() { + return new Twinferno(this); + } +} diff --git a/Mage.Sets/src/mage/sets/DominariaUnited.java b/Mage.Sets/src/mage/sets/DominariaUnited.java index 3b384b4847..b1491e5005 100644 --- a/Mage.Sets/src/mage/sets/DominariaUnited.java +++ b/Mage.Sets/src/mage/sets/DominariaUnited.java @@ -223,6 +223,7 @@ public final class DominariaUnited extends ExpansionSet { cards.add(new SetCardInfo("Tori D'Avenant, Fury Rider", 223, Rarity.UNCOMMON, mage.cards.t.ToriDAvenantFuryRider.class)); cards.add(new SetCardInfo("Toxic Abomination", 112, Rarity.COMMON, mage.cards.t.ToxicAbomination.class)); cards.add(new SetCardInfo("Tura Kennerud, Skyknight", 224, Rarity.UNCOMMON, mage.cards.t.TuraKennerudSkyknight.class)); + cards.add(new SetCardInfo("Twinferno", 149, Rarity.UNCOMMON, mage.cards.t.Twinferno.class)); cards.add(new SetCardInfo("Urza Assembles the Titans", 37, Rarity.RARE, mage.cards.u.UrzaAssemblesTheTitans.class)); cards.add(new SetCardInfo("Uurg, Spawn of Turg", 225, Rarity.UNCOMMON, mage.cards.u.UurgSpawnOfTurg.class)); cards.add(new SetCardInfo("Valiant Veteran", 38, Rarity.RARE, mage.cards.v.ValiantVeteran.class)); diff --git a/Mage/src/main/java/mage/abilities/common/delayed/CopyNextSpellDelayedTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/delayed/CopyNextSpellDelayedTriggeredAbility.java new file mode 100644 index 0000000000..5a263b8a5a --- /dev/null +++ b/Mage/src/main/java/mage/abilities/common/delayed/CopyNextSpellDelayedTriggeredAbility.java @@ -0,0 +1,62 @@ +package mage.abilities.common.delayed; + +import mage.abilities.DelayedTriggeredAbility; +import mage.abilities.effects.common.CopyTargetSpellEffect; +import mage.constants.Duration; +import mage.filter.FilterSpell; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.stack.Spell; +import mage.target.targetpointer.FixedTarget; + +/** + * @author TheElk801 + */ +public class CopyNextSpellDelayedTriggeredAbility extends DelayedTriggeredAbility { + + private final FilterSpell filter; + + public CopyNextSpellDelayedTriggeredAbility() { + this(StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY); + } + + public CopyNextSpellDelayedTriggeredAbility(FilterSpell filter) { + super(new CopyTargetSpellEffect(true), Duration.EndOfTurn); + this.filter = filter; + } + + private CopyNextSpellDelayedTriggeredAbility(final CopyNextSpellDelayedTriggeredAbility ability) { + super(ability); + this.filter = ability.filter; + } + + @Override + public CopyNextSpellDelayedTriggeredAbility copy() { + return new CopyNextSpellDelayedTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.SPELL_CAST; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (!isControlledBy(event.getPlayerId())) { + return false; + } + Spell spell = game.getStack().getSpell(event.getTargetId()); + if (spell == null || !filter.match(spell, getControllerId(), this, game)) { + return false; + } + this.getEffects().setTargetPointer(new FixedTarget(event.getTargetId())); + return true; + } + + @Override + public String getRule() { + return "When you cast your next " + filter.getMessage() + " this turn, " + + "copy that spell. You may choose new targets for the copy."; + } +}