mirror of
https://github.com/magefree/mage.git
synced 2025-12-20 02:30:08 -08:00
[OTC] Implement 2 cards, refactor some exile effects ("Gonti-like") (#12118)
[OTC] Implement Gonti, Canny Acquisitor [OTC] Implement Dream Thief's Bandana
This commit is contained in:
parent
c77634c843
commit
607d55f16b
20 changed files with 487 additions and 1252 deletions
|
|
@ -1,38 +1,27 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.MageObject;
|
||||
import mage.constants.*;
|
||||
import mage.game.Game;
|
||||
import mage.players.ManaPoolItem;
|
||||
import mage.players.Player;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
import mage.util.CardUtil;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.FirstSpellOpponentsTurnTriggeredAbility;
|
||||
import mage.abilities.effects.AsThoughEffectImpl;
|
||||
import mage.abilities.effects.AsThoughManaEffect;
|
||||
import mage.abilities.effects.ContinuousEffect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.asthought.MayLookAtTargetCardEffect;
|
||||
import mage.abilities.effects.common.ExileFaceDownTopNLibraryYouMayPlayAsLongAsExiledTargetEffect;
|
||||
import mage.abilities.keyword.DeathtouchAbility;
|
||||
import mage.cards.Card;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.CastManaAdjustment;
|
||||
import mage.constants.SetTargetPointer;
|
||||
import mage.constants.SubType;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Xanderhall
|
||||
*/
|
||||
public final class BlightwingBandit extends CardImpl {
|
||||
|
||||
public BlightwingBandit(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}");
|
||||
|
||||
|
||||
this.subtype.add(SubType.FAERIE);
|
||||
this.subtype.add(SubType.ROGUE);
|
||||
this.power = new MageInt(2);
|
||||
|
|
@ -45,7 +34,12 @@ public final class BlightwingBandit extends CardImpl {
|
|||
this.addAbility(DeathtouchAbility.getInstance());
|
||||
|
||||
// Whenever you cast your first spell during each opponent's turn, look at the top card of that player's library, then exile it face down. You may play that card for as long as it remains exiled, and mana of any type can be spent to cast it.
|
||||
this.addAbility(new FirstSpellOpponentsTurnTriggeredAbility(new BlightwingBanditEffect(), false, SetTargetPointer.PLAYER));
|
||||
this.addAbility(new FirstSpellOpponentsTurnTriggeredAbility(
|
||||
new ExileFaceDownTopNLibraryYouMayPlayAsLongAsExiledTargetEffect(false, CastManaAdjustment.AS_THOUGH_ANY_MANA_TYPE)
|
||||
.setText("look at the top card of that player's library, then exile it face down. "
|
||||
+ "You may play that card for as long as it remains exiled, and mana of any type can be spent to cast it."),
|
||||
false, SetTargetPointer.PLAYER
|
||||
));
|
||||
}
|
||||
|
||||
private BlightwingBandit(final BlightwingBandit card) {
|
||||
|
|
@ -56,164 +50,4 @@ public final class BlightwingBandit extends CardImpl {
|
|||
public BlightwingBandit copy() {
|
||||
return new BlightwingBandit(this);
|
||||
}
|
||||
}
|
||||
|
||||
class BlightwingBanditEffect extends OneShotEffect {
|
||||
|
||||
private static final String VALUE_PREFIX = "ExileZones";
|
||||
|
||||
public BlightwingBanditEffect() {
|
||||
super(Outcome.Benefit);
|
||||
this.staticText = "look at the top card of that player's library, then exile it face down. "
|
||||
+ "You may play that card for as long as it remains exiled, and mana of any type can be spent to cast it.";
|
||||
}
|
||||
|
||||
private BlightwingBanditEffect(final BlightwingBanditEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlightwingBanditEffect copy() {
|
||||
return new BlightwingBanditEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
Player opponent = game.getPlayer(getTargetPointer().getFirst(game, source));
|
||||
MageObject sourceObject = source.getSourceObject(game);
|
||||
|
||||
if (controller == null || opponent == null || sourceObject == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Card topCard = opponent.getLibrary().getFromTop(game);
|
||||
if (topCard == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
UUID exileZoneId = CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter());
|
||||
topCard.setFaceDown(true, game);
|
||||
|
||||
// Move card to exile
|
||||
if (controller.moveCardsToExile(topCard, source, game, false, exileZoneId, sourceObject.getIdName())) {
|
||||
topCard.setFaceDown(true, game);
|
||||
|
||||
Set<UUID> exileZones = (Set<UUID>) game.getState().getValue(VALUE_PREFIX + source.getSourceId().toString());
|
||||
if (exileZones == null) {
|
||||
exileZones = new HashSet<>();
|
||||
game.getState().setValue(VALUE_PREFIX + source.getSourceId().toString(), exileZones);
|
||||
}
|
||||
exileZones.add(exileZoneId);
|
||||
|
||||
// You may play the card
|
||||
ContinuousEffect effect = new BlightwingBanditPlayFromExileEffect();
|
||||
effect.setTargetPointer(new FixedTarget(topCard.getId(), game));
|
||||
game.addEffect(effect, source);
|
||||
|
||||
// And you may spend mana as though it were mana of any color to cast it
|
||||
effect = new BlightwingBanditSpendAnyManaEffect();
|
||||
effect.setTargetPointer(new FixedTarget(topCard.getId(), game));
|
||||
game.addEffect(effect, source);
|
||||
|
||||
// For as long as that card remains exiled, you may look at it
|
||||
effect = new MayLookAtTargetCardEffect(controller.getId());
|
||||
effect.setTargetPointer(new FixedTarget(topCard.getId(), game));
|
||||
game.addEffect(effect, source);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class BlightwingBanditPlayFromExileEffect extends AsThoughEffectImpl {
|
||||
|
||||
BlightwingBanditPlayFromExileEffect() {
|
||||
super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.Custom, Outcome.Benefit);
|
||||
staticText = "You may look at and play that card for as long as it remains exiled, " +
|
||||
"and you may spend mana as though it were mana of any color to cast that spell.";
|
||||
}
|
||||
|
||||
private BlightwingBanditPlayFromExileEffect(final BlightwingBanditPlayFromExileEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlightwingBanditPlayFromExileEffect copy() {
|
||||
return new BlightwingBanditPlayFromExileEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
|
||||
UUID targetId = getTargetPointer().getFirst(game, source);
|
||||
if (targetId == null) {
|
||||
// card is no longer in the origin zone, effect can be discarded
|
||||
this.discard();
|
||||
return false;
|
||||
}
|
||||
Card theCard = game.getCard(objectId);
|
||||
if (theCard == null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// for split cards
|
||||
objectId = theCard.getMainCard().getId();
|
||||
|
||||
if (objectId.equals(targetId) && affectedControllerId.equals(source.getControllerId())) {
|
||||
Card card = game.getCard(objectId);
|
||||
return card != null;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class BlightwingBanditSpendAnyManaEffect extends AsThoughEffectImpl implements AsThoughManaEffect {
|
||||
|
||||
public BlightwingBanditSpendAnyManaEffect() {
|
||||
super(AsThoughEffectType.SPEND_OTHER_MANA, Duration.Custom, Outcome.Benefit);
|
||||
staticText = "you may spend mana as though it were mana of any color to cast that spell";
|
||||
}
|
||||
|
||||
private BlightwingBanditSpendAnyManaEffect(final BlightwingBanditSpendAnyManaEffect effect) { super(effect); }
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlightwingBanditSpendAnyManaEffect copy() {
|
||||
return new BlightwingBanditSpendAnyManaEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
|
||||
Card theCard = game.getCard(objectId);
|
||||
if (theCard == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// for split cards
|
||||
objectId = theCard.getMainCard().getId();
|
||||
|
||||
if (objectId.equals(((FixedTarget) getTargetPointer()).getTarget())
|
||||
&& game.getState().getZoneChangeCounter(objectId) <= ((FixedTarget) getTargetPointer()).getZoneChangeCounter() + 1) {
|
||||
// if the card moved from exile to spell the zone change counter is increased by 1 (effect must applies before and on stack, use isCheckPlayableMode?)
|
||||
return source.isControlledBy(affectedControllerId);
|
||||
} else if (((FixedTarget) getTargetPointer()).getTarget().equals(objectId)) {
|
||||
// object has moved zone so effect can be discarded
|
||||
this.discard();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ManaType getAsThoughManaType(ManaType manaType, ManaPoolItem mana, UUID affectedControllerId, Ability source, Game game) {
|
||||
return mana.getFirstAvailable();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,29 +1,19 @@
|
|||
package mage.cards.d;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.AttacksTriggeredAbility;
|
||||
import mage.abilities.effects.ContinuousEffect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.ExileFaceDownTopNLibraryYouMayPlayAsLongAsExiledTargetEffect;
|
||||
import mage.abilities.effects.common.CreateTokenEffect;
|
||||
import mage.abilities.effects.common.asthought.MayLookAtTargetCardEffect;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.abilities.keyword.TrampleAbility;
|
||||
import mage.cards.*;
|
||||
import mage.cards.AdventureCard;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.CastManaAdjustment;
|
||||
import mage.constants.SubType;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.token.TreasureToken;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetOpponent;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
|
|
@ -49,7 +39,11 @@ public final class DecadentDragon extends AdventureCard {
|
|||
|
||||
// Expensive Taste
|
||||
// Exile the top two cards of target opponent's library face down. You may look at and play those cards for as long as they remain exiled.
|
||||
this.getSpellCard().getSpellAbility().addEffect(new ExpensiveTasteEffect());
|
||||
this.getSpellCard().getSpellAbility().addEffect(
|
||||
new ExileFaceDownTopNLibraryYouMayPlayAsLongAsExiledTargetEffect(false, CastManaAdjustment.NONE, 2)
|
||||
.setText("Exile the top two cards of target opponent's library face down. "
|
||||
+ "You may look at and play those cards for as long as they remain exiled.")
|
||||
);
|
||||
this.getSpellCard().getSpellAbility().addTarget(new TargetOpponent());
|
||||
|
||||
this.finalizeAdventure();
|
||||
|
|
@ -63,58 +57,4 @@ public final class DecadentDragon extends AdventureCard {
|
|||
public DecadentDragon copy() {
|
||||
return new DecadentDragon(this);
|
||||
}
|
||||
}
|
||||
|
||||
class ExpensiveTasteEffect extends OneShotEffect {
|
||||
|
||||
private static final String VALUE_PREFIX = "ExileZones";
|
||||
|
||||
ExpensiveTasteEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "exile the top two cards of target opponent's library face down. You may look at and play those cards for as long as they remain exiled.";
|
||||
}
|
||||
|
||||
private ExpensiveTasteEffect(final ExpensiveTasteEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpensiveTasteEffect copy() {
|
||||
return new ExpensiveTasteEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
Player opponent = game.getPlayer(source.getFirstTarget());
|
||||
MageObject sourceObject = source.getSourceObject(game);
|
||||
if (opponent == null || controller == null || sourceObject == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Cards topCards = new CardsImpl();
|
||||
topCards.addAllCards(opponent.getLibrary().getTopCards(game, 2));
|
||||
|
||||
for (Card card : topCards.getCards(game)) {
|
||||
UUID exileZoneId = CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter());
|
||||
card.setFaceDown(true, game);
|
||||
if (controller.moveCardsToExile(card, source, game, false, exileZoneId, sourceObject.getIdName())) {
|
||||
card.setFaceDown(true, game);
|
||||
Set<UUID> exileZones = (Set<UUID>) game.getState().getValue(VALUE_PREFIX + source.getSourceId().toString());
|
||||
if (exileZones == null) {
|
||||
exileZones = new HashSet<>();
|
||||
game.getState().setValue(VALUE_PREFIX + source.getSourceId().toString(), exileZones);
|
||||
}
|
||||
exileZones.add(exileZoneId);
|
||||
// allow to cast the card
|
||||
CardUtil.makeCardPlayable(game, source, card, false, Duration.EndOfGame, false, controller.getId(), null);
|
||||
// For as long as that card remains exiled, you may look at it
|
||||
ContinuousEffect effect = new MayLookAtTargetCardEffect(controller.getId());
|
||||
effect.setTargetPointer(new FixedTarget(card.getId(), game));
|
||||
game.addEffect(effect, source);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
45
Mage.Sets/src/mage/cards/d/DreamThiefsBandana.java
Normal file
45
Mage.Sets/src/mage/cards/d/DreamThiefsBandana.java
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
package mage.cards.d;
|
||||
|
||||
import mage.abilities.common.DealsDamageToAPlayerAttachedTriggeredAbility;
|
||||
import mage.abilities.effects.common.ExileFaceDownTopNLibraryYouMayPlayAsLongAsExiledTargetEffect;
|
||||
import mage.abilities.keyword.EquipAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.CastManaAdjustment;
|
||||
import mage.constants.SubType;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author Susucr
|
||||
*/
|
||||
public final class DreamThiefsBandana extends CardImpl {
|
||||
|
||||
public DreamThiefsBandana(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}");
|
||||
|
||||
this.subtype.add(SubType.EQUIPMENT);
|
||||
|
||||
// Whenever equipped creature deals combat damage to a player, look at the top card of their library, then exile it face down. For as long as it remains exiled, you may play it, and mana of any type can be spent to cast that spell.
|
||||
this.addAbility(new DealsDamageToAPlayerAttachedTriggeredAbility(
|
||||
new ExileFaceDownTopNLibraryYouMayPlayAsLongAsExiledTargetEffect(false, CastManaAdjustment.AS_THOUGH_ANY_MANA_TYPE)
|
||||
.setText("look at the top card of their library, then exile it face down. "
|
||||
+ "For as long as it remains exiled, you may play it, and mana of any type can be spent to cast that spell"),
|
||||
"equipped creature", false, true
|
||||
));
|
||||
|
||||
// Equip {1}
|
||||
this.addAbility(new EquipAbility(1));
|
||||
}
|
||||
|
||||
private DreamThiefsBandana(final DreamThiefsBandana card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DreamThiefsBandana copy() {
|
||||
return new DreamThiefsBandana(this);
|
||||
}
|
||||
}
|
||||
|
||||
55
Mage.Sets/src/mage/cards/g/GontiCannyAcquisitor.java
Normal file
55
Mage.Sets/src/mage/cards/g/GontiCannyAcquisitor.java
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
package mage.cards.g;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.common.DealCombatDamageControlledTriggeredAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.common.ExileFaceDownTopNLibraryYouMayPlayAsLongAsExiledTargetEffect;
|
||||
import mage.abilities.effects.common.cost.SpellsCostReductionControllerEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.filter.FilterCard;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author Susucr
|
||||
*/
|
||||
public final class GontiCannyAcquisitor extends CardImpl {
|
||||
|
||||
private static final FilterCard filter = new FilterCard("Spells you cast but don't own");
|
||||
|
||||
static {
|
||||
filter.add(TargetController.NOT_YOU.getOwnerPredicate());
|
||||
}
|
||||
|
||||
public GontiCannyAcquisitor(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}{G}{U}");
|
||||
|
||||
this.supertype.add(SuperType.LEGENDARY);
|
||||
this.subtype.add(SubType.AETHERBORN);
|
||||
this.subtype.add(SubType.ROGUE);
|
||||
this.power = new MageInt(5);
|
||||
this.toughness = new MageInt(5);
|
||||
|
||||
// Spells you cast but don't own cost {1} less to cast.
|
||||
this.addAbility(new SimpleStaticAbility(new SpellsCostReductionControllerEffect(filter, 1)));
|
||||
|
||||
// Whenever one or more creatures you control deal combat damage to a player, look at the top card of that player's library, then exile it face down. You may play that card for as long as it remains exiled, and mana of any type can be spent to cast that spell.
|
||||
this.addAbility(new DealCombatDamageControlledTriggeredAbility(
|
||||
new ExileFaceDownTopNLibraryYouMayPlayAsLongAsExiledTargetEffect(false, CastManaAdjustment.AS_THOUGH_ANY_MANA_TYPE)
|
||||
.setText("look at the top card of that player's library, then exile it face down. "
|
||||
+ "You may play that card for as long as it remains exiled, and mana of any type can be spent to cast that spell"),
|
||||
SetTargetPointer.PLAYER
|
||||
));
|
||||
}
|
||||
|
||||
private GontiCannyAcquisitor(final GontiCannyAcquisitor card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GontiCannyAcquisitor copy() {
|
||||
return new GontiCannyAcquisitor(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@ import mage.MageInt;
|
|||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.effects.ExileFaceDownYouMayPlayAsLongAsExiledTargetEffect;
|
||||
import mage.abilities.effects.common.ExileFaceDownYouMayPlayAsLongAsExiledTargetEffect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.keyword.DeathtouchAbility;
|
||||
import mage.cards.*;
|
||||
|
|
@ -56,7 +56,7 @@ class GontiLordOfLuxuryEffect extends OneShotEffect {
|
|||
|
||||
public GontiLordOfLuxuryEffect() {
|
||||
super(Outcome.Benefit);
|
||||
this.staticText = "look at the top four cards of target opponent's library, exile one of them face down, then put the rest on the bottom of that library in a random order. You may look at and cast that card for as long as it remains exiled, and you may spend mana as though it were mana of any type to cast that spell";
|
||||
this.staticText = "look at the top four cards of target opponent's library, exile one of them face down, then put the rest on the bottom of that library in a random order. You may cast that card for as long as it remains exiled, and mana of any type can be spent to cast it";
|
||||
}
|
||||
|
||||
private GontiLordOfLuxuryEffect(final GontiLordOfLuxuryEffect effect) {
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@ import mage.MageInt;
|
|||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.effects.AsThoughEffectImpl;
|
||||
import mage.abilities.effects.ContinuousEffect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.asthought.MayLookAtTargetCardEffect;
|
||||
import mage.abilities.effects.common.combat.CantBlockAllEffect;
|
||||
import mage.abilities.keyword.HasteAbility;
|
||||
import mage.cards.Card;
|
||||
|
|
@ -125,46 +125,11 @@ class HeadlinerScarlettExileEffect extends OneShotEffect {
|
|||
if (game.getState().getZone(card.getId()) == Zone.EXILED) {
|
||||
card.setFaceDown(true, game);
|
||||
CardUtil.makeCardPlayable(game, source, card, false, Duration.EndOfTurn, false);
|
||||
ContinuousEffect effect = new HeadlinerScarlettLookEffect(controller.getId());
|
||||
ContinuousEffect effect = new MayLookAtTargetCardEffect(controller.getId());
|
||||
effect.setTargetPointer(new FixedTarget(card, game));
|
||||
game.addEffect(effect, source);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class HeadlinerScarlettLookEffect extends AsThoughEffectImpl {
|
||||
|
||||
private final UUID authorizedPlayerId;
|
||||
|
||||
public HeadlinerScarlettLookEffect(UUID authorizedPlayerId) {
|
||||
super(AsThoughEffectType.LOOK_AT_FACE_DOWN, Duration.EndOfGame, Outcome.Benefit);
|
||||
this.authorizedPlayerId = authorizedPlayerId;
|
||||
}
|
||||
|
||||
private HeadlinerScarlettLookEffect(final HeadlinerScarlettLookEffect effect) {
|
||||
super(effect);
|
||||
this.authorizedPlayerId = effect.authorizedPlayerId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HeadlinerScarlettLookEffect copy() {
|
||||
return new HeadlinerScarlettLookEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
|
||||
UUID cardId = getTargetPointer().getFirst(game, source);
|
||||
if (cardId == null) {
|
||||
this.discard(); // card is no longer in the origin zone, effect can be discarded
|
||||
}
|
||||
return affectedControllerId.equals(authorizedPlayerId)
|
||||
&& objectId.equals(cardId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,11 +4,13 @@ import mage.MageInt;
|
|||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.condition.common.SourceRemainsInZoneCondition;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.AsThoughEffectImpl;
|
||||
import mage.abilities.effects.ContinuousEffect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.DoIfCostPaid;
|
||||
import mage.abilities.effects.common.asthought.MayLookAtTargetCardEffect;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
|
|
@ -16,11 +18,10 @@ import mage.cards.CardSetInfo;
|
|||
import mage.constants.*;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.condition.common.SourceRemainsInZoneCondition;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
|
||||
/**
|
||||
* @author fireshoes
|
||||
|
|
@ -39,14 +40,9 @@ public final class IntetTheDreamer extends CardImpl {
|
|||
// Flying
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
|
||||
// Whenever Intet, the Dreamer deals combat damage to a player, you may pay {2}{U}. If you do, exile the top card of your library face down.
|
||||
// You may play that card without paying its mana cost for as long as Intet remains on the battlefield.
|
||||
// Whenever Intet, the Dreamer deals combat damage to a player, you may pay {2}{U}. If you do, exile the top card of your library face down. You may look at that card for as long as it remains exiled. You may play that card without paying its mana cost for as long as Intet remains on the battlefield.
|
||||
this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(
|
||||
new DoIfCostPaid(new IntetTheDreamerExileEffect(), new ManaCostsImpl<>("{2}{U}")), false, true));
|
||||
|
||||
// You may look at that card for as long as it remains exiled.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.ALL, new IntetTheDreamerLookEffect()));
|
||||
|
||||
}
|
||||
|
||||
private IntetTheDreamer(final IntetTheDreamer card) {
|
||||
|
|
@ -63,7 +59,9 @@ class IntetTheDreamerExileEffect extends OneShotEffect {
|
|||
|
||||
IntetTheDreamerExileEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "exile the top card of your library face down. You may play that card without paying its mana cost for as long as Intet remains on the battlefield";
|
||||
staticText = "exile the top card of your library face down. "
|
||||
+ "You may look at that card for as long as it remains exiled. "
|
||||
+ "You may play that card without paying its mana cost for as long as Intet remains on the battlefield";
|
||||
}
|
||||
|
||||
private IntetTheDreamerExileEffect(final IntetTheDreamerExileEffect effect) {
|
||||
|
|
@ -73,23 +71,28 @@ class IntetTheDreamerExileEffect extends OneShotEffect {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null) {
|
||||
Card card = controller.getLibrary().getFromTop(game);
|
||||
MageObject sourceObject = source.getSourceObject(game);
|
||||
if (card != null && sourceObject != null) {
|
||||
card.setFaceDown(true, game);
|
||||
controller.moveCardsToExile(card, source, game, false,
|
||||
CardUtil.getExileZoneId(game, source.getSourceId(), sourceObject.getZoneChangeCounter(game)), // sourceObject must be used due to source not working correctly
|
||||
sourceObject.getIdName() + " (" + sourceObject.getZoneChangeCounter(game) + ")");
|
||||
card.setFaceDown(true, game);
|
||||
IntetTheDreamerAsThoughEffect effect = new IntetTheDreamerAsThoughEffect();
|
||||
effect.setTargetPointer(new FixedTarget(card.getId(), game.getState().getZoneChangeCounter(card.getId())));
|
||||
game.getState().addEffect(effect, source);
|
||||
game.getState().setValue("Exiled_IntetTheDreamer" + card.getId(), Boolean.TRUE); // TODO This value will never be removed
|
||||
return true;
|
||||
}
|
||||
if (controller == null) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
|
||||
Card card = controller.getLibrary().getFromTop(game);
|
||||
MageObject sourceObject = source.getSourceObject(game);
|
||||
if (card == null || sourceObject == null) {
|
||||
return false;
|
||||
}
|
||||
UUID exileId = CardUtil.getExileZoneId(game, source.getSourceId(), sourceObject.getZoneChangeCounter(game));
|
||||
String exileName = sourceObject.getIdName() + " (" + sourceObject.getZoneChangeCounter(game) + ")";
|
||||
card.setFaceDown(true, game);
|
||||
if (controller.moveCardsToExile(card, source, game, false, exileId, exileName)) {
|
||||
card.setFaceDown(true, game);
|
||||
ContinuousEffect effect = new IntetTheDreamerAsThoughEffect();
|
||||
effect.setTargetPointer(new FixedTarget(card.getId(), game.getState().getZoneChangeCounter(card.getId())));
|
||||
game.getState().addEffect(effect, source);
|
||||
effect = new MayLookAtTargetCardEffect(controller.getId());
|
||||
effect.setTargetPointer(new FixedTarget(card, game));
|
||||
game.addEffect(effect, source);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -148,7 +151,7 @@ class IntetTheDreamerAsThoughEffect extends AsThoughEffectImpl {
|
|||
allowCardToPlayWithoutMana(objectId, source, affectedControllerId, game);
|
||||
|
||||
// while Intet remains on battlefield
|
||||
if(!(new SourceRemainsInZoneCondition(Zone.BATTLEFIELD).apply(game, source))) {
|
||||
if (!(new SourceRemainsInZoneCondition(Zone.BATTLEFIELD).apply(game, source))) {
|
||||
this.discard();
|
||||
return false;
|
||||
}
|
||||
|
|
@ -156,47 +159,4 @@ class IntetTheDreamerAsThoughEffect extends AsThoughEffectImpl {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class IntetTheDreamerLookEffect extends AsThoughEffectImpl {
|
||||
|
||||
IntetTheDreamerLookEffect() {
|
||||
super(AsThoughEffectType.LOOK_AT_FACE_DOWN, Duration.EndOfGame, Outcome.Benefit);
|
||||
staticText = "You may look at that card for as long as it remains exiled";
|
||||
}
|
||||
|
||||
private IntetTheDreamerLookEffect(final IntetTheDreamerLookEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IntetTheDreamerLookEffect copy() {
|
||||
return new IntetTheDreamerLookEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
|
||||
if (affectedControllerId.equals(source.getControllerId())) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null) {
|
||||
Card card = game.getCard(objectId);
|
||||
if (card != null) {
|
||||
if (card.isFaceDown(game)
|
||||
&& game.getExile().containsId(card.getId(), game)
|
||||
&& Boolean.TRUE.equals(game.getState().getValue("Exiled_IntetTheDreamer" + card.getId()))) {
|
||||
return true;
|
||||
} else {
|
||||
this.discard();
|
||||
game.getState().setValue("Exiled_IntetTheDreamer" + card.getId(), null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,26 +1,19 @@
|
|||
package mage.cards.i;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.BeginningOfYourEndStepTriggeredAbility;
|
||||
import mage.abilities.effects.AsThoughEffectImpl;
|
||||
import mage.abilities.effects.AsThoughManaEffect;
|
||||
import mage.abilities.effects.ContinuousEffect;
|
||||
import mage.abilities.effects.common.ExileFaceDownYouMayPlayAsLongAsExiledTargetEffect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.abilities.keyword.ToxicAbility;
|
||||
import mage.abilities.keyword.VigilanceAbility;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.cards.*;
|
||||
import mage.constants.*;
|
||||
import mage.counters.CounterType;
|
||||
import mage.game.Game;
|
||||
import mage.players.ManaPoolItem;
|
||||
import mage.players.Player;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
import mage.util.CardUtil;
|
||||
import mage.target.targetpointer.FixedTargets;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
|
@ -83,158 +76,22 @@ class IxhelScionOfAtraxaEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
MageObject sourceObject = source.getSourceObject(game);
|
||||
UUID exileZoneId = CardUtil.getExileZoneId(game, sourceObject.getId(), sourceObject.getZoneChangeCounter(game));
|
||||
|
||||
Cards cards = new CardsImpl();
|
||||
for (UUID opponentId : game.getOpponents(source.getControllerId(), true)) {
|
||||
Player opponent = game.getPlayer(opponentId);
|
||||
if (opponent == null || opponent.getCounters().getCount(CounterType.POISON) < 3 || !opponent.getLibrary().hasCards()) {
|
||||
continue;
|
||||
}
|
||||
// move card to exile
|
||||
Card topCard = opponent.getLibrary().getFromTop(game);
|
||||
topCard.setFaceDown(true, game);
|
||||
if (opponent.moveCardsToExile(topCard, source, game, false, exileZoneId, sourceObject.getIdName())) {
|
||||
topCard.setFaceDown(true, game);
|
||||
Card card = opponent.getLibrary().getFromTop(game);
|
||||
if (card != null) {
|
||||
cards.add(card);
|
||||
}
|
||||
game.getState().setValue(topCard.getId().toString() + game.getState().getZoneChangeCounter(topCard.getId()), exileZoneId);
|
||||
// you may play that card
|
||||
ContinuousEffect effect = new IxhelScionOfAtraxaPlayFromExileEffect();
|
||||
effect.setTargetPointer(new FixedTarget(topCard.getId(), game));
|
||||
game.addEffect(effect, source);
|
||||
// you may spend mana as though it were many of any color to cast it
|
||||
effect = new IxhelScionOfAtraxaSpendAnyManaEffect();
|
||||
effect.setTargetPointer(new FixedTarget(topCard.getId(), game));
|
||||
game.addEffect(effect, source);
|
||||
// for as long as that card remains exiled, you may look at it
|
||||
effect = new IxhelScionOfAtraxaLookEffect(source.getControllerId());
|
||||
effect.setTargetPointer(new FixedTarget(topCard.getId(), game));
|
||||
game.addEffect(effect, source);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class IxhelScionOfAtraxaPlayFromExileEffect extends AsThoughEffectImpl {
|
||||
|
||||
IxhelScionOfAtraxaPlayFromExileEffect() {
|
||||
super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.Custom, Outcome.Benefit);
|
||||
}
|
||||
|
||||
private IxhelScionOfAtraxaPlayFromExileEffect(final IxhelScionOfAtraxaPlayFromExileEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IxhelScionOfAtraxaPlayFromExileEffect copy() {
|
||||
return new IxhelScionOfAtraxaPlayFromExileEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
|
||||
UUID targetId = getTargetPointer().getFirst(game, source);
|
||||
if (targetId == null) {
|
||||
// card is no longer in the origin zone, effect can be discarded
|
||||
this.discard();
|
||||
if (cards.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
Card theCard = game.getCard(objectId);
|
||||
if (theCard == null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// for split cards
|
||||
objectId = theCard.getMainCard().getId();
|
||||
|
||||
if (objectId.equals(targetId) && affectedControllerId.equals(source.getControllerId())) {
|
||||
Card card = game.getCard(objectId);
|
||||
return card != null;
|
||||
}
|
||||
return false;
|
||||
return new ExileFaceDownYouMayPlayAsLongAsExiledTargetEffect(false, CastManaAdjustment.AS_THOUGH_ANY_MANA_COLOR)
|
||||
.setTargetPointer(new FixedTargets(cards, game))
|
||||
.apply(game, source);
|
||||
}
|
||||
}
|
||||
|
||||
class IxhelScionOfAtraxaSpendAnyManaEffect extends AsThoughEffectImpl implements AsThoughManaEffect {
|
||||
|
||||
public IxhelScionOfAtraxaSpendAnyManaEffect() {
|
||||
super(AsThoughEffectType.SPEND_OTHER_MANA, Duration.Custom, Outcome.Benefit);
|
||||
}
|
||||
|
||||
private IxhelScionOfAtraxaSpendAnyManaEffect(final IxhelScionOfAtraxaSpendAnyManaEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IxhelScionOfAtraxaSpendAnyManaEffect copy() {
|
||||
return new IxhelScionOfAtraxaSpendAnyManaEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
|
||||
Card theCard = game.getCard(objectId);
|
||||
if (theCard == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// for split cards
|
||||
objectId = theCard.getMainCard().getId();
|
||||
|
||||
if (objectId.equals(((FixedTarget) getTargetPointer()).getTarget())
|
||||
&& game.getState().getZoneChangeCounter(objectId) <= ((FixedTarget) getTargetPointer()).getZoneChangeCounter() + 1) {
|
||||
// if the card moved from exile to spell the zone change counter is increased by 1 (effect must applies before and on stack, use isCheckPlayableMode?)
|
||||
return source.isControlledBy(affectedControllerId);
|
||||
} else if (((FixedTarget) getTargetPointer()).getTarget().equals(objectId)) {
|
||||
// object has moved zone so effect can be discarded
|
||||
this.discard();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ManaType getAsThoughManaType(ManaType manaType, ManaPoolItem mana, UUID affectedControllerId, Ability source, Game game) {
|
||||
return mana.getFirstAvailable();
|
||||
}
|
||||
}
|
||||
|
||||
class IxhelScionOfAtraxaLookEffect extends AsThoughEffectImpl {
|
||||
|
||||
private final UUID authorizedPlayerId;
|
||||
|
||||
public IxhelScionOfAtraxaLookEffect(UUID authorizedPlayerId) {
|
||||
super(AsThoughEffectType.LOOK_AT_FACE_DOWN, Duration.EndOfGame, Outcome.Benefit);
|
||||
this.authorizedPlayerId = authorizedPlayerId;
|
||||
}
|
||||
|
||||
private IxhelScionOfAtraxaLookEffect(final IxhelScionOfAtraxaLookEffect effect) {
|
||||
super(effect);
|
||||
this.authorizedPlayerId = effect.authorizedPlayerId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) { return true; }
|
||||
|
||||
@Override
|
||||
public IxhelScionOfAtraxaLookEffect copy() { return new IxhelScionOfAtraxaLookEffect(this); }
|
||||
|
||||
@Override
|
||||
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
|
||||
UUID cardId = getTargetPointer().getFirst(game, source);
|
||||
|
||||
// card is no longer in the origin zone, effect can be discarded
|
||||
if (cardId == null) {
|
||||
this.discard();
|
||||
}
|
||||
|
||||
return affectedControllerId.equals(authorizedPlayerId) && objectId.equals(cardId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,15 +3,21 @@ package mage.cards.m;
|
|||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.MutatesSourceTriggeredAbility;
|
||||
import mage.abilities.effects.AsThoughEffectImpl;
|
||||
import mage.abilities.effects.common.ExileFaceDownYouMayPlayAsLongAsExiledTargetEffect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.abilities.keyword.MutateAbility;
|
||||
import mage.cards.*;
|
||||
import mage.constants.*;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.cards.Cards;
|
||||
import mage.cards.CardsImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.CastManaAdjustment;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
import mage.target.targetpointer.FixedTargets;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
|
@ -82,93 +88,8 @@ class MindleecherEffect extends OneShotEffect {
|
|||
if (cards.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
controller.moveCards(cards, Zone.EXILED, source, game);
|
||||
cards.removeIf(uuid -> game.getState().getZone(uuid) != Zone.EXILED);
|
||||
if (cards.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
cards.getCards(game).stream().forEach(card -> card.setFaceDown(true, game));
|
||||
for (Card card : cards.getCards(game)) {
|
||||
game.addEffect(new MindleecherCastFromExileEffect(controller.getId())
|
||||
.setTargetPointer(new FixedTarget(card, game)), source);
|
||||
game.addEffect(new MindleecherLookEffect(controller.getId())
|
||||
.setTargetPointer(new FixedTarget(card, game)), source);
|
||||
}
|
||||
return true;
|
||||
return new ExileFaceDownYouMayPlayAsLongAsExiledTargetEffect(false, CastManaAdjustment.NONE)
|
||||
.setTargetPointer(new FixedTargets(cards, game))
|
||||
.apply(game, source);
|
||||
}
|
||||
}
|
||||
|
||||
class MindleecherCastFromExileEffect extends AsThoughEffectImpl {
|
||||
|
||||
private final UUID authorizedPlayerId;
|
||||
|
||||
MindleecherCastFromExileEffect(UUID authorizedPlayerId) {
|
||||
super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.Custom, Outcome.Benefit);
|
||||
this.authorizedPlayerId = authorizedPlayerId;
|
||||
staticText = "For as long as that card remains exiled, you may play it";
|
||||
}
|
||||
|
||||
private MindleecherCastFromExileEffect(final MindleecherCastFromExileEffect effect) {
|
||||
super(effect);
|
||||
this.authorizedPlayerId = effect.authorizedPlayerId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MindleecherCastFromExileEffect copy() {
|
||||
return new MindleecherCastFromExileEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
|
||||
UUID cardId = getTargetPointer().getFirst(game, source);
|
||||
if (cardId == null) {
|
||||
this.discard(); // card is no longer in the origin zone, effect can be discarded
|
||||
return false;
|
||||
}
|
||||
return objectId.equals(cardId)
|
||||
&& affectedControllerId.equals(authorizedPlayerId)
|
||||
&& game.getCard(objectId) != null;
|
||||
}
|
||||
}
|
||||
|
||||
class MindleecherLookEffect extends AsThoughEffectImpl {
|
||||
|
||||
private final UUID authorizedPlayerId;
|
||||
|
||||
MindleecherLookEffect(UUID authorizedPlayerId) {
|
||||
super(AsThoughEffectType.LOOK_AT_FACE_DOWN, Duration.EndOfGame, Outcome.Benefit);
|
||||
this.authorizedPlayerId = authorizedPlayerId;
|
||||
staticText = "For as long as that card remains exiled, you may look at it";
|
||||
}
|
||||
|
||||
private MindleecherLookEffect(final MindleecherLookEffect effect) {
|
||||
super(effect);
|
||||
this.authorizedPlayerId = effect.authorizedPlayerId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MindleecherLookEffect copy() {
|
||||
return new MindleecherLookEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
|
||||
UUID cardId = getTargetPointer().getFirst(game, source);
|
||||
if (cardId == null) {
|
||||
this.discard(); // card is no longer in the origin zone, effect can be discarded
|
||||
return false;
|
||||
}
|
||||
return affectedControllerId.equals(authorizedPlayerId)
|
||||
&& objectId.equals(cardId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,23 +1,13 @@
|
|||
package mage.cards.o;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.ContinuousEffect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.asthought.MayLookAtTargetCardEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.abilities.dynamicvalue.common.ManacostVariableValue;
|
||||
import mage.abilities.effects.common.ExileFaceDownTopNLibraryYouMayPlayAsLongAsExiledTargetEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.constants.CastManaAdjustment;
|
||||
import mage.target.common.TargetOpponent;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
|
|
@ -28,10 +18,14 @@ public final class OutrageousRobbery extends CardImpl {
|
|||
public OutrageousRobbery(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{X}{B}{B}");
|
||||
|
||||
// Target opponent exiles the top X cards of their library face down.
|
||||
// You may look at and play those cards for as long as they remain exiled.
|
||||
// If you cast a spell this way, you may spend mana as though it were mana of any type to cast it.
|
||||
this.getSpellAbility().addEffect(new OutrageousRobberyEffect());
|
||||
// Target opponent exiles the top X cards of their library face down. You may look at and play those cards for as long as they remain exiled. If you cast a spell this way, you may spend mana as though it were mana of any type to cast it.
|
||||
this.getSpellAbility().addEffect(
|
||||
new ExileFaceDownTopNLibraryYouMayPlayAsLongAsExiledTargetEffect(
|
||||
false, CastManaAdjustment.AS_THOUGH_ANY_MANA_TYPE, ManacostVariableValue.REGULAR
|
||||
).setText("Target opponent exiles the top X cards of their library face down. "
|
||||
+ "You may look at and play those cards for as long as they remain exiled. "
|
||||
+ "If you cast a spell this way, you may spend mana as though it were mana of any type to cast it.")
|
||||
);
|
||||
this.getSpellAbility().addTarget(new TargetOpponent());
|
||||
}
|
||||
|
||||
|
|
@ -43,57 +37,4 @@ public final class OutrageousRobbery extends CardImpl {
|
|||
public OutrageousRobbery copy() {
|
||||
return new OutrageousRobbery(this);
|
||||
}
|
||||
}
|
||||
|
||||
class OutrageousRobberyEffect extends OneShotEffect {
|
||||
|
||||
OutrageousRobberyEffect() {
|
||||
super(Outcome.Benefit);
|
||||
this.staticText = "Target opponent exiles the top X cards of their library face down. " +
|
||||
"You may look at and play those cards for as long as they remain exiled. " +
|
||||
"If you cast a spell this way, you may spend mana as though it were mana of any type to cast it.";
|
||||
}
|
||||
|
||||
private OutrageousRobberyEffect(final OutrageousRobberyEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutrageousRobberyEffect copy() {
|
||||
return new OutrageousRobberyEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
Player opponent = game.getPlayer(source.getFirstTarget());
|
||||
MageObject sourceObject = source.getSourceObject(game);
|
||||
if (controller == null || opponent == null || sourceObject == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int xValue = source.getManaCostsToPay().getX();
|
||||
if (xValue == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Set<Card> cards = opponent.getLibrary().getTopCards(game, xValue);
|
||||
cards.forEach(card -> card.setFaceDown(true, game));
|
||||
UUID exileZoneId = CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter());
|
||||
if (cards.size() > 0 && opponent.moveCardsToExile(cards, source, game, false, exileZoneId,
|
||||
sourceObject.getIdName() + " (" + controller.getName() + ")")) {
|
||||
for (Card card : cards) {
|
||||
card.setFaceDown(true, game);
|
||||
|
||||
ContinuousEffect effect = new MayLookAtTargetCardEffect(controller.getId());
|
||||
effect.setTargetPointer(new FixedTarget(card.getId(), game));
|
||||
game.addEffect(effect, source);
|
||||
|
||||
CardUtil.makeCardPlayable(
|
||||
game, source, card, false, Duration.Custom, true,
|
||||
source.getControllerId(), null);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,18 +2,19 @@ package mage.cards.p;
|
|||
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.AsThoughEffectImpl;
|
||||
import mage.abilities.effects.common.ExileFaceDownYouMayPlayAsLongAsExiledTargetEffect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.game.ExileZone;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.CastManaAdjustment;
|
||||
import mage.constants.Outcome;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetCardInLibrary;
|
||||
import mage.target.common.TargetOpponent;
|
||||
import mage.util.CardUtil;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
|
@ -25,8 +26,7 @@ public final class PraetorsGrasp extends CardImpl {
|
|||
public PraetorsGrasp(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{B}{B}");
|
||||
|
||||
// Search target opponent's library for a card and exile it face down. Then that player
|
||||
//shuffles their library. You may look at and play that card for as long as it remains exiled.
|
||||
// Search target opponent's library for a card and exile it face down. Then that player shuffles their library. You may look at and play that card for as long as it remains exiled.
|
||||
this.getSpellAbility().addEffect(new PraetorsGraspEffect());
|
||||
this.getSpellAbility().addTarget(new TargetOpponent());
|
||||
}
|
||||
|
|
@ -74,121 +74,13 @@ class PraetorsGraspEffect extends OneShotEffect {
|
|||
if (card == null) {
|
||||
return false;
|
||||
}
|
||||
// account for card going into exile from the library
|
||||
final int zcc = game.getState().getZoneChangeCounter(card.getId()) + 1;
|
||||
UUID exileId = CardUtil.getExileZoneId(card.getId().toString() + zcc, game);
|
||||
if (exileId != null) {
|
||||
game.informPlayers(controller.getLogName() + " moves the searched "
|
||||
+ "card face down to exile");
|
||||
card.moveToExile(exileId, sourceObject.getIdName(), source, game);
|
||||
card.setFaceDown(true, game);
|
||||
game.addEffect(new PraetorsGraspPlayEffect(card.getId()), source);
|
||||
game.addEffect(new PraetorsGraspRevealEffect(card.getId()), source);
|
||||
}
|
||||
new ExileFaceDownYouMayPlayAsLongAsExiledTargetEffect(false, CastManaAdjustment.NONE)
|
||||
.setTargetPointer(new FixedTarget(card, game))
|
||||
.apply(game, source);
|
||||
}
|
||||
opponent.shuffleLibrary(source, game);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class PraetorsGraspPlayEffect extends AsThoughEffectImpl {
|
||||
|
||||
private UUID cardId;
|
||||
|
||||
public PraetorsGraspPlayEffect(UUID cardId) {
|
||||
super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfGame, Outcome.Benefit);
|
||||
this.cardId = cardId;
|
||||
staticText = "You may look at and play that card for as long as it remains exiled";
|
||||
}
|
||||
|
||||
private PraetorsGraspPlayEffect(final PraetorsGraspPlayEffect effect) {
|
||||
super(effect);
|
||||
this.cardId = effect.cardId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PraetorsGraspPlayEffect copy() {
|
||||
return new PraetorsGraspPlayEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
|
||||
if (objectId.equals(cardId)
|
||||
&& affectedControllerId.equals(source.getControllerId())) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
UUID exileId = CardUtil.getExileZoneId(cardId.toString() + game.getState().getZoneChangeCounter(cardId), game);
|
||||
if (exileId != null
|
||||
&& controller != null) {
|
||||
ExileZone exileZone = game.getExile().getExileZone(exileId);
|
||||
if (exileZone != null
|
||||
&& exileZone.contains(cardId)) {
|
||||
return true;
|
||||
} else {
|
||||
discard();
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class PraetorsGraspRevealEffect extends AsThoughEffectImpl {
|
||||
|
||||
private final UUID cardId;
|
||||
|
||||
public PraetorsGraspRevealEffect(UUID cardId) {
|
||||
super(AsThoughEffectType.LOOK_AT_FACE_DOWN, Duration.EndOfGame, Outcome.Benefit);
|
||||
this.cardId = cardId;
|
||||
staticText = "You may look at and play that card for as long as it remains exiled";
|
||||
}
|
||||
|
||||
private PraetorsGraspRevealEffect(final PraetorsGraspRevealEffect effect) {
|
||||
super(effect);
|
||||
this.cardId = effect.cardId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PraetorsGraspRevealEffect copy() {
|
||||
return new PraetorsGraspRevealEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
|
||||
if (objectId.equals(cardId)
|
||||
&& affectedControllerId.equals(source.getControllerId())) {
|
||||
MageObject sourceObject = source.getSourceObject(game);
|
||||
UUID exileId = CardUtil.getExileZoneId(cardId.toString() + game.getState().getZoneChangeCounter(cardId), game);
|
||||
if (exileId != null
|
||||
&& sourceObject != null) {
|
||||
ExileZone exileZone = game.getExile().getExileZone(exileId);
|
||||
if (exileZone != null
|
||||
&& exileZone.contains(cardId)) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
Card card = game.getCard(cardId);
|
||||
if (controller != null
|
||||
&& card != null
|
||||
&& game.getState().getZone(cardId) == Zone.EXILED) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
discard();
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,26 +1,16 @@
|
|||
package mage.cards.p;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
|
||||
import mage.abilities.effects.AsThoughEffectImpl;
|
||||
import mage.abilities.effects.AsThoughManaEffect;
|
||||
import mage.abilities.effects.ContinuousEffect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.asthought.MayLookAtTargetCardEffect;
|
||||
import mage.abilities.effects.common.ExileFaceDownTopNLibraryYouMayPlayAsLongAsExiledTargetEffect;
|
||||
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
|
||||
import mage.abilities.keyword.MenaceAbility;
|
||||
import mage.cards.*;
|
||||
import mage.constants.*;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.CastManaAdjustment;
|
||||
import mage.constants.Duration;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.players.ManaPoolItem;
|
||||
import mage.players.Player;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
|
|
@ -29,13 +19,13 @@ import java.util.UUID;
|
|||
public final class PredatorsHour extends CardImpl {
|
||||
|
||||
public PredatorsHour(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{1}{B}");
|
||||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{B}");
|
||||
|
||||
// Until end of turn, creatures you control gain menace
|
||||
this.getSpellAbility().addEffect(new GainAbilityControlledEffect(
|
||||
new MenaceAbility(false),
|
||||
Duration.EndOfTurn,
|
||||
StaticFilters.FILTER_CONTROLLED_CREATURES
|
||||
new MenaceAbility(false),
|
||||
Duration.EndOfTurn,
|
||||
StaticFilters.FILTER_CONTROLLED_CREATURES
|
||||
).setText("Until end of turn, creatures you control gain menace")
|
||||
);
|
||||
|
||||
|
|
@ -43,178 +33,30 @@ public final class PredatorsHour extends CardImpl {
|
|||
// exile the top card of that player's library face down.
|
||||
// You may look at and play that card for as long as it remains exiled,
|
||||
// and you may spend mana as though it were mana of any color to cast that spell.”
|
||||
this.getSpellAbility().addEffect(new GainAbilityControlledEffect(
|
||||
new DealsCombatDamageToAPlayerTriggeredAbility(
|
||||
new PredatorsHourEffect(),
|
||||
false,
|
||||
true),
|
||||
Duration.EndOfTurn,
|
||||
StaticFilters.FILTER_CONTROLLED_CREATURES
|
||||
this.getSpellAbility().addEffect(
|
||||
new GainAbilityControlledEffect(
|
||||
new DealsCombatDamageToAPlayerTriggeredAbility(
|
||||
new ExileFaceDownTopNLibraryYouMayPlayAsLongAsExiledTargetEffect(false, CastManaAdjustment.AS_THOUGH_ANY_MANA_COLOR)
|
||||
.setText("exile the top card of that player's library face down. "
|
||||
+ "You may look at and play that card for as long as it remains exiled, "
|
||||
+ "and you may spend mana as though it were mana of any color to cast that spell."),
|
||||
false, true),
|
||||
Duration.EndOfTurn,
|
||||
StaticFilters.FILTER_CONTROLLED_CREATURES
|
||||
).setText("\"Whenever this creature deals combat damage to a player, " +
|
||||
"exile the top card of that player's library face down. " +
|
||||
"You may look at and play that card for as long as it remains exiled, " +
|
||||
"and you may spend mana as though it were mana of any color to cast that spell.\"")
|
||||
.concatBy("and")
|
||||
"and you may spend mana as though it were mana of any color to cast that spell.\""
|
||||
).concatBy("and")
|
||||
);
|
||||
}
|
||||
|
||||
private PredatorsHour(final PredatorsHour card) { super(card); }
|
||||
|
||||
@Override
|
||||
public PredatorsHour copy() { return new PredatorsHour(this); }
|
||||
}
|
||||
|
||||
// Based on Gonti, Lord of Luxury
|
||||
class PredatorsHourEffect extends OneShotEffect {
|
||||
|
||||
private static final String VALUE_PREFIX = "ExileZones";
|
||||
|
||||
public PredatorsHourEffect() {
|
||||
super(Outcome.Benefit);
|
||||
this.staticText = "exile the top card of that player's library face down. " +
|
||||
"You may look at and play that card for as long as it remains exiled, " +
|
||||
"and you may spend mana as though it were mana of any color to cast that spell.";
|
||||
}
|
||||
|
||||
private PredatorsHourEffect(final PredatorsHourEffect effect) { super(effect); }
|
||||
|
||||
@Override
|
||||
public PredatorsHourEffect copy() { return new PredatorsHourEffect(this); }
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Player opponent = game.getPlayer(getTargetPointer().getFirst(game, source));
|
||||
if (opponent == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MageObject sourceObject = source.getSourceObject(game);
|
||||
if (sourceObject == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Card topCard = opponent.getLibrary().getFromTop(game);
|
||||
if (topCard == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
UUID exileZoneId = CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter());
|
||||
topCard.setFaceDown(true, game);
|
||||
|
||||
// Move card to exile
|
||||
if (controller.moveCardsToExile(topCard, source, game, false, exileZoneId, sourceObject.getIdName())) {
|
||||
topCard.setFaceDown(true, game);
|
||||
|
||||
Set<UUID> exileZones = (Set<UUID>) game.getState().getValue(VALUE_PREFIX + source.getSourceId().toString());
|
||||
if (exileZones == null) {
|
||||
exileZones = new HashSet<>();
|
||||
game.getState().setValue(VALUE_PREFIX + source.getSourceId().toString(), exileZones);
|
||||
}
|
||||
exileZones.add(exileZoneId);
|
||||
|
||||
// You may play the card
|
||||
ContinuousEffect effect = new PredatorsHourPlayFromExileEffect();
|
||||
effect.setTargetPointer(new FixedTarget(topCard.getId(), game));
|
||||
game.addEffect(effect, source);
|
||||
|
||||
// And you may spend mana as though it were mana of any color to cast it
|
||||
effect = new PredatorsHourSpendAnyManaEffect();
|
||||
effect.setTargetPointer(new FixedTarget(topCard.getId(), game));
|
||||
game.addEffect(effect, source);
|
||||
|
||||
// For as long as that card remains exiled, you may look at it
|
||||
effect = new MayLookAtTargetCardEffect(controller.getId());
|
||||
effect.setTargetPointer(new FixedTarget(topCard.getId(), game));
|
||||
game.addEffect(effect, source);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class PredatorsHourPlayFromExileEffect extends AsThoughEffectImpl {
|
||||
|
||||
PredatorsHourPlayFromExileEffect() {
|
||||
super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.Custom, Outcome.Benefit);
|
||||
staticText = "You may look at and play that card for as long as it remains exiled, " +
|
||||
"and you may spend mana as though it were mana of any color to cast that spell.";
|
||||
}
|
||||
|
||||
private PredatorsHourPlayFromExileEffect(final PredatorsHourPlayFromExileEffect effect) { super(effect); }
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) { return true; }
|
||||
|
||||
@Override
|
||||
public PredatorsHourPlayFromExileEffect copy() { return new PredatorsHourPlayFromExileEffect(this); }
|
||||
|
||||
@Override
|
||||
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
|
||||
UUID targetId = getTargetPointer().getFirst(game, source);
|
||||
if (targetId == null) {
|
||||
// card is no longer in the origin zone, effect can be discarded
|
||||
this.discard();
|
||||
return false;
|
||||
}
|
||||
Card theCard = game.getCard(objectId);
|
||||
if (theCard == null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// for split cards
|
||||
objectId = theCard.getMainCard().getId();
|
||||
|
||||
if (objectId.equals(targetId) && affectedControllerId.equals(source.getControllerId())) {
|
||||
Card card = game.getCard(objectId);
|
||||
return card != null;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class PredatorsHourSpendAnyManaEffect extends AsThoughEffectImpl implements AsThoughManaEffect {
|
||||
|
||||
public PredatorsHourSpendAnyManaEffect() {
|
||||
super(AsThoughEffectType.SPEND_OTHER_MANA, Duration.Custom, Outcome.Benefit);
|
||||
staticText = "you may spend mana as though it were mana of any color to cast that spell";
|
||||
}
|
||||
|
||||
private PredatorsHourSpendAnyManaEffect(final PredatorsHourSpendAnyManaEffect effect) { super(effect); }
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) { return true; }
|
||||
|
||||
@Override
|
||||
public PredatorsHourSpendAnyManaEffect copy() { return new PredatorsHourSpendAnyManaEffect(this); }
|
||||
|
||||
@Override
|
||||
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
|
||||
Card theCard = game.getCard(objectId);
|
||||
if (theCard == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// for split cards
|
||||
objectId = theCard.getMainCard().getId();
|
||||
|
||||
if (objectId.equals(((FixedTarget) getTargetPointer()).getTarget())
|
||||
&& game.getState().getZoneChangeCounter(objectId) <= ((FixedTarget) getTargetPointer()).getZoneChangeCounter() + 1) {
|
||||
// if the card moved from exile to spell the zone change counter is increased by 1 (effect must applies before and on stack, use isCheckPlayableMode?)
|
||||
return source.isControlledBy(affectedControllerId);
|
||||
} else if (((FixedTarget) getTargetPointer()).getTarget().equals(objectId)) {
|
||||
// object has moved zone so effect can be discarded
|
||||
this.discard();
|
||||
}
|
||||
return false;
|
||||
private PredatorsHour(final PredatorsHour card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ManaType getAsThoughManaType(ManaType manaType, ManaPoolItem mana, UUID affectedControllerId, Ability source, Game game) {
|
||||
return mana.getFirstAvailable();
|
||||
public PredatorsHour copy() {
|
||||
return new PredatorsHour(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,25 +3,21 @@ package mage.cards.s;
|
|||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.AsThoughEffectImpl;
|
||||
import mage.abilities.effects.AsThoughManaEffect;
|
||||
import mage.abilities.effects.ContinuousEffect;
|
||||
import mage.abilities.effects.common.ExileFaceDownYouMayPlayAsLongAsExiledTargetEffect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.asthought.MayLookAtTargetCardEffect;
|
||||
import mage.abilities.keyword.FlashbackAbility;
|
||||
import mage.cards.*;
|
||||
import mage.constants.*;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.CastManaAdjustment;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.game.Game;
|
||||
import mage.players.ManaPoolItem;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetCard;
|
||||
import mage.target.common.TargetOpponent;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
|
|
@ -88,122 +84,12 @@ class SiphonInsightEffect extends OneShotEffect {
|
|||
controller.putCardsOnBottomOfLibrary(topCards, game, source, false);
|
||||
return true;
|
||||
}
|
||||
topCards.remove(card);
|
||||
// move card to exile
|
||||
UUID exileZoneId = CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter());
|
||||
card.setFaceDown(true, game);
|
||||
if (controller.moveCardsToExile(card, source, game, false, exileZoneId, sourceObject.getIdName())) {
|
||||
card.setFaceDown(true, game);
|
||||
Set<UUID> exileZones = (Set<UUID>) game.getState().getValue(VALUE_PREFIX + source.getSourceId().toString());
|
||||
if (exileZones == null) {
|
||||
exileZones = new HashSet<>();
|
||||
game.getState().setValue(VALUE_PREFIX + source.getSourceId().toString(), exileZones);
|
||||
}
|
||||
exileZones.add(exileZoneId);
|
||||
// allow to cast the card
|
||||
ContinuousEffect effect = new SiphonInsightCastFromExileEffect();
|
||||
effect.setTargetPointer(new FixedTarget(card.getId(), game));
|
||||
game.addEffect(effect, source);
|
||||
// and you may spend mana as though it were mana of any color to cast it
|
||||
effect = new SiphonInsightSpendAnyManaEffect();
|
||||
effect.setTargetPointer(new FixedTarget(card.getId(), game));
|
||||
game.addEffect(effect, source);
|
||||
// For as long as that card remains exiled, you may look at it
|
||||
effect = new MayLookAtTargetCardEffect(controller.getId());
|
||||
effect.setTargetPointer(new FixedTarget(card.getId(), game));
|
||||
game.addEffect(effect, source);
|
||||
}
|
||||
new ExileFaceDownYouMayPlayAsLongAsExiledTargetEffect(false, CastManaAdjustment.AS_THOUGH_ANY_MANA_COLOR)
|
||||
.setTargetPointer(new FixedTarget(card, game))
|
||||
.apply(game, source);
|
||||
topCards.retainZone(Zone.LIBRARY, game);
|
||||
// then put the rest on the bottom of that library in a random order
|
||||
controller.putCardsOnBottomOfLibrary(topCards, game, source, false);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class SiphonInsightCastFromExileEffect extends AsThoughEffectImpl {
|
||||
|
||||
SiphonInsightCastFromExileEffect() {
|
||||
super(AsThoughEffectType.CAST_FROM_NOT_OWN_HAND_ZONE, Duration.Custom, Outcome.Benefit);
|
||||
staticText = "You may cast that card for as long as it remains exiled, and you may spend mana as though it were mana of any color to cast that spell";
|
||||
}
|
||||
|
||||
private SiphonInsightCastFromExileEffect(final SiphonInsightCastFromExileEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SiphonInsightCastFromExileEffect copy() {
|
||||
return new SiphonInsightCastFromExileEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
|
||||
UUID targetId = getTargetPointer().getFirst(game, source);
|
||||
if (targetId == null) {
|
||||
this.discard(); // card is no longer in the origin zone, effect can be discarded
|
||||
return false;
|
||||
}
|
||||
Card theCard = game.getCard(objectId);
|
||||
if (theCard == null) {
|
||||
return false;
|
||||
}
|
||||
objectId = theCard.getMainCard().getId(); // for split cards
|
||||
|
||||
if (objectId.equals(targetId)
|
||||
&& affectedControllerId.equals(source.getControllerId())) {
|
||||
Card card = game.getCard(objectId);
|
||||
// TODO: Allow to cast Zoetic Cavern face down
|
||||
return card != null;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class SiphonInsightSpendAnyManaEffect extends AsThoughEffectImpl implements AsThoughManaEffect {
|
||||
|
||||
public SiphonInsightSpendAnyManaEffect() {
|
||||
super(AsThoughEffectType.SPEND_OTHER_MANA, Duration.Custom, Outcome.Benefit);
|
||||
staticText = "you may spend mana as though it were mana of any color to cast it";
|
||||
}
|
||||
|
||||
private SiphonInsightSpendAnyManaEffect(final SiphonInsightSpendAnyManaEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SiphonInsightSpendAnyManaEffect copy() {
|
||||
return new SiphonInsightSpendAnyManaEffect(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
|
||||
if (objectId.equals(((FixedTarget) getTargetPointer()).getTarget())
|
||||
&& game.getState().getZoneChangeCounter(objectId) <= ((FixedTarget) getTargetPointer()).getZoneChangeCounter() + 1) {
|
||||
// if the card moved from exile to spell the zone change counter is increased by 1 (effect must applies before and on stack, use isCheckPlayableMode?)
|
||||
return source.isControlledBy(affectedControllerId);
|
||||
} else if (((FixedTarget) getTargetPointer()).getTarget().equals(objectId)) {
|
||||
// object has moved zone so effect can be discarded
|
||||
this.discard();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ManaType getAsThoughManaType(ManaType manaType, ManaPoolItem mana, UUID affectedControllerId, Ability source, Game game) {
|
||||
return mana.getFirstAvailable();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,24 +4,17 @@ import mage.MageInt;
|
|||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
|
||||
import mage.abilities.effects.AsThoughEffectImpl;
|
||||
import mage.abilities.effects.AsThoughManaEffect;
|
||||
import mage.abilities.effects.ContinuousEffect;
|
||||
import mage.abilities.effects.common.ExileFaceDownYouMayPlayAsLongAsExiledTargetEffect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.asthought.MayLookAtTargetCardEffect;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.cards.*;
|
||||
import mage.constants.*;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.game.Game;
|
||||
import mage.players.ManaPoolItem;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetCard;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
|
|
@ -29,8 +22,6 @@ import java.util.UUID;
|
|||
*/
|
||||
public final class ThiefOfSanity extends CardImpl {
|
||||
|
||||
protected static final String VALUE_PREFIX = "ExileZones";
|
||||
|
||||
public ThiefOfSanity(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}{B}");
|
||||
|
||||
|
|
@ -60,7 +51,7 @@ class ThiefOfSanityEffect extends OneShotEffect {
|
|||
ThiefOfSanityEffect() {
|
||||
super(Outcome.Benefit);
|
||||
this.staticText = "look at the top three cards of that player's library, exile one of them face down, then put the rest into their graveyard. "
|
||||
+ "For as long as that card remains exiled, you may look at it, you may cast it, and you may spend mana as though it were mana of any type to cast it";
|
||||
+ "You may cast that card for as long as it remains exiled, and mana of any type can be spent to cast it";
|
||||
}
|
||||
|
||||
private ThiefOfSanityEffect(final ThiefOfSanityEffect effect) {
|
||||
|
|
@ -77,139 +68,24 @@ class ThiefOfSanityEffect extends OneShotEffect {
|
|||
Player controller = game.getPlayer(source.getControllerId());
|
||||
Player damagedPlayer = game.getPlayer(getTargetPointer().getFirst(game, source));
|
||||
MageObject sourceObject = source.getSourceObject(game);
|
||||
if (controller != null && damagedPlayer != null && sourceObject != null) {
|
||||
Cards topCards = new CardsImpl();
|
||||
topCards.addAllCards(damagedPlayer.getLibrary().getTopCards(game, 3));
|
||||
TargetCard target = new TargetCard(Zone.LIBRARY, new FilterCard("card to exile face down"));
|
||||
if (controller.choose(outcome, topCards, target, source, game)) {
|
||||
Card card = game.getCard(target.getFirstTarget());
|
||||
if (card != null) {
|
||||
topCards.remove(card);
|
||||
// move card to exile
|
||||
UUID exileZoneId = CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter());
|
||||
card.setFaceDown(true, game);
|
||||
if (controller.moveCardsToExile(card, source, game, false, exileZoneId, sourceObject.getIdName() + " (" + controller.getName() + ")")) {
|
||||
card.setFaceDown(true, game);
|
||||
Set<UUID> exileZones = (Set<UUID>) game.getState().getValue(ThiefOfSanity.VALUE_PREFIX + source.getSourceId().toString());
|
||||
if (exileZones == null) {
|
||||
exileZones = new HashSet<>();
|
||||
game.getState().setValue(ThiefOfSanity.VALUE_PREFIX + source.getSourceId().toString(), exileZones);
|
||||
}
|
||||
exileZones.add(exileZoneId);
|
||||
// rule information: https://blogs.magicjudges.org/rulestips/2018/11/thief-of-sanity-and-control-changing/
|
||||
// allow to cast the card
|
||||
ContinuousEffect effect = new ThiefOfSanityCastFromExileEffect(controller.getId());
|
||||
effect.setTargetPointer(new FixedTarget(card.getId(), game));
|
||||
game.addEffect(effect, source);
|
||||
// and you may spend mana as though it were mana of any color to cast it
|
||||
effect = new ThiefOfSanitySpendAnyManaEffect(controller.getId());
|
||||
effect.setTargetPointer(new FixedTarget(card.getId(), game));
|
||||
game.addEffect(effect, source);
|
||||
// For as long as that card remains exiled, you may look at it
|
||||
effect = new MayLookAtTargetCardEffect(controller.getId());
|
||||
effect.setTargetPointer(new FixedTarget(card.getId(), game));
|
||||
game.addEffect(effect, source);
|
||||
}
|
||||
}
|
||||
}
|
||||
// put the rest into their graveyard
|
||||
if (controller == null || damagedPlayer == null || sourceObject == null) {
|
||||
return false;
|
||||
}
|
||||
Cards topCards = new CardsImpl();
|
||||
topCards.addAllCards(damagedPlayer.getLibrary().getTopCards(game, 3));
|
||||
TargetCard target = new TargetCard(Zone.LIBRARY, new FilterCard("card to exile face down"));
|
||||
controller.choose(outcome, topCards, target, source, game);
|
||||
Card card = game.getCard(target.getFirstTarget());
|
||||
if (card == null) {
|
||||
controller.moveCards(topCards, Zone.GRAVEYARD, source, game);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class ThiefOfSanityCastFromExileEffect extends AsThoughEffectImpl {
|
||||
|
||||
private final UUID authorizedPlayerId;
|
||||
|
||||
public ThiefOfSanityCastFromExileEffect(UUID authorizedPlayerId) {
|
||||
super(AsThoughEffectType.CAST_FROM_NOT_OWN_HAND_ZONE, Duration.Custom, Outcome.Benefit);
|
||||
this.authorizedPlayerId = authorizedPlayerId;
|
||||
staticText = "For as long as that card remains exiled, you may cast it";
|
||||
}
|
||||
|
||||
private ThiefOfSanityCastFromExileEffect(final ThiefOfSanityCastFromExileEffect effect) {
|
||||
super(effect);
|
||||
this.authorizedPlayerId = effect.authorizedPlayerId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
new ExileFaceDownYouMayPlayAsLongAsExiledTargetEffect(true, CastManaAdjustment.AS_THOUGH_ANY_MANA_TYPE)
|
||||
.setTargetPointer(new FixedTarget(card, game))
|
||||
.apply(game, source);
|
||||
topCards.retainZone(Zone.LIBRARY, game);
|
||||
// put the rest into their graveyard
|
||||
controller.moveCards(topCards, Zone.GRAVEYARD, source, game);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ThiefOfSanityCastFromExileEffect copy() {
|
||||
return new ThiefOfSanityCastFromExileEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
|
||||
UUID cardId = getTargetPointer().getFirst(game, source);
|
||||
if (cardId == null) {
|
||||
this.discard(); // card is no longer in the origin zone, effect can be discarded
|
||||
return false;
|
||||
}
|
||||
Card theCard = game.getCard(objectId);
|
||||
if (theCard == null || theCard.isLand(game)) {
|
||||
return false;
|
||||
}
|
||||
objectId = theCard.getMainCard().getId(); // for split cards
|
||||
|
||||
if (objectId.equals(cardId)
|
||||
&& affectedControllerId.equals(authorizedPlayerId)) {
|
||||
Card card = game.getCard(objectId);
|
||||
// TODO: Allow to cast Zoetic Cavern face down
|
||||
return card != null;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class ThiefOfSanitySpendAnyManaEffect extends AsThoughEffectImpl implements AsThoughManaEffect {
|
||||
|
||||
private final UUID authorizedPlayerId;
|
||||
|
||||
public ThiefOfSanitySpendAnyManaEffect(UUID authorizedPlayerId) {
|
||||
super(AsThoughEffectType.SPEND_OTHER_MANA, Duration.Custom, Outcome.Benefit);
|
||||
this.authorizedPlayerId = authorizedPlayerId;
|
||||
staticText = "For as long as that card remains exiled, you may spend mana as though it were mana of any color to cast it";
|
||||
}
|
||||
|
||||
private ThiefOfSanitySpendAnyManaEffect(final ThiefOfSanitySpendAnyManaEffect effect) {
|
||||
super(effect);
|
||||
this.authorizedPlayerId = effect.authorizedPlayerId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ThiefOfSanitySpendAnyManaEffect copy() {
|
||||
return new ThiefOfSanitySpendAnyManaEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
|
||||
objectId = CardUtil.getMainCardId(game, objectId); // for split cards
|
||||
if (objectId.equals(((FixedTarget) getTargetPointer()).getTarget())
|
||||
&& game.getState().getZoneChangeCounter(objectId) <= ((FixedTarget) getTargetPointer()).getZoneChangeCounter() + 1) {
|
||||
// if the card moved from exile to spell the zone change counter is increased by 1 (effect must applies before and on stack, use isCheckPlayableMode?)
|
||||
return affectedControllerId.equals(authorizedPlayerId);
|
||||
} else if (((FixedTarget) getTargetPointer()).getTarget().equals(objectId)) {
|
||||
// object has moved zone so effect can be discarded
|
||||
this.discard();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ManaType getAsThoughManaType(ManaType manaType, ManaPoolItem mana, UUID affectedControllerId, Ability source, Game game) {
|
||||
return mana.getFirstAvailable();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -95,6 +95,7 @@ public final class OutlawsOfThunderJunctionCommander extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Dire Fleet Ravager", 132, Rarity.MYTHIC, mage.cards.d.DireFleetRavager.class));
|
||||
cards.add(new SetCardInfo("Discreet Retreat", 20, Rarity.RARE, mage.cards.d.DiscreetRetreat.class));
|
||||
cards.add(new SetCardInfo("Dragonskull Summit", 289, Rarity.RARE, mage.cards.d.DragonskullSummit.class));
|
||||
cards.add(new SetCardInfo("Dream-Thief's Bandana", 38, Rarity.RARE, mage.cards.d.DreamThiefsBandana.class));
|
||||
cards.add(new SetCardInfo("Drowned Catacomb", 290, Rarity.RARE, mage.cards.d.DrownedCatacomb.class));
|
||||
cards.add(new SetCardInfo("Dune Chanter", 31, Rarity.RARE, mage.cards.d.DuneChanter.class));
|
||||
cards.add(new SetCardInfo("Dunes of the Dead", 291, Rarity.UNCOMMON, mage.cards.d.DunesOfTheDead.class));
|
||||
|
|
@ -130,6 +131,7 @@ public final class OutlawsOfThunderJunctionCommander extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Ghostly Pilferer", 98, Rarity.RARE, mage.cards.g.GhostlyPilferer.class));
|
||||
cards.add(new SetCardInfo("Glittering Stockpile", 167, Rarity.UNCOMMON, mage.cards.g.GlitteringStockpile.class));
|
||||
cards.add(new SetCardInfo("Goblin Electromancer", 228, Rarity.COMMON, mage.cards.g.GoblinElectromancer.class));
|
||||
cards.add(new SetCardInfo("Gonti, Canny Acquisitor", 1, Rarity.MYTHIC, mage.cards.g.GontiCannyAcquisitor.class));
|
||||
cards.add(new SetCardInfo("Gonti, Lord of Luxury", 135, Rarity.RARE, mage.cards.g.GontiLordOfLuxury.class));
|
||||
cards.add(new SetCardInfo("Graywater's Fixer", 36, Rarity.RARE, mage.cards.g.GraywatersFixer.class));
|
||||
cards.add(new SetCardInfo("Grenzo, Havoc Raiser", 168, Rarity.RARE, mage.cards.g.GrenzoHavocRaiser.class));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
package org.mage.test.cards.single.otc;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
* @author Susucr
|
||||
*/
|
||||
public class GontiCannyAcquisitorTest extends CardTestPlayerBase {
|
||||
|
||||
/**
|
||||
* {@link mage.cards.g.GontiCannyAcquisitor Gonti, Canny Acquisitor} {2}{B}{G}{U}
|
||||
* Legendary Creature — Aetherborn Rogue
|
||||
* Spells you cast but don’t own cost {1} less to cast.
|
||||
* Whenever one or more creatures you control deal combat damage to a player, look at the top card of that player’s library, then exile it face down. You may play that card for as long as it remains exiled, and mana of any type can be spent to cast that spell.
|
||||
* 5/5
|
||||
*/
|
||||
private static final String gonti = "Gonti, Canny Acquisitor";
|
||||
|
||||
@Test
|
||||
public void test_Simple() {
|
||||
setStrictChooseMode(true);
|
||||
skipInitShuffling();
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, gonti);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain");
|
||||
addCard(Zone.LIBRARY, playerB, "Grizzly Bears", 1); // {1}{G}
|
||||
|
||||
attack(1, playerA, gonti, playerB);
|
||||
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Grizzly Bears");
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerA, "Grizzly Bears", 1);
|
||||
assertTapped("Mountain", true);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
package org.mage.test.cards.single.woc;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
* @author Susucr
|
||||
*/
|
||||
public class BlightwingBanditTest extends CardTestPlayerBase {
|
||||
|
||||
/**
|
||||
* {@link mage.cards.b.BlightwingBandit Blightwing Bandit} {3}{B}
|
||||
* Creature — Faerie Rogue
|
||||
* Flying, deathtouch
|
||||
* Whenever you cast your first spell during each opponent’s turn, look at the top card of that player’s library, then exile it face down. You may play that card for as long as it remains exiled, and mana of any type can be spent to cast it.
|
||||
* 2/2
|
||||
*/
|
||||
private static final String bandit = "Blightwing Bandit";
|
||||
|
||||
@Test
|
||||
public void test_Simple() {
|
||||
setStrictChooseMode(true);
|
||||
skipInitShuffling();
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, bandit);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
|
||||
addCard(Zone.HAND, playerA, "Lightning Bolt");
|
||||
addCard(Zone.LIBRARY, playerB, "Fire // Ice", 1); // split card just to check it works on both faces
|
||||
|
||||
castSpell(2, PhaseStep.UPKEEP, playerA, "Lightning Bolt", playerB);
|
||||
waitStackResolved(2, PhaseStep.UPKEEP); // resolve trigger from bandit
|
||||
checkPlayableAbility("can cast fire", 2, PhaseStep.UPKEEP, playerA, "Cast Fire", true);
|
||||
checkPlayableAbility("can cast ice", 2, PhaseStep.UPKEEP, playerA, "Cast Ice", true);
|
||||
castSpell(2, PhaseStep.UPKEEP, playerA, "Ice", bandit);
|
||||
|
||||
setStopAt(2, PhaseStep.DRAW);
|
||||
execute();
|
||||
|
||||
assertGraveyardCount(playerB, "Fire // Ice", 1);
|
||||
assertTappedCount("Mountain", true, 3);
|
||||
assertHandCount(playerA, 1); // draw from Ice
|
||||
assertTapped(bandit, true); // tapped from Ice
|
||||
assertLife(playerB, 20 - 3);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
package org.mage.test.cards.single.woe;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
* @author Susucr
|
||||
*/
|
||||
public class DecadentDragonTest extends CardTestPlayerBase {
|
||||
|
||||
/**
|
||||
* {@link mage.cards.d.DecadentDragon Decadent Dragon} {2}{R}{R}
|
||||
* Creature — Dragon
|
||||
* Flying, trample
|
||||
* Whenever Decadent Dragon attacks, create a Treasure token.
|
||||
* 4/4
|
||||
* Expensive Taste {2}{B}
|
||||
* Instant — Adventure
|
||||
* Exile the top two cards of target opponent’s library face down. You may look at and play those cards for as long as they remain exiled.
|
||||
*/
|
||||
private static final String dragon = "Decadent Dragon";
|
||||
|
||||
@Test
|
||||
public void test_MDFC_And_Split() {
|
||||
setStrictChooseMode(true);
|
||||
skipInitShuffling();
|
||||
|
||||
addCard(Zone.HAND, playerA, dragon);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3 + 4);
|
||||
addCard(Zone.LIBRARY, playerB, "Pain // Suffering", 1); // can cast Pain, but Suffering cost {3}{R} so can't be cast
|
||||
addCard(Zone.LIBRARY, playerB, "Blackbloom Rogue", 1); // mdfc {2}{B} with land Blackbloom Bog on the back.
|
||||
addCard(Zone.HAND, playerB, "Abandon Hope"); // to discard to Pain
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Expensive Taste", playerB);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA);
|
||||
|
||||
checkPlayableAbility("can cast Pain", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Pain", true);
|
||||
checkPlayableAbility("can not cast Suffering", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Suffering", false);
|
||||
checkPlayableAbility("can cast Blackbloom Rogue", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Blackbloom Rogue", true);
|
||||
checkPlayableAbility("can play Blackbloom Bog", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Play Blackbloom Bog", true);
|
||||
|
||||
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Blackbloom Bog");
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Pain", playerB);
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertGraveyardCount(playerB, "Pain // Suffering", 1);
|
||||
assertGraveyardCount(playerB, "Abandon Hope", 1);
|
||||
assertTappedCount("Blackbloom Bog", true, 1);
|
||||
assertTappedCount("Swamp", true, 4);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
package mage.abilities.effects.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.dynamicvalue.common.StaticValue;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.Cards;
|
||||
import mage.cards.CardsImpl;
|
||||
import mage.constants.CastManaAdjustment;
|
||||
import mage.constants.Outcome;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.targetpointer.FixedTargets;
|
||||
|
||||
/**
|
||||
* This exiles the target players' top N cards of library.
|
||||
* Each card can be looked at by the source's controller.
|
||||
* For each card exiled this way, that player may play|cast that card as long as it stays exiled. (+ mana adjustement)
|
||||
* e.g. [[Gonti, Canny Acquisitor]]
|
||||
*
|
||||
* @author Susucr
|
||||
*/
|
||||
public class ExileFaceDownTopNLibraryYouMayPlayAsLongAsExiledTargetEffect extends OneShotEffect {
|
||||
|
||||
private final boolean useCastSpellOnly;
|
||||
private final CastManaAdjustment manaAdjustment;
|
||||
private final DynamicValue value;
|
||||
|
||||
public ExileFaceDownTopNLibraryYouMayPlayAsLongAsExiledTargetEffect(boolean useCastSpellOnly, CastManaAdjustment manaAdjustment) {
|
||||
this(useCastSpellOnly, manaAdjustment, 1);
|
||||
}
|
||||
|
||||
public ExileFaceDownTopNLibraryYouMayPlayAsLongAsExiledTargetEffect(boolean useCastSpellOnly, CastManaAdjustment manaAdjustment, int amount) {
|
||||
this(useCastSpellOnly, manaAdjustment, StaticValue.get(amount));
|
||||
}
|
||||
|
||||
public ExileFaceDownTopNLibraryYouMayPlayAsLongAsExiledTargetEffect(boolean useCastSpellOnly, CastManaAdjustment manaAdjustment, DynamicValue value) {
|
||||
super(Outcome.Exile);
|
||||
this.value = value;
|
||||
this.useCastSpellOnly = useCastSpellOnly;
|
||||
this.manaAdjustment = manaAdjustment;
|
||||
}
|
||||
|
||||
private ExileFaceDownTopNLibraryYouMayPlayAsLongAsExiledTargetEffect(final ExileFaceDownTopNLibraryYouMayPlayAsLongAsExiledTargetEffect effect) {
|
||||
super(effect);
|
||||
this.value = effect.value;
|
||||
this.useCastSpellOnly = effect.useCastSpellOnly;
|
||||
this.manaAdjustment = effect.manaAdjustment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExileFaceDownTopNLibraryYouMayPlayAsLongAsExiledTargetEffect copy() {
|
||||
return new ExileFaceDownTopNLibraryYouMayPlayAsLongAsExiledTargetEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(getTargetPointer().getFirst(game, source));
|
||||
if (player == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int amount = value.calculate(game, source, this);
|
||||
Cards cards = new CardsImpl(player.getLibrary().getTopCards(game, amount));
|
||||
if (cards.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return new ExileFaceDownYouMayPlayAsLongAsExiledTargetEffect(useCastSpellOnly, manaAdjustment)
|
||||
.setTargetPointer(new FixedTargets(cards, game))
|
||||
.apply(game, source);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,7 +1,9 @@
|
|||
package mage.abilities.effects;
|
||||
package mage.abilities.effects.common;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.ContinuousEffect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.asthought.MayLookAtTargetCardEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.Cards;
|
||||
Loading…
Add table
Add a link
Reference in a new issue