Merge remote-tracking branch 'upstream/master'

This commit is contained in:
mnapoleon 2015-03-02 08:42:26 -05:00
commit 92e21073e1
343 changed files with 6350 additions and 1156 deletions

4
.gitignore vendored
View file

@ -18,6 +18,7 @@ Mage.Server.Plugins/Mage.Deck.Limited/target
Mage.Server.Plugins/Mage.Game.CommanderDuel/target Mage.Server.Plugins/Mage.Game.CommanderDuel/target
Mage.Server.Plugins/Mage.Game.FreeForAll/target Mage.Server.Plugins/Mage.Game.FreeForAll/target
Mage.Server.Plugins/Mage.Game.TwoPlayerDuel/target Mage.Server.Plugins/Mage.Game.TwoPlayerDuel/target
Mage.Server.Plugins/Mage.Game.TinyLeadersDuel/target
Mage.Server.Plugins/Mage.Player.AI/target Mage.Server.Plugins/Mage.Player.AI/target
Mage.Server.Plugins/Mage.Player.AIMinimax/target Mage.Server.Plugins/Mage.Player.AIMinimax/target
Mage.Server.Plugins/Mage.Player.AI.MA/target Mage.Server.Plugins/Mage.Player.AI.MA/target
@ -83,3 +84,6 @@ Mage.Server.Plugins/Mage.Draft.8PlayerBooster/target
/Mage.Server/config/ai.please.cast.this.txt /Mage.Server/config/ai.please.cast.this.txt
/Mage.Stats/target/ /Mage.Stats/target/
/Utils/*_unimplemented.txt /Utils/*_unimplemented.txt
*.netbeans_automatic_build
*.txt
Mage.Client/serverlist.txt

View file

@ -27,6 +27,7 @@
*/ */
package mage.client.game; package mage.client.game;
import com.sun.java.swing.plaf.windows.WindowsBorders;
import java.awt.BorderLayout; import java.awt.BorderLayout;
import java.awt.Color; import java.awt.Color;
import java.awt.Component; import java.awt.Component;
@ -606,7 +607,14 @@ public final class GamePanel extends javax.swing.JPanel {
else { else {
this.txtStep.setText(""); this.txtStep.setText("");
} }
this.txtPhasesBottomInfo.setText(" " + (game.getSpellsCastCurrentTurn() > 0 ? Integer.toString(game.getSpellsCastCurrentTurn()):"")); if (game.getSpellsCastCurrentTurn() > 0) {
this.phasesBottomPanel.setVisible(true);
this.txtPhasesBottomInfo.setText(Integer.toString(game.getSpellsCastCurrentTurn()));
} else {
this.phasesBottomPanel.setVisible(false);
this.txtPhasesBottomInfo.setText("");
}
this.txtActivePlayer.setText(game.getActivePlayerName()); this.txtActivePlayer.setText(game.getActivePlayerName());
this.txtPriority.setText(game.getPriorityPlayerName()); this.txtPriority.setText(game.getPriorityPlayerName());
this.txtTurn.setText(Integer.toString(game.getTurn())); this.txtTurn.setText(Integer.toString(game.getTurn()));
@ -1508,8 +1516,9 @@ public final class GamePanel extends javax.swing.JPanel {
phasesContainer.add(empty1, ratio); phasesContainer.add(empty1, ratio);
phasesContainer.add(jPhases); phasesContainer.add(jPhases);
JPanel phasesBottomPanel = new JPanel(); phasesBottomPanel = new JPanel();
phasesBottomPanel.setBackground(new Color(0, 0, 0, 0)); phasesBottomPanel.setBackground(Color.LIGHT_GRAY);
phasesBottomPanel.setBorder(new LineBorder(Color.DARK_GRAY, 2));
phasesBottomPanel.add(txtPhasesBottomInfo); phasesBottomPanel.add(txtPhasesBottomInfo);
phasesContainer.add(phasesBottomPanel); phasesContainer.add(phasesBottomPanel);
@ -1862,6 +1871,7 @@ public final class GamePanel extends javax.swing.JPanel {
private javax.swing.JSplitPane jSplitPane2; private javax.swing.JSplitPane jSplitPane2;
private JPanel jPhases; private JPanel jPhases;
private JPanel phasesContainer; private JPanel phasesContainer;
private JPanel phasesBottomPanel;
private javax.swing.JLabel txtPhasesBottomInfo; private javax.swing.JLabel txtPhasesBottomInfo;
private HoverButton currentStep; private HoverButton currentStep;

View file

@ -27,7 +27,7 @@ public class ConstructedFormats {
private static final String[] constructedFormats = { private static final String[] constructedFormats = {
ALL, STANDARD, EXTENDED, MODERN, ALL, STANDARD, EXTENDED, MODERN,
"* Khans of Tarkir Block", "Khans of Tarkir", "Fate Reforged", /*"Dragons of Tarkir"*/ "* Khans of Tarkir Block", "Khans of Tarkir", "Fate Reforged", "Dragons of Tarkir",
"* Theros Block", "Journey into Nyx", "Born of the Gods", "Theros", "* Theros Block", "Journey into Nyx", "Born of the Gods", "Theros",
"* Return to Ravnica Block", "Dragon's Maze", "Gatecrash", "Return to Ravnica", "* Return to Ravnica Block", "Dragon's Maze", "Gatecrash", "Return to Ravnica",
"* Innistrad Block", "Avacyn Restored", "Dark Ascension", "Innistrad", "* Innistrad Block", "Avacyn Restored", "Dark Ascension", "Innistrad",
@ -113,7 +113,10 @@ public class ConstructedFormats {
public static List<String> getSetsByFormat(String format) { public static List<String> getSetsByFormat(String format) {
if (format.equals("* Khans of Tarkir Block")) { if (format.equals("* Khans of Tarkir Block")) {
return Arrays.asList("KTK", "FRF"); return Arrays.asList("KTK", "FRF","DTK");
}
if (format.equals("Dragons of Tarkir")) {
return Arrays.asList("DTK");
} }
if (format.equals("Fate Reforged")) { if (format.equals("Fate Reforged")) {
return Arrays.asList("FRF"); return Arrays.asList("FRF");

View file

@ -44,8 +44,7 @@ public class GathererSets implements Iterable<DownloadJob> {
"MMA", "MMA",
"THS", "BNG", "JOU", "THS", "BNG", "JOU",
"CNS", "VMA", "CNS", "VMA",
"KTK", "FRF" "KTK", "FRF", "DTK"};
};
private static final HashMap<String, String> symbolsReplacements = new HashMap<>(); private static final HashMap<String, String> symbolsReplacements = new HashMap<>();
static { static {

View file

@ -16,6 +16,7 @@ public class MagicCardsImageSource implements CardImageSource {
private static final Map<String, String> setNameTokenReplacement = new HashMap<String, String>() { private static final Map<String, String> setNameTokenReplacement = new HashMap<String, String>() {
{ {
put("DTK", "dragons-of-tarkir");
put("GRC","wpngateway"); put("GRC","wpngateway");
put("MBP","media-inserts"); put("MBP","media-inserts");
put("MLP", "launch-party"); put("MLP", "launch-party");

View file

@ -28,8 +28,6 @@
package org.mage.plugins.card.dl.sources; package org.mage.plugins.card.dl.sources;
import java.net.URLEncoder;
import mage.cards.SplitCard;
import org.mage.plugins.card.images.CardDownloadData; import org.mage.plugins.card.images.CardDownloadData;
/** /**

View file

@ -29,6 +29,7 @@ public class WizardCardsImageSource implements CardImageSource {
public WizardCardsImageSource() { public WizardCardsImageSource() {
sets = new HashMap<>(); sets = new HashMap<>();
setsAliases = new HashMap<>(); setsAliases = new HashMap<>();
setsAliases.put("DTK", "dragonsoftarkir/cig");
setsAliases.put("FRF", "fatereforged/cig"); setsAliases.put("FRF", "fatereforged/cig");
setsAliases.put("C14", "commander2014/cig"); setsAliases.put("C14", "commander2014/cig");
setsAliases.put("KTK", "khansoftarkir/cig"); setsAliases.put("KTK", "khansoftarkir/cig");

View file

@ -65,6 +65,6 @@ ddd=gvl
unh=uh unh=uh
dde=pvc dde=pvc
# Remove setname as soon as the images can be downloaded # Remove setname as soon as the images can be downloaded
ignore.urls=TOK ignore.urls=TOK,DTK
# sets ordered by release time (newest goes first) # sets ordered by release time (newest goes first)
token.lookup.order=FRF,KTK,M15,VMA,CNS,JOU,BNG,THS,DDL,M14,MMA,DGM,GTC,RTR,M13,AVR,DDI,DKA,ISD,M12,NPH,MBS,SOM,M11,ROE,DDE,WWK,ZEN,M10,GVL,ARB,DVD,CFX,JVC,ALA,EVE,SHM,EVG,MOR,LRW,10E,CLS,CHK,GRC token.lookup.order=DTK,FRF,KTK,M15,VMA,CNS,JOU,BNG,THS,DDL,M14,MMA,DGM,GTC,RTR,M13,AVR,DDI,DKA,ISD,M12,NPH,MBS,SOM,M11,ROE,DDE,WWK,ZEN,M10,GVL,ARB,DVD,CFX,JVC,ALA,EVE,SHM,EVG,MOR,LRW,10E,CLS,CHK,GRC

View file

@ -50,6 +50,7 @@ import mage.target.Targets;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import mage.game.Game;
/** /**
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
@ -116,21 +117,27 @@ public class CardView extends SimpleCardView {
protected boolean canAttack; protected boolean canAttack;
public CardView(Card card) { public CardView(Card card) {
this(card, null, false); this(card, null, null, false);
} }
public CardView(Card card, UUID cardId) { public CardView(Card card, UUID cardId) {
this(card, null, false); this(card, null, null, false);
this.id = cardId;
}
public CardView(Card card, Game game, UUID cardId) {
this(card, game, null, false);
this.id = cardId; this.id = cardId;
} }
/** /**
* *
* @param card * @param card
* @param game
* @param cardId * @param cardId
* @param controlled is the card view created for the card controller - used for morph / face down cards to know which player may see information for the card * @param controlled is the card view created for the card controller - used for morph / face down cards to know which player may see information for the card
*/ */
public CardView(Card card, UUID cardId, boolean controlled) { public CardView(Card card, Game game, UUID cardId, boolean controlled) {
super(card.getId(), card.getExpansionSetCode(), card.getCardNumber(), card.isFaceDown(), card.getUsesVariousArt(), card.getTokenSetCode()); super(card.getId(), card.getExpansionSetCode(), card.getCardNumber(), card.isFaceDown(), card.getUsesVariousArt(), card.getTokenSetCode());
this.morphCard = card.isMorphCard(); this.morphCard = card.isMorphCard();
// no information available for face down cards as long it's not a controlled face down morph card // no information available for face down cards as long it's not a controlled face down morph card
@ -241,9 +248,9 @@ public class CardView extends SimpleCardView {
this.rarity = card.getRarity(); this.rarity = card.getRarity();
this.isToken = false; this.isToken = false;
} }
if (card.getCounters() != null && !card.getCounters().isEmpty()) { if (game != null && card.getCounters(game) != null && !card.getCounters(game).isEmpty()) {
counters = new ArrayList<>(); counters = new ArrayList<>();
for (Counter counter: card.getCounters().values()) { for (Counter counter: card.getCounters(game).values()) {
counters.add(new CounterView(counter)); counters.add(new CounterView(counter));
} }
} }

View file

@ -136,7 +136,7 @@ public class GameView implements Serializable {
} }
else { else {
// Spell // Spell
stack.put(stackObject.getId(), new CardView((Spell)stackObject, null, stackObject.getControllerId().equals(createdForPlayerId))); stack.put(stackObject.getId(), new CardView((Spell)stackObject, game, null, stackObject.getControllerId().equals(createdForPlayerId)));
checkPaid(stackObject.getId(), (Spell)stackObject); checkPaid(stackObject.getId(), (Spell)stackObject);
} }
//stackOrder.add(stackObject.getId()); //stackOrder.add(stackObject.getId());

View file

@ -62,7 +62,7 @@ public class PermanentView extends CardView {
private final boolean attachedToPermanent; private final boolean attachedToPermanent;
public PermanentView(Permanent permanent, Card card, UUID createdForPlayerId, Game game) { public PermanentView(Permanent permanent, Card card, UUID createdForPlayerId, Game game) {
super(permanent, null, permanent.getControllerId().equals(createdForPlayerId)); super(permanent, game, null, permanent.getControllerId().equals(createdForPlayerId));
this.controlled = permanent.getControllerId().equals(createdForPlayerId); this.controlled = permanent.getControllerId().equals(createdForPlayerId);
this.rules = permanent.getRules(); this.rules = permanent.getRules();
this.tapped = permanent.isTapped(); this.tapped = permanent.isTapped();

View file

@ -0,0 +1,213 @@
/*
* Copyright 2011 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.deck;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import mage.abilities.common.CanBeYourCommanderAbility;
import mage.cards.Card;
import mage.cards.decks.Deck;
import mage.cards.decks.DeckValidator;
import mage.constants.CardType;
import mage.filter.FilterMana;
import mage.util.CardUtil;
/**
*
* @author JRHerlehy
*/
public class TinyLeaders extends DeckValidator {
protected List<String> banned = new ArrayList<>();
protected List<String> bannedCommander = new ArrayList<>();
public TinyLeaders() {
this("Tiny Leaders");
//Banned list from tinyleaders.blodspot.ca/p/ban-list.html
//Ban list updated as of 11/08/14
banned.add("Ancestral Recall");
banned.add("Balance");
banned.add("Black Lotus");
banned.add("Channel");
banned.add("Counterbalance");
banned.add("Demonic Tutor");
banned.add("Earthcraft");
banned.add("Edric, Spymaster of Trest");
banned.add("Fastbond");
banned.add("Goblin Recruiter");
banned.add("Hermit Druid");
banned.add("Imperial Seal");
banned.add("Library of Alexandria");
banned.add("Karakas");
banned.add("Mana Crypt");
banned.add("Mana Drain");
banned.add("Mana Vault");
banned.add("metalworker");
banned.add("Mind Twist");
banned.add("Mishra's Workshop");
banned.add("Mox Emerald");
banned.add("Mox Jet");
banned.add("Mox Pearl");
banned.add("Mox Ruby");
banned.add("Mox Sapphire");
banned.add("Necropotence");
banned.add("Painter's Servant");
banned.add("Shahrazad");
banned.add("Skullclamp");
banned.add("Sol Ring");
banned.add("Strip Mine");
banned.add("Survival of the Fittest");
banned.add("Sword of Body and Mind");
banned.add("Time Vault");
banned.add("Time Walk");
banned.add("Timetwister");
banned.add("Tolarian Academy");
banned.add("Umezawa's Jitte");
banned.add("Vampiric Tutor");
banned.add("Yawgmoth's Will");
//Additionally, these Legendary creatures cannot be used as Commanders
bannedCommander.add("Erayo, Soratami Ascendant");
bannedCommander.add("Rofellos, Llanowar Emissary");
bannedCommander.add("Derevi, Empyrical Tactician");
}
public TinyLeaders(String name) {
super(name);
}
/**
*
* @param deck
* @return - True if deck is valid
*/
@Override
public boolean validate(Deck deck) {
boolean valid = true;
if (deck.getCards().size() != 49) {
invalid.put("Deck", "Must contain 49 cards: has " + deck.getCards().size() + " cards");
valid = false;
}
List<String> basicLandNames = new ArrayList<>(Arrays.asList("Forest", "Island", "Mountain", "Swamp", "Plains",
"Snow-Covered Forest", "Snow-Covered Island", "Snow-Covered Mountain", "Snow-Covered Swamp", "Snow-Covered Plains"));
Map<String, Integer> counts = new HashMap<>();
countCards(counts, deck.getCards());
countCards(counts, deck.getSideboard());
for (Map.Entry<String, Integer> entry : counts.entrySet()) {
if (entry.getValue() > 1) {
if (!basicLandNames.contains(entry.getKey()) && !entry.getKey().equals("Relentless Rats") && !entry.getKey().equals("Shadowborn Apostle")) {
invalid.put(entry.getKey(), "Too many: " + entry.getValue());
valid = false;
}
}
}
for (String bannedCard : banned) {
if (counts.containsKey(bannedCard)) {
invalid.put(bannedCard, "Banned");
valid = false;
}
}
if (deck.getSideboard().size() <= 11) {
Card commander = null;
for (Card card : deck.getSideboard()) {
if (card.getName().equalsIgnoreCase(deck.getName())) {
commander = card;
}
}
/**
* 905.5b - Each card must have a converted mana cost of three of less.
* Cards with {X} in their mana cost count X as zero.
* Split and double-face cards are legal only if both of their halves would be legal independently.
*/
if (commander == null || commander.getManaCost().convertedManaCost() > 3) {
if (commander == null) {
invalid.put("Leader", "Please be sure to set your leader in the NAME field in the DECK EDITOR");
}
if (commander != null && commander.getManaCost().convertedManaCost() > 3) {
invalid.put("Leader", "Commander CMC is Greater than 3");
}
return false;
}
if ((commander.getCardType().contains(CardType.CREATURE) && commander.getSupertype().contains("Legendary"))
|| (commander.getCardType().contains(CardType.PLANESWALKER) && commander.getAbilities().contains(CanBeYourCommanderAbility.getInstance()))) {
if (!bannedCommander.contains(commander.getName())) {
FilterMana color = CardUtil.getColorIdentity(commander);
for (Card card : deck.getCards()) {
if (!cardHasValideColor(color, card)) {
invalid.put(card.getName(), "Invalid color (" + commander.getName() + ")");
valid = false;
}
//905.5b - Converted mana cost must be 3 or less
if (card.getManaCost().convertedManaCost() > 3) {
invalid.put(card.getName(), "Invalid cost (" + card.getManaCost().convertedManaCost() + ")");
valid = false;
}
}
} else {
invalid.put("Commander", "Commander banned (" + commander.getName() + ")");
valid = false;
}
} else {
invalid.put("Commander", "Commander invalide (" + commander.getName() + ")");
valid = false;
}
} else {
invalid.put("Commander", "Sideboard must contain only the commander and a maximum of 10 sideboard cards");
valid = false;
}
return valid;
}
/**
*
* @param commander FilterMana object with Color Identity of Commander set
* @param card Card to validate
* @return True if card has a valid color identity
*/
public boolean cardHasValideColor(FilterMana commander, Card card) {
FilterMana cardColor = CardUtil.getColorIdentity(card);
return !(cardColor.isBlack() && !commander.isBlack()
|| cardColor.isBlue() && !commander.isBlue()
|| cardColor.isGreen() && !commander.isGreen()
|| cardColor.isRed() && !commander.isRed()
|| cardColor.isWhite() && !commander.isWhite());
}
}

View file

@ -0,0 +1,50 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.3.0</version>
</parent>
<artifactId>mage-game-tinyleadersduel</artifactId>
<packaging>jar</packaging>
<name>Mage Game Tiny Leaders Two Player</name>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>mage</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
<finalName>mage-game-tinyleadersduel</finalName>
</build>
<properties/>
</project>

View file

@ -0,0 +1,64 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.game;
import mage.constants.MultiplayerAttackOption;
import mage.constants.RangeOfInfluence;
import mage.game.match.MatchType;
/**
*
* @author JRHerlehy
*/
public class TinyLeadersDuel extends GameTinyLeadersImpl {
public TinyLeadersDuel(MultiplayerAttackOption attackOption, RangeOfInfluence range, int freeMulligans, int startLife) {
super(attackOption, range, freeMulligans, startLife);
}
public TinyLeadersDuel(final TinyLeadersDuel game) {
super(game);
}
@Override
public MatchType getGameType() {
return new TinyLeadersDuelType();
}
@Override
public int getNumPlayers() {
return 2;
}
@Override
public TinyLeadersDuel copy() {
return new TinyLeadersDuel(this);
}
}

View file

@ -0,0 +1,58 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.game;
import mage.game.match.MatchImpl;
import mage.game.match.MatchOptions;
/**
*
* @author JRHerlehy
*/
public class TinyLeadersDuelMatch extends MatchImpl {
public TinyLeadersDuelMatch(MatchOptions options) {
super(options);
}
@Override
public void startGame() throws GameException {
//Tiny Leaders Play Rule 13: Players begin the game with 25 life.
int startLife = 25;
TinyLeadersDuel game = new TinyLeadersDuel(options.getAttackOption(), options.getRange(), options.getFreeMulligans(), startLife);
game.setStartMessage(this.createGameStartMessage());
//Tucking a Tiny Leader is legal
game.setAlsoLibrary(false);
this.initGame(game);
games.add(game);
}
}

View file

@ -0,0 +1,58 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.game;
import mage.game.match.MatchType;
/**
*
* @author JRHerlehy
*/
public class TinyLeadersDuelType extends MatchType {
public TinyLeadersDuelType() {
this.name = "Tiny Leaders Two Player Duel";
this.maxPlayers = 2;
this.minPlayers = 2;
this.numTeams = 0;
this.useAttackOption = false;
this.useRange = false;
this.sideboardingAllowed = true;
}
protected TinyLeadersDuelType(final TinyLeadersDuelType matchType){
super(matchType);
}
@Override
public TinyLeadersDuelType copy() {
return new TinyLeadersDuelType(this);
}
}

View file

@ -75,6 +75,9 @@ import java.io.IOException;
import java.io.Serializable; import java.io.Serializable;
import java.util.*; import java.util.*;
import java.util.Map.Entry; import java.util.Map.Entry;
import mage.filter.Filter;
import mage.filter.predicate.other.PlayerIdPredicate;
import mage.filter.predicate.permanent.ControllerIdPredicate;
/** /**
@ -1011,7 +1014,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
} }
@Override @Override
public boolean playMana(ManaCost unpaid, Game game) { public boolean playMana(ManaCost unpaid, String promptText, Game game) {
payManaMode = true; payManaMode = true;
boolean result = playManaHandling(unpaid, game); boolean result = playManaHandling(unpaid, game);
payManaMode = false; payManaMode = false;
@ -1283,6 +1286,9 @@ public class ComputerPlayer extends PlayerImpl implements Player {
if (card != null) { if (card != null) {
target.addTarget(card.getId(), source, game); target.addTarget(card.getId(), source, game);
cardChoices.remove(card); cardChoices.remove(card);
} else {
// We don't have any valid target to choose so stop choosing
return target.getTargets().size() < target.getNumberOfTargets();
} }
if (outcome.equals(Outcome.Neutral) && target.getTargets().size() > target.getNumberOfTargets() + (target.getMaxNumberOfTargets() - target.getNumberOfTargets()) / 2) { if (outcome.equals(Outcome.Neutral) && target.getTargets().size() > target.getNumberOfTargets() + (target.getMaxNumberOfTargets() - target.getNumberOfTargets()) / 2) {
return true; return true;
@ -1947,10 +1953,14 @@ public class ComputerPlayer extends PlayerImpl implements Player {
} }
protected List<Permanent> threats(UUID playerId, UUID sourceId, FilterPermanent filter, Game game, List<UUID> targets) { protected List<Permanent> threats(UUID playerId, UUID sourceId, FilterPermanent filter, Game game, List<UUID> targets) {
List<Permanent> threats = (playerId == null || sourceId ==null) ? List<Permanent> threats;
game.getBattlefield().getActivePermanents(filter, this.getId(), sourceId, game) : // all permanents within the range of the player if (playerId == null) {
game.getBattlefield().getActivePermanents(filter, playerId, sourceId, game); threats = game.getBattlefield().getActivePermanents(filter, this.getId(), sourceId, game); // all permanents within the range of the player
} else {
FilterPermanent filterCopy = filter.copy();
filterCopy.add(new ControllerIdPredicate(playerId));
threats = game.getBattlefield().getActivePermanents(filter, this.getId(), sourceId, game);
}
Iterator<Permanent> it = threats.iterator(); Iterator<Permanent> it = threats.iterator();
while (it.hasNext()) { // remove permanents already targeted while (it.hasNext()) { // remove permanents already targeted
Permanent test = it.next(); Permanent test = it.next();

View file

@ -432,15 +432,31 @@ public class HumanPlayer extends PlayerImpl {
if (target.getTargets().size() >= target.getNumberOfTargets()) { if (target.getTargets().size() >= target.getNumberOfTargets()) {
required = false; required = false;
} }
game.fireSelectTargetEvent(playerId, target.getMessage(), cards, required, getOptions(target, null)); Map<String, Serializable> options = getOptions(target, null);
List<UUID> chosen = target.getTargets();
options.put("chosen", (Serializable)chosen);
List<UUID> choosable = new ArrayList<>();
for (UUID cardId : cards) {
if (target.canTarget(cardId, cards, game)) {
choosable.add(cardId);
}
}
if (!choosable.isEmpty()) {
options.put("choosable", (Serializable) choosable);
}
game.fireSelectTargetEvent(playerId, target.getMessage(), cards, required, options);
waitForResponse(game); waitForResponse(game);
if (response.getUUID() != null) { if (response.getUUID() != null) {
if (target.getTargets().contains(response.getUUID())) { // if already included remove it
target.remove(response.getUUID());
} else {
if (target.canTarget(response.getUUID(), cards, game)) { if (target.canTarget(response.getUUID(), cards, game)) {
target.addTarget(response.getUUID(), source, game); target.addTarget(response.getUUID(), source, game);
if(target.doneChosing()){ if (target.doneChosing()) {
return true; return true;
} }
} }
}
} else { } else {
if (target.getTargets().size() >= target.getNumberOfTargets()) { if (target.getTargets().size() >= target.getNumberOfTargets()) {
return true; return true;
@ -606,17 +622,17 @@ public class HumanPlayer extends PlayerImpl {
@Override @Override
public boolean playMana(ManaCost unpaid, Game game) { public boolean playMana(ManaCost unpaid, String promptText, Game game) {
payManaMode = true; payManaMode = true;
boolean result = playManaHandling(unpaid, game); boolean result = playManaHandling(unpaid, promptText, game);
payManaMode = false; payManaMode = false;
return result; return result;
} }
protected boolean playManaHandling(ManaCost unpaid, Game game) { protected boolean playManaHandling(ManaCost unpaid, String promptText, Game game) {
updateGameStatePriority("playMana", game); updateGameStatePriority("playMana", game);
game.firePlayManaEvent(playerId, "Pay " + unpaid.getText()); game.firePlayManaEvent(playerId, "Pay " + promptText);
waitForResponse(game); waitForResponse(game);
if (!this.isInGame()) { if (!this.isInGame()) {
return false; return false;

View file

@ -21,15 +21,8 @@
<module>Mage.Game.CommanderFreeForAll</module> <module>Mage.Game.CommanderFreeForAll</module>
<module>Mage.Game.FreeForAll</module> <module>Mage.Game.FreeForAll</module>
<module>Mage.Game.TwoPlayerDuel</module> <module>Mage.Game.TwoPlayerDuel</module>
<module>Mage.Player.AI</module>
<module>Mage.Player.AIMinimax</module>
<module>Mage.Player.AI.MA</module>
<module>Mage.Player.AIMCTS</module>
<module>Mage.Player.AI.DraftBot</module>
<module>Mage.Player.Human</module> <module>Mage.Player.Human</module>
<module>Mage.Tournament.BoosterDraft</module> <module>Mage.Game.TinyLeadersDuel</module>
<module>Mage.Tournament.Constructed</module>
<module>Mage.Tournament.Sealed</module>
</modules> </modules>
</project> </project>

View file

@ -48,6 +48,7 @@
<gameType name="Free For All" jar="mage-game-freeforall.jar" className="mage.game.FreeForAllMatch" typeName="mage.game.FreeForAllType"/> <gameType name="Free For All" jar="mage-game-freeforall.jar" className="mage.game.FreeForAllMatch" typeName="mage.game.FreeForAllType"/>
<gameType name="Commander Two Player Duel" jar="mage-game-commanderduel.jar" className="mage.game.CommanderDuelMatch" typeName="mage.game.CommanderDuelType"/> <gameType name="Commander Two Player Duel" jar="mage-game-commanderduel.jar" className="mage.game.CommanderDuelMatch" typeName="mage.game.CommanderDuelType"/>
<gameType name="Commander Free For All" jar="mage-game-commanderfreeforall.jar" className="mage.game.CommanderFreeForAllMatch" typeName="mage.game.CommanderFreeForAllType"/> <gameType name="Commander Free For All" jar="mage-game-commanderfreeforall.jar" className="mage.game.CommanderFreeForAllMatch" typeName="mage.game.CommanderFreeForAllType"/>
<gameType name="Tiny Leaders Two Player Duel" jar="mage-game-tinyleadersduel.jar" className="mage.game.TinyLeadersDuelMatch" typeName="mage.game.TinyLeadersDuelType"/>
</gameTypes> </gameTypes>
<tournamentTypes> <tournamentTypes>
<tournamentType name="Constructed Elimination" jar="mage-tournament-constructed.jar" className="mage.tournament.ConstructedEliminationTournament" typeName="mage.tournament.ConstructedEliminationTournamentType"/> <tournamentType name="Constructed Elimination" jar="mage-tournament-constructed.jar" className="mage.tournament.ConstructedEliminationTournament" typeName="mage.tournament.ConstructedEliminationTournamentType"/>
@ -91,6 +92,7 @@
<deckType name="Block Constructed - Zendikar" jar="mage-deck-constructed.jar" className="mage.deck.ZendikarBlock"/> <deckType name="Block Constructed - Zendikar" jar="mage-deck-constructed.jar" className="mage.deck.ZendikarBlock"/>
<deckType name="Variant Magic - Commander" jar="mage-deck-constructed.jar" className="mage.deck.Commander"/> <deckType name="Variant Magic - Commander" jar="mage-deck-constructed.jar" className="mage.deck.Commander"/>
<deckType name="Variant Magic - Duel Commander" jar="mage-deck-constructed.jar" className="mage.deck.DuelCommander"/> <deckType name="Variant Magic - Duel Commander" jar="mage-deck-constructed.jar" className="mage.deck.DuelCommander"/>
<deckType name="Variant Magic - Tiny Leaders" jar="mage-deck-constructed.jar" className="mage.deck.TinyLeaders"/>
<deckType name="Limited" jar="mage-deck-limited.jar" className="mage.deck.Limited"/> <deckType name="Limited" jar="mage-deck-limited.jar" className="mage.deck.Limited"/>
</deckTypes> </deckTypes>
</config> </config>

View file

@ -133,6 +133,12 @@
<version>${project.version}</version> <version>${project.version}</version>
<scope>runtime</scope> <scope>runtime</scope>
</dependency> </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>mage-game-tinyleadersduel</artifactId>
<version>${project.version}</version>
<scope>runtime</scope>
</dependency>
</dependencies> </dependencies>
<build> <build>

View file

@ -924,7 +924,9 @@ public class TableController {
} }
if (matchPlayer.getPlayer().isHuman()) { if (matchPlayer.getPlayer().isHuman()) {
humanPlayers++; humanPlayers++;
if ((table.getState().equals(TableState.WAITING) || table.getState().equals(TableState.STARTING) || table.getState().equals(TableState.READY_TO_START)) || if ((table.getState().equals(TableState.WAITING) ||
table.getState().equals(TableState.STARTING) ||
table.getState().equals(TableState.READY_TO_START)) ||
!match.isDoneSideboarding() || !match.isDoneSideboarding() ||
(!matchPlayer.hasQuit() && match.getGame() != null && matchPlayer.getPlayer().isInGame())) { (!matchPlayer.hasQuit() && match.getGame() != null && matchPlayer.getPlayer().isInGame())) {
User user = UserManager.getInstance().getUser(userPlayerEntry.getKey()); User user = UserManager.getInstance().getUser(userPlayerEntry.getKey());

View file

@ -395,8 +395,6 @@ public class TableManager {
debugServerState(); debugServerState();
} }
logger.debug("TABLE HEALTH CHECK"); logger.debug("TABLE HEALTH CHECK");
List<UUID> toRemove = new ArrayList<>();
ArrayList<Table> tableCopy = new ArrayList<>(); ArrayList<Table> tableCopy = new ArrayList<>();
tableCopy.addAll(tables.values()); tableCopy.addAll(tables.values());
for (Table table : tableCopy) { for (Table table : tableCopy) {
@ -406,13 +404,13 @@ public class TableManager {
logger.debug(table.getId() + " [" + table.getName()+ "] " + formatter.format(table.getStartTime() == null ? table.getCreateTime() : table.getCreateTime()) +" (" + table.getState().toString() + ") " + (table.isTournament() ? "- Tournament":"")); logger.debug(table.getId() + " [" + table.getName()+ "] " + formatter.format(table.getStartTime() == null ? table.getCreateTime() : table.getCreateTime()) +" (" + table.getState().toString() + ") " + (table.isTournament() ? "- Tournament":""));
TableController tableController = getController(table.getId()); TableController tableController = getController(table.getId());
if (tableController != null) { if (tableController != null) {
if (table.isTournament()) { if ((table.isTournament() && !tableController.isTournamentStillValid()) ||
if (!tableController.isTournamentStillValid()) { (!table.isTournament() && !tableController.isMatchTableStillValid())) {
toRemove.add(table.getId()); try {
} logger.warn("Removing unhealthy tableId " + table.getId());
} else { removeTable(table.getId());
if (!tableController.isMatchTableStillValid()) { } catch (Exception e) {
toRemove.add(table.getId()); logger.error(e);
} }
} }
} }
@ -422,14 +420,6 @@ public class TableManager {
logger.debug(Arrays.toString(ex.getStackTrace())); logger.debug(Arrays.toString(ex.getStackTrace()));
} }
} }
for (UUID tableId : toRemove) {
try {
logger.warn("Removing unhealthy tableId " + tableId);
removeTable(tableId);
} catch (Exception e) {
logger.error(e);
}
}
logger.debug("TABLE HEALTH CHECK - END"); logger.debug("TABLE HEALTH CHECK - END");
} }

View file

@ -62,7 +62,7 @@ public class GameWorker<T> implements Callable {
gameController.gameResult(game.getWinner()); gameController.gameResult(game.getWinner());
game.cleanUp(); game.cleanUp();
} catch (MageException ex) { } catch (MageException ex) {
logger.fatal("GameWorker mage error [" + game.getId() + "]" +ex, ex); logger.fatal("GameWorker mage error [" + game.getId() + "]" + ex, ex);
ex.printStackTrace(); ex.printStackTrace();
} catch (Exception e) { } catch (Exception e) {
logger.fatal("GameWorker general exception [" + game.getId() + "]" + e.getMessage(), e); logger.fatal("GameWorker general exception [" + game.getId() + "]" + e.getMessage(), e);

View file

@ -0,0 +1,60 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets;
import java.util.GregorianCalendar;
import mage.cards.ExpansionSet;
import mage.constants.SetType;
/**
*
* @author fireshoes
*/
public class DragonsOfTarkir extends ExpansionSet {
private static final DragonsOfTarkir fINSTANCE = new DragonsOfTarkir();
public static DragonsOfTarkir getInstance() {
return fINSTANCE;
}
private DragonsOfTarkir() {
super("Dragons of Tarkir", "DTK", "mage.sets.dragonsoftarkir", new GregorianCalendar(2015, 3, 27).getTime(), SetType.EXPANSION);
this.blockName = "Dragons of Tarkir";
this.hasBoosters = true;
this.hasBasicLands = true;
this.numBoosterLands = 1;
this.numBoosterCommon = 10;
this.numBoosterUncommon = 3;
this.numBoosterRare = 1;
this.ratioBoosterMythic = 8;
}
}

View file

@ -0,0 +1,52 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.ajanivsnicolbolas;
import java.util.UUID;
/**
*
* @author jeffwadsworth
*/
public class SapseepForest extends mage.sets.shadowmoor.SapseepForest {
public SapseepForest(UUID ownerId) {
super(ownerId);
this.cardNumber = 36;
this.expansionSetCode = "DDH";
}
public SapseepForest(final SapseepForest card) {
super(card);
}
@Override
public SapseepForest copy() {
return new SapseepForest(this);
}
}

View file

@ -36,9 +36,8 @@ import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.filter.common.FilterCreaturePermanent; import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.mageobject.MonocoloredPredicate; import mage.filter.predicate.mageobject.MonocoloredPredicate;
import mage.filter.predicate.permanent.ControllerPredicate;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.players.Player; import mage.players.Player;
@ -91,12 +90,11 @@ class DefilerOfSoulsEffect extends OneShotEffect {
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
FilterCreaturePermanent filter = new FilterCreaturePermanent("monocolored creature"); FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("monocolored creature");
Player player = game.getPlayer(targetPointer.getFirst(game, source)); Player player = game.getPlayer(targetPointer.getFirst(game, source));
if (player == null) { if (player == null) {
return false; return false;
} }
filter.add(new ControllerPredicate(TargetController.YOU));
filter.add(new MonocoloredPredicate()); filter.add(new MonocoloredPredicate());
int amount; int amount;

View file

@ -63,8 +63,7 @@ public class MaelstromNexus extends CardImpl {
// The first spell you cast each turn has cascade. // The first spell you cast each turn has cascade.
this.addAbility(new MaelstromNexusTriggeredAbility()); this.addAbility(new MaelstromNexusTriggeredAbility(), new FirstSpellCastThisTurnWatcher());
this.addWatcher(new FirstSpellCastThisTurnWatcher());
} }

View file

@ -61,8 +61,7 @@ public class PredatoryAdvantage extends CardImpl {
// At the beginning of each opponent's end step, if that player didn't cast a creature spell this turn, put a 2/2 green Lizard creature token onto the battlefield. // At the beginning of each opponent's end step, if that player didn't cast a creature spell this turn, put a 2/2 green Lizard creature token onto the battlefield.
this.addWatcher(new CastCreatureWatcher()); this.addAbility(new BeginningOfEndStepTriggeredAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new LizardToken()), TargetController.OPPONENT, new DidNotCastCreatureCondition(), false), new CastCreatureWatcher());
this.addAbility(new BeginningOfEndStepTriggeredAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new LizardToken()), TargetController.OPPONENT, new DidNotCastCreatureCondition(), false));
} }
public PredatoryAdvantage(final PredatoryAdvantage card) { public PredatoryAdvantage(final PredatoryAdvantage card) {

View file

@ -37,7 +37,7 @@ import mage.cards.CardImpl;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Rarity; import mage.constants.Rarity;
import mage.constants.Zone; import mage.constants.Zone;
import mage.filter.common.FilterArtifactPermanent; import mage.filter.common.FilterControlledArtifactPermanent;
import mage.target.common.TargetControlledPermanent; import mage.target.common.TargetControlledPermanent;
/** /**
@ -50,12 +50,9 @@ public class TimeSieve extends CardImpl {
super(ownerId, 31, "Time Sieve", Rarity.RARE, new CardType[]{CardType.ARTIFACT}, "{U}{B}"); super(ownerId, 31, "Time Sieve", Rarity.RARE, new CardType[]{CardType.ARTIFACT}, "{U}{B}");
this.expansionSetCode = "ARB"; this.expansionSetCode = "ARB";
// {tap}, Sacrifice five artifacts: Take an extra turn after this one. // {tap}, Sacrifice five artifacts: Take an extra turn after this one.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddExtraTurnControllerEffect(), new TapSourceCost()); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddExtraTurnControllerEffect(), new TapSourceCost());
ability.addCost(new SacrificeTargetCost(new TargetControlledPermanent(5, 5, new FilterArtifactPermanent("five artifacts"), true))); ability.addCost(new SacrificeTargetCost(new TargetControlledPermanent(5, 5, new FilterControlledArtifactPermanent("five artifacts"), true)));
this.addAbility(ability); this.addAbility(ability);
} }

View file

@ -79,8 +79,7 @@ public class UnscytheKillerOfKings extends CardImpl {
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(FirstStrikeAbility.getInstance(), AttachmentType.EQUIPMENT))); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(FirstStrikeAbility.getInstance(), AttachmentType.EQUIPMENT)));
// Whenever a creature dealt damage by equipped creature this turn dies, you may exile that card. If you do, put a 2/2 black Zombie creature token onto the battlefield. // Whenever a creature dealt damage by equipped creature this turn dies, you may exile that card. If you do, put a 2/2 black Zombie creature token onto the battlefield.
this.addAbility(new UnscytheKillerOfKingsTriggeredAbility(new UnscytheEffect())); this.addAbility(new UnscytheKillerOfKingsTriggeredAbility(new UnscytheEffect()), new EquippedDidDamageWatcher());
this.addWatcher(new EquippedDidDamageWatcher());
// Equip {2} // Equip {2}
this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(2), new TargetControlledCreaturePermanent())); this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(2), new TargetControlledCreaturePermanent()));

View file

@ -0,0 +1,53 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.antiquities;
import java.util.UUID;
/**
*
* @author Plopman
*/
public class CircleOfProtectionArtifacts extends mage.sets.fifthdawn.CircleOfProtectionArtifacts {
public CircleOfProtectionArtifacts(UUID ownerId) {
super(ownerId);
this.cardNumber = 97;
this.expansionSetCode = "ATQ";
}
public CircleOfProtectionArtifacts(final CircleOfProtectionArtifacts card) {
super(card);
}
@Override
public CircleOfProtectionArtifacts copy() {
return new CircleOfProtectionArtifacts(this);
}
}

View file

@ -0,0 +1,52 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.archenemy;
import java.util.UUID;
/**
*
* @author jeffwadsworth
*/
public class TorrentOfSouls extends mage.sets.shadowmoor.TorrentOfSouls {
public TorrentOfSouls(UUID ownerId) {
super(ownerId);
this.cardNumber = 96;
this.expansionSetCode = "ARC";
}
public TorrentOfSouls(final TorrentOfSouls card) {
super(card);
}
@Override
public TorrentOfSouls copy() {
return new TorrentOfSouls(this);
}
}

View file

@ -62,7 +62,7 @@ public class Aggravate extends CardImpl {
this.getSpellAbility().addTarget(new TargetPlayer()); this.getSpellAbility().addTarget(new TargetPlayer());
// Each creature dealt damage this way attacks this turn if able. // Each creature dealt damage this way attacks this turn if able.
this.getSpellAbility().addEffect(new AggravateRequirementEffect()); this.getSpellAbility().addEffect(new AggravateRequirementEffect());
this.addWatcher(new DamagedByWatcher()); this.getSpellAbility().addWatcher(new DamagedByWatcher());
} }
public Aggravate(final Aggravate card) { public Aggravate(final Aggravate card) {

View file

@ -36,6 +36,7 @@ import mage.Mana;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.AsEntersBattlefieldAbility;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.effects.ContinuousRuleModifiyingEffectImpl; import mage.abilities.effects.ContinuousRuleModifiyingEffectImpl;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.mana.ColorlessManaAbility; import mage.abilities.mana.ColorlessManaAbility;
@ -79,8 +80,7 @@ public class CavernOfSouls extends CardImpl {
this.addAbility(new ColorlessManaAbility()); this.addAbility(new ColorlessManaAbility());
// {T}: Add one mana of any color to your mana pool. Spend this mana only to cast a creature spell of the chosen type, and that spell can't be countered. // {T}: Add one mana of any color to your mana pool. Spend this mana only to cast a creature spell of the chosen type, and that spell can't be countered.
this.addAbility(new ConditionalAnyColorManaAbility(1, new CavernOfSoulsManaBuilder())); this.addAbility(new ConditionalAnyColorManaAbility(new TapSourceCost(), 1, new CavernOfSoulsManaBuilder(), true), new CavernOfSoulsWatcher());
this.addWatcher(new CavernOfSoulsWatcher());
this.addAbility(new SimpleStaticAbility(Zone.ALL, new CavernOfSoulsCantCounterEffect())); this.addAbility(new SimpleStaticAbility(Zone.ALL, new CavernOfSoulsCantCounterEffect()));
} }

View file

@ -62,6 +62,7 @@ public class PillarOfFlame extends CardImpl {
this.getSpellAbility().addTarget(new TargetCreatureOrPlayer()); this.getSpellAbility().addTarget(new TargetCreatureOrPlayer());
// If a creature dealt damage this way would die this turn, exile it instead. // If a creature dealt damage this way would die this turn, exile it instead.
this.getSpellAbility().addEffect(new DealtDamageToCreatureBySourceDies(this, Duration.EndOfTurn)); this.getSpellAbility().addEffect(new DealtDamageToCreatureBySourceDies(this, Duration.EndOfTurn));
this.getSpellAbility().addWatcher(new DamagedByWatcher());
} }
public PillarOfFlame(final PillarOfFlame card) { public PillarOfFlame(final PillarOfFlame card) {

View file

@ -63,8 +63,7 @@ public class GoblinCohort extends CardImpl {
this.toughness = new MageInt(2); this.toughness = new MageInt(2);
// Goblin Cohort can't attack unless you've cast a creature spell this turn. // Goblin Cohort can't attack unless you've cast a creature spell this turn.
this.addWatcher(new PlayerCastCreatureWatcher()); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GoblinCohortEffect()), new PlayerCastCreatureWatcher());
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GoblinCohortEffect()));
} }

View file

@ -77,8 +77,8 @@ public class KumanosBlessing extends CardImpl {
this.addAbility(ability); this.addAbility(ability);
// If a creature dealt damage by enchanted creature this turn would die, exile it instead. // If a creature dealt damage by enchanted creature this turn would die, exile it instead.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new KumanosBlessingEffect())); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new KumanosBlessingEffect()), new DamagedByEnchantedWatcher());
this.addWatcher(new DamagedByEnchantedWatcher());
} }
public KumanosBlessing(final KumanosBlessing card) { public KumanosBlessing(final KumanosBlessing card) {

View file

@ -37,7 +37,7 @@ import mage.cards.CardImpl;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Rarity; import mage.constants.Rarity;
import mage.constants.Zone; import mage.constants.Zone;
import mage.filter.common.FilterCreaturePermanent; import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.common.FilterPermanentCard; import mage.filter.common.FilterPermanentCard;
import mage.filter.predicate.mageobject.SubtypePredicate; import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.filter.predicate.mageobject.SupertypePredicate; import mage.filter.predicate.mageobject.SupertypePredicate;
@ -70,7 +70,7 @@ public class Lifespinner extends CardImpl {
SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD,
new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(filter)), new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(filter)),
new TapSourceCost()); new TapSourceCost());
ability.addCost(new SacrificeTargetCost(new TargetControlledPermanent(3, 3, new FilterCreaturePermanent("Spirit", "three Spirits"), false))); ability.addCost(new SacrificeTargetCost(new TargetControlledPermanent(3, 3, new FilterControlledCreaturePermanent("Spirit", "three Spirits"), false)));
this.addAbility(ability); this.addAbility(ability);
} }

View file

@ -34,7 +34,7 @@ import mage.abilities.keyword.SpliceOntoArcaneAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Rarity; import mage.constants.Rarity;
import mage.filter.common.FilterLandPermanent; import mage.filter.common.FilterControlledLandPermanent;
import mage.filter.predicate.mageobject.SubtypePredicate; import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.target.common.TargetControlledPermanent; import mage.target.common.TargetControlledPermanent;
import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetCreaturePermanent;
@ -44,7 +44,7 @@ import mage.target.common.TargetCreaturePermanent;
* @author LevelX2 * @author LevelX2
*/ */
public class TorrentOfStone extends CardImpl { public class TorrentOfStone extends CardImpl {
private static final FilterLandPermanent filterSacrifice = new FilterLandPermanent("two Mountains"); private static final FilterControlledLandPermanent filterSacrifice = new FilterControlledLandPermanent("two Mountains");
static { static {
filterSacrifice.add(new SubtypePredicate("Mountain")); filterSacrifice.add(new SubtypePredicate("Mountain"));

View file

@ -78,8 +78,8 @@ public class EpharaGodOfThePolis extends CardImpl {
this.addAbility(new ConditionalTriggeredAbility( this.addAbility(new ConditionalTriggeredAbility(
new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), TargetController.ANY, false), new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), TargetController.ANY, false),
HadAnotherCreatureEnterTheBattlefieldCondition.getInstance(), HadAnotherCreatureEnterTheBattlefieldCondition.getInstance(),
"At the beginning of each upkeep, if you had another creature enter the battlefield under your control last turn, draw a card.")); "At the beginning of each upkeep, if you had another creature enter the battlefield under your control last turn, draw a card."),
this.addWatcher(new CreatureEnteredBattlefieldLastTurnWatcher()); new CreatureEnteredBattlefieldLastTurnWatcher());
} }

View file

@ -28,6 +28,7 @@
package mage.sets.bornofthegods; package mage.sets.bornofthegods;
import java.util.UUID; import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility; import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
@ -162,6 +163,7 @@ class SearingBloodDelayedEffect extends OneShotEffect {
if (permanent != null) { if (permanent != null) {
Player player = game.getPlayer(permanent.getControllerId()); Player player = game.getPlayer(permanent.getControllerId());
if (player != null) { if (player != null) {
MageObject sourceObject = source.getSourceObject(game);
player.damage(3, source.getSourceId(), game, false, true); player.damage(3, source.getSourceId(), game, false, true);
return true; return true;
} }

View file

@ -60,8 +60,7 @@ public class SpiritOfTheLabyrinth extends CardImpl {
this.toughness = new MageInt(1); this.toughness = new MageInt(1);
// Each player can't draw more than one card each turn. // Each player can't draw more than one card each turn.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpiritOfTheLabyrinthEffect())); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpiritOfTheLabyrinthEffect()), new SpiritOfTheLabyrinthWatcher());
this.addWatcher(new SpiritOfTheLabyrinthWatcher());
} }

View file

@ -54,8 +54,7 @@ public class AshenSkinZubera extends CardImpl {
this.toughness = new MageInt(2); this.toughness = new MageInt(2);
Ability ability = new DiesTriggeredAbility(new DiscardTargetEffect(new ZuberasDiedDynamicValue())); Ability ability = new DiesTriggeredAbility(new DiscardTargetEffect(new ZuberasDiedDynamicValue()));
ability.addTarget(new TargetOpponent()); ability.addTarget(new TargetOpponent());
this.addAbility(ability); this.addAbility(ability, new ZuberasDiedWatcher());
this.addWatcher(new ZuberasDiedWatcher());
} }
public AshenSkinZubera(final AshenSkinZubera card) { public AshenSkinZubera(final AshenSkinZubera card) {

View file

@ -75,8 +75,7 @@ public class BoseijuWhoSheltersAll extends CardImpl {
ability.getEffects().get(0).setText("Add {1} to your mana pool. If that mana is spent on an instant or sorcery spell, that spell can't be countered by spells or abilities"); ability.getEffects().get(0).setText("Add {1} to your mana pool. If that mana is spent on an instant or sorcery spell, that spell can't be countered by spells or abilities");
this.addAbility(ability); this.addAbility(ability);
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoseijuWhoSheltersAllCantCounterEffect())); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoseijuWhoSheltersAllCantCounterEffect()), new BoseijuWhoSheltersAllWatcher());
this.addWatcher(new BoseijuWhoSheltersAllWatcher());
} }
public BoseijuWhoSheltersAll(final BoseijuWhoSheltersAll card) { public BoseijuWhoSheltersAll(final BoseijuWhoSheltersAll card) {

View file

@ -51,8 +51,7 @@ public class DrippingTongueZubera extends CardImpl {
this.color.setGreen(true); this.color.setGreen(true);
this.power = new MageInt(1); this.power = new MageInt(1);
this.toughness = new MageInt(2); this.toughness = new MageInt(2);
this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new SpiritToken(), new ZuberasDiedDynamicValue()), false)); this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new SpiritToken(), new ZuberasDiedDynamicValue()), false), new ZuberasDiedWatcher());
this.addWatcher(new ZuberasDiedWatcher());
} }
public DrippingTongueZubera (final DrippingTongueZubera card) { public DrippingTongueZubera (final DrippingTongueZubera card) {

View file

@ -55,8 +55,7 @@ public class EmberFistZubera extends CardImpl {
this.toughness = new MageInt(2); this.toughness = new MageInt(2);
Ability ability = new DiesTriggeredAbility(new DamageTargetEffect(new ZuberasDiedDynamicValue())); Ability ability = new DiesTriggeredAbility(new DamageTargetEffect(new ZuberasDiedDynamicValue()));
ability.addTarget(new TargetCreatureOrPlayer()); ability.addTarget(new TargetCreatureOrPlayer());
this.addAbility(ability); this.addAbility(ability, new ZuberasDiedWatcher());
this.addWatcher(new ZuberasDiedWatcher());
} }
public EmberFistZubera (final EmberFistZubera card) { public EmberFistZubera (final EmberFistZubera card) {

View file

@ -32,13 +32,12 @@ import java.util.UUID;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.constants.Rarity; import mage.constants.Rarity;
import mage.constants.Zone;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.DestroyTargetEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledLandPermanent;
import mage.filter.common.FilterLandPermanent; import mage.filter.common.FilterControlledPermanent;
import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.filter.predicate.permanent.ControllerIdPredicate;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
@ -93,23 +92,25 @@ class FeastOfWormsEffect extends OneShotEffect {
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
Permanent permanent = (Permanent) game.getLastKnownInformation(source.getFirstTarget(), Zone.BATTLEFIELD); Permanent permanent = game.getPermanentOrLKIBattlefield(id);
Player targetPlayer = game.getPlayer(permanent.getControllerId()); Player targetPlayer = null;
if (targetPlayer != null && permanent != null && (permanent.getSupertype().get(0).toString().equals("Legendary"))) { if (permanent != null) {
FilterPermanent filter = new FilterLandPermanent("land to sacrifice"); targetPlayer = game.getPlayer(permanent.getControllerId());
}
if (targetPlayer != null && permanent != null && (permanent.getSupertype().get(0).equals("Legendary"))) {
FilterControlledPermanent filter = new FilterControlledLandPermanent("land to sacrifice");
filter.add(new ControllerIdPredicate(targetPlayer.getId())); filter.add(new ControllerIdPredicate(targetPlayer.getId()));
TargetControlledPermanent target = new TargetControlledPermanent(1, 1, filter, false); TargetControlledPermanent target = new TargetControlledPermanent(1, 1, filter, false);
if (target.canChoose(targetPlayer.getId(), game)) { if (target.canChoose(targetPlayer.getId(), game)) {
targetPlayer.choose(Outcome.Sacrifice, target, source.getSourceId(), game); targetPlayer.chooseTarget(Outcome.Sacrifice, target, source, game);
Permanent land = game.getPermanent(target.getFirstTarget()); Permanent land = game.getPermanent(target.getFirstTarget());
if (land != null) { if (land != null) {
return land.sacrifice(source.getSourceId(), game); land.sacrifice(source.getSourceId(), game);
}
} }
return true; return true;
} }
}
return false; return false;
} }
} }

View file

@ -60,8 +60,7 @@ public class FloatingDreamZubera extends CardImpl {
this.color.setBlue(true); this.color.setBlue(true);
this.power = new MageInt(1); this.power = new MageInt(1);
this.toughness = new MageInt(2); this.toughness = new MageInt(2);
this.addAbility(new DiesTriggeredAbility(new DrawCardSourceControllerEffect(new ZuberasDiedDynamicValue()))); this.addAbility(new DiesTriggeredAbility(new DrawCardSourceControllerEffect(new ZuberasDiedDynamicValue())), new ZuberasDiedWatcher());
this.addWatcher(new ZuberasDiedWatcher());
} }
public FloatingDreamZubera(final FloatingDreamZubera card) { public FloatingDreamZubera(final FloatingDreamZubera card) {

View file

@ -42,6 +42,7 @@ import mage.constants.Duration;
import mage.constants.Rarity; import mage.constants.Rarity;
import mage.constants.Zone; import mage.constants.Zone;
import mage.target.common.TargetCreatureOrPlayer; import mage.target.common.TargetCreatureOrPlayer;
import mage.watchers.common.DamagedByWatcher;
/** /**
* @author LevelX * @author LevelX
@ -62,7 +63,7 @@ public class Frostwielder extends CardImpl {
ability.addTarget(new TargetCreatureOrPlayer()); ability.addTarget(new TargetCreatureOrPlayer());
this.addAbility(ability); this.addAbility(ability);
// If a creature dealt damage by Frostwielder this turn would die, exile it instead. // If a creature dealt damage by Frostwielder this turn would die, exile it instead.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new DealtDamageToCreatureBySourceDies(this, Duration.WhileOnBattlefield))); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new DealtDamageToCreatureBySourceDies(this, Duration.WhileOnBattlefield)), new DamagedByWatcher());
} }

View file

@ -77,9 +77,7 @@ public class HallOfTheBanditLord extends CardImpl {
effect.setText("Add {1} to your mana pool. If that mana is spent on a creature spell, it gains haste"); effect.setText("Add {1} to your mana pool. If that mana is spent on a creature spell, it gains haste");
Ability ability = new SimpleManaAbility(Zone.BATTLEFIELD, effect, new TapSourceCost()); Ability ability = new SimpleManaAbility(Zone.BATTLEFIELD, effect, new TapSourceCost());
ability.addCost(new PayLifeCost(3)); ability.addCost(new PayLifeCost(3));
this.addAbility(ability); this.addAbility(ability, new HallOfTheBanditLordWatcher(ability));
this.addWatcher(new HallOfTheBanditLordWatcher(ability));
} }
public HallOfTheBanditLord(final HallOfTheBanditLord card) { public HallOfTheBanditLord(final HallOfTheBanditLord card) {

View file

@ -44,6 +44,7 @@ import mage.constants.Duration;
import mage.constants.Rarity; import mage.constants.Rarity;
import mage.constants.Zone; import mage.constants.Zone;
import mage.target.common.TargetCreatureOrPlayer; import mage.target.common.TargetCreatureOrPlayer;
import mage.watchers.common.DamagedByWatcher;
/** /**
* @author LevelX * @author LevelX
@ -65,7 +66,7 @@ public class KumanoMasterYamabushi extends CardImpl {
ability.addTarget(new TargetCreatureOrPlayer()); ability.addTarget(new TargetCreatureOrPlayer());
this.addAbility(ability); this.addAbility(ability);
// If a creature dealt damage by Kumano this turn would die, exile it instead. // If a creature dealt damage by Kumano this turn would die, exile it instead.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new DealtDamageToCreatureBySourceDies(this, Duration.WhileOnBattlefield))); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new DealtDamageToCreatureBySourceDies(this, Duration.WhileOnBattlefield)), new DamagedByWatcher());
} }

View file

@ -37,6 +37,7 @@ import mage.constants.CardType;
import mage.constants.Duration; import mage.constants.Duration;
import mage.constants.Rarity; import mage.constants.Rarity;
import mage.constants.Zone; import mage.constants.Zone;
import mage.watchers.common.DamagedByWatcher;
/** /**
* @author LevelX * @author LevelX
@ -53,7 +54,7 @@ public class KumanosPupils extends CardImpl {
this.toughness = new MageInt(3); this.toughness = new MageInt(3);
// If a creature dealt damage by Kumano's Pupils this turn would die, exile it instead. // If a creature dealt damage by Kumano's Pupils this turn would die, exile it instead.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new DealtDamageToCreatureBySourceDies(this, Duration.WhileOnBattlefield))); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new DealtDamageToCreatureBySourceDies(this, Duration.WhileOnBattlefield)), new DamagedByWatcher());
} }
public KumanosPupils(final KumanosPupils card) { public KumanosPupils(final KumanosPupils card) {

View file

@ -72,7 +72,7 @@ public class MyojinOfCleansingFire extends CardImpl {
this.power = new MageInt(4); this.power = new MageInt(4);
this.toughness = new MageInt(6); this.toughness = new MageInt(6);
this.addWatcher(new CastFromHandWatcher()); this.getSpellAbility().addWatcher(new CastFromHandWatcher());
// Myojin of Cleansing Fire enters the battlefield with a divinity counter on it if you cast it from your hand. // Myojin of Cleansing Fire enters the battlefield with a divinity counter on it if you cast it from your hand.
this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.DIVINITY.createInstance()), new CastFromHandCondition(), ""), "{this} enters the battlefield with a divinity counter on it if you cast it from your hand")); this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.DIVINITY.createInstance()), new CastFromHandCondition(), ""), "{this} enters the battlefield with a divinity counter on it if you cast it from your hand"));

View file

@ -68,7 +68,7 @@ public class MyojinOfInfiniteRage extends CardImpl {
this.power = new MageInt(7); this.power = new MageInt(7);
this.toughness = new MageInt(4); this.toughness = new MageInt(4);
this.addWatcher(new CastFromHandWatcher()); this.getSpellAbility().addWatcher(new CastFromHandWatcher());
// Myojin of Infinite Rage enters the battlefield with a divinity counter on it if you cast it from your hand. // Myojin of Infinite Rage enters the battlefield with a divinity counter on it if you cast it from your hand.
this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.DIVINITY.createInstance()), new CastFromHandCondition(), ""), "{this} enters the battlefield with a divinity counter on it if you cast it from your hand")); this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.DIVINITY.createInstance()), new CastFromHandCondition(), ""), "{this} enters the battlefield with a divinity counter on it if you cast it from your hand"));

View file

@ -73,7 +73,7 @@ public class MyojinOfLifesWeb extends CardImpl {
this.power = new MageInt(8); this.power = new MageInt(8);
this.toughness = new MageInt(8); this.toughness = new MageInt(8);
this.addWatcher(new CastFromHandWatcher()); this.getSpellAbility().addWatcher(new CastFromHandWatcher());
// Myojin of Life's Web enters the battlefield with a divinity counter on it if you cast it from your hand. // Myojin of Life's Web enters the battlefield with a divinity counter on it if you cast it from your hand.
this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.DIVINITY.createInstance()), new CastFromHandCondition(), ""), "{this} enters the battlefield with a divinity counter on it if you cast it from your hand")); this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.DIVINITY.createInstance()), new CastFromHandCondition(), ""), "{this} enters the battlefield with a divinity counter on it if you cast it from your hand"));

View file

@ -66,7 +66,7 @@ public class MyojinOfNightsReach extends CardImpl {
this.power = new MageInt(5); this.power = new MageInt(5);
this.toughness = new MageInt(2); this.toughness = new MageInt(2);
this.addWatcher(new CastFromHandWatcher()); this.getSpellAbility().addWatcher(new CastFromHandWatcher());
// Myojin of Night's Reach enters the battlefield with a divinity counter on it if you cast it from your hand. // Myojin of Night's Reach enters the battlefield with a divinity counter on it if you cast it from your hand.
this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.DIVINITY.createInstance()), new CastFromHandCondition(), ""), "{this} enters the battlefield with a divinity counter on it if you cast it from your hand")); this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.DIVINITY.createInstance()), new CastFromHandCondition(), ""), "{this} enters the battlefield with a divinity counter on it if you cast it from your hand"));

View file

@ -71,7 +71,7 @@ public class MyojinOfSeeingWinds extends CardImpl {
this.power = new MageInt(3); this.power = new MageInt(3);
this.toughness = new MageInt(3); this.toughness = new MageInt(3);
this.addWatcher(new CastFromHandWatcher()); this.getSpellAbility().addWatcher(new CastFromHandWatcher());
// Myojin of Seeing Winds enters the battlefield with a divinity counter on it if you cast it from your hand. // Myojin of Seeing Winds enters the battlefield with a divinity counter on it if you cast it from your hand.
this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.DIVINITY.createInstance()), new CastFromHandCondition(), ""), "{this} enters the battlefield with a divinity counter on it if you cast it from your hand")); this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.DIVINITY.createInstance()), new CastFromHandCondition(), ""), "{this} enters the battlefield with a divinity counter on it if you cast it from your hand"));

View file

@ -36,7 +36,7 @@ import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ReplacementEffectImpl; import mage.abilities.effects.ReplacementEffectImpl;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.counters.CounterType; import mage.counters.CounterType;
import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledPermanent;
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.Permanent;
@ -106,7 +106,7 @@ class ShimatsuTheBloodcloakedEffect extends ReplacementEffectImpl {
Permanent creature = game.getPermanent(event.getTargetId()); Permanent creature = game.getPermanent(event.getTargetId());
Player controller = game.getPlayer(source.getControllerId()); Player controller = game.getPlayer(source.getControllerId());
if (creature != null && controller != null) { if (creature != null && controller != null) {
Target target = new TargetControlledPermanent(0, Integer.MAX_VALUE, new FilterPermanent(), true); Target target = new TargetControlledPermanent(0, Integer.MAX_VALUE, new FilterControlledPermanent(), true);
if (!target.canChoose(source.getSourceId(), source.getControllerId(), game)) { if (!target.canChoose(source.getSourceId(), source.getControllerId(), game)) {
return false; return false;
} }

View file

@ -74,7 +74,7 @@ public class SiftThroughSands extends CardImpl {
this.getSpellAbility().addEffect(effect); this.getSpellAbility().addEffect(effect);
// If you've cast a spell named Peer Through Depths and a spell named Reach Through Mists this turn, you may search your library for a card named The Unspeakable, put it onto the battlefield, then shuffle your library. // If you've cast a spell named Peer Through Depths and a spell named Reach Through Mists this turn, you may search your library for a card named The Unspeakable, put it onto the battlefield, then shuffle your library.
this.getSpellAbility().addEffect(new ConditionalOneShotEffect(new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(filter), false, true), new SiftThroughSandsCondition(), rule)); this.getSpellAbility().addEffect(new ConditionalOneShotEffect(new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(filter), false, true), new SiftThroughSandsCondition(), rule));
this.addWatcher(new SiftThroughSandsWatcher()); this.getSpellAbility().addWatcher(new SiftThroughSandsWatcher());
} }
public SiftThroughSands(final SiftThroughSands card) { public SiftThroughSands(final SiftThroughSands card) {

View file

@ -56,8 +56,7 @@ public class SilentChantZubera extends CardImpl {
this.power = new MageInt(1); this.power = new MageInt(1);
this.toughness = new MageInt(2); this.toughness = new MageInt(2);
Ability ability = new DiesTriggeredAbility(new GainLifeEffect(new SilentChantZuberaDynamicValue())); Ability ability = new DiesTriggeredAbility(new GainLifeEffect(new SilentChantZuberaDynamicValue()));
this.addAbility(ability); this.addAbility(ability, new ZuberasDiedWatcher());
this.addWatcher(new ZuberasDiedWatcher());
} }
public SilentChantZubera (final SilentChantZubera card) { public SilentChantZubera (final SilentChantZubera card) {

View file

@ -41,7 +41,7 @@ import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.constants.Zone; import mage.constants.Zone;
import mage.filter.FilterSpell; import mage.filter.FilterSpell;
import mage.filter.common.FilterLandPermanent; import mage.filter.common.FilterControlledLandPermanent;
import mage.filter.predicate.Predicates; import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.CardTypePredicate; import mage.filter.predicate.mageobject.CardTypePredicate;
import mage.target.TargetSpell; import mage.target.TargetSpell;
@ -67,7 +67,7 @@ public class UyoSilentProphet extends CardImpl {
this.supertype.add("Legendary"); this.supertype.add("Legendary");
this.subtype.add("Moonfolk"); this.subtype.add("Moonfolk");
this.subtype.add("Wizard"); this.subtype.add("Wizard");
this.color.setBlue(true);
this.power = new MageInt(4); this.power = new MageInt(4);
this.toughness = new MageInt(4); this.toughness = new MageInt(4);
@ -75,7 +75,7 @@ public class UyoSilentProphet extends CardImpl {
this.addAbility(FlyingAbility.getInstance()); this.addAbility(FlyingAbility.getInstance());
// {2}, Return two lands you control to their owner's hand: Copy target instant or sorcery spell. You may choose new targets for the copy. // {2}, Return two lands you control to their owner's hand: Copy target instant or sorcery spell. You may choose new targets for the copy.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CopyTargetSpellEffect(), new GenericManaCost(2)); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CopyTargetSpellEffect(), new GenericManaCost(2));
ability.addCost(new ReturnToHandTargetCost(new TargetControlledPermanent(2, 2, new FilterLandPermanent("lands"), false))); ability.addCost(new ReturnToHandTargetCost(new TargetControlledPermanent(2, 2, new FilterControlledLandPermanent("lands"), false)));
ability.addTarget(new TargetSpell(filter)); ability.addTarget(new TargetSpell(filter));
this.addAbility(ability); this.addAbility(ability);
} }

View file

@ -37,6 +37,7 @@ import mage.constants.CardType;
import mage.constants.Duration; import mage.constants.Duration;
import mage.constants.Rarity; import mage.constants.Rarity;
import mage.target.common.TargetCreatureOrPlayer; import mage.target.common.TargetCreatureOrPlayer;
import mage.watchers.common.DamagedByWatcher;
/** /**
* *
@ -55,6 +56,7 @@ public class YamabushisFlame extends CardImpl {
// If a creature dealt damage this way would die this turn, exile it instead. // If a creature dealt damage this way would die this turn, exile it instead.
this.getSpellAbility().addEffect(new DealtDamageToCreatureBySourceDies(this, Duration.EndOfTurn)); this.getSpellAbility().addEffect(new DealtDamageToCreatureBySourceDies(this, Duration.EndOfTurn));
this.getSpellAbility().addWatcher(new DamagedByWatcher());
} }
public YamabushisFlame(final YamabushisFlame card) { public YamabushisFlame(final YamabushisFlame card) {

View file

@ -63,6 +63,7 @@ public class YamabushisStorm extends CardImpl {
this.getSpellAbility().addEffect(new DamageAllEffect(1, new FilterCreaturePermanent())); this.getSpellAbility().addEffect(new DamageAllEffect(1, new FilterCreaturePermanent()));
// If a creature dealt damage this way would die this turn, exile it instead. // If a creature dealt damage this way would die this turn, exile it instead.
this.getSpellAbility().addEffect(new DealtDamageToCreatureBySourceDies(this, Duration.EndOfTurn)); this.getSpellAbility().addEffect(new DealtDamageToCreatureBySourceDies(this, Duration.EndOfTurn));
this.getSpellAbility().addWatcher(new DamagedByWatcher());
} }
public YamabushisStorm(final YamabushisStorm card) { public YamabushisStorm(final YamabushisStorm card) {

View file

@ -75,7 +75,7 @@ public class FuryOfTheHorde extends CardImpl {
// Untap all creatures that attacked this turn. After this main phase, there is an additional combat phase followed by an additional main phase. // Untap all creatures that attacked this turn. After this main phase, there is an additional combat phase followed by an additional main phase.
this.getSpellAbility().addEffect(new FuryOfTheHordeUntapEffect()); this.getSpellAbility().addEffect(new FuryOfTheHordeUntapEffect());
this.getSpellAbility().addEffect(new FuryOfTheHordeAddPhasesEffect()); this.getSpellAbility().addEffect(new FuryOfTheHordeAddPhasesEffect());
this.addWatcher(new AttackedThisTurnWatcher()); this.getSpellAbility().addWatcher(new AttackedThisTurnWatcher());
} }

View file

@ -100,7 +100,7 @@ class LightningStormCountCondition implements DynamicValue {
public int calculate(Game game, Ability sourceAbility, Effect effect) { public int calculate(Game game, Ability sourceAbility, Effect effect) {
Spell spell = game.getStack().getSpell(sourceAbility.getSourceId()); Spell spell = game.getStack().getSpell(sourceAbility.getSourceId());
if (spell != null) { if (spell != null) {
return spell.getCounters().getCount(counter) + 3; return spell.getCounters(game).getCount(counter) + 3;
} }
return 0; return 0;
} }

View file

@ -66,8 +66,7 @@ public class CourtHussar extends CardImpl {
new LookLibraryAndPickControllerEffect(new StaticValue(3), false, new StaticValue(1), new FilterCard(), Zone.LIBRARY, false, false), new LookLibraryAndPickControllerEffect(new StaticValue(3), false, new StaticValue(1), new FilterCard(), Zone.LIBRARY, false, false),
false)); false));
// When Court Hussar enters the battlefield, sacrifice it unless {W} was spent to cast it. // When Court Hussar enters the battlefield, sacrifice it unless {W} was spent to cast it.
this.addAbility(new EntersBattlefieldTriggeredAbility(new SacrificeSourceUnlessConditionEffect(new ManaWasSpentCondition(ColoredManaSymbol.W)), false)); this.addAbility(new EntersBattlefieldTriggeredAbility(new SacrificeSourceUnlessConditionEffect(new ManaWasSpentCondition(ColoredManaSymbol.W)), false), new ManaSpentToCastWatcher());
this.addWatcher(new ManaSpentToCastWatcher());
} }
public CourtHussar(final CourtHussar card) { public CourtHussar(final CourtHussar card) {

View file

@ -82,8 +82,7 @@ public class KaradorGhostChieftain extends CardImpl {
this.addAbility(new SimpleStaticAbility(Zone.STACK, new KaradorGhostChieftainCostReductionEffect())); this.addAbility(new SimpleStaticAbility(Zone.STACK, new KaradorGhostChieftainCostReductionEffect()));
// During each of your turns, you may cast one creature card from your graveyard. // During each of your turns, you may cast one creature card from your graveyard.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new KaradorGhostChieftainContinuousEffect())); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new KaradorGhostChieftainContinuousEffect()), new KaradorGhostChieftainWatcher());
this.addWatcher(new KaradorGhostChieftainWatcher());
} }
public KaradorGhostChieftain(final KaradorGhostChieftain card) { public KaradorGhostChieftain(final KaradorGhostChieftain card) {

View file

@ -60,8 +60,7 @@ public class AzoriusHerald extends CardImpl {
// When Azorius Herald enters the battlefield, you gain 4 life. // When Azorius Herald enters the battlefield, you gain 4 life.
this.addAbility(new EntersBattlefieldTriggeredAbility(new GainLifeEffect(4))); this.addAbility(new EntersBattlefieldTriggeredAbility(new GainLifeEffect(4)));
// When Azorius Herald enters the battlefield, sacrifice it unless {U} was spent to cast it. // When Azorius Herald enters the battlefield, sacrifice it unless {U} was spent to cast it.
this.addAbility(new EntersBattlefieldTriggeredAbility(new SacrificeSourceUnlessConditionEffect(new ManaWasSpentCondition(ColoredManaSymbol.U)), false)); this.addAbility(new EntersBattlefieldTriggeredAbility(new SacrificeSourceUnlessConditionEffect(new ManaWasSpentCondition(ColoredManaSymbol.U)), false), new ManaSpentToCastWatcher());
this.addWatcher(new ManaSpentToCastWatcher());
} }
public AzoriusHerald(final AzoriusHerald card) { public AzoriusHerald(final AzoriusHerald card) {

View file

@ -78,8 +78,7 @@ public class FellShepherd extends CardImpl {
this.toughness = new MageInt(6); this.toughness = new MageInt(6);
// Whenever Fell Shepherd deals combat damage to a player, you may return to your hand all creature cards that were put into your graveyard from the battlefield this turn. // Whenever Fell Shepherd deals combat damage to a player, you may return to your hand all creature cards that were put into your graveyard from the battlefield this turn.
this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new FellShepherdEffect(), true)); this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new FellShepherdEffect(), true), new FellShepherdWatcher());
this.addWatcher(new FellShepherdWatcher());
// {B}, Sacrifice another creature: Target creature gets -2/-2 until end of turn. // {B}, Sacrifice another creature: Target creature gets -2/-2 until end of turn.
SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostTargetEffect(-2,-2, Duration.EndOfTurn), new ManaCostsImpl("{B}")); SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostTargetEffect(-2,-2, Duration.EndOfTurn), new ManaCostsImpl("{B}"));

View file

@ -76,8 +76,7 @@ public class JelevaNephaliasScourge extends CardImpl {
// When Jeleva, Nephalia's Scourge enters the battlefield, each player exiles the top X cards of his or her library, where X is the amount of mana spent to cast Jeleva. // When Jeleva, Nephalia's Scourge enters the battlefield, each player exiles the top X cards of his or her library, where X is the amount of mana spent to cast Jeleva.
this.addAbility(new EntersBattlefieldTriggeredAbility(new JelevaNephaliasScourgeEffect(), false)); this.addAbility(new EntersBattlefieldTriggeredAbility(new JelevaNephaliasScourgeEffect(), false));
// Whenever Jeleva attacks, you may cast an instant or sorcery card exiled with it without paying its mana cost. // Whenever Jeleva attacks, you may cast an instant or sorcery card exiled with it without paying its mana cost.
this.addAbility(new AttacksTriggeredAbility(new JelevaNephaliasCastEffect(), false)); this.addAbility(new AttacksTriggeredAbility(new JelevaNephaliasCastEffect(), false), new JelevaNephaliasWatcher());
this.addWatcher(new JelevaNephaliasWatcher());
} }

View file

@ -75,13 +75,12 @@ public class OpalPalace extends CardImpl {
// {1}, {tap}: Add to your mana pool one mana of any color in your commander's color identity. If you spend this mana to cast your commander, it enters the battlefield with a number of +1/+1 counters on it equal to the number of times it's been cast from the command zone this game. // {1}, {tap}: Add to your mana pool one mana of any color in your commander's color identity. If you spend this mana to cast your commander, it enters the battlefield with a number of +1/+1 counters on it equal to the number of times it's been cast from the command zone this game.
Ability ability = new CommanderColorIdentityManaAbility(new GenericManaCost(1)); Ability ability = new CommanderColorIdentityManaAbility(new GenericManaCost(1));
ability.addCost(new TapSourceCost()); ability.addCost(new TapSourceCost());
this.addAbility(ability); this.addAbility(ability, new OpalPalaceWatcher());
ability = new SimpleStaticAbility(Zone.ALL, new OpalPalaceEntersBattlefieldEffect()); ability = new SimpleStaticAbility(Zone.ALL, new OpalPalaceEntersBattlefieldEffect());
ability.setRuleVisible(false); ability.setRuleVisible(false);
this.addAbility(ability); this.addAbility(ability);
this.addWatcher(new OpalPalaceWatcher());
} }
public OpalPalace(final OpalPalace card) { public OpalPalace(final OpalPalace card) {

View file

@ -68,7 +68,7 @@ public class PhantomNantuko extends CardImpl {
// Trample // Trample
this.addAbility(TrampleAbility.getInstance()); this.addAbility(TrampleAbility.getInstance());
// Phantom Nantuko enters the battlefield with two +1/+1 counters on it. // Phantom Nantuko enters the battlefield with two +1/+1 counters on it.
this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance(2), true))); this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance(2), true), "with two +1/+1 counters on it"));
// If damage would be dealt to Phantom Nantuko, prevent that damage. Remove a +1/+1 counter from Phantom Nantuko. // If damage would be dealt to Phantom Nantuko, prevent that damage. Remove a +1/+1 counter from Phantom Nantuko.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new PhantomNantukoPreventionEffect())); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new PhantomNantukoPreventionEffect()));
// {tap}: Put a +1/+1 counter on Phantom Nantuko. // {tap}: Put a +1/+1 counter on Phantom Nantuko.

View file

@ -65,8 +65,7 @@ public class AngelOfTheDireHour extends CardImpl {
Ability ability = new EntersBattlefieldTriggeredAbility( Ability ability = new EntersBattlefieldTriggeredAbility(
new ConditionalOneShotEffect(new ExileAllEffect(new FilterAttackingCreature("attacking creatures")), new CastFromHandCondition(), new ConditionalOneShotEffect(new ExileAllEffect(new FilterAttackingCreature("attacking creatures")), new CastFromHandCondition(),
" if you cast it from your hand, exile all attacking creatures")); " if you cast it from your hand, exile all attacking creatures"));
this.addAbility(ability); this.addAbility(ability, new CastFromHandWatcher());
this.addWatcher(new CastFromHandWatcher());
} }
public AngelOfTheDireHour(final AngelOfTheDireHour card) { public AngelOfTheDireHour(final AngelOfTheDireHour card) {

View file

@ -68,8 +68,7 @@ public class BreachingLeviathan extends CardImpl {
Ability ability = new EntersBattlefieldTriggeredAbility( Ability ability = new EntersBattlefieldTriggeredAbility(
new ConditionalOneShotEffect(new BreachingLeviathanEffect(), new CastFromHandCondition(), new ConditionalOneShotEffect(new BreachingLeviathanEffect(), new CastFromHandCondition(),
"if you cast it from your hand, tap all nonblue creatures. Those creatures don't untap during their controllers' next untap steps")); "if you cast it from your hand, tap all nonblue creatures. Those creatures don't untap during their controllers' next untap steps"));
this.addAbility(ability); this.addAbility(ability, new CastFromHandWatcher());
this.addWatcher(new CastFromHandWatcher());
} }
public BreachingLeviathan(final BreachingLeviathan card) { public BreachingLeviathan(final BreachingLeviathan card) {

View file

@ -72,8 +72,7 @@ public class ContainmentPriest extends CardImpl {
// Flash // Flash
this.addAbility(FlashAbility.getInstance()); this.addAbility(FlashAbility.getInstance());
// If a nontoken creature would enter the battlefield and it wasn't cast, exile it instead. // If a nontoken creature would enter the battlefield and it wasn't cast, exile it instead.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ContainmentPriestReplacementEffect())); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ContainmentPriestReplacementEffect()), new CreatureCastWatcher());
this.addWatcher(new CreatureCastWatcher());
} }
public ContainmentPriest(final ContainmentPriest card) { public ContainmentPriest(final ContainmentPriest card) {

View file

@ -62,7 +62,7 @@ public class ImpactResonance extends CardImpl {
effect.setText("{this} deals X damage divided as you choose among any number of target creatures, where X is the greatest amount of damage dealt by a source to a permanent or player this turn"); effect.setText("{this} deals X damage divided as you choose among any number of target creatures, where X is the greatest amount of damage dealt by a source to a permanent or player this turn");
this.getSpellAbility().addEffect(effect); this.getSpellAbility().addEffect(effect);
this.getSpellAbility().addTarget(new TargetCreaturePermanentAmount(xValue)); this.getSpellAbility().addTarget(new TargetCreaturePermanentAmount(xValue));
this.addWatcher(new GreatestAmountOfDamageWatcher()); this.getSpellAbility().addWatcher(new GreatestAmountOfDamageWatcher());
} }
public ImpactResonance(final ImpactResonance card) { public ImpactResonance(final ImpactResonance card) {

View file

@ -61,7 +61,7 @@ public class SpoilsOfBlood extends CardImpl {
// Put an X/X black Horror creature token onto the battlefield, where X is the number of creatures that died this turn. // Put an X/X black Horror creature token onto the battlefield, where X is the number of creatures that died this turn.
this.getSpellAbility().addEffect(new SpoilsOfBloodEffect()); this.getSpellAbility().addEffect(new SpoilsOfBloodEffect());
this.addWatcher(new CreaturesDiedThisTurnWatcher()); this.getSpellAbility().addWatcher(new CreaturesDiedThisTurnWatcher());
} }
public SpoilsOfBlood(final SpoilsOfBlood card) { public SpoilsOfBlood(final SpoilsOfBlood card) {

View file

@ -81,9 +81,8 @@ public class DungeonGeists extends CardImpl {
ability.addEffect(new DungeonGeistsEffect()); ability.addEffect(new DungeonGeistsEffect());
Target target = new TargetCreaturePermanent(filter); Target target = new TargetCreaturePermanent(filter);
ability.addTarget(target); ability.addTarget(target);
this.addAbility(ability); this.addAbility(ability, new DungeonGeistsWatcher());
// watcher needed to send normal events to Dungeon Geists ReplacementEffect // watcher needed to send normal events to Dungeon Geists ReplacementEffect
this.addWatcher(new DungeonGeistsWatcher());
} }
public DungeonGeists(final DungeonGeists card) { public DungeonGeists(final DungeonGeists card) {

View file

@ -67,7 +67,7 @@ public class Flamebreak extends CardImpl {
// Flamebreak deals 3 damage to each creature without flying and each player. Creatures dealt damage this way can't be regenerated this turn. // Flamebreak deals 3 damage to each creature without flying and each player. Creatures dealt damage this way can't be regenerated this turn.
this.getSpellAbility().addEffect(new DamageEverythingEffect(new StaticValue(3), filter1)); this.getSpellAbility().addEffect(new DamageEverythingEffect(new StaticValue(3), filter1));
this.getSpellAbility().addEffect(new FlamebreakCantRegenerateEffect()); this.getSpellAbility().addEffect(new FlamebreakCantRegenerateEffect());
this.addWatcher(new DamagedByWatcher()); this.getSpellAbility().addWatcher(new DamagedByWatcher());
} }
public Flamebreak(final Flamebreak card) { public Flamebreak(final Flamebreak card) {

View file

@ -75,8 +75,7 @@ public class CryptChampion extends CardImpl {
this.addAbility(new EntersBattlefieldTriggeredAbility(new CryptChampionEffect())); this.addAbility(new EntersBattlefieldTriggeredAbility(new CryptChampionEffect()));
// When Crypt Champion enters the battlefield, sacrifice it unless {R} was spent to cast it. // When Crypt Champion enters the battlefield, sacrifice it unless {R} was spent to cast it.
this.addAbility(new EntersBattlefieldTriggeredAbility(new SacrificeSourceUnlessConditionEffect(new ManaWasSpentCondition(ColoredManaSymbol.R)), false)); this.addAbility(new EntersBattlefieldTriggeredAbility(new SacrificeSourceUnlessConditionEffect(new ManaWasSpentCondition(ColoredManaSymbol.R)), false), new ManaSpentToCastWatcher());
this.addWatcher(new ManaSpentToCastWatcher());
} }
public CryptChampion(final CryptChampion card) { public CryptChampion(final CryptChampion card) {

View file

@ -63,8 +63,7 @@ public class PatagiaViper extends CardImpl {
this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new PatagiaViperSnakeToken(), 2), false)); this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new PatagiaViperSnakeToken(), 2), false));
// When Patagia Viper enters the battlefield, sacrifice it unless {U} was spent to cast it. // When Patagia Viper enters the battlefield, sacrifice it unless {U} was spent to cast it.
this.addAbility(new EntersBattlefieldTriggeredAbility(new SacrificeSourceUnlessConditionEffect(new ManaWasSpentCondition(ColoredManaSymbol.U)), false)); this.addAbility(new EntersBattlefieldTriggeredAbility(new SacrificeSourceUnlessConditionEffect(new ManaWasSpentCondition(ColoredManaSymbol.U)), false), new ManaSpentToCastWatcher());
this.addWatcher(new ManaSpentToCastWatcher());
} }
public PatagiaViper(final PatagiaViper card) { public PatagiaViper(final PatagiaViper card) {

View file

@ -72,8 +72,7 @@ public class ReiverDemon extends CardImpl {
Ability ability = new EntersBattlefieldTriggeredAbility( Ability ability = new EntersBattlefieldTriggeredAbility(
new ConditionalOneShotEffect(new DestroyAllEffect(filter), new CastFromHandCondition(), new ConditionalOneShotEffect(new DestroyAllEffect(filter), new CastFromHandCondition(),
"if you cast it from your hand, destroy all nonartifact, nonblack creatures. They can't be regenerated")); "if you cast it from your hand, destroy all nonartifact, nonblack creatures. They can't be regenerated"));
this.addAbility(ability); this.addAbility(ability, new CastFromHandWatcher());
this.addWatcher(new CastFromHandWatcher());
} }
public ReiverDemon(final ReiverDemon card) { public ReiverDemon(final ReiverDemon card) {

View file

@ -43,14 +43,12 @@ import mage.abilities.effects.common.continious.GainAbilityTargetEffect;
import mage.abilities.effects.common.continious.GainControlTargetEffect; import mage.abilities.effects.common.continious.GainControlTargetEffect;
import mage.abilities.keyword.HasteAbility; import mage.abilities.keyword.HasteAbility;
import mage.cards.SplitCard; import mage.cards.SplitCard;
import mage.constants.TargetController;
import mage.filter.FilterPermanent; import mage.filter.FilterPermanent;
import mage.filter.common.FilterArtifactPermanent; import mage.filter.common.FilterControlledArtifactPermanent;
import mage.filter.common.FilterCreaturePermanent; import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.common.FilterEnchantmentPermanent; import mage.filter.common.FilterControlledEnchantmentPermanent;
import mage.filter.common.FilterLandPermanent; import mage.filter.common.FilterControlledLandPermanent;
import mage.filter.common.FilterPlaneswalkerPermanent; import mage.filter.common.FilterControlledPlaneswalkerPermanent;
import mage.filter.predicate.permanent.ControllerPredicate;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.players.Player; import mage.players.Player;
@ -70,13 +68,8 @@ public class CatchRelease extends SplitCard {
super(ownerId, 125, "Catch", "Release", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{1}{U}{R}", "{4}{R}{W}",true); super(ownerId, 125, "Catch", "Release", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{1}{U}{R}", "{4}{R}{W}",true);
this.expansionSetCode = "DGM"; this.expansionSetCode = "DGM";
this.color.setBlue(true);
this.color.setRed(true);
this.color.setWhite(true);
// Catch // Catch
// Gain control of target permanent until end of turn. Untap it. It gains haste until end of turn. // Gain control of target permanent until end of turn. Untap it. It gains haste until end of turn.
getLeftHalfCard().getColor().setRed(true);
getLeftHalfCard().getSpellAbility().addTarget(new TargetPermanent(new FilterPermanent())); getLeftHalfCard().getSpellAbility().addTarget(new TargetPermanent(new FilterPermanent()));
getLeftHalfCard().getSpellAbility().addEffect(new GainControlTargetEffect(Duration.EndOfTurn)); getLeftHalfCard().getSpellAbility().addEffect(new GainControlTargetEffect(Duration.EndOfTurn));
getLeftHalfCard().getSpellAbility().addEffect(new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn)); getLeftHalfCard().getSpellAbility().addEffect(new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn));
@ -84,7 +77,6 @@ public class CatchRelease extends SplitCard {
// Release // Release
// Each player sacrifices an artifact, a creature, an enchantment, a land, and a planeswalker. // Each player sacrifices an artifact, a creature, an enchantment, a land, and a planeswalker.
getRightHalfCard().getColor().setGreen(true);
getRightHalfCard().getSpellAbility().addEffect(new ReleaseSacrificeEffect()); getRightHalfCard().getSpellAbility().addEffect(new ReleaseSacrificeEffect());
} }
@ -101,20 +93,6 @@ public class CatchRelease extends SplitCard {
class ReleaseSacrificeEffect extends OneShotEffect { class ReleaseSacrificeEffect extends OneShotEffect {
private static final FilterArtifactPermanent filter1 = new FilterArtifactPermanent("artifact you control");
private static final FilterCreaturePermanent filter2 = new FilterCreaturePermanent("creature you control");
private static final FilterEnchantmentPermanent filter3 = new FilterEnchantmentPermanent("enchantment you control");
private static final FilterLandPermanent filter4 = new FilterLandPermanent("land you control");
private static final FilterPlaneswalkerPermanent filter5 = new FilterPlaneswalkerPermanent("planeswalker you control");
static {
filter1.add(new ControllerPredicate(TargetController.YOU));
filter2.add(new ControllerPredicate(TargetController.YOU));
filter3.add(new ControllerPredicate(TargetController.YOU));
filter4.add(new ControllerPredicate(TargetController.YOU));
filter5.add(new ControllerPredicate(TargetController.YOU));
}
public ReleaseSacrificeEffect() { public ReleaseSacrificeEffect() {
super(Outcome.DestroyPermanent); super(Outcome.DestroyPermanent);
staticText = "Each player sacrifices an artifact, a creature, an enchantment, a land, and a planeswalker"; staticText = "Each player sacrifices an artifact, a creature, an enchantment, a land, and a planeswalker";
@ -126,7 +104,7 @@ class ReleaseSacrificeEffect extends OneShotEffect {
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
List<UUID> chosen = new ArrayList<UUID>(); List<UUID> chosen = new ArrayList<>();
Player controller = game.getPlayer(source.getControllerId()); Player controller = game.getPlayer(source.getControllerId());
if (controller == null) { if (controller == null) {
return false; return false;
@ -134,18 +112,11 @@ class ReleaseSacrificeEffect extends OneShotEffect {
for (UUID playerId : controller.getInRange()) { for (UUID playerId : controller.getInRange()) {
Player player = game.getPlayer(playerId); Player player = game.getPlayer(playerId);
Target target1 = new TargetControlledPermanent(1, 1, filter1, false); Target target1 = new TargetControlledPermanent(1, 1, new FilterControlledArtifactPermanent(), true);
Target target2 = new TargetControlledPermanent(1, 1, filter2, false); Target target2 = new TargetControlledPermanent(1, 1, new FilterControlledCreaturePermanent(), true);
Target target3 = new TargetControlledPermanent(1, 1, filter3, false); Target target3 = new TargetControlledPermanent(1, 1, new FilterControlledEnchantmentPermanent(), true);
Target target4 = new TargetControlledPermanent(1, 1, filter4, false); Target target4 = new TargetControlledPermanent(1, 1, new FilterControlledLandPermanent(), true);
Target target5 = new TargetControlledPermanent(1, 1, filter5, false); Target target5 = new TargetControlledPermanent(1, 1, new FilterControlledPlaneswalkerPermanent(), true);
target1.setNotTarget(false);
target2.setNotTarget(false);
target3.setNotTarget(false);
target4.setNotTarget(false);
target5.setNotTarget(false);
if (target1.canChoose(player.getId(), game)) { if (target1.canChoose(player.getId(), game)) {
while (player.isInGame() && !target1.isChosen() && target1.canChoose(player.getId(), game)) { while (player.isInGame() && !target1.isChosen() && target1.canChoose(player.getId(), game)) {

View file

@ -65,8 +65,7 @@ public class NotionThief extends CardImpl {
// Flash // Flash
this.addAbility(FlashAbility.getInstance()); this.addAbility(FlashAbility.getInstance());
// If an opponent would draw a card except the first one he or she draws in each of his or her draw steps, instead that player skips that draw and you draw a card. // If an opponent would draw a card except the first one he or she draws in each of his or her draw steps, instead that player skips that draw and you draw a card.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new NotionThiefReplacementEffect())); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new NotionThiefReplacementEffect()), new CardsDrawnDuringDrawStepWatcher());
this.addWatcher(new CardsDrawnDuringDrawStepWatcher());
} }

View file

@ -54,7 +54,7 @@ public class RestoreThePeace extends CardImpl {
// Return each creature that dealt damage this turn to its owner's hand. // Return each creature that dealt damage this turn to its owner's hand.
this.getSpellAbility().addEffect(new RestoreThePeaceEffect()); this.getSpellAbility().addEffect(new RestoreThePeaceEffect());
this.addWatcher(new SourceDidDamageWatcher()); this.getSpellAbility().addWatcher(new SourceDidDamageWatcher());
} }

View file

@ -59,14 +59,12 @@ public class ScionOfVituGhazi extends CardImpl {
this.power = new MageInt(4); this.power = new MageInt(4);
this.toughness = new MageInt(4); this.toughness = new MageInt(4);
this.addWatcher(new CastFromHandWatcher());
// When Scion of Vitu-Ghazi enters the battlefield, if you cast it from your hand, put a 1/1 white Bird creature token with flying onto the battlefield, then populate. // When Scion of Vitu-Ghazi enters the battlefield, if you cast it from your hand, put a 1/1 white Bird creature token with flying onto the battlefield, then populate.
Ability ability = new EntersBattlefieldTriggeredAbility( Ability ability = new EntersBattlefieldTriggeredAbility(
new ConditionalOneShotEffect(new CreateTokenEffect(new BirdToken()), new CastFromHandCondition(), new ConditionalOneShotEffect(new CreateTokenEffect(new BirdToken()), new CastFromHandCondition(),
"if you cast it from your hand, put a 1/1 white Bird creature token with flying onto the battlefield,")); "if you cast it from your hand, put a 1/1 white Bird creature token with flying onto the battlefield,"));
ability.addEffect(new PopulateEffect("then")); ability.addEffect(new PopulateEffect("then"));
this.addAbility(ability); this.addAbility(ability, new CastFromHandWatcher());
} }
public ScionOfVituGhazi (final ScionOfVituGhazi card) { public ScionOfVituGhazi (final ScionOfVituGhazi card) {

View file

@ -70,7 +70,7 @@ public class BatwingBrume extends CardImpl {
new BatwingBrumeEffect(), new BatwingBrumeEffect(),
new ManaWasSpentCondition(ColoredManaSymbol.B), "Each player loses 1 life for each attacking creature he or she controls if {B} was spent to cast {this}")); new ManaWasSpentCondition(ColoredManaSymbol.B), "Each player loses 1 life for each attacking creature he or she controls if {B} was spent to cast {this}"));
this.addInfo("Info1", "<i>(Do both if {W}{B} was spent.)<i>"); this.addInfo("Info1", "<i>(Do both if {W}{B} was spent.)<i>");
this.addWatcher(new ManaSpentToCastWatcher()); this.getSpellAbility().addWatcher(new ManaSpentToCastWatcher());
} }

View file

@ -66,7 +66,7 @@ public class CankerousThirst extends CardImpl {
"If {G} was spent to cast {this}, you may have target creature get +3/+3 until end of turn")); "If {G} was spent to cast {this}, you may have target creature get +3/+3 until end of turn"));
this.getSpellAbility().addTarget(new TargetCreaturePermanent()); this.getSpellAbility().addTarget(new TargetCreaturePermanent());
this.addInfo("Info1", "<i>(Do both if {B}{G} was spent.)<i>"); this.addInfo("Info1", "<i>(Do both if {B}{G} was spent.)<i>");
this.addWatcher(new ManaSpentToCastWatcher()); this.getSpellAbility().addWatcher(new ManaSpentToCastWatcher());
} }
public CankerousThirst(final CankerousThirst card) { public CankerousThirst(final CankerousThirst card) {

View file

@ -70,8 +70,7 @@ public class DreamThief extends CardImpl {
this.addAbility(FlyingAbility.getInstance()); this.addAbility(FlyingAbility.getInstance());
// When Dream Thief enters the battlefield, draw a card if you've cast another blue spell this turn. // When Dream Thief enters the battlefield, draw a card if you've cast another blue spell this turn.
this.addAbility(new EntersBattlefieldTriggeredAbility(new ConditionalOneShotEffect(new DrawCardSourceControllerEffect(1), new CastBlueSpellThisTurnCondition(), rule))); this.addAbility(new EntersBattlefieldTriggeredAbility(new ConditionalOneShotEffect(new DrawCardSourceControllerEffect(1), new CastBlueSpellThisTurnCondition(), rule)), new DreamThiefWatcher(this.getId()));
this.addWatcher(new DreamThiefWatcher(this.getId()));
} }

View file

@ -79,8 +79,7 @@ public class GroundlingPouncer extends CardImpl {
Effect effect2 = new GainAbilitySourceEffect(FlyingAbility.getInstance(), Duration.EndOfTurn, false, true); Effect effect2 = new GainAbilitySourceEffect(FlyingAbility.getInstance(), Duration.EndOfTurn, false, true);
Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{G/U}"), condition, rule); Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{G/U}"), condition, rule);
ability.addEffect(effect2); ability.addEffect(effect2);
this.addAbility(ability); this.addAbility(ability, new ActivatedAbilityUsedThisTurnWatcher());
this.addWatcher(new ActivatedAbilityUsedThisTurnWatcher());
} }

View file

@ -71,8 +71,7 @@ public class HotheadedGiant extends CardImpl {
// Hotheaded Giant enters the battlefield with two -1/-1 counters on it unless you've cast another red spell this turn. // Hotheaded Giant enters the battlefield with two -1/-1 counters on it unless you've cast another red spell this turn.
Condition condition = new CastRedSpellThisTurnCondition(); Condition condition = new CastRedSpellThisTurnCondition();
this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.M1M1.createInstance(2)), new InvertCondition(condition), ""), "with two -1/-1 counters on it unless you've cast another red spell this turn")); this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.M1M1.createInstance(2)), new InvertCondition(condition), ""), "with two -1/-1 counters on it unless you've cast another red spell this turn"), new HotHeadedGiantWatcher(this.getId()));
this.addWatcher(new HotHeadedGiantWatcher(this.getId()));
} }

View file

@ -73,7 +73,7 @@ public class InvertTheSkies extends CardImpl {
new LockedInCondition(new ManaWasSpentCondition(ColoredManaSymbol.U)), new LockedInCondition(new ManaWasSpentCondition(ColoredManaSymbol.U)),
"and creatures you control gain flying until end of turn if {U} was spent to cast it")); "and creatures you control gain flying until end of turn if {U} was spent to cast it"));
this.addInfo("Info1", "<i>(Do both if {G}{U} was spent.)<i>"); this.addInfo("Info1", "<i>(Do both if {G}{U} was spent.)<i>");
this.addWatcher(new ManaSpentToCastWatcher()); this.getSpellAbility().addWatcher(new ManaSpentToCastWatcher());
} }
public InvertTheSkies(final InvertTheSkies card) { public InvertTheSkies(final InvertTheSkies card) {

View file

@ -73,7 +73,7 @@ public class Moonhold extends CardImpl {
new LockedInCondition(new ManaWasSpentCondition(ColoredManaSymbol.W)))); new LockedInCondition(new ManaWasSpentCondition(ColoredManaSymbol.W))));
this.getSpellAbility().addTarget(new TargetPlayer()); this.getSpellAbility().addTarget(new TargetPlayer());
this.addInfo("Info1", "<i>(Do both if {R}{W} was spent.)</i>"); this.addInfo("Info1", "<i>(Do both if {R}{W} was spent.)</i>");
this.addWatcher(new ManaSpentToCastWatcher()); this.getSpellAbility().addWatcher(new ManaSpentToCastWatcher());
} }
public Moonhold(final Moonhold card) { public Moonhold(final Moonhold card) {

View file

@ -78,7 +78,7 @@ public class SoulReap extends CardImpl {
this.getSpellAbility().addEffect(new DestroyTargetEffect()); this.getSpellAbility().addEffect(new DestroyTargetEffect());
this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter));
this.getSpellAbility().addEffect(new ConditionalOneShotEffect(new SoulReapEffect(), new CastBlackSpellThisTurnCondition(), rule)); this.getSpellAbility().addEffect(new ConditionalOneShotEffect(new SoulReapEffect(), new CastBlackSpellThisTurnCondition(), rule));
this.addWatcher(new SoulReapWatcher(this.getId())); this.getSpellAbility().addWatcher(new SoulReapWatcher(this.getId()));
} }

View file

@ -71,8 +71,7 @@ public class TalarasBattalion extends CardImpl {
this.addAbility(TrampleAbility.getInstance()); this.addAbility(TrampleAbility.getInstance());
// Cast Talara's Battalion only if you've cast another green spell this turn. // Cast Talara's Battalion only if you've cast another green spell this turn.
this.addAbility(new SimpleStaticAbility(Zone.ALL, new TalarasBattalionEffect())); this.addAbility(new SimpleStaticAbility(Zone.ALL, new TalarasBattalionEffect()), new TalarasBattalionWatcher(this.getId()));
this.addWatcher(new TalarasBattalionWatcher(this.getId()));
} }

View file

@ -72,7 +72,7 @@ public class UnnervingAssault extends CardImpl {
new BoostAllEffect(1, 0, Duration.EndOfTurn, filter2, false), new BoostAllEffect(1, 0, Duration.EndOfTurn, filter2, false),
new ManaWasSpentCondition(ColoredManaSymbol.R), " and creatures you control get +1/0 until end of turn if {R} was spent to cast it")); new ManaWasSpentCondition(ColoredManaSymbol.R), " and creatures you control get +1/0 until end of turn if {R} was spent to cast it"));
this.addInfo("Info1", "<i>(Do both if {U}{R} was spent.)</i>"); this.addInfo("Info1", "<i>(Do both if {U}{R} was spent.)</i>");
this.addWatcher(new ManaSpentToCastWatcher()); this.getSpellAbility().addWatcher(new ManaSpentToCastWatcher());
} }

View file

@ -62,7 +62,7 @@ public class WavesOfAggression extends CardImpl {
this.color.setWhite(true); this.color.setWhite(true);
// Untap all creatures that attacked this turn. After this main phase, there is an additional combat phase followed by an additional main phase. // Untap all creatures that attacked this turn. After this main phase, there is an additional combat phase followed by an additional main phase.
this.addWatcher(new AttackedThisTurnWatcher()); this.getSpellAbility().addWatcher(new AttackedThisTurnWatcher());
this.getSpellAbility().addEffect(new WavesOfAggressionUntapEffect()); this.getSpellAbility().addEffect(new WavesOfAggressionUntapEffect());
this.getSpellAbility().addEffect(new WavesOfAggressionAddPhasesEffect()); this.getSpellAbility().addEffect(new WavesOfAggressionAddPhasesEffect());
// Retrace // Retrace

View file

@ -37,12 +37,10 @@ import mage.cards.CardImpl;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.constants.Rarity; import mage.constants.Rarity;
import mage.constants.TargetController; import mage.filter.common.FilterControlledArtifactPermanent;
import mage.filter.common.FilterArtifactPermanent; import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.common.FilterCreaturePermanent; import mage.filter.common.FilterControlledEnchantmentPermanent;
import mage.filter.common.FilterEnchantmentPermanent; import mage.filter.common.FilterControlledLandPermanent;
import mage.filter.common.FilterLandPermanent;
import mage.filter.predicate.permanent.ControllerPredicate;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.players.Player; import mage.players.Player;
@ -59,8 +57,6 @@ public class Cataclysm extends CardImpl {
super(ownerId, 3, "Cataclysm", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{2}{W}{W}"); super(ownerId, 3, "Cataclysm", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{2}{W}{W}");
this.expansionSetCode = "EXO"; this.expansionSetCode = "EXO";
this.color.setWhite(true);
// Each player chooses from the permanents he or she controls an artifact, a creature, an enchantment, and a land, then sacrifices the rest. // Each player chooses from the permanents he or she controls an artifact, a creature, an enchantment, and a land, then sacrifices the rest.
this.getSpellAbility().addEffect(new CataclysmEffect()); this.getSpellAbility().addEffect(new CataclysmEffect());
} }
@ -77,18 +73,6 @@ public class Cataclysm extends CardImpl {
class CataclysmEffect extends OneShotEffect { class CataclysmEffect extends OneShotEffect {
private static final FilterArtifactPermanent filter1 = new FilterArtifactPermanent("artifact you control");
private static final FilterCreaturePermanent filter2 = new FilterCreaturePermanent("creature you control");
private static final FilterEnchantmentPermanent filter3 = new FilterEnchantmentPermanent("enchantment you control");
private static final FilterLandPermanent filter4 = new FilterLandPermanent("land you control");
static {
filter1.add(new ControllerPredicate(TargetController.YOU));
filter2.add(new ControllerPredicate(TargetController.YOU));
filter3.add(new ControllerPredicate(TargetController.YOU));
filter4.add(new ControllerPredicate(TargetController.YOU));
}
public CataclysmEffect() { public CataclysmEffect() {
super(Outcome.DestroyPermanent); super(Outcome.DestroyPermanent);
staticText = "Each player chooses from among the permanents he or she controls an artifact, a creature, an enchantment, and a land, then sacrifices the rest"; staticText = "Each player chooses from among the permanents he or she controls an artifact, a creature, an enchantment, and a land, then sacrifices the rest";
@ -105,20 +89,14 @@ class CataclysmEffect extends OneShotEffect {
for (UUID playerId : game.getPlayerList()) { for (UUID playerId : game.getPlayerList()) {
Player player = game.getPlayer(playerId); Player player = game.getPlayer(playerId);
Target target1 = new TargetControlledPermanent(1, 1, filter1, false); Target target1 = new TargetControlledPermanent(1, 1, new FilterControlledArtifactPermanent(), true);
Target target2 = new TargetControlledPermanent(1, 1, filter2, false); Target target2 = new TargetControlledPermanent(1, 1, new FilterControlledCreaturePermanent(), true);
Target target3 = new TargetControlledPermanent(1, 1, filter3, false); Target target3 = new TargetControlledPermanent(1, 1, new FilterControlledEnchantmentPermanent(), true);
Target target4 = new TargetControlledPermanent(1, 1, filter4, false); Target target4 = new TargetControlledPermanent(1, 1, new FilterControlledLandPermanent(), true);
target1.setNotTarget(true);
target2.setNotTarget(true);
target3.setNotTarget(true);
target4.setNotTarget(true);
if (target1.canChoose(player.getId(), game)) { if (target1.canChoose(player.getId(), game)) {
while (player.isInGame() && !target1.isChosen() && target1.canChoose(player.getId(), game)) { while (player.isInGame() && !target1.isChosen() && target1.canChoose(player.getId(), game)) {
player.choose(Outcome.Benefit, target1, source.getSourceId(), game); player.chooseTarget(Outcome.Benefit, target1, source, game);
} }
Permanent artifact = game.getPermanent(target1.getFirstTarget()); Permanent artifact = game.getPermanent(target1.getFirstTarget());
if (artifact != null) { if (artifact != null) {
@ -129,7 +107,7 @@ class CataclysmEffect extends OneShotEffect {
if (target2.canChoose(player.getId(), game)) { if (target2.canChoose(player.getId(), game)) {
while (player.isInGame() && !target2.isChosen() && target2.canChoose(player.getId(), game)) { while (player.isInGame() && !target2.isChosen() && target2.canChoose(player.getId(), game)) {
player.choose(Outcome.Benefit, target2, source.getSourceId(), game); player.chooseTarget(Outcome.Benefit, target2, source, game);
} }
Permanent creature = game.getPermanent(target2.getFirstTarget()); Permanent creature = game.getPermanent(target2.getFirstTarget());
if (creature != null) { if (creature != null) {
@ -140,7 +118,7 @@ class CataclysmEffect extends OneShotEffect {
if (target3.canChoose(player.getId(), game)) { if (target3.canChoose(player.getId(), game)) {
while (player.isInGame() && !target3.isChosen() && target3.canChoose(player.getId(), game)) { while (player.isInGame() && !target3.isChosen() && target3.canChoose(player.getId(), game)) {
player.choose(Outcome.Benefit, target3, source.getSourceId(), game); player.chooseTarget(Outcome.Benefit, target3, source, game);
} }
Permanent enchantment = game.getPermanent(target3.getFirstTarget()); Permanent enchantment = game.getPermanent(target3.getFirstTarget());
if (enchantment != null) { if (enchantment != null) {
@ -151,7 +129,7 @@ class CataclysmEffect extends OneShotEffect {
if (target4.canChoose(player.getId(), game)) { if (target4.canChoose(player.getId(), game)) {
while (player.isInGame() && !target4.isChosen() && target4.canChoose(player.getId(), game)) { while (player.isInGame() && !target4.isChosen() && target4.canChoose(player.getId(), game)) {
player.choose(Outcome.Benefit, target4, source.getSourceId(), game); player.chooseTarget(Outcome.Benefit, target4, source, game);
} }
Permanent land = game.getPermanent(target4.getFirstTarget()); Permanent land = game.getPermanent(target4.getFirstTarget());
if (land != null) { if (land != null) {

View file

@ -116,7 +116,7 @@ class GhastlyConscriptionEffect extends OneShotEffect {
} }
MageObjectReference objectReference= new MageObjectReference(card.getId(), card.getZoneChangeCounter() +1, game); MageObjectReference objectReference= new MageObjectReference(card.getId(), card.getZoneChangeCounter() +1, game);
game.addEffect(new BecomesFaceDownCreatureEffect(manaCosts, objectReference, Duration.Custom, FaceDownType.MANIFESTED), newSource); game.addEffect(new BecomesFaceDownCreatureEffect(manaCosts, objectReference, Duration.Custom, FaceDownType.MANIFESTED), newSource);
if (card.moveToZone(Zone.BATTLEFIELD, newSource.getSourceId(), game, false)) { if (controller.putOntoBattlefieldWithInfo(card, game, Zone.EXILED, source.getSourceId())) {
game.informPlayers(new StringBuilder(controller.getName()) game.informPlayers(new StringBuilder(controller.getName())
.append(" puts facedown card from exile onto the battlefield").toString()); .append(" puts facedown card from exile onto the battlefield").toString());
} }

Some files were not shown because too many files have changed in this diff Show more