[DMU] Implemented Twinferno (#9437)

* create common class for copying the next spell cast

* [DMU] Implemented Twinferno

* add filter to CopyNextSpellDelayedTriggeredAbility
This commit is contained in:
Evan Kranzler 2022-08-29 18:51:22 -04:00 committed by GitHub
parent 697586a552
commit a7b7f1bbe3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 135 additions and 310 deletions

View file

@ -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.";
}
}

View file

@ -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.";
}
}

View file

@ -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.";
}
}

View file

@ -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.";
}
}

View file

@ -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.";
}
}

View file

@ -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.";
}
}

View file

@ -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);
}
}

View file

@ -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));

View file

@ -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.";
}
}