implement Lava Burst

This commit is contained in:
Steven Knipe 2025-10-31 22:38:42 -07:00 committed by xenohedron
parent 865b05781e
commit f10a08e6aa
5 changed files with 125 additions and 0 deletions

View file

@ -0,0 +1,86 @@
package mage.cards.l;
import mage.abilities.Ability;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.RedirectionEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetAnyTarget;
import mage.util.CardUtil;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
/**
*
* @author notgreat
*/
public final class LavaBurst extends CardImpl {
public LavaBurst(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{R}");
// Lava Burst deals X damage to any target. If Lava Burst would deal damage to a creature, that damage can't be prevented or dealt instead to another creature or player.
this.getSpellAbility().addEffect(new LavaBurstEffect());
this.getSpellAbility().addTarget(new TargetAnyTarget());
}
private LavaBurst(final LavaBurst card) {
super(card);
}
@Override
public LavaBurst copy() {
return new LavaBurst(this);
}
}
class LavaBurstEffect extends OneShotEffect {
LavaBurstEffect() {
super(Outcome.Damage);
staticText = "{this} deals X damage to any target. If {this} would deal damage to a creature, that damage can't be prevented or dealt instead to another permanent or player.";
}
private LavaBurstEffect(final LavaBurstEffect effect) {
super(effect);
}
@Override
public LavaBurstEffect copy() {
return new LavaBurstEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player targetPlayer = game.getPlayer(source.getFirstTarget());
int damage = CardUtil.getSourceCostsTag(game, source, "X", 0);
if (targetPlayer != null) {
targetPlayer.damage(damage, source.getSourceId(), source, game, false, true);
return true;
}
Permanent targetPermanent = game.getPermanent(source.getFirstTarget());
if (targetPermanent != null) {
if (targetPermanent.isCreature(game)) {
// hack to avoid needing to create a DAMAGE_REDIRECTION event
// Pretend that all possible redirection effects have already been applied
List<UUID> redirectionEffects = game.getState().getContinuousEffects().getReplacementEffects().stream()
.filter(x -> x instanceof RedirectionEffect).map(Effect::getId).collect(Collectors.toList());
targetPermanent.damage(damage, source.getSourceId(), source, game, false, false, redirectionEffects);
} else {
targetPermanent.damage(damage, source.getSourceId(), source, game, false, true);
}
return true;
}
return false;
}
}

View file

@ -219,6 +219,7 @@ public final class IceAge extends ExpansionSet {
cards.add(new SetCardInfo("Krovikan Vampire", 141, Rarity.UNCOMMON, mage.cards.k.KrovikanVampire.class, RETRO_ART));
cards.add(new SetCardInfo("Land Cap", 357, Rarity.RARE, mage.cards.l.LandCap.class, RETRO_ART));
cards.add(new SetCardInfo("Lapis Lazuli Talisman", 327, Rarity.UNCOMMON, mage.cards.l.LapisLazuliTalisman.class, RETRO_ART));
cards.add(new SetCardInfo("Lava Burst", 198, Rarity.COMMON, mage.cards.l.LavaBurst.class, RETRO_ART));
cards.add(new SetCardInfo("Lava Tubes", 358, Rarity.RARE, mage.cards.l.LavaTubes.class, RETRO_ART));
cards.add(new SetCardInfo("Legions of Lim-Dul", 142, Rarity.COMMON, mage.cards.l.LegionsOfLimDul.class, RETRO_ART));
cards.add(new SetCardInfo("Leshrac's Rite", 143, Rarity.UNCOMMON, mage.cards.l.LeshracsRite.class, RETRO_ART));

View file

@ -154,6 +154,7 @@ public final class MastersEditionII extends ExpansionSet {
cards.add(new SetCardInfo("Krovikan Sorcerer", 51, Rarity.COMMON, mage.cards.k.KrovikanSorcerer.class, RETRO_ART));
cards.add(new SetCardInfo("Krovikan Vampire", 102, Rarity.UNCOMMON, mage.cards.k.KrovikanVampire.class, RETRO_ART));
cards.add(new SetCardInfo("Lat-Nam's Legacy", 52, Rarity.COMMON, mage.cards.l.LatNamsLegacy.class, RETRO_ART));
cards.add(new SetCardInfo("Lava Burst", 134, Rarity.UNCOMMON, mage.cards.l.LavaBurst.class, RETRO_ART));
cards.add(new SetCardInfo("Leaping Lizard", 171, Rarity.COMMON, mage.cards.l.LeapingLizard.class, RETRO_ART));
cards.add(new SetCardInfo("Lim-Dul's High Guard", 103, Rarity.UNCOMMON, mage.cards.l.LimDulsHighGuard.class, RETRO_ART));
cards.add(new SetCardInfo("Lodestone Bauble", 213, Rarity.RARE, mage.cards.l.LodestoneBauble.class, RETRO_ART));

View file

@ -30,6 +30,7 @@ public class HarmsWayRedirectDamageTest extends CardTestPlayerBase {
setChoice(playerB, "Lightning Bolt");
setStopAt(1, PhaseStep.END_TURN);
setStrictChooseMode(true);
execute();
assertGraveyardCount(playerA, "Lightning Bolt", 1);
@ -57,6 +58,7 @@ public class HarmsWayRedirectDamageTest extends CardTestPlayerBase {
setChoice(playerA, "Craw Wurm");
setStopAt(2, PhaseStep.END_TURN);
setStrictChooseMode(true);
execute();
// only 4 combat damage
@ -91,6 +93,7 @@ public class HarmsWayRedirectDamageTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Lightning Bolt", "Magma Phoenix");
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
setStrictChooseMode(true);
execute();
assertLife(playerA, 19); // 3 damage from dying Phoenix -> 2 redirected to playerB so playerA gets only 1 damage
@ -122,6 +125,7 @@ public class HarmsWayRedirectDamageTest extends CardTestPlayerBase {
setChoice(playerB, "Wild Slash");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
setStrictChooseMode(true);
execute();
assertGraveyardCount(playerA, "Wild Slash", 1);
@ -132,4 +136,33 @@ public class HarmsWayRedirectDamageTest extends CardTestPlayerBase {
assertLife(playerB, 20);
}
/**
* Tests redirection doesn't happen vs. Lava Burst on creature, does on player
*/
@Test
public void testNoRedirectLavaBurst() {
addCard(Zone.HAND, playerB, "Harm's Way", 2);
addCard(Zone.BATTLEFIELD, playerB, "Plains", 2);
addCard(Zone.HAND, playerA, "Lava Burst", 2);
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 9);
addCard(Zone.BATTLEFIELD, playerB, "Aegis Turtle");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lava Burst", "Aegis Turtle");
setChoice(playerA, "X=4");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Harm's Way", playerA);
setChoice(playerB, "Lava Burst");
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Lava Burst", playerB);
setChoice(playerA, "X=3");
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Harm's Way", playerA);
setChoice(playerB, "Lava Burst");
setStopAt(1, PhaseStep.END_TURN);
setStrictChooseMode(true);
execute();
assertLife(playerA, 18);
assertLife(playerB, 19);
assertDamageReceived(playerB, "Aegis Turtle", 4);
}
}

View file

@ -108,6 +108,10 @@ public class ContinuousEffects implements Serializable {
return requirementEffects;
}
public List<ReplacementEffect> getReplacementEffects() {
return replacementEffects;
}
public List<RestrictionEffect> getRestrictionEffects() {
return restrictionEffects;
}