[LTC] Implementations part 3 (#11471)

* Fell Beast's Shriek
* Mordor on the March
* Olorin's Searing Light
* Sorcerous Squall
This commit is contained in:
ssk97 2023-11-27 21:57:35 -08:00 committed by GitHub
parent 02eafaf062
commit 2ef9439773
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 409 additions and 28 deletions

View file

@ -7,12 +7,10 @@ import mage.abilities.effects.common.DamagePlayersEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.ComparisonType;
import mage.constants.Outcome;
import mage.constants.TargetController;
import mage.filter.StaticFilters;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.mageobject.PowerPredicate;
import mage.filter.predicate.permanent.GreatestPowerControlledPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
@ -50,6 +48,10 @@ public final class CracklingDoom extends CardImpl {
class CracklingDoomEffect extends OneShotEffect {
static FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("creature with the greatest power among creatures you control");
static {
filter.add(GreatestPowerControlledPredicate.instance);
}
public CracklingDoomEffect() {
super(Outcome.Sacrifice);
this.staticText = "Each opponent sacrifices a creature with the greatest power among creatures that player controls";
@ -73,31 +75,12 @@ class CracklingDoomEffect extends OneShotEffect {
if (controller.hasOpponent(playerId, game)) {
Player opponent = game.getPlayer(playerId);
if (opponent != null) {
int greatestPower = Integer.MIN_VALUE;
int numberOfCreatures = 0;
Permanent permanentToSacrifice = null;
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, playerId, game)) {
if (permanent.getPower().getValue() > greatestPower) {
greatestPower = permanent.getPower().getValue();
numberOfCreatures = 1;
permanentToSacrifice = permanent;
} else if (permanent.getPower().getValue() == greatestPower) {
numberOfCreatures++;
}
}
if (numberOfCreatures == 1) {
if (permanentToSacrifice != null) {
toSacrifice.add(permanentToSacrifice);
}
} else if (greatestPower != Integer.MIN_VALUE) {
FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("creature to sacrifice with power equal to " + greatestPower);
filter.add(new PowerPredicate(ComparisonType.EQUAL_TO, greatestPower));
Target target = new TargetControlledCreaturePermanent(filter);
if (opponent.choose(outcome, target, source, game)) {
Permanent permanent = game.getPermanent(target.getFirstTarget());
if (permanent != null) {
toSacrifice.add(permanent);
}
Target target = new TargetControlledCreaturePermanent(filter);
target.withNotTarget(true);
if (opponent.choose(outcome, target, source, game)) {
Permanent permanent = game.getPermanent(target.getFirstTarget());
if (permanent != null) {
toSacrifice.add(permanent);
}
}
}

View file

@ -0,0 +1,95 @@
package mage.cards.f;
import mage.abilities.Ability;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.TapAllEffect;
import mage.abilities.effects.common.combat.GoadAllEffect;
import mage.abilities.keyword.SpliceAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.permanent.PermanentInListPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetControlledCreaturePermanent;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
/**
*
* @author notgreat
*/
public final class FellBeastsShriek extends CardImpl {
public FellBeastsShriek(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{U}{R}");
// Each opponent chooses a creature they control. Tap and goad the chosen creatures.
this.getSpellAbility().addEffect(new FellBeastsShriekEffect());
// Splice onto instant or sorcery {2}{U}{R}
this.addAbility(new SpliceAbility(SpliceAbility.INSTANT_OR_SORCERY, "{2}{U}{R}"));
}
private FellBeastsShriek(final FellBeastsShriek card) {
super(card);
}
@Override
public FellBeastsShriek copy() {
return new FellBeastsShriek(this);
}
}
class FellBeastsShriekEffect extends OneShotEffect {
public FellBeastsShriekEffect() {
super(Outcome.Benefit);
this.staticText = "Each opponent chooses a creature they control. Tap and goad the chosen creatures.";
}
private FellBeastsShriekEffect(final FellBeastsShriekEffect effect) {
super(effect);
}
@Override
public FellBeastsShriekEffect copy() {
return new FellBeastsShriekEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
List<Permanent> creaturesChosen = new ArrayList<>();
// For each opponent, get the creature to tap+goad
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
if (controller.hasOpponent(playerId, game)) {
Player opponent = game.getPlayer(playerId);
if (opponent != null) {
TargetControlledCreaturePermanent target = new TargetControlledCreaturePermanent();
target.withNotTarget(true);
if (opponent.choose(Outcome.Detriment, target, source, game)) {
creaturesChosen.add(game.getPermanent(target.getTargets().get(0)));
}
}
}
}
FilterPermanent filter = new FilterCreaturePermanent();
filter.add(new PermanentInListPredicate(creaturesChosen));
new TapAllEffect(filter).apply(game, source);
ContinuousEffect goadEffect = new GoadAllEffect(filter);
game.addEffect(goadEffect, source);
return true;
}
return false;
}
}

View file

@ -0,0 +1,108 @@
package mage.cards.m;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateTokenCopyTargetEffect;
import mage.abilities.effects.common.ExileTargetEffect;
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
import mage.abilities.keyword.HasteAbility;
import mage.abilities.keyword.StormAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetCard;
import mage.target.common.TargetCardInYourGraveyard;
import mage.target.targetpointer.FixedTarget;
import mage.target.targetpointer.FixedTargets;
import java.util.UUID;
/**
*
* @author notgreat
*/
public final class MordorOnTheMarch extends CardImpl {
public MordorOnTheMarch(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{B}{R}");
// Exile a creature card from your graveyard. Create a token that's a copy of it. It gains haste until end of turn. Exile it at the beginning of the next end step.
this.getSpellAbility().addEffect(new MordorOnTheMarchEffect());
// Storm
this.addAbility(new StormAbility());
}
private MordorOnTheMarch(final MordorOnTheMarch card) {
super(card);
}
@Override
public MordorOnTheMarch copy() {
return new MordorOnTheMarch(this);
}
}
class MordorOnTheMarchEffect extends OneShotEffect {
public MordorOnTheMarchEffect() {
super(Outcome.PutCreatureInPlay);
this.staticText = "exile a creature card from your graveyard. Create a token that's a copy of it. It gains haste until end of turn. Exile it at the beginning of the next end step";
}
private MordorOnTheMarchEffect(final MordorOnTheMarchEffect effect) {
super(effect);
}
@Override
public MordorOnTheMarchEffect copy() {
return new MordorOnTheMarchEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller == null) {
return false;
}
TargetCard target = new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_CREATURE_YOUR_GRAVEYARD);
target.withNotTarget(true);
if (!target.canChoose(source.getControllerId(), source, game)) {
return true;
}
controller.choose(outcome, target, source, game);
Card card = game.getCard(target.getFirstTarget());
if (card != null) {
CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect(source.getControllerId(), null, false);
effect.setTargetPointer(new FixedTarget(card.getId(), card.getZoneChangeCounter(game) + 1));
controller.moveCards(card, Zone.EXILED, source, game);
effect.apply(game, source);
effect.getAddedPermanents().stream().forEach(permanent -> {
ContinuousEffect continuousEffect = new GainAbilityTargetEffect(
HasteAbility.getInstance(), Duration.UntilYourNextTurn
);
continuousEffect.setTargetPointer(new FixedTarget(permanent, game));
game.addEffect(continuousEffect, source);
});
ExileTargetEffect exileEffect = new ExileTargetEffect();
exileEffect.setTargetPointer(new FixedTargets(effect.getAddedPermanents(), game));
DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(exileEffect);
game.addDelayedTriggeredAbility(delayedAbility, source);
return true;
}
return false;
}
}

View file

@ -0,0 +1,104 @@
package mage.cards.o;
import mage.abilities.Ability;
import mage.abilities.condition.common.SpellMasteryCondition;
import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.permanent.GreatestPowerControlledPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.Target;
import mage.target.common.TargetControlledCreaturePermanent;
import java.util.*;
/**
*
* @author notgreat
*/
public final class OlorinsSearingLight extends CardImpl {
public OlorinsSearingLight(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{R}{W}");
// Each opponent exiles a creature with the greatest power among creatures that player controls.
// Spell mastery -- If there are two or more instant and/or sorcery cards in your graveyard, Olorin's Searing Light deals damage to each opponent equal to the power of the creature they exiled.
this.getSpellAbility().addEffect(new OlorinsSearingLightEffect());
}
private OlorinsSearingLight(final OlorinsSearingLight card) {
super(card);
}
@Override
public OlorinsSearingLight copy() {
return new OlorinsSearingLight(this);
}
}
//See Crackling Doom
class OlorinsSearingLightEffect extends OneShotEffect {
static FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("creature with the greatest power among creatures you control");
static {
filter.add(GreatestPowerControlledPredicate.instance);
}
public OlorinsSearingLightEffect() {
super(Outcome.Sacrifice);
this.staticText = "Each opponent exiles a creature with the greatest power among creatures that player controls.<br>"
+"<i>Spell mastery</i> &mdash; If there are two or more instant and/or sorcery cards in your graveyard, {this} deals damage to each opponent equal to the power of the creature they exiled.";
}
private OlorinsSearingLightEffect(final OlorinsSearingLightEffect effect) {
super(effect);
}
@Override
public OlorinsSearingLightEffect copy() {
return new OlorinsSearingLightEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
List<Permanent> toExile = new ArrayList<>();
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
if (controller.hasOpponent(playerId, game)) {
Player opponent = game.getPlayer(playerId);
if (opponent != null) {
Target target = new TargetControlledCreaturePermanent(filter);
target.withNotTarget(true);
if (opponent.choose(outcome, target, source, game)) {
Permanent permanentChosen = game.getPermanent(target.getFirstTarget());
if (permanentChosen != null) {
toExile.add(permanentChosen);
}
}
}
}
}
List<Map.Entry<Player, Integer>> damageList = new ArrayList<>();
for (Permanent permanent : toExile) {
Player opponent = game.getPlayer(permanent.getControllerId());
if (opponent != null) {
damageList.add(new AbstractMap.SimpleImmutableEntry<>(opponent, permanent.getPower().getValue()));
opponent.moveCards(permanent, Zone.EXILED, source, game);
}
}
if (SpellMasteryCondition.instance.apply(game, source)){
game.getState().processAction(game);
for (Map.Entry<Player, Integer> entry : damageList) {
entry.getKey().damage(entry.getValue(), source, game);
}
}
return true;
}
return false;
}
}

View file

@ -0,0 +1,87 @@
package mage.cards.s;
import mage.abilities.Ability;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.MayCastTargetThenExileEffect;
import mage.abilities.effects.common.MillCardsTargetEffect;
import mage.abilities.effects.common.replacement.ThatSpellGraveyardExileReplacementEffect;
import mage.abilities.keyword.DelveAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.filter.FilterCard;
import mage.filter.common.FilterInstantOrSorceryCard;
import mage.filter.predicate.card.OwnerIdPredicate;
import mage.game.Game;
import mage.players.Player;
import mage.target.Target;
import mage.target.common.TargetCardInGraveyard;
import mage.target.common.TargetOpponent;
import mage.target.targetpointer.FixedTarget;
import java.util.UUID;
/**
*
* @author notgreat
*/
public final class SorcerousSquall extends CardImpl {
public SorcerousSquall(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{6}{U}{U}{U}");
// Delve
this.addAbility(new DelveAbility());
// Target opponent mills nine cards, then you may cast an instant or sorcery spell from that player's graveyard without paying its mana cost. If that spell would be put into a graveyard, exile it instead.
this.getSpellAbility().addEffect(new MillCardsTargetEffect(9));
this.getSpellAbility().addEffect(new SorcerousSquallEffect().concatBy(", then"));
this.getSpellAbility().addTarget(new TargetOpponent());
}
private SorcerousSquall(final SorcerousSquall card) {
super(card);
}
@Override
public SorcerousSquall copy() {
return new SorcerousSquall(this);
}
}
class SorcerousSquallEffect extends OneShotEffect {
SorcerousSquallEffect() {
super(Outcome.Detriment);
setText("you may cast an instant or sorcery spell from that player's graveyard without paying its mana cost. "+ ThatSpellGraveyardExileReplacementEffect.RULE_A);
}
private SorcerousSquallEffect(final SorcerousSquallEffect effect) {
super(effect);
}
@Override
public SorcerousSquallEffect copy() {
return new SorcerousSquallEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getFirstTarget());
if (player == null) {
return false;
}
FilterCard filter = new FilterInstantOrSorceryCard("instant or sorcery card from that player's graveyard");
filter.add(new OwnerIdPredicate(source.getFirstTarget()));
Target target = new TargetCardInGraveyard(1, 1, filter, true);
player.choose(outcome, target, source, game);
Effect effect = new MayCastTargetThenExileEffect(true);
effect.setTargetPointer(new FixedTarget(target.getFirstTarget(), game));
effect.apply(game, source);
return true;
}
}

View file

@ -114,6 +114,7 @@ public final class TalesOfMiddleEarthCommander extends ExpansionSet {
cards.add(new SetCardInfo("Feasting Hobbit", 37, Rarity.RARE, mage.cards.f.FeastingHobbit.class));
cards.add(new SetCardInfo("Feed the Swarm", 200, Rarity.COMMON, mage.cards.f.FeedTheSwarm.class));
cards.add(new SetCardInfo("Fell Beast of Mordor", 513, Rarity.RARE, mage.cards.f.FellBeastOfMordor.class));
cards.add(new SetCardInfo("Fell Beast's Shriek", 508, Rarity.RARE, mage.cards.f.FellBeastsShriek.class));
cards.add(new SetCardInfo("Fell the Mighty", 167, Rarity.RARE, mage.cards.f.FellTheMighty.class));
cards.add(new SetCardInfo("Field of Ruin", 308, Rarity.UNCOMMON, mage.cards.f.FieldOfRuin.class));
cards.add(new SetCardInfo("Field-Tested Frying Pan", 11, Rarity.RARE, mage.cards.f.FieldTestedFryingPan.class));
@ -204,6 +205,7 @@ public final class TalesOfMiddleEarthCommander extends ExpansionSet {
cards.add(new SetCardInfo("Mists of Lorien", 501, Rarity.RARE, mage.cards.m.MistsOfLorien.class));
cards.add(new SetCardInfo("Model of Unity", 78, Rarity.RARE, mage.cards.m.ModelOfUnity.class));
cards.add(new SetCardInfo("Monstrosity of the Lake", 22, Rarity.RARE, mage.cards.m.MonstrosityOfTheLake.class));
cards.add(new SetCardInfo("Mordor on the March", 512, Rarity.RARE, mage.cards.m.MordorOnTheMarch.class));
cards.add(new SetCardInfo("Moria Scavenger", 63, Rarity.RARE, mage.cards.m.MoriaScavenger.class));
cards.add(new SetCardInfo("Mortify", 269, Rarity.UNCOMMON, mage.cards.m.Mortify.class));
cards.add(new SetCardInfo("Motivated Pony", 42, Rarity.RARE, mage.cards.m.MotivatedPony.class));
@ -218,6 +220,7 @@ public final class TalesOfMiddleEarthCommander extends ExpansionSet {
cards.add(new SetCardInfo("Oath of Eorl", 64, Rarity.RARE, mage.cards.o.OathOfEorl.class));
cards.add(new SetCardInfo("Oboro, Palace in the Clouds", 371, Rarity.MYTHIC, mage.cards.o.OboroPalaceInTheClouds.class));
cards.add(new SetCardInfo("Of Herbs and Stewed Rabbit", 17, Rarity.RARE, mage.cards.o.OfHerbsAndStewedRabbit.class));
cards.add(new SetCardInfo("Olorin's Searing Light", 503, Rarity.RARE, mage.cards.o.OlorinsSearingLight.class));
cards.add(new SetCardInfo("Opt", 194, Rarity.COMMON, mage.cards.o.Opt.class));
cards.add(new SetCardInfo("Orchard Strider", 253, Rarity.COMMON, mage.cards.o.OrchardStrider.class));
cards.add(new SetCardInfo("Orcish Siegemaster", 33, Rarity.RARE, mage.cards.o.OrcishSiegemaster.class));
@ -280,6 +283,7 @@ public final class TalesOfMiddleEarthCommander extends ExpansionSet {
cards.add(new SetCardInfo("Smoldering Marsh", 332, Rarity.RARE, mage.cards.s.SmolderingMarsh.class));
cards.add(new SetCardInfo("Sol Ring", 284, Rarity.UNCOMMON, mage.cards.s.SolRing.class));
cards.add(new SetCardInfo("Song of Earendil", 69, Rarity.RARE, mage.cards.s.SongOfEarendil.class));
cards.add(new SetCardInfo("Sorcerous Squall", 504, Rarity.RARE, mage.cards.s.SorcerousSquall.class));
cards.add(new SetCardInfo("Soul's Attendant", 520, Rarity.UNCOMMON, mage.cards.s.SoulsAttendant.class));
cards.add(new SetCardInfo("Stonehewer Giant", 521, Rarity.RARE, mage.cards.s.StonehewerGiant.class));
cards.add(new SetCardInfo("Subjugate the Hobbits", 24, Rarity.RARE, mage.cards.s.SubjugateTheHobbits.class));