forked from External/mage
Merge pull request 'master' (#19) from External/mage:master into master
All checks were successful
/ example-docker-compose (push) Successful in 15m4s
All checks were successful
/ example-docker-compose (push) Successful in 15m4s
Reviewed-on: #19
This commit is contained in:
commit
d1ca46fd85
111 changed files with 3335 additions and 976 deletions
|
|
@ -152,7 +152,7 @@ public class AbilityPicker extends JXPanel implements MouseWheelListener {
|
||||||
setBackgroundPainter(mwPanelPainter);
|
setBackgroundPainter(mwPanelPainter);
|
||||||
|
|
||||||
title = new ColorPane();
|
title = new ColorPane();
|
||||||
title.setFont(new Font("Times New Roman", 1, sizeMod(15)));
|
title.setFont(new Font("Times New Roman", Font.BOLD, sizeMod(15)));
|
||||||
title.setEditable(false);
|
title.setEditable(false);
|
||||||
title.setFocusCycleRoot(false);
|
title.setFocusCycleRoot(false);
|
||||||
title.setOpaque(false);
|
title.setOpaque(false);
|
||||||
|
|
@ -186,11 +186,12 @@ public class AbilityPicker extends JXPanel implements MouseWheelListener {
|
||||||
rows.addMouseListener(new MouseAdapter() {
|
rows.addMouseListener(new MouseAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void mousePressed(MouseEvent evt) {
|
public void mousePressed(MouseEvent evt) {
|
||||||
if (SwingUtilities.isLeftMouseButton(evt)) {
|
if (SwingUtilities.isLeftMouseButton(evt) && !rows.isSelectionEmpty()) {
|
||||||
objectMouseClicked(evt);
|
objectMouseClicked(evt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
rows.setSelectedIndex(0);
|
rows.setSelectedIndex(0);
|
||||||
rows.setFont(new Font("Times New Roman", 1, sizeMod(17)));
|
rows.setFont(new Font("Times New Roman", 1, sizeMod(17)));
|
||||||
rows.setBorder(BorderFactory.createEmptyBorder());
|
rows.setBorder(BorderFactory.createEmptyBorder());
|
||||||
|
|
@ -233,18 +234,16 @@ public class AbilityPicker extends JXPanel implements MouseWheelListener {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseWheelMoved(MouseWheelEvent e) {
|
public void mouseWheelMoved(MouseWheelEvent e) {
|
||||||
int notches = e.getWheelRotation();
|
int direction = e.getWheelRotation() < 0 ? -1 : +1;
|
||||||
int index = rows.getSelectedIndex();
|
int index = rows.getSelectedIndex() + direction;
|
||||||
|
if (index < 0) {
|
||||||
if (notches < 0) {
|
index = 0;
|
||||||
if (index > 0) {
|
} else if (index >= choices.size()) {
|
||||||
rows.setSelectedIndex(index - 1);
|
index = choices.size() - 1;
|
||||||
rows.repaint();
|
|
||||||
}
|
|
||||||
} else if (index < choices.size() - 1) {
|
|
||||||
rows.setSelectedIndex(index + 1);
|
|
||||||
rows.repaint();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rows.setSelectedIndex(index);
|
||||||
|
rows.repaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void objectMouseClicked(MouseEvent event) {
|
private void objectMouseClicked(MouseEvent event) {
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ public class DialogContainer extends JPanel {
|
||||||
case EMBLEMS: {
|
case EMBLEMS: {
|
||||||
backgroundColor = new Color(0, 0, 50, 110);
|
backgroundColor = new Color(0, 0, 50, 110);
|
||||||
alpha = 0;
|
alpha = 0;
|
||||||
ChoiceDialog dlg = new ChoiceDialog(params, "Command Zone (Commander, Emblems and Planes)");
|
ChoiceDialog dlg = new ChoiceDialog(params, "Command Zone (Commanders, Emblems, and Planes)");
|
||||||
add(dlg);
|
add(dlg);
|
||||||
dlg.setLocation(X_OFFSET + 10, Y_OFFSET + 10);
|
dlg.setLocation(X_OFFSET + 10, Y_OFFSET + 10);
|
||||||
dlg.updateSize(params.rect.width - 80, params.rect.height - 80);
|
dlg.updateSize(params.rect.width - 80, params.rect.height - 80);
|
||||||
|
|
|
||||||
|
|
@ -687,11 +687,11 @@ public class PlayerPanelExt extends javax.swing.JPanel {
|
||||||
zonesPanel.setLayout(null);
|
zonesPanel.setLayout(null);
|
||||||
zonesPanel.setOpaque(false);
|
zonesPanel.setOpaque(false);
|
||||||
|
|
||||||
// tools button like hints
|
// hints
|
||||||
toolHintsHelper = new JButton();
|
toolHintsHelper = new JButton();
|
||||||
toolHintsHelper.setFont(this.getFont());
|
toolHintsHelper.setFont(this.getFont());
|
||||||
toolHintsHelper.setText("hints");
|
toolHintsHelper.setText("Hints");
|
||||||
toolHintsHelper.setToolTipText("Open new card hints helper window");
|
toolHintsHelper.setToolTipText("Open card hints helper window");
|
||||||
toolHintsHelper.addActionListener(this::btnToolHintsHelperActionPerformed);
|
toolHintsHelper.addActionListener(this::btnToolHintsHelperActionPerformed);
|
||||||
toolHintsHelper.setBounds(sizeMod(3), sizeMod(2 + 21 + 2), sizeMod(73), sizeMod(21));
|
toolHintsHelper.setBounds(sizeMod(3), sizeMod(2 + 21 + 2), sizeMod(73), sizeMod(21));
|
||||||
zonesPanel.add(toolHintsHelper);
|
zonesPanel.add(toolHintsHelper);
|
||||||
|
|
@ -701,7 +701,7 @@ public class PlayerPanelExt extends javax.swing.JPanel {
|
||||||
image = ImageHelper.getImageFromResources("/info/command_zone.png");
|
image = ImageHelper.getImageFromResources("/info/command_zone.png");
|
||||||
resized = ImageHelper.getResizedImage(BufferedImageBuilder.bufferImage(image, BufferedImage.TYPE_INT_ARGB), r);
|
resized = ImageHelper.getResizedImage(BufferedImageBuilder.bufferImage(image, BufferedImage.TYPE_INT_ARGB), r);
|
||||||
commandZone = new HoverButton(null, resized, resized, resized, r, this.guiScaleMod);
|
commandZone = new HoverButton(null, resized, resized, resized, r, this.guiScaleMod);
|
||||||
commandZone.setToolTipText("Command Zone (Commanders, Emblems and Planes)");
|
commandZone.setToolTipText("Command Zone (Commanders, Emblems, and Planes)");
|
||||||
commandZone.setOpaque(false);
|
commandZone.setOpaque(false);
|
||||||
commandZone.setObserver(() -> btnCommandZoneActionPerformed(null));
|
commandZone.setObserver(() -> btnCommandZoneActionPerformed(null));
|
||||||
commandZone.setBounds(sizeMod(3), 0, sizeMod(21), sizeMod(21));
|
commandZone.setBounds(sizeMod(3), 0, sizeMod(21), sizeMod(21));
|
||||||
|
|
|
||||||
|
|
@ -579,6 +579,10 @@ public class ScryfallImageSupportCards {
|
||||||
add("INR"); // Innistrad Remastered
|
add("INR"); // Innistrad Remastered
|
||||||
add("DFT"); // Aetherdrift
|
add("DFT"); // Aetherdrift
|
||||||
add("DRC"); // Aetherdrift Commander
|
add("DRC"); // Aetherdrift Commander
|
||||||
|
add("TDM"); // Tarkir: Dragonstorm
|
||||||
|
add("TDC"); // Tarkir: Dragonstorm Commander
|
||||||
|
add("FIN"); // Final Fantasy
|
||||||
|
add("FIC"); // Final Fantasy Commander
|
||||||
|
|
||||||
// Custom sets using Scryfall images - must provide a direct link for each card in directDownloadLinks
|
// Custom sets using Scryfall images - must provide a direct link for each card in directDownloadLinks
|
||||||
add("CALC"); // Custom Alchemized versions of existing cards
|
add("CALC"); // Custom Alchemized versions of existing cards
|
||||||
|
|
|
||||||
|
|
@ -2169,6 +2169,8 @@ public class ScryfallImageSupportTokens {
|
||||||
|
|
||||||
// WHO
|
// WHO
|
||||||
put("WHO/Alien Insect", "https://api.scryfall.com/cards/twho/19/en?format=image");
|
put("WHO/Alien Insect", "https://api.scryfall.com/cards/twho/19/en?format=image");
|
||||||
|
put("WHO/Human Noble", "https://api.scryfall.com/cards/twho/7/en?format=image");
|
||||||
|
put("WHO/Horse", "https://api.scryfall.com/cards/twho/4/en?format=image");
|
||||||
|
|
||||||
// 8ED
|
// 8ED
|
||||||
put("8ED/Rukh", "https://api.scryfall.com/cards/p03/7/en?format=image");
|
put("8ED/Rukh", "https://api.scryfall.com/cards/p03/7/en?format=image");
|
||||||
|
|
|
||||||
|
|
@ -64,10 +64,10 @@ public class MageTable extends JTable {
|
||||||
// html tooltip
|
// html tooltip
|
||||||
java.awt.Point p = e.getPoint();
|
java.awt.Point p = e.getPoint();
|
||||||
int colIndex = columnModel.getColumnIndexAtX(p.x);
|
int colIndex = columnModel.getColumnIndexAtX(p.x);
|
||||||
TableColumn col = columnModel.getColumn(colIndex);
|
|
||||||
if (colIndex < 0) {
|
if (colIndex < 0) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
TableColumn col = columnModel.getColumn(colIndex);
|
||||||
int realIndex = col.getModelIndex();
|
int realIndex = col.getModelIndex();
|
||||||
|
|
||||||
String tip;
|
String tip;
|
||||||
|
|
|
||||||
|
|
@ -2951,7 +2951,7 @@ public class HumanPlayer extends PlayerImpl {
|
||||||
protected boolean passWithManaPoolCheck(Game game) {
|
protected boolean passWithManaPoolCheck(Game game) {
|
||||||
if (userData.confirmEmptyManaPool()
|
if (userData.confirmEmptyManaPool()
|
||||||
&& game.getStack().isEmpty() && getManaPool().count() > 0 && getManaPool().canLostManaOnEmpty()) {
|
&& game.getStack().isEmpty() && getManaPool().count() > 0 && getManaPool().canLostManaOnEmpty()) {
|
||||||
String message = GameLog.getPlayerConfirmColoredText("You still have mana in your mana pool and it will be lose. Pass anyway?");
|
String message = GameLog.getPlayerConfirmColoredText("You still have mana in your mana pool and it will be lost. Pass anyway?");
|
||||||
if (!chooseUse(Outcome.Detriment, message, null, game)) {
|
if (!chooseUse(Outcome.Detriment, message, null, game)) {
|
||||||
sendPlayerAction(PlayerAction.PASS_PRIORITY_CANCEL_ALL_ACTIONS, game, null);
|
sendPlayerAction(PlayerAction.PASS_PRIORITY_CANCEL_ALL_ACTIONS, game, null);
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -591,7 +591,7 @@ public class GameController implements GameCallback {
|
||||||
if (playerId != null) {
|
if (playerId != null) {
|
||||||
Player player = game.getPlayer(playerId);
|
Player player = game.getPlayer(playerId);
|
||||||
if (player != null) {
|
if (player != null) {
|
||||||
game.informPlayers(player.getLogName() + " want to concede");
|
game.informPlayers(player.getLogName() + " wants to concede");
|
||||||
game.setConcedingPlayer(getPlayerId(userId));
|
game.setConcedingPlayer(getPlayerId(userId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
118
Mage.Sets/src/mage/cards/a/AlacrianArmory.java
Normal file
118
Mage.Sets/src/mage/cards/a/AlacrianArmory.java
Normal file
|
|
@ -0,0 +1,118 @@
|
||||||
|
package mage.cards.a;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.common.CrewSaddleIncreasedPowerAbility;
|
||||||
|
import mage.abilities.common.SimpleStaticAbility;
|
||||||
|
import mage.abilities.effects.Effect;
|
||||||
|
import mage.abilities.effects.OneShotEffect;
|
||||||
|
import mage.abilities.effects.common.EndTurnEffect;
|
||||||
|
import mage.abilities.effects.common.continuous.AddCardTypeTargetEffect;
|
||||||
|
import mage.abilities.effects.common.continuous.BoostControlledEffect;
|
||||||
|
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
|
||||||
|
import mage.abilities.keyword.CrewAbility;
|
||||||
|
import mage.abilities.keyword.SaddleAbility;
|
||||||
|
import mage.abilities.keyword.VigilanceAbility;
|
||||||
|
import mage.abilities.triggers.BeginningOfCombatTriggeredAbility;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.Duration;
|
||||||
|
import mage.constants.Outcome;
|
||||||
|
import mage.constants.SubType;
|
||||||
|
import mage.constants.TargetController;
|
||||||
|
import mage.filter.FilterPermanent;
|
||||||
|
import mage.filter.common.FilterCreaturePermanent;
|
||||||
|
import mage.filter.predicate.Predicates;
|
||||||
|
import mage.filter.predicate.permanent.SaddledSourceThisTurnPredicate;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.game.events.GameEvent;
|
||||||
|
import mage.game.permanent.Permanent;
|
||||||
|
import mage.target.TargetPermanent;
|
||||||
|
import mage.target.targetpointer.FixedTarget;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Jmlundeen
|
||||||
|
*/
|
||||||
|
public final class AlacrianArmory extends CardImpl {
|
||||||
|
|
||||||
|
private static final FilterCreaturePermanent creatureFilter = new FilterCreaturePermanent("Creatures you control");
|
||||||
|
private static final FilterPermanent mountOrVehicleFilter = new FilterPermanent("Mount or Vehicle you control");
|
||||||
|
|
||||||
|
static {
|
||||||
|
mountOrVehicleFilter.add(Predicates.or(
|
||||||
|
SubType.MOUNT.getPredicate(),
|
||||||
|
SubType.VEHICLE.getPredicate()
|
||||||
|
));
|
||||||
|
mountOrVehicleFilter.add(TargetController.YOU.getControllerPredicate());
|
||||||
|
}
|
||||||
|
public AlacrianArmory(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}{W}");
|
||||||
|
|
||||||
|
// Creatures you control get +0/+1 and have vigilance.
|
||||||
|
Ability staticAbility = new SimpleStaticAbility(new BoostControlledEffect(0, 1, Duration.WhileOnBattlefield, creatureFilter));
|
||||||
|
Effect effect = new GainAbilityControlledEffect(VigilanceAbility.getInstance(), Duration.WhileOnBattlefield, creatureFilter);
|
||||||
|
effect.setText("and have vigilance");
|
||||||
|
staticAbility.addEffect(effect);
|
||||||
|
this.addAbility(staticAbility);
|
||||||
|
// At the beginning of combat on your turn, choose up to one target Mount or Vehicle you control. Until end of turn, that permanent becomes saddled if it's a Mount and becomes an artifact creature if it's a Vehicle.
|
||||||
|
Ability animateAbility = new BeginningOfCombatTriggeredAbility(
|
||||||
|
new AlacrianArmoryAnimateEffect()
|
||||||
|
);
|
||||||
|
animateAbility.addTarget(new TargetPermanent(0, 1, mountOrVehicleFilter));
|
||||||
|
this.addAbility(animateAbility);
|
||||||
|
}
|
||||||
|
|
||||||
|
private AlacrianArmory(final AlacrianArmory card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AlacrianArmory copy() {
|
||||||
|
return new AlacrianArmory(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class AlacrianArmoryAnimateEffect extends OneShotEffect {
|
||||||
|
|
||||||
|
AlacrianArmoryAnimateEffect() {
|
||||||
|
super(Outcome.Benefit);
|
||||||
|
staticText = "choose up to one target Mount or Vehicle you control. " +
|
||||||
|
"Until end of turn, that permanent becomes saddled if it's a Mount " +
|
||||||
|
"and becomes an artifact creature if it's a Vehicle";
|
||||||
|
}
|
||||||
|
|
||||||
|
private AlacrianArmoryAnimateEffect(final AlacrianArmoryAnimateEffect effect) {
|
||||||
|
super(effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AlacrianArmoryAnimateEffect copy() {
|
||||||
|
return new AlacrianArmoryAnimateEffect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source) {
|
||||||
|
Permanent target = game.getPermanent(source.getFirstTarget());
|
||||||
|
if (target == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (target.hasSubtype(SubType.MOUNT, game)) {
|
||||||
|
target.getAbilities().stream().filter(
|
||||||
|
ability -> ability instanceof SaddleAbility)
|
||||||
|
.findFirst()
|
||||||
|
.ifPresent(ability -> game.fireEvent(GameEvent.getEvent(
|
||||||
|
GameEvent.EventType.MOUNT_SADDLED,
|
||||||
|
ability.getSourceId(),
|
||||||
|
ability, source.getControllerId()))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (target.hasSubtype(SubType.VEHICLE, game)) {
|
||||||
|
game.addEffect(new AddCardTypeTargetEffect(Duration.EndOfTurn, CardType.CREATURE, CardType.ARTIFACT)
|
||||||
|
.setTargetPointer(new FixedTarget(target, game)), source);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
97
Mage.Sets/src/mage/cards/a/AlexiosDeimosOfKosmos.java
Normal file
97
Mage.Sets/src/mage/cards/a/AlexiosDeimosOfKosmos.java
Normal file
|
|
@ -0,0 +1,97 @@
|
||||||
|
package mage.cards.a;
|
||||||
|
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.common.AttacksEachCombatStaticAbility;
|
||||||
|
import mage.abilities.effects.*;
|
||||||
|
import mage.abilities.effects.common.TargetPlayerGainControlSourceEffect;
|
||||||
|
import mage.abilities.effects.common.UntapSourceEffect;
|
||||||
|
import mage.abilities.effects.common.continuous.CantBeSacrificedSourceEffect;
|
||||||
|
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
|
||||||
|
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
||||||
|
import mage.abilities.keyword.HasteAbility;
|
||||||
|
import mage.abilities.keyword.TrampleAbility;
|
||||||
|
import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.*;
|
||||||
|
import mage.counters.CounterType;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.game.permanent.Permanent;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class AlexiosDeimosOfKosmos extends CardImpl {
|
||||||
|
public AlexiosDeimosOfKosmos(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}");
|
||||||
|
this.supertype.add(SuperType.LEGENDARY);
|
||||||
|
this.subtype.add(SubType.HUMAN);
|
||||||
|
this.subtype.add(SubType.BERSERKER);
|
||||||
|
|
||||||
|
this.power = new MageInt(4);
|
||||||
|
this.toughness = new MageInt(4);
|
||||||
|
|
||||||
|
// Trample
|
||||||
|
this.addAbility(TrampleAbility.getInstance());
|
||||||
|
|
||||||
|
// attacks each combat if able, can't be sacrificed, and can't attack it's owner
|
||||||
|
Ability ability = new AttacksEachCombatStaticAbility();
|
||||||
|
ability.addEffect(new CantBeSacrificedSourceEffect().setText(", can't be sacrificed"));
|
||||||
|
ability.addEffect(new AlexiosDeimosOfKosmosRestrictionEffect());
|
||||||
|
this.addAbility(ability);
|
||||||
|
|
||||||
|
// at the beginning of each player's upkeep, that player gains control of alexios, untaps it, and puts a +1/+1 counter on it. it gains haste until end of turn
|
||||||
|
Ability upkeepAbility = new BeginningOfUpkeepTriggeredAbility(TargetController.EACH_PLAYER, null, false);
|
||||||
|
upkeepAbility.addEffect(new TargetPlayerGainControlSourceEffect().setText("that player gains control of Alexios"));
|
||||||
|
upkeepAbility.addEffect(new UntapSourceEffect().setText(", untaps it"));
|
||||||
|
upkeepAbility.addEffect(new AddCountersSourceEffect(CounterType.P1P1.createInstance(1)).setText(", and puts a +1/+1 counter on it"));
|
||||||
|
upkeepAbility.addEffect(new GainAbilitySourceEffect(HasteAbility.getInstance(), Duration.EndOfTurn).setText("it gains haste until end of turn"));
|
||||||
|
this.addAbility(upkeepAbility);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AlexiosDeimosOfKosmos(CardImpl card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AlexiosDeimosOfKosmos copy() {
|
||||||
|
return new AlexiosDeimosOfKosmos(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
class AlexiosDeimosOfKosmosRestrictionEffect extends RestrictionEffect {
|
||||||
|
public AlexiosDeimosOfKosmosRestrictionEffect() {
|
||||||
|
super(Duration.WhileOnBattlefield);
|
||||||
|
this.staticText = ", and can't attack it's owner";
|
||||||
|
}
|
||||||
|
|
||||||
|
public AlexiosDeimosOfKosmosRestrictionEffect(RestrictionEffect effect) {
|
||||||
|
super(effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean applies(Permanent permanent, Ability source, Game game) {
|
||||||
|
return Objects.equals(permanent.getId(), source.getSourceId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AlexiosDeimosOfKosmosRestrictionEffect copy() {
|
||||||
|
return new AlexiosDeimosOfKosmosRestrictionEffect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canAttack(Permanent attacker, UUID defenderId, Ability source, Game game, boolean canUseChooseDialogs) {
|
||||||
|
if (defenderId == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Permanent permanent = source.getSourcePermanentIfItStillExists(game);
|
||||||
|
if (permanent == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
UUID ownerId = permanent.getOwnerId();
|
||||||
|
return !defenderId.equals(ownerId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
60
Mage.Sets/src/mage/cards/a/AncientVendetta.java
Normal file
60
Mage.Sets/src/mage/cards/a/AncientVendetta.java
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
package mage.cards.a;
|
||||||
|
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.effects.common.ChooseACardNameEffect;
|
||||||
|
import mage.abilities.effects.common.search.SearchTargetGraveyardHandLibraryForCardNameAndExileEffect;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.target.common.TargetOpponent;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author jam736
|
||||||
|
*/
|
||||||
|
public final class AncientVendetta extends CardImpl {
|
||||||
|
|
||||||
|
public AncientVendetta(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{B}");
|
||||||
|
|
||||||
|
// Choose a card name. Search target opponent’s graveyard, hand, and library for up to four cards with that name and exile them. Then that player shuffles.
|
||||||
|
this.getSpellAbility().addEffect((new ChooseACardNameEffect(ChooseACardNameEffect.TypeOfName.ALL)));
|
||||||
|
this.getSpellAbility().addEffect(new AncientVendettaEffect());
|
||||||
|
this.getSpellAbility().addTarget(new TargetOpponent());
|
||||||
|
}
|
||||||
|
|
||||||
|
private AncientVendetta(final AncientVendetta card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AncientVendetta copy() {
|
||||||
|
return new AncientVendetta(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class AncientVendettaEffect extends SearchTargetGraveyardHandLibraryForCardNameAndExileEffect {
|
||||||
|
|
||||||
|
AncientVendettaEffect() {
|
||||||
|
super(true, "target opponent's", "up to four cards with that name", false, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
private AncientVendettaEffect(final AncientVendettaEffect effect) {
|
||||||
|
super(effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AncientVendettaEffect copy() {
|
||||||
|
return new AncientVendettaEffect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source) {
|
||||||
|
String chosenCardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY);
|
||||||
|
return applySearchAndExile(game, source, chosenCardName, getTargetPointer().getFirst(game, source));
|
||||||
|
}
|
||||||
|
}
|
||||||
64
Mage.Sets/src/mage/cards/b/BarrensteppeSiege.java
Normal file
64
Mage.Sets/src/mage/cards/b/BarrensteppeSiege.java
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
package mage.cards.b;
|
||||||
|
|
||||||
|
import mage.abilities.common.EntersBattlefieldAbility;
|
||||||
|
import mage.abilities.condition.Condition;
|
||||||
|
import mage.abilities.condition.common.CreatureDiedControlledCondition;
|
||||||
|
import mage.abilities.condition.common.ModeChoiceSourceCondition;
|
||||||
|
import mage.abilities.decorator.ConditionalTriggeredAbility;
|
||||||
|
import mage.abilities.effects.common.ChooseModeEffect;
|
||||||
|
import mage.abilities.effects.common.SacrificeOpponentsEffect;
|
||||||
|
import mage.abilities.effects.common.counter.AddCountersAllEffect;
|
||||||
|
import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.counters.CounterType;
|
||||||
|
import mage.filter.StaticFilters;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public final class BarrensteppeSiege extends CardImpl {
|
||||||
|
|
||||||
|
private static final Condition condition1 = new ModeChoiceSourceCondition("Abzan");
|
||||||
|
private static final String rule1 = "&bull Abzan — At the beginning of your end step, " +
|
||||||
|
"put a +1/+1 counter on each creature you control.";
|
||||||
|
private static final Condition condition2 = new ModeChoiceSourceCondition("Mardu");
|
||||||
|
private static final String rule2 = "&bull Mardu — At the beginning of your end step, " +
|
||||||
|
"if a creature died under your control this turn, each opponent sacrifices a creature of their choice.";
|
||||||
|
|
||||||
|
public BarrensteppeSiege(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}{B}");
|
||||||
|
|
||||||
|
// As this enchantment enters, choose Abzan or Mardu.
|
||||||
|
this.addAbility(new EntersBattlefieldAbility(
|
||||||
|
new ChooseModeEffect("Abzan or Mardu?", "Abzan", "Mardu"),
|
||||||
|
null, "As {this} enters, choose Abzan or Mardu.", ""
|
||||||
|
));
|
||||||
|
|
||||||
|
// * Abzan -- At the beginning of your end step, put a +1/+1 counter on each creature you control.
|
||||||
|
this.addAbility(new ConditionalTriggeredAbility(
|
||||||
|
new BeginningOfEndStepTriggeredAbility(new AddCountersAllEffect(
|
||||||
|
CounterType.P1P1.createInstance(), StaticFilters.FILTER_CONTROLLED_CREATURE
|
||||||
|
)), condition1, rule1
|
||||||
|
));
|
||||||
|
|
||||||
|
// * Mardu -- At the beginning of your end step, if a creature died under your control this turn, each opponent sacrifices a creature of their choice.
|
||||||
|
this.addAbility(new ConditionalTriggeredAbility(
|
||||||
|
new BeginningOfEndStepTriggeredAbility(
|
||||||
|
new SacrificeOpponentsEffect(StaticFilters.FILTER_PERMANENT_CREATURE)
|
||||||
|
).withInterveningIf(CreatureDiedControlledCondition.instance), condition2, rule2
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
private BarrensteppeSiege(final BarrensteppeSiege card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BarrensteppeSiege copy() {
|
||||||
|
return new BarrensteppeSiege(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -61,7 +61,7 @@ public final class BaruWurmspeaker extends CardImpl {
|
||||||
).setText("and have trample"));
|
).setText("and have trample"));
|
||||||
this.addAbility(ability);
|
this.addAbility(ability);
|
||||||
|
|
||||||
// {7}{G}, {T}: Create a 4/4 green Wurm creature token. This ability costs {X} less to activate, whre X is the greatest power among Wurms you control.
|
// {7}{G}, {T}: Create a 4/4 green Wurm creature token. This ability costs {X} less to activate, where X is the greatest power among Wurms you control.
|
||||||
ability = new SimpleActivatedAbility(new CreateTokenEffect(new Wurm44Token()), new ManaCostsImpl<>("{7}{G}"));
|
ability = new SimpleActivatedAbility(new CreateTokenEffect(new Wurm44Token()), new ManaCostsImpl<>("{7}{G}"));
|
||||||
ability.addCost(new TapSourceCost());
|
ability.addCost(new TapSourceCost());
|
||||||
ability.addEffect(new InfoEffect("this ability costs {X} less to activate, " +
|
ability.addEffect(new InfoEffect("this ability costs {X} less to activate, " +
|
||||||
|
|
|
||||||
124
Mage.Sets/src/mage/cards/b/BillPotts.java
Normal file
124
Mage.Sets/src/mage/cards/b/BillPotts.java
Normal file
|
|
@ -0,0 +1,124 @@
|
||||||
|
package mage.cards.b;
|
||||||
|
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.MageItem;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.Abilities;
|
||||||
|
import mage.abilities.AbilitiesImpl;
|
||||||
|
import mage.abilities.Mode;
|
||||||
|
import mage.abilities.common.ActivateAbilityTriggeredAbility;
|
||||||
|
import mage.abilities.common.SpellCastControllerTriggeredAbility;
|
||||||
|
import mage.abilities.effects.common.CopyStackObjectEffect;
|
||||||
|
import mage.abilities.meta.OrTriggeredAbility;
|
||||||
|
import mage.constants.SubType;
|
||||||
|
import mage.constants.SuperType;
|
||||||
|
import mage.abilities.keyword.DoctorsCompanionAbility;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.SetTargetPointer;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import mage.filter.common.FilterInstantOrSorcerySpell;
|
||||||
|
import mage.filter.FilterSpell;
|
||||||
|
import mage.filter.FilterStackObject;
|
||||||
|
import mage.filter.predicate.ObjectSourcePlayer;
|
||||||
|
import mage.filter.predicate.ObjectSourcePlayerPredicate;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.game.stack.StackObject;
|
||||||
|
import mage.game.stack.Spell;
|
||||||
|
import mage.target.Target;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author padfoot
|
||||||
|
*/
|
||||||
|
public final class BillPotts extends CardImpl {
|
||||||
|
|
||||||
|
private static final FilterSpell filterInstantOrSorcery = new FilterInstantOrSorcerySpell("an instant or sorcery that targets only {this}");
|
||||||
|
private static final FilterStackObject filterAbility = new FilterStackObject("an ability that targets only {this}");
|
||||||
|
|
||||||
|
static {
|
||||||
|
filterInstantOrSorcery.add(BillPottsPredicate.instance);
|
||||||
|
filterAbility.add(BillPottsPredicate.instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BillPotts(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}");
|
||||||
|
|
||||||
|
this.supertype.add(SuperType.LEGENDARY);
|
||||||
|
this.subtype.add(SubType.HUMAN);
|
||||||
|
this.power = new MageInt(2);
|
||||||
|
this.toughness = new MageInt(4);
|
||||||
|
|
||||||
|
// Whenever you cast an instant or sorcery spell that targets only Bill Potts or activate an ability that targets only Bill Potts, copy that spell or ability. You may choose new targets for the copy. This ability triggers only once each turn.
|
||||||
|
this.addAbility(new OrTriggeredAbility(
|
||||||
|
Zone.BATTLEFIELD,
|
||||||
|
new CopyStackObjectEffect("that spell or ability"),
|
||||||
|
false,
|
||||||
|
"",
|
||||||
|
new SpellCastControllerTriggeredAbility(
|
||||||
|
null,
|
||||||
|
filterInstantOrSorcery,
|
||||||
|
false,
|
||||||
|
SetTargetPointer.SPELL
|
||||||
|
),
|
||||||
|
new ActivateAbilityTriggeredAbility(
|
||||||
|
null,
|
||||||
|
filterAbility,
|
||||||
|
SetTargetPointer.SPELL
|
||||||
|
)
|
||||||
|
).setTriggersLimitEachTurn(1));
|
||||||
|
|
||||||
|
// Doctor's companion
|
||||||
|
this.addAbility(DoctorsCompanionAbility.getInstance());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private BillPotts(final BillPotts card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BillPotts copy() {
|
||||||
|
return new BillPotts(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum BillPottsPredicate implements ObjectSourcePlayerPredicate<StackObject> {
|
||||||
|
instance;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(ObjectSourcePlayer<StackObject> input, Game game) {
|
||||||
|
List<UUID> oneTargetList = Arrays.asList(input.getSourceId());
|
||||||
|
return (makeStream(input, game).collect(Collectors.toList()).equals(oneTargetList));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final Stream<UUID> makeStream(ObjectSourcePlayer<StackObject> input, Game game) {
|
||||||
|
Abilities<Ability> objectAbilities = new AbilitiesImpl<>();
|
||||||
|
if (input.getObject() instanceof Spell) {
|
||||||
|
objectAbilities.addAll(((Spell) input.getObject()).getSpellAbilities());
|
||||||
|
} else {
|
||||||
|
objectAbilities.add(input.getObject().getStackAbility());
|
||||||
|
}
|
||||||
|
return objectAbilities
|
||||||
|
.stream()
|
||||||
|
.map(Ability::getModes)
|
||||||
|
.flatMap(m -> m.getSelectedModes().stream().map(m::get))
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.map(Mode::getTargets)
|
||||||
|
.flatMap(Collection::stream)
|
||||||
|
.filter(t -> !t.isNotTarget())
|
||||||
|
.map(Target::getTargets)
|
||||||
|
.flatMap(Collection::stream)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.distinct();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,26 +1,20 @@
|
||||||
package mage.cards.b;
|
package mage.cards.b;
|
||||||
|
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.abilities.Ability;
|
|
||||||
import mage.abilities.DelayedTriggeredAbility;
|
|
||||||
import mage.abilities.common.PutIntoGraveFromBattlefieldSourceTriggeredAbility;
|
import mage.abilities.common.PutIntoGraveFromBattlefieldSourceTriggeredAbility;
|
||||||
import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
|
import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
|
||||||
import mage.abilities.effects.Effect;
|
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
|
||||||
import mage.abilities.effects.common.LoseLifeSourceControllerEffect;
|
import mage.abilities.effects.common.LoseLifeSourceControllerEffect;
|
||||||
import mage.abilities.effects.common.ReturnToHandTargetEffect;
|
import mage.abilities.effects.common.ReturnSourceFromGraveyardToHandEffect;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Outcome;
|
|
||||||
import mage.constants.SubType;
|
import mage.constants.SubType;
|
||||||
import mage.game.Game;
|
|
||||||
import mage.target.targetpointer.FixedTarget;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author mpouedras
|
* @author mpouedras, notgreat
|
||||||
*/
|
*/
|
||||||
public final class BroodOfCockroaches extends CardImpl {
|
public final class BroodOfCockroaches extends CardImpl {
|
||||||
|
|
||||||
|
|
@ -33,7 +27,13 @@ public final class BroodOfCockroaches extends CardImpl {
|
||||||
|
|
||||||
// When Brood of Cockroaches is put into your graveyard from the battlefield,
|
// When Brood of Cockroaches is put into your graveyard from the battlefield,
|
||||||
// at the beginning of the next end step, you lose 1 life and return Brood of Cockroaches to your hand.
|
// at the beginning of the next end step, you lose 1 life and return Brood of Cockroaches to your hand.
|
||||||
this.addAbility(new PutIntoGraveFromBattlefieldSourceTriggeredAbility(new BroodOfCockroachesEffect(), false, true));
|
|
||||||
|
AtTheBeginOfNextEndStepDelayedTriggeredAbility delayed =
|
||||||
|
new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new LoseLifeSourceControllerEffect(1));
|
||||||
|
delayed.addEffect(new ReturnSourceFromGraveyardToHandEffect().concatBy("and").setText("return this card to your hand"));
|
||||||
|
CreateDelayedTriggeredAbilityEffect delayedEffect = new CreateDelayedTriggeredAbilityEffect(delayed);
|
||||||
|
|
||||||
|
this.addAbility(new PutIntoGraveFromBattlefieldSourceTriggeredAbility(delayedEffect, false, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
private BroodOfCockroaches(final BroodOfCockroaches card) {
|
private BroodOfCockroaches(final BroodOfCockroaches card) {
|
||||||
|
|
@ -45,36 +45,3 @@ public final class BroodOfCockroaches extends CardImpl {
|
||||||
return new BroodOfCockroaches(this);
|
return new BroodOfCockroaches(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class BroodOfCockroachesEffect extends OneShotEffect {
|
|
||||||
private static final String effectText = "at the beginning of the next end step, you lose 1 life and return {this} to your hand.";
|
|
||||||
|
|
||||||
BroodOfCockroachesEffect() {
|
|
||||||
super(Outcome.Benefit);
|
|
||||||
staticText = effectText;
|
|
||||||
}
|
|
||||||
|
|
||||||
private BroodOfCockroachesEffect(final BroodOfCockroachesEffect effect) {
|
|
||||||
super(effect);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean apply(Game game, Ability source) {
|
|
||||||
AtTheBeginOfNextEndStepDelayedTriggeredAbility delayedLifeLost =
|
|
||||||
new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new LoseLifeSourceControllerEffect(1));
|
|
||||||
game.addDelayedTriggeredAbility(delayedLifeLost, source);
|
|
||||||
|
|
||||||
Effect effect = new ReturnToHandTargetEffect();
|
|
||||||
effect.setText("return {this} to your hand.");
|
|
||||||
effect.setTargetPointer(new FixedTarget(source.getSourceId(), source.getSourceObjectZoneChangeCounter()));
|
|
||||||
DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(effect);
|
|
||||||
game.addDelayedTriggeredAbility(delayedAbility, source);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BroodOfCockroachesEffect copy() {
|
|
||||||
return new BroodOfCockroachesEffect(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
106
Mage.Sets/src/mage/cards/b/BrotherhoodHeadquarters.java
Normal file
106
Mage.Sets/src/mage/cards/b/BrotherhoodHeadquarters.java
Normal file
|
|
@ -0,0 +1,106 @@
|
||||||
|
package mage.cards.b;
|
||||||
|
|
||||||
|
import mage.ConditionalMana;
|
||||||
|
import mage.MageObject;
|
||||||
|
import mage.Mana;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.SpellAbility;
|
||||||
|
import mage.abilities.condition.Condition;
|
||||||
|
import mage.abilities.keyword.FreerunningAbility;
|
||||||
|
import mage.abilities.mana.ColorlessManaAbility;
|
||||||
|
import mage.abilities.mana.ConditionalAnyColorManaAbility;
|
||||||
|
import mage.abilities.mana.builder.ConditionalManaBuilder;
|
||||||
|
import mage.cards.Card;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.SubType;
|
||||||
|
import mage.filter.Filter;
|
||||||
|
import mage.filter.predicate.Predicate;
|
||||||
|
import mage.filter.predicate.mageobject.AbilityPredicate;
|
||||||
|
import mage.game.Game;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class BrotherhoodHeadquarters extends CardImpl {
|
||||||
|
|
||||||
|
private static final Predicate<MageObject> predicate = new AbilityPredicate(FreerunningAbility.class);
|
||||||
|
|
||||||
|
public BrotherhoodHeadquarters(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.LAND}, "");
|
||||||
|
|
||||||
|
// Add one colorless
|
||||||
|
this.addAbility(new ColorlessManaAbility());
|
||||||
|
|
||||||
|
// Add one mana of any color. Spend this mana only to cast an Assassin spell or a spell that has freerunning, or to activate an ability of an Assassin source.
|
||||||
|
this.addAbility(new ConditionalAnyColorManaAbility(1, new BrotherhoodHeadquartersManaBuilder()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public BrotherhoodHeadquarters(BrotherhoodHeadquarters card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BrotherhoodHeadquarters copy() {
|
||||||
|
return new BrotherhoodHeadquarters(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
class BrotherhoodHeadquartersManaBuilder extends ConditionalManaBuilder {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getRule() {
|
||||||
|
return "Spend this mana only to cast an Assassin spell or a spell that has freerunning, or to activate an ability of an Assassin source.";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ConditionalMana build(Object... options) {
|
||||||
|
return new BrotherhoodHeadquartersConditionalMana(this.mana);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class BrotherhoodHeadquartersConditionalMana extends ConditionalMana {
|
||||||
|
|
||||||
|
public BrotherhoodHeadquartersConditionalMana(Mana mana) {
|
||||||
|
super(mana);
|
||||||
|
addCondition(new BrotherhoodHeadquartersAssassinSpellManaCondition());
|
||||||
|
addCondition(new BrotherhoodHeadquartersFreerunningManaCondition());
|
||||||
|
addCondition(new BrotherhoodHeadquartersAssassinSourceManaCondition());
|
||||||
|
setComparisonScope(Filter.ComparisonScope.Any);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class BrotherhoodHeadquartersAssassinSpellManaCondition implements Condition {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source) {
|
||||||
|
if (source instanceof SpellAbility) {
|
||||||
|
Card card = game.getCard(source.getSourceId());
|
||||||
|
return card != null && card.hasSubtype(SubType.ASSASSIN, game);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class BrotherhoodHeadquartersFreerunningManaCondition implements Condition {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source) {
|
||||||
|
MageObject sourceObject = game.getObject(source);
|
||||||
|
return sourceObject != null && predicate.apply(sourceObject, game);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class BrotherhoodHeadquartersAssassinSourceManaCondition implements Condition {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source) {
|
||||||
|
if (source.isActivatedAbility()) {
|
||||||
|
MageObject object = game.getObject(source.getSourceId());
|
||||||
|
return object != null && object.hasSubtype(SubType.ASSASSIN, game);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
43
Mage.Sets/src/mage/cards/c/CanyonVaulter.java
Normal file
43
Mage.Sets/src/mage/cards/c/CanyonVaulter.java
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
package mage.cards.c;
|
||||||
|
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.abilities.effects.Effect;
|
||||||
|
import mage.abilities.effects.common.CrewsVehicleSourceTriggeredAbility;
|
||||||
|
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
|
||||||
|
import mage.abilities.keyword.FlyingAbility;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.Duration;
|
||||||
|
import mage.constants.SubType;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author notgreat
|
||||||
|
*/
|
||||||
|
public final class CanyonVaulter extends CardImpl {
|
||||||
|
|
||||||
|
public CanyonVaulter(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}");
|
||||||
|
|
||||||
|
this.subtype.add(SubType.KOR);
|
||||||
|
this.subtype.add(SubType.PILOT);
|
||||||
|
this.power = new MageInt(3);
|
||||||
|
this.toughness = new MageInt(1);
|
||||||
|
|
||||||
|
// Whenever this creature saddles a Mount or crews a Vehicle during your main phase, that Mount or Vehicle gains flying until end of turn.
|
||||||
|
Effect effect = new GainAbilityTargetEffect(FlyingAbility.getInstance(), Duration.EndOfTurn);
|
||||||
|
effect.setText("that Mount or Vehicle gains flying until end of turn");
|
||||||
|
this.addAbility(new CrewsVehicleSourceTriggeredAbility(effect, true, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
private CanyonVaulter(final CanyonVaulter card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CanyonVaulter copy() {
|
||||||
|
return new CanyonVaulter(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
69
Mage.Sets/src/mage/cards/c/CaptainHowlerSeaScourge.java
Normal file
69
Mage.Sets/src/mage/cards/c/CaptainHowlerSeaScourge.java
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
package mage.cards.c;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
|
||||||
|
import mage.abilities.costs.CompositeCost;
|
||||||
|
import mage.abilities.costs.common.PayLifeCost;
|
||||||
|
import mage.abilities.dynamicvalue.DynamicValue;
|
||||||
|
import mage.abilities.dynamicvalue.MultipliedValue;
|
||||||
|
import mage.abilities.dynamicvalue.common.SavedDiscardValue;
|
||||||
|
import mage.abilities.dynamicvalue.common.StaticValue;
|
||||||
|
import mage.abilities.effects.common.DiscardOneOrMoreCardsTriggeredAbility;
|
||||||
|
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
||||||
|
import mage.abilities.effects.common.continuous.BoostTargetEffect;
|
||||||
|
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
|
||||||
|
import mage.constants.SubType;
|
||||||
|
import mage.constants.SuperType;
|
||||||
|
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
|
import mage.abilities.keyword.WardAbility;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.target.common.TargetCreaturePermanent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Jmlundeen
|
||||||
|
*/
|
||||||
|
public final class CaptainHowlerSeaScourge extends CardImpl {
|
||||||
|
private static final DynamicValue powerValue = new MultipliedValue(SavedDiscardValue.MANY, 2);
|
||||||
|
|
||||||
|
public CaptainHowlerSeaScourge(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}{R}");
|
||||||
|
|
||||||
|
this.supertype.add(SuperType.LEGENDARY);
|
||||||
|
this.subtype.add(SubType.SHARK);
|
||||||
|
this.subtype.add(SubType.PIRATE);
|
||||||
|
this.power = new MageInt(5);
|
||||||
|
this.toughness = new MageInt(4);
|
||||||
|
|
||||||
|
// Ward--{2}, Pay 2 life.
|
||||||
|
CompositeCost cost = new CompositeCost(new ManaCostsImpl<>("{2}"), new PayLifeCost(2), "{2}, Pay 2 life");
|
||||||
|
this.addAbility(new WardAbility(cost, false));
|
||||||
|
|
||||||
|
// Whenever you discard one or more cards, target creature gets +2/+0 until end of turn for each card discarded this way. Whenever that creature deals combat damage to a player this turn, you draw a card.
|
||||||
|
Ability ability = new DiscardOneOrMoreCardsTriggeredAbility(
|
||||||
|
new BoostTargetEffect(powerValue, StaticValue.get(0))
|
||||||
|
.setText("target creature gets +2/+0 until end of turn for each card discarded this way")
|
||||||
|
);
|
||||||
|
ability.addEffect(new GainAbilityTargetEffect(
|
||||||
|
new DealsCombatDamageToAPlayerTriggeredAbility(
|
||||||
|
new DrawCardSourceControllerEffect(1), false
|
||||||
|
))
|
||||||
|
.setText("Whenever that creature deals combat damage to a player this turn, you draw a card")
|
||||||
|
);
|
||||||
|
ability.addTarget(new TargetCreaturePermanent());
|
||||||
|
this.addAbility(ability);
|
||||||
|
}
|
||||||
|
|
||||||
|
private CaptainHowlerSeaScourge(final CaptainHowlerSeaScourge card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CaptainHowlerSeaScourge copy() {
|
||||||
|
return new CaptainHowlerSeaScourge(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
60
Mage.Sets/src/mage/cards/c/CloudspireSkycycle.java
Normal file
60
Mage.Sets/src/mage/cards/c/CloudspireSkycycle.java
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
package mage.cards.c;
|
||||||
|
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||||
|
import mage.abilities.effects.common.counter.DistributeCountersEffect;
|
||||||
|
import mage.abilities.keyword.CrewAbility;
|
||||||
|
import mage.abilities.keyword.FlyingAbility;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.SubType;
|
||||||
|
import mage.filter.common.FilterControlledPermanent;
|
||||||
|
import mage.filter.predicate.Predicates;
|
||||||
|
import mage.filter.predicate.mageobject.AnotherPredicate;
|
||||||
|
import mage.target.common.TargetPermanentAmount;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author notgreat
|
||||||
|
*/
|
||||||
|
public final class CloudspireSkycycle extends CardImpl {
|
||||||
|
|
||||||
|
private static final FilterControlledPermanent filter = new FilterControlledPermanent("other target Vehicles and/or creatures you control");
|
||||||
|
|
||||||
|
static {
|
||||||
|
filter.add(AnotherPredicate.instance);
|
||||||
|
filter.add(Predicates.or(SubType.VEHICLE.getPredicate(), CardType.CREATURE.getPredicate()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public CloudspireSkycycle(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}{R}{W}");
|
||||||
|
|
||||||
|
this.subtype.add(SubType.VEHICLE);
|
||||||
|
this.power = new MageInt(2);
|
||||||
|
this.toughness = new MageInt(3);
|
||||||
|
|
||||||
|
// Flying
|
||||||
|
this.addAbility(FlyingAbility.getInstance());
|
||||||
|
|
||||||
|
// When this Vehicle enters, distribute two +1/+1 counters among one or two other target Vehicles and/or creatures you control.
|
||||||
|
Ability ability = new EntersBattlefieldTriggeredAbility(new DistributeCountersEffect());
|
||||||
|
ability.addTarget(new TargetPermanentAmount(2, 1, filter));
|
||||||
|
this.addAbility(ability);
|
||||||
|
|
||||||
|
// Crew 1
|
||||||
|
this.addAbility(new CrewAbility(1));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private CloudspireSkycycle(final CloudspireSkycycle card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CloudspireSkycycle copy() {
|
||||||
|
return new CloudspireSkycycle(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
116
Mage.Sets/src/mage/cards/c/CoalstokeGearhulk.java
Normal file
116
Mage.Sets/src/mage/cards/c/CoalstokeGearhulk.java
Normal file
|
|
@ -0,0 +1,116 @@
|
||||||
|
package mage.cards.c;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.DelayedTriggeredAbility;
|
||||||
|
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||||
|
import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
|
||||||
|
import mage.abilities.effects.ContinuousEffect;
|
||||||
|
import mage.abilities.effects.OneShotEffect;
|
||||||
|
import mage.abilities.effects.common.ExileTargetEffect;
|
||||||
|
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldWithCounterTargetEffect;
|
||||||
|
import mage.abilities.effects.common.SacrificeTargetEffect;
|
||||||
|
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
|
||||||
|
import mage.abilities.keyword.HasteAbility;
|
||||||
|
import mage.cards.Card;
|
||||||
|
import mage.constants.ComparisonType;
|
||||||
|
import mage.constants.Duration;
|
||||||
|
import mage.constants.Outcome;
|
||||||
|
import mage.constants.SubType;
|
||||||
|
import mage.abilities.keyword.MenaceAbility;
|
||||||
|
import mage.abilities.keyword.DeathtouchAbility;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.TargetController;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import mage.counters.CounterType;
|
||||||
|
import mage.filter.Filter;
|
||||||
|
import mage.filter.StaticFilters;
|
||||||
|
import mage.filter.common.FilterCreatureCard;
|
||||||
|
import mage.filter.predicate.card.ManaValueLessThanControlledLandCountPredicate;
|
||||||
|
import mage.filter.predicate.mageobject.ManaValuePredicate;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.game.permanent.Permanent;
|
||||||
|
import mage.players.Player;
|
||||||
|
import mage.target.common.TargetCardInGraveyard;
|
||||||
|
import mage.target.targetpointer.FixedTarget;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author anonymous
|
||||||
|
*/
|
||||||
|
public final class CoalstokeGearhulk extends CardImpl {
|
||||||
|
private static final FilterCreatureCard filter = new FilterCreatureCard("creature card with mana value 4 or less from a graveyard");
|
||||||
|
|
||||||
|
static {
|
||||||
|
filter.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, 5));
|
||||||
|
}
|
||||||
|
public CoalstokeGearhulk(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{1}{B}{B}{R}{R}");
|
||||||
|
|
||||||
|
this.subtype.add(SubType.CONSTRUCT);
|
||||||
|
this.power = new MageInt(5);
|
||||||
|
this.toughness = new MageInt(4);
|
||||||
|
|
||||||
|
// Menace
|
||||||
|
this.addAbility(new MenaceAbility());
|
||||||
|
|
||||||
|
// Deathtouch
|
||||||
|
this.addAbility(DeathtouchAbility.getInstance());
|
||||||
|
|
||||||
|
// When this creature enters, put target creature card with mana value 4 or less from a graveyard onto the battlefield under your control with a finality counter on it. That creature gains menace, deathtouch, and haste. At the beginnning of your next end step, exile that creature.
|
||||||
|
Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnFromGraveyardToBattlefieldWithCounterTargetEffect(CounterType.FINALITY.createInstance()))
|
||||||
|
.setTriggerPhrase("When this creature enters, ");
|
||||||
|
ability.addEffect(new GainAbilityTargetEffect(new MenaceAbility())
|
||||||
|
.setText("That creature gains menace"));
|
||||||
|
ability.addEffect(new GainAbilityTargetEffect(DeathtouchAbility.getInstance())
|
||||||
|
.setText("deathtouch")
|
||||||
|
.concatBy(","));
|
||||||
|
ability.addEffect(new GainAbilityTargetEffect(HasteAbility.getInstance())
|
||||||
|
.setText("haste")
|
||||||
|
.concatBy(", and"));
|
||||||
|
ability.addEffect(new CoalstokeGearhulkEffect());
|
||||||
|
ability.addTarget(new TargetCardInGraveyard(filter));
|
||||||
|
this.addAbility(ability);
|
||||||
|
}
|
||||||
|
|
||||||
|
private CoalstokeGearhulk(final CoalstokeGearhulk card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CoalstokeGearhulk copy() {
|
||||||
|
return new CoalstokeGearhulk(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CoalstokeGearhulkEffect extends OneShotEffect {
|
||||||
|
public CoalstokeGearhulkEffect() {
|
||||||
|
super(Outcome.Benefit);
|
||||||
|
this.staticText = "At the beginning of your next end step, exile that creature.";
|
||||||
|
}
|
||||||
|
|
||||||
|
public CoalstokeGearhulkEffect(final CoalstokeGearhulkEffect effect) {
|
||||||
|
super(effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CoalstokeGearhulkEffect copy() {
|
||||||
|
return new CoalstokeGearhulkEffect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source) {
|
||||||
|
Permanent permanent = game.getPermanent(source.getFirstTarget());
|
||||||
|
if (permanent == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ExileTargetEffect exileEffect = new ExileTargetEffect("At the beginning of your next end step, exile " + permanent.getLogName());
|
||||||
|
exileEffect.setTargetPointer(new FixedTarget(permanent, game));
|
||||||
|
DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(exileEffect, TargetController.YOU);
|
||||||
|
game.addDelayedTriggeredAbility(delayedAbility, source);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package mage.cards.c;
|
package mage.cards.c;
|
||||||
|
|
||||||
import mage.abilities.effects.common.search.SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect;
|
import mage.abilities.effects.common.search.SearchLibraryPutOntoBattlefieldTappedRestInHandEffect;
|
||||||
import mage.cards.*;
|
import mage.cards.*;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.filter.StaticFilters;
|
import mage.filter.StaticFilters;
|
||||||
|
|
@ -17,7 +17,7 @@ public final class Cultivate extends CardImpl {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{G}");
|
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{G}");
|
||||||
|
|
||||||
// Search your library for up to two basic land cards, reveal those cards, put one onto the battlefield tapped and the other into your hand, then shuffle.
|
// Search your library for up to two basic land cards, reveal those cards, put one onto the battlefield tapped and the other into your hand, then shuffle.
|
||||||
this.getSpellAbility().addEffect(new SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect(
|
this.getSpellAbility().addEffect(new SearchLibraryPutOntoBattlefieldTappedRestInHandEffect(
|
||||||
new TargetCardInLibrary(0, 2, StaticFilters.FILTER_CARD_BASIC_LANDS)));
|
new TargetCardInLibrary(0, 2, StaticFilters.FILTER_CARD_BASIC_LANDS)));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
90
Mage.Sets/src/mage/cards/c/CurseclothWrappings.java
Normal file
90
Mage.Sets/src/mage/cards/c/CurseclothWrappings.java
Normal file
|
|
@ -0,0 +1,90 @@
|
||||||
|
package mage.cards.c;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.common.SimpleActivatedAbility;
|
||||||
|
import mage.abilities.common.SimpleStaticAbility;
|
||||||
|
import mage.abilities.costs.common.TapSourceCost;
|
||||||
|
import mage.abilities.effects.ContinuousEffectImpl;
|
||||||
|
import mage.abilities.effects.common.continuous.BoostControlledEffect;
|
||||||
|
import mage.abilities.keyword.EmbalmAbility;
|
||||||
|
import mage.cards.Card;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.Duration;
|
||||||
|
import mage.constants.Layer;
|
||||||
|
import mage.constants.Outcome;
|
||||||
|
import mage.constants.SubLayer;
|
||||||
|
import mage.constants.SubType;
|
||||||
|
import mage.filter.common.FilterCreatureCard;
|
||||||
|
import mage.filter.common.FilterCreaturePermanent;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.target.common.TargetCardInYourGraveyard;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Jmlundeen
|
||||||
|
*/
|
||||||
|
public final class CurseclothWrappings extends CardImpl {
|
||||||
|
public static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Zombies you control");
|
||||||
|
|
||||||
|
static {
|
||||||
|
filter.add(SubType.ZOMBIE.getPredicate());
|
||||||
|
}
|
||||||
|
public CurseclothWrappings(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}{B}{B}");
|
||||||
|
|
||||||
|
|
||||||
|
// Zombies you control get +1/+1.
|
||||||
|
this.addAbility(new SimpleStaticAbility(new BoostControlledEffect(1, 1, Duration.WhileOnBattlefield, filter)));
|
||||||
|
// {T}: Target creature card in your graveyard gains embalm until end of turn. The embalm cost is equal to its mana cost.
|
||||||
|
Ability ability = new SimpleActivatedAbility(
|
||||||
|
new CurseClothWrappingsEffect(),
|
||||||
|
new TapSourceCost()
|
||||||
|
);
|
||||||
|
ability.addTarget(new TargetCardInYourGraveyard(new FilterCreatureCard("creature card in your graveyard")));
|
||||||
|
this.addAbility(ability);
|
||||||
|
}
|
||||||
|
|
||||||
|
private CurseclothWrappings(final CurseclothWrappings card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CurseclothWrappings copy() {
|
||||||
|
return new CurseclothWrappings(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CurseClothWrappingsEffect extends ContinuousEffectImpl {
|
||||||
|
public CurseClothWrappingsEffect() {
|
||||||
|
super(Duration.EndOfTurn, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility);
|
||||||
|
this.staticText = "Target creature card in your graveyard gains embalm until end of turn. " +
|
||||||
|
"The embalm cost is equal to its mana cost. (Exile that card and pay its embalm cost: " +
|
||||||
|
"Create a token that's a copy of it, except it's a white Zombie in addition to its other types " +
|
||||||
|
"and has no mana cost. Embalm only as a sorcery.)";
|
||||||
|
}
|
||||||
|
|
||||||
|
public CurseClothWrappingsEffect(final CurseClothWrappingsEffect effect) {
|
||||||
|
super(effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CurseClothWrappingsEffect copy() {
|
||||||
|
return new CurseClothWrappingsEffect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source) {
|
||||||
|
Card card = game.getCard(getTargetPointer().getFirst(game, source));
|
||||||
|
if (card != null) {
|
||||||
|
EmbalmAbility embalmAbility = new EmbalmAbility(card.getManaCost(), card);
|
||||||
|
game.getState().addOtherAbility(card, embalmAbility);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -10,21 +10,17 @@ import mage.abilities.costs.Costs;
|
||||||
import mage.abilities.costs.CostsImpl;
|
import mage.abilities.costs.CostsImpl;
|
||||||
import mage.abilities.costs.common.ExileFromGraveCost;
|
import mage.abilities.costs.common.ExileFromGraveCost;
|
||||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
import mage.abilities.dynamicvalue.DynamicValue;
|
import mage.abilities.dynamicvalue.common.InstantAndSorceryCastThisTurn;
|
||||||
import mage.abilities.effects.AsThoughEffectImpl;
|
import mage.abilities.effects.AsThoughEffectImpl;
|
||||||
import mage.abilities.effects.Effect;
|
|
||||||
import mage.abilities.effects.common.ExileTargetCardCopyAndCastEffect;
|
import mage.abilities.effects.common.ExileTargetCardCopyAndCastEffect;
|
||||||
import mage.abilities.effects.common.cost.SpellCostReductionForEachSourceEffect;
|
import mage.abilities.effects.common.cost.SpellCostReductionForEachSourceEffect;
|
||||||
import mage.abilities.hint.ValueHint;
|
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.*;
|
import mage.constants.*;
|
||||||
import mage.filter.StaticFilters;
|
import mage.filter.StaticFilters;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.stack.Spell;
|
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.target.common.TargetCardInYourGraveyard;
|
import mage.target.common.TargetCardInYourGraveyard;
|
||||||
import mage.watchers.common.SpellsCastWatcher;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
|
@ -43,8 +39,8 @@ public final class Demilich extends CardImpl {
|
||||||
|
|
||||||
// This spell costs {U} less to cast for each instant and sorcery you've cast this turn.
|
// This spell costs {U} less to cast for each instant and sorcery you've cast this turn.
|
||||||
this.addAbility(new SimpleStaticAbility(Zone.ALL, new SpellCostReductionForEachSourceEffect(
|
this.addAbility(new SimpleStaticAbility(Zone.ALL, new SpellCostReductionForEachSourceEffect(
|
||||||
new ManaCostsImpl<>("{U}"), DemilichValue.instance
|
new ManaCostsImpl<>("{U}"), InstantAndSorceryCastThisTurn.YOU
|
||||||
)).addHint(new ValueHint("Instants and sorceries you've cast this turn", DemilichValue.instance)));
|
)).addHint(InstantAndSorceryCastThisTurn.YOU.getHint()));
|
||||||
|
|
||||||
// Whenever Demilich attacks, exile up to one target instant or sorcery card from your graveyard. Copy it. You may cast the copy.
|
// Whenever Demilich attacks, exile up to one target instant or sorcery card from your graveyard. Copy it. You may cast the copy.
|
||||||
Ability ability = new AttacksTriggeredAbility(new ExileTargetCardCopyAndCastEffect(false).setText(
|
Ability ability = new AttacksTriggeredAbility(new ExileTargetCardCopyAndCastEffect(false).setText(
|
||||||
|
|
@ -66,34 +62,6 @@ public final class Demilich extends CardImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum DemilichValue implements DynamicValue {
|
|
||||||
instance;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int calculate(Game game, Ability sourceAbility, Effect effect) {
|
|
||||||
int spells = 0;
|
|
||||||
SpellsCastWatcher watcher = game.getState().getWatcher(SpellsCastWatcher.class);
|
|
||||||
if (watcher != null) {
|
|
||||||
for (Spell spell : watcher.getSpellsCastThisTurn(sourceAbility.getControllerId())) {
|
|
||||||
if (spell.isInstantOrSorcery(game)) {
|
|
||||||
spells++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return spells;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DemilichValue copy() {
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getMessage() {
|
|
||||||
return "instant and sorcery spell you've cast this turn";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class DemilichPlayEffect extends AsThoughEffectImpl {
|
class DemilichPlayEffect extends AsThoughEffectImpl {
|
||||||
|
|
||||||
DemilichPlayEffect() {
|
DemilichPlayEffect() {
|
||||||
|
|
|
||||||
117
Mage.Sets/src/mage/cards/d/DemonicJunker.java
Normal file
117
Mage.Sets/src/mage/cards/d/DemonicJunker.java
Normal file
|
|
@ -0,0 +1,117 @@
|
||||||
|
package mage.cards.d;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||||
|
import mage.abilities.effects.OneShotEffect;
|
||||||
|
import mage.constants.Outcome;
|
||||||
|
import mage.constants.SubType;
|
||||||
|
import mage.abilities.keyword.AffinityForArtifactsAbility;
|
||||||
|
import mage.abilities.keyword.CrewAbility;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.counters.CounterType;
|
||||||
|
import mage.filter.common.FilterCreaturePermanent;
|
||||||
|
import mage.filter.predicate.permanent.ControllerIdPredicate;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.game.permanent.Permanent;
|
||||||
|
import mage.players.Player;
|
||||||
|
import mage.target.TargetPermanent;
|
||||||
|
import mage.target.targetadjustment.TargetAdjuster;
|
||||||
|
import mage.target.targetpointer.EachTargetPointer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Jmlundeen
|
||||||
|
*/
|
||||||
|
public final class DemonicJunker extends CardImpl {
|
||||||
|
|
||||||
|
public DemonicJunker(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{6}{B}");
|
||||||
|
|
||||||
|
this.subtype.add(SubType.VEHICLE);
|
||||||
|
this.power = new MageInt(4);
|
||||||
|
this.toughness = new MageInt(3);
|
||||||
|
|
||||||
|
// Affinity for artifacts
|
||||||
|
this.addAbility(new AffinityForArtifactsAbility());
|
||||||
|
|
||||||
|
// When this Vehicle enters, for each player, destroy up to one target creature that player controls. If a creature you controlled was destroyed this way, put two +1/+1 counters on this Vehicle.
|
||||||
|
Ability ability = new EntersBattlefieldTriggeredAbility(new DemonicJunkerEffect()
|
||||||
|
.setTargetPointer(new EachTargetPointer()))
|
||||||
|
.setTriggerPhrase("When this Vehicle enters, ");
|
||||||
|
this.addAbility(ability.setTargetAdjuster(DemonicJunkerAdjuster.instance));
|
||||||
|
|
||||||
|
// Crew 2
|
||||||
|
this.addAbility(new CrewAbility(2));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private DemonicJunker(final DemonicJunker card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DemonicJunker copy() {
|
||||||
|
return new DemonicJunker(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum DemonicJunkerAdjuster implements TargetAdjuster {
|
||||||
|
instance;
|
||||||
|
@Override
|
||||||
|
public void adjustTargets(Ability ability, Game game) {
|
||||||
|
ability.getTargets().clear();
|
||||||
|
for (UUID playerId : game.getState().getPlayersInRange(ability.getControllerId(), game)) {
|
||||||
|
Player player = game.getPlayer(playerId);
|
||||||
|
if (player == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String playerName = ability.isControlledBy(playerId) ? "you" : player.getName();
|
||||||
|
FilterCreaturePermanent filter = new FilterCreaturePermanent("creature controlled by " + playerName);
|
||||||
|
filter.add(new ControllerIdPredicate(playerId));
|
||||||
|
ability.addTarget(new TargetPermanent(0, 1, filter));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DemonicJunkerEffect extends OneShotEffect {
|
||||||
|
|
||||||
|
DemonicJunkerEffect() {
|
||||||
|
super(Outcome.DestroyPermanent);
|
||||||
|
staticText = "for each player, destroy up to one target creature that player controls. If a creature you controlled was destroyed this way, put two +1/+1 counters on this Vehicle";
|
||||||
|
}
|
||||||
|
|
||||||
|
public DemonicJunkerEffect(final DemonicJunkerEffect effect) {
|
||||||
|
super(effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DemonicJunkerEffect copy() {
|
||||||
|
return new DemonicJunkerEffect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source) {
|
||||||
|
boolean giveCounters = false;
|
||||||
|
for (UUID permanentId : getTargetPointer().getTargets(game, source)) {
|
||||||
|
Permanent permanent = game.getPermanent(permanentId);
|
||||||
|
if (permanent == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (permanent.destroy(source, game, false)) {
|
||||||
|
giveCounters = permanent.getControllerId().equals(source.getControllerId());
|
||||||
|
}
|
||||||
|
if (giveCounters) {
|
||||||
|
Permanent vehicle = game.getPermanent(source.getSourceId());
|
||||||
|
if (vehicle != null) {
|
||||||
|
vehicle.addCounters(CounterType.P1P1.createInstance(2), source.getControllerId(), source, game);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
57
Mage.Sets/src/mage/cards/d/DuneDrifter.java
Normal file
57
Mage.Sets/src/mage/cards/d/DuneDrifter.java
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
package mage.cards.d;
|
||||||
|
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||||
|
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
|
||||||
|
import mage.abilities.keyword.CrewAbility;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.ComparisonType;
|
||||||
|
import mage.constants.SubType;
|
||||||
|
import mage.filter.FilterCard;
|
||||||
|
import mage.filter.predicate.Predicates;
|
||||||
|
import mage.target.common.TargetCardInYourGraveyard;
|
||||||
|
import mage.target.targetadjustment.XManaValueTargetAdjuster;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author notgreat
|
||||||
|
*/
|
||||||
|
public final class DuneDrifter extends CardImpl {
|
||||||
|
|
||||||
|
private static final FilterCard filter = new FilterCard("artifact or creature card with mana value X or less from your graveyard");
|
||||||
|
|
||||||
|
static {
|
||||||
|
filter.add(Predicates.or(CardType.ARTIFACT.getPredicate(), CardType.CREATURE.getPredicate()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public DuneDrifter(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{X}{W}{B}");
|
||||||
|
|
||||||
|
this.subtype.add(SubType.VEHICLE);
|
||||||
|
this.power = new MageInt(3);
|
||||||
|
this.toughness = new MageInt(3);
|
||||||
|
|
||||||
|
// When this Vehicle enters, return target artifact or creature card with mana value X or less from your graveyard to the battlefield.
|
||||||
|
Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnFromGraveyardToBattlefieldTargetEffect());
|
||||||
|
ability.addTarget(new TargetCardInYourGraveyard(filter));
|
||||||
|
ability.setTargetAdjuster(new XManaValueTargetAdjuster(ComparisonType.OR_LESS));
|
||||||
|
this.addAbility(ability);
|
||||||
|
|
||||||
|
// Crew 2
|
||||||
|
this.addAbility(new CrewAbility(2));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private DuneDrifter(final DuneDrifter card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DuneDrifter copy() {
|
||||||
|
return new DuneDrifter(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -61,17 +61,21 @@ class FanaticOfTheHarrowingEffect extends OneShotEffect {
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
boolean flag = false;
|
boolean flag = false;
|
||||||
for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) {
|
for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) {
|
||||||
Player player = game.getPlayer(source.getControllerId());
|
Player player = game.getPlayer(playerId);
|
||||||
if (player == null) {
|
if (player == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!player.discard(1, false, false, source, game).isEmpty()
|
if (!player.discard(1, false, false, source, game).isEmpty()
|
||||||
&& player.equals(source.getControllerId())) {
|
&& playerId.equals(source.getControllerId())) {
|
||||||
flag = true;
|
flag = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
game.processAction();
|
||||||
if (flag) {
|
if (flag) {
|
||||||
game.getPlayer(source.getControllerId()).drawCards(1, source, game);
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
|
if (controller != null) {
|
||||||
|
controller.drawCards(1, source, game);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ package mage.cards.f;
|
||||||
import mage.ObjectColor;
|
import mage.ObjectColor;
|
||||||
import mage.abilities.costs.AlternativeCostSourceAbility;
|
import mage.abilities.costs.AlternativeCostSourceAbility;
|
||||||
import mage.abilities.costs.common.SacrificeTargetCost;
|
import mage.abilities.costs.common.SacrificeTargetCost;
|
||||||
import mage.abilities.effects.common.search.SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect;
|
import mage.abilities.effects.common.search.SearchLibraryPutOntoBattlefieldTappedRestInHandEffect;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
|
|
@ -35,7 +35,7 @@ public final class FlareOfCultivation extends CardImpl {
|
||||||
this.addAbility(new AlternativeCostSourceAbility(new SacrificeTargetCost(filter)).setRuleAtTheTop(true));
|
this.addAbility(new AlternativeCostSourceAbility(new SacrificeTargetCost(filter)).setRuleAtTheTop(true));
|
||||||
|
|
||||||
// Search your library for up to two basic land cards, reveal those cards, put one onto the battlefield tapped and the other into your hand, then shuffle.
|
// Search your library for up to two basic land cards, reveal those cards, put one onto the battlefield tapped and the other into your hand, then shuffle.
|
||||||
this.getSpellAbility().addEffect(new SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect(
|
this.getSpellAbility().addEffect(new SearchLibraryPutOntoBattlefieldTappedRestInHandEffect(
|
||||||
new TargetCardInLibrary(0, 2, StaticFilters.FILTER_CARD_BASIC_LANDS)
|
new TargetCardInLibrary(0, 2, StaticFilters.FILTER_CARD_BASIC_LANDS)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import mage.abilities.common.TurnedFaceUpSourceTriggeredAbility;
|
||||||
import mage.abilities.dynamicvalue.DynamicValue;
|
import mage.abilities.dynamicvalue.DynamicValue;
|
||||||
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
|
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
|
||||||
import mage.abilities.effects.common.continuous.BoostSourceEffect;
|
import mage.abilities.effects.common.continuous.BoostSourceEffect;
|
||||||
import mage.abilities.effects.common.search.SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect;
|
import mage.abilities.effects.common.search.SearchLibraryPutOntoBattlefieldTappedRestInHandEffect;
|
||||||
import mage.abilities.hint.Hint;
|
import mage.abilities.hint.Hint;
|
||||||
import mage.abilities.hint.ValueHint;
|
import mage.abilities.hint.ValueHint;
|
||||||
import mage.constants.Duration;
|
import mage.constants.Duration;
|
||||||
|
|
@ -56,7 +56,7 @@ public final class FlourishingBloomKin extends CardImpl {
|
||||||
// When Flourishing Bloom-Kin is turned face up, search your library for up to two Forest cards and reveal them.
|
// When Flourishing Bloom-Kin is turned face up, search your library for up to two Forest cards and reveal them.
|
||||||
// Put one of them onto the battlefield tapped and the other into your hand, then shuffle.
|
// Put one of them onto the battlefield tapped and the other into your hand, then shuffle.
|
||||||
this.addAbility(new TurnedFaceUpSourceTriggeredAbility(
|
this.addAbility(new TurnedFaceUpSourceTriggeredAbility(
|
||||||
new SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect(new TargetCardInLibrary(0, 2, filterForestCards))
|
new SearchLibraryPutOntoBattlefieldTappedRestInHandEffect(new TargetCardInLibrary(0, 2, filterForestCards))
|
||||||
.setText("search your library for up to two Forest cards and reveal them. Put one of them onto the battlefield tapped and the other into your hand, then shuffle")));
|
.setText("search your library for up to two Forest cards and reveal them. Put one of them onto the battlefield tapped and the other into your hand, then shuffle")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Duration;
|
import mage.constants.Duration;
|
||||||
import mage.constants.SubType;
|
import mage.constants.SubType;
|
||||||
|
import mage.constants.Zone;
|
||||||
import mage.counters.CounterType;
|
import mage.counters.CounterType;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
@ -48,7 +49,7 @@ public final class GastalThrillroller extends CardImpl {
|
||||||
|
|
||||||
// {2}{R}, Discard a card: Return this card from your graveyard to the battlefield with a finality counter on it. Activate only as a sorcery.
|
// {2}{R}, Discard a card: Return this card from your graveyard to the battlefield with a finality counter on it. Activate only as a sorcery.
|
||||||
Ability ability = new ActivateAsSorceryActivatedAbility(
|
Ability ability = new ActivateAsSorceryActivatedAbility(
|
||||||
new ReturnSourceFromGraveyardToBattlefieldWithCounterEffect(
|
Zone.GRAVEYARD, new ReturnSourceFromGraveyardToBattlefieldWithCounterEffect(
|
||||||
CounterType.FINALITY.createInstance(), false
|
CounterType.FINALITY.createInstance(), false
|
||||||
), new ManaCostsImpl<>("{2}{R}")
|
), new ManaCostsImpl<>("{2}{R}")
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import mage.abilities.effects.Effect;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.abilities.effects.common.DamageTargetEffect;
|
import mage.abilities.effects.common.DamageTargetEffect;
|
||||||
import mage.abilities.effects.common.GainLifeEffect;
|
import mage.abilities.effects.common.GainLifeEffect;
|
||||||
|
import mage.abilities.hint.ValueHint;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
|
|
@ -39,6 +40,7 @@ public final class GnostroVoiceOfTheCrags extends CardImpl {
|
||||||
// {T}: Choose one. X is the number of spells you've cast this turn.
|
// {T}: Choose one. X is the number of spells you've cast this turn.
|
||||||
// • Scry X.
|
// • Scry X.
|
||||||
Ability ability = new SimpleActivatedAbility(new GnostroVoiceOfTheCragsEffect(), new TapSourceCost());
|
Ability ability = new SimpleActivatedAbility(new GnostroVoiceOfTheCragsEffect(), new TapSourceCost());
|
||||||
|
ability.addHint(new ValueHint("Number of spells you've cast this turn", GnostroVoiceOfTheCragsValue.instance));
|
||||||
ability.getModes().setChooseText("choose one. X is the number of spells you've cast this turn.");
|
ability.getModes().setChooseText("choose one. X is the number of spells you've cast this turn.");
|
||||||
|
|
||||||
// • Gnostro, Voice of the Crags deals X damage to target creature.
|
// • Gnostro, Voice of the Crags deals X damage to target creature.
|
||||||
|
|
@ -104,7 +106,7 @@ class GnostroVoiceOfTheCragsEffect extends OneShotEffect {
|
||||||
if (player == null) {
|
if (player == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return player.scry (
|
return player.scry(
|
||||||
GnostroVoiceOfTheCragsValue.instance.calculate(game, source, this), source, game
|
GnostroVoiceOfTheCragsValue.instance.calculate(game, source, this), source, game
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.abilities.effects.common.DestroyTargetEffect;
|
import mage.abilities.effects.common.DestroyTargetEffect;
|
||||||
import mage.abilities.effects.common.DoWhenCostPaid;
|
import mage.abilities.effects.common.DoWhenCostPaid;
|
||||||
import mage.abilities.effects.common.LoseLifeOpponentsEffect;
|
import mage.abilities.effects.common.LoseLifeOpponentsEffect;
|
||||||
|
import mage.abilities.hint.ValueHint;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.*;
|
import mage.constants.*;
|
||||||
|
|
@ -34,9 +35,6 @@ import java.util.UUID;
|
||||||
* @author TheElk801
|
* @author TheElk801
|
||||||
*/
|
*/
|
||||||
public final class GristTheHungerTide extends CardImpl {
|
public final class GristTheHungerTide extends CardImpl {
|
||||||
|
|
||||||
private static final DynamicValue xValue = new CardsInControllerGraveyardCount(StaticFilters.FILTER_CARD_CREATURES);
|
|
||||||
|
|
||||||
public GristTheHungerTide(UUID ownerId, CardSetInfo setInfo) {
|
public GristTheHungerTide(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{1}{B}{G}");
|
super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{1}{B}{G}");
|
||||||
|
|
||||||
|
|
@ -61,7 +59,10 @@ public final class GristTheHungerTide extends CardImpl {
|
||||||
), -2));
|
), -2));
|
||||||
|
|
||||||
// −5: Each opponent loses life equal to the number of creature cards in your graveyard.
|
// −5: Each opponent loses life equal to the number of creature cards in your graveyard.
|
||||||
this.addAbility(new LoyaltyAbility(new LoseLifeOpponentsEffect(xValue).setText("each opponent loses life equal to the number of creature cards in your graveyard"), -5));
|
DynamicValue creatureCardsInGraveyard = new CardsInControllerGraveyardCount(StaticFilters.FILTER_CARD_CREATURES);
|
||||||
|
this.addAbility(new LoyaltyAbility(new LoseLifeOpponentsEffect(creatureCardsInGraveyard)
|
||||||
|
.setText("each opponent loses life equal to the number of creature cards in your graveyard"), -5)
|
||||||
|
.addHint(new ValueHint("Creature cards in your graveyard", creatureCardsInGraveyard)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private GristTheHungerTide(final GristTheHungerTide card) {
|
private GristTheHungerTide(final GristTheHungerTide card) {
|
||||||
|
|
|
||||||
|
|
@ -136,7 +136,7 @@ enum HakimLoreweaverCondition implements Condition {
|
||||||
.stream()
|
.stream()
|
||||||
.map(game::getPermanent)
|
.map(game::getPermanent)
|
||||||
.filter(Objects::nonNull)
|
.filter(Objects::nonNull)
|
||||||
.anyMatch(permanent -> permanent.hasSubtype(SubType.AURA, game));
|
.noneMatch(permanent -> permanent.hasSubtype(SubType.AURA, game));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
74
Mage.Sets/src/mage/cards/h/HaythamKenway.java
Normal file
74
Mage.Sets/src/mage/cards/h/HaythamKenway.java
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
package mage.cards.h;
|
||||||
|
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||||
|
import mage.abilities.common.SimpleStaticAbility;
|
||||||
|
import mage.abilities.effects.common.ExileUntilSourceLeavesEffect;
|
||||||
|
import mage.abilities.effects.common.continuous.BoostControlledEffect;
|
||||||
|
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
|
||||||
|
import mage.abilities.keyword.ProtectionAbility;
|
||||||
|
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.filter.FilterCard;
|
||||||
|
import mage.filter.common.FilterCreaturePermanent;
|
||||||
|
import mage.target.common.TargetCreaturePermanent;
|
||||||
|
import mage.target.targetadjustment.ForEachOpponentTargetsAdjuster;
|
||||||
|
import mage.target.targetpointer.EachTargetPointer;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author PurpleCrowbar
|
||||||
|
*/
|
||||||
|
public final class HaythamKenway extends CardImpl {
|
||||||
|
|
||||||
|
private static final FilterCard filter = new FilterCard("Assassins");
|
||||||
|
private static final FilterCreaturePermanent filter2 = new FilterCreaturePermanent(SubType.KNIGHT, "Knights");
|
||||||
|
|
||||||
|
static {
|
||||||
|
filter.add(SubType.ASSASSIN.getPredicate());
|
||||||
|
}
|
||||||
|
|
||||||
|
public HaythamKenway(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}{U}");
|
||||||
|
this.supertype.add(SuperType.LEGENDARY);
|
||||||
|
this.subtype.add(SubType.HUMAN, SubType.KNIGHT);
|
||||||
|
this.power = new MageInt(3);
|
||||||
|
this.toughness = new MageInt(3);
|
||||||
|
|
||||||
|
// Protection from Assassins
|
||||||
|
this.addAbility(new ProtectionAbility(filter));
|
||||||
|
|
||||||
|
// Other Knights you control get +2/+2 and have protection from Assassins.
|
||||||
|
Ability ability = new SimpleStaticAbility(new BoostControlledEffect(
|
||||||
|
2, 2, Duration.WhileOnBattlefield, filter2, true
|
||||||
|
));
|
||||||
|
ability.addEffect(new GainAbilityControlledEffect(
|
||||||
|
new ProtectionAbility(filter), Duration.WhileOnBattlefield, filter2, true
|
||||||
|
).setText("and have protection from Assassins"));
|
||||||
|
this.addAbility(ability);
|
||||||
|
|
||||||
|
// When Haytham Kenway enters, for each opponent, exile up to one target creature that player controls until Haytham Kenway leaves the battlefield.
|
||||||
|
Ability ability2 = new EntersBattlefieldTriggeredAbility(new ExileUntilSourceLeavesEffect()
|
||||||
|
.setTargetPointer(new EachTargetPointer())
|
||||||
|
.setText("for each opponent, exile up to one target creature that player controls until {this} leaves the battlefield")
|
||||||
|
);
|
||||||
|
ability2.addTarget(new TargetCreaturePermanent(0, 1));
|
||||||
|
ability2.setTargetAdjuster(new ForEachOpponentTargetsAdjuster());
|
||||||
|
this.addAbility(ability2);
|
||||||
|
}
|
||||||
|
|
||||||
|
private HaythamKenway(final HaythamKenway card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HaythamKenway copy() {
|
||||||
|
return new HaythamKenway(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
40
Mage.Sets/src/mage/cards/i/InevitableDefeat.java
Normal file
40
Mage.Sets/src/mage/cards/i/InevitableDefeat.java
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
package mage.cards.i;
|
||||||
|
|
||||||
|
import mage.abilities.common.CantBeCounteredSourceAbility;
|
||||||
|
import mage.abilities.effects.common.ExileTargetEffect;
|
||||||
|
import mage.abilities.effects.common.GainLifeEffect;
|
||||||
|
import mage.abilities.effects.common.LoseLifeTargetControllerEffect;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.target.common.TargetNonlandPermanent;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public final class InevitableDefeat extends CardImpl {
|
||||||
|
|
||||||
|
public InevitableDefeat(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{R}{W}{B}");
|
||||||
|
|
||||||
|
// This spell can't be countered.
|
||||||
|
this.addAbility(new CantBeCounteredSourceAbility());
|
||||||
|
|
||||||
|
// Exile target nonland permanent. Its controller loses 3 life and you gain 3 life.
|
||||||
|
this.getSpellAbility().addEffect(new ExileTargetEffect());
|
||||||
|
this.getSpellAbility().addEffect(new LoseLifeTargetControllerEffect(3));
|
||||||
|
this.getSpellAbility().addEffect(new GainLifeEffect(3).concatBy("and"));
|
||||||
|
this.getSpellAbility().addTarget(new TargetNonlandPermanent());
|
||||||
|
}
|
||||||
|
|
||||||
|
private InevitableDefeat(final InevitableDefeat card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InevitableDefeat copy() {
|
||||||
|
return new InevitableDefeat(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
40
Mage.Sets/src/mage/cards/j/JumboCactuar.java
Normal file
40
Mage.Sets/src/mage/cards/j/JumboCactuar.java
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
package mage.cards.j;
|
||||||
|
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.abilities.common.AttacksTriggeredAbility;
|
||||||
|
import mage.abilities.effects.common.continuous.BoostSourceEffect;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.Duration;
|
||||||
|
import mage.constants.SubType;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public final class JumboCactuar extends CardImpl {
|
||||||
|
|
||||||
|
public JumboCactuar(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{G}{G}");
|
||||||
|
|
||||||
|
this.subtype.add(SubType.PLANT);
|
||||||
|
this.power = new MageInt(1);
|
||||||
|
this.toughness = new MageInt(7);
|
||||||
|
|
||||||
|
// 10,000 Needles -- Whenever this creature attacks, it gets +9999/+0 until end of turn.
|
||||||
|
this.addAbility(new AttacksTriggeredAbility(
|
||||||
|
new BoostSourceEffect(9999, 0, Duration.EndOfTurn, "it")
|
||||||
|
).withFlavorWord("10,000 Needles"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private JumboCactuar(final JumboCactuar card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JumboCactuar copy() {
|
||||||
|
return new JumboCactuar(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package mage.cards.k;
|
package mage.cards.k;
|
||||||
|
|
||||||
import mage.abilities.effects.common.search.SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect;
|
import mage.abilities.effects.common.search.SearchLibraryPutOntoBattlefieldTappedRestInHandEffect;
|
||||||
import mage.cards.*;
|
import mage.cards.*;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.SubType;
|
import mage.constants.SubType;
|
||||||
|
|
@ -19,7 +19,7 @@ public final class KodamasReach extends CardImpl {
|
||||||
this.subtype.add(SubType.ARCANE);
|
this.subtype.add(SubType.ARCANE);
|
||||||
|
|
||||||
// Search your library for up to two basic land cards, reveal those cards, put one onto the battlefield tapped and the other into your hand, then shuffle.
|
// Search your library for up to two basic land cards, reveal those cards, put one onto the battlefield tapped and the other into your hand, then shuffle.
|
||||||
this.getSpellAbility().addEffect(new SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect(
|
this.getSpellAbility().addEffect(new SearchLibraryPutOntoBattlefieldTappedRestInHandEffect(
|
||||||
new TargetCardInLibrary(0, 2, StaticFilters.FILTER_CARD_BASIC_LANDS)));
|
new TargetCardInLibrary(0, 2, StaticFilters.FILTER_CARD_BASIC_LANDS)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,12 @@
|
||||||
package mage.cards.l;
|
package mage.cards.l;
|
||||||
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.dynamicvalue.common.InstantAndSorceryCastThisTurn;
|
||||||
import mage.abilities.dynamicvalue.DynamicValue;
|
|
||||||
import mage.abilities.dynamicvalue.IntPlusDynamicValue;
|
|
||||||
import mage.abilities.effects.Effect;
|
|
||||||
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
||||||
import mage.abilities.keyword.PlotAbility;
|
import mage.abilities.keyword.PlotAbility;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.game.Game;
|
|
||||||
import mage.watchers.common.SpellsCastWatcher;
|
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -20,15 +14,14 @@ import java.util.UUID;
|
||||||
*/
|
*/
|
||||||
public final class LockAndLoad extends CardImpl {
|
public final class LockAndLoad extends CardImpl {
|
||||||
|
|
||||||
private static final DynamicValue xValue = new IntPlusDynamicValue(1, LockAndLoadValue.instance);
|
|
||||||
|
|
||||||
public LockAndLoad(UUID ownerId, CardSetInfo setInfo) {
|
public LockAndLoad(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{U}");
|
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{U}");
|
||||||
|
|
||||||
// Draw a card, then draw a card for each other instant and sorcery spell you've cast this turn.
|
// Draw a card, then draw a card for each other instant and sorcery spell you've cast this turn.
|
||||||
this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(xValue)
|
this.getSpellAbility()
|
||||||
|
.addHint(InstantAndSorceryCastThisTurn.YOU.getHint())
|
||||||
|
.addEffect(new DrawCardSourceControllerEffect(InstantAndSorceryCastThisTurn.YOU)
|
||||||
.setText("Draw a card, then draw a card for each other instant and sorcery spell you've cast this turn"));
|
.setText("Draw a card, then draw a card for each other instant and sorcery spell you've cast this turn"));
|
||||||
|
|
||||||
// Plot {3}{U}
|
// Plot {3}{U}
|
||||||
this.addAbility(new PlotAbility("{3}{U}"));
|
this.addAbility(new PlotAbility("{3}{U}"));
|
||||||
}
|
}
|
||||||
|
|
@ -41,37 +34,4 @@ public final class LockAndLoad extends CardImpl {
|
||||||
public LockAndLoad copy() {
|
public LockAndLoad copy() {
|
||||||
return new LockAndLoad(this);
|
return new LockAndLoad(this);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
enum LockAndLoadValue implements DynamicValue {
|
|
||||||
instance;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int calculate(Game game, Ability sourceAbility, Effect effect) {
|
|
||||||
SpellsCastWatcher watcher = game.getState().getWatcher(SpellsCastWatcher.class);
|
|
||||||
return watcher == null ? 0 :
|
|
||||||
watcher.getSpellsCastThisTurn(sourceAbility.getControllerId())
|
|
||||||
.stream()
|
|
||||||
.filter(Objects::nonNull)
|
|
||||||
.filter(s -> s.isInstantOrSorcery(game))
|
|
||||||
.filter(s -> !s.getSourceId().equals(sourceAbility.getSourceId())
|
|
||||||
|| s.getZoneChangeCounter(game) != sourceAbility.getSourceObjectZoneChangeCounter())
|
|
||||||
.mapToInt(x -> 1)
|
|
||||||
.sum();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public LockAndLoadValue copy() {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "X";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getMessage() {
|
|
||||||
return "Number of other instant and sorcery spell you've cast this turn";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -2,7 +2,6 @@ package mage.cards.m;
|
||||||
|
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.Mode;
|
|
||||||
import mage.abilities.SpellAbility;
|
import mage.abilities.SpellAbility;
|
||||||
import mage.abilities.common.SimpleActivatedAbility;
|
import mage.abilities.common.SimpleActivatedAbility;
|
||||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
|
|
@ -17,8 +16,8 @@ import mage.filter.predicate.ObjectSourcePlayerPredicate;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.game.stack.Spell;
|
import mage.game.stack.Spell;
|
||||||
import mage.target.Target;
|
|
||||||
import mage.target.TargetSpell;
|
import mage.target.TargetSpell;
|
||||||
|
import mage.util.CardUtil;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
|
@ -69,13 +68,10 @@ enum MistfolkPredicate implements ObjectSourcePlayerPredicate<Spell> {
|
||||||
if (sourceObject == null || input.getObject() == null) {
|
if (sourceObject == null || input.getObject() == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (SpellAbility spellAbility : input.getObject().getSpellAbilities()) {
|
for (SpellAbility spellAbility : input.getObject().getSpellAbilities()) {
|
||||||
for (Mode mode : spellAbility.getModes().values()) {
|
if (CardUtil.getAllSelectedTargets(spellAbility, game).contains(input.getSourceId())) {
|
||||||
for (Target target : spellAbility.getTargets()) {
|
return true;
|
||||||
if (target.getTargets().contains(input.getSourceId())) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
50
Mage.Sets/src/mage/cards/m/MoxJasper.java
Normal file
50
Mage.Sets/src/mage/cards/m/MoxJasper.java
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
package mage.cards.m;
|
||||||
|
|
||||||
|
import mage.abilities.condition.Condition;
|
||||||
|
import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition;
|
||||||
|
import mage.abilities.costs.common.TapSourceCost;
|
||||||
|
import mage.abilities.effects.mana.AddManaOfAnyColorEffect;
|
||||||
|
import mage.abilities.hint.ConditionHint;
|
||||||
|
import mage.abilities.hint.Hint;
|
||||||
|
import mage.abilities.mana.ActivateIfConditionManaAbility;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.SubType;
|
||||||
|
import mage.constants.SuperType;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import mage.filter.common.FilterControlledPermanent;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public final class MoxJasper extends CardImpl {
|
||||||
|
|
||||||
|
private static final Condition condition = new PermanentsOnTheBattlefieldCondition(
|
||||||
|
new FilterControlledPermanent(SubType.DRAGON, "you control a Dragon")
|
||||||
|
);
|
||||||
|
private static final Hint hint = new ConditionHint(condition, "You control a Dragon");
|
||||||
|
|
||||||
|
public MoxJasper(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{0}");
|
||||||
|
|
||||||
|
this.supertype.add(SuperType.LEGENDARY);
|
||||||
|
|
||||||
|
// {T}: Add one mana of any color. Activate only if you control a Dragon.
|
||||||
|
this.addAbility(new ActivateIfConditionManaAbility(
|
||||||
|
Zone.BATTLEFIELD, new AddManaOfAnyColorEffect(1),
|
||||||
|
new TapSourceCost(), condition
|
||||||
|
).addHint(hint));
|
||||||
|
}
|
||||||
|
|
||||||
|
private MoxJasper(final MoxJasper card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MoxJasper copy() {
|
||||||
|
return new MoxJasper(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -32,7 +32,7 @@ public final class MuYanlingWindRider extends CardImpl {
|
||||||
= new FilterCreaturePermanent("creatures you control with flying");
|
= new FilterCreaturePermanent("creatures you control with flying");
|
||||||
|
|
||||||
static {
|
static {
|
||||||
filter.add(new AbilityPredicate(FlyingAbility.class));
|
filter2.add(new AbilityPredicate(FlyingAbility.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
public MuYanlingWindRider(UUID ownerId, CardSetInfo setInfo) {
|
public MuYanlingWindRider(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
|
|
||||||
81
Mage.Sets/src/mage/cards/n/NarsetJeskaiWaymaster.java
Normal file
81
Mage.Sets/src/mage/cards/n/NarsetJeskaiWaymaster.java
Normal file
|
|
@ -0,0 +1,81 @@
|
||||||
|
package mage.cards.n;
|
||||||
|
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.costs.common.DiscardHandCost;
|
||||||
|
import mage.abilities.dynamicvalue.DynamicValue;
|
||||||
|
import mage.abilities.effects.Effect;
|
||||||
|
import mage.abilities.effects.common.DoIfCostPaid;
|
||||||
|
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
||||||
|
import mage.abilities.hint.Hint;
|
||||||
|
import mage.abilities.hint.ValueHint;
|
||||||
|
import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.SubType;
|
||||||
|
import mage.constants.SuperType;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.watchers.common.CastSpellLastTurnWatcher;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public final class NarsetJeskaiWaymaster extends CardImpl {
|
||||||
|
|
||||||
|
public NarsetJeskaiWaymaster(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{U}{R}{W}");
|
||||||
|
|
||||||
|
this.supertype.add(SuperType.LEGENDARY);
|
||||||
|
this.subtype.add(SubType.HUMAN);
|
||||||
|
this.subtype.add(SubType.MONK);
|
||||||
|
this.power = new MageInt(3);
|
||||||
|
this.toughness = new MageInt(4);
|
||||||
|
|
||||||
|
// At the beginning of your end step, you may discard your hand. If you do, draw cards equal to the number of spells you've cast this turn.
|
||||||
|
this.addAbility(new BeginningOfEndStepTriggeredAbility(new DoIfCostPaid(
|
||||||
|
new DrawCardSourceControllerEffect(NarsetJeskaiWaymasterValue.instance), new DiscardHandCost()
|
||||||
|
)).addHint(NarsetJeskaiWaymasterValue.getHint()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private NarsetJeskaiWaymaster(final NarsetJeskaiWaymaster card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NarsetJeskaiWaymaster copy() {
|
||||||
|
return new NarsetJeskaiWaymaster(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum NarsetJeskaiWaymasterValue implements DynamicValue {
|
||||||
|
instance;
|
||||||
|
private static final Hint hint = new ValueHint("Spells you've cast this turn", instance);
|
||||||
|
|
||||||
|
public static Hint getHint() {
|
||||||
|
return hint;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int calculate(Game game, Ability sourceAbility, Effect effect) {
|
||||||
|
CastSpellLastTurnWatcher watcher = game.getState().getWatcher(CastSpellLastTurnWatcher.class);
|
||||||
|
return watcher == null ? 0 : watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(sourceAbility.getControllerId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NarsetJeskaiWaymasterValue copy() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getMessage() {
|
||||||
|
return "the number of spells you've cast this turn";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "1";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -5,7 +5,7 @@ import mage.abilities.common.SimpleActivatedAbility;
|
||||||
import mage.abilities.costs.common.SacrificeSourceCost;
|
import mage.abilities.costs.common.SacrificeSourceCost;
|
||||||
import mage.abilities.costs.common.TapSourceCost;
|
import mage.abilities.costs.common.TapSourceCost;
|
||||||
import mage.abilities.costs.mana.GenericManaCost;
|
import mage.abilities.costs.mana.GenericManaCost;
|
||||||
import mage.abilities.effects.common.search.SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect;
|
import mage.abilities.effects.common.search.SearchLibraryPutOntoBattlefieldTappedRestInHandEffect;
|
||||||
import mage.cards.*;
|
import mage.cards.*;
|
||||||
import mage.constants.*;
|
import mage.constants.*;
|
||||||
import mage.filter.FilterCard;
|
import mage.filter.FilterCard;
|
||||||
|
|
@ -32,7 +32,7 @@ public final class NavigationOrb extends CardImpl {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}");
|
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}");
|
||||||
|
|
||||||
// {2}, {T}, Sacrifice Navigation Orb: Search your library for up to two basic land cards and/or Gate cards, reveal those cards, put one onto the battlefield tapped and the other into your hand, then shuffle.
|
// {2}, {T}, Sacrifice Navigation Orb: Search your library for up to two basic land cards and/or Gate cards, reveal those cards, put one onto the battlefield tapped and the other into your hand, then shuffle.
|
||||||
Ability ability = new SimpleActivatedAbility(new SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect(
|
Ability ability = new SimpleActivatedAbility(new SearchLibraryPutOntoBattlefieldTappedRestInHandEffect(
|
||||||
new TargetCardInLibrary(0, 2, filter)), new GenericManaCost(2));
|
new TargetCardInLibrary(0, 2, filter)), new GenericManaCost(2));
|
||||||
ability.addCost(new TapSourceCost());
|
ability.addCost(new TapSourceCost());
|
||||||
ability.addCost(new SacrificeSourceCost());
|
ability.addCost(new SacrificeSourceCost());
|
||||||
|
|
|
||||||
99
Mage.Sets/src/mage/cards/n/NissaWorldsoulSpeaker.java
Normal file
99
Mage.Sets/src/mage/cards/n/NissaWorldsoulSpeaker.java
Normal file
|
|
@ -0,0 +1,99 @@
|
||||||
|
package mage.cards.n;
|
||||||
|
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.common.LandfallAbility;
|
||||||
|
import mage.abilities.common.SimpleStaticAbility;
|
||||||
|
import mage.abilities.condition.common.SourceIsSpellCondition;
|
||||||
|
import mage.abilities.costs.AlternativeCostSourceAbility;
|
||||||
|
import mage.abilities.costs.common.PayEnergyCost;
|
||||||
|
import mage.abilities.effects.ContinuousEffectImpl;
|
||||||
|
import mage.abilities.effects.common.counter.GetEnergyCountersControllerEffect;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.*;
|
||||||
|
import mage.filter.common.FilterPermanentCard;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.players.Player;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author PurpleCrowbar
|
||||||
|
*/
|
||||||
|
public final class NissaWorldsoulSpeaker extends CardImpl {
|
||||||
|
|
||||||
|
public NissaWorldsoulSpeaker(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}");
|
||||||
|
this.supertype.add(SuperType.LEGENDARY);
|
||||||
|
this.subtype.add(SubType.ELF, SubType.DRUID);
|
||||||
|
this.power = new MageInt(3);
|
||||||
|
this.toughness = new MageInt(3);
|
||||||
|
|
||||||
|
// Landfall -- Whenever a land you control enters, you get {E}{E}.
|
||||||
|
this.addAbility(new LandfallAbility(
|
||||||
|
new GetEnergyCountersControllerEffect(2), false
|
||||||
|
));
|
||||||
|
|
||||||
|
// You may pay eight {E} rather than pay the mana cost for permanent spells you cast.
|
||||||
|
this.addAbility(new SimpleStaticAbility(new NissaWorldsoulSpeakerEffect()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private NissaWorldsoulSpeaker(final NissaWorldsoulSpeaker card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NissaWorldsoulSpeaker copy() {
|
||||||
|
return new NissaWorldsoulSpeaker(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class NissaWorldsoulSpeakerEffect extends ContinuousEffectImpl {
|
||||||
|
|
||||||
|
private static final FilterPermanentCard filter = new FilterPermanentCard();
|
||||||
|
|
||||||
|
private final AlternativeCostSourceAbility alternativeCastingCostAbility = new AlternativeCostSourceAbility(
|
||||||
|
new PayEnergyCost(8), SourceIsSpellCondition.instance, null, filter, true
|
||||||
|
);
|
||||||
|
|
||||||
|
public NissaWorldsoulSpeakerEffect() {
|
||||||
|
super(Duration.WhileOnBattlefield, Outcome.Detriment);
|
||||||
|
staticText = "You may pay eight {E} rather than pay the mana cost for permanent spells you cast";
|
||||||
|
}
|
||||||
|
|
||||||
|
private NissaWorldsoulSpeakerEffect(final NissaWorldsoulSpeakerEffect effect) {
|
||||||
|
super(effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NissaWorldsoulSpeakerEffect copy() {
|
||||||
|
return new NissaWorldsoulSpeakerEffect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(Ability source, Game game, UUID activePlayerId) {
|
||||||
|
super.init(source, game, activePlayerId);
|
||||||
|
alternativeCastingCostAbility.setSourceId(source.getSourceId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
|
||||||
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
|
if (controller != null) {
|
||||||
|
controller.getAlternativeSourceCosts().add(alternativeCastingCostAbility);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasLayer(Layer layer) {
|
||||||
|
return layer == Layer.RulesEffects;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,7 +4,7 @@ package mage.cards.n;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import mage.abilities.condition.common.SpellMasteryCondition;
|
import mage.abilities.condition.common.SpellMasteryCondition;
|
||||||
import mage.abilities.decorator.ConditionalOneShotEffect;
|
import mage.abilities.decorator.ConditionalOneShotEffect;
|
||||||
import mage.abilities.effects.common.search.SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect;
|
import mage.abilities.effects.common.search.SearchLibraryPutOntoBattlefieldTappedRestInHandEffect;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
|
|
@ -32,8 +32,8 @@ public final class NissasPilgrimage extends CardImpl {
|
||||||
// Search your library for up to two basic Forest cards, reveal those cards, and put one onto the battlefield tapped and the rest into your hand. Then shuffle.
|
// Search your library for up to two basic Forest cards, reveal those cards, and put one onto the battlefield tapped and the rest into your hand. Then shuffle.
|
||||||
// <i>Spell Mastery</i> — If there are two or more instant and/or sorcery cards in your graveyard, search your library for up to three basic Forest cards instead of two.
|
// <i>Spell Mastery</i> — If there are two or more instant and/or sorcery cards in your graveyard, search your library for up to three basic Forest cards instead of two.
|
||||||
this.getSpellAbility().addEffect(new ConditionalOneShotEffect(
|
this.getSpellAbility().addEffect(new ConditionalOneShotEffect(
|
||||||
new SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect(new TargetCardInLibrary(0, 3, filter)),
|
new SearchLibraryPutOntoBattlefieldTappedRestInHandEffect(new TargetCardInLibrary(0, 3, filter)),
|
||||||
new SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect(new TargetCardInLibrary(0, 2, filter)),
|
new SearchLibraryPutOntoBattlefieldTappedRestInHandEffect(new TargetCardInLibrary(0, 2, filter)),
|
||||||
SpellMasteryCondition.instance,
|
SpellMasteryCondition.instance,
|
||||||
"Search your library for up to two basic Forest cards, reveal those cards, and put one onto the battlefield tapped and the rest into your hand. Then shuffle."
|
"Search your library for up to two basic Forest cards, reveal those cards, and put one onto the battlefield tapped and the rest into your hand. Then shuffle."
|
||||||
+ "<br><i>Spell mastery</i> — If there are two or more instant and/or sorcery cards in your graveyard, search your library for up to three basic Forest cards instead of two."));
|
+ "<br><i>Spell mastery</i> — If there are two or more instant and/or sorcery cards in your graveyard, search your library for up to three basic Forest cards instead of two."));
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||||
import mage.abilities.dynamicvalue.DynamicValue;
|
import mage.abilities.dynamicvalue.DynamicValue;
|
||||||
import mage.abilities.effects.Effect;
|
import mage.abilities.effects.Effect;
|
||||||
import mage.abilities.effects.common.DamageTargetEffect;
|
import mage.abilities.effects.common.DamageTargetEffect;
|
||||||
|
import mage.abilities.hint.ValueHint;
|
||||||
import mage.abilities.keyword.CascadeAbility;
|
import mage.abilities.keyword.CascadeAbility;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
|
|
@ -38,6 +39,7 @@ public final class NoiseMarine extends CardImpl {
|
||||||
new DamageTargetEffect(NoiseMarineValue.instance, "it")
|
new DamageTargetEffect(NoiseMarineValue.instance, "it")
|
||||||
);
|
);
|
||||||
ability.addTarget(new TargetAnyTarget());
|
ability.addTarget(new TargetAnyTarget());
|
||||||
|
ability.addHint(new ValueHint("Number of spells you've cast this turn", NoiseMarineValue.instance));
|
||||||
this.addAbility(ability.withFlavorWord("Sonic Blaster"));
|
this.addAbility(ability.withFlavorWord("Sonic Blaster"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,7 @@ class NotDeadAfterAllEffect extends OneShotEffect {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
player.moveCards(card, Zone.BATTLEFIELD, source, game, true, false, false, null);
|
player.moveCards(card, Zone.BATTLEFIELD, source, game, true, false, true, null);
|
||||||
Permanent permanent = game.getPermanent(card.getId());
|
Permanent permanent = game.getPermanent(card.getId());
|
||||||
if (permanent == null) {
|
if (permanent == null) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package mage.cards.p;
|
package mage.cards.p;
|
||||||
|
|
||||||
import mage.abilities.effects.Effect;
|
import mage.abilities.effects.Effect;
|
||||||
import mage.abilities.effects.common.search.SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect;
|
import mage.abilities.effects.common.search.SearchLibraryPutOntoBattlefieldTappedRestInHandEffect;
|
||||||
import mage.abilities.effects.keyword.ScryEffect;
|
import mage.abilities.effects.keyword.ScryEffect;
|
||||||
import mage.cards.*;
|
import mage.cards.*;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
|
|
@ -19,7 +19,7 @@ public final class Peregrination extends CardImpl {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{G}");
|
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{G}");
|
||||||
|
|
||||||
// Search your library for up to two basic land cards, reveal those cards, and put one onto the battlefield tapped and the other into your hand. Shuffle, then scry 1.
|
// Search your library for up to two basic land cards, reveal those cards, and put one onto the battlefield tapped and the other into your hand. Shuffle, then scry 1.
|
||||||
this.getSpellAbility().addEffect(new SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect(
|
this.getSpellAbility().addEffect(new SearchLibraryPutOntoBattlefieldTappedRestInHandEffect(
|
||||||
new TargetCardInLibrary(0, 2, StaticFilters.FILTER_CARD_BASIC_LANDS))
|
new TargetCardInLibrary(0, 2, StaticFilters.FILTER_CARD_BASIC_LANDS))
|
||||||
.setText("search your library for up to two basic land cards, reveal those cards, and put one onto the battlefield tapped and the other into your hand. Shuffle"));
|
.setText("search your library for up to two basic land cards, reveal those cards, and put one onto the battlefield tapped and the other into your hand. Shuffle"));
|
||||||
Effect effect = new ScryEffect(1);
|
Effect effect = new ScryEffect(1);
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.filter.FilterCard;
|
import mage.filter.FilterCard;
|
||||||
import mage.filter.predicate.Predicates;
|
import mage.filter.common.FilterPermanentCard;
|
||||||
import mage.target.common.TargetCardInYourGraveyard;
|
import mage.target.common.TargetCardInYourGraveyard;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -17,16 +17,7 @@ import mage.target.common.TargetCardInYourGraveyard;
|
||||||
*/
|
*/
|
||||||
public final class ProfoundJourney extends CardImpl {
|
public final class ProfoundJourney extends CardImpl {
|
||||||
|
|
||||||
private static final FilterCard filter = new FilterCard("permanent card from your graveyard");
|
private static final FilterCard filter = new FilterPermanentCard("permanent card from your graveyard");
|
||||||
|
|
||||||
static {
|
|
||||||
filter.add(Predicates.or(
|
|
||||||
CardType.ARTIFACT.getPredicate(),
|
|
||||||
CardType.CREATURE.getPredicate(),
|
|
||||||
CardType.ENCHANTMENT.getPredicate(),
|
|
||||||
CardType.LAND.getPredicate(),
|
|
||||||
CardType.PLANESWALKER.getPredicate()));
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProfoundJourney(UUID ownerId, CardSetInfo setInfo) {
|
public ProfoundJourney(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{5}{W}{W}");
|
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{5}{W}{W}");
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,24 @@
|
||||||
package mage.cards.r;
|
package mage.cards.r;
|
||||||
|
|
||||||
import mage.MageObjectReference;
|
import mage.MageObjectReference;
|
||||||
import mage.abilities.Ability;
|
|
||||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||||
import mage.abilities.common.SimpleStaticAbility;
|
import mage.abilities.common.SimpleStaticAbility;
|
||||||
import mage.abilities.condition.Condition;
|
|
||||||
import mage.abilities.effects.ContinuousEffectImpl;
|
|
||||||
import mage.abilities.effects.common.CreateTokenEffect;
|
import mage.abilities.effects.common.CreateTokenEffect;
|
||||||
|
import mage.abilities.effects.common.continuous.GainAbilityControlledSpellsEffect;
|
||||||
import mage.abilities.keyword.CascadeAbility;
|
import mage.abilities.keyword.CascadeAbility;
|
||||||
|
import mage.cards.Card;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.*;
|
import mage.constants.*;
|
||||||
|
import mage.filter.common.FilterNonlandCard;
|
||||||
|
import mage.filter.predicate.ObjectSourcePlayer;
|
||||||
|
import mage.filter.predicate.ObjectSourcePlayerPredicate;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.GameEvent;
|
import mage.game.events.GameEvent;
|
||||||
|
import mage.game.permanent.Permanent;
|
||||||
import mage.game.permanent.token.TreasureToken;
|
import mage.game.permanent.token.TreasureToken;
|
||||||
import mage.game.stack.Spell;
|
import mage.game.stack.Spell;
|
||||||
import mage.game.stack.StackObject;
|
import mage.game.stack.StackObject;
|
||||||
import mage.players.Player;
|
|
||||||
import mage.watchers.Watcher;
|
import mage.watchers.Watcher;
|
||||||
import mage.watchers.common.ManaPaidSourceWatcher;
|
import mage.watchers.common.ManaPaidSourceWatcher;
|
||||||
|
|
||||||
|
|
@ -25,10 +27,18 @@ import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Alex-Vasile
|
* @author Alex-Vasile, Susucr
|
||||||
*/
|
*/
|
||||||
public class RainOfRiches extends CardImpl {
|
public class RainOfRiches extends CardImpl {
|
||||||
|
|
||||||
|
|
||||||
|
private static final FilterNonlandCard filter =
|
||||||
|
new FilterNonlandCard("The first spell you cast each turn that mana from a Treasure was spent to cast");
|
||||||
|
|
||||||
|
static {
|
||||||
|
filter.add(RainOfRichesPredicate.instance);
|
||||||
|
}
|
||||||
|
|
||||||
public RainOfRiches(UUID ownerId, CardSetInfo setInfo) {
|
public RainOfRiches(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{R}{R}");
|
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{R}{R}");
|
||||||
|
|
||||||
|
|
@ -40,7 +50,7 @@ public class RainOfRiches extends CardImpl {
|
||||||
// You may cast it without paying its mana cost.
|
// You may cast it without paying its mana cost.
|
||||||
// Put the exiled cards on the bottom of your library in a random order.)
|
// Put the exiled cards on the bottom of your library in a random order.)
|
||||||
this.addAbility(
|
this.addAbility(
|
||||||
new SimpleStaticAbility(new RainOfRichesGainsCascadeEffect()),
|
new SimpleStaticAbility(new GainAbilityControlledSpellsEffect(new CascadeAbility(false), filter)),
|
||||||
new RainOfRichesWatcher()
|
new RainOfRichesWatcher()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -55,65 +65,20 @@ public class RainOfRiches extends CardImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class RainOfRichesGainsCascadeEffect extends ContinuousEffectImpl {
|
enum RainOfRichesPredicate implements ObjectSourcePlayerPredicate<Card> {
|
||||||
|
|
||||||
private final Ability cascadeAbility = new CascadeAbility();
|
|
||||||
|
|
||||||
RainOfRichesGainsCascadeEffect() {
|
|
||||||
super(Duration.WhileOnBattlefield, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility);
|
|
||||||
this.staticText =
|
|
||||||
"The first spell you cast each turn that mana from a Treasure was spent to cast has cascade. " +
|
|
||||||
"<i>(When you cast the spell, exile cards from the top of your library until you exile a nonland card that costs less. " +
|
|
||||||
"You may cast it without paying its mana cost. " +
|
|
||||||
"Put the exiled cards on the bottom of your library in a random order.)</i>";
|
|
||||||
}
|
|
||||||
|
|
||||||
private RainOfRichesGainsCascadeEffect(final RainOfRichesGainsCascadeEffect effect) {
|
|
||||||
super(effect);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean apply(Game game, Ability source) {
|
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
|
||||||
RainOfRichesWatcher watcher = game.getState().getWatcher(RainOfRichesWatcher.class);
|
|
||||||
if (controller == null || watcher == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (StackObject stackObject : game.getStack()) {
|
|
||||||
// Only spells cast, so no copies of spells
|
|
||||||
if ((stackObject instanceof Spell)
|
|
||||||
&& !stackObject.isCopy()
|
|
||||||
&& stackObject.isControlledBy(source.getControllerId())) {
|
|
||||||
Spell spell = (Spell) stackObject;
|
|
||||||
|
|
||||||
if (FirstSpellCastWithTreasureCondition.instance.apply(game, source)) {
|
|
||||||
game.getState().addOtherAbility(spell.getCard(), cascadeAbility);
|
|
||||||
return true; // TODO: I think this should return here as soon as it finds the first one.
|
|
||||||
// If it should, change WildMageSorcerer to also return early.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RainOfRichesGainsCascadeEffect copy() {
|
|
||||||
return new RainOfRichesGainsCascadeEffect(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum FirstSpellCastWithTreasureCondition implements Condition {
|
|
||||||
instance;
|
instance;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(ObjectSourcePlayer<Card> input, Game game) {
|
||||||
if (game.getStack().isEmpty()) {
|
Permanent sourcePermanent = input.getSource().getSourcePermanentOrLKI(game);
|
||||||
|
if (sourcePermanent == null || !sourcePermanent.getControllerId().equals(input.getPlayerId())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
RainOfRichesWatcher watcher = game.getState().getWatcher(RainOfRichesWatcher.class);
|
RainOfRichesWatcher watcher = game.getState().getWatcher(RainOfRichesWatcher.class);
|
||||||
StackObject so = game.getStack().getFirst();
|
Card card = input.getObject();
|
||||||
return watcher != null && RainOfRichesWatcher.checkSpell(so, game);
|
return watcher != null
|
||||||
|
&& card instanceof StackObject
|
||||||
|
&& watcher.checkSpell((Spell) card, game);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -127,7 +92,7 @@ class RainOfRichesWatcher extends Watcher {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void watch(GameEvent event, Game game) {
|
public void watch(GameEvent event, Game game) {
|
||||||
if (event.getType() != GameEvent.EventType.CAST_SPELL) {
|
if (event.getType() != GameEvent.EventType.SPELL_CAST) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Spell spell = game.getSpell(event.getSourceId());
|
Spell spell = game.getSpell(event.getSourceId());
|
||||||
|
|
@ -148,13 +113,15 @@ class RainOfRichesWatcher extends Watcher {
|
||||||
super.reset();
|
super.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean checkSpell(StackObject stackObject, Game game) {
|
boolean checkSpell(StackObject stackObject, Game game) {
|
||||||
if (stackObject.isCopy()
|
if (stackObject.isCopy()
|
||||||
|| !(stackObject instanceof Spell)) {
|
|| !(stackObject instanceof Spell)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
RainOfRichesWatcher watcher = game.getState().getWatcher(RainOfRichesWatcher.class);
|
if (playerMap.containsKey(stackObject.getControllerId())) {
|
||||||
return watcher.playerMap.containsKey(stackObject.getControllerId())
|
return playerMap.get(stackObject.getControllerId()).refersTo(((Spell) stackObject).getMainCard(), game);
|
||||||
&& watcher.playerMap.get(stackObject.getControllerId()).refersTo(((Spell) stackObject).getMainCard(), game);
|
} else {
|
||||||
|
return ManaPaidSourceWatcher.getTreasurePaid(stackObject.getId(), game) >= 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,8 @@ import mage.abilities.common.EntersBattlefieldAbility;
|
||||||
import mage.abilities.condition.Condition;
|
import mage.abilities.condition.Condition;
|
||||||
import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition;
|
import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition;
|
||||||
import mage.abilities.decorator.ConditionalOneShotEffect;
|
import mage.abilities.decorator.ConditionalOneShotEffect;
|
||||||
import mage.abilities.dynamicvalue.DynamicValue;
|
import mage.abilities.dynamicvalue.common.InstantAndSorceryCastThisTurn;
|
||||||
import mage.abilities.effects.AsThoughEffectImpl;
|
import mage.abilities.effects.AsThoughEffectImpl;
|
||||||
import mage.abilities.effects.Effect;
|
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.abilities.effects.common.DamageMultiEffect;
|
import mage.abilities.effects.common.DamageMultiEffect;
|
||||||
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
||||||
|
|
@ -34,9 +33,7 @@ import mage.game.Game;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.target.common.TargetAnyTargetAmount;
|
import mage.target.common.TargetAnyTargetAmount;
|
||||||
import mage.util.CardUtil;
|
import mage.util.CardUtil;
|
||||||
import mage.watchers.common.SpellsCastWatcher;
|
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
|
@ -67,9 +64,11 @@ public final class RalLeylineProdigy extends CardImpl {
|
||||||
|
|
||||||
// Ral, Leyline Prodigy enters the battlefield with an additional loyalty counter on him for each instant and sorcery spell you've cast this turn.
|
// Ral, Leyline Prodigy enters the battlefield with an additional loyalty counter on him for each instant and sorcery spell you've cast this turn.
|
||||||
this.addAbility(new EntersBattlefieldAbility(
|
this.addAbility(new EntersBattlefieldAbility(
|
||||||
new AddCountersSourceEffect(CounterType.LOYALTY.createInstance(), RalLeylineProdigyValue.instance, false)
|
new AddCountersSourceEffect(CounterType.LOYALTY.createInstance(), InstantAndSorceryCastThisTurn.YOU,
|
||||||
.setText("with an additional loyalty counter on him for each instant and sorcery spell you've cast this turn")
|
false)
|
||||||
));
|
.setText("with an additional loyalty counter on him for each instant and sorcery spell you've cast this turn"))
|
||||||
|
.addHint(InstantAndSorceryCastThisTurn.YOU.getHint())
|
||||||
|
);
|
||||||
|
|
||||||
// +1: Until your next turn, instant and sorcery spells you cast cost {1} less to cast.
|
// +1: Until your next turn, instant and sorcery spells you cast cost {1} less to cast.
|
||||||
this.addAbility(new LoyaltyAbility(new RalLeylineProdigyCostReductionEffect(), 1));
|
this.addAbility(new LoyaltyAbility(new RalLeylineProdigyCostReductionEffect(), 1));
|
||||||
|
|
@ -126,35 +125,6 @@ class RalLeylineProdigyCostReductionEffect extends OneShotEffect {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum RalLeylineProdigyValue implements DynamicValue {
|
|
||||||
instance;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int calculate(Game game, Ability sourceAbility, Effect effect) {
|
|
||||||
SpellsCastWatcher watcher = game.getState().getWatcher(SpellsCastWatcher.class);
|
|
||||||
if (watcher == null) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return watcher
|
|
||||||
.getSpellsCastThisTurn(sourceAbility.getControllerId())
|
|
||||||
.stream()
|
|
||||||
.filter(Objects::nonNull)
|
|
||||||
.filter(spell -> spell.isInstantOrSorcery(game))
|
|
||||||
.mapToInt(spell -> 1)
|
|
||||||
.sum();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RalLeylineProdigyValue copy() {
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getMessage() {
|
|
||||||
return "instant and sorcery spell you've cast this turn";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class RalLeylineProdigyMinusEightEffect extends OneShotEffect {
|
class RalLeylineProdigyMinusEightEffect extends OneShotEffect {
|
||||||
|
|
||||||
RalLeylineProdigyMinusEightEffect() {
|
RalLeylineProdigyMinusEightEffect() {
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package mage.cards.r;
|
||||||
|
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.dynamicvalue.common.InstantAndSorceryCastThisTurn;
|
||||||
import mage.constants.Pronoun;
|
import mage.constants.Pronoun;
|
||||||
import mage.abilities.common.SimpleStaticAbility;
|
import mage.abilities.common.SimpleStaticAbility;
|
||||||
import mage.abilities.common.SpellCastControllerTriggeredAbility;
|
import mage.abilities.common.SpellCastControllerTriggeredAbility;
|
||||||
|
|
@ -45,7 +46,8 @@ public final class RalMonsoonMage extends CardImpl {
|
||||||
|
|
||||||
// Whenever you cast an instant or sorcery spell during your turn, flip a coin. If you lose the flip, Ral, Monsoon Mage deals 1 damage to you. If you win the flip, you may exile Ral. If you do, return him to the battlefield transformed under his owner control.
|
// Whenever you cast an instant or sorcery spell during your turn, flip a coin. If you lose the flip, Ral, Monsoon Mage deals 1 damage to you. If you win the flip, you may exile Ral. If you do, return him to the battlefield transformed under his owner control.
|
||||||
this.addAbility(new TransformAbility());
|
this.addAbility(new TransformAbility());
|
||||||
this.addAbility(new RalMonsoonMageTriggeredAbility());
|
this.addAbility(new RalMonsoonMageTriggeredAbility()
|
||||||
|
.addHint(InstantAndSorceryCastThisTurn.YOU.getHint()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private RalMonsoonMage(final RalMonsoonMage card) {
|
private RalMonsoonMage(final RalMonsoonMage card) {
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,17 @@
|
||||||
package mage.cards.r;
|
package mage.cards.r;
|
||||||
|
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.abilities.TriggeredAbilityImpl;
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.effects.Effect;
|
||||||
|
import mage.abilities.effects.common.CrewsVehicleSourceTriggeredAbility;
|
||||||
import mage.abilities.effects.common.continuous.BoostTargetEffect;
|
import mage.abilities.effects.common.continuous.BoostTargetEffect;
|
||||||
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
|
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
|
||||||
import mage.abilities.keyword.TrampleAbility;
|
import mage.abilities.keyword.TrampleAbility;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.Duration;
|
||||||
import mage.constants.SubType;
|
import mage.constants.SubType;
|
||||||
import mage.constants.Zone;
|
|
||||||
import mage.game.Game;
|
|
||||||
import mage.game.events.GameEvent;
|
|
||||||
import mage.target.targetpointer.FixedTarget;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
|
@ -30,7 +29,14 @@ public final class RecklessVelocitaur extends CardImpl {
|
||||||
this.toughness = new MageInt(3);
|
this.toughness = new MageInt(3);
|
||||||
|
|
||||||
// Whenever this creature saddles a Mount or crews a Vehicle during your main phase, that Mount or Vehicle gets +2/+0 and gains trample until end of turn.
|
// Whenever this creature saddles a Mount or crews a Vehicle during your main phase, that Mount or Vehicle gets +2/+0 and gains trample until end of turn.
|
||||||
this.addAbility(new RecklessVelocitaurTriggeredAbility());
|
|
||||||
|
Effect boostEffect = new BoostTargetEffect(2, 0, Duration.EndOfTurn)
|
||||||
|
.setText("that Mount or Vehicle gets +2/+0");
|
||||||
|
Effect abilityGainEffect = new GainAbilityTargetEffect(TrampleAbility.getInstance(), Duration.EndOfTurn)
|
||||||
|
.setText("and gains trample until end of turn");
|
||||||
|
Ability ability = new CrewsVehicleSourceTriggeredAbility(boostEffect, true, true);
|
||||||
|
ability.addEffect(abilityGainEffect);
|
||||||
|
this.addAbility(ability);
|
||||||
}
|
}
|
||||||
|
|
||||||
private RecklessVelocitaur(final RecklessVelocitaur card) {
|
private RecklessVelocitaur(final RecklessVelocitaur card) {
|
||||||
|
|
@ -42,43 +48,3 @@ public final class RecklessVelocitaur extends CardImpl {
|
||||||
return new RecklessVelocitaur(this);
|
return new RecklessVelocitaur(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class RecklessVelocitaurTriggeredAbility extends TriggeredAbilityImpl {
|
|
||||||
|
|
||||||
RecklessVelocitaurTriggeredAbility() {
|
|
||||||
super(Zone.BATTLEFIELD, new BoostTargetEffect(2, 0).setText("that Mount or Vehicle gets +2/+0"));
|
|
||||||
this.addEffect(new GainAbilityTargetEffect(TrampleAbility.getInstance()).setText("and gains trample until end of turn"));
|
|
||||||
this.setTriggerPhrase("Whenever {this} saddles a Mount or crews a Vehicle during your main phase, ");
|
|
||||||
}
|
|
||||||
|
|
||||||
private RecklessVelocitaurTriggeredAbility(final RecklessVelocitaurTriggeredAbility ability) {
|
|
||||||
super(ability);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RecklessVelocitaurTriggeredAbility copy() {
|
|
||||||
return new RecklessVelocitaurTriggeredAbility(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checkEventType(GameEvent event, Game game) {
|
|
||||||
switch (event.getType()) {
|
|
||||||
case SADDLED_MOUNT:
|
|
||||||
case CREWED_VEHICLE:
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checkTrigger(GameEvent event, Game game) {
|
|
||||||
if (!this.isControlledBy(game.getActivePlayerId())
|
|
||||||
|| !game.isMainPhase()
|
|
||||||
|| !event.getTargetId().equals(this.getSourceId())) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
this.getEffects().setTargetPointer(new FixedTarget(event.getSourceId()));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -2,23 +2,17 @@ package mage.cards.r;
|
||||||
|
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.dynamicvalue.common.InstantAndSorceryCastThisTurn;
|
||||||
import mage.abilities.triggers.BeginningOfCombatTriggeredAbility;
|
import mage.abilities.triggers.BeginningOfCombatTriggeredAbility;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.abilities.effects.common.CreateTokenCopyTargetEffect;
|
import mage.abilities.effects.common.CreateTokenCopyTargetEffect;
|
||||||
import mage.abilities.hint.Hint;
|
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.*;
|
import mage.constants.*;
|
||||||
import mage.filter.StaticFilters;
|
import mage.filter.StaticFilters;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.GameEvent;
|
|
||||||
import mage.game.stack.Spell;
|
|
||||||
import mage.target.TargetPermanent;
|
import mage.target.TargetPermanent;
|
||||||
import mage.util.CardUtil;
|
|
||||||
import mage.watchers.Watcher;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -40,7 +34,7 @@ public final class RionyaFireDancer extends CardImpl {
|
||||||
new RionyaFireDancerEffect()
|
new RionyaFireDancerEffect()
|
||||||
);
|
);
|
||||||
ability.addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_CREATURE_YOU_CONTROL));
|
ability.addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_CREATURE_YOU_CONTROL));
|
||||||
this.addAbility(ability.addHint(RionyaFireDancerHint.instance), new RionyaFireDancerWatcher());
|
this.addAbility(ability.addHint(InstantAndSorceryCastThisTurn.YOU.getHint()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private RionyaFireDancer(final RionyaFireDancer card) {
|
private RionyaFireDancer(final RionyaFireDancer card) {
|
||||||
|
|
@ -53,21 +47,6 @@ public final class RionyaFireDancer extends CardImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum RionyaFireDancerHint implements Hint {
|
|
||||||
instance;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getText(Game game, Ability ability) {
|
|
||||||
return "Instants and sorceries you've cast this turn: "
|
|
||||||
+ RionyaFireDancerWatcher.getValue(ability.getControllerId(), game);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RionyaFireDancerHint copy() {
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class RionyaFireDancerEffect extends OneShotEffect {
|
class RionyaFireDancerEffect extends OneShotEffect {
|
||||||
|
|
||||||
RionyaFireDancerEffect() {
|
RionyaFireDancerEffect() {
|
||||||
|
|
@ -90,41 +69,10 @@ class RionyaFireDancerEffect extends OneShotEffect {
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect(
|
CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect(
|
||||||
source.getControllerId(), null, true,
|
source.getControllerId(), null, true,
|
||||||
RionyaFireDancerWatcher.getValue(source.getControllerId(), game) + 1
|
InstantAndSorceryCastThisTurn.YOU.calculate(game, source, this) + 1
|
||||||
);
|
);
|
||||||
effect.apply(game, source);
|
effect.apply(game, source);
|
||||||
effect.exileTokensCreatedAtNextEndStep(game, source);
|
effect.exileTokensCreatedAtNextEndStep(game, source);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class RionyaFireDancerWatcher extends Watcher {
|
|
||||||
|
|
||||||
private final Map<UUID, Integer> playerMap = new HashMap<>();
|
|
||||||
|
|
||||||
RionyaFireDancerWatcher() {
|
|
||||||
super(WatcherScope.GAME);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void watch(GameEvent event, Game game) {
|
|
||||||
if (event.getType() != GameEvent.EventType.SPELL_CAST) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Spell spell = game.getSpell(event.getTargetId());
|
|
||||||
if (spell != null && spell.isInstantOrSorcery(game)) {
|
|
||||||
playerMap.compute(spell.getControllerId(), CardUtil::setOrIncrementValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void reset() {
|
|
||||||
super.reset();
|
|
||||||
playerMap.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
static int getValue(UUID playerId, Game game) {
|
|
||||||
RionyaFireDancerWatcher watcher = game.getState().getWatcher(RionyaFireDancerWatcher.class);
|
|
||||||
return watcher == null ? 0 : watcher.playerMap.getOrDefault(playerId, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
38
Mage.Sets/src/mage/cards/s/SazhsChocobo.java
Normal file
38
Mage.Sets/src/mage/cards/s/SazhsChocobo.java
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
package mage.cards.s;
|
||||||
|
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.abilities.common.LandfallAbility;
|
||||||
|
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.SubType;
|
||||||
|
import mage.counters.CounterType;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public final class SazhsChocobo extends CardImpl {
|
||||||
|
|
||||||
|
public SazhsChocobo(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}");
|
||||||
|
|
||||||
|
this.subtype.add(SubType.BIRD);
|
||||||
|
this.power = new MageInt(0);
|
||||||
|
this.toughness = new MageInt(1);
|
||||||
|
|
||||||
|
// Landfall -- Whenever a land you control enters, put a +1/+1 counter on this creature.
|
||||||
|
this.addAbility(new LandfallAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance())));
|
||||||
|
}
|
||||||
|
|
||||||
|
private SazhsChocobo(final SazhsChocobo card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SazhsChocobo copy() {
|
||||||
|
return new SazhsChocobo(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -8,6 +8,7 @@ import mage.abilities.effects.Effect;
|
||||||
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
||||||
import mage.abilities.effects.common.LoseLifeOpponentsEffect;
|
import mage.abilities.effects.common.LoseLifeOpponentsEffect;
|
||||||
import mage.abilities.effects.common.SacrificeAllEffect;
|
import mage.abilities.effects.common.SacrificeAllEffect;
|
||||||
|
import mage.abilities.hint.ValueHint;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
|
|
@ -22,7 +23,6 @@ import java.util.UUID;
|
||||||
* @author jimga150
|
* @author jimga150
|
||||||
*/
|
*/
|
||||||
public final class SeasonOfLoss extends CardImpl {
|
public final class SeasonOfLoss extends CardImpl {
|
||||||
|
|
||||||
public SeasonOfLoss(UUID ownerId, CardSetInfo setInfo) {
|
public SeasonOfLoss(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{B}{B}");
|
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{B}{B}");
|
||||||
|
|
||||||
|
|
@ -41,9 +41,11 @@ public final class SeasonOfLoss extends CardImpl {
|
||||||
this.getSpellAbility().addMode(mode2.withPawPrintValue(2));
|
this.getSpellAbility().addMode(mode2.withPawPrintValue(2));
|
||||||
|
|
||||||
// {P}{P}{P} -- Each opponent loses X life, where X is the number of creature cards in your graveyard.
|
// {P}{P}{P} -- Each opponent loses X life, where X is the number of creature cards in your graveyard.
|
||||||
Mode mode3 = new Mode(new LoseLifeOpponentsEffect(new CardsInControllerGraveyardCount(StaticFilters.FILTER_CARD_CREATURES))
|
DynamicValue creatureCardsInGraveyard = new CardsInControllerGraveyardCount(StaticFilters.FILTER_CARD_CREATURES);
|
||||||
|
Mode mode3 = new Mode(new LoseLifeOpponentsEffect(creatureCardsInGraveyard)
|
||||||
.setText("Each opponent loses X life, where X is the number of creature cards in your graveyard."));
|
.setText("Each opponent loses X life, where X is the number of creature cards in your graveyard."));
|
||||||
this.getSpellAbility().addMode(mode3.withPawPrintValue(3));
|
this.getSpellAbility().addMode(mode3.withPawPrintValue(3));
|
||||||
|
this.getSpellAbility().addHint(new ValueHint("Creature cards in your graveyard", creatureCardsInGraveyard));
|
||||||
}
|
}
|
||||||
|
|
||||||
private SeasonOfLoss(final SeasonOfLoss card) {
|
private SeasonOfLoss(final SeasonOfLoss card) {
|
||||||
|
|
|
||||||
64
Mage.Sets/src/mage/cards/s/ShikoParagonOfTheWay.java
Normal file
64
Mage.Sets/src/mage/cards/s/ShikoParagonOfTheWay.java
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
package mage.cards.s;
|
||||||
|
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||||
|
import mage.abilities.effects.common.ExileTargetCardCopyAndCastEffect;
|
||||||
|
import mage.abilities.keyword.FlyingAbility;
|
||||||
|
import mage.abilities.keyword.VigilanceAbility;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.ComparisonType;
|
||||||
|
import mage.constants.SubType;
|
||||||
|
import mage.constants.SuperType;
|
||||||
|
import mage.filter.FilterCard;
|
||||||
|
import mage.filter.common.FilterNonlandCard;
|
||||||
|
import mage.filter.predicate.mageobject.ManaValuePredicate;
|
||||||
|
import mage.target.common.TargetCardInYourGraveyard;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public final class ShikoParagonOfTheWay extends CardImpl {
|
||||||
|
|
||||||
|
private static final FilterCard filter = new FilterNonlandCard("nonland card with mana value 3 or less");
|
||||||
|
|
||||||
|
static {
|
||||||
|
filter.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, 4));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShikoParagonOfTheWay(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}{R}{W}");
|
||||||
|
|
||||||
|
this.supertype.add(SuperType.LEGENDARY);
|
||||||
|
this.subtype.add(SubType.SPIRIT);
|
||||||
|
this.subtype.add(SubType.DRAGON);
|
||||||
|
this.power = new MageInt(4);
|
||||||
|
this.toughness = new MageInt(5);
|
||||||
|
|
||||||
|
// Flying
|
||||||
|
this.addAbility(FlyingAbility.getInstance());
|
||||||
|
|
||||||
|
// Vigilance
|
||||||
|
this.addAbility(VigilanceAbility.getInstance());
|
||||||
|
|
||||||
|
// When Shiko enters, exile target nonland card with mana value 3 or less from your graveyard. Copy it, then you may cast the copy without paying its mana cost.
|
||||||
|
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileTargetCardCopyAndCastEffect(true)
|
||||||
|
.setText("exile target nonland card with mana value 3 or less from your graveyard. " +
|
||||||
|
"Copy it, then you may cast the copy without paying its mana cost"));
|
||||||
|
ability.addTarget(new TargetCardInYourGraveyard(filter));
|
||||||
|
this.addAbility(ability);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ShikoParagonOfTheWay(final ShikoParagonOfTheWay card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ShikoParagonOfTheWay copy() {
|
||||||
|
return new ShikoParagonOfTheWay(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package mage.cards.s;
|
package mage.cards.s;
|
||||||
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.dynamicvalue.common.InstantAndSorceryCastThisTurn;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.abilities.effects.common.CastSourceTriggeredAbility;
|
import mage.abilities.effects.common.CastSourceTriggeredAbility;
|
||||||
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
|
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
|
||||||
|
|
@ -17,7 +18,6 @@ import mage.game.stack.Spell;
|
||||||
import mage.target.common.TargetCreaturePermanent;
|
import mage.target.common.TargetCreaturePermanent;
|
||||||
import mage.watchers.common.SpellsCastWatcher;
|
import mage.watchers.common.SpellsCastWatcher;
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -29,7 +29,8 @@ public final class ShowOfConfidence extends CardImpl {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}");
|
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}");
|
||||||
|
|
||||||
// When you cast this spell, copy it for each other instant or sorcery spell you've cast this turn. You may choose new targets for the copies.
|
// When you cast this spell, copy it for each other instant or sorcery spell you've cast this turn. You may choose new targets for the copies.
|
||||||
this.addAbility(new CastSourceTriggeredAbility(new ShowOfConfidenceEffect()));
|
this.addAbility(new CastSourceTriggeredAbility(new ShowOfConfidenceEffect())
|
||||||
|
.addHint(InstantAndSorceryCastThisTurn.YOU.getHint()));
|
||||||
|
|
||||||
// Put a +1/+1 counter on target creature. It gains vigilance until end of turn.
|
// Put a +1/+1 counter on target creature. It gains vigilance until end of turn.
|
||||||
this.getSpellAbility().addEffect(new AddCountersTargetEffect(CounterType.P1P1.createInstance()));
|
this.getSpellAbility().addEffect(new AddCountersTargetEffect(CounterType.P1P1.createInstance()));
|
||||||
|
|
@ -73,14 +74,7 @@ class ShowOfConfidenceEffect extends OneShotEffect {
|
||||||
if (spell == null || watcher == null) {
|
if (spell == null || watcher == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int copies = watcher.getSpellsCastThisTurn(source.getControllerId())
|
int copies = InstantAndSorceryCastThisTurn.YOU.calculate(game, source, this) - 1;
|
||||||
.stream()
|
|
||||||
.filter(Objects::nonNull)
|
|
||||||
.filter(spell1 -> spell1.isInstantOrSorcery(game))
|
|
||||||
.filter(s -> !s.getSourceId().equals(source.getSourceId())
|
|
||||||
|| s.getZoneChangeCounter(game) != source.getSourceObjectZoneChangeCounter())
|
|
||||||
.mapToInt(x -> 1)
|
|
||||||
.sum();
|
|
||||||
if (copies > 0) {
|
if (copies > 0) {
|
||||||
spell.createCopyOnStack(game, source, source.getControllerId(), true, copies);
|
spell.createCopyOnStack(game, source, source.getControllerId(), true, copies);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
45
Mage.Sets/src/mage/cards/s/SkirmishRhino.java
Normal file
45
Mage.Sets/src/mage/cards/s/SkirmishRhino.java
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
package mage.cards.s;
|
||||||
|
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||||
|
import mage.abilities.effects.common.GainLifeEffect;
|
||||||
|
import mage.abilities.effects.common.LoseLifeOpponentsEffect;
|
||||||
|
import mage.abilities.keyword.TrampleAbility;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.SubType;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public final class SkirmishRhino extends CardImpl {
|
||||||
|
|
||||||
|
public SkirmishRhino(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}{B}{G}");
|
||||||
|
|
||||||
|
this.subtype.add(SubType.RHINO);
|
||||||
|
this.power = new MageInt(3);
|
||||||
|
this.toughness = new MageInt(4);
|
||||||
|
|
||||||
|
// Trample
|
||||||
|
this.addAbility(TrampleAbility.getInstance());
|
||||||
|
|
||||||
|
// When this creature enters, each opponent loses 2 life and you gain 2 life.
|
||||||
|
Ability ability = new EntersBattlefieldTriggeredAbility(new LoseLifeOpponentsEffect(2));
|
||||||
|
ability.addEffect(new GainLifeEffect(2).concatBy("and"));
|
||||||
|
this.addAbility(ability);
|
||||||
|
}
|
||||||
|
|
||||||
|
private SkirmishRhino(final SkirmishRhino card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SkirmishRhino copy() {
|
||||||
|
return new SkirmishRhino(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
91
Mage.Sets/src/mage/cards/s/SmileAtDeath.java
Normal file
91
Mage.Sets/src/mage/cards/s/SmileAtDeath.java
Normal file
|
|
@ -0,0 +1,91 @@
|
||||||
|
package mage.cards.s;
|
||||||
|
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.effects.OneShotEffect;
|
||||||
|
import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.cards.Cards;
|
||||||
|
import mage.cards.CardsImpl;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.ComparisonType;
|
||||||
|
import mage.constants.Outcome;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import mage.counters.CounterType;
|
||||||
|
import mage.filter.FilterCard;
|
||||||
|
import mage.filter.common.FilterCreatureCard;
|
||||||
|
import mage.filter.predicate.mageobject.PowerPredicate;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.players.Player;
|
||||||
|
import mage.target.common.TargetCardInYourGraveyard;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public final class SmileAtDeath extends CardImpl {
|
||||||
|
|
||||||
|
private static final FilterCard filter = new FilterCreatureCard("creature cards with power 2 or less");
|
||||||
|
|
||||||
|
static {
|
||||||
|
filter.add(new PowerPredicate(ComparisonType.FEWER_THAN, 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
public SmileAtDeath(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{W}{W}");
|
||||||
|
|
||||||
|
// At the beginning of your upkeep, return up to two target creature cards with power 2 or less from your graveyard to the battlefield. Put a +1/+1 counter on each of those creatures.
|
||||||
|
Ability ability = new BeginningOfUpkeepTriggeredAbility(new SmileAtDeathEffect());
|
||||||
|
ability.addTarget(new TargetCardInYourGraveyard(0, 2, filter));
|
||||||
|
this.addAbility(ability);
|
||||||
|
}
|
||||||
|
|
||||||
|
private SmileAtDeath(final SmileAtDeath card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SmileAtDeath copy() {
|
||||||
|
return new SmileAtDeath(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SmileAtDeathEffect extends OneShotEffect {
|
||||||
|
|
||||||
|
SmileAtDeathEffect() {
|
||||||
|
super(Outcome.Benefit);
|
||||||
|
staticText = "return up to two target creature cards with power 2 or less " +
|
||||||
|
"from your graveyard to the battlefield. Put a +1/+1 counter on each of those creatures";
|
||||||
|
}
|
||||||
|
|
||||||
|
private SmileAtDeathEffect(final SmileAtDeathEffect effect) {
|
||||||
|
super(effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SmileAtDeathEffect copy() {
|
||||||
|
return new SmileAtDeathEffect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source) {
|
||||||
|
Player player = game.getPlayer(source.getControllerId());
|
||||||
|
if (player == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Cards cards = new CardsImpl(getTargetPointer().getTargets(game, source));
|
||||||
|
cards.retainZone(Zone.GRAVEYARD, game);
|
||||||
|
if (cards.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
player.moveCards(cards, Zone.BATTLEFIELD, source, game);
|
||||||
|
for (UUID cardId : cards) {
|
||||||
|
Optional.ofNullable(cardId)
|
||||||
|
.map(game::getPermanent)
|
||||||
|
.ifPresent(permanent -> permanent.addCounters(CounterType.P1P1.createInstance(), source, game));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,8 +2,10 @@ package mage.cards.s;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import mage.Mana;
|
import mage.Mana;
|
||||||
|
import mage.abilities.dynamicvalue.DynamicValue;
|
||||||
import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount;
|
import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount;
|
||||||
import mage.abilities.effects.mana.DynamicManaEffect;
|
import mage.abilities.effects.mana.DynamicManaEffect;
|
||||||
|
import mage.abilities.hint.ValueHint;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
|
|
@ -14,13 +16,14 @@ import mage.filter.StaticFilters;
|
||||||
* @author fireshoes
|
* @author fireshoes
|
||||||
*/
|
*/
|
||||||
public final class SongsOfTheDamned extends CardImpl {
|
public final class SongsOfTheDamned extends CardImpl {
|
||||||
|
|
||||||
public SongsOfTheDamned(UUID ownerId, CardSetInfo setInfo) {
|
public SongsOfTheDamned(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{B}");
|
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{B}");
|
||||||
|
|
||||||
// Add {B} for each creature card in your graveyard.
|
// Add {B} for each creature card in your graveyard.
|
||||||
DynamicManaEffect effect = new DynamicManaEffect(Mana.BlackMana(1), new CardsInControllerGraveyardCount(StaticFilters.FILTER_CARD_CREATURE));
|
DynamicValue creatureCardsInGraveyard = new CardsInControllerGraveyardCount(StaticFilters.FILTER_CARD_CREATURES);
|
||||||
|
DynamicManaEffect effect = new DynamicManaEffect(Mana.BlackMana(1), creatureCardsInGraveyard);
|
||||||
this.getSpellAbility().addEffect(effect);
|
this.getSpellAbility().addEffect(effect);
|
||||||
|
this.getSpellAbility().addHint(new ValueHint("Creature cards in your graveyard", creatureCardsInGraveyard));
|
||||||
}
|
}
|
||||||
|
|
||||||
private SongsOfTheDamned(final SongsOfTheDamned card) {
|
private SongsOfTheDamned(final SongsOfTheDamned card) {
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import mage.abilities.common.SimpleStaticAbility;
|
||||||
import mage.abilities.common.SpellCastControllerTriggeredAbility;
|
import mage.abilities.common.SpellCastControllerTriggeredAbility;
|
||||||
import mage.abilities.condition.Condition;
|
import mage.abilities.condition.Condition;
|
||||||
import mage.abilities.costs.Cost;
|
import mage.abilities.costs.Cost;
|
||||||
|
import mage.abilities.dynamicvalue.common.InstantAndSorceryCastThisTurn;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.abilities.effects.common.DrawDiscardControllerEffect;
|
import mage.abilities.effects.common.DrawDiscardControllerEffect;
|
||||||
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
|
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
|
||||||
|
|
@ -24,14 +25,9 @@ import mage.cards.CardSetInfo;
|
||||||
import mage.constants.*;
|
import mage.constants.*;
|
||||||
import mage.filter.StaticFilters;
|
import mage.filter.StaticFilters;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.GameEvent;
|
|
||||||
import mage.game.stack.Spell;
|
import mage.game.stack.Spell;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.util.CardUtil;
|
|
||||||
import mage.watchers.Watcher;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -76,7 +72,7 @@ public final class SorcererClass extends CardImpl {
|
||||||
StaticFilters.FILTER_SPELL_AN_INSTANT_OR_SORCERY,
|
StaticFilters.FILTER_SPELL_AN_INSTANT_OR_SORCERY,
|
||||||
false, SetTargetPointer.SPELL
|
false, SetTargetPointer.SPELL
|
||||||
), 3
|
), 3
|
||||||
)), new SorcererClassWatcher());
|
)).addHint(InstantAndSorceryCastThisTurn.YOU.getHint()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private SorcererClass(final SorcererClass card) {
|
private SorcererClass(final SorcererClass card) {
|
||||||
|
|
@ -151,7 +147,7 @@ class SorcererClassEffect extends OneShotEffect {
|
||||||
if (spell == null) {
|
if (spell == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int count = SorcererClassWatcher.spellCount(source.getControllerId(), game);
|
int count = InstantAndSorceryCastThisTurn.YOU.calculate(game, source, this);
|
||||||
if (count < 1) {
|
if (count < 1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -165,35 +161,3 @@ class SorcererClassEffect extends OneShotEffect {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SorcererClassWatcher extends Watcher {
|
|
||||||
|
|
||||||
private final Map<UUID, Integer> spellMap = new HashMap<>();
|
|
||||||
|
|
||||||
SorcererClassWatcher() {
|
|
||||||
super(WatcherScope.GAME);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void watch(GameEvent event, Game game) {
|
|
||||||
if (event.getType() != GameEvent.EventType.SPELL_CAST) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Spell spell = game.getSpell(event.getTargetId());
|
|
||||||
if (spell == null || !spell.isInstantOrSorcery(game)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
spellMap.compute(spell.getControllerId(), CardUtil::setOrIncrementValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void reset() {
|
|
||||||
spellMap.clear();
|
|
||||||
super.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
static int spellCount(UUID playerId, Game game) {
|
|
||||||
SorcererClassWatcher watcher = game.getState().getWatcher(SorcererClassWatcher.class);
|
|
||||||
return watcher != null ? watcher.spellMap.getOrDefault(playerId, 0) : 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
51
Mage.Sets/src/mage/cards/s/StormscaleScion.java
Normal file
51
Mage.Sets/src/mage/cards/s/StormscaleScion.java
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
package mage.cards.s;
|
||||||
|
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.abilities.common.SimpleStaticAbility;
|
||||||
|
import mage.abilities.effects.common.continuous.BoostControlledEffect;
|
||||||
|
import mage.abilities.keyword.FlyingAbility;
|
||||||
|
import mage.abilities.keyword.StormAbility;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.Duration;
|
||||||
|
import mage.constants.SubType;
|
||||||
|
import mage.filter.common.FilterCreaturePermanent;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public final class StormscaleScion extends CardImpl {
|
||||||
|
|
||||||
|
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(SubType.DRAGON, "Dragons");
|
||||||
|
|
||||||
|
public StormscaleScion(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{R}{R}");
|
||||||
|
|
||||||
|
this.subtype.add(SubType.DRAGON);
|
||||||
|
this.power = new MageInt(4);
|
||||||
|
this.toughness = new MageInt(4);
|
||||||
|
|
||||||
|
// Flying
|
||||||
|
this.addAbility(FlyingAbility.getInstance());
|
||||||
|
|
||||||
|
// Other Dragons you control get +1/+1.
|
||||||
|
this.addAbility(new SimpleStaticAbility(new BoostControlledEffect(
|
||||||
|
1, 1, Duration.WhileOnBattlefield, filter, true
|
||||||
|
)));
|
||||||
|
|
||||||
|
// Storm
|
||||||
|
this.addAbility(new StormAbility());
|
||||||
|
}
|
||||||
|
|
||||||
|
private StormscaleScion(final StormscaleScion card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StormscaleScion copy() {
|
||||||
|
return new StormscaleScion(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
78
Mage.Sets/src/mage/cards/s/StrongTheBrutishThespian.java
Normal file
78
Mage.Sets/src/mage/cards/s/StrongTheBrutishThespian.java
Normal file
|
|
@ -0,0 +1,78 @@
|
||||||
|
package mage.cards.s;
|
||||||
|
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.common.DealtDamageToSourceTriggeredAbility;
|
||||||
|
import mage.abilities.common.SimpleStaticAbility;
|
||||||
|
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
|
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
|
||||||
|
import mage.abilities.effects.common.counter.AddCountersPlayersEffect;
|
||||||
|
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
||||||
|
import mage.abilities.keyword.WardAbility;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.*;
|
||||||
|
import mage.counters.CounterType;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.game.events.GameEvent;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class StrongTheBrutishThespian extends CardImpl {
|
||||||
|
public StrongTheBrutishThespian(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{G}{G}");
|
||||||
|
this.addSuperType(SuperType.LEGENDARY);
|
||||||
|
this.addSubType(SubType.MUTANT);
|
||||||
|
this.addSubType(SubType.BERSERKER);
|
||||||
|
|
||||||
|
this.power = new MageInt(7);
|
||||||
|
this.toughness = new MageInt(7);
|
||||||
|
|
||||||
|
// Ward {2}
|
||||||
|
this.addAbility(new WardAbility(new ManaCostsImpl<>("{2}")));
|
||||||
|
|
||||||
|
// Enrage - Whenever strong is dealt damage, you get three rad counters and put three +1/+1 counters on Strong.
|
||||||
|
Ability enrageAbility = new DealtDamageToSourceTriggeredAbility(new AddCountersPlayersEffect(CounterType.RAD.createInstance(3), TargetController.YOU), false, true);
|
||||||
|
enrageAbility.addEffect(new AddCountersSourceEffect(CounterType.P1P1.createInstance(3)).setText("put three +1/+1 counters on Strong"));
|
||||||
|
this.addAbility(enrageAbility);
|
||||||
|
|
||||||
|
// You gain life rather than lose life from radiation.
|
||||||
|
Ability healAbility = new SimpleStaticAbility(new StrongTheBrutishThespianHealEffect().setText("You gain life rather than lose life from radiation."));
|
||||||
|
this.addAbility(healAbility);
|
||||||
|
}
|
||||||
|
|
||||||
|
public StrongTheBrutishThespian(StrongTheBrutishThespian card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StrongTheBrutishThespian copy() {
|
||||||
|
return new StrongTheBrutishThespian(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
class StrongTheBrutishThespianHealEffect extends ContinuousRuleModifyingEffectImpl {
|
||||||
|
|
||||||
|
protected StrongTheBrutishThespianHealEffect() {
|
||||||
|
super(Duration.Custom, Outcome.Benefit);
|
||||||
|
}
|
||||||
|
|
||||||
|
public StrongTheBrutishThespianHealEffect(StrongTheBrutishThespianHealEffect effect) {
|
||||||
|
super(effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StrongTheBrutishThespianHealEffect copy() {
|
||||||
|
return new StrongTheBrutishThespianHealEffect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean checksEventType(GameEvent event, Game game) {
|
||||||
|
return event.getType() == GameEvent.EventType.RADIATION_GAIN_LIFE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||||
|
return event.getPlayerId().equals(source.getControllerId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
78
Mage.Sets/src/mage/cards/s/SummonShiva.java
Normal file
78
Mage.Sets/src/mage/cards/s/SummonShiva.java
Normal file
|
|
@ -0,0 +1,78 @@
|
||||||
|
package mage.cards.s;
|
||||||
|
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.abilities.common.SagaAbility;
|
||||||
|
import mage.abilities.dynamicvalue.DynamicValue;
|
||||||
|
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
|
||||||
|
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
||||||
|
import mage.abilities.effects.common.TapTargetEffect;
|
||||||
|
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
|
||||||
|
import mage.abilities.hint.Hint;
|
||||||
|
import mage.abilities.hint.ValueHint;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.SagaChapter;
|
||||||
|
import mage.constants.SubType;
|
||||||
|
import mage.counters.CounterType;
|
||||||
|
import mage.filter.FilterPermanent;
|
||||||
|
import mage.filter.common.FilterOpponentsCreaturePermanent;
|
||||||
|
import mage.filter.predicate.permanent.TappedPredicate;
|
||||||
|
import mage.target.common.TargetOpponentsCreaturePermanent;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public final class SummonShiva extends CardImpl {
|
||||||
|
|
||||||
|
private static final FilterPermanent filter
|
||||||
|
= new FilterOpponentsCreaturePermanent("tapped creature your opponents control");
|
||||||
|
|
||||||
|
static {
|
||||||
|
filter.add(TappedPredicate.TAPPED);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final DynamicValue xValue = new PermanentsOnBattlefieldCount(filter, 1);
|
||||||
|
private static final Hint hint = new ValueHint("Tapped creatures your opponents control", xValue);
|
||||||
|
|
||||||
|
public SummonShiva(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT, CardType.CREATURE}, "{3}{U}{U}");
|
||||||
|
|
||||||
|
this.subtype.add(SubType.SAGA);
|
||||||
|
this.subtype.add(SubType.ELEMENTAL);
|
||||||
|
this.power = new MageInt(4);
|
||||||
|
this.toughness = new MageInt(5);
|
||||||
|
|
||||||
|
// (As this Saga enters and after your draw step, add a lore counter. Sacrifice after III.)
|
||||||
|
SagaAbility sagaAbility = new SagaAbility(this);
|
||||||
|
|
||||||
|
// I, II -- Heavenly Strike -- Tap target creature an opponent controls. Put a stun counter on it.
|
||||||
|
sagaAbility.addChapterEffect(this, SagaChapter.CHAPTER_I, SagaChapter.CHAPTER_II, ability -> {
|
||||||
|
ability.addEffect(new TapTargetEffect());
|
||||||
|
ability.addEffect(new AddCountersTargetEffect(CounterType.STUN.createInstance())
|
||||||
|
.setText("Put a stun counter on it"));
|
||||||
|
ability.addTarget(new TargetOpponentsCreaturePermanent());
|
||||||
|
ability.withFlavorWord("Heavenly Strike");
|
||||||
|
});
|
||||||
|
|
||||||
|
// III -- Diamond Dust -- Draw a card for each tapped creature your opponents control.
|
||||||
|
sagaAbility.addChapterEffect(this, SagaChapter.CHAPTER_III, ability -> {
|
||||||
|
ability.addEffect(new DrawCardSourceControllerEffect(xValue));
|
||||||
|
ability.withFlavorWord("Diamond Dust");
|
||||||
|
ability.addHint(hint);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.addAbility(sagaAbility);
|
||||||
|
}
|
||||||
|
|
||||||
|
private SummonShiva(final SummonShiva card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SummonShiva copy() {
|
||||||
|
return new SummonShiva(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
89
Mage.Sets/src/mage/cards/s/SuppressorSkyguard.java
Normal file
89
Mage.Sets/src/mage/cards/s/SuppressorSkyguard.java
Normal file
|
|
@ -0,0 +1,89 @@
|
||||||
|
package mage.cards.s;
|
||||||
|
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.abilities.TriggeredAbilityImpl;
|
||||||
|
import mage.abilities.effects.common.PreventDamageToControllerEffect;
|
||||||
|
import mage.abilities.keyword.FlyingAbility;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.*;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.game.combat.CombatGroup;
|
||||||
|
import mage.game.events.GameEvent;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class SuppressorSkyguard extends CardImpl {
|
||||||
|
public SuppressorSkyguard(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}{U}");
|
||||||
|
|
||||||
|
this.addSubType(SubType.HUMAN);
|
||||||
|
this.addSubType(SubType.KNIGHT);
|
||||||
|
|
||||||
|
this.power = new MageInt(2);
|
||||||
|
this.toughness = new MageInt(4);
|
||||||
|
|
||||||
|
// Flying
|
||||||
|
this.addAbility(FlyingAbility.getInstance());
|
||||||
|
|
||||||
|
// whenever a player attacks you, if that player has another opponent who isn't being attacked, prevent all combat damage that would be dealt to you this combat
|
||||||
|
this.addAbility(new SuppressorSkyguardTriggerAttackYou());
|
||||||
|
}
|
||||||
|
|
||||||
|
public SuppressorSkyguard(SuppressorSkyguard card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SuppressorSkyguard copy() {
|
||||||
|
return new SuppressorSkyguard(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
class SuppressorSkyguardTriggerAttackYou extends TriggeredAbilityImpl {
|
||||||
|
SuppressorSkyguardTriggerAttackYou() {
|
||||||
|
super(Zone.BATTLEFIELD, new PreventDamageToControllerEffect(Duration.EndOfCombat, true, false, Integer.MAX_VALUE), false);
|
||||||
|
this.setTriggerPhrase("whenever a player attacks you, ");
|
||||||
|
}
|
||||||
|
|
||||||
|
private SuppressorSkyguardTriggerAttackYou(final SuppressorSkyguardTriggerAttackYou ability) {
|
||||||
|
super(ability);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SuppressorSkyguardTriggerAttackYou copy() {
|
||||||
|
return new SuppressorSkyguardTriggerAttackYou(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean checkEventType(GameEvent event, Game game) {
|
||||||
|
return event.getType() == GameEvent.EventType.DEFENDER_ATTACKED;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean checkTrigger(GameEvent event, Game game) {
|
||||||
|
return getControllerId().equals(event.getTargetId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean checkInterveningIfClause(Game game) {
|
||||||
|
UUID activePlayerId = game.getActivePlayerId();
|
||||||
|
Set<UUID> opponents = game.getOpponents(activePlayerId);
|
||||||
|
game.getCombat()
|
||||||
|
.getGroups()
|
||||||
|
.stream()
|
||||||
|
.map(CombatGroup::getDefenderId)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.distinct()
|
||||||
|
.forEach(opponents::remove);
|
||||||
|
|
||||||
|
return !opponents.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getRule() {
|
||||||
|
return "Whenever a player attacks you, if that player has another opponent who isn't being attacked, prevent all combat damage that would be dealt to you this combat.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
68
Mage.Sets/src/mage/cards/t/TerraHeraldOfHope.java
Normal file
68
Mage.Sets/src/mage/cards/t/TerraHeraldOfHope.java
Normal file
|
|
@ -0,0 +1,68 @@
|
||||||
|
package mage.cards.t;
|
||||||
|
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
|
||||||
|
import mage.abilities.common.delayed.ReflexiveTriggeredAbility;
|
||||||
|
import mage.abilities.costs.mana.GenericManaCost;
|
||||||
|
import mage.abilities.effects.common.DoWhenCostPaid;
|
||||||
|
import mage.abilities.effects.common.MillCardsControllerEffect;
|
||||||
|
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
|
||||||
|
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
|
||||||
|
import mage.abilities.keyword.FlyingAbility;
|
||||||
|
import mage.abilities.triggers.BeginningOfCombatTriggeredAbility;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.*;
|
||||||
|
import mage.filter.FilterCard;
|
||||||
|
import mage.filter.common.FilterCreatureCard;
|
||||||
|
import mage.filter.predicate.mageobject.PowerPredicate;
|
||||||
|
import mage.target.common.TargetCardInYourGraveyard;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public final class TerraHeraldOfHope extends CardImpl {
|
||||||
|
|
||||||
|
private static final FilterCard filter = new FilterCreatureCard("creature card with power 3 or less from your graveyard");
|
||||||
|
|
||||||
|
static {
|
||||||
|
filter.add(new PowerPredicate(ComparisonType.FEWER_THAN, 4));
|
||||||
|
}
|
||||||
|
|
||||||
|
public TerraHeraldOfHope(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{R}{W}{B}");
|
||||||
|
|
||||||
|
this.supertype.add(SuperType.LEGENDARY);
|
||||||
|
this.subtype.add(SubType.HUMAN);
|
||||||
|
this.subtype.add(SubType.WIZARD);
|
||||||
|
this.subtype.add(SubType.WARRIOR);
|
||||||
|
this.power = new MageInt(3);
|
||||||
|
this.toughness = new MageInt(3);
|
||||||
|
|
||||||
|
// Trance -- At the beginning of combat on your turn, mill two cards. Terra gains flying until end of turn.
|
||||||
|
Ability ability = new BeginningOfCombatTriggeredAbility(new MillCardsControllerEffect(2));
|
||||||
|
ability.addEffect(new GainAbilitySourceEffect(FlyingAbility.getInstance(), Duration.EndOfTurn));
|
||||||
|
this.addAbility(ability.withFlavorWord("Trance"));
|
||||||
|
|
||||||
|
// Whenever Terra deals combat damage to a player, you may pay {2}. When you do, return target creature card with power 3 or less from your graveyard to the battlefield tapped.
|
||||||
|
ReflexiveTriggeredAbility reflexiveAbility = new ReflexiveTriggeredAbility(
|
||||||
|
new ReturnFromGraveyardToBattlefieldTargetEffect(true), false
|
||||||
|
);
|
||||||
|
ability.addTarget(new TargetCardInYourGraveyard(filter));
|
||||||
|
this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(
|
||||||
|
new DoWhenCostPaid(reflexiveAbility, new GenericManaCost(2), "Pay {2}?")
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
private TerraHeraldOfHope(final TerraHeraldOfHope card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TerraHeraldOfHope copy() {
|
||||||
|
return new TerraHeraldOfHope(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
92
Mage.Sets/src/mage/cards/t/TevalTheBalancedScale.java
Normal file
92
Mage.Sets/src/mage/cards/t/TevalTheBalancedScale.java
Normal file
|
|
@ -0,0 +1,92 @@
|
||||||
|
package mage.cards.t;
|
||||||
|
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.common.AttacksTriggeredAbility;
|
||||||
|
import mage.abilities.common.CardsLeaveGraveyardTriggeredAbility;
|
||||||
|
import mage.abilities.effects.OneShotEffect;
|
||||||
|
import mage.abilities.effects.common.CreateTokenEffect;
|
||||||
|
import mage.abilities.effects.common.MillCardsControllerEffect;
|
||||||
|
import mage.abilities.keyword.FlyingAbility;
|
||||||
|
import mage.cards.Card;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.*;
|
||||||
|
import mage.filter.StaticFilters;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.game.permanent.token.ZombieDruidToken;
|
||||||
|
import mage.players.Player;
|
||||||
|
import mage.target.TargetCard;
|
||||||
|
import mage.target.common.TargetCardInYourGraveyard;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public final class TevalTheBalancedScale extends CardImpl {
|
||||||
|
|
||||||
|
public TevalTheBalancedScale(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}{G}{U}");
|
||||||
|
|
||||||
|
this.supertype.add(SuperType.LEGENDARY);
|
||||||
|
this.subtype.add(SubType.SPIRIT);
|
||||||
|
this.subtype.add(SubType.DRAGON);
|
||||||
|
this.power = new MageInt(4);
|
||||||
|
this.toughness = new MageInt(4);
|
||||||
|
|
||||||
|
// Flying
|
||||||
|
this.addAbility(FlyingAbility.getInstance());
|
||||||
|
|
||||||
|
// Whenever Teval attacks, mill three cards. Then you may return a land card from your graveyard to the battlefield tapped.
|
||||||
|
Ability ability = new AttacksTriggeredAbility(new MillCardsControllerEffect(3));
|
||||||
|
ability.addEffect(new TevalTheBalancedScaleEffect());
|
||||||
|
this.addAbility(ability);
|
||||||
|
|
||||||
|
// Whenever one or more cards leave your graveyard, create a 2/2 black Zombie Druid creature token.
|
||||||
|
this.addAbility(new CardsLeaveGraveyardTriggeredAbility(new CreateTokenEffect(new ZombieDruidToken())));
|
||||||
|
}
|
||||||
|
|
||||||
|
private TevalTheBalancedScale(final TevalTheBalancedScale card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TevalTheBalancedScale copy() {
|
||||||
|
return new TevalTheBalancedScale(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TevalTheBalancedScaleEffect extends OneShotEffect {
|
||||||
|
|
||||||
|
TevalTheBalancedScaleEffect() {
|
||||||
|
super(Outcome.Benefit);
|
||||||
|
staticText = "Then you may return a land card from your graveyard to the battlefield tapped";
|
||||||
|
}
|
||||||
|
|
||||||
|
private TevalTheBalancedScaleEffect(final TevalTheBalancedScaleEffect effect) {
|
||||||
|
super(effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TevalTheBalancedScaleEffect copy() {
|
||||||
|
return new TevalTheBalancedScaleEffect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source) {
|
||||||
|
Player player = game.getPlayer(source.getControllerId());
|
||||||
|
if (player == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
TargetCard target = new TargetCardInYourGraveyard(
|
||||||
|
0, 1, StaticFilters.FILTER_CARD_LAND, true
|
||||||
|
);
|
||||||
|
player.choose(outcome, player.getGraveyard(), target, source, game);
|
||||||
|
Card card = game.getCard(target.getFirstTarget());
|
||||||
|
return card != null && player.moveCards(
|
||||||
|
card, Zone.BATTLEFIELD, source, game, true,
|
||||||
|
false, false, null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
105
Mage.Sets/src/mage/cards/t/TheGirlInTheFireplace.java
Normal file
105
Mage.Sets/src/mage/cards/t/TheGirlInTheFireplace.java
Normal file
|
|
@ -0,0 +1,105 @@
|
||||||
|
package mage.cards.t;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.abilities.DelayedTriggeredAbility;
|
||||||
|
import mage.abilities.common.SagaAbility;
|
||||||
|
import mage.abilities.effects.common.CreateTokenEffect;
|
||||||
|
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
|
||||||
|
import mage.abilities.effects.common.counter.TimeTravelEffect;
|
||||||
|
import mage.constants.Duration;
|
||||||
|
import mage.constants.SubType;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.SagaChapter;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.game.events.DamagedPlayerEvent;
|
||||||
|
import mage.game.events.GameEvent;
|
||||||
|
import mage.game.permanent.Permanent;
|
||||||
|
import mage.game.permanent.token.TheGirlInTheFireplaceHorseToken;
|
||||||
|
import mage.game.permanent.token.TheGirlInTheFireplaceHumanNobleToken;
|
||||||
|
import mage.filter.common.FilterControlledCreaturePermanent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author padfoot
|
||||||
|
*/
|
||||||
|
public final class TheGirlInTheFireplace extends CardImpl {
|
||||||
|
|
||||||
|
|
||||||
|
public TheGirlInTheFireplace(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}");
|
||||||
|
|
||||||
|
this.subtype.add(SubType.SAGA);
|
||||||
|
|
||||||
|
// (As this Saga enters and after your draw step, add a lore counter. Sacrifice after III.)
|
||||||
|
SagaAbility sagaAbility = new SagaAbility(this);
|
||||||
|
|
||||||
|
// I -- Create a 1/1 white Human Noble creature token with vanishing 3 and "Prevent all damage that would be dealt to this creature."
|
||||||
|
sagaAbility.addChapterEffect(this, SagaChapter.CHAPTER_I, new CreateTokenEffect(new TheGirlInTheFireplaceHumanNobleToken()));
|
||||||
|
|
||||||
|
// II -- Create a 2/2 white Horse creature token with "Doctors you control have horsemanship."
|
||||||
|
sagaAbility.addChapterEffect(this, SagaChapter.CHAPTER_II, new CreateTokenEffect(new TheGirlInTheFireplaceHorseToken())
|
||||||
|
.withAdditionalRules(" <i>(They can't be blocked except by creatures with horsemanship.)</i>"));
|
||||||
|
|
||||||
|
// III -- Whenever a creature you control deals combat damage to a player this turn, time travel.
|
||||||
|
sagaAbility.addChapterEffect(
|
||||||
|
this, SagaChapter.CHAPTER_III,
|
||||||
|
new CreateDelayedTriggeredAbilityEffect(
|
||||||
|
new TheGirlInTheFireplaceTriggeredAbility()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
this.addAbility(sagaAbility);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private TheGirlInTheFireplace(final TheGirlInTheFireplace card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TheGirlInTheFireplace copy() {
|
||||||
|
return new TheGirlInTheFireplace(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TheGirlInTheFireplaceTriggeredAbility extends DelayedTriggeredAbility {
|
||||||
|
|
||||||
|
private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent();
|
||||||
|
|
||||||
|
public TheGirlInTheFireplaceTriggeredAbility() {
|
||||||
|
super(new TimeTravelEffect(), Duration.EndOfTurn, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private TheGirlInTheFireplaceTriggeredAbility(TheGirlInTheFireplaceTriggeredAbility ability) {
|
||||||
|
super(ability);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TheGirlInTheFireplaceTriggeredAbility copy() {
|
||||||
|
return new TheGirlInTheFireplaceTriggeredAbility(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean checkEventType(GameEvent event, Game game) {
|
||||||
|
return event.getType() == GameEvent.EventType.DAMAGED_PLAYER;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean checkTrigger(GameEvent event, Game game) {
|
||||||
|
if (!((DamagedPlayerEvent) event).isCombatDamage()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Permanent permanent = game.getPermanentOrLKIBattlefield(event.getSourceId());
|
||||||
|
if (!filter.match(permanent, getControllerId(), this, game)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getRule() {
|
||||||
|
return "Whenever a creature you control deals combat damage to a player this turn, time travel.";
|
||||||
|
}
|
||||||
|
}
|
||||||
62
Mage.Sets/src/mage/cards/t/Tonberry.java
Normal file
62
Mage.Sets/src/mage/cards/t/Tonberry.java
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
package mage.cards.t;
|
||||||
|
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.common.EntersBattlefieldAbility;
|
||||||
|
import mage.abilities.common.SimpleStaticAbility;
|
||||||
|
import mage.abilities.condition.common.MyTurnCondition;
|
||||||
|
import mage.abilities.decorator.ConditionalContinuousEffect;
|
||||||
|
import mage.abilities.effects.common.TapSourceEffect;
|
||||||
|
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
|
||||||
|
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
||||||
|
import mage.abilities.keyword.DeathtouchAbility;
|
||||||
|
import mage.abilities.keyword.FirstStrikeAbility;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.SubType;
|
||||||
|
import mage.counters.CounterType;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public final class Tonberry extends CardImpl {
|
||||||
|
|
||||||
|
public Tonberry(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B}");
|
||||||
|
|
||||||
|
this.subtype.add(SubType.SALAMANDER);
|
||||||
|
this.subtype.add(SubType.HORROR);
|
||||||
|
this.power = new MageInt(2);
|
||||||
|
this.toughness = new MageInt(1);
|
||||||
|
|
||||||
|
// This creature enters tapped with a stun counter on it.
|
||||||
|
Ability ability = new EntersBattlefieldAbility(
|
||||||
|
new TapSourceEffect(true), "tapped with a stun counter on it"
|
||||||
|
);
|
||||||
|
ability.addEffect(new AddCountersSourceEffect(CounterType.STUN.createInstance()));
|
||||||
|
this.addAbility(ability);
|
||||||
|
|
||||||
|
// Chef's Knife -- During your turn, this creature has first strike and deathtouch.
|
||||||
|
ability = new SimpleStaticAbility(new ConditionalContinuousEffect(
|
||||||
|
new GainAbilitySourceEffect(FirstStrikeAbility.getInstance()),
|
||||||
|
MyTurnCondition.instance, "during your turn, this creature has first strike"
|
||||||
|
));
|
||||||
|
ability.addEffect(new ConditionalContinuousEffect(
|
||||||
|
new GainAbilitySourceEffect(DeathtouchAbility.getInstance()),
|
||||||
|
MyTurnCondition.instance, "and deathtouch"
|
||||||
|
));
|
||||||
|
this.addAbility(ability.withFlavorWord("Chef's Knife"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Tonberry(final Tonberry card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Tonberry copy() {
|
||||||
|
return new Tonberry(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
32
Mage.Sets/src/mage/cards/v/ViewpointSynchronization.java
Normal file
32
Mage.Sets/src/mage/cards/v/ViewpointSynchronization.java
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
package mage.cards.v;
|
||||||
|
|
||||||
|
import mage.abilities.effects.common.search.SearchLibraryPutOntoBattlefieldTappedRestInHandEffect;
|
||||||
|
import mage.abilities.keyword.FreerunningAbility;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.filter.StaticFilters;
|
||||||
|
import mage.target.common.TargetCardInLibrary;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class ViewpointSynchronization extends CardImpl {
|
||||||
|
public ViewpointSynchronization(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{G}");
|
||||||
|
|
||||||
|
this.addAbility(new FreerunningAbility("{2}{G}"));
|
||||||
|
|
||||||
|
// Search your library for up to three basic land cards and reveal them. Put two of them onto the battlefield tapped and the other in your hand, then shuffle.
|
||||||
|
this.getSpellAbility().addEffect(new SearchLibraryPutOntoBattlefieldTappedRestInHandEffect(
|
||||||
|
new TargetCardInLibrary(0, 3, StaticFilters.FILTER_CARD_BASIC_LANDS), 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ViewpointSynchronization(ViewpointSynchronization card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ViewpointSynchronization copy() {
|
||||||
|
return new ViewpointSynchronization(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,11 +4,10 @@ import mage.MageInt;
|
||||||
import mage.MageObject;
|
import mage.MageObject;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||||
|
import mage.abilities.costs.Cost;
|
||||||
import mage.abilities.costs.common.PayEnergyCost;
|
import mage.abilities.costs.common.PayEnergyCost;
|
||||||
import mage.abilities.effects.ContinuousEffect;
|
import mage.abilities.effects.ContinuousEffect;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.abilities.effects.common.DoIfCostPaid;
|
|
||||||
import mage.abilities.effects.common.SacrificeTargetEffect;
|
|
||||||
import mage.abilities.effects.common.continuous.ExchangeControlTargetEffect;
|
import mage.abilities.effects.common.continuous.ExchangeControlTargetEffect;
|
||||||
import mage.abilities.keyword.FlyingAbility;
|
import mage.abilities.keyword.FlyingAbility;
|
||||||
import mage.abilities.keyword.HexproofBaseAbility;
|
import mage.abilities.keyword.HexproofBaseAbility;
|
||||||
|
|
@ -138,10 +137,13 @@ class VolatileStormdrakeEffect extends OneShotEffect {
|
||||||
game.addEffect(effect, source);
|
game.addEffect(effect, source);
|
||||||
game.processAction();
|
game.processAction();
|
||||||
controller.addCounters(CounterType.ENERGY.createInstance(4), controller.getId(), source, game);
|
controller.addCounters(CounterType.ENERGY.createInstance(4), controller.getId(), source, game);
|
||||||
new DoIfCostPaid(
|
Cost cost = new PayEnergyCost(targetPermanent.getManaValue());
|
||||||
null, new SacrificeTargetEffect("", controller.getId()),
|
if (cost.canPay(source, source, controller.getId(), game) &&
|
||||||
new PayEnergyCost(targetPermanent.getManaValue()), true
|
controller.chooseUse(Outcome.Benefit, "Pay " + cost.getText() + " to prevent sacrifice?", source, game) &&
|
||||||
).apply(game, source);
|
cost.pay(source, game, source, controller.getId(), false)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
targetPermanent.sacrifice(source, game);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import mage.abilities.Ability;
|
||||||
import mage.abilities.dynamicvalue.DynamicValue;
|
import mage.abilities.dynamicvalue.DynamicValue;
|
||||||
import mage.abilities.effects.Effect;
|
import mage.abilities.effects.Effect;
|
||||||
import mage.abilities.effects.common.DamageAllEffect;
|
import mage.abilities.effects.common.DamageAllEffect;
|
||||||
|
import mage.abilities.hint.ValueHint;
|
||||||
import mage.abilities.keyword.CascadeAbility;
|
import mage.abilities.keyword.CascadeAbility;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
|
|
@ -36,6 +37,7 @@ public final class VolcanicTorrent extends CardImpl {
|
||||||
|
|
||||||
// Volcanic Torrent deals X damage to each creature and planeswalker your opponents control, where X is the number of spells you've cast this turn.
|
// Volcanic Torrent deals X damage to each creature and planeswalker your opponents control, where X is the number of spells you've cast this turn.
|
||||||
this.getSpellAbility().addEffect(new DamageAllEffect(VolcanicTorrentValue.instance, filter));
|
this.getSpellAbility().addEffect(new DamageAllEffect(VolcanicTorrentValue.instance, filter));
|
||||||
|
this.getSpellAbility().addHint(new ValueHint("Number of spells you've cast this turn", VolcanicTorrentValue.instance));
|
||||||
}
|
}
|
||||||
|
|
||||||
private VolcanicTorrent(final VolcanicTorrent card) {
|
private VolcanicTorrent(final VolcanicTorrent card) {
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,8 @@ enum CanTargetOnlyWallsPredicate implements Predicate<MageObject> {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
boolean canTargetOnlyWalls = false;
|
boolean canTargetOnlyWalls = false;
|
||||||
for (Mode mode : stackObject.getStackAbility().getModes().values()) {
|
for (UUID modeId : stackObject.getStackAbility().getModes().getSelectedModes()) {
|
||||||
|
Mode mode = stackObject.getStackAbility().getModes().get(modeId);
|
||||||
for (Target target : mode.getTargets()) {
|
for (Target target : mode.getTargets()) {
|
||||||
Filter filter = target.getFilter();
|
Filter filter = target.getFilter();
|
||||||
if (!(filter instanceof FilterPermanent)) {
|
if (!(filter instanceof FilterPermanent)) {
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import mage.MageInt;
|
||||||
import mage.abilities.common.ZoneChangeTriggeredAbility;
|
import mage.abilities.common.ZoneChangeTriggeredAbility;
|
||||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
import mage.abilities.dynamicvalue.common.GetXValue;
|
import mage.abilities.dynamicvalue.common.GetXValue;
|
||||||
|
import mage.abilities.effects.common.DestroyTargetEffect;
|
||||||
import mage.abilities.keyword.CyclingAbility;
|
import mage.abilities.keyword.CyclingAbility;
|
||||||
import mage.abilities.keyword.ReachAbility;
|
import mage.abilities.keyword.ReachAbility;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
|
|
@ -58,7 +59,7 @@ public final class WebstrikeElite extends CardImpl {
|
||||||
class WebstrikeEliteTriggeredAbility extends ZoneChangeTriggeredAbility {
|
class WebstrikeEliteTriggeredAbility extends ZoneChangeTriggeredAbility {
|
||||||
|
|
||||||
WebstrikeEliteTriggeredAbility() {
|
WebstrikeEliteTriggeredAbility() {
|
||||||
super(Zone.ALL, null, "", false);
|
super(Zone.ALL, new DestroyTargetEffect(), "", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private WebstrikeEliteTriggeredAbility(final WebstrikeEliteTriggeredAbility ability) {
|
private WebstrikeEliteTriggeredAbility(final WebstrikeEliteTriggeredAbility ability) {
|
||||||
|
|
|
||||||
110
Mage.Sets/src/mage/cards/w/WhatMustBeDone.java
Normal file
110
Mage.Sets/src/mage/cards/w/WhatMustBeDone.java
Normal file
|
|
@ -0,0 +1,110 @@
|
||||||
|
package mage.cards.w;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.Mode;
|
||||||
|
import mage.abilities.effects.ReplacementEffectImpl;
|
||||||
|
import mage.abilities.effects.common.DestroyAllEffect;
|
||||||
|
import mage.abilities.effects.common.InfoEffect;
|
||||||
|
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.Duration;
|
||||||
|
import mage.constants.Outcome;
|
||||||
|
import mage.counters.CounterType;
|
||||||
|
import mage.filter.FilterCard;
|
||||||
|
import mage.filter.FilterPermanent;
|
||||||
|
import mage.filter.common.FilterPermanentCard;
|
||||||
|
import mage.filter.predicate.Predicates;
|
||||||
|
import mage.filter.predicate.mageobject.HistoricPredicate;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.game.events.EntersTheBattlefieldEvent;
|
||||||
|
import mage.game.events.GameEvent;
|
||||||
|
import mage.game.permanent.Permanent;
|
||||||
|
import mage.target.common.TargetCardInYourGraveyard;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author anonymous
|
||||||
|
*/
|
||||||
|
public final class WhatMustBeDone extends CardImpl {
|
||||||
|
|
||||||
|
private static final FilterPermanent filterArtifactsAndCreatures = new FilterPermanent("artifacts and creatures");
|
||||||
|
static {
|
||||||
|
filterArtifactsAndCreatures.add(Predicates.or(
|
||||||
|
CardType.ARTIFACT.getPredicate(),
|
||||||
|
CardType.CREATURE.getPredicate()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final FilterCard filterHistoricPermanentCard = new FilterPermanentCard("historic permanent card from your graveyard");
|
||||||
|
static {
|
||||||
|
filterHistoricPermanentCard.add(HistoricPredicate.instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WhatMustBeDone(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{W}{W}");
|
||||||
|
|
||||||
|
// Choose one --
|
||||||
|
// * Let the World Burn -- Destroy all artifacts and creatures.
|
||||||
|
this.getSpellAbility().addEffect(new DestroyAllEffect(filterArtifactsAndCreatures));
|
||||||
|
this.getSpellAbility().withFirstModeFlavorWord("Let the World Burn");
|
||||||
|
|
||||||
|
// * Release Juno -- Return target historic permanent card from your graveyard to the battlefield. It enters with two additional +1/+1 counters on it if it's a creature.
|
||||||
|
this.getSpellAbility().addMode(new Mode(
|
||||||
|
new WhatMustBeDoneReplacementEffect(
|
||||||
|
)).addEffect(new ReturnFromGraveyardToBattlefieldTargetEffect()
|
||||||
|
).addTarget(new TargetCardInYourGraveyard(filterHistoricPermanentCard)
|
||||||
|
).addEffect(new InfoEffect("It enters with two additional +1/+1 counters on it if it's a creature. "
|
||||||
|
+ "<i>(Artifacts, legendaries, and Sagas are historic.)</i>" )
|
||||||
|
).withFlavorWord("Release Juno"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private WhatMustBeDone(final WhatMustBeDone card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WhatMustBeDone copy() {
|
||||||
|
return new WhatMustBeDone(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class WhatMustBeDoneReplacementEffect extends ReplacementEffectImpl {
|
||||||
|
|
||||||
|
WhatMustBeDoneReplacementEffect() {
|
||||||
|
super(Duration.EndOfStep, Outcome.BoostCreature);
|
||||||
|
}
|
||||||
|
|
||||||
|
private WhatMustBeDoneReplacementEffect(final WhatMustBeDoneReplacementEffect effect) {
|
||||||
|
super(effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean checksEventType(GameEvent event, Game game) {
|
||||||
|
return event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||||
|
return getTargetPointer().getTargets(game, source).contains(event.getTargetId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||||
|
Permanent permanent = ((EntersTheBattlefieldEvent) event).getTarget();
|
||||||
|
if (permanent == null || !permanent.isCreature(game)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
permanent.addCounters(CounterType.P1P1.createInstance(2), source.getControllerId(), source, game, event.getAppliedEffects());
|
||||||
|
discard();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WhatMustBeDoneReplacementEffect copy() {
|
||||||
|
return new WhatMustBeDoneReplacementEffect(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -28,8 +28,10 @@ public final class Aetherdrift extends ExpansionSet {
|
||||||
cards.add(new SetCardInfo("Afterburner Expert", 150, Rarity.RARE, mage.cards.a.AfterburnerExpert.class));
|
cards.add(new SetCardInfo("Afterburner Expert", 150, Rarity.RARE, mage.cards.a.AfterburnerExpert.class));
|
||||||
cards.add(new SetCardInfo("Agonasaur Rex", 151, Rarity.RARE, mage.cards.a.AgonasaurRex.class));
|
cards.add(new SetCardInfo("Agonasaur Rex", 151, Rarity.RARE, mage.cards.a.AgonasaurRex.class));
|
||||||
cards.add(new SetCardInfo("Air Response Unit", 1, Rarity.UNCOMMON, mage.cards.a.AirResponseUnit.class));
|
cards.add(new SetCardInfo("Air Response Unit", 1, Rarity.UNCOMMON, mage.cards.a.AirResponseUnit.class));
|
||||||
|
cards.add(new SetCardInfo("Alacrian Armory", 2, Rarity.UNCOMMON, mage.cards.a.AlacrianArmory.class));
|
||||||
cards.add(new SetCardInfo("Alacrian Jaguar", 152, Rarity.COMMON, mage.cards.a.AlacrianJaguar.class));
|
cards.add(new SetCardInfo("Alacrian Jaguar", 152, Rarity.COMMON, mage.cards.a.AlacrianJaguar.class));
|
||||||
cards.add(new SetCardInfo("Amonkhet Raceway", 248, Rarity.UNCOMMON, mage.cards.a.AmonkhetRaceway.class));
|
cards.add(new SetCardInfo("Amonkhet Raceway", 248, Rarity.UNCOMMON, mage.cards.a.AmonkhetRaceway.class));
|
||||||
|
cards.add(new SetCardInfo("Ancient Vendetta", 75, Rarity.UNCOMMON, mage.cards.a.AncientVendetta.class));
|
||||||
cards.add(new SetCardInfo("Apocalypse Runner", 188, Rarity.UNCOMMON, mage.cards.a.ApocalypseRunner.class));
|
cards.add(new SetCardInfo("Apocalypse Runner", 188, Rarity.UNCOMMON, mage.cards.a.ApocalypseRunner.class));
|
||||||
cards.add(new SetCardInfo("Autarch Mammoth", 153, Rarity.UNCOMMON, mage.cards.a.AutarchMammoth.class));
|
cards.add(new SetCardInfo("Autarch Mammoth", 153, Rarity.UNCOMMON, mage.cards.a.AutarchMammoth.class));
|
||||||
cards.add(new SetCardInfo("Avishkar Raceway", 249, Rarity.COMMON, mage.cards.a.AvishkarRaceway.class));
|
cards.add(new SetCardInfo("Avishkar Raceway", 249, Rarity.COMMON, mage.cards.a.AvishkarRaceway.class));
|
||||||
|
|
@ -60,6 +62,10 @@ public final class Aetherdrift extends ExpansionSet {
|
||||||
cards.add(new SetCardInfo("Burnout Bashtronaut", 115, Rarity.RARE, mage.cards.b.BurnoutBashtronaut.class));
|
cards.add(new SetCardInfo("Burnout Bashtronaut", 115, Rarity.RARE, mage.cards.b.BurnoutBashtronaut.class));
|
||||||
cards.add(new SetCardInfo("Caelorna, Coral Tyrant", 40, Rarity.UNCOMMON, mage.cards.c.CaelornaCoralTyrant.class));
|
cards.add(new SetCardInfo("Caelorna, Coral Tyrant", 40, Rarity.UNCOMMON, mage.cards.c.CaelornaCoralTyrant.class));
|
||||||
cards.add(new SetCardInfo("Camera Launcher", 232, Rarity.COMMON, mage.cards.c.CameraLauncher.class));
|
cards.add(new SetCardInfo("Camera Launcher", 232, Rarity.COMMON, mage.cards.c.CameraLauncher.class));
|
||||||
|
cards.add(new SetCardInfo("Captain Howler, Sea Scourge", 194, Rarity.RARE, mage.cards.c.CaptainHowlerSeaScourge.class, NON_FULL_USE_VARIOUS));
|
||||||
|
cards.add(new SetCardInfo("Captain Howler, Sea Scourge", 361, Rarity.RARE, mage.cards.c.CaptainHowlerSeaScourge.class, NON_FULL_USE_VARIOUS));
|
||||||
|
cards.add(new SetCardInfo("Captain Howler, Sea Scourge", 475, Rarity.RARE, mage.cards.c.CaptainHowlerSeaScourge.class, NON_FULL_USE_VARIOUS));
|
||||||
|
cards.add(new SetCardInfo("Canyon Vaulter", 8, Rarity.UNCOMMON, mage.cards.c.CanyonVaulter.class));
|
||||||
cards.add(new SetCardInfo("Caradora, Heart of Alacria", 195, Rarity.RARE, mage.cards.c.CaradoraHeartOfAlacria.class));
|
cards.add(new SetCardInfo("Caradora, Heart of Alacria", 195, Rarity.RARE, mage.cards.c.CaradoraHeartOfAlacria.class));
|
||||||
cards.add(new SetCardInfo("Carrion Cruiser", 78, Rarity.UNCOMMON, mage.cards.c.CarrionCruiser.class));
|
cards.add(new SetCardInfo("Carrion Cruiser", 78, Rarity.UNCOMMON, mage.cards.c.CarrionCruiser.class));
|
||||||
cards.add(new SetCardInfo("Chandra, Spark Hunter", 116, Rarity.MYTHIC, mage.cards.c.ChandraSparkHunter.class));
|
cards.add(new SetCardInfo("Chandra, Spark Hunter", 116, Rarity.MYTHIC, mage.cards.c.ChandraSparkHunter.class));
|
||||||
|
|
@ -67,16 +73,30 @@ public final class Aetherdrift extends ExpansionSet {
|
||||||
cards.add(new SetCardInfo("Clamorous Ironclad", 117, Rarity.COMMON, mage.cards.c.ClamorousIronclad.class));
|
cards.add(new SetCardInfo("Clamorous Ironclad", 117, Rarity.COMMON, mage.cards.c.ClamorousIronclad.class));
|
||||||
cards.add(new SetCardInfo("Cloudspire Captain", 9, Rarity.UNCOMMON, mage.cards.c.CloudspireCaptain.class));
|
cards.add(new SetCardInfo("Cloudspire Captain", 9, Rarity.UNCOMMON, mage.cards.c.CloudspireCaptain.class));
|
||||||
cards.add(new SetCardInfo("Cloudspire Coordinator", 196, Rarity.UNCOMMON, mage.cards.c.CloudspireCoordinator.class));
|
cards.add(new SetCardInfo("Cloudspire Coordinator", 196, Rarity.UNCOMMON, mage.cards.c.CloudspireCoordinator.class));
|
||||||
|
cards.add(new SetCardInfo("Cloudspire Skycycle", 197, Rarity.UNCOMMON, mage.cards.c.CloudspireSkycycle.class));
|
||||||
|
cards.add(new SetCardInfo("Coalstoke Gearhulk", 198, Rarity.MYTHIC, mage.cards.c.CoalstokeGearhulk.class, NON_FULL_USE_VARIOUS));
|
||||||
|
cards.add(new SetCardInfo("Coalstoke Gearhulk", 349, Rarity.MYTHIC, mage.cards.c.CoalstokeGearhulk.class, NON_FULL_USE_VARIOUS));
|
||||||
|
cards.add(new SetCardInfo("Coalstoke Gearhulk", 477, Rarity.MYTHIC, mage.cards.c.CoalstokeGearhulk.class, NON_FULL_USE_VARIOUS));
|
||||||
|
cards.add(new SetCardInfo("Coalstoke Gearhulk", 548, Rarity.MYTHIC, mage.cards.c.CoalstokeGearhulk.class, NON_FULL_USE_VARIOUS));
|
||||||
cards.add(new SetCardInfo("Collision Course", 10, Rarity.COMMON, mage.cards.c.CollisionCourse.class));
|
cards.add(new SetCardInfo("Collision Course", 10, Rarity.COMMON, mage.cards.c.CollisionCourse.class));
|
||||||
cards.add(new SetCardInfo("Count on Luck", 118, Rarity.RARE, mage.cards.c.CountOnLuck.class));
|
cards.add(new SetCardInfo("Count on Luck", 118, Rarity.RARE, mage.cards.c.CountOnLuck.class));
|
||||||
cards.add(new SetCardInfo("Country Roads", 253, Rarity.UNCOMMON, mage.cards.c.CountryRoads.class));
|
cards.add(new SetCardInfo("Country Roads", 253, Rarity.UNCOMMON, mage.cards.c.CountryRoads.class));
|
||||||
cards.add(new SetCardInfo("Crash and Burn", 119, Rarity.COMMON, mage.cards.c.CrashAndBurn.class));
|
cards.add(new SetCardInfo("Crash and Burn", 119, Rarity.COMMON, mage.cards.c.CrashAndBurn.class));
|
||||||
cards.add(new SetCardInfo("Cryptcaller Chariot", 80, Rarity.RARE, mage.cards.c.CryptcallerChariot.class));
|
cards.add(new SetCardInfo("Cryptcaller Chariot", 80, Rarity.RARE, mage.cards.c.CryptcallerChariot.class));
|
||||||
|
cards.add(new SetCardInfo("Cursecloth Wrappings", 81, Rarity.RARE, mage.cards.c.CurseclothWrappings.class, NON_FULL_USE_VARIOUS));
|
||||||
|
cards.add(new SetCardInfo("Cursecloth Wrappings", 383, Rarity.RARE, mage.cards.c.CurseclothWrappings.class, NON_FULL_USE_VARIOUS));
|
||||||
|
cards.add(new SetCardInfo("Cursecloth Wrappings", 400, Rarity.MYTHIC, mage.cards.c.CurseclothWrappings.class, NON_FULL_USE_VARIOUS));
|
||||||
|
cards.add(new SetCardInfo("Cursecloth Wrappings", 410, Rarity.MYTHIC, mage.cards.c.CurseclothWrappings.class, NON_FULL_USE_VARIOUS));
|
||||||
|
cards.add(new SetCardInfo("Cursecloth Wrappings", 447, Rarity.RARE, mage.cards.c.CurseclothWrappings.class, NON_FULL_USE_VARIOUS));
|
||||||
cards.add(new SetCardInfo("Daretti, Rocketeer Engineer", 120, Rarity.RARE, mage.cards.d.DarettiRocketeerEngineer.class));
|
cards.add(new SetCardInfo("Daretti, Rocketeer Engineer", 120, Rarity.RARE, mage.cards.d.DarettiRocketeerEngineer.class));
|
||||||
cards.add(new SetCardInfo("Daring Mechanic", 11, Rarity.COMMON, mage.cards.d.DaringMechanic.class));
|
cards.add(new SetCardInfo("Daring Mechanic", 11, Rarity.COMMON, mage.cards.d.DaringMechanic.class));
|
||||||
cards.add(new SetCardInfo("Deathless Pilot", 82, Rarity.COMMON, mage.cards.d.DeathlessPilot.class));
|
cards.add(new SetCardInfo("Deathless Pilot", 82, Rarity.COMMON, mage.cards.d.DeathlessPilot.class));
|
||||||
cards.add(new SetCardInfo("Debris Beetle", 199, Rarity.RARE, mage.cards.d.DebrisBeetle.class));
|
cards.add(new SetCardInfo("Debris Beetle", 199, Rarity.RARE, mage.cards.d.DebrisBeetle.class));
|
||||||
cards.add(new SetCardInfo("Defend the Rider", 157, Rarity.UNCOMMON, mage.cards.d.DefendTheRider.class));
|
cards.add(new SetCardInfo("Defend the Rider", 157, Rarity.UNCOMMON, mage.cards.d.DefendTheRider.class));
|
||||||
|
cards.add(new SetCardInfo("Demonic Junker", 83, Rarity.RARE, mage.cards.d.DemonicJunker.class, NON_FULL_USE_VARIOUS));
|
||||||
|
cards.add(new SetCardInfo("Demonic Junker", 307, Rarity.RARE, mage.cards.d.DemonicJunker.class, NON_FULL_USE_VARIOUS));
|
||||||
|
cards.add(new SetCardInfo("Demonic Junker", 448, Rarity.RARE, mage.cards.d.DemonicJunker.class, NON_FULL_USE_VARIOUS));
|
||||||
|
cards.add(new SetCardInfo("Demonic Junker", 524, Rarity.RARE, mage.cards.d.DemonicJunker.class, NON_FULL_USE_VARIOUS));
|
||||||
cards.add(new SetCardInfo("Detention Chariot", 12, Rarity.UNCOMMON, mage.cards.d.DetentionChariot.class));
|
cards.add(new SetCardInfo("Detention Chariot", 12, Rarity.UNCOMMON, mage.cards.d.DetentionChariot.class));
|
||||||
cards.add(new SetCardInfo("Dismal Backwater", 254, Rarity.COMMON, mage.cards.d.DismalBackwater.class));
|
cards.add(new SetCardInfo("Dismal Backwater", 254, Rarity.COMMON, mage.cards.d.DismalBackwater.class));
|
||||||
cards.add(new SetCardInfo("District Mascot", 158, Rarity.RARE, mage.cards.d.DistrictMascot.class));
|
cards.add(new SetCardInfo("District Mascot", 158, Rarity.RARE, mage.cards.d.DistrictMascot.class));
|
||||||
|
|
@ -84,6 +104,7 @@ public final class Aetherdrift extends ExpansionSet {
|
||||||
cards.add(new SetCardInfo("Draconautics Engineer", 121, Rarity.RARE, mage.cards.d.DraconauticsEngineer.class));
|
cards.add(new SetCardInfo("Draconautics Engineer", 121, Rarity.RARE, mage.cards.d.DraconauticsEngineer.class));
|
||||||
cards.add(new SetCardInfo("Dracosaur Auxiliary", 122, Rarity.UNCOMMON, mage.cards.d.DracosaurAuxiliary.class));
|
cards.add(new SetCardInfo("Dracosaur Auxiliary", 122, Rarity.UNCOMMON, mage.cards.d.DracosaurAuxiliary.class));
|
||||||
cards.add(new SetCardInfo("Dredger's Insight", 159, Rarity.UNCOMMON, mage.cards.d.DredgersInsight.class));
|
cards.add(new SetCardInfo("Dredger's Insight", 159, Rarity.UNCOMMON, mage.cards.d.DredgersInsight.class));
|
||||||
|
cards.add(new SetCardInfo("Dune Drifter", 200, Rarity.UNCOMMON, mage.cards.d.DuneDrifter.class));
|
||||||
cards.add(new SetCardInfo("Dynamite Diver", 123, Rarity.COMMON, mage.cards.d.DynamiteDiver.class));
|
cards.add(new SetCardInfo("Dynamite Diver", 123, Rarity.COMMON, mage.cards.d.DynamiteDiver.class));
|
||||||
cards.add(new SetCardInfo("Earthrumbler", 160, Rarity.UNCOMMON, mage.cards.e.Earthrumbler.class));
|
cards.add(new SetCardInfo("Earthrumbler", 160, Rarity.UNCOMMON, mage.cards.e.Earthrumbler.class));
|
||||||
cards.add(new SetCardInfo("Embalmed Ascendant", 201, Rarity.UNCOMMON, mage.cards.e.EmbalmedAscendant.class));
|
cards.add(new SetCardInfo("Embalmed Ascendant", 201, Rarity.UNCOMMON, mage.cards.e.EmbalmedAscendant.class));
|
||||||
|
|
|
||||||
|
|
@ -110,6 +110,8 @@ public final class AetherdriftCommander extends ExpansionSet {
|
||||||
cards.add(new SetCardInfo("Midnight Reaper", 44, Rarity.RARE, mage.cards.m.MidnightReaper.class));
|
cards.add(new SetCardInfo("Midnight Reaper", 44, Rarity.RARE, mage.cards.m.MidnightReaper.class));
|
||||||
cards.add(new SetCardInfo("Murderous Rider", 45, Rarity.RARE, mage.cards.m.MurderousRider.class));
|
cards.add(new SetCardInfo("Murderous Rider", 45, Rarity.RARE, mage.cards.m.MurderousRider.class));
|
||||||
cards.add(new SetCardInfo("Never // Return", 96, Rarity.RARE, mage.cards.n.NeverReturn.class));
|
cards.add(new SetCardInfo("Never // Return", 96, Rarity.RARE, mage.cards.n.NeverReturn.class));
|
||||||
|
cards.add(new SetCardInfo("Nissa, Worldsoul Speaker", 13, Rarity.RARE, mage.cards.n.NissaWorldsoulSpeaker.class, NON_FULL_USE_VARIOUS));
|
||||||
|
cards.add(new SetCardInfo("Nissa, Worldsoul Speaker", 29, Rarity.RARE, mage.cards.n.NissaWorldsoulSpeaker.class, NON_FULL_USE_VARIOUS));
|
||||||
cards.add(new SetCardInfo("On Wings of Gold", 5, Rarity.RARE, mage.cards.o.OnWingsOfGold.class));
|
cards.add(new SetCardInfo("On Wings of Gold", 5, Rarity.RARE, mage.cards.o.OnWingsOfGold.class));
|
||||||
cards.add(new SetCardInfo("One with the Machine", 80, Rarity.RARE, mage.cards.o.OneWithTheMachine.class));
|
cards.add(new SetCardInfo("One with the Machine", 80, Rarity.RARE, mage.cards.o.OneWithTheMachine.class));
|
||||||
cards.add(new SetCardInfo("Ornithopter of Paradise", 133, Rarity.COMMON, mage.cards.o.OrnithopterOfParadise.class));
|
cards.add(new SetCardInfo("Ornithopter of Paradise", 133, Rarity.COMMON, mage.cards.o.OrnithopterOfParadise.class));
|
||||||
|
|
|
||||||
|
|
@ -30,9 +30,9 @@ public final class AssassinsCreed extends ExpansionSet {
|
||||||
cards.add(new SetCardInfo("Adewale, Breaker of Chains", 44, Rarity.UNCOMMON, mage.cards.a.AdewaleBreakerOfChains.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("Adewale, Breaker of Chains", 44, Rarity.UNCOMMON, mage.cards.a.AdewaleBreakerOfChains.class, NON_FULL_USE_VARIOUS));
|
||||||
cards.add(new SetCardInfo("Adrestia", 252, Rarity.UNCOMMON, mage.cards.a.Adrestia.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("Adrestia", 252, Rarity.UNCOMMON, mage.cards.a.Adrestia.class, NON_FULL_USE_VARIOUS));
|
||||||
cards.add(new SetCardInfo("Adrestia", 68, Rarity.UNCOMMON, mage.cards.a.Adrestia.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("Adrestia", 68, Rarity.UNCOMMON, mage.cards.a.Adrestia.class, NON_FULL_USE_VARIOUS));
|
||||||
//cards.add(new SetCardInfo("Alexios, Deimos of Kosmos", 134, Rarity.UNCOMMON, mage.cards.a.AlexiosDeimosOfKosmos.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("Alexios, Deimos of Kosmos", 134, Rarity.UNCOMMON, mage.cards.a.AlexiosDeimosOfKosmos.class, NON_FULL_USE_VARIOUS));
|
||||||
//cards.add(new SetCardInfo("Alexios, Deimos of Kosmos", 214, Rarity.UNCOMMON, mage.cards.a.AlexiosDeimosOfKosmos.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("Alexios, Deimos of Kosmos", 214, Rarity.UNCOMMON, mage.cards.a.AlexiosDeimosOfKosmos.class, NON_FULL_USE_VARIOUS));
|
||||||
//cards.add(new SetCardInfo("Alexios, Deimos of Kosmos", 33, Rarity.UNCOMMON, mage.cards.a.AlexiosDeimosOfKosmos.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("Alexios, Deimos of Kosmos", 33, Rarity.UNCOMMON, mage.cards.a.AlexiosDeimosOfKosmos.class, NON_FULL_USE_VARIOUS));
|
||||||
//cards.add(new SetCardInfo("Altair Ibn-La'Ahad", 137, Rarity.MYTHIC, mage.cards.a.AltairIbnLaAhad.class, NON_FULL_USE_VARIOUS));
|
//cards.add(new SetCardInfo("Altair Ibn-La'Ahad", 137, Rarity.MYTHIC, mage.cards.a.AltairIbnLaAhad.class, NON_FULL_USE_VARIOUS));
|
||||||
//cards.add(new SetCardInfo("Altair Ibn-La'Ahad", 225, Rarity.MYTHIC, mage.cards.a.AltairIbnLaAhad.class, NON_FULL_USE_VARIOUS));
|
//cards.add(new SetCardInfo("Altair Ibn-La'Ahad", 225, Rarity.MYTHIC, mage.cards.a.AltairIbnLaAhad.class, NON_FULL_USE_VARIOUS));
|
||||||
//cards.add(new SetCardInfo("Altair Ibn-La'Ahad", 268, Rarity.MYTHIC, mage.cards.a.AltairIbnLaAhad.class, NON_FULL_USE_VARIOUS));
|
//cards.add(new SetCardInfo("Altair Ibn-La'Ahad", 268, Rarity.MYTHIC, mage.cards.a.AltairIbnLaAhad.class, NON_FULL_USE_VARIOUS));
|
||||||
|
|
@ -77,8 +77,8 @@ public final class AssassinsCreed extends ExpansionSet {
|
||||||
cards.add(new SetCardInfo("Bleeding Effect", 232, Rarity.UNCOMMON, mage.cards.b.BleedingEffect.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("Bleeding Effect", 232, Rarity.UNCOMMON, mage.cards.b.BleedingEffect.class, NON_FULL_USE_VARIOUS));
|
||||||
cards.add(new SetCardInfo("Bleeding Effect", 51, Rarity.UNCOMMON, mage.cards.b.BleedingEffect.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("Bleeding Effect", 51, Rarity.UNCOMMON, mage.cards.b.BleedingEffect.class, NON_FULL_USE_VARIOUS));
|
||||||
cards.add(new SetCardInfo("Brotherhood Ambushers", 285, Rarity.UNCOMMON, mage.cards.b.BrotherhoodAmbushers.class));
|
cards.add(new SetCardInfo("Brotherhood Ambushers", 285, Rarity.UNCOMMON, mage.cards.b.BrotherhoodAmbushers.class));
|
||||||
//cards.add(new SetCardInfo("Brotherhood Headquarters", 266, Rarity.UNCOMMON, mage.cards.b.BrotherhoodHeadquarters.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("Brotherhood Headquarters", 266, Rarity.UNCOMMON, mage.cards.b.BrotherhoodHeadquarters.class, NON_FULL_USE_VARIOUS));
|
||||||
//cards.add(new SetCardInfo("Brotherhood Headquarters", 80, Rarity.UNCOMMON, mage.cards.b.BrotherhoodHeadquarters.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("Brotherhood Headquarters", 80, Rarity.UNCOMMON, mage.cards.b.BrotherhoodHeadquarters.class, NON_FULL_USE_VARIOUS));
|
||||||
cards.add(new SetCardInfo("Brotherhood Patriarch", 286, Rarity.COMMON, mage.cards.b.BrotherhoodPatriarch.class));
|
cards.add(new SetCardInfo("Brotherhood Patriarch", 286, Rarity.COMMON, mage.cards.b.BrotherhoodPatriarch.class));
|
||||||
cards.add(new SetCardInfo("Brotherhood Regalia", 255, Rarity.UNCOMMON, mage.cards.b.BrotherhoodRegalia.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("Brotherhood Regalia", 255, Rarity.UNCOMMON, mage.cards.b.BrotherhoodRegalia.class, NON_FULL_USE_VARIOUS));
|
||||||
cards.add(new SetCardInfo("Brotherhood Regalia", 71, Rarity.UNCOMMON, mage.cards.b.BrotherhoodRegalia.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("Brotherhood Regalia", 71, Rarity.UNCOMMON, mage.cards.b.BrotherhoodRegalia.class, NON_FULL_USE_VARIOUS));
|
||||||
|
|
@ -157,9 +157,9 @@ public final class AssassinsCreed extends ExpansionSet {
|
||||||
//cards.add(new SetCardInfo("Havi, the All-Father", 56, Rarity.RARE, mage.cards.h.HaviTheAllFather.class, NON_FULL_USE_VARIOUS));
|
//cards.add(new SetCardInfo("Havi, the All-Father", 56, Rarity.RARE, mage.cards.h.HaviTheAllFather.class, NON_FULL_USE_VARIOUS));
|
||||||
cards.add(new SetCardInfo("Haystack", 175, Rarity.UNCOMMON, mage.cards.h.Haystack.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("Haystack", 175, Rarity.UNCOMMON, mage.cards.h.Haystack.class, NON_FULL_USE_VARIOUS));
|
||||||
cards.add(new SetCardInfo("Haystack", 5, Rarity.UNCOMMON, mage.cards.h.Haystack.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("Haystack", 5, Rarity.UNCOMMON, mage.cards.h.Haystack.class, NON_FULL_USE_VARIOUS));
|
||||||
//cards.add(new SetCardInfo("Haytham Kenway", 147, Rarity.RARE, mage.cards.h.HaythamKenway.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("Haytham Kenway", 57, Rarity.RARE, mage.cards.h.HaythamKenway.class, NON_FULL_USE_VARIOUS));
|
||||||
//cards.add(new SetCardInfo("Haytham Kenway", 238, Rarity.RARE, mage.cards.h.HaythamKenway.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("Haytham Kenway", 147, Rarity.RARE, mage.cards.h.HaythamKenway.class, NON_FULL_USE_VARIOUS));
|
||||||
//cards.add(new SetCardInfo("Haytham Kenway", 57, Rarity.RARE, mage.cards.h.HaythamKenway.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("Haytham Kenway", 238, Rarity.RARE, mage.cards.h.HaythamKenway.class, NON_FULL_USE_VARIOUS));
|
||||||
cards.add(new SetCardInfo("Headsplitter", 289, Rarity.COMMON, mage.cards.h.Headsplitter.class));
|
cards.add(new SetCardInfo("Headsplitter", 289, Rarity.COMMON, mage.cards.h.Headsplitter.class));
|
||||||
cards.add(new SetCardInfo("Hemlock Vial", 206, Rarity.UNCOMMON, mage.cards.h.HemlockVial.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("Hemlock Vial", 206, Rarity.UNCOMMON, mage.cards.h.HemlockVial.class, NON_FULL_USE_VARIOUS));
|
||||||
cards.add(new SetCardInfo("Hemlock Vial", 26, Rarity.UNCOMMON, mage.cards.h.HemlockVial.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("Hemlock Vial", 26, Rarity.UNCOMMON, mage.cards.h.HemlockVial.class, NON_FULL_USE_VARIOUS));
|
||||||
|
|
@ -321,12 +321,12 @@ public final class AssassinsCreed extends ExpansionSet {
|
||||||
cards.add(new SetCardInfo("Towering Viewpoint", 263, Rarity.UNCOMMON, mage.cards.t.ToweringViewpoint.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("Towering Viewpoint", 263, Rarity.UNCOMMON, mage.cards.t.ToweringViewpoint.class, NON_FULL_USE_VARIOUS));
|
||||||
cards.add(new SetCardInfo("Towering Viewpoint", 77, Rarity.UNCOMMON, mage.cards.t.ToweringViewpoint.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("Towering Viewpoint", 77, Rarity.UNCOMMON, mage.cards.t.ToweringViewpoint.class, NON_FULL_USE_VARIOUS));
|
||||||
cards.add(new SetCardInfo("Tranquilize", 284, Rarity.COMMON, mage.cards.t.Tranquilize.class));
|
cards.add(new SetCardInfo("Tranquilize", 284, Rarity.COMMON, mage.cards.t.Tranquilize.class));
|
||||||
//cards.add(new SetCardInfo("Viewpoint Synchronization", 223, Rarity.UNCOMMON, mage.cards.v.ViewpointSynchronization.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("Viewpoint Synchronization", 223, Rarity.UNCOMMON, mage.cards.v.ViewpointSynchronization.class, NON_FULL_USE_VARIOUS));
|
||||||
//cards.add(new SetCardInfo("Viewpoint Synchronization", 43, Rarity.UNCOMMON, mage.cards.v.ViewpointSynchronization.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("Viewpoint Synchronization", 43, Rarity.UNCOMMON, mage.cards.v.ViewpointSynchronization.class, NON_FULL_USE_VARIOUS));
|
||||||
cards.add(new SetCardInfo("Waterlogged Grove", 116, Rarity.RARE, mage.cards.w.WaterloggedGrove.class));
|
cards.add(new SetCardInfo("Waterlogged Grove", 116, Rarity.RARE, mage.cards.w.WaterloggedGrove.class));
|
||||||
//cards.add(new SetCardInfo("What Must Be Done", 11, Rarity.RARE, mage.cards.w.WhatMustBeDone.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("What Must Be Done", 11, Rarity.RARE, mage.cards.w.WhatMustBeDone.class, NON_FULL_USE_VARIOUS));
|
||||||
//cards.add(new SetCardInfo("What Must Be Done", 157, Rarity.RARE, mage.cards.w.WhatMustBeDone.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("What Must Be Done", 157, Rarity.RARE, mage.cards.w.WhatMustBeDone.class, NON_FULL_USE_VARIOUS));
|
||||||
//cards.add(new SetCardInfo("What Must Be Done", 184, Rarity.RARE, mage.cards.w.WhatMustBeDone.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("What Must Be Done", 184, Rarity.RARE, mage.cards.w.WhatMustBeDone.class, NON_FULL_USE_VARIOUS));
|
||||||
cards.add(new SetCardInfo("Yggdrasil, Rebirth Engine", 126, Rarity.MYTHIC, mage.cards.y.YggdrasilRebirthEngine.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("Yggdrasil, Rebirth Engine", 126, Rarity.MYTHIC, mage.cards.y.YggdrasilRebirthEngine.class, NON_FULL_USE_VARIOUS));
|
||||||
cards.add(new SetCardInfo("Yggdrasil, Rebirth Engine", 264, Rarity.MYTHIC, mage.cards.y.YggdrasilRebirthEngine.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("Yggdrasil, Rebirth Engine", 264, Rarity.MYTHIC, mage.cards.y.YggdrasilRebirthEngine.class, NON_FULL_USE_VARIOUS));
|
||||||
cards.add(new SetCardInfo("Yggdrasil, Rebirth Engine", 78, Rarity.MYTHIC, mage.cards.y.YggdrasilRebirthEngine.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("Yggdrasil, Rebirth Engine", 78, Rarity.MYTHIC, mage.cards.y.YggdrasilRebirthEngine.class, NON_FULL_USE_VARIOUS));
|
||||||
|
|
|
||||||
|
|
@ -95,10 +95,10 @@ public final class DoctorWho extends ExpansionSet {
|
||||||
cards.add(new SetCardInfo("Bessie, the Doctor's Roadster", 776, Rarity.RARE, mage.cards.b.BessieTheDoctorsRoadster.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("Bessie, the Doctor's Roadster", 776, Rarity.RARE, mage.cards.b.BessieTheDoctorsRoadster.class, NON_FULL_USE_VARIOUS));
|
||||||
cards.add(new SetCardInfo("Bigger on the Inside", 115, Rarity.UNCOMMON, mage.cards.b.BiggerOnTheInside.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("Bigger on the Inside", 115, Rarity.UNCOMMON, mage.cards.b.BiggerOnTheInside.class, NON_FULL_USE_VARIOUS));
|
||||||
cards.add(new SetCardInfo("Bigger on the Inside", 720, Rarity.UNCOMMON, mage.cards.b.BiggerOnTheInside.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("Bigger on the Inside", 720, Rarity.UNCOMMON, mage.cards.b.BiggerOnTheInside.class, NON_FULL_USE_VARIOUS));
|
||||||
//cards.add(new SetCardInfo("Bill Potts", 379, Rarity.RARE, mage.cards.b.BillPotts.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("Bill Potts", 379, Rarity.RARE, mage.cards.b.BillPotts.class, NON_FULL_USE_VARIOUS));
|
||||||
//cards.add(new SetCardInfo("Bill Potts", 681, Rarity.RARE, mage.cards.b.BillPotts.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("Bill Potts", 681, Rarity.RARE, mage.cards.b.BillPotts.class, NON_FULL_USE_VARIOUS));
|
||||||
//cards.add(new SetCardInfo("Bill Potts", 76, Rarity.RARE, mage.cards.b.BillPotts.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("Bill Potts", 76, Rarity.RARE, mage.cards.b.BillPotts.class, NON_FULL_USE_VARIOUS));
|
||||||
//cards.add(new SetCardInfo("Bill Potts", 970, Rarity.RARE, mage.cards.b.BillPotts.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("Bill Potts", 970, Rarity.RARE, mage.cards.b.BillPotts.class, NON_FULL_USE_VARIOUS));
|
||||||
cards.add(new SetCardInfo("Blasphemous Act", 1063, Rarity.RARE, mage.cards.b.BlasphemousAct.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("Blasphemous Act", 1063, Rarity.RARE, mage.cards.b.BlasphemousAct.class, NON_FULL_USE_VARIOUS));
|
||||||
cards.add(new SetCardInfo("Blasphemous Act", 224, Rarity.RARE, mage.cards.b.BlasphemousAct.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("Blasphemous Act", 224, Rarity.RARE, mage.cards.b.BlasphemousAct.class, NON_FULL_USE_VARIOUS));
|
||||||
cards.add(new SetCardInfo("Blasphemous Act", 472, Rarity.RARE, mage.cards.b.BlasphemousAct.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("Blasphemous Act", 472, Rarity.RARE, mage.cards.b.BlasphemousAct.class, NON_FULL_USE_VARIOUS));
|
||||||
|
|
@ -955,8 +955,8 @@ public final class DoctorWho extends ExpansionSet {
|
||||||
cards.add(new SetCardInfo("The Fugitive Doctor", 417, Rarity.RARE, mage.cards.t.TheFugitiveDoctor.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("The Fugitive Doctor", 417, Rarity.RARE, mage.cards.t.TheFugitiveDoctor.class, NON_FULL_USE_VARIOUS));
|
||||||
cards.add(new SetCardInfo("The Fugitive Doctor", 541, Rarity.RARE, mage.cards.t.TheFugitiveDoctor.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("The Fugitive Doctor", 541, Rarity.RARE, mage.cards.t.TheFugitiveDoctor.class, NON_FULL_USE_VARIOUS));
|
||||||
cards.add(new SetCardInfo("The Fugitive Doctor", 735, Rarity.RARE, mage.cards.t.TheFugitiveDoctor.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("The Fugitive Doctor", 735, Rarity.RARE, mage.cards.t.TheFugitiveDoctor.class, NON_FULL_USE_VARIOUS));
|
||||||
//cards.add(new SetCardInfo("The Girl in the Fireplace", 21, Rarity.RARE, mage.cards.t.TheGirlInTheFireplace.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("The Girl in the Fireplace", 21, Rarity.RARE, mage.cards.t.TheGirlInTheFireplace.class, NON_FULL_USE_VARIOUS));
|
||||||
//cards.add(new SetCardInfo("The Girl in the Fireplace", 626, Rarity.RARE, mage.cards.t.TheGirlInTheFireplace.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("The Girl in the Fireplace", 626, Rarity.RARE, mage.cards.t.TheGirlInTheFireplace.class, NON_FULL_USE_VARIOUS));
|
||||||
//cards.add(new SetCardInfo("The Lux Foundation Library", 588, Rarity.COMMON, mage.cards.t.TheLuxFoundationLibrary.class));
|
//cards.add(new SetCardInfo("The Lux Foundation Library", 588, Rarity.COMMON, mage.cards.t.TheLuxFoundationLibrary.class));
|
||||||
//cards.add(new SetCardInfo("The Master, Formed Anew", 1017, Rarity.RARE, mage.cards.t.TheMasterFormedAnew.class, NON_FULL_USE_VARIOUS));
|
//cards.add(new SetCardInfo("The Master, Formed Anew", 1017, Rarity.RARE, mage.cards.t.TheMasterFormedAnew.class, NON_FULL_USE_VARIOUS));
|
||||||
//cards.add(new SetCardInfo("The Master, Formed Anew", 1133, Rarity.RARE, mage.cards.t.TheMasterFormedAnew.class, NON_FULL_USE_VARIOUS));
|
//cards.add(new SetCardInfo("The Master, Formed Anew", 1133, Rarity.RARE, mage.cards.t.TheMasterFormedAnew.class, NON_FULL_USE_VARIOUS));
|
||||||
|
|
|
||||||
|
|
@ -835,10 +835,10 @@ public final class Fallout extends ExpansionSet {
|
||||||
//cards.add(new SetCardInfo("Strong Back", 611, Rarity.RARE, mage.cards.s.StrongBack.class, NON_FULL_USE_VARIOUS));
|
//cards.add(new SetCardInfo("Strong Back", 611, Rarity.RARE, mage.cards.s.StrongBack.class, NON_FULL_USE_VARIOUS));
|
||||||
//cards.add(new SetCardInfo("Strong Back", 83, Rarity.RARE, mage.cards.s.StrongBack.class, NON_FULL_USE_VARIOUS));
|
//cards.add(new SetCardInfo("Strong Back", 83, Rarity.RARE, mage.cards.s.StrongBack.class, NON_FULL_USE_VARIOUS));
|
||||||
//cards.add(new SetCardInfo("Strong Back", 930, Rarity.RARE, mage.cards.s.StrongBack.class, NON_FULL_USE_VARIOUS));
|
//cards.add(new SetCardInfo("Strong Back", 930, Rarity.RARE, mage.cards.s.StrongBack.class, NON_FULL_USE_VARIOUS));
|
||||||
//cards.add(new SetCardInfo("Strong, the Brutish Thespian", 403, Rarity.RARE, mage.cards.s.StrongTheBrutishThespian.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("Strong, the Brutish Thespian", 403, Rarity.RARE, mage.cards.s.StrongTheBrutishThespian.class, NON_FULL_USE_VARIOUS));
|
||||||
//cards.add(new SetCardInfo("Strong, the Brutish Thespian", 612, Rarity.RARE, mage.cards.s.StrongTheBrutishThespian.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("Strong, the Brutish Thespian", 612, Rarity.RARE, mage.cards.s.StrongTheBrutishThespian.class, NON_FULL_USE_VARIOUS));
|
||||||
//cards.add(new SetCardInfo("Strong, the Brutish Thespian", 84, Rarity.RARE, mage.cards.s.StrongTheBrutishThespian.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("Strong, the Brutish Thespian", 84, Rarity.RARE, mage.cards.s.StrongTheBrutishThespian.class, NON_FULL_USE_VARIOUS));
|
||||||
//cards.add(new SetCardInfo("Strong, the Brutish Thespian", 931, Rarity.RARE, mage.cards.s.StrongTheBrutishThespian.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("Strong, the Brutish Thespian", 931, Rarity.RARE, mage.cards.s.StrongTheBrutishThespian.class, NON_FULL_USE_VARIOUS));
|
||||||
cards.add(new SetCardInfo("Struggle for Project Purity", 380, Rarity.RARE, mage.cards.s.StruggleForProjectPurity.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("Struggle for Project Purity", 380, Rarity.RARE, mage.cards.s.StruggleForProjectPurity.class, NON_FULL_USE_VARIOUS));
|
||||||
cards.add(new SetCardInfo("Struggle for Project Purity", 39, Rarity.RARE, mage.cards.s.StruggleForProjectPurity.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("Struggle for Project Purity", 39, Rarity.RARE, mage.cards.s.StruggleForProjectPurity.class, NON_FULL_USE_VARIOUS));
|
||||||
cards.add(new SetCardInfo("Struggle for Project Purity", 567, Rarity.RARE, mage.cards.s.StruggleForProjectPurity.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("Struggle for Project Purity", 567, Rarity.RARE, mage.cards.s.StruggleForProjectPurity.class, NON_FULL_USE_VARIOUS));
|
||||||
|
|
|
||||||
28
Mage.Sets/src/mage/sets/FinalFantasy.java
Normal file
28
Mage.Sets/src/mage/sets/FinalFantasy.java
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
package mage.sets;
|
||||||
|
|
||||||
|
import mage.cards.ExpansionSet;
|
||||||
|
import mage.constants.Rarity;
|
||||||
|
import mage.constants.SetType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public final class FinalFantasy extends ExpansionSet {
|
||||||
|
|
||||||
|
private static final FinalFantasy instance = new FinalFantasy();
|
||||||
|
|
||||||
|
public static FinalFantasy getInstance() {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private FinalFantasy() {
|
||||||
|
super("Final Fantasy", "FIN", ExpansionSet.buildDate(2025, 6, 13), SetType.EXPANSION);
|
||||||
|
this.blockName = "Final Fantasy"; // for sorting in GUI
|
||||||
|
this.hasBasicLands = false; // temporary
|
||||||
|
|
||||||
|
cards.add(new SetCardInfo("Jumbo Cactuar", 191, Rarity.RARE, mage.cards.j.JumboCactuar.class));
|
||||||
|
cards.add(new SetCardInfo("Sazh's Chocobo", 200, Rarity.UNCOMMON, mage.cards.s.SazhsChocobo.class));
|
||||||
|
cards.add(new SetCardInfo("Summon: Shiva", 78, Rarity.UNCOMMON, mage.cards.s.SummonShiva.class));
|
||||||
|
cards.add(new SetCardInfo("Tonberry", 122, Rarity.UNCOMMON, mage.cards.t.Tonberry.class));
|
||||||
|
}
|
||||||
|
}
|
||||||
24
Mage.Sets/src/mage/sets/FinalFantasyCommander.java
Normal file
24
Mage.Sets/src/mage/sets/FinalFantasyCommander.java
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
package mage.sets;
|
||||||
|
|
||||||
|
import mage.cards.ExpansionSet;
|
||||||
|
import mage.constants.Rarity;
|
||||||
|
import mage.constants.SetType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public final class FinalFantasyCommander extends ExpansionSet {
|
||||||
|
|
||||||
|
private static final FinalFantasyCommander instance = new FinalFantasyCommander();
|
||||||
|
|
||||||
|
public static FinalFantasyCommander getInstance() {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private FinalFantasyCommander() {
|
||||||
|
super("Final Fantasy Commander", "FIC", ExpansionSet.buildDate(2025, 6, 13), SetType.SUPPLEMENTAL);
|
||||||
|
this.hasBasicLands = false;
|
||||||
|
|
||||||
|
cards.add(new SetCardInfo("Terra, Herald of Hope", 4, Rarity.MYTHIC, mage.cards.t.TerraHeraldOfHope.class));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -253,7 +253,7 @@ public final class RavnicaClueEdition extends ExpansionSet {
|
||||||
cards.add(new SetCardInfo("Stunt Double", 101, Rarity.RARE, mage.cards.s.StuntDouble.class));
|
cards.add(new SetCardInfo("Stunt Double", 101, Rarity.RARE, mage.cards.s.StuntDouble.class));
|
||||||
cards.add(new SetCardInfo("Sumala Rumblers", 45, Rarity.UNCOMMON, mage.cards.s.SumalaRumblers.class));
|
cards.add(new SetCardInfo("Sumala Rumblers", 45, Rarity.UNCOMMON, mage.cards.s.SumalaRumblers.class));
|
||||||
cards.add(new SetCardInfo("Sunhome Stalwart", 73, Rarity.UNCOMMON, mage.cards.s.SunhomeStalwart.class));
|
cards.add(new SetCardInfo("Sunhome Stalwart", 73, Rarity.UNCOMMON, mage.cards.s.SunhomeStalwart.class));
|
||||||
//cards.add(new SetCardInfo("Suppressor Skyguard", 46, Rarity.RARE, mage.cards.s.SuppressorSkyguard.class));
|
cards.add(new SetCardInfo("Suppressor Skyguard", 46, Rarity.RARE, mage.cards.s.SuppressorSkyguard.class));
|
||||||
cards.add(new SetCardInfo("Supreme Verdict", 211, Rarity.RARE, mage.cards.s.SupremeVerdict.class));
|
cards.add(new SetCardInfo("Supreme Verdict", 211, Rarity.RARE, mage.cards.s.SupremeVerdict.class));
|
||||||
cards.add(new SetCardInfo("Swamp", 262, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("Swamp", 262, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS));
|
||||||
cards.add(new SetCardInfo("Swamp", 263, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS));
|
cards.add(new SetCardInfo("Swamp", 263, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS));
|
||||||
|
|
|
||||||
32
Mage.Sets/src/mage/sets/TarkirDragonstorm.java
Normal file
32
Mage.Sets/src/mage/sets/TarkirDragonstorm.java
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
package mage.sets;
|
||||||
|
|
||||||
|
import mage.cards.ExpansionSet;
|
||||||
|
import mage.constants.Rarity;
|
||||||
|
import mage.constants.SetType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public final class TarkirDragonstorm extends ExpansionSet {
|
||||||
|
|
||||||
|
private static final TarkirDragonstorm instance = new TarkirDragonstorm();
|
||||||
|
|
||||||
|
public static TarkirDragonstorm getInstance() {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private TarkirDragonstorm() {
|
||||||
|
super("Tarkir: Dragonstorm", "TDM", ExpansionSet.buildDate(2025, 4, 11), SetType.EXPANSION);
|
||||||
|
this.blockName = "Tarkir: Dragonstorm"; // for sorting in GUI
|
||||||
|
this.hasBasicLands = false; // temporary
|
||||||
|
|
||||||
|
cards.add(new SetCardInfo("Barrensteppe Siege", 171, Rarity.RARE, mage.cards.b.BarrensteppeSiege.class));
|
||||||
|
cards.add(new SetCardInfo("Inevitable Defeat", 194, Rarity.RARE, mage.cards.i.InevitableDefeat.class));
|
||||||
|
cards.add(new SetCardInfo("Mox Jasper", 246, Rarity.MYTHIC, mage.cards.m.MoxJasper.class));
|
||||||
|
cards.add(new SetCardInfo("Narset, Jeskai Waymaster", 209, Rarity.RARE, mage.cards.n.NarsetJeskaiWaymaster.class));
|
||||||
|
cards.add(new SetCardInfo("Shiko, Paragon of the Way", 223, Rarity.MYTHIC, mage.cards.s.ShikoParagonOfTheWay.class));
|
||||||
|
cards.add(new SetCardInfo("Skirmish Rhino", 224, Rarity.UNCOMMON, mage.cards.s.SkirmishRhino.class));
|
||||||
|
cards.add(new SetCardInfo("Smile at Death", 24, Rarity.MYTHIC, mage.cards.s.SmileAtDeath.class));
|
||||||
|
cards.add(new SetCardInfo("Stormscale Scion", 123, Rarity.MYTHIC, mage.cards.s.StormscaleScion.class));
|
||||||
|
}
|
||||||
|
}
|
||||||
24
Mage.Sets/src/mage/sets/TarkirDragonstormCommander.java
Normal file
24
Mage.Sets/src/mage/sets/TarkirDragonstormCommander.java
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
package mage.sets;
|
||||||
|
|
||||||
|
import mage.cards.ExpansionSet;
|
||||||
|
import mage.constants.Rarity;
|
||||||
|
import mage.constants.SetType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public final class TarkirDragonstormCommander extends ExpansionSet {
|
||||||
|
|
||||||
|
private static final TarkirDragonstormCommander instance = new TarkirDragonstormCommander();
|
||||||
|
|
||||||
|
public static TarkirDragonstormCommander getInstance() {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private TarkirDragonstormCommander() {
|
||||||
|
super("Tarkir: Dragonstorm Commander", "TDC", ExpansionSet.buildDate(2025, 4, 11), SetType.SUPPLEMENTAL);
|
||||||
|
this.hasBasicLands = false;
|
||||||
|
|
||||||
|
cards.add(new SetCardInfo("Teval, the Balanced Scale", 8, Rarity.MYTHIC, mage.cards.t.TevalTheBalancedScale.class));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
package org.mage.test.cards.single.dft;
|
||||||
|
|
||||||
|
import mage.abilities.keyword.FlyingAbility;
|
||||||
|
import mage.constants.PhaseStep;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import mage.counters.CounterType;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author jimga150
|
||||||
|
*/
|
||||||
|
public class MuYanlingWindRiderTest extends CardTestPlayerBase {
|
||||||
|
|
||||||
|
// When this creature enters, create a 3/2 colorless Vehicle artifact token with crew 1.
|
||||||
|
// Vehicles you control have flying.
|
||||||
|
// Whenever one or more creatures you control with flying deal combat damage to a player, draw a card.
|
||||||
|
private final String muyanling = "Mu Yanling, Wind Rider";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testToken() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Island", 4);
|
||||||
|
addCard(Zone.HAND, playerA, muyanling);
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, muyanling, true);
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertPermanentCount(playerA, muyanling, 1);
|
||||||
|
assertPermanentCount(playerA, "Vehicle Token", 1);
|
||||||
|
assertAbility(playerA, "Vehicle Token", FlyingAbility.getInstance(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDraw() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Island", 4);
|
||||||
|
addCard(Zone.HAND, playerA, muyanling);
|
||||||
|
addCard(Zone.HAND, playerA, "Memnite");
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Ankle Biter");
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, muyanling, true);
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Memnite", true);
|
||||||
|
|
||||||
|
activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Crew 1");
|
||||||
|
setChoice(playerA, "Memnite");
|
||||||
|
|
||||||
|
attack(3, playerA, "Vehicle Token", playerB);
|
||||||
|
attack(3, playerA, muyanling, playerB);
|
||||||
|
attack(3, playerA, "Ankle Biter", playerB);
|
||||||
|
|
||||||
|
setStopAt(3, PhaseStep.POSTCOMBAT_MAIN);
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertPermanentCount(playerA, muyanling, 1);
|
||||||
|
assertPermanentCount(playerA, "Vehicle Token", 1);
|
||||||
|
assertAbility(playerA, "Vehicle Token", FlyingAbility.getInstance(), true);
|
||||||
|
assertHandCount(playerA, 2); // 1 for turn plus 1 for attack
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,118 @@
|
||||||
|
package org.mage.test.cards.single.ncc;
|
||||||
|
|
||||||
|
import mage.constants.PhaseStep;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import org.junit.Ignore;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Susucr
|
||||||
|
*/
|
||||||
|
public class RainOfRichesTest extends CardTestPlayerBase {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link mage.cards.r.RainOfRiches Rain of Riches} {3}{R}{R}
|
||||||
|
* Enchantment
|
||||||
|
* When Rain of Riches enters the battlefield, create two Treasure tokens.
|
||||||
|
* The first spell you cast each turn that mana from a Treasure was spent to cast has cascade.
|
||||||
|
*/
|
||||||
|
private static final String rain = "Rain of Riches";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_Using_Treasures() {
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
|
||||||
|
addCard(Zone.HAND, playerA, rain, 1);
|
||||||
|
addCard(Zone.HAND, playerA, "Goblin Piker", 1);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 5);
|
||||||
|
addCard(Zone.LIBRARY, playerA, "Elite Vanguard", 1);
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, rain, true);
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Goblin Piker");
|
||||||
|
setChoice(playerA, "Red"); // choice for treasure mana
|
||||||
|
setChoice(playerA, "Red"); // choice for treasure mana
|
||||||
|
setChoice(playerA, true); // yes to Cascade
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertPermanentCount(playerA, "Goblin Piker", 1);
|
||||||
|
assertPermanentCount(playerA, "Elite Vanguard", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_Not_Using_Treasures() {
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
|
||||||
|
addCard(Zone.HAND, playerA, rain, 1);
|
||||||
|
addCard(Zone.HAND, playerA, "Goblin Piker", 1);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 7);
|
||||||
|
addCard(Zone.LIBRARY, playerA, "Elite Vanguard", 1);
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, rain, true);
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Goblin Piker");
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertPermanentCount(playerA, "Goblin Piker", 1);
|
||||||
|
assertPermanentCount(playerA, "Elite Vanguard", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Ignore("Does not work until actions are processed between the last mana being paid and the spell being cast.")
|
||||||
|
public void test_Cast_Two_Using_Treasures() {
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
skipInitShuffling();
|
||||||
|
|
||||||
|
addCard(Zone.HAND, playerA, rain, 1);
|
||||||
|
addCard(Zone.HAND, playerA, "Raging Goblin", 2); // {R}
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 5);
|
||||||
|
addCard(Zone.LIBRARY, playerA, "Memnite", 2);
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, rain, true);
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Raging Goblin");
|
||||||
|
setChoice(playerA, "Red"); // choice for treasure mana
|
||||||
|
setChoice(playerA, true); // yes to Cascade
|
||||||
|
waitStackResolved(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Raging Goblin");
|
||||||
|
setChoice(playerA, "Red"); // choice for treasure mana
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertPermanentCount(playerA, "Raging Goblin", 2);
|
||||||
|
assertPermanentCount(playerA, "Memnite", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Ignore("Does not work until actions are processed between the last mana being paid and the spell being cast.")
|
||||||
|
public void test_Cast_SomethingElse_Then_Cast_Using_Treasure() {
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
|
||||||
|
addCard(Zone.HAND, playerA, rain, 1);
|
||||||
|
addCard(Zone.HAND, playerA, "Raging Goblin", 2); // {R}
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 6);
|
||||||
|
addCard(Zone.LIBRARY, playerA, "Memnite", 2);
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, rain, true);
|
||||||
|
|
||||||
|
activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "{T}: Add");
|
||||||
|
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Raging Goblin", true);
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Raging Goblin");
|
||||||
|
setChoice(playerA, "Red"); // choice for treasure mana
|
||||||
|
setChoice(playerA, true); // yes to Cascade
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertPermanentCount(playerA, "Raging Goblin", 2);
|
||||||
|
assertPermanentCount(playerA, "Memnite", 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,13 +1,11 @@
|
||||||
package org.mage.test.cards.single.vis;
|
package org.mage.test.cards.single.vis;
|
||||||
|
|
||||||
import mage.game.permanent.Permanent;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||||
|
|
||||||
import static mage.constants.PhaseStep.*;
|
import static mage.constants.PhaseStep.*;
|
||||||
import static mage.constants.Zone.BATTLEFIELD;
|
import static mage.constants.Zone.BATTLEFIELD;
|
||||||
import static mage.constants.Zone.HAND;
|
import static mage.constants.Zone.HAND;
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
|
|
||||||
public class BroodOfCockroachesTest extends CardTestPlayerBase {
|
public class BroodOfCockroachesTest extends CardTestPlayerBase {
|
||||||
|
|
||||||
|
|
@ -16,19 +14,6 @@ public class BroodOfCockroachesTest extends CardTestPlayerBase {
|
||||||
private static final String BROOD_OF_COCKROACHES = "Brood of Cockroaches";
|
private static final String BROOD_OF_COCKROACHES = "Brood of Cockroaches";
|
||||||
private static final String SHOCK = "Shock";
|
private static final String SHOCK = "Shock";
|
||||||
|
|
||||||
@Test
|
|
||||||
public void should_display_correct_text() {
|
|
||||||
String expectedText = "When {this} is put into your graveyard from the battlefield, at the beginning of the next end step, you lose 1 life and return {this} to your hand.";
|
|
||||||
|
|
||||||
playerA_casts_Brood_of_Cockroaches_at_precombat_main_phase();
|
|
||||||
|
|
||||||
setStopAt(TURN_1, END_TURN);
|
|
||||||
execute();
|
|
||||||
|
|
||||||
Permanent permanent = getPermanent(BROOD_OF_COCKROACHES, playerA);
|
|
||||||
assertEquals(expectedText, permanent.getAbilities().get(1).toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void should_reduce_life_of_playerA_by_1_at_the_beginning_of_the_next_end_step() {
|
public void should_reduce_life_of_playerA_by_1_at_the_beginning_of_the_next_end_step() {
|
||||||
setLife(playerA, ANY_LIFE_TOTAL);
|
setLife(playerA, ANY_LIFE_TOTAL);
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,10 @@ import mage.abilities.dynamicvalue.common.ControllerSpeedCount;
|
||||||
import mage.abilities.effects.ContinuousEffectImpl;
|
import mage.abilities.effects.ContinuousEffectImpl;
|
||||||
import mage.abilities.effects.Effect;
|
import mage.abilities.effects.Effect;
|
||||||
import mage.cards.Card;
|
import mage.cards.Card;
|
||||||
import mage.constants.*;
|
import mage.constants.Duration;
|
||||||
|
import mage.constants.Layer;
|
||||||
|
import mage.constants.Outcome;
|
||||||
|
import mage.constants.SubLayer;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.util.CardUtil;
|
import mage.util.CardUtil;
|
||||||
|
|
@ -22,7 +25,7 @@ public class MaxSpeedAbility extends StaticAbility {
|
||||||
}
|
}
|
||||||
|
|
||||||
public MaxSpeedAbility(Ability ability) {
|
public MaxSpeedAbility(Ability ability) {
|
||||||
super(Zone.ALL, new MaxSpeedAbilityEffect(ability));
|
super(ability.getZone(), new MaxSpeedAbilityEffect(ability));
|
||||||
}
|
}
|
||||||
|
|
||||||
private MaxSpeedAbility(final MaxSpeedAbility ability) {
|
private MaxSpeedAbility(final MaxSpeedAbility ability) {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
package mage.abilities.dynamicvalue.common;
|
||||||
|
|
||||||
|
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.dynamicvalue.DynamicValue;
|
||||||
|
import mage.abilities.effects.Effect;
|
||||||
|
import mage.abilities.hint.Hint;
|
||||||
|
import mage.abilities.hint.ValueHint;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.watchers.common.SpellsCastWatcher;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public enum InstantAndSorceryCastThisTurn implements DynamicValue
|
||||||
|
{
|
||||||
|
YOU("you've cast"),
|
||||||
|
ALL("all players have cast"),
|
||||||
|
OPPONENTS("your opponents have cast");
|
||||||
|
|
||||||
|
private final String message;
|
||||||
|
private final ValueHint hint;
|
||||||
|
|
||||||
|
InstantAndSorceryCastThisTurn(String message) {
|
||||||
|
this.message = "Instant and sorcery spells " + message + " this turn";
|
||||||
|
this.hint = new ValueHint(this.message, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int calculate(Game game, Ability sourceAbility, Effect effect) {
|
||||||
|
return getSpellsCastThisTurn(game, sourceAbility);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InstantAndSorceryCastThisTurn copy() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getMessage() {
|
||||||
|
return this.message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Hint getHint() {
|
||||||
|
return this.hint;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getSpellsCastThisTurn(Game game, Ability ability) {
|
||||||
|
Collection<UUID> playerIds;
|
||||||
|
switch (this) {
|
||||||
|
case YOU:
|
||||||
|
playerIds = Collections.singletonList(ability.getControllerId());
|
||||||
|
break;
|
||||||
|
case ALL:
|
||||||
|
playerIds = game.getState().getPlayersInRange(ability.getControllerId(), game);
|
||||||
|
break;
|
||||||
|
case OPPONENTS:
|
||||||
|
playerIds = game.getOpponents(ability.getControllerId());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
SpellsCastWatcher watcher = game.getState().getWatcher(SpellsCastWatcher.class);
|
||||||
|
if (watcher == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return (int) playerIds.stream()
|
||||||
|
.map(watcher::getSpellsCastThisTurn)
|
||||||
|
.flatMap(Collection::stream)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.filter(spell -> spell.isInstantOrSorcery(game))
|
||||||
|
.count();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -22,7 +22,6 @@ import mage.game.stack.Spell;
|
||||||
import mage.players.ManaPoolItem;
|
import mage.players.ManaPoolItem;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.target.common.TargetCardInHand;
|
import mage.target.common.TargetCardInHand;
|
||||||
import mage.util.trace.TraceInfo;
|
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
@ -1405,88 +1404,6 @@ public class ContinuousEffects implements Serializable {
|
||||||
return controllerFound;
|
return controllerFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Debug only: prints out a status of the currently existing continuous effects
|
|
||||||
*
|
|
||||||
* @param game
|
|
||||||
*/
|
|
||||||
public void traceContinuousEffects(Game game) {
|
|
||||||
game.getContinuousEffects().getLayeredEffects(game);
|
|
||||||
logger.info("-------------------------------------------------------------------------------------------------");
|
|
||||||
int numberEffects = 0;
|
|
||||||
for (ContinuousEffectsList list : allEffectsLists) {
|
|
||||||
numberEffects += list.size();
|
|
||||||
}
|
|
||||||
logger.info("Turn: " + game.getTurnNum() + " - currently existing continuous effects: " + numberEffects);
|
|
||||||
logger.info("layeredEffects ...................: " + layeredEffects.size());
|
|
||||||
logger.info("continuousRuleModifyingEffects ...: " + continuousRuleModifyingEffects.size());
|
|
||||||
logger.info("replacementEffects ...............: " + replacementEffects.size());
|
|
||||||
logger.info("preventionEffects ................: " + preventionEffects.size());
|
|
||||||
logger.info("requirementEffects ...............: " + requirementEffects.size());
|
|
||||||
logger.info("restrictionEffects ...............: " + restrictionEffects.size());
|
|
||||||
logger.info("restrictionUntapNotMoreThanEffects: " + restrictionUntapNotMoreThanEffects.size());
|
|
||||||
logger.info("costModificationEffects ..........: " + costModificationEffects.size());
|
|
||||||
logger.info("spliceCardEffects ................: " + spliceCardEffects.size());
|
|
||||||
logger.info("asThoughEffects:");
|
|
||||||
for (Map.Entry<AsThoughEffectType, ContinuousEffectsList<AsThoughEffect>> entry : asThoughEffectsMap.entrySet()) {
|
|
||||||
logger.info("... " + entry.getKey().toString() + ": " + entry.getValue().size());
|
|
||||||
}
|
|
||||||
logger.info("applyStatus ....................: " + (applyStatus != null ? "exists" : "null"));
|
|
||||||
logger.info("auraReplacementEffect ............: " + (continuousRuleModifyingEffects != null ? "exists" : "null"));
|
|
||||||
Map<String, TraceInfo> orderedEffects = new TreeMap<>();
|
|
||||||
traceAddContinuousEffects(orderedEffects, layeredEffects, game, "layeredEffects................");
|
|
||||||
traceAddContinuousEffects(orderedEffects, continuousRuleModifyingEffects, game, "continuousRuleModifyingEffects");
|
|
||||||
traceAddContinuousEffects(orderedEffects, replacementEffects, game, "replacementEffects............");
|
|
||||||
traceAddContinuousEffects(orderedEffects, preventionEffects, game, "preventionEffects.............");
|
|
||||||
traceAddContinuousEffects(orderedEffects, requirementEffects, game, "requirementEffects............");
|
|
||||||
traceAddContinuousEffects(orderedEffects, restrictionEffects, game, "restrictionEffects............");
|
|
||||||
traceAddContinuousEffects(orderedEffects, restrictionUntapNotMoreThanEffects, game, "restrictionUntapNotMore...");
|
|
||||||
traceAddContinuousEffects(orderedEffects, costModificationEffects, game, "costModificationEffects.......");
|
|
||||||
traceAddContinuousEffects(orderedEffects, spliceCardEffects, game, "spliceCardEffects.............");
|
|
||||||
for (Map.Entry<AsThoughEffectType, ContinuousEffectsList<AsThoughEffect>> entry : asThoughEffectsMap.entrySet()) {
|
|
||||||
traceAddContinuousEffects(orderedEffects, entry.getValue(), game, entry.getKey().toString());
|
|
||||||
}
|
|
||||||
String playerName = "";
|
|
||||||
for (Map.Entry<String, TraceInfo> entry : orderedEffects.entrySet()) {
|
|
||||||
if (!entry.getValue().getPlayerName().equals(playerName)) {
|
|
||||||
playerName = entry.getValue().getPlayerName();
|
|
||||||
logger.info("--- Player: " + playerName + " --------------------------------");
|
|
||||||
}
|
|
||||||
logger.info(entry.getValue().getInfo()
|
|
||||||
+ " " + entry.getValue().getSourceName()
|
|
||||||
+ " " + entry.getValue().getDuration().name()
|
|
||||||
+ " " + entry.getValue().getRule()
|
|
||||||
+ " (Order: " + entry.getValue().getOrder() + ")"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
logger.info("---- End trace Continuous effects --------------------------------------------------------------------------");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void traceAddContinuousEffects(Map orderedEffects, ContinuousEffectsList<?> cel, Game game, String listName) {
|
|
||||||
for (ContinuousEffect effect : cel) {
|
|
||||||
Set<Ability> abilities = cel.getAbility(effect.getId());
|
|
||||||
for (Ability ability : abilities) {
|
|
||||||
Player controller = game.getPlayer(ability.getControllerId());
|
|
||||||
MageObject source = game.getObject(ability.getSourceId());
|
|
||||||
TraceInfo traceInfo = new TraceInfo();
|
|
||||||
traceInfo.setInfo(listName);
|
|
||||||
traceInfo.setOrder(effect.getOrder());
|
|
||||||
if (ability instanceof MageSingleton) {
|
|
||||||
traceInfo.setPlayerName("Mage Singleton");
|
|
||||||
traceInfo.setSourceName("Mage Singleton");
|
|
||||||
} else {
|
|
||||||
traceInfo.setPlayerName(controller == null ? "no controller" : controller.getName());
|
|
||||||
traceInfo.setSourceName(source == null ? "no source" : source.getIdName());
|
|
||||||
}
|
|
||||||
traceInfo.setRule(ability.getRule());
|
|
||||||
traceInfo.setAbilityId(ability.getId());
|
|
||||||
traceInfo.setEffectId(effect.getId());
|
|
||||||
traceInfo.setDuration(effect.getDuration());
|
|
||||||
orderedEffects.put(traceInfo.getPlayerName() + traceInfo.getSourceName() + effect.getId() + ability.getId(), traceInfo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getTotalEffectsCount() {
|
public int getTotalEffectsCount() {
|
||||||
return allEffectsLists.stream().mapToInt(ContinuousEffectsList::size).sum();
|
return allEffectsLists.stream().mapToInt(ContinuousEffectsList::size).sum();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import mage.abilities.effects.Effect;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.target.targetpointer.TargetPointer;
|
import mage.target.targetpointer.TargetPointer;
|
||||||
|
import mage.util.CardUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author BetaSteward_at_googlemail.com
|
* @author BetaSteward_at_googlemail.com
|
||||||
|
|
@ -67,7 +68,7 @@ public class CreateDelayedTriggeredAbilityEffect extends OneShotEffect {
|
||||||
return staticText;
|
return staticText;
|
||||||
}
|
}
|
||||||
if (ability.getRuleVisible()) {
|
if (ability.getRuleVisible()) {
|
||||||
return rulePrefix + ability.getRule();
|
return rulePrefix + CardUtil.getTextWithFirstCharLowerCase(ability.getRule());
|
||||||
} else {
|
} else {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,14 +10,26 @@ import mage.target.targetpointer.FixedTarget;
|
||||||
|
|
||||||
public class CrewsVehicleSourceTriggeredAbility extends TriggeredAbilityImpl {
|
public class CrewsVehicleSourceTriggeredAbility extends TriggeredAbilityImpl {
|
||||||
|
|
||||||
|
private final boolean mountsAlso;
|
||||||
|
private final boolean yourMainPhaseOnly;
|
||||||
|
|
||||||
public CrewsVehicleSourceTriggeredAbility(Effect effect) {
|
public CrewsVehicleSourceTriggeredAbility(Effect effect) {
|
||||||
|
this(effect, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CrewsVehicleSourceTriggeredAbility(Effect effect, boolean mountsAlso, boolean yourMainPhaseOnly) {
|
||||||
super(Zone.BATTLEFIELD, effect, false);
|
super(Zone.BATTLEFIELD, effect, false);
|
||||||
this.addIcon(CardIconImpl.ABILITY_CREW);
|
this.addIcon(CardIconImpl.ABILITY_CREW);
|
||||||
setTriggerPhrase("Whenever {this} crews a Vehicle, ");
|
this.mountsAlso = mountsAlso;
|
||||||
|
this.yourMainPhaseOnly = yourMainPhaseOnly;
|
||||||
|
setTriggerPhrase("Whenever {this}" + (mountsAlso ? " saddles a Mount or" : "") +
|
||||||
|
" crews a Vehicle" + (yourMainPhaseOnly ? " during your main phase" : "") + ", ");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected CrewsVehicleSourceTriggeredAbility(final CrewsVehicleSourceTriggeredAbility ability) {
|
protected CrewsVehicleSourceTriggeredAbility(final CrewsVehicleSourceTriggeredAbility ability) {
|
||||||
super(ability);
|
super(ability);
|
||||||
|
this.mountsAlso = ability.mountsAlso;
|
||||||
|
this.yourMainPhaseOnly = ability.yourMainPhaseOnly;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -27,11 +39,14 @@ public class CrewsVehicleSourceTriggeredAbility extends TriggeredAbilityImpl {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean checkEventType(GameEvent event, Game game) {
|
public boolean checkEventType(GameEvent event, Game game) {
|
||||||
return event.getType() == GameEvent.EventType.CREWED_VEHICLE;
|
return event.getType() == GameEvent.EventType.CREWED_VEHICLE || (mountsAlso && event.getType() == GameEvent.EventType.SADDLED_MOUNT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean checkTrigger(GameEvent event, Game game) {
|
public boolean checkTrigger(GameEvent event, Game game) {
|
||||||
|
if (yourMainPhaseOnly && !(game.isMainPhase() && this.isControlledBy(game.getActivePlayerId()))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (event.getTargetId().equals(getSourceId())) {
|
if (event.getTargetId().equals(getSourceId())) {
|
||||||
for (Effect effect : getEffects()) {
|
for (Effect effect : getEffects()) {
|
||||||
// set the vehicle id as target
|
// set the vehicle id as target
|
||||||
|
|
|
||||||
|
|
@ -45,22 +45,22 @@ public class GainAbilityControlledSpellsEffect extends ContinuousEffectImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Card card : game.getExile().getAllCardsByRange(game, source.getControllerId())) {
|
for (Card card : game.getExile().getAllCardsByRange(game, source.getControllerId())) {
|
||||||
if (filter.match(card, game)) {
|
if (filter.match(card, player.getId(), source, game)) {
|
||||||
game.getState().addOtherAbility(card, ability);
|
game.getState().addOtherAbility(card, ability);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (Card card : player.getLibrary().getCards(game)) {
|
for (Card card : player.getLibrary().getCards(game)) {
|
||||||
if (filter.match(card, game)) {
|
if (filter.match(card, player.getId(), source, game)) {
|
||||||
game.getState().addOtherAbility(card, ability);
|
game.getState().addOtherAbility(card, ability);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (Card card : player.getHand().getCards(game)) {
|
for (Card card : player.getHand().getCards(game)) {
|
||||||
if (filter.match(card, game)) {
|
if (filter.match(card, player.getId(), source, game)) {
|
||||||
game.getState().addOtherAbility(card, ability);
|
game.getState().addOtherAbility(card, ability);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (Card card : player.getGraveyard().getCards(game)) {
|
for (Card card : player.getGraveyard().getCards(game)) {
|
||||||
if (filter.match(card, game)) {
|
if (filter.match(card, player.getId(), source, game)) {
|
||||||
game.getState().addOtherAbility(card, ability);
|
game.getState().addOtherAbility(card, ability);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -68,7 +68,7 @@ public class GainAbilityControlledSpellsEffect extends ContinuousEffectImpl {
|
||||||
// workaround to gain cost reduction abilities to commanders before cast (make it playable)
|
// workaround to gain cost reduction abilities to commanders before cast (make it playable)
|
||||||
game.getCommanderCardsFromCommandZone(player, CommanderCardType.ANY)
|
game.getCommanderCardsFromCommandZone(player, CommanderCardType.ANY)
|
||||||
.stream()
|
.stream()
|
||||||
.filter(card -> filter.match(card, game))
|
.filter(card -> filter.match(card, player.getId(), source, game))
|
||||||
.forEach(card -> game.getState().addOtherAbility(card, ability));
|
.forEach(card -> game.getState().addOtherAbility(card, ability));
|
||||||
|
|
||||||
for (StackObject stackObject : game.getStack()) {
|
for (StackObject stackObject : game.getStack()) {
|
||||||
|
|
@ -77,7 +77,7 @@ public class GainAbilityControlledSpellsEffect extends ContinuousEffectImpl {
|
||||||
}
|
}
|
||||||
// TODO: Distinguish "you cast" to exclude copies
|
// TODO: Distinguish "you cast" to exclude copies
|
||||||
Card card = game.getCard(stackObject.getSourceId());
|
Card card = game.getCard(stackObject.getSourceId());
|
||||||
if (card != null && filter.match((Spell) stackObject, game)) {
|
if (card != null && filter.match((Spell) stackObject, player.getId(), source, game)) {
|
||||||
game.getState().addOtherAbility(card, ability);
|
game.getState().addOtherAbility(card, ability);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,27 +12,37 @@ import mage.filter.FilterCard;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.target.common.TargetCardInLibrary;
|
import mage.target.common.TargetCardInLibrary;
|
||||||
|
import mage.util.CardUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author BetaSteward_at_googlemail.com, edited by Cguy7777
|
* @author BetaSteward_at_googlemail.com, edited by Cguy7777
|
||||||
*/
|
*/
|
||||||
public class SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect extends SearchEffect {
|
public class SearchLibraryPutOntoBattlefieldTappedRestInHandEffect extends SearchEffect {
|
||||||
|
|
||||||
private static final FilterCard filter = new FilterCard("card to put on the battlefield tapped");
|
private final FilterCard filter;
|
||||||
|
private final int numToBattlefield;
|
||||||
|
|
||||||
public SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect(TargetCardInLibrary target) {
|
public SearchLibraryPutOntoBattlefieldTappedRestInHandEffect(TargetCardInLibrary target, int numToBattlefield) {
|
||||||
super(target, Outcome.PutLandInPlay);
|
super(target, Outcome.PutLandInPlay);
|
||||||
staticText = "search your library for " + target.getDescription() +
|
staticText = "search your library for " + target.getDescription() +
|
||||||
", reveal those cards, put one onto the battlefield tapped and the other into your hand, then shuffle";
|
", reveal those cards, put " + CardUtil.numberToText(numToBattlefield) + " onto the battlefield tapped and the other into your hand, then shuffle";
|
||||||
|
this.filter = new FilterCard((numToBattlefield > 1 ? "cards" : "card") + "to put on the battlefield tapped");
|
||||||
|
this.numToBattlefield = numToBattlefield;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect(final SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect effect) {
|
public SearchLibraryPutOntoBattlefieldTappedRestInHandEffect(TargetCardInLibrary target) {
|
||||||
|
this(target, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected SearchLibraryPutOntoBattlefieldTappedRestInHandEffect(final SearchLibraryPutOntoBattlefieldTappedRestInHandEffect effect) {
|
||||||
super(effect);
|
super(effect);
|
||||||
|
this.filter = effect.filter.copy();
|
||||||
|
this.numToBattlefield = effect.numToBattlefield;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect copy() {
|
public SearchLibraryPutOntoBattlefieldTappedRestInHandEffect copy() {
|
||||||
return new SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect(this);
|
return new SearchLibraryPutOntoBattlefieldTappedRestInHandEffect(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -49,14 +59,15 @@ public class SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect extends Se
|
||||||
controller.revealCards(sourceObject.getIdName(), revealed, game);
|
controller.revealCards(sourceObject.getIdName(), revealed, game);
|
||||||
|
|
||||||
if (target.getTargets().size() >= 2) {
|
if (target.getTargets().size() >= 2) {
|
||||||
TargetCardInLibrary targetCardToBattlefield = new TargetCardInLibrary(filter);
|
int maxToBattlefield = Math.min(numToBattlefield, target.getTargets().size());
|
||||||
controller.choose(Outcome.PutLandInPlay, revealed, targetCardToBattlefield, source, game);
|
TargetCardInLibrary targetCardsToBattlefield = new TargetCardInLibrary(maxToBattlefield, filter);
|
||||||
|
controller.choose(Outcome.PutLandInPlay, revealed, targetCardsToBattlefield, source, game);
|
||||||
|
|
||||||
Card cardToBattlefield = revealed.get(targetCardToBattlefield.getFirstTarget(), game);
|
Cards cardsToBattlefield = new CardsImpl(targetCardsToBattlefield.getTargets());
|
||||||
Cards cardsToHand = new CardsImpl(revealed);
|
Cards cardsToHand = new CardsImpl(revealed);
|
||||||
if (cardToBattlefield != null) {
|
if (!cardsToBattlefield.isEmpty()) {
|
||||||
controller.moveCards(cardToBattlefield, Zone.BATTLEFIELD, source, game, true, false, false, null);
|
controller.moveCards(cardsToBattlefield.getCards(game), Zone.BATTLEFIELD, source, game, true, false, false, null);
|
||||||
cardsToHand.remove(cardToBattlefield);
|
cardsToHand.removeAll(cardsToBattlefield);
|
||||||
}
|
}
|
||||||
|
|
||||||
controller.moveCardsToHandWithInfo(cardsToHand, source, game, true);
|
controller.moveCardsToHandWithInfo(cardsToHand, source, game, true);
|
||||||
|
|
@ -551,7 +551,7 @@ public enum SubType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Subtype(" + subtype + ')';
|
return "Subtype(" + subtype + ')'; // warning, do not change until refactor code like predicate.toString().equals
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3814,7 +3814,7 @@ public abstract class GameImpl implements Game {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean endTurn(Ability source) {
|
public boolean endTurn(Ability source) {
|
||||||
getTurn().endTurn(this, getActivePlayerId(), source);
|
getTurn().endTurn(this, source);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,6 @@ import mage.target.common.TargetControlledPermanent;
|
||||||
import mage.target.common.TargetDefender;
|
import mage.target.common.TargetDefender;
|
||||||
import mage.util.CardUtil;
|
import mage.util.CardUtil;
|
||||||
import mage.util.Copyable;
|
import mage.util.Copyable;
|
||||||
import mage.util.trace.TraceUtil;
|
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
@ -744,8 +743,6 @@ public class Combat implements Serializable, Copyable<Combat> {
|
||||||
game.getCombat().logBlockerInfo(defender, game);
|
game.getCombat().logBlockerInfo(defender, game);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// tool to catch the bug about flyers blocked by non flyers or intimidate blocked by creatures with other colors
|
|
||||||
TraceUtil.traceCombatIfNeeded(game, game.getCombat());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void makeSureItsNotComputer(Player controller) {
|
private void makeSureItsNotComputer(Player controller) {
|
||||||
|
|
@ -761,7 +758,7 @@ public class Combat implements Serializable, Copyable<Combat> {
|
||||||
* Add info about attacker blocked by blocker to the game log
|
* Add info about attacker blocked by blocker to the game log
|
||||||
*/
|
*/
|
||||||
private void logBlockerInfo(Player defender, Game game) {
|
private void logBlockerInfo(Player defender, Game game) {
|
||||||
boolean shownDefendingPlayer = game.getPlayers().size() < 3; // only two players no need to saw the attacked player
|
boolean shownDefendingPlayer = game.getPlayers().size() <= 2; // 1 vs 1 game, no need to saw the attacked player
|
||||||
for (CombatGroup group : game.getCombat().getGroups()) {
|
for (CombatGroup group : game.getCombat().getGroups()) {
|
||||||
if (group.defendingPlayerId.equals(defender.getId())) {
|
if (group.defendingPlayerId.equals(defender.getId())) {
|
||||||
if (!shownDefendingPlayer) {
|
if (!shownDefendingPlayer) {
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,8 @@ class DackFaydenEmblemTriggeredAbility extends TriggeredAbilityImpl {
|
||||||
Spell spell = game.getStack().getSpell(event.getTargetId());
|
Spell spell = game.getStack().getSpell(event.getTargetId());
|
||||||
if (spell != null) {
|
if (spell != null) {
|
||||||
SpellAbility spellAbility = spell.getSpellAbility();
|
SpellAbility spellAbility = spell.getSpellAbility();
|
||||||
for (Mode mode : spellAbility.getModes().values()) {
|
for (UUID modeId : spellAbility.getModes().getSelectedModes()) {
|
||||||
|
Mode mode = spellAbility.getModes().get(modeId);
|
||||||
for (Target target : mode.getTargets()) {
|
for (Target target : mode.getTargets()) {
|
||||||
if (!target.isNotTarget()) {
|
if (!target.isNotTarget()) {
|
||||||
for (UUID targetId : target.getTargets()) {
|
for (UUID targetId : target.getTargets()) {
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ import mage.counters.CounterType;
|
||||||
import mage.filter.StaticFilters;
|
import mage.filter.StaticFilters;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.command.Emblem;
|
import mage.game.command.Emblem;
|
||||||
|
import mage.game.events.GameEvent;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -106,8 +107,13 @@ class RadiationEffect extends OneShotEffect {
|
||||||
Cards milled = player.millCards(amount, source, game);
|
Cards milled = player.millCards(amount, source, game);
|
||||||
int countNonLand = milled.count(StaticFilters.FILTER_CARD_NON_LAND, player.getId(), source, game);
|
int countNonLand = milled.count(StaticFilters.FILTER_CARD_NON_LAND, player.getId(), source, game);
|
||||||
if (countNonLand > 0) {
|
if (countNonLand > 0) {
|
||||||
// TODO: support gaining life instead with [[Strong, the Brutish Thespian]]
|
GameEvent event = new GameEvent(GameEvent.EventType.RADIATION_GAIN_LIFE, null, source, player.getId(), amount, false);
|
||||||
player.loseLife(countNonLand, game, source, false);
|
if (game.replaceEvent(event)) {
|
||||||
|
player.gainLife(countNonLand, game, source);
|
||||||
|
} else {
|
||||||
|
player.loseLife(countNonLand, game, source, false);
|
||||||
|
}
|
||||||
|
|
||||||
player.loseCounters(CounterType.RAD.getName(), countNonLand, source, game);
|
player.loseCounters(CounterType.RAD.getName(), countNonLand, source, game);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue