[FDN] Implement Strongbox Raider

This commit is contained in:
theelk801 2024-10-31 11:41:36 -04:00
parent e0c39f10e8
commit 9226e5239f
15 changed files with 156 additions and 516 deletions

View file

@ -8,19 +8,18 @@ import mage.abilities.condition.Condition;
import mage.abilities.condition.common.SolvedSourceCondition;
import mage.abilities.costs.common.SacrificeSourceCost;
import mage.abilities.decorator.ConditionalActivatedAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.effects.common.ExileTopXMayPlayUntilEffect;
import mage.abilities.hint.common.CaseSolvedHint;
import mage.cards.*;
import mage.constants.*;
import mage.filter.StaticFilters;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
import mage.constants.WatcherScope;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.players.Player;
import mage.target.TargetCard;
import mage.target.common.TargetCardInExile;
import mage.target.common.TargetOpponentsCreaturePermanent;
import mage.util.CardUtil;
import mage.watchers.Watcher;
import java.util.*;
@ -46,12 +45,14 @@ public final class CaseOfTheBurningMasks extends CardImpl {
initialAbility.addTarget(new TargetOpponentsCreaturePermanent());
// To solve -- Three or more sources you controlled dealt damage this turn.
// Solved -- Sacrifice this Case: Exile the top three cards of your library. Choose one of them. You may play that card this turn.
Ability solvedAbility = new ConditionalActivatedAbility(new CaseOfTheBurningMasksEffect(),
new SacrificeSourceCost().setText("sacrifice this Case"), SolvedSourceCondition.SOLVED);
Ability solvedAbility = new ConditionalActivatedAbility(
new ExileTopXMayPlayUntilEffect(3, true, Duration.EndOfTurn),
new SacrificeSourceCost().setText("sacrifice this Case"), SolvedSourceCondition.SOLVED
);
this.addAbility(new CaseAbility(initialAbility, CaseOfTheBurningMasksCondition.instance, solvedAbility)
.addHint(new CaseOfTheBurningMasksHint()),
new CaseOfTheBurningMasksWatcher());
this.addAbility(new CaseAbility(
initialAbility, CaseOfTheBurningMasksCondition.instance, solvedAbility
).addHint(new CaseOfTheBurningMasksHint()), new CaseOfTheBurningMasksWatcher());
}
private CaseOfTheBurningMasks(final CaseOfTheBurningMasks card) {
@ -134,49 +135,3 @@ class CaseOfTheBurningMasksWatcher extends Watcher {
return damagingObjects.getOrDefault(controllerId, Collections.emptySet()).size();
}
}
class CaseOfTheBurningMasksEffect extends OneShotEffect {
CaseOfTheBurningMasksEffect() {
super(Outcome.Benefit);
staticText = "Exile the top three cards of your library. Choose one of them. You may play that card this turn.";
}
private CaseOfTheBurningMasksEffect(final CaseOfTheBurningMasksEffect effect) {
super(effect);
}
@Override
public CaseOfTheBurningMasksEffect copy() {
return new CaseOfTheBurningMasksEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player == null) {
return false;
}
Cards cards = new CardsImpl(player.getLibrary().getTopCards(game, 3));
player.moveCards(cards, Zone.EXILED, source, game);
cards.retainZone(Zone.EXILED, game);
Card card;
switch (cards.size()) {
case 0:
return false;
case 1:
card = cards.getRandom(game);
break;
default:
TargetCard target = new TargetCardInExile(StaticFilters.FILTER_CARD);
target.withNotTarget(true);
player.choose(outcome, cards, target, source, game);
card = game.getCard(target.getFirstTarget());
}
if (card != null) {
CardUtil.makeCardPlayable(game, source, card, false, Duration.EndOfTurn, false);
}
return true;
}
}

View file

@ -64,7 +64,7 @@ public final class DragonhawkFatesTempest extends CardImpl {
class DragonhawkExileEffect extends ExileTopXMayPlayUntilEffect {
DragonhawkExileEffect(DynamicValue amount, Duration duration) {
super(amount, duration);
super(amount, false, duration);
this.withTextOptions("those cards", true);
staticText += ". At the beginning of your next end step, " + DragonhawkFatesTempestDamageEffect.STATIC_TEXT;
}

View file

@ -1,18 +1,14 @@
package mage.cards.f;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.triggers.BeginningOfSecondMainTriggeredAbility;
import mage.abilities.condition.common.OpponentsLostLifeCondition;
import mage.abilities.effects.OneShotEffect;
import mage.cards.*;
import mage.constants.*;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetCard;
import mage.target.common.TargetCardInExile;
import mage.util.CardUtil;
import mage.abilities.effects.common.ExileTopXMayPlayUntilEffect;
import mage.abilities.triggers.BeginningOfSecondMainTriggeredAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
import java.util.UUID;
@ -30,8 +26,9 @@ public final class FireglassMentor extends CardImpl {
this.toughness = new MageInt(1);
// At the beginning of your second main phase, if an opponent lost life this turn, exile the top two cards of your library. Choose one of them. Until end of turn, you may play that card.
this.addAbility(new BeginningOfSecondMainTriggeredAbility(new FireglassMentorEffect(), false)
.withInterveningIf(OpponentsLostLifeCondition.instance));
this.addAbility(new BeginningOfSecondMainTriggeredAbility(
new ExileTopXMayPlayUntilEffect(2, true, Duration.EndOfTurn), false
).withInterveningIf(OpponentsLostLifeCondition.instance));
}
private FireglassMentor(final FireglassMentor card) {
@ -43,50 +40,3 @@ public final class FireglassMentor extends CardImpl {
return new FireglassMentor(this);
}
}
//Based on CaseOfTheBurningMasksEffect
class FireglassMentorEffect extends OneShotEffect {
FireglassMentorEffect() {
super(Outcome.Benefit);
staticText = "exile the top two cards of your library. Choose one of them. Until end of turn, you may play that card";
}
private FireglassMentorEffect(final FireglassMentorEffect effect) {
super(effect);
}
@Override
public FireglassMentorEffect copy() {
return new FireglassMentorEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player == null) {
return false;
}
Cards cards = new CardsImpl(player.getLibrary().getTopCards(game, 2));
player.moveCards(cards, Zone.EXILED, source, game);
cards.retainZone(Zone.EXILED, game);
Card card;
switch (cards.size()) {
case 0:
return false;
case 1:
card = cards.getRandom(game);
break;
default:
TargetCard target = new TargetCardInExile(StaticFilters.FILTER_CARD);
target.withNotTarget(true);
player.choose(outcome, cards, target, source, game);
card = game.getCard(target.getFirstTarget());
}
if (card != null) {
CardUtil.makeCardPlayable(game, source, card, false, Duration.EndOfTurn, false);
}
return true;
}
}

View file

@ -35,7 +35,7 @@ public final class HugsGrislyGuardian extends CardImpl {
// When Hugs, Grisly Guardian enters, exile the top X cards of your library. Until the end of your next turn, you may play those cards.
this.addAbility(new EntersBattlefieldTriggeredAbility(new ExileTopXMayPlayUntilEffect(
GetXValue.instance, Duration.UntilEndOfYourNextTurn
GetXValue.instance, false, Duration.UntilEndOfYourNextTurn
)));
// You may play an additional land on each of your turns.

View file

@ -5,23 +5,22 @@ import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.LoyaltyAbility;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.AttackingCreatureCount;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.effects.common.GetEmblemEffect;
import mage.cards.*;
import mage.constants.*;
import mage.abilities.effects.common.*;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.game.Controllable;
import mage.game.Game;
import mage.game.command.emblems.JayaFieryNegotiatorEmblem;
import mage.game.events.GameEvent;
import mage.game.permanent.token.MonkRedToken;
import mage.players.Player;
import mage.target.common.TargetOpponentsCreaturePermanent;
import mage.util.CardUtil;
import java.util.*;
import java.util.Objects;
import java.util.UUID;
/**
* @author TheElk801
@ -39,7 +38,7 @@ public final class JayaFieryNegotiator extends CardImpl {
this.addAbility(new LoyaltyAbility(new CreateTokenEffect(new MonkRedToken()), 1));
// 1: Exile the top two cards of your library. Choose one of them. You may play that card this turn.
this.addAbility(new LoyaltyAbility(new JayaFieryNegotiatorExileEffect(), -1));
this.addAbility(new LoyaltyAbility(new ExileTopXMayPlayUntilEffect(2, true, Duration.EndOfTurn), -1));
// 2: Choose target creature an opponent controls. Whenever you attack this turn, Jaya, Fiery Negotiator deals damage equal to the number of attacking creatures to that creature.
Ability ability = new LoyaltyAbility(new CreateDelayedTriggeredAbilityEffect(
@ -63,57 +62,6 @@ public final class JayaFieryNegotiator extends CardImpl {
}
}
class JayaFieryNegotiatorExileEffect extends OneShotEffect {
JayaFieryNegotiatorExileEffect() {
super(Outcome.Benefit);
staticText = "exile the top two cards of your library. Choose one of them. You may play that card this turn";
}
private JayaFieryNegotiatorExileEffect(final JayaFieryNegotiatorExileEffect effect) {
super(effect);
}
@Override
public JayaFieryNegotiatorExileEffect copy() {
return new JayaFieryNegotiatorExileEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player == null) {
return false;
}
Cards cards = new CardsImpl(player.getLibrary().getTopCards(game, 2));
Card card;
if (cards.size() == 0) {
return false;
} else if (cards.size() == 1) {
card = cards.getRandom(game);
player.moveCardsToExile(card, source, game, true, CardUtil.getExileZoneId(game, source), "Jaya, Fiery Negotiator");
} else {
Iterator<Card> iterator = cards.getCards(game).iterator();
Card card1 = iterator.next();
Card card2 = iterator.next();
card = player.chooseUse(
outcome, "Choose a card to play this turn", null,
card1.getName(), card2.getName(), source, game
) ? card1 : card2;
Set<Card> exileCards = new HashSet<>(2);
exileCards.add(card1);
exileCards.add(card2);
player.moveCardsToExile(exileCards, source, game, true, CardUtil.getExileZoneId(game, source), "Jaya, Fiery Negotiator");
}
if (card != null) {
CardUtil.makeCardPlayable(game, source, card, false, Duration.EndOfTurn, false);
}
return true;
}
}
class JayaFieryNegotiatorTriggeredAbility extends DelayedTriggeredAbility {
private static final DynamicValue xValue = new AttackingCreatureCount();

View file

@ -2,12 +2,12 @@ package mage.cards.l;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.ExileTopXMayPlayUntilEffect;
import mage.abilities.keyword.WardAbility;
import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
@ -38,7 +38,7 @@ public final class LootTheKeyToEverything extends CardImpl {
// At the beginning of your upkeep, exile the top X cards of your library, where X is the number of card types among other nonland permanents you control. You may play those cards this turn.
this.addAbility(new BeginningOfUpkeepTriggeredAbility(
new ExileTopXMayPlayUntilEffect(LootTheKeyToEverythingValue.instance, Duration.EndOfTurn)
new ExileTopXMayPlayUntilEffect(LootTheKeyToEverythingValue.instance, false, Duration.EndOfTurn)
.setText("exile the top X cards of your library, where X is the number of card types " +
"among other nonland permanents you control. You may play those cards this turn")
));

View file

@ -1,7 +1,6 @@
package mage.cards.m;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
@ -12,18 +11,16 @@ import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.decorator.ConditionalContinuousEffect;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount;
import mage.abilities.effects.AsThoughEffectImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ExileTopXMayPlayUntilEffect;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.abilities.hint.Hint;
import mage.abilities.hint.ValueHint;
import mage.cards.*;
import mage.constants.*;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetCard;
import mage.target.common.TargetCardInExile;
import java.util.UUID;
@ -54,7 +51,7 @@ public final class MagmaticChanneler extends CardImpl {
)).addHint(hint));
// {T}, Discard a card: Exile the top two cards of your library, then choose one of them. You may play that card this turn.
Ability ability = new SimpleActivatedAbility(new MagmaticChannelerExileEffect(), new TapSourceCost());
Ability ability = new SimpleActivatedAbility(new ExileTopXMayPlayUntilEffect(2, true, Duration.EndOfTurn), new TapSourceCost());
ability.addCost(new DiscardCardCost());
this.addAbility(ability);
}
@ -68,83 +65,3 @@ public final class MagmaticChanneler extends CardImpl {
return new MagmaticChanneler(this);
}
}
class MagmaticChannelerExileEffect extends OneShotEffect {
MagmaticChannelerExileEffect() {
super(Outcome.Benefit);
staticText = "Exile the top two cards of your library, then choose one of them. You may play that card this turn.";
}
private MagmaticChannelerExileEffect(final MagmaticChannelerExileEffect effect) {
super(effect);
}
@Override
public MagmaticChannelerExileEffect copy() {
return new MagmaticChannelerExileEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player == null) {
return false;
}
Cards cards = new CardsImpl(player.getLibrary().getTopCards(game, 2));
player.moveCards(cards, Zone.EXILED, source, game);
cards.removeIf(uuid -> game.getState().getZone(uuid) != Zone.EXILED);
Card card = null;
if (cards.isEmpty()) {
return false;
} else if (cards.size() == 1) {
card = cards.getRandom(game);
} else {
TargetCard targetCard = new TargetCardInExile(StaticFilters.FILTER_CARD);
player.choose(outcome, cards, targetCard, source, game);
card = game.getCard(targetCard.getFirstTarget());
}
if (card == null) {
return false;
}
game.addEffect(new MagmaticChannelerCastFromExileEffect(new MageObjectReference(card, game)), source);
return true;
}
}
class MagmaticChannelerCastFromExileEffect extends AsThoughEffectImpl {
private final MageObjectReference mor;
MagmaticChannelerCastFromExileEffect(MageObjectReference mor) {
super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfTurn, Outcome.Benefit);
this.mor = mor;
}
private MagmaticChannelerCastFromExileEffect(final MagmaticChannelerCastFromExileEffect effect) {
super(effect);
this.mor = effect.mor;
}
@Override
public boolean apply(Game game, Ability source) {
return true;
}
@Override
public MagmaticChannelerCastFromExileEffect copy() {
return new MagmaticChannelerCastFromExileEffect(this);
}
@Override
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
Card theCard = game.getCard(objectId);
if (theCard == null) {
return false;
}
objectId = theCard.getMainCard().getId(); // for split cards/MDFC/Adventure cards
return source.isControlledBy(affectedControllerId)
&& mor.refersTo(objectId, game);
}
}

View file

@ -6,19 +6,12 @@ import mage.abilities.costs.common.SacrificeSourceCost;
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.ExileTopXMayPlayUntilEffect;
import mage.abilities.keyword.UnearthAbility;
import mage.cards.*;
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.TargetCardInExile;
import mage.util.CardUtil;
import java.util.UUID;
@ -31,7 +24,9 @@ public final class MishrasResearchDesk extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}");
// {1}, {T}, Sacrifice Mishra's Research Desk: Exile the top two cards of your library. Choose one of them. Until the end of your next turn, you may play that card.
Ability ability = new SimpleActivatedAbility(new MishrasResearchDeskEffect(), new GenericManaCost(1));
Ability ability = new SimpleActivatedAbility(new ExileTopXMayPlayUntilEffect(
2, true, Duration.UntilEndOfYourNextTurn
), new GenericManaCost(1));
ability.addCost(new TapSourceCost());
ability.addCost(new SacrificeSourceCost());
this.addAbility(ability);
@ -49,50 +44,3 @@ public final class MishrasResearchDesk extends CardImpl {
return new MishrasResearchDesk(this);
}
}
class MishrasResearchDeskEffect extends OneShotEffect {
MishrasResearchDeskEffect() {
super(Outcome.Benefit);
staticText = "exile the top two cards of your library. Choose one of them. " +
"Until the end of your next turn, you may play that card";
}
private MishrasResearchDeskEffect(final MishrasResearchDeskEffect effect) {
super(effect);
}
@Override
public MishrasResearchDeskEffect copy() {
return new MishrasResearchDeskEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player == null) {
return false;
}
Cards cards = new CardsImpl(player.getLibrary().getTopCards(game, 2));
player.moveCards(cards, Zone.EXILED, source, game);
cards.retainZone(Zone.EXILED, game);
Card card;
switch (cards.size()) {
case 0:
return false;
case 1:
card = cards.getRandom(game);
break;
default:
TargetCard target = new TargetCardInExile(StaticFilters.FILTER_CARD);
target.withNotTarget(true);
player.choose(outcome, cards, target, source, game);
card = game.getCard(target.getFirstTarget());
}
if (card == null) {
return false;
}
CardUtil.makeCardPlayable(game, source, card, false, Duration.UntilEndOfYourNextTurn, false);
return true;
}
}

View file

@ -1,28 +1,23 @@
package mage.cards.p;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.triggers.BeginningOfFirstMainTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.common.DiscardCardCost;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DoIfCostPaid;
import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect;
import mage.abilities.effects.common.ExileTopXMayPlayUntilEffect;
import mage.abilities.effects.common.continuous.GainAbilityControlledSpellsEffect;
import mage.abilities.keyword.ConvokeAbility;
import mage.cards.*;
import mage.constants.*;
import mage.filter.StaticFilters;
import mage.abilities.triggers.BeginningOfFirstMainTriggeredAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.common.FilterNonlandCard;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.card.CastFromZonePredicate;
import mage.filter.predicate.mageobject.AbilityPredicate;
import mage.game.ExileZone;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetCard;
import mage.target.targetpointer.FixedTarget;
import mage.util.CardUtil;
import java.util.UUID;
@ -53,12 +48,9 @@ public final class PartyThrasher extends CardImpl {
));
// At the beginning of your precombat main phase, you may discard a card. If you do, exile the top two cards of your library, then choose one of them. You may play that card this turn.
this.addAbility(new BeginningOfFirstMainTriggeredAbility(
new DoIfCostPaid(
new PartyThrasherEffect(),
new DiscardCardCost()
)
));
this.addAbility(new BeginningOfFirstMainTriggeredAbility(new DoIfCostPaid(
new ExileTopXMayPlayUntilEffect(2, true, Duration.EndOfTurn), new DiscardCardCost()
)));
}
private PartyThrasher(final PartyThrasher card) {
@ -70,56 +62,3 @@ public final class PartyThrasher extends CardImpl {
return new PartyThrasher(this);
}
}
class PartyThrasherEffect extends OneShotEffect {
PartyThrasherEffect() {
super(Outcome.DrawCard);
staticText = "exile the top two cards of your library, then choose one of them. You may play that card this turn";
}
private PartyThrasherEffect(final PartyThrasherEffect effect) {
super(effect);
}
@Override
public PartyThrasherEffect copy() {
return new PartyThrasherEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller == null) {
return false;
}
Cards cards = new CardsImpl(controller.getLibrary().getTopCards(game, 2));
if (cards.isEmpty()) {
return false;
}
controller.moveCardsToExile(cards.getCards(game), source, game, true, null, "");
game.processAction();
cards.retainZone(Zone.EXILED, game);
if (cards.isEmpty()) {
return true;
}
TargetCard target = new TargetCard(Zone.EXILED, StaticFilters.FILTER_CARD_A);
target.withNotTarget(true);
if (!controller.choose(Outcome.DrawCard, cards, target, source, game)) {
return true;
}
Card card = game.getCard(target.getFirstTarget());
if (card == null) {
return true;
}
String exileName = CardUtil.getSourceIdName(game, source);
UUID exileId = CardUtil.getExileZoneId(game, source);
ExileZone exileZone = game.getExile().createZone(exileId, exileName);
exileZone.setCleanupOnEndTurn(true);
game.getExile().moveToAnotherZone(card, game, exileZone);
game.addEffect(new PlayFromNotOwnHandZoneTargetEffect(Zone.EXILED, Duration.EndOfTurn)
.setTargetPointer(new FixedTarget(card, game)), source);
return true;
}
}

View file

@ -42,7 +42,7 @@ public final class RotisserieElemental extends CardImpl {
false
).withRuleTextReplacement(false);
ability.addEffect(new DoIfCostPaid(
new ExileTopXMayPlayUntilEffect(xValue, Duration.EndOfTurn)
new ExileTopXMayPlayUntilEffect(xValue, false, Duration.EndOfTurn)
.setText("exile the top X cards of your library, where X is the number of skewer counters "
+ "on {this}. You may play those cards this turn"),
new SacrificeSourceCost().setText("sacrifice it")

View file

@ -0,0 +1,45 @@
package mage.cards.s;
import mage.MageInt;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.condition.common.RaidCondition;
import mage.abilities.effects.common.ExileTopXMayPlayUntilEffect;
import mage.abilities.hint.common.RaidHint;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.AbilityWord;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
import mage.watchers.common.PlayerAttackedWatcher;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class StrongboxRaider extends CardImpl {
public StrongboxRaider(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}{R}");
this.subtype.add(SubType.ORC);
this.subtype.add(SubType.PIRATE);
this.power = new MageInt(5);
this.toughness = new MageInt(2);
// Raid -- When this creature enters, if you attacked this turn, exile the top two cards of your library. Choose one of them. Until the end of your next turn, you may play that card.
this.addAbility(new EntersBattlefieldTriggeredAbility(
new ExileTopXMayPlayUntilEffect(2, true, Duration.UntilEndOfYourNextTurn)
).withInterveningIf(RaidCondition.instance).setAbilityWord(AbilityWord.RAID).addHint(RaidHint.instance), new PlayerAttackedWatcher());
}
private StrongboxRaider(final StrongboxRaider card) {
super(card);
}
@Override
public StrongboxRaider copy() {
return new StrongboxRaider(this);
}
}

View file

@ -1,25 +1,17 @@
package mage.cards.t;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.TriggeredAbility;
import mage.abilities.common.AttacksTriggeredAbility;
import mage.abilities.common.BecomesTargetSourceTriggeredAbility;
import mage.abilities.effects.AsThoughEffectImpl;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DamagePlayersEffect;
import mage.abilities.effects.common.ExileTopXMayPlayUntilEffect;
import mage.abilities.meta.OrTriggeredAbility;
import mage.cards.*;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.FilterSpell;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetCard;
import mage.target.common.TargetCardInExile;
import mage.target.targetpointer.FixedTarget;
import java.util.UUID;
@ -29,6 +21,7 @@ import java.util.UUID;
public final class TectonicGiant extends CardImpl {
private static final FilterSpell filter = new FilterSpell("a spell an opponent controls");
static {
filter.add(TargetController.OPPONENT.getControllerPredicate());
}
@ -44,11 +37,13 @@ public final class TectonicGiant extends CardImpl {
// Whenever Tectonic Giant attacks or becomes the target of a spell an opponent controls, choose one
// Tectonic Giant deals 3 damage to each opponent.
// Exile the top two cards of your library. Choose one of them. Until the end of your next turn, you may play that card.
TriggeredAbility ability = new OrTriggeredAbility(Zone.BATTLEFIELD, new DamagePlayersEffect(3, TargetController.OPPONENT), false,
TriggeredAbility ability = new OrTriggeredAbility(
Zone.BATTLEFIELD, new DamagePlayersEffect(3, TargetController.OPPONENT), false,
"Whenever {this} attacks or becomes the target of a spell an opponent controls, ",
new AttacksTriggeredAbility(null),
new BecomesTargetSourceTriggeredAbility(null, filter));
ability.addMode(new Mode(new TectonicGiantEffect()));
new BecomesTargetSourceTriggeredAbility(null, filter)
);
ability.addMode(new Mode(new ExileTopXMayPlayUntilEffect(2, true, Duration.UntilEndOfYourNextTurn)));
this.addAbility(ability);
}
@ -61,87 +56,3 @@ public final class TectonicGiant extends CardImpl {
return new TectonicGiant(this);
}
}
class TectonicGiantEffect extends OneShotEffect {
TectonicGiantEffect() {
super(Outcome.Benefit);
staticText = "exile the top two cards of your library. Choose one of them. "
+ "Until the end of your next turn, you may play that card";
}
private TectonicGiantEffect(final TectonicGiantEffect effect) {
super(effect);
}
@Override
public TectonicGiantEffect copy() {
return new TectonicGiantEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller == null) {
return false;
}
Cards cards = new CardsImpl(controller.getLibrary().getTopCards(game, 2));
controller.moveCards(cards, Zone.EXILED, source, game);
TargetCard targetCard = new TargetCardInExile(StaticFilters.FILTER_CARD);
controller.choose(outcome, cards, targetCard, source, game);
Card card = game.getCard(targetCard.getFirstTarget());
if (card == null) {
return true;
}
ContinuousEffect effect = new TectonicGiantMayPlayEffect();
effect.setTargetPointer(new FixedTarget(card.getId()));
game.addEffect(effect, source);
return true;
}
}
class TectonicGiantMayPlayEffect extends AsThoughEffectImpl {
private int castOnTurn = 0;
TectonicGiantMayPlayEffect() {
super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.Custom, Outcome.Benefit);
this.staticText = "Until the end of your next turn, you may play that card.";
}
private TectonicGiantMayPlayEffect(final TectonicGiantMayPlayEffect effect) {
super(effect);
castOnTurn = effect.castOnTurn;
}
@Override
public TectonicGiantMayPlayEffect copy() {
return new TectonicGiantMayPlayEffect(this);
}
@Override
public void init(Ability source, Game game) {
super.init(source, game);
castOnTurn = game.getTurnNum();
}
@Override
public boolean isInactive(Ability source, Game game) {
return castOnTurn != game.getTurnNum()
&& game.getPhase().getStep().getType() == PhaseStep.END_TURN
&& game.isActivePlayer(source.getControllerId());
}
@Override
public boolean apply(Game game, Ability source) {
return true;
}
@Override
public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) {
return source.isControlledBy(affectedControllerId)
&& getTargetPointer().getTargets(game, source).contains(sourceId);
}
}

View file

@ -20,7 +20,6 @@ import mage.game.permanent.Permanent;
import java.util.UUID;
/**
*
* @author notgreat
*/
public final class WitchKingSkyScourge extends CardImpl {
@ -31,6 +30,7 @@ public final class WitchKingSkyScourge extends CardImpl {
filter.add(TargetController.YOU.getControllerPredicate());
filter.add(SubType.WRAITH.getPredicate());
}
public WitchKingSkyScourge(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{B}{R}");
@ -45,7 +45,7 @@ public final class WitchKingSkyScourge extends CardImpl {
// Whenever you attack with one or more Wraiths, exile the top X cards of your library, where X is their total power. You may play those cards this turn.
this.addAbility(new AttacksWithCreaturesTriggeredAbility(Zone.BATTLEFIELD,
new ExileTopXMayPlayUntilEffect(TotalTargetsPowerValue.instance, Duration.EndOfTurn)
new ExileTopXMayPlayUntilEffect(TotalTargetsPowerValue.instance, false, Duration.EndOfTurn)
.setText("exile the top X cards of your library, where X is their total power. You may play those cards this turn.")
, 1, filter, true));

View file

@ -273,6 +273,7 @@ public final class Foundations extends ExpansionSet {
cards.add(new SetCardInfo("Stroke of Midnight", 148, Rarity.UNCOMMON, mage.cards.s.StrokeOfMidnight.class));
cards.add(new SetCardInfo("Stromkirk Bloodthief", 185, Rarity.UNCOMMON, mage.cards.s.StromkirkBloodthief.class));
cards.add(new SetCardInfo("Stromkirk Noble", 632, Rarity.RARE, mage.cards.s.StromkirkNoble.class));
cards.add(new SetCardInfo("Strongbox Raider", 96, Rarity.UNCOMMON, mage.cards.s.StrongboxRaider.class));
cards.add(new SetCardInfo("Surrak, the Hunt Caller", 647, Rarity.RARE, mage.cards.s.SurrakTheHuntCaller.class));
cards.add(new SetCardInfo("Swamp", 276, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Swiftblade Vindicator", 246, Rarity.RARE, mage.cards.s.SwiftbladeVindicator.class));

View file

@ -6,11 +6,16 @@ import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect;
import mage.cards.Card;
import mage.cards.Cards;
import mage.cards.CardsImpl;
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.TargetCardInExile;
import mage.target.targetpointer.FixedTargets;
import mage.util.CardUtil;
@ -19,22 +24,29 @@ import java.util.Set;
public class ExileTopXMayPlayUntilEffect extends OneShotEffect {
private final DynamicValue amount;
private final boolean chooseOne;
private final Duration duration;
public ExileTopXMayPlayUntilEffect(int amount, Duration duration) {
this(StaticValue.get(amount), duration);
this(amount, false, duration);
}
public ExileTopXMayPlayUntilEffect(DynamicValue amount, Duration duration) {
public ExileTopXMayPlayUntilEffect(int amount, boolean chooseOne, Duration duration) {
this(StaticValue.get(amount), chooseOne, duration);
}
public ExileTopXMayPlayUntilEffect(DynamicValue amount, boolean chooseOne, Duration duration) {
super(Outcome.Benefit);
this.amount = amount.copy();
this.chooseOne = chooseOne;
this.duration = duration;
makeText(amount.toString().equals("1") ? "that card" : "those cards", duration == Duration.EndOfTurn);
makeText(amount.toString().equals("1") || chooseOne ? "that card" : "those cards", duration == Duration.EndOfTurn);
}
protected ExileTopXMayPlayUntilEffect(final ExileTopXMayPlayUntilEffect effect) {
super(effect);
this.amount = effect.amount.copy();
this.chooseOne = effect.chooseOne;
this.duration = effect.duration;
}
@ -50,18 +62,29 @@ public class ExileTopXMayPlayUntilEffect extends OneShotEffect {
return false;
}
int resolvedAmount = amount.calculate(game, source, this);
Set<Card> cards = controller.getLibrary().getTopCards(game, resolvedAmount);
Cards cards = new CardsImpl(controller.getLibrary().getTopCards(game, resolvedAmount));
if (cards.isEmpty()) {
return true;
}
controller.moveCardsToExile(cards, source, game, true, CardUtil.getExileZoneId(game, source), CardUtil.getSourceName(game, source));
controller.moveCardsToExile(
cards.getCards(game), source, game, true,
CardUtil.getExileZoneId(game, source),
CardUtil.getSourceName(game, source)
);
// remove cards that could not be moved to exile
cards.removeIf(card -> !Zone.EXILED.equals(game.getState().getZone(card.getId())));
if (!cards.isEmpty()) {
game.addEffect(new PlayFromNotOwnHandZoneTargetEffect(Zone.EXILED, duration)
.setTargetPointer(new FixedTargets(cards, game)), source);
effectCards(game, source, cards);
cards.retainZone(Zone.EXILED, game);
if (chooseOne && cards.size() > 1) {
TargetCard target = new TargetCardInExile(StaticFilters.FILTER_CARD);
target.withNotTarget(true);
controller.choose(outcome, cards, target, source, game);
cards.removeIf(uuid -> !uuid.equals(target.getFirstTarget()));
}
if (cards.isEmpty()) {
return true;
}
game.addEffect(new PlayFromNotOwnHandZoneTargetEffect(Zone.EXILED, duration)
.setTargetPointer(new FixedTargets(cards, game)), source);
effectCards(game, source, cards.getCards(game));
return true;
}
@ -86,6 +109,9 @@ public class ExileTopXMayPlayUntilEffect extends OneShotEffect {
} else {
text += " of your library. ";
}
if (chooseOne) {
text += "Choose one of them. ";
}
if (durationRuleAtEnd) {
text += "You may play " + refCardText + ' ' + (duration == Duration.EndOfTurn ? "this turn" : duration.toString());
} else {