more refactoring

This commit is contained in:
theelk801 2024-09-26 18:49:24 -04:00
parent b9b69586dc
commit a519d687da
19 changed files with 454 additions and 727 deletions

View file

@ -1,37 +1,37 @@
package mage.cards.c;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.SpellCastAllTriggeredAbility;
import mage.abilities.costs.Cost;
import mage.abilities.costs.mana.GenericManaCost;
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.FilterCard;
import mage.filter.predicate.mageobject.NamePredicate;
import mage.constants.SetTargetPointer;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.stack.Spell;
import mage.players.Player;
import mage.util.ManaUtil;
import java.util.Collection;
import java.util.Objects;
import java.util.UUID;
/**
* @author jeffwadsworth
* @author TheElk801
*/
public final class CephalidShrine extends CardImpl {
public CephalidShrine(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{U}{U}");
// Whenever a player casts a spell, counter that spell unless that player
// pays {X}, where X is the number of cards in all graveyards with the same name as the spell.
this.addAbility(new CephalidShrineTriggeredAbility());
// Whenever a player casts a spell, counter that spell unless that player pays {X}, where X is the number of cards in all graveyards with the same name as the spell.
this.addAbility(new SpellCastAllTriggeredAbility(
new CephalidShrineEffect(), StaticFilters.FILTER_SPELL_A,
false, SetTargetPointer.PLAYER
));
}
private CephalidShrine(final CephalidShrine card) {
@ -44,95 +44,46 @@ public final class CephalidShrine extends CardImpl {
}
}
class CephalidShrineTriggeredAbility extends TriggeredAbilityImpl {
public CephalidShrineTriggeredAbility() {
super(Zone.BATTLEFIELD, new CephalidShrineEffect(), false);
}
private CephalidShrineTriggeredAbility(final CephalidShrineTriggeredAbility ability) {
super(ability);
}
@Override
public CephalidShrineTriggeredAbility copy() {
return new CephalidShrineTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.SPELL_CAST;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Spell spell = game.getStack().getSpell(event.getTargetId());
MageObject mageObject = game.getObject(sourceId);
if (spell != null
&& mageObject != null) {
game.getState().setValue("cephalidShrine" + mageObject, spell);
return true;
}
return false;
}
}
class CephalidShrineEffect extends OneShotEffect {
CephalidShrineEffect() {
super(Outcome.Detriment);
staticText = "Whenever a player casts a spell, counter that "
+ "spell unless that player pays {X}, where X is the "
+ "number of cards in all graveyards with the same name "
+ "as the spell";
super(Outcome.Benefit);
staticText = "counter that spell unless that player pays {X}, " +
"where X is the number of cards in all graveyards with the same name as the spell";
}
private CephalidShrineEffect(final CephalidShrineEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
int count = 0;
MageObject mageObject = game.getObject(source);
if (mageObject != null) {
Spell spell = (Spell) game.getState().getValue("cephalidShrine" + mageObject);
if (spell != null) {
Player controller = game.getPlayer(spell.getControllerId());
if (controller != null) {
String name = spell.getName();
FilterCard filterCardName = new FilterCard();
filterCardName.add(new NamePredicate(name));
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
Player player = game.getPlayer(playerId);
if (player != null) {
count += player.getGraveyard().count(filterCardName, game);
}
}
// even if the cost is 0, we still offer
Cost cost = ManaUtil.createManaCost(count, true);
if (game.getStack().contains(spell)
&& cost.canPay(source, source, controller.getId(), game)
&& controller.chooseUse(outcome, "Pay " + cost.getText()
+ " to prevent countering " + spell.getName() + "?", source, game)
&& cost.pay(source, game, source, controller.getId(), false)
&& cost.isPaid()) {
return false;
} else {
game.getStack().counter(spell.getId(), source, game);
game.informPlayers(spell.getName() + " has been countered due to "
+ controller.getName() + " not paying " + cost.getText());
return true;
}
}
}
}
return false;
}
@Override
public CephalidShrineEffect copy() {
return new CephalidShrineEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(getTargetPointer().getFirst(game, source));
Spell spell = (Spell) getValue("spellCast");
if (player == null || spell == null) {
return false;
}
int amount = game
.getState()
.getPlayersInRange(source.getControllerId(), game)
.stream()
.map(game::getPlayer)
.filter(Objects::nonNull)
.map(Player::getGraveyard)
.map(g -> g.getCards(game))
.flatMap(Collection::stream)
.filter(card -> card.sharesName(spell, game))
.mapToInt(x -> 1)
.sum();
Cost cost = new GenericManaCost(amount);
return (cost.canPay(source, source, player.getId(), game)
&& player.chooseUse(outcome, "Pay {" + amount + "}?", source, game)
&& cost.pay(source, game, source, player.getId(), false))
|| game.getStack().counter(spell.getId(), source, game);
}
}

View file

@ -3,40 +3,30 @@ package mage.cards.d;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.delayed.OnLeaveReturnExiledAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ExileUntilSourceLeavesEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.TargetController;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterNonlandPermanent;
import mage.filter.predicate.mageobject.NamePredicate;
import mage.filter.predicate.permanent.ControllerIdPredicate;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.TargetPermanent;
import mage.util.CardUtil;
import mage.target.targetpointer.FixedTargets;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
/**
* @author TheElk801
*/
public final class DeputyOfDetention extends CardImpl {
private static final FilterPermanent filter = new FilterNonlandPermanent("nonland permanent an opponent controls");
static {
filter.add(TargetController.OPPONENT.getControllerPredicate());
}
public DeputyOfDetention(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}{U}");
@ -47,7 +37,7 @@ public final class DeputyOfDetention extends CardImpl {
// When Deputy of Detention enters the battlefield, exile target nonland permanent an opponent controls and all other nonland permanents that player controls with the same name as that permanent until Deputy of Detention leaves the battlefield.
Ability ability = new EntersBattlefieldTriggeredAbility(new DeputyOfDetentionExileEffect(), false);
ability.addTarget(new TargetPermanent(filter));
ability.addTarget(new TargetPermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_NON_LAND));
this.addAbility(ability);
}
@ -78,31 +68,25 @@ class DeputyOfDetentionExileEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Permanent permanent = source.getSourcePermanentIfItStillExists(game);
Permanent targeted = game.getPermanent(source.getFirstTarget());
Permanent targeted = game.getPermanent(getTargetPointer().getFirst(game, source));
if (permanent == null || controller == null || targeted == null) {
return false;
}
FilterPermanent filter = new FilterNonlandPermanent();
filter.add(new ControllerIdPredicate(targeted.getControllerId()));
filter.add(new NamePredicate(targeted.getName()));
Set<Card> toExile = new LinkedHashSet<>();
for (Permanent creature : game.getBattlefield().getActivePermanents(filter, controller.getId(), game)) {
toExile.add(creature);
}
if (!toExile.isEmpty()) {
controller.moveCardsToExile(toExile, source, game, true, CardUtil.getCardExileZoneId(game, source), permanent.getIdName());
game.addDelayedTriggeredAbility(new OnLeaveReturnExiledAbility(), source);
}
return true;
Set<Card> set = game
.getBattlefield()
.getActivePermanents(
StaticFilters.FILTER_CONTROLLED_PERMANENT_NON_LAND,
targeted.getControllerId(), source, game
)
.stream()
.filter(p -> p.sharesName(targeted, game))
.collect(Collectors.toSet());
set.add(targeted);
return new ExileUntilSourceLeavesEffect().setTargetPointer(new FixedTargets(set, game)).apply(game, source);
}
@Override
public DeputyOfDetentionExileEffect copy() {
return new DeputyOfDetentionExileEffect(this);
}
}

View file

@ -1,35 +1,34 @@
package mage.cards.d;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.SpellCastAllTriggeredAbility;
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.FilterCard;
import mage.filter.predicate.mageobject.NamePredicate;
import mage.constants.SetTargetPointer;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.stack.Spell;
import mage.players.Player;
import java.util.Collection;
import java.util.Objects;
import java.util.UUID;
/**
* @author jeffwadsworth
* @author TheElk801
*/
public final class DwarvenShrine extends CardImpl {
public DwarvenShrine(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{R}{R}");
// Whenever a player casts a spell, Dwarven Shrine deals X damage to that player, where X is twice the number of cards in all graveyards with the same name as that spell.
this.addAbility(new DwarvenShrineTriggeredAbility());
this.addAbility(new SpellCastAllTriggeredAbility(
new DwarvenShrineEffect(), StaticFilters.FILTER_SPELL_A, false, SetTargetPointer.PLAYER
));
}
private DwarvenShrine(final DwarvenShrine card) {
@ -42,43 +41,12 @@ public final class DwarvenShrine extends CardImpl {
}
}
class DwarvenShrineTriggeredAbility extends TriggeredAbilityImpl {
public DwarvenShrineTriggeredAbility() {
super(Zone.BATTLEFIELD, new DwarvenShrineEffect(), false);
}
private DwarvenShrineTriggeredAbility(final DwarvenShrineTriggeredAbility ability) {
super(ability);
}
@Override
public DwarvenShrineTriggeredAbility copy() {
return new DwarvenShrineTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.SPELL_CAST;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Spell spell = game.getStack().getSpell(event.getTargetId());
MageObject mageObject = game.getObject(sourceId);
if (spell != null && mageObject != null) {
game.getState().setValue("dwarvenShrine" + mageObject, spell);
return true;
}
return false;
}
}
class DwarvenShrineEffect extends OneShotEffect {
DwarvenShrineEffect() {
super(Outcome.Detriment);
staticText = "Whenever a player casts a spell, {this} deals X damage to that player, where X is twice the number of cards in all graveyards with the same name as that spell.";
staticText = "{this} deals X damage to that player, where X is twice " +
"the number of cards in all graveyards with the same name as that spell.";
}
private DwarvenShrineEffect(final DwarvenShrineEffect effect) {
@ -87,28 +55,24 @@ class DwarvenShrineEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
int count = 0;
MageObject mageObject = game.getObject(source);
if (mageObject != null) {
Spell spell = (Spell) game.getState().getValue("dwarvenShrine" + mageObject);
if (spell != null) {
Player controller = game.getPlayer(spell.getControllerId());
if (controller != null) {
String name = spell.getName();
FilterCard filterCardName = new FilterCard();
filterCardName.add(new NamePredicate(name));
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
Player player = game.getPlayer(playerId);
if (player != null) {
count += player.getGraveyard().count(filterCardName, game);
}
}
controller.damage(count * 2, mageObject.getId(), source, game);
return true;
}
}
Player player = game.getPlayer(getTargetPointer().getFirst(game, source));
Spell spell = (Spell) getValue("spellCast");
if (player == null || spell == null) {
return false;
}
return false;
int count = game
.getState()
.getPlayersInRange(source.getControllerId(), game)
.stream()
.map(game::getPlayer)
.filter(Objects::nonNull)
.map(Player::getGraveyard)
.map(g -> g.getCards(game))
.flatMap(Collection::stream)
.filter(c -> c.sharesName(spell, game))
.mapToInt(x -> 1)
.sum();
return count > 0 && player.damage(2 * count, source, game) > 0;
}
@Override

View file

@ -1,6 +1,5 @@
package mage.cards.h;
import mage.ApprovingObject;
import mage.abilities.Ability;
import mage.abilities.common.SpellCastControllerTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
@ -9,30 +8,42 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SetTargetPointer;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.common.FilterInstantOrSorcerySpell;
import mage.filter.predicate.mageobject.NamePredicate;
import mage.filter.StaticFilters;
import mage.filter.predicate.ObjectSourcePlayer;
import mage.filter.predicate.ObjectSourcePlayerPredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.stack.Spell;
import mage.players.Player;
import mage.target.common.TargetCardInYourGraveyard;
import mage.watchers.common.CastFromHandWatcher;
import mage.util.CardUtil;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public final class HarnessTheStorm extends CardImpl {
private static final FilterCard filter = new FilterCard("card with the same name as that spell from your graveyard");
static {
filter.add(HarnessTheStormPredicate.instance);
}
public HarnessTheStorm(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}");
// Whenever you cast an instant or sorcery spell from your hand, you may cast
// target card with the same name as that spell from your graveyard.
this.addAbility(new HarnessTheStormTriggeredAbility(), new CastFromHandWatcher());
// Whenever you cast an instant or sorcery spell from your hand, you may cast target card with the same name as that spell from your graveyard.
Ability ability = new SpellCastControllerTriggeredAbility(
Zone.BATTLEFIELD, new HarnessTheStormEffect(),
StaticFilters.FILTER_SPELL_AN_INSTANT_OR_SORCERY,
false, SetTargetPointer.NONE, Zone.HAND
);
ability.addTarget(new TargetCardInYourGraveyard(filter));
this.addAbility(ability);
}
private HarnessTheStorm(final HarnessTheStorm card) {
@ -46,41 +57,21 @@ public final class HarnessTheStorm extends CardImpl {
}
class HarnessTheStormTriggeredAbility extends SpellCastControllerTriggeredAbility {
private static final FilterInstantOrSorcerySpell filterSpell = new FilterInstantOrSorcerySpell("an instant or sorcery spell from your hand");
HarnessTheStormTriggeredAbility() {
super(new HarnessTheStormEffect(), filterSpell, false);
}
private HarnessTheStormTriggeredAbility(final HarnessTheStormTriggeredAbility ability) {
super(ability);
}
enum HarnessTheStormPredicate implements ObjectSourcePlayerPredicate<Card> {
instance;
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (super.checkTrigger(event, game)) {
CastFromHandWatcher watcher = game.getState().getWatcher(CastFromHandWatcher.class);
if (watcher != null && watcher.spellWasCastFromHand(event.getSourceId())) {
Spell spell = game.getState().getStack().getSpell(event.getSourceId());
if (spell != null) {
FilterCard filterCard = new FilterCard("a card named " + spell.getName() + " in your graveyard");
filterCard.add(new NamePredicate(spell.getName()));
this.getTargets().clear();
this.getTargets().add(new TargetCardInYourGraveyard(filterCard));
return true;
}
}
}
return false;
public boolean apply(ObjectSourcePlayer<Card> input, Game game) {
return input
.getSource()
.getEffects()
.stream()
.map(effect -> effect.getValue("spellCast"))
.map(Spell.class::cast)
.findFirst()
.map(spell -> spell.sharesName(input.getObject(), game))
.orElse(false);
}
@Override
public HarnessTheStormTriggeredAbility copy() {
return new HarnessTheStormTriggeredAbility(this);
}
}
class HarnessTheStormEffect extends OneShotEffect {
@ -103,20 +94,8 @@ class HarnessTheStormEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller == null) {
return false;
}
Card card = controller.getGraveyard().get(getTargetPointer().getFirst(game, source), game);
if (card == null) {
return false;
}
if (controller.chooseUse(outcome, "Cast " + card.getIdName() + " from your graveyard?", source, game)) {
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
controller.cast(controller.chooseAbilityForCast(card, game, false),
game, false, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
}
return true;
Card card = game.getCard(getTargetPointer().getFirst(game, source));
return controller != null && card != null
&& CardUtil.castSpellWithAttributesForFree(controller, source, game, card);
}
}

View file

@ -1,27 +1,24 @@
package mage.cards.l;
import java.util.HashSet;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.FilterPermanent;
import mage.filter.StaticFilters;
import mage.filter.predicate.mageobject.NamePredicate;
import mage.filter.predicate.permanent.ControllerIdPredicate;
import mage.filter.predicate.permanent.TokenPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetNonlandPermanent;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
/**
*
* @author weirddan455
*/
public final class LegionsToAshes extends CardImpl {
@ -48,7 +45,8 @@ class LegionsToAshesEffect extends OneShotEffect {
LegionsToAshesEffect() {
super(Outcome.Exile);
this.staticText = "Exile target nonland permanent an opponent controls and all tokens that player controls with the same name as that permanent.";
this.staticText = "Exile target nonland permanent an opponent controls " +
"and all tokens that player controls with the same name as that permanent.";
}
private LegionsToAshesEffect(final LegionsToAshesEffect effect) {
@ -63,17 +61,21 @@ class LegionsToAshesEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Permanent targetPermanent = game.getPermanent(source.getFirstTarget());
Permanent targetPermanent = game.getPermanent(getTargetPointer().getFirst(game, source));
if (controller == null || targetPermanent == null) {
return false;
}
FilterPermanent filter = new FilterPermanent();
filter.add(TokenPredicate.TRUE);
filter.add(new ControllerIdPredicate(targetPermanent.getControllerId()));
filter.add(new NamePredicate(targetPermanent.getName()));
HashSet<Permanent> toExile = new HashSet<>(game.getBattlefield().getActivePermanents(filter, controller.getId(), source, game));
toExile.add(targetPermanent);
controller.moveCards(toExile, Zone.EXILED, source, game);
return true;
Set<Card> set = game
.getBattlefield()
.getActivePermanents(
StaticFilters.FILTER_PERMANENT_TOKEN,
source.getControllerId(), source, game
)
.stream()
.filter(permanent -> permanent.sharesName(targetPermanent, game)
&& permanent.isControlledBy(targetPermanent.getControllerId()))
.collect(Collectors.toSet());
set.add(targetPermanent);
return controller.moveCards(set, Zone.EXILED, source, game);
}
}

View file

@ -1,7 +1,5 @@
package mage.cards.m;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.costs.common.SacrificeTargetCost;
import mage.abilities.effects.OneShotEffect;
@ -12,27 +10,19 @@ import mage.constants.CardType;
import mage.constants.Outcome;
import mage.filter.FilterCard;
import mage.filter.StaticFilters;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.mageobject.NamePredicate;
import mage.filter.predicate.permanent.TokenPredicate;
import mage.filter.predicate.mageobject.SharesNamePredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.common.TargetCardInLibrary;
import mage.target.common.TargetControlledCreaturePermanent;
import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
/**
*
* @author TheElk801
*/
public final class MaskOfTheMimic extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nontoken creature");
static {
filter.add(TokenPredicate.FALSE);
}
public MaskOfTheMimic(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{U}");
@ -41,7 +31,7 @@ public final class MaskOfTheMimic extends CardImpl {
// Search your library for a card with the same name as target nontoken creature and put that card onto the battlefield. Then shuffle your library.
this.getSpellAbility().addEffect(new MaskOfTheMimicEffect());
this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter));
this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_NON_TOKEN));
}
private MaskOfTheMimic(final MaskOfTheMimic card) {
@ -58,7 +48,7 @@ class MaskOfTheMimicEffect extends OneShotEffect {
MaskOfTheMimicEffect() {
super(Outcome.Benefit);
this.staticText = "Search your library for a card with the same name as target nontoken creature,"
this.staticText = "search your library for a card with the same name as target nontoken creature,"
+ " put that card onto the battlefield, then shuffle.";
}
@ -73,12 +63,12 @@ class MaskOfTheMimicEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Permanent creature = game.getPermanent(source.getFirstTarget());
Permanent creature = game.getPermanent(getTargetPointer().getFirst(game, source));
if (creature == null) {
return false;
}
FilterCard filter = new FilterCard("a card named " + creature.getName());
filter.add(new NamePredicate(creature.getName()));
FilterCard filter = new FilterCard("a card with the same name");
filter.add(new SharesNamePredicate(creature));
return new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(filter)).apply(game, source);
}
}

View file

@ -1,7 +1,5 @@
package mage.cards.m;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.ReplicateAbility;
@ -13,15 +11,16 @@ import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.StaticFilters;
import mage.filter.predicate.mageobject.NamePredicate;
import mage.filter.predicate.mageobject.SharesNamePredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.TargetPermanent;
import mage.target.common.TargetCardInLibrary;
import java.util.UUID;
/**
*
* @author TheElk801
*/
public final class Mimeofacture extends CardImpl {
@ -68,7 +67,7 @@ class MimeofactureEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Permanent permanent = game.getPermanent(source.getFirstTarget());
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
if (controller == null || permanent == null) {
return false;
}
@ -76,8 +75,8 @@ class MimeofactureEffect extends OneShotEffect {
if (opponent == null) {
return false;
}
FilterCard filter = new FilterCard("card named " + permanent.getName());
filter.add(new NamePredicate(permanent.getName()));
FilterCard filter = new FilterCard("card with the same name");
filter.add(new SharesNamePredicate(permanent));
TargetCardInLibrary target = new TargetCardInLibrary(0, 1, filter);
if (controller.searchLibrary(target, source, game, opponent.getId())) {
Card card = opponent.getLibrary().getCard(target.getFirstTarget(), game);

View file

@ -1,37 +1,32 @@
package mage.cards.m;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.SpellCastControllerTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Outcome;
import mage.constants.SuperType;
import mage.constants.Zone;
import mage.constants.*;
import mage.filter.FilterCard;
import mage.filter.predicate.mageobject.NamePredicate;
import mage.filter.StaticFilters;
import mage.filter.predicate.mageobject.SharesNamePredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.stack.Spell;
import mage.players.Player;
import mage.target.common.TargetCardInHand;
import mage.target.common.TargetCardInLibrary;
import mage.target.common.TargetCardInYourGraveyard;
import java.util.UUID;
/**
*
* @author emerald000
*/
public final class MishraArtificerProdigy extends CardImpl {
public MishraArtificerProdigy(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{U}{B}{R}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}{B}{R}");
this.supertype.add(SuperType.LEGENDARY);
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.ARTIFICER);
@ -39,7 +34,9 @@ public final class MishraArtificerProdigy extends CardImpl {
this.toughness = new MageInt(4);
// Whenever you cast an artifact spell, you may search your graveyard, hand, and/or library for a card with the same name as that spell and put it onto the battlefield. If you search your library this way, shuffle it.
this.addAbility(new MishraArtificerProdigyTriggeredAbility());
this.addAbility(new SpellCastControllerTriggeredAbility(
new MishraArtificerProdigyEffect(), StaticFilters.FILTER_SPELL_AN_ARTIFACT, true
));
}
private MishraArtificerProdigy(final MishraArtificerProdigy card) {
@ -52,56 +49,16 @@ public final class MishraArtificerProdigy extends CardImpl {
}
}
class MishraArtificerProdigyTriggeredAbility extends TriggeredAbilityImpl {
MishraArtificerProdigyTriggeredAbility() {
super(Zone.BATTLEFIELD, new MishraArtificerProdigyEffect(), true);
}
private MishraArtificerProdigyTriggeredAbility(final MishraArtificerProdigyTriggeredAbility ability) {
super(ability);
}
@Override
public MishraArtificerProdigyTriggeredAbility copy() {
return new MishraArtificerProdigyTriggeredAbility(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.isArtifact(game)) {
((MishraArtificerProdigyEffect) this.getEffects().get(0)).setName(spell.getName());
return true;
}
}
return false;
}
@Override
public String getRule() {
return "Whenever you cast an artifact spell, you may search your graveyard, hand, and/or library for a card with the same name as that spell and put it onto the battlefield. If you search your library this way, shuffle.";
}
}
class MishraArtificerProdigyEffect extends OneShotEffect {
private String cardName;
MishraArtificerProdigyEffect() {
super(Outcome.PutCardInPlay);
this.staticText = "Search your graveyard, hand, and/or library for a card named <i>" + cardName + "</i> and put it onto the battlefield. If you search your library this way, shuffle.";
this.staticText = "search your graveyard, hand, and/or library for a card with the same name as " +
"that spell and put it onto the battlefield. If you search your library this way, shuffle";
}
private MishraArtificerProdigyEffect(final MishraArtificerProdigyEffect effect) {
super(effect);
this.cardName = effect.cardName;
}
@Override
@ -112,43 +69,40 @@ class MishraArtificerProdigyEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
FilterCard filter = new FilterCard("card named " + this.cardName);
filter.add(new NamePredicate(cardName));
Card card = null;
// Graveyard
if (controller.chooseUse(Outcome.Neutral, "Search your graveyard?", source, game)) {
// You can't fail to find the card in your graveyard because it's not hidden
TargetCardInYourGraveyard target = new TargetCardInYourGraveyard(1, 1, filter);
if (controller.choose(Outcome.PutCardInPlay, controller.getGraveyard(), target, source, game)) {
card = game.getCard(target.getFirstTarget());
}
}
// Hand
if (card == null && controller.chooseUse(Outcome.Neutral, "Search your hand?", source, game)) {
TargetCardInHand target = new TargetCardInHand(0, 1, filter);
if (controller.choose(Outcome.PutCardInPlay, controller.getHand(), target, source, game)) {
card = game.getCard(target.getFirstTarget());
}
}
// Library
if (card == null && controller.chooseUse(Outcome.Neutral, "Search your library?", source, game)) {
TargetCardInLibrary target = new TargetCardInLibrary(0, 1, filter);
if (controller.searchLibrary(target, source, game)) {
card = game.getCard(target.getFirstTarget());
}
controller.shuffleLibrary(source, game);
}
// Put on battlefield
if (card != null) {
controller.moveCards(card, Zone.BATTLEFIELD, source, game);
}
return true;
Spell spell = (Spell) getValue("spellCast");
if (controller == null || spell == null) {
return false;
}
return false;
}
public void setName(String cardName) {
this.cardName = cardName;
FilterCard filter = new FilterCard("card with the same name");
filter.add(new SharesNamePredicate(spell));
Card card = null;
// Graveyard
if (controller.chooseUse(Outcome.Neutral, "Search your graveyard?", source, game)) {
// You can't fail to find the card in your graveyard because it's not hidden
TargetCardInYourGraveyard target = new TargetCardInYourGraveyard(1, 1, filter);
if (controller.choose(Outcome.PutCardInPlay, controller.getGraveyard(), target, source, game)) {
card = game.getCard(target.getFirstTarget());
}
}
// Hand
if (card == null && controller.chooseUse(Outcome.Neutral, "Search your hand?", source, game)) {
TargetCardInHand target = new TargetCardInHand(0, 1, filter);
if (controller.choose(Outcome.PutCardInPlay, controller.getHand(), target, source, game)) {
card = game.getCard(target.getFirstTarget());
}
}
// Library
if (card == null && controller.chooseUse(Outcome.Neutral, "Search your library?", source, game)) {
TargetCardInLibrary target = new TargetCardInLibrary(0, 1, filter);
if (controller.searchLibrary(target, source, game)) {
card = game.getCard(target.getFirstTarget());
}
controller.shuffleLibrary(source, game);
}
// Put on battlefield
if (card != null) {
controller.moveCards(card, Zone.BATTLEFIELD, source, game);
}
return true;
}
}

View file

@ -1,36 +1,38 @@
package mage.cards.m;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.*;
import mage.abilities.effects.common.LookLibraryAndPickControllerEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.constants.PutCards;
import mage.filter.FilterCard;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.NamePredicate;
import mage.filter.StaticFilters;
import mage.filter.predicate.ObjectSourcePlayer;
import mage.filter.predicate.ObjectSourcePlayerPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.TargetCard;
import java.util.UUID;
/**
*
* @author North
*/
public final class MitoticManipulation extends CardImpl {
private static final FilterCard filter = new FilterCard("a card with the same name as a permanent");
static {
filter.add(MitoticManipulationPredicate.instance);
}
public MitoticManipulation(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{U}{U}");
this.getSpellAbility().addEffect(new MitoticManipulationEffect());
this.getSpellAbility().addEffect(new LookLibraryAndPickControllerEffect(
7, 1, filter, PutCards.BATTLEFIELD, PutCards.BOTTOM_ANY
).setText("look at the top seven cards of your library. You may put one of those cards onto the battlefield " +
"if it has the same name as a permanent. Put the rest on the bottom of your library in any order"));
}
private MitoticManipulation(final MitoticManipulation card) {
@ -43,57 +45,18 @@ public final class MitoticManipulation extends CardImpl {
}
}
class MitoticManipulationEffect extends OneShotEffect {
MitoticManipulationEffect() {
super(Outcome.PutCardInPlay);
this.staticText = "Look at the top seven cards of your library. You may put one of those cards onto the battlefield if it has the same name as a permanent. Put the rest on the bottom of your library in any order";
}
private MitoticManipulationEffect(final MitoticManipulationEffect effect) {
super(effect);
}
enum MitoticManipulationPredicate implements ObjectSourcePlayerPredicate<Card> {
instance;
@Override
public MitoticManipulationEffect copy() {
return new MitoticManipulationEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
MageObject sourceObject = source.getSourceObject(game);
if (controller != null && sourceObject != null) {
Set<String> permanentNames = new HashSet<>();
for (Permanent permanent : game.getBattlefield().getActivePermanents(source.getControllerId(), game)) {
permanentNames.add(permanent.getName());
}
Cards cardsFromTop = new CardsImpl();
cardsFromTop.addAllCards(controller.getLibrary().getTopCards(game, 7));
controller.lookAtCards(sourceObject.getIdName(), cardsFromTop, game);
FilterCard filter = new FilterCard("card to put onto the battlefield");
List<NamePredicate> namePredicates = new ArrayList<>();
for (String name : permanentNames) {
namePredicates.add(new NamePredicate(name));
}
if (!namePredicates.isEmpty() && !cardsFromTop.isEmpty()) {
filter.add(Predicates.or(namePredicates));
TargetCard target = new TargetCard(Zone.LIBRARY, filter);
if (cardsFromTop.count(filter, source.getControllerId(), source, game) > 0
&& controller.chooseUse(Outcome.PutCardInPlay, "Put a card on the battlefield?", source, game)) {
if (controller.choose(Outcome.PutCardInPlay, cardsFromTop, target, source, game)) {
Card card = cardsFromTop.get(target.getFirstTarget(), game);
if (card != null) {
controller.moveCards(card, Zone.BATTLEFIELD, source, game);
cardsFromTop.remove(card);
}
}
}
}
controller.putCardsOnBottomOfLibrary(cardsFromTop, game, source, true);
return true;
}
return false;
public boolean apply(ObjectSourcePlayer<Card> input, Game game) {
return game
.getBattlefield()
.getActivePermanents(
StaticFilters.FILTER_PERMANENT,
input.getPlayerId(), input.getSource(), game
)
.stream()
.anyMatch(permanent -> permanent.sharesName(input.getObject(), game));
}
}

View file

@ -1,7 +1,5 @@
package mage.cards.m;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.SacrificeSourceCost;
@ -9,23 +7,27 @@ import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ExileAllEffect;
import mage.abilities.effects.common.ExileGraveyardAllPlayersEffect;
import mage.abilities.effects.common.ExileTargetEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.FilterPermanent;
import mage.filter.StaticFilters;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.NamePredicate;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetCardInGraveyard;
import java.util.Collection;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
/**
*
* @author TheElk801
*/
public final class MoratoriumStone extends CardImpl {
@ -81,15 +83,31 @@ class MoratoriumStoneEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Card card = game.getCard(source.getFirstTarget());
if (card == null) {
Player player = game.getPlayer(source.getControllerId());
Card card = game.getCard(getTargetPointer().getFirst(game, source));
if (player == null || card == null) {
return false;
}
String cardName = card.getName();
FilterCard filter1 = new FilterCard();
filter1.add(new NamePredicate(cardName));
FilterPermanent filter2 = new FilterPermanent();
filter2.add(new NamePredicate(cardName));
return new ExileGraveyardAllPlayersEffect(filter1).apply(game, source) && new ExileAllEffect(filter2).apply(game, source);
Set<Card> cards = game
.getState()
.getPlayersInRange(source.getControllerId(), game)
.stream()
.map(game::getPlayer)
.filter(Objects::nonNull)
.map(Player::getGraveyard)
.map(g -> g.getCards(game))
.flatMap(Collection::stream)
.filter(c -> c.sharesName(card, game))
.collect(Collectors.toSet());
cards.add(card);
game.getBattlefield()
.getActivePermanents(
StaticFilters.FILTER_PERMANENT,
source.getControllerId(), source, game
)
.stream()
.filter(permanent -> permanent.sharesName(card, game))
.forEach(cards::add);
return player.moveCards(card, Zone.EXILED, source, game);
}
}

View file

@ -1,7 +1,5 @@
package mage.cards.n;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SpellCastAllTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
@ -10,17 +8,18 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SetTargetPointer;
import mage.filter.FilterCard;
import mage.filter.StaticFilters;
import mage.filter.predicate.mageobject.NamePredicate;
import mage.game.Game;
import mage.game.permanent.token.SquirrelToken;
import mage.game.stack.Spell;
import mage.players.Player;
import java.util.Collection;
import java.util.Objects;
import java.util.UUID;
/**
*
* @author LevelX2
* @author TheElk801
*/
public final class NantukoShrine extends CardImpl {
@ -28,7 +27,9 @@ public final class NantukoShrine extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{G}{G}");
// Whenever a player casts a spell, that player puts X 1/1 green Squirrel creature tokens onto the battlefield, where X is the number of cards in all graveyards with the same name as that spell.
this.addAbility(new SpellCastAllTriggeredAbility(new NantukoShrineEffect(), StaticFilters.FILTER_SPELL, false, SetTargetPointer.SPELL));
this.addAbility(new SpellCastAllTriggeredAbility(
new NantukoShrineEffect(), StaticFilters.FILTER_SPELL, false, SetTargetPointer.PLAYER
));
}
private NantukoShrine(final NantukoShrine card) {
@ -59,26 +60,23 @@ class NantukoShrineEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Spell spell = game.getStack().getSpell(getTargetPointer().getFirst(game, source));
if (spell != null) {
Player controller = game.getPlayer(spell.getControllerId());
if (controller != null) {
int count = 0;
String name = spell.getName();
FilterCard filterCardName = new FilterCard();
filterCardName.add(new NamePredicate(name));
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
Player player = game.getPlayer(playerId);
if (player != null) {
count += player.getGraveyard().count(filterCardName, game);
}
}
if (count > 0) {
new SquirrelToken().putOntoBattlefield(count, game, source, spell.getControllerId());
}
return true;
}
Player player = game.getPlayer(getTargetPointer().getFirst(game, source));
Spell spell = (Spell) getValue("spellCast");
if (player == null || spell == null) {
return false;
}
return false;
int count = game
.getState()
.getPlayersInRange(source.getControllerId(), game)
.stream()
.map(game::getPlayer)
.filter(Objects::nonNull)
.map(Player::getGraveyard)
.map(g -> g.getCards(game))
.flatMap(Collection::stream)
.filter(c -> c.sharesName(spell, game))
.mapToInt(x -> 1)
.sum();
return count > 0 && new SquirrelToken().putOntoBattlefield(count, game, source, player.getId());
}
}

View file

@ -1,4 +1,3 @@
package mage.cards.p;
import mage.abilities.Ability;
@ -9,8 +8,7 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.filter.FilterCard;
import mage.filter.common.FilterPermanentCard;
import mage.filter.predicate.mageobject.NamePredicate;
import mage.filter.predicate.mageobject.SharesNamePredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.common.TargetCardInLibrary;
@ -19,7 +17,6 @@ import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
/**
*
* @author ciaccona007
*/
public final class PackHunt extends CardImpl {
@ -41,11 +38,13 @@ public final class PackHunt extends CardImpl {
return new PackHunt(this);
}
}
class PackHuntEffect extends OneShotEffect {
PackHuntEffect() {
super(Outcome.Benefit);
this.staticText = "Search your library for up to three cards with the same name as target creature, reveal them, and put them into your hand. Then shuffle";
this.staticText = "search your library for up to three cards with the same name as " +
"target creature, reveal them, and put them into your hand. Then shuffle";
}
private PackHuntEffect(final PackHuntEffect effect) {
@ -59,9 +58,14 @@ class PackHuntEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getFirstTarget());
FilterCard filter = new FilterPermanentCard();
filter.add(new NamePredicate(permanent.getName()));
return new SearchLibraryPutInHandEffect(new TargetCardInLibrary(0,3, filter), true).apply(game, source);
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
if (permanent == null) {
return false;
}
FilterCard filter = new FilterCard();
filter.add(new SharesNamePredicate(permanent));
return new SearchLibraryPutInHandEffect(
new TargetCardInLibrary(0, 3, filter), true
).apply(game, source);
}
}

View file

@ -1,21 +1,19 @@
package mage.cards.r;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.Ability;
import mage.abilities.common.DiesCreatureTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Zone;
import mage.constants.Outcome;
import mage.filter.FilterCard;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.mageobject.NamePredicate;
import mage.filter.predicate.permanent.TokenPredicate;
import mage.filter.StaticFilters;
import mage.filter.predicate.mageobject.SharesNamePredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetCardInLibrary;
import java.util.UUID;
@ -29,7 +27,9 @@ public final class Remembrance extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{W}");
// Whenever a nontoken creature you control dies, you may search your library for a card with the same name as that creature, reveal it, and put it into your hand. If you do, shuffle your library.
this.addAbility(new RemembranceTriggeredAbility());
this.addAbility(new DiesCreatureTriggeredAbility(
new RemembranceEffect(), true, StaticFilters.FILTER_CONTROLLED_CREATURE_NON_TOKEN
));
}
private Remembrance(final Remembrance card) {
@ -42,54 +42,32 @@ public final class Remembrance extends CardImpl {
}
}
class RemembranceTriggeredAbility extends TriggeredAbilityImpl {
class RemembranceEffect extends OneShotEffect {
private static final FilterPermanent filter = new FilterControlledCreaturePermanent();
static {
filter.add(TokenPredicate.FALSE);
RemembranceEffect() {
super(Outcome.Benefit);
staticText = "search your library for a card with the same name as that creature, " +
"reveal it, and put it into your hand. If you do, shuffle your library";
}
RemembranceTriggeredAbility() {
super(Zone.BATTLEFIELD, null, true);
}
private RemembranceTriggeredAbility(final RemembranceTriggeredAbility ability) {
super(ability);
private RemembranceEffect(final RemembranceEffect effect) {
super(effect);
}
@Override
public RemembranceTriggeredAbility copy() {
return new RemembranceTriggeredAbility(this);
public RemembranceEffect copy() {
return new RemembranceEffect(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ZONE_CHANGE;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (!((ZoneChangeEvent) event).isDiesEvent()) {
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
Permanent permanent = (Permanent) getValue("creatureDied");
if (player == null || permanent == null) {
return false;
}
Permanent permanent = game.getPermanentOrLKIBattlefield(event.getTargetId());
if (permanent != null && filter.match(permanent, game)) {
FilterCard filterCard = new FilterCard("card named " + permanent.getName());
filterCard.add(new NamePredicate(permanent.getName()));
this.getEffects().clear();
this.addEffect(new SearchLibraryPutInHandEffect(
new TargetCardInLibrary(filterCard), true
));
return true;
}
return false;
}
@Override
public String getRule() {
return "Whenever a nontoken creature you control dies, " +
"you may search your library for a card with the same name as that creature, " +
"reveal it, put it into your hand, then shuffle.";
FilterCard filter = new FilterCard("card with the same name");
filter.add(new SharesNamePredicate(permanent));
return new SearchLibraryPutInHandEffect(new TargetCardInLibrary(filter), true).apply(game, source);
}
}

View file

@ -11,12 +11,11 @@ import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.common.FilterNonlandCard;
import mage.filter.predicate.mageobject.NamePredicate;
import mage.filter.predicate.mageobject.SharesNamePredicate;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetCardInLibrary;
import mage.target.common.TargetCardInYourGraveyard;
import mage.util.CardUtil;
import java.util.UUID;
@ -72,9 +71,8 @@ class SecretSalvageEffect extends OneShotEffect {
return false;
}
controller.moveCards(targetCard, Zone.EXILED, source, game);
String nameToSearch = CardUtil.getCardNameForSameNameSearch(targetCard);
FilterCard nameFilter = new FilterCard("card named " + nameToSearch);
nameFilter.add(new NamePredicate(nameToSearch));
FilterCard nameFilter = new FilterCard("card with the same name");
nameFilter.add(new SharesNamePredicate(targetCard));
return new SearchLibraryPutInHandEffect(new TargetCardInLibrary(
0, Integer.MAX_VALUE, nameFilter
), true).apply(game, source);

View file

@ -4,21 +4,21 @@ import mage.abilities.Ability;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.FlashbackAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.mageobject.NamePredicate;
import mage.filter.predicate.permanent.PermanentIdPredicate;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetCreaturePermanent;
import mage.util.CardUtil;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
/**
* @author North
@ -28,10 +28,10 @@ public final class SeverTheBloodline extends CardImpl {
public SeverTheBloodline(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{B}");
// Exile target creature and all other creatures with the same name as that creature.
this.getSpellAbility().addEffect(new SeverTheBloodlineEffect());
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
// Flashback {5}{B}{B}
this.addAbility(new FlashbackAbility(this, new ManaCostsImpl<>("{5}{B}{B}")));
}
@ -64,20 +64,21 @@ class SeverTheBloodlineEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Player player = game.getPlayer(source.getControllerId());
Permanent targetPermanent = game.getPermanent(getTargetPointer().getFirst(game, source));
if (controller != null && targetPermanent != null) {
FilterCreaturePermanent filter = new FilterCreaturePermanent();
if (CardUtil.haveEmptyName(targetPermanent)) {
filter.add(new PermanentIdPredicate(targetPermanent.getId())); // if no name (face down creature) only the creature itself is selected
} else {
filter.add(new NamePredicate(targetPermanent.getName()));
}
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game)) {
controller.moveCardToExileWithInfo(permanent, null, "", source, game, Zone.BATTLEFIELD, true);
}
return true;
if (player == null || targetPermanent == null) {
return false;
}
return false;
Set<Card> set = game
.getBattlefield()
.getActivePermanents(
StaticFilters.FILTER_PERMANENT_CREATURE,
source.getControllerId(), source, game
)
.stream()
.filter(permanent -> permanent.sharesName(targetPermanent, game))
.collect(Collectors.toSet());
set.add(targetPermanent);
return player.moveCards(set, Zone.EXILED, source, game);
}
}

View file

@ -1,11 +1,8 @@
package mage.cards.s;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
@ -14,17 +11,21 @@ import mage.abilities.keyword.EquipAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterLandCard;
import mage.filter.predicate.mageobject.NamePredicate;
import mage.constants.AbilityWord;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.filter.StaticFilters;
import mage.game.ExileZone;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetCardInLibrary;
import mage.util.CardUtil;
import java.util.Set;
import java.util.UUID;
/**
*
* @author Loki
*/
public final class StrataScythe extends CardImpl {
@ -37,10 +38,12 @@ public final class StrataScythe extends CardImpl {
this.addAbility(new EntersBattlefieldTriggeredAbility(new StrataScytheImprintEffect()).setAbilityWord(AbilityWord.IMPRINT));
// Equipped creature gets +1/+1 for each land on the battlefield with the same name as the exiled card.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(SameNameAsExiledCountValue.getInstance(), SameNameAsExiledCountValue.getInstance())));
this.addAbility(new SimpleStaticAbility(new BoostEquippedEffect(
StrataScytheValue.instance, StrataScytheValue.instance
)));
// Equip {3}
this.addAbility(new EquipAbility(Outcome.BoostCreature, new GenericManaCost(3), false));
this.addAbility(new EquipAbility(3, false));
}
private StrataScythe(final StrataScythe card) {
@ -71,19 +74,15 @@ class StrataScytheImprintEffect extends OneShotEffect {
if (player == null) {
return false;
}
TargetCardInLibrary target = new TargetCardInLibrary(new FilterLandCard());
if (player.searchLibrary(target, source, game)) {
if (!target.getTargets().isEmpty()) {
UUID cardId = target.getTargets().get(0);
Card card = player.getLibrary().remove(cardId, game);
if (card != null) {
card.moveToExile(source.getSourceId(), "Strata Scythe", source, game);
Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent != null) {
permanent.imprint(card.getId(), game);
}
}
}
TargetCardInLibrary target = new TargetCardInLibrary(StaticFilters.FILTER_CARD_LAND_A);
player.searchLibrary(target, source, game);
Card card = player.getLibrary().getCard(target.getFirstTarget(), game);
if (card != null) {
player.moveCardsToExile(
card, source, game, true,
CardUtil.getExileZoneId(game, source),
CardUtil.getSourceName(game, source)
);
}
player.shuffleLibrary(source, game);
return true;
@ -96,31 +95,32 @@ class StrataScytheImprintEffect extends OneShotEffect {
}
class SameNameAsExiledCountValue implements DynamicValue {
private static final SameNameAsExiledCountValue instance = new SameNameAsExiledCountValue();
public static SameNameAsExiledCountValue getInstance() {
return instance;
}
private SameNameAsExiledCountValue() {
}
enum StrataScytheValue implements DynamicValue {
instance;
@Override
public int calculate(Game game, Ability sourceAbility, Effect effect) {
int value = 0;
Permanent permanent = game.getPermanent(sourceAbility.getSourceId());
if (permanent != null && !permanent.getImprinted().isEmpty()) {
FilterPermanent filterPermanent = new FilterPermanent();
filterPermanent.add(new NamePredicate(game.getCard(permanent.getImprinted().get(0)).getName()));
value = game.getBattlefield().count(filterPermanent, sourceAbility.getControllerId(), sourceAbility, game);
public int calculate(Game game, Ability source, Effect effect) {
ExileZone exileZone = game
.getExile()
.getExileZone(CardUtil.getExileZoneId(
game, source.getSourceId(),
game.getState().getZoneChangeCounter(source.getSourceId())
));
if (exileZone == null || exileZone.isEmpty()) {
return 0;
}
return value;
Set<Card> cards = exileZone.getCards(game);
return game
.getBattlefield()
.getActivePermanents(StaticFilters.FILTER_LAND, source.getControllerId(), source, game)
.stream()
.filter(permanent -> cards.stream().anyMatch(card -> card.sharesName(permanent, game)))
.mapToInt(x -> 1)
.sum();
}
@Override
public DynamicValue copy() {
public StrataScytheValue copy() {
return instance;
}

View file

@ -9,14 +9,14 @@ import mage.constants.CardType;
import mage.constants.SagaChapter;
import mage.constants.SubType;
import mage.filter.FilterPermanent;
import mage.filter.StaticFilters;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.predicate.ObjectSourcePlayer;
import mage.filter.predicate.ObjectSourcePlayerPredicate;
import mage.filter.predicate.mageobject.NamePredicate;
import mage.filter.predicate.permanent.TokenPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.game.permanent.PermanentToken;
import mage.target.common.TargetControlledCreaturePermanent;
import java.util.UUID;
@ -77,15 +77,14 @@ enum TheApprenticesFollyPredicate implements ObjectSourcePlayerPredicate<Permane
@Override
public boolean apply(ObjectSourcePlayer<Permanent> input, Game game) {
String name = input.getObject().getName();
if (name == null || name.isEmpty()) {
return true;
}
FilterControlledPermanent filter = new FilterControlledPermanent();
filter.add(new NamePredicate(name));
filter.add(TokenPredicate.TRUE);
// This works due to the non-token clause on the target. There should be no controlled token with that name.
return game.getBattlefield().count(filter, input.getPlayerId(), input.getSource(), game) == 0;
return game
.getBattlefield()
.getActivePermanents(
StaticFilters.FILTER_CONTROLLED_PERMANENT,
input.getPlayerId(), input.getSource(), game
)
.stream()
.filter(PermanentToken.class::isInstance)
.noneMatch(permanent -> permanent.sharesName(input.getObject(), game));
}
}
}

View file

@ -1,12 +1,8 @@
package mage.cards.v;
import java.util.*;
import mage.MageObject;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.DiesCreatureTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
@ -15,30 +11,35 @@ import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.filter.predicate.mageobject.NamePredicate;
import mage.filter.predicate.mageobject.SharesNamePredicate;
import mage.filter.predicate.permanent.TokenPredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetCardInLibrary;
import java.util.UUID;
/**
*
* @author jeffwadsworth, jimga150
* @author TheElk801
*/
public final class VerdantSuccession extends CardImpl {
private static final FilterPermanent filter = new FilterCreaturePermanent("a green nontoken creature");
static {
filter.add(new ColorPredicate(ObjectColor.GREEN));
filter.add(TokenPredicate.FALSE);
}
public VerdantSuccession(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{4}{G}");
// Whenever a green nontoken creature dies, that creature's controller may search their library for a card
// with the same name as that creature and put it onto the battlefield. If that player does, they shuffle their library.
this.addAbility(new VerdantSuccessionTriggeredAbility());
// Whenever a green nontoken creature dies, that creature's controller may search their library for a card with the same name as that creature and put it onto the battlefield. If that player does, they shuffle their library.
this.addAbility(new DiesCreatureTriggeredAbility(new VerdantSuccessionEffect(), false, filter));
}
private VerdantSuccession(final VerdantSuccession card) {
@ -51,70 +52,16 @@ public final class VerdantSuccession extends CardImpl {
}
}
class VerdantSuccessionTriggeredAbility extends TriggeredAbilityImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("green nontoken creature");
static {
filter.add(new ColorPredicate(ObjectColor.GREEN));
filter.add(TokenPredicate.FALSE);
}
VerdantSuccessionTriggeredAbility() {
super(Zone.BATTLEFIELD, null, true);
}
private VerdantSuccessionTriggeredAbility(final VerdantSuccessionTriggeredAbility ability) {
super(ability);
}
@Override
public VerdantSuccessionTriggeredAbility copy() {
return new VerdantSuccessionTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ZONE_CHANGE;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
ZoneChangeEvent zoneChangeEvent = (ZoneChangeEvent) event;
if (zoneChangeEvent.isDiesEvent()) {
Permanent permanent = (Permanent) game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD);
MageObject mageObject = game.getObject(sourceId);
if (permanent != null && mageObject != null
&& filter.match(permanent, game)) {
this.getEffects().clear();
this.addEffect(new VerdantSuccessionEffect(permanent.getName(), permanent.getControllerId()));
return true;
}
}
return false;
}
@Override
public String getRule() {
return "Whenever a green nontoken creature dies, that creature's controller may search their library for a card with the same name as that creature, put it onto the battlefield, then shuffle.";
}
}
class VerdantSuccessionEffect extends OneShotEffect {
private final String creatureName;
private final UUID controllerId;
VerdantSuccessionEffect(String creatureName, UUID controllerId) {
super(Outcome.PutCardInPlay);
this.creatureName = creatureName;
this.controllerId = controllerId;
VerdantSuccessionEffect() {
super(Outcome.Benefit);
staticText = "that creature's controller may search their library for a card " +
"with the same name as that creature, put it onto the battlefield, then shuffle.";
}
private VerdantSuccessionEffect(final VerdantSuccessionEffect effect) {
super(effect);
this.creatureName = effect.creatureName;
this.controllerId = effect.controllerId;
}
@Override
@ -124,26 +71,25 @@ class VerdantSuccessionEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(controllerId);
if (controller == null) {
Permanent permanent = (Permanent) getValue("creatureDied");
if (permanent == null) {
return false;
}
MageObject mageObject = game.getObject(source);
if (mageObject == null) {
Player player = game.getPlayer(permanent.getControllerId());
if (player == null || !player.chooseUse(
Outcome.PutCreatureInPlay, "Search for a card with the same name?", source, game
)) {
return false;
}
FilterCard filterCard = new FilterCard("Card named " + creatureName);
filterCard.add(new NamePredicate(creatureName));
TargetCardInLibrary target = new TargetCardInLibrary(filterCard);
controller.searchLibrary(target, source, game);
if (target.getTargets().isEmpty()) {
return false;
}
Card card = game.getCard(target.getFirstTarget());
if (card != null
&& controller.moveCards(card, Zone.BATTLEFIELD, source, game)) {
controller.shuffleLibrary(source, game);
FilterCard filter = new FilterCard("card with the same name");
filter.add(new SharesNamePredicate(permanent));
TargetCardInLibrary target = new TargetCardInLibrary(filter);
player.searchLibrary(target, source, game);
Card card = player.getLibrary().getCard(target.getFirstTarget(), game);
if (card != null) {
player.moveCards(card, Zone.BATTLEFIELD, source, game);
}
player.shuffleLibrary(source, game);
return true;
}
}

View file

@ -1,32 +1,30 @@
package mage.cards.w;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.filter.FilterPermanent;
import mage.filter.predicate.mageobject.NamePredicate;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.common.TargetNonlandPermanent;
import java.util.UUID;
/**
*
* @author LoneFox
*/
public final class Winnow extends CardImpl {
public Winnow(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{W}");
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}");
// Destroy target nonland permanent if another permanent with the same name is on the battlefield.
this.getSpellAbility().addEffect(new WinnowEffect());
this.getSpellAbility().addTarget(new TargetNonlandPermanent());
// Draw a card.
this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1).concatBy("<br>"));
}
@ -59,15 +57,16 @@ class WinnowEffect extends DestroyTargetEffect {
@Override
public boolean apply(Game game, Ability source) {
Permanent target = game.getPermanent(source.getFirstTarget());
if(target != null) {
FilterPermanent filter = new FilterPermanent();
filter.add(new NamePredicate(target.getName()));
if(new PermanentsOnBattlefieldCount(filter).calculate(game, source, this) > 1) {
super.apply(game, source);
}
return true;
Permanent target = game.getPermanent(getTargetPointer().getFirst(game, source));
if (target == null) {
return false;
}
return false;
return game
.getBattlefield()
.getActivePermanents(StaticFilters.FILTER_PERMANENT, source.getControllerId(), source, game)
.stream()
.filter(p -> p.sharesName(target, game))
.anyMatch(p -> !p.getId().equals(target.getId()))
&& target.destroy(source, game);
}
}