[LTR] Implement Galadriel of Lothorien

This commit is contained in:
theelk801 2023-06-08 20:25:08 -04:00
parent bdb010cfff
commit 8a742ca1d5
10 changed files with 235 additions and 250 deletions

View file

@ -1,7 +1,10 @@
package mage.cards.c;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.ScryTriggeredAbility;
import mage.abilities.condition.Condition;
import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition;
import mage.abilities.costs.common.ExileSourceFromGraveCost;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.effects.common.DoIfCostPaid;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.cards.CardImpl;
@ -9,10 +12,7 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterControlledPermanent;
import mage.game.Game;
import mage.game.events.GameEvent;
import java.util.UUID;
@ -21,6 +21,9 @@ import java.util.UUID;
*/
public final class CouncilsDeliberation extends CardImpl {
private static final Condition condition
= new PermanentsOnTheBattlefieldCondition(new FilterControlledPermanent(SubType.ISLAND));
public CouncilsDeliberation(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}");
@ -28,7 +31,15 @@ public final class CouncilsDeliberation extends CardImpl {
this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1));
// Whenever you scry, if you control an Island, you may exile Council's Deliberation from your graveyard. If you do, draw a card.
this.addAbility(new CouncilsDeliberationTriggeredAbility());
this.addAbility(new ConditionalInterveningIfTriggeredAbility(
new ScryTriggeredAbility(
Zone.GRAVEYARD,
new DoIfCostPaid(
new DrawCardSourceControllerEffect(1), new ExileSourceFromGraveCost()
), false
), condition, "Whenever you scry, if you control an Island, " +
"you may exile {this} from your graveyard. If you do, draw a card."
));
}
private CouncilsDeliberation(final CouncilsDeliberation card) {
@ -40,41 +51,3 @@ public final class CouncilsDeliberation extends CardImpl {
return new CouncilsDeliberation(this);
}
}
class CouncilsDeliberationTriggeredAbility extends TriggeredAbilityImpl {
private static final FilterPermanent filter = new FilterControlledPermanent(SubType.ISLAND);
CouncilsDeliberationTriggeredAbility() {
super(Zone.GRAVEYARD, new DoIfCostPaid(new DrawCardSourceControllerEffect(1), new ExileSourceFromGraveCost()));
}
private CouncilsDeliberationTriggeredAbility(final CouncilsDeliberationTriggeredAbility ability) {
super(ability);
}
@Override
public CouncilsDeliberationTriggeredAbility copy() {
return new CouncilsDeliberationTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.SCRIED;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
return isControlledBy(event.getPlayerId());
}
@Override
public boolean checkInterveningIfClause(Game game) {
return game.getBattlefield().contains(filter, this, game, 1);
}
@Override
public String getRule() {
return "Whenever you scry, if you control an Island, you may exile {this} from your graveyard. If you do, draw a card.";
}
}

View file

@ -3,8 +3,8 @@ package mage.cards.e;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
import mage.abilities.SpellAbility;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.CanBeYourCommanderAbility;
import mage.abilities.common.ScryTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.cost.CostModificationEffectImpl;
@ -38,7 +38,7 @@ public final class Elminster extends CardImpl {
this.setStartingLoyalty(5);
// Whenever you scry, the next instant or sorcery spell you cast this turn costs {X} less to cast, where X is the number of cards looked at while scrying this way.
this.addAbility(new ElminsterTriggeredAbility());
this.addAbility(new ScryTriggeredAbility(new ElminsterReductionEffect()), new ElminsterWatcher());
// +2: Draw a card, then scry 2.
Ability ability = new LoyaltyAbility(new DrawCardSourceControllerEffect(1), 2);
@ -62,58 +62,18 @@ public final class Elminster extends CardImpl {
}
}
class ElminsterTriggeredAbility extends TriggeredAbilityImpl {
ElminsterTriggeredAbility() {
super(Zone.BATTLEFIELD, null);
this.addWatcher(new ElminsterWatcher());
}
private ElminsterTriggeredAbility(final ElminsterTriggeredAbility ability) {
super(ability);
}
@Override
public ElminsterTriggeredAbility copy() {
return new ElminsterTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.SCRIED;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (isControlledBy(event.getPlayerId())) {
this.getEffects().clear();
this.addEffect(new ElminsterReductionEffect(event.getAmount()));
return true;
}
return false;
}
@Override
public String getRule() {
return "Whenever you scry, the next instant or sorcery spell you cast this turn costs {X} less to cast, where X is the number of cards looked at while scrying this way.";
}
}
class ElminsterReductionEffect extends CostModificationEffectImpl {
private int spellsCast;
private final int amount;
ElminsterReductionEffect(int amount) {
ElminsterReductionEffect() {
super(Duration.EndOfTurn, Outcome.Benefit, CostModificationType.REDUCE_COST);
this.amount = amount;
staticText = "the next instant or sorcery spell you cast this turn costs {X} less to cast, " +
"where X is {this}'s power as this ability resolves";
staticText = " the next instant or sorcery spell you cast this turn costs {X} less to cast, " +
"where X is the number of cards looked at while scrying this way";
}
private ElminsterReductionEffect(final ElminsterReductionEffect effect) {
super(effect);
this.amount = effect.amount;
this.spellsCast = effect.spellsCast;
}
@ -128,7 +88,7 @@ class ElminsterReductionEffect extends CostModificationEffectImpl {
@Override
public boolean apply(Game game, Ability source, Ability abilityToModify) {
CardUtil.reduceCost(abilityToModify, amount);
CardUtil.reduceCost(abilityToModify, (Integer) getValue("amount"));
return true;
}

View file

@ -1,30 +1,26 @@
package mage.cards.f;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.Ability;
import mage.abilities.common.ScryTriggeredAbility;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
import mage.abilities.keyword.FirstStrikeAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.constants.SubType;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public final class FlamespeakerAdept extends CardImpl {
public FlamespeakerAdept(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{R}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.SHAMAN);
@ -32,7 +28,13 @@ public final class FlamespeakerAdept extends CardImpl {
this.toughness = new MageInt(3);
// Whenever you scry, Flamespeaker Adept gets +2/+0 and gains first strike until end of turn.
this.addAbility(new ScryTriggeredAbility());
Ability ability = new ScryTriggeredAbility(new BoostSourceEffect(
2, 0, Duration.EndOfTurn
).setText("{this} gets +2/+0"));
ability.addEffect(new GainAbilitySourceEffect(
FirstStrikeAbility.getInstance(), Duration.EndOfTurn
).setText("and gains first strike until end of turn"));
this.addAbility(ability);
}
private FlamespeakerAdept(final FlamespeakerAdept card) {
@ -44,30 +46,3 @@ public final class FlamespeakerAdept extends CardImpl {
return new FlamespeakerAdept(this);
}
}
class ScryTriggeredAbility extends TriggeredAbilityImpl {
public ScryTriggeredAbility() {
super(Zone.BATTLEFIELD, new BoostSourceEffect(2,0, Duration.EndOfTurn), false);
this.addEffect(new GainAbilitySourceEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn));
setTriggerPhrase("Whenever you scry, ");
}
public ScryTriggeredAbility(final ScryTriggeredAbility ability) {
super(ability);
}
@Override
public ScryTriggeredAbility copy() {
return new ScryTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.SCRIED;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
return event.getPlayerId().equals(this.getControllerId());
}
}

View file

@ -0,0 +1,83 @@
package mage.cards.g;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.ScryTriggeredAbility;
import mage.abilities.common.TheRingTemptsYouChooseAnotherTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.keyword.ScryEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.CardsImpl;
import mage.constants.*;
import mage.game.Game;
import mage.players.Player;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class GaladrielOfLothlorien extends CardImpl {
public GaladrielOfLothlorien(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}{U}");
this.supertype.add(SuperType.LEGENDARY);
this.subtype.add(SubType.ELF);
this.subtype.add(SubType.NOBLE);
this.power = new MageInt(3);
this.toughness = new MageInt(3);
// Whenever the Ring tempts you, if you chose a creature other than Galadriel of Lothlorien as your Ring-bearer, scry 3.
this.addAbility(new TheRingTemptsYouChooseAnotherTriggeredAbility(
new ScryEffect(3, false)
));
// Whenever you scry, you may reveal the top card of your library. If a land card is revealed this way, put it onto the battlefield tapped.
this.addAbility(new ScryTriggeredAbility(new GaladrielOfLothlorienEffect(), true));
}
private GaladrielOfLothlorien(final GaladrielOfLothlorien card) {
super(card);
}
@Override
public GaladrielOfLothlorien copy() {
return new GaladrielOfLothlorien(this);
}
}
class GaladrielOfLothlorienEffect extends OneShotEffect {
GaladrielOfLothlorienEffect() {
super(Outcome.Benefit);
staticText = "reveal the top card of your library. If a land card is revealed this way, put it onto the battlefield tapped";
}
private GaladrielOfLothlorienEffect(final GaladrielOfLothlorienEffect effect) {
super(effect);
}
@Override
public GaladrielOfLothlorienEffect copy() {
return new GaladrielOfLothlorienEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player == null) {
return false;
}
Card card = player.getLibrary().getFromTop(game);
if (card == null) {
return false;
}
player.revealCards(source, new CardsImpl(card), game);
return card.isLand(game) && player.moveCards(
card, Zone.BATTLEFIELD, source, game, true, false, false, null
);
}
}

View file

@ -1,17 +1,18 @@
package mage.cards.g;
import mage.MageInt;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.common.TheRingTemptsYouChooseAnotherTriggeredAbility;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.continuous.CastAsThoughItHadFlashAllEffect;
import mage.abilities.keyword.FlashAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.filter.FilterCard;
import mage.game.Game;
import mage.game.events.GameEvent;
import java.util.UUID;
@ -42,7 +43,7 @@ public final class GandalfFriendOfTheShire extends CardImpl {
this.addAbility(new SimpleStaticAbility(new CastAsThoughItHadFlashAllEffect(Duration.WhileOnBattlefield, filter)));
// Whenever the Ring tempts you, if you chose a creature other than Gandalf, Friend of the Shire as your Ring-bearer, draw a card.
this.addAbility(new GandalfFriendOfTheShireTriggeredAbility());
this.addAbility(new TheRingTemptsYouChooseAnotherTriggeredAbility(new DrawCardSourceControllerEffect(1)));
}
private GandalfFriendOfTheShire(final GandalfFriendOfTheShire card) {
@ -55,31 +56,3 @@ public final class GandalfFriendOfTheShire extends CardImpl {
}
}
class GandalfFriendOfTheShireTriggeredAbility extends TriggeredAbilityImpl {
GandalfFriendOfTheShireTriggeredAbility() {
super(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1));
this.setTriggerPhrase("Whenever the Ring tempts you, if you chose a creature other than {this} as your Ring-bearer, ");
}
private GandalfFriendOfTheShireTriggeredAbility(final GandalfFriendOfTheShireTriggeredAbility ability) {
super(ability);
}
@Override
public GandalfFriendOfTheShireTriggeredAbility copy() {
return new GandalfFriendOfTheShireTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.TEMPTED_BY_RING;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
return this.isControlledBy(event.getPlayerId())
&& event.getTargetId() != null
&& !event.getTargetId().equals(this.getSourceId());
}
}

View file

@ -1,33 +1,31 @@
package mage.cards.k;
import java.util.UUID;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.Ability;
import mage.abilities.common.ScryTriggeredAbility;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.effects.common.DoIfCostPaid;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.target.common.TargetAnyTarget;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public final class KnowledgeAndPower extends CardImpl {
public KnowledgeAndPower(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{4}{R}");
// Whenever you scry, you may pay 2. If you do. Knowledge and Power deals 2 damage to any target.
this.addAbility(new ScryTriggeredAbility() );
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{4}{R}");
// Whenever you scry, you may pay {2}. If you do, Knowledge and Power deals 2 damage to any target.
Ability ability = new ScryTriggeredAbility(
new DoIfCostPaid(new DamageTargetEffect(2), new GenericManaCost(2))
);
ability.addTarget(new TargetAnyTarget());
this.addAbility(ability);
}
private KnowledgeAndPower(final KnowledgeAndPower card) {
@ -39,31 +37,3 @@ public final class KnowledgeAndPower extends CardImpl {
return new KnowledgeAndPower(this);
}
}
class ScryTriggeredAbility extends TriggeredAbilityImpl {
public ScryTriggeredAbility() {
super(Zone.BATTLEFIELD, new DoIfCostPaid(new DamageTargetEffect(2), new GenericManaCost(2)), false);
this.addTarget(new TargetAnyTarget());
setTriggerPhrase("Whenever you scry, ");
}
public ScryTriggeredAbility(final ScryTriggeredAbility ability) {
super(ability);
}
@Override
public ScryTriggeredAbility copy() {
return new ScryTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.SCRIED;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
return event.getPlayerId().equals(this.getControllerId());
}
}

View file

@ -1,8 +1,10 @@
package mage.cards.l;
import mage.MageInt;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.DiesCreatureTriggeredAbility;
import mage.abilities.common.ScryTriggeredAbility;
import mage.abilities.condition.common.SourceTappedCondition;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.effects.common.UntapSourceEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.abilities.keyword.ReachAbility;
@ -11,15 +13,9 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.constants.Zone;
import mage.counters.CounterType;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
/**
@ -40,7 +36,10 @@ public final class LegolasCounterOfKills extends CardImpl {
this.addAbility(ReachAbility.getInstance());
// Whenever you scry, if Legolas, Counter of Kills is tapped, you may untap it. Do this only once each turn.
this.addAbility(new LegolasCounterOfKillsTriggeredAbility());
this.addAbility(new ConditionalInterveningIfTriggeredAbility(
new ScryTriggeredAbility(new UntapSourceEffect()).setDoOnlyOnce(true), SourceTappedCondition.TAPPED,
"Whenever you scry, if {this} is tapped, you may untap it. Do this only once each turn."
));
// Whenever a creature an opponent controls dies, put a +1/+1 counter on Legolas.
this.addAbility(new DiesCreatureTriggeredAbility(
@ -58,44 +57,3 @@ public final class LegolasCounterOfKills extends CardImpl {
return new LegolasCounterOfKills(this);
}
}
class LegolasCounterOfKillsTriggeredAbility extends TriggeredAbilityImpl {
LegolasCounterOfKillsTriggeredAbility() {
super(Zone.BATTLEFIELD, new UntapSourceEffect(), true);
this.setDoOnlyOnce(true);
}
private LegolasCounterOfKillsTriggeredAbility(final LegolasCounterOfKillsTriggeredAbility ability) {
super(ability);
}
@Override
public LegolasCounterOfKillsTriggeredAbility copy() {
return new LegolasCounterOfKillsTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.SCRIED;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
return isControlledBy(event.getPlayerId());
}
@Override
public boolean checkInterveningIfClause(Game game) {
return Optional
.ofNullable(this.getSourcePermanentIfItStillExists(game))
.filter(Objects::nonNull)
.map(Permanent::isTapped)
.orElse(false);
}
@Override
public String getRule() {
return "Whenever you scry, if Legolas, Counter of Kills is tapped, you may untap it. Do this only once each turn.";
}
}

View file

@ -54,6 +54,7 @@ public final class TheLordOfTheRingsTalesOfMiddleEarth extends ExpansionSet {
cards.add(new SetCardInfo("Frodo, Determined Hero", 388, Rarity.RARE, mage.cards.f.FrodoDeterminedHero.class));
cards.add(new SetCardInfo("Frodo, Sauron's Bane", 18, Rarity.RARE, mage.cards.f.FrodoSauronsBane.class));
cards.add(new SetCardInfo("Galadhrim Bow", 167, Rarity.COMMON, mage.cards.g.GaladhrimBow.class));
cards.add(new SetCardInfo("Galadriel of Lothlorien", 206, Rarity.RARE, mage.cards.g.GaladrielOfLothlorien.class));
cards.add(new SetCardInfo("Galadriel, Gift-Giver", 296, Rarity.RARE, mage.cards.g.GaladrielGiftGiver.class));
cards.add(new SetCardInfo("Gandalf the Grey", 207, Rarity.RARE, mage.cards.g.GandalfTheGrey.class));
cards.add(new SetCardInfo("Gandalf, Friend of the Shire", 50, Rarity.UNCOMMON, mage.cards.g.GandalfFriendOfTheShire.class));

View file

@ -0,0 +1,49 @@
package mage.abilities.common;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.Effect;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
/**
* @author TheElk801
*/
public class ScryTriggeredAbility extends TriggeredAbilityImpl {
public ScryTriggeredAbility(Effect effect) {
this(effect, false);
}
public ScryTriggeredAbility(Effect effect, boolean optional) {
this(Zone.BATTLEFIELD, effect, optional);
}
public ScryTriggeredAbility(Zone zone, Effect effect, boolean optional) {
super(zone, effect, false);
setTriggerPhrase("Whenever you scry, ");
}
private ScryTriggeredAbility(final ScryTriggeredAbility ability) {
super(ability);
}
@Override
public ScryTriggeredAbility copy() {
return new ScryTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.SCRIED;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (isControlledBy(event.getPlayerId())) {
this.getEffects().setValue("amount", event.getAmount());
return true;
}
return false;
}
}

View file

@ -0,0 +1,43 @@
package mage.abilities.common;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.Effect;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
/**
* @author TheElk801
*/
public class TheRingTemptsYouChooseAnotherTriggeredAbility extends TriggeredAbilityImpl {
public TheRingTemptsYouChooseAnotherTriggeredAbility(Effect effect) {
this(effect, false);
}
public TheRingTemptsYouChooseAnotherTriggeredAbility(Effect effect, boolean optional) {
super(Zone.BATTLEFIELD, effect, optional);
setTriggerPhrase("Whenever the Ring tempts you, if you chose a creature other than {this} as your Ring-bearer, ");
}
private TheRingTemptsYouChooseAnotherTriggeredAbility(final TheRingTemptsYouChooseAnotherTriggeredAbility ability) {
super(ability);
}
@Override
public TheRingTemptsYouChooseAnotherTriggeredAbility copy() {
return new TheRingTemptsYouChooseAnotherTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.TEMPTED_BY_RING;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
return this.isControlledBy(event.getPlayerId())
&& event.getTargetId() != null
&& !event.getTargetId().equals(this.getSourceId());
}
}