Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Derek Monturo 2017-04-17 10:35:13 -04:00
commit 217b4919f3
202 changed files with 2718 additions and 1929 deletions

View file

@ -6,7 +6,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-root</artifactId>
<version>1.4.22</version>
<version>1.4.23</version>
</parent>
<groupId>org.mage</groupId>

View file

@ -27,6 +27,21 @@
*/
package mage.client;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.prefs.Preferences;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import mage.cards.decks.Deck;
import mage.cards.repository.CardCriteria;
import mage.cards.repository.CardInfo;
@ -77,22 +92,6 @@ import org.mage.plugins.card.images.DownloadPictures;
import org.mage.plugins.card.info.CardInfoPaneImpl;
import org.mage.plugins.card.utils.impl.ImageManagerImpl;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.prefs.Preferences;
/**
* @author BetaSteward_at_googlemail.com
*/
@ -1056,7 +1055,7 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
// use already open editor
Component[] windows = desktopPane.getComponentsInLayer(JLayeredPane.DEFAULT_LAYER);
for (Component window : windows) {
if (window instanceof DeckEditorPane && ((MagePane)window).getTitle().equals(name)) {
if (window instanceof DeckEditorPane && ((MagePane) window).getTitle().equals(name)) {
setActive((MagePane) window);
return;
}

View file

@ -45,6 +45,7 @@ import java.io.InputStreamReader;
import java.io.Writer;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.UnknownHostException;
@ -391,7 +392,12 @@ public class ConnectDialog extends MageDialog {
connection.setUsername(this.txtUserName.getText().trim());
connection.setPassword(this.txtPassword.getText().trim());
connection.setForceDBComparison(this.chkForceUpdateDB.isSelected());
connection.setUserIdStr(System.getProperty("user.name") + ':' + MagePreferences.getUserNames());
String allMAC = "";
try {
allMAC = connection.getMAC();
} catch (SocketException ex) {
}
connection.setUserIdStr(System.getProperty("user.name") + ":" + System.getProperty("os.name") + ":" + MagePreferences.getUserNames() + ":" + allMAC);
MageFrame.getPreferences().put(KEY_CONNECT_FLAG, ((CountryItemEditor) cbFlag.getEditor()).getImageItem());
PreferencesDialog.setProxyInformation(connection);

View file

@ -86,13 +86,14 @@ public class MythicspoilerComSource implements CardImageSource {
cardNameAliases.put("THS-soldierofpantheon", "soldierofthepantheon");
cardNameAliases.put("THS-vulpinegolaith", "vulpinegoliath");
cardNameAliases.put("ORI-kothopedhoarderofsouls", "kothophedsoulhoarder");
cardNameAliases.put("BFZ-unisonstrike", "tandemtactics");
cardNameAliases.put("BFZ-eldrazidevastator", "eldrazidevastator");
cardNameAliases.put("BFZ-kozliekschanneler", "kozilekschanneler");
cardNameAliases.put("OGW-wastes", "wastes1");
cardNameAliases.put("OGW-wastes2", "wastes2");
cardNameAliases.put("AER-locketofmyths", "lifecraftersbestiary");
cardNameAliases.put("AER-aegisautomation", "aegisautomaton");
cardNameAliases.put("AKH-illusorywrappins", "illusorywrappings");
cardNameAliases.put("AKH-reducerumble", "reducerubble");
cardNameAliases.put("AKH-forsakethewordly", "forsaketheworldly");
cardNameAliases.put("AKH-kefnatsmonument", "kefnetsmonument");
cardNameAliasesStart = new HashMap<>();
HashSet<String> names = new HashSet<>();
@ -182,14 +183,9 @@ public class MythicspoilerComSource implements CardImageSource {
if (cardNameAliases.containsKey(cardSet + '-' + cardName)) {
cardName = cardNameAliases.get(cardSet + '-' + cardName);
} else if (cardName.endsWith("1") || cardName.endsWith("2") || cardName.endsWith("3") || cardName.endsWith("4") || cardName.endsWith("5")) {
if (!cardName.startsWith("forest")
&& !cardName.startsWith("swamp")
&& !cardName.startsWith("mountain")
&& !cardName.startsWith("island")
&& !cardName.startsWith("plains")) {
cardName = cardName.substring(0, cardName.length() - 1);
}
cardName = cardName.substring(0, cardName.length() - 1);
} else if (cardName.endsWith("promo")) {
cardName = cardName.substring(0, cardName.length() - 5);
}
pageLinks.put(cardName, baseUrl + cardLink);
}
@ -213,7 +209,8 @@ public class MythicspoilerComSource implements CardImageSource {
.replaceAll(" ", "")
.replaceAll("-", "")
.replaceAll("'", "")
.replaceAll(",", "");
.replaceAll(",", "")
.replaceAll("/", "");
String link = setLinks.get(searchName);
return link;
}

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-root</artifactId>
<version>1.4.22</version>
<version>1.4.23</version>
</parent>
<artifactId>mage-common</artifactId>

View file

@ -56,6 +56,7 @@ public class Connection {
private int clientCardDatabaseVersion;
private boolean forceDBComparison;
private String userIdStr;
private int socketWriteTimeout;
private UserData userData;
@ -76,6 +77,7 @@ public class Connection {
public Connection(String parameter) {
this.parameter = parameter;
socketWriteTimeout = 10000;
}
@Override
@ -258,6 +260,24 @@ public class Connection {
return null;
}
public static String getMAC() throws SocketException {
StringBuilder allMACs = new StringBuilder();
for (Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces(); interfaces.hasMoreElements();) {
NetworkInterface iface = interfaces.nextElement();
byte[] mac = iface.getHardwareAddress();
if (mac != null) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < mac.length; i++) {
sb.append(String.format("%02X%s", mac[i], (i < mac.length - 1) ? "-" : ""));
}
sb.append(';');
allMACs.append(sb.toString());
}
}
return allMACs.toString();
}
public void setUserData(UserData userData) {
this.userData = userData;
}
@ -273,4 +293,8 @@ public class Connection {
public void setForceDBComparison(boolean forceDBComparison) {
this.forceDBComparison = forceDBComparison;
}
public int getSocketWriteTimeout() {
return socketWriteTimeout;
}
}

View file

@ -27,6 +27,12 @@
*/
package mage.remote;
import java.io.IOException;
import java.lang.reflect.UndeclaredThrowableException;
import java.net.*;
import java.util.*;
import java.util.concurrent.TimeUnit;
import javax.swing.*;
import mage.MageException;
import mage.cards.decks.DeckCardLists;
import mage.cards.decks.InvalidDeckException;
@ -56,13 +62,6 @@ import org.jboss.remoting.transport.bisocket.Bisocket;
import org.jboss.remoting.transport.socket.SocketWrapper;
import org.jboss.remoting.transporter.TransporterClient;
import javax.swing.*;
import java.io.IOException;
import java.lang.reflect.UndeclaredThrowableException;
import java.net.*;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
* @author BetaSteward_at_googlemail.com
*/
@ -220,34 +219,35 @@ public class SessionImpl implements Session {
public synchronized boolean connect(final Connection connection) {
return establishJBossRemotingConnection(connection)
&& handleRemotingTaskExceptions(new RemotingTask() {
@Override
public boolean run() throws Throwable {
logger.info("Trying to log-in as " + getUserName() + " to XMAGE server at " + connection.getHost() + ':' + connection.getPort());
boolean registerResult;
if (connection.getAdminPassword() == null) {
// for backward compatibility. don't remove twice call - first one does nothing but for version checking
registerResult = server.connectUser(connection.getUsername(), connection.getPassword(), sessionId, client.getVersion(), connection.getUserIdStr());
if (registerResult) {
server.setUserData(connection.getUsername(), sessionId, connection.getUserData(), client.getVersion().toString(), connection.getUserIdStr());
@Override
public boolean run() throws Throwable {
logger.info("Trying to log-in as " + getUserName() + " to XMAGE server at " + connection.getHost() + ':' + connection.getPort());
boolean registerResult;
if (connection.getAdminPassword() == null) {
// for backward compatibility. don't remove twice call - first one does nothing but for version checking
registerResult = server.connectUser(connection.getUsername(), connection.getPassword(), sessionId, client.getVersion(), connection.getUserIdStr());
if (registerResult) {
server.setUserData(connection.getUsername(), sessionId, connection.getUserData(), client.getVersion().toString(), connection.getUserIdStr());
}
} else {
registerResult = server.connectAdmin(connection.getAdminPassword(), sessionId, client.getVersion());
}
if (registerResult) {
serverState = server.getServerState();
if (!connection.getUsername().equals("Admin")) {
updateDatabase(connection.isForceDBComparison(), serverState);
}
logger.info("Logged-in as " + getUserName() + " to MAGE server at " + connection.getHost() + ':' + connection.getPort());
client.connected(getUserName() + '@' + connection.getHost() + ':' + connection.getPort() + ' ');
return true;
}
disconnect(false);
return false;
}
} else {
registerResult = server.connectAdmin(connection.getAdminPassword(), sessionId, client.getVersion());
}
if (registerResult) {
serverState = server.getServerState();
if (!connection.getUsername().equals("Admin")) {
updateDatabase(connection.isForceDBComparison(), serverState);
}
logger.info("Logged-in as " + getUserName() + " to MAGE server at " + connection.getHost() + ':' + connection.getPort());
client.connected(getUserName() + '@' + connection.getHost() + ':' + connection.getPort() + ' ');
return true;
}
disconnect(false);
return false;
}
});
});
}
@Override
public Optional<String> getServerHostname() {
return isConnected() ? Optional.of(connection.getHost()) : Optional.<String>empty();
}
@ -305,14 +305,14 @@ public class SessionImpl implements Session {
to a value greater than 1, an invocation interrupted by a write timeout can be retried.
Note. The write timeout facility applies to writing of both invocations and responses. It applies to push callbacks as well.
*/
metadata.put(SocketWrapper.WRITE_TIMEOUT, "2000");
metadata.put(SocketWrapper.WRITE_TIMEOUT, String.valueOf(connection.getSocketWriteTimeout()));
metadata.put("generalizeSocketException", "true");
server = (MageServer) TransporterClient.createTransporterClient(clientLocator.getLocatorURI(), MageServer.class, metadata);
// http://docs.jboss.org/jbossremoting/docs/guide/2.5/html_single/#d0e1057
Map<String, String> clientMetadata = new HashMap<>();
clientMetadata.put(SocketWrapper.WRITE_TIMEOUT, "2000");
clientMetadata.put(SocketWrapper.WRITE_TIMEOUT, String.valueOf(connection.getSocketWriteTimeout()));
/* generalizeSocketException
* If set to false, a failed invocation will be retried in the case of
* SocketExceptions. If set to true, a failed invocation will be retried in the case of
@ -473,7 +473,7 @@ public class SessionImpl implements Session {
/**
* @param askForReconnect - true = connection was lost because of error and
* ask the user if he want to try to reconnect
* ask the user if he want to try to reconnect
*/
@Override
public synchronized void disconnect(boolean askForReconnect) {
@ -967,7 +967,6 @@ public class SessionImpl implements Session {
return false;
}
@Override
public boolean joinGame(UUID gameId) {
try {

View file

@ -40,7 +40,7 @@ public class MageVersion implements Serializable, Comparable<MageVersion> {
*/
public final static int MAGE_VERSION_MAJOR = 1;
public final static int MAGE_VERSION_MINOR = 4;
public final static int MAGE_VERSION_PATCH = 22;
public final static int MAGE_VERSION_PATCH = 23;
public final static String MAGE_VERSION_MINOR_PATCH = "V0";
public final static String MAGE_VERSION_INFO = "";

View file

@ -27,6 +27,7 @@
*/
package mage.view;
import java.util.*;
import mage.MageObject;
import mage.ObjectColor;
import mage.abilities.Abilities;
@ -50,8 +51,6 @@ import mage.game.stack.StackAbility;
import mage.target.Target;
import mage.target.Targets;
import java.util.*;
/**
* @author BetaSteward_at_googlemail.com
*/
@ -219,8 +218,8 @@ public class CardView extends SimpleCardView {
* @param card
* @param game
* @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
* for morph / face down cards to know which player may see information for
* the card
*/
public CardView(Card card, Game game, boolean controlled) {
this(card, game, controlled, false, false);
@ -246,12 +245,12 @@ public class CardView extends SimpleCardView {
/**
* @param card
* @param game
* @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
* @param showFaceDownCard if true and the card is not on the battlefield,
* also a face down card is shown in the view, face down cards will be shown
* @param storeZone if true the card zone will be set in the zone attribute.
* also a face down card is shown in the view, face down cards will be shown
* @param storeZone if true the card zone will be set in the zone attribute.
*/
public CardView(Card card, Game game, boolean controlled, boolean showFaceDownCard, boolean storeZone) {
super(card.getId(), card.getExpansionSetCode(), card.getCardNumber(), card.getUsesVariousArt(), card.getTokenSetCode(), game != null, card.getTokenDescriptor());
@ -303,13 +302,17 @@ public class CardView extends SimpleCardView {
SplitCard splitCard = null;
if (card.isSplitCard()) {
splitCard = (SplitCard) card;
rotate = true;
rotate = (((SplitCard) card).getSpellAbility().getSpellAbilityType()) != SpellAbilityType.SPLIT_AFTERMATH;
} else if (card instanceof Spell) {
switch (((Spell) card).getSpellAbility().getSpellAbilityType()) {
case SPLIT_FUSED:
splitCard = (SplitCard) ((Spell) card).getCard();
rotate = true;
break;
case SPLIT_AFTERMATH:
splitCard = (SplitCard) ((Spell) card).getCard();
rotate = false;
break;
case SPLIT_LEFT:
case SPLIT_RIGHT:
rotate = true;
@ -430,23 +433,19 @@ public class CardView extends SimpleCardView {
// Needs a special art rect
if (ty == SpellAbilityType.SPLIT_FUSED) {
artRect = ArtRect.SPLIT_FUSED;
} else {
if (spell.getCard() != null) {
SplitCard wholeCard = ((SplitCardHalf) spell.getCard()).getParentCard();
Abilities<Ability> aftermathHalfAbilities = wholeCard.getRightHalfCard().getAbilities();
if (aftermathHalfAbilities.stream().anyMatch(ability -> ability instanceof AftermathAbility)) {
if (ty == SpellAbilityType.SPLIT_RIGHT) {
artRect = ArtRect.AFTERMATH_BOTTOM;
} else {
artRect = ArtRect.AFTERMATH_TOP;
}
} else if (spell.getCard() != null) {
SplitCard wholeCard = ((SplitCardHalf) spell.getCard()).getParentCard();
Abilities<Ability> aftermathHalfAbilities = wholeCard.getRightHalfCard().getAbilities();
if (aftermathHalfAbilities.stream().anyMatch(ability -> ability instanceof AftermathAbility)) {
if (ty == SpellAbilityType.SPLIT_RIGHT) {
artRect = ArtRect.AFTERMATH_BOTTOM;
} else {
if (ty == SpellAbilityType.SPLIT_RIGHT) {
artRect = ArtRect.SPLIT_RIGHT;
} else {
artRect = ArtRect.SPLIT_LEFT;
}
artRect = ArtRect.AFTERMATH_TOP;
}
} else if (ty == SpellAbilityType.SPLIT_RIGHT) {
artRect = ArtRect.SPLIT_RIGHT;
} else {
artRect = ArtRect.SPLIT_LEFT;
}
}
}
@ -964,13 +963,21 @@ public class CardView extends SimpleCardView {
}
public String getColorText() {
if (getColor().getColorCount() == 0) return "Colorless";
else if (getColor().getColorCount() > 1) return "Gold";
else if (getColor().isBlack()) return "Black";
else if (getColor().isBlue()) return "Blue";
else if (getColor().isWhite()) return "White";
else if (getColor().isGreen()) return "Green";
else if (getColor().isRed()) return "Red";
if (getColor().getColorCount() == 0) {
return "Colorless";
} else if (getColor().getColorCount() > 1) {
return "Gold";
} else if (getColor().isBlack()) {
return "Black";
} else if (getColor().isBlue()) {
return "Blue";
} else if (getColor().isWhite()) {
return "White";
} else if (getColor().isGreen()) {
return "Green";
} else if (getColor().isRed()) {
return "Red";
}
return "";
}

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-plugins</artifactId>
<version>1.4.22</version>
<version>1.4.23</version>
</parent>
<artifactId>mage-counter-plugin</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-root</artifactId>
<version>1.4.22</version>
<version>1.4.23</version>
</parent>
<artifactId>mage-plugins</artifactId>

View file

@ -6,7 +6,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-root</artifactId>
<version>1.4.22</version>
<version>1.4.23</version>
</parent>
<groupId>org.mage</groupId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.22</version>
<version>1.4.23</version>
</parent>
<artifactId>mage-deck-constructed</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.22</version>
<version>1.4.23</version>
</parent>
<artifactId>mage-deck-limited</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.22</version>
<version>1.4.23</version>
</parent>
<artifactId>mage-game-canadianhighlanderduel</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.22</version>
<version>1.4.23</version>
</parent>
<artifactId>mage-game-commanderduel</artifactId>

View file

@ -6,7 +6,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.22</version>
<version>1.4.23</version>
</parent>
<artifactId>mage-game-commanderfreeforall</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.22</version>
<version>1.4.23</version>
</parent>
<artifactId>mage-game-freeforall</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.22</version>
<version>1.4.23</version>
</parent>
<artifactId>mage-game-momirduel</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.22</version>
<version>1.4.23</version>
</parent>
<artifactId>mage-game-tinyleadersduel</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.22</version>
<version>1.4.23</version>
</parent>
<artifactId>mage-game-twoplayerduel</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.22</version>
<version>1.4.23</version>
</parent>
<artifactId>mage-player-ai-draftbot</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.22</version>
<version>1.4.23</version>
</parent>
<artifactId>mage-player-ai-ma</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.22</version>
<version>1.4.23</version>
</parent>
<artifactId>mage-player-ai</artifactId>

View file

@ -27,6 +27,10 @@
*/
package mage.player.ai;
import java.io.IOException;
import java.io.Serializable;
import java.util.*;
import java.util.Map.Entry;
import mage.MageObject;
import mage.Mana;
import mage.abilities.*;
@ -77,11 +81,6 @@ import mage.util.TournamentUtil;
import mage.util.TreeNode;
import org.apache.log4j.Logger;
import java.io.IOException;
import java.io.Serializable;
import java.util.*;
import java.util.Map.Entry;
/**
*
* suitable for two player games and some multiplayer games
@ -1480,6 +1479,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
switch (ability.getSpellAbilityType()) {
case SPLIT:
case SPLIT_FUSED:
case SPLIT_AFTERMATH:
MageObject object = game.getObject(ability.getSourceId());
if (object != null) {
LinkedHashMap<UUID, ActivatedAbility> useableAbilities = getSpellAbilities(object, game.getState().getZone(object.getId()), game);

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.22</version>
<version>1.4.23</version>
</parent>
<artifactId>mage-player-ai-mcts</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.22</version>
<version>1.4.23</version>
</parent>
<artifactId>mage-player-aiminimax</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.22</version>
<version>1.4.23</version>
</parent>
<artifactId>mage-player-human</artifactId>

View file

@ -27,6 +27,8 @@
*/
package mage.player.human;
import java.io.Serializable;
import java.util.*;
import mage.MageObject;
import mage.abilities.*;
import mage.abilities.costs.VariableCost;
@ -42,6 +44,8 @@ import mage.cards.decks.Deck;
import mage.choices.Choice;
import mage.choices.ChoiceImpl;
import mage.constants.*;
import static mage.constants.PlayerAction.REQUEST_AUTO_ANSWER_RESET_ALL;
import static mage.constants.PlayerAction.TRIGGER_AUTO_ORDER_RESET_ALL;
import mage.filter.common.FilterAttackingCreature;
import mage.filter.common.FilterBlockingCreature;
import mage.filter.common.FilterCreatureForCombat;
@ -70,12 +74,6 @@ import mage.util.ManaUtil;
import mage.util.MessageToClient;
import org.apache.log4j.Logger;
import java.io.Serializable;
import java.util.*;
import static mage.constants.PlayerAction.REQUEST_AUTO_ANSWER_RESET_ALL;
import static mage.constants.PlayerAction.TRIGGER_AUTO_ORDER_RESET_ALL;
/**
*
* @author BetaSteward_at_googlemail.com
@ -300,7 +298,7 @@ public class HumanPlayer extends PlayerImpl {
public boolean choose(Outcome outcome, Target target, UUID sourceId, Game game, Map<String, Serializable> options) {
updateGameStatePriority("choose(5)", game);
UUID abilityControllerId = playerId;
if (target.getTargetController() != null
if (target.getTargetController() != null
&& target.getAbilityController() != null) {
abilityControllerId = target.getAbilityController();
}
@ -309,7 +307,7 @@ public class HumanPlayer extends PlayerImpl {
}
while (!abort) {
Set<UUID> targetIds = target.possibleTargets(sourceId, abilityControllerId, game);
if (targetIds == null
if (targetIds == null
|| targetIds.isEmpty()) {
return target.getTargets().size() >= target.getNumberOfTargets();
}
@ -381,7 +379,7 @@ public class HumanPlayer extends PlayerImpl {
while (!abort) {
Set<UUID> possibleTargets = target.possibleTargets(source == null ? null : source.getSourceId(), abilityControllerId, game);
boolean required = target.isRequired(source != null ? source.getSourceId() : null, game);
if (possibleTargets.isEmpty()
if (possibleTargets.isEmpty()
|| target.getTargets().size() >= target.getNumberOfTargets()) {
required = false;
}
@ -417,7 +415,7 @@ public class HumanPlayer extends PlayerImpl {
if (options == null) {
options = new HashMap<>();
}
if (target.getTargets().size() >= target.getNumberOfTargets()
if (target.getTargets().size() >= target.getNumberOfTargets()
&& !options.containsKey("UI.right.btn.text")) {
options.put("UI.right.btn.text", "Done");
}
@ -571,13 +569,13 @@ public class HumanPlayer extends PlayerImpl {
}
}
if (getJustActivatedType() != null && !holdingPriority) {
if (controllingPlayer.getUserData().isPassPriorityCast()
if (controllingPlayer.getUserData().isPassPriorityCast()
&& getJustActivatedType() == AbilityType.SPELL) {
setJustActivatedType(null);
pass(game);
return false;
}
if (controllingPlayer.getUserData().isPassPriorityActivation()
if (controllingPlayer.getUserData().isPassPriorityActivation()
&& getJustActivatedType() == AbilityType.ACTIVATED) {
setJustActivatedType(null);
pass(game);
@ -585,7 +583,7 @@ public class HumanPlayer extends PlayerImpl {
}
}
if (isGameUnderControl()) { // Use the skip actions only if the player itself controls its turn
if (passedAllTurns
if (passedAllTurns
|| passedTurnSkipStack) {
if (passWithManaPoolCheck(game)) {
return false;
@ -609,18 +607,18 @@ public class HumanPlayer extends PlayerImpl {
if (game.getStack().isEmpty()) {
passedUntilStackResolved = false;
boolean dontCheckPassStep = false;
if (passedTurn
if (passedTurn
|| passedTurnSkipStack) {
if (passWithManaPoolCheck(game)) {
return false;
}
}
if (passedUntilNextMain) {
if (game.getTurn().getStepType() == PhaseStep.POSTCOMBAT_MAIN
if (game.getTurn().getStepType() == PhaseStep.POSTCOMBAT_MAIN
|| game.getTurn().getStepType() == PhaseStep.PRECOMBAT_MAIN) {
// it's a main phase
if (!skippedAtLeastOnce
|| (!playerId.equals(game.getActivePlayerId())
if (!skippedAtLeastOnce
|| (!playerId.equals(game.getActivePlayerId())
&& !this.getUserData().getUserSkipPrioritySteps().isStopOnAllMainPhases())) {
skippedAtLeastOnce = true;
if (passWithManaPoolCheck(game)) {
@ -640,8 +638,8 @@ public class HumanPlayer extends PlayerImpl {
if (passedUntilEndOfTurn) {
if (game.getTurn().getStepType() == PhaseStep.END_TURN) {
// It's end of turn phase
if (!skippedAtLeastOnce
|| (playerId.equals(game.getActivePlayerId())
if (!skippedAtLeastOnce
|| (playerId.equals(game.getActivePlayerId())
&& !this.getUserData().getUserSkipPrioritySteps().isStopOnAllEndPhases())) {
skippedAtLeastOnce = true;
if (passWithManaPoolCheck(game)) {
@ -658,7 +656,7 @@ public class HumanPlayer extends PlayerImpl {
}
}
}
if (!dontCheckPassStep
if (!dontCheckPassStep
&& checkPassStep(game, controllingPlayer)) {
if (passWithManaPoolCheck(game)) {
return false;
@ -683,7 +681,7 @@ public class HumanPlayer extends PlayerImpl {
if (game.executingRollback()) {
return true;
}
if (response.getBoolean() != null
if (response.getBoolean() != null
|| response.getInteger() != null) {
if (passWithManaPoolCheck(game)) {
return false;
@ -694,7 +692,7 @@ public class HumanPlayer extends PlayerImpl {
break;
}
if (response.getString() != null
if (response.getString() != null
&& response.getString().equals("special")) {
specialAction(game);
} else if (response.getUUID() != null) {
@ -716,7 +714,7 @@ public class HumanPlayer extends PlayerImpl {
}
if (actingPlayer != null) {
LinkedHashMap<UUID, ActivatedAbility> useableAbilities = actingPlayer.getUseableActivatedAbilities(object, zone, game);
if (useableAbilities != null
if (useableAbilities != null
&& !useableAbilities.isEmpty()) {
activateAbility(useableAbilities, object, game);
result = true;
@ -786,7 +784,7 @@ public class HumanPlayer extends PlayerImpl {
if (abilitiesWithNoOrderSet.isEmpty()) {
return abilityOrderLast;
}
if (abilitiesWithNoOrderSet.size() == 1
if (abilitiesWithNoOrderSet.size() == 1
|| autoOrderUse) {
return abilitiesWithNoOrderSet.iterator().next();
}
@ -824,7 +822,7 @@ public class HumanPlayer extends PlayerImpl {
return false;
} else if (response.getUUID() != null) {
playManaAbilities(abilityToCast, unpaid, game);
} else if (response.getString() != null
} else if (response.getString() != null
&& response.getString().equals("special")) {
if (unpaid instanceof ManaCostsImpl) {
specialManaAction(unpaid, game);
@ -856,9 +854,9 @@ public class HumanPlayer extends PlayerImpl {
do {
game.fireGetAmountEvent(playerId, message, min, max);
waitForResponse(game);
} while (response.getInteger() == null
} while (response.getInteger() == null
&& !abort);
if (response != null
if (response != null
&& response.getInteger() != null) {
xValue = response.getInteger();
}
@ -1322,6 +1320,7 @@ public class HumanPlayer extends PlayerImpl {
switch (ability.getSpellAbilityType()) {
case SPLIT:
case SPLIT_FUSED:
case SPLIT_AFTERMATH:
MageObject object = game.getObject(ability.getSourceId());
if (object != null) {
LinkedHashMap<UUID, ActivatedAbility> useableAbilities = getSpellAbilities(object, game.getState().getZone(object.getId()), game);

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.22</version>
<version>1.4.23</version>
</parent>
<artifactId>mage-tournament-boosterdraft</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.22</version>
<version>1.4.23</version>
</parent>
<artifactId>mage-tournament-constructed</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.22</version>
<version>1.4.23</version>
</parent>
<artifactId>mage-tournament-sealed</artifactId>

View file

@ -6,7 +6,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-root</artifactId>
<version>1.4.22</version>
<version>1.4.23</version>
</parent>
<artifactId>mage-server-plugins</artifactId>

View file

@ -12,6 +12,7 @@
leasePeriod - To turn on server side connection failure detection of remoting clients, it is necessary to satisfy two criteria.
The first is that the client lease period is set and is a value greater than 0. The value is represented in milliseconds.
The client lease period can be set by either the 'clientLeasePeriod' attribute within the Connector configuration or by calling the Connector method
socketWriteTimeout - All write operations will time out if they do not complete within the configured period.
maxGameThreads - Number of games that can be started simultanously on the server
maxSecondsIdle - Number of seconds after that a game is auto conceded by the player that was idle for such a time
minUserNameLength - minmal allowed length of a user name to connect to the server
@ -40,6 +41,7 @@
numAcceptThreads="2"
maxPoolSize="300"
leasePeriod="5000"
socketWriteTimeout="10000"
maxGameThreads="10"
maxSecondsIdle="600"
minUserNameLength="3"
@ -109,6 +111,7 @@
<draftCube name="MTGO Legacy Cube January 2016" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.LegacyCubeJanuary2016"/>
<draftCube name="MTGO Legacy Cube September 2016" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.LegacyCubeSeptember2016"/>
<draftCube name="MTGO Legacy Cube January 2017" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.LegacyCubeJanuary2017"/>
<draftCube name="MTGO Legacy Cube April 2017" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.LegacyCubeApril2017"/>
<draftCube name="MTGO Legendary Cube" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.LegendaryCube"/>
<draftCube name="MTGO Legendary Cube April 2016" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.LegendaryCubeApril2016"/>
<draftCube name="MTGO Modern Cube 2017" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.ModernCube2017"/>

View file

@ -6,7 +6,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-root</artifactId>
<version>1.4.22</version>
<version>1.4.23</version>
</parent>
<artifactId>mage-server</artifactId>

View file

@ -12,6 +12,7 @@
leasePeriod - To turn on server side connection failure detection of remoting clients, it is necessary to satisfy two criteria.
The first is that the client lease period is set and is a value greater than 0. The value is represented in milliseconds.
The client lease period can be set by either the 'clientLeasePeriod' attribute within the Connector configuration or by calling the Connector method
socketWriteTimeout - All write operations will time out if they do not complete within the configured period.
maxGameThreads - Number of games that can be started simultanously on the server
maxSecondsIdle - Number of seconds after that a game is auto conceded by the player that was idle for such a time
minUserNameLength - minmal allowed length of a user name to connect to the server
@ -39,6 +40,7 @@
numAcceptThreads="2"
maxPoolSize="300"
leasePeriod="5000"
socketWriteTimeout="10000"
maxGameThreads="10"
maxSecondsIdle="600"
minUserNameLength="3"
@ -106,6 +108,7 @@
<draftCube name="MTGO Legacy Cube January 2016" jar="mage-tournament-booster-draft-${project.version}.jar" className="mage.tournament.cubes.LegacyCubeJanuary2016"/>
<draftCube name="MTGO Legacy Cube September 2016" jar="mage-tournament-booster-draft-${project.version}.jar" className="mage.tournament.cubes.LegacyCubeSeptember2016"/>
<draftCube name="MTGO Legacy Cube January 2017" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.LegacyCubeJanuary2017"/>
<draftCube name="MTGO Legacy Cube April 2017" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.LegacyCubeApril2017"/>
<draftCube name="MTGO Legendary Cube" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.LegendaryCube"/>
<draftCube name="MTGO Legendary Cube April 2016" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.LegendaryCubeApril2016"/>
<draftCube name="MTGO Modern Cube 2017" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.ModernCube2017"/>

View file

@ -27,6 +27,12 @@
*/
package mage.server;
import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.util.*;
import javax.management.MBeanServer;
import mage.cards.ExpansionSet;
import mage.cards.Sets;
import mage.cards.repository.CardScanner;
@ -59,13 +65,6 @@ import org.jboss.remoting.transporter.TransporterClient;
import org.jboss.remoting.transporter.TransporterServer;
import org.w3c.dom.Element;
import javax.management.MBeanServer;
import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.util.*;
/**
* @author BetaSteward_at_googlemail.com
*/
@ -202,6 +201,7 @@ public final class Main {
logger.info("Config - save game active: " + (config.isSaveGameActivated() ? "true" : "false"));
logger.info("Config - backlog size : " + config.getBacklogSize());
logger.info("Config - lease period : " + config.getLeasePeriod());
logger.info("Config - sock wrt timeout: " + config.getSocketWriteTimeout());
logger.info("Config - max pool size : " + config.getMaxPoolSize());
logger.info("Config - num accp.threads: " + config.getNumAcceptThreads());
logger.info("Config - second.bind port: " + config.getSecondaryBindPort());
@ -244,7 +244,7 @@ public final class Main {
static boolean isAlreadyRunning(InvokerLocator serverLocator) {
Map<String, String> metadata = new HashMap<>();
metadata.put(SocketWrapper.WRITE_TIMEOUT, "2000");
metadata.put(SocketWrapper.WRITE_TIMEOUT, String.valueOf(ConfigSettings.instance.getSocketWriteTimeout()));
metadata.put("generalizeSocketException", "true");
try {
MageServer testServer = (MageServer) TransporterClient.createTransporterClient(serverLocator.getLocatorURI(), MageServer.class, metadata);

View file

@ -24,8 +24,7 @@
* 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.server.util;
import java.io.File;
@ -33,7 +32,6 @@ import java.util.List;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import mage.server.util.config.Config;
import mage.server.util.config.GamePlugin;
import mage.server.util.config.Plugin;
@ -48,7 +46,6 @@ public enum ConfigSettings {
private Config config;
ConfigSettings() {
try {
JAXBContext jaxbContext = JAXBContext.newInstance("mage.server.util.config");
@ -79,6 +76,10 @@ public enum ConfigSettings {
return config.getServer().getLeasePeriod().intValue();
}
public int getSocketWriteTimeout() {
return config.getServer().getSocketWriteTimeout().intValue();
}
public int getMaxPoolSize() {
return config.getServer().getMaxPoolSize().intValue();
}

View file

@ -9,6 +9,7 @@
numAcceptThreads="2"
maxPoolSize="300"
leasePeriod="5000"
socketWriteTimeout="10000"
maxGameThreads="10"
maxSecondsIdle="600"
minUserNameLength="3"

View file

@ -2,102 +2,103 @@
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="config">
<xs:complexType>
<xs:sequence>
<xs:element ref="server"/>
<xs:element ref="playerTypes"/>
<xs:element ref="gameTypes"/>
<xs:element ref="tournamentTypes"/>
<xs:element ref="draftCubes"/>
<xs:element ref="deckTypes"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="config">
<xs:complexType>
<xs:sequence>
<xs:element ref="server"/>
<xs:element ref="playerTypes"/>
<xs:element ref="gameTypes"/>
<xs:element ref="tournamentTypes"/>
<xs:element ref="draftCubes"/>
<xs:element ref="deckTypes"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="server">
<xs:complexType>
<xs:attribute name="serverAddress" type="xs:string" use="required"/>
<xs:attribute name="serverName" type="xs:string" use="required"/>
<xs:attribute name="port" type="xs:positiveInteger" use="required"/>
<xs:attribute name="maxGameThreads" type="xs:positiveInteger" use="required"/>
<xs:attribute name="maxSecondsIdle" type="xs:positiveInteger" use="required"/>
<xs:attribute name="secondaryBindPort" type="xs:integer" use="required"/>
<xs:attribute name="backlogSize" type="xs:positiveInteger" use="required"/>
<xs:attribute name="numAcceptThreads" type="xs:positiveInteger" use="required"/>
<xs:attribute name="maxPoolSize" type="xs:positiveInteger" use="required"/>
<xs:attribute name="leasePeriod" type="xs:positiveInteger" use="required"/>
<xs:attribute name="minUserNameLength" type="xs:positiveInteger" use="required"/>
<xs:attribute name="maxUserNameLength" type="xs:positiveInteger" use="required"/>
<xs:attribute name="invalidUserNamePattern" type="xs:string" use="required"/>
<xs:attribute name="minPasswordLength" type="xs:positiveInteger" use="required"/>
<xs:attribute name="maxPasswordLength" type="xs:positiveInteger" use="required"/>
<xs:attribute name="maxAiOpponents" type="xs:string" use="optional"/>
<xs:attribute name="saveGameActivated" type="xs:boolean" use="optional"/>
<xs:attribute name="authenticationActivated" type="xs:boolean" use="optional"/>
<xs:attribute name="googleAccount" type="xs:string" use="optional"/>
<xs:attribute name="mailgunApiKey" type="xs:string" use="optional"/>
<xs:attribute name="mailgunDomain" type="xs:string" use="optional"/>
<xs:attribute name="mailSmtpHost" type="xs:string" use="optional"/>
<xs:attribute name="mailSmtpPort" type="xs:string" use="optional"/>
<xs:attribute name="mailUser" type="xs:string" use="optional"/>
<xs:attribute name="mailPassword" type="xs:string" use="optional"/>
<xs:attribute name="mailFromAddress" type="xs:string" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="server">
<xs:complexType>
<xs:attribute name="serverAddress" type="xs:string" use="required"/>
<xs:attribute name="serverName" type="xs:string" use="required"/>
<xs:attribute name="port" type="xs:positiveInteger" use="required"/>
<xs:attribute name="maxGameThreads" type="xs:positiveInteger" use="required"/>
<xs:attribute name="maxSecondsIdle" type="xs:positiveInteger" use="required"/>
<xs:attribute name="secondaryBindPort" type="xs:integer" use="required"/>
<xs:attribute name="backlogSize" type="xs:positiveInteger" use="required"/>
<xs:attribute name="numAcceptThreads" type="xs:positiveInteger" use="required"/>
<xs:attribute name="maxPoolSize" type="xs:positiveInteger" use="required"/>
<xs:attribute name="leasePeriod" type="xs:positiveInteger" use="required"/>
<xs:attribute name="socketWriteTimeout" type="xs:positiveInteger" use="required"/>
<xs:attribute name="minUserNameLength" type="xs:positiveInteger" use="required"/>
<xs:attribute name="maxUserNameLength" type="xs:positiveInteger" use="required"/>
<xs:attribute name="invalidUserNamePattern" type="xs:string" use="required"/>
<xs:attribute name="minPasswordLength" type="xs:positiveInteger" use="required"/>
<xs:attribute name="maxPasswordLength" type="xs:positiveInteger" use="required"/>
<xs:attribute name="maxAiOpponents" type="xs:string" use="optional"/>
<xs:attribute name="saveGameActivated" type="xs:boolean" use="optional"/>
<xs:attribute name="authenticationActivated" type="xs:boolean" use="optional"/>
<xs:attribute name="googleAccount" type="xs:string" use="optional"/>
<xs:attribute name="mailgunApiKey" type="xs:string" use="optional"/>
<xs:attribute name="mailgunDomain" type="xs:string" use="optional"/>
<xs:attribute name="mailSmtpHost" type="xs:string" use="optional"/>
<xs:attribute name="mailSmtpPort" type="xs:string" use="optional"/>
<xs:attribute name="mailUser" type="xs:string" use="optional"/>
<xs:attribute name="mailPassword" type="xs:string" use="optional"/>
<xs:attribute name="mailFromAddress" type="xs:string" use="optional"/>
</xs:complexType>
</xs:element>
<xs:complexType name="plugin">
<xs:attribute name="name" type="xs:string"/>
<xs:attribute name="jar" type="xs:string"/>
<xs:attribute name="className" type="xs:string"/>
</xs:complexType>
<xs:complexType name="plugin">
<xs:attribute name="name" type="xs:string"/>
<xs:attribute name="jar" type="xs:string"/>
<xs:attribute name="className" type="xs:string"/>
</xs:complexType>
<xs:complexType name="gamePlugin">
<xs:complexContent>
<xs:extension base="plugin">
<xs:attribute name="typeName" type="xs:string"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="gamePlugin">
<xs:complexContent>
<xs:extension base="plugin">
<xs:attribute name="typeName" type="xs:string"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="playerTypes">
<xs:complexType>
<xs:sequence>
<xs:element name="playerType" type="plugin" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="playerTypes">
<xs:complexType>
<xs:sequence>
<xs:element name="playerType" type="plugin" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="gameTypes">
<xs:complexType>
<xs:sequence>
<xs:element name="gameType" type="gamePlugin" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="gameTypes">
<xs:complexType>
<xs:sequence>
<xs:element name="gameType" type="gamePlugin" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="tournamentTypes">
<xs:complexType>
<xs:sequence>
<xs:element name="tournamentType" type="gamePlugin" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="tournamentTypes">
<xs:complexType>
<xs:sequence>
<xs:element name="tournamentType" type="gamePlugin" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="draftCubes">
<xs:complexType>
<xs:sequence>
<xs:element name="draftCube" type="plugin" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType>
<xs:sequence>
<xs:element name="draftCube" type="plugin" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="deckTypes">
<xs:complexType>
<xs:sequence>
<xs:element name="deckType" type="plugin" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="deckTypes">
<xs:complexType>
<xs:sequence>
<xs:element name="deckType" type="plugin" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-root</artifactId>
<version>1.4.22</version>
<version>1.4.23</version>
</parent>
<groupId>org.mage</groupId>

View file

@ -43,11 +43,6 @@ import mage.filter.predicate.permanent.AnotherPredicate;
* @author stravant
*/
public class AhnCropChampion extends CardImpl {
private final static FilterControlledCreaturePermanent otherCreaturesFilter = new FilterControlledCreaturePermanent("other creatures you control");
static {
otherCreaturesFilter.add(new AnotherPredicate());
}
public AhnCropChampion(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}{W}");
@ -57,7 +52,7 @@ public class AhnCropChampion extends CardImpl {
this.toughness = new MageInt(4);
// You may exert Ahn-Crop Champion as it attacks. When you do, untap all other creatures you control.
addAbility(new ExertAbility(new BecomesExertSourceTriggeredAbility(new UntapAllControllerEffect(otherCreaturesFilter))));
addAbility(new ExertAbility(new BecomesExertSourceTriggeredAbility(new UntapAllControllerEffect(new FilterControlledCreaturePermanent("creatures you control"), null, false))));
}
public AhnCropChampion(final AhnCropChampion card) {

View file

@ -27,6 +27,7 @@
*/
package mage.cards.a;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateTokenEffect;
@ -34,13 +35,12 @@ import mage.cards.CardSetInfo;
import mage.cards.SplitCard;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SpellAbilityType;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.game.Game;
import mage.game.permanent.token.CentaurToken;
import mage.players.Player;
import java.util.UUID;
/**
*
* @author LevelX2
@ -48,7 +48,7 @@ import java.util.UUID;
public class AliveWell extends SplitCard {
public AliveWell(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{G}", "{W}", true);
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{G}", "{W}", SpellAbilityType.SPLIT_FUSED);
// Alive
// Create a 3/3 green Centaur creature token.

View file

@ -1,7 +1,8 @@
package mage.cards.a;
import java.util.*;
import mage.abilities.Ability;
import mage.abilities.SpellAbility;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
@ -9,24 +10,20 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.WatcherScope;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.DamagedPlayerEvent;
import mage.game.events.GameEvent;
import mage.game.stack.Spell;
import mage.players.Player;
import mage.watchers.Watcher;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
/**
* @author stravant
*/
public class ApproachOfTheSecondSun extends CardImpl {
public ApproachOfTheSecondSun(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{6}{W}");
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{6}{W}");
getSpellAbility().addEffect(new ApproachOfTheSecondSunEffect());
getSpellAbility().addWatcher(new ApproachOfTheSecondSunWatcher());
@ -43,11 +40,12 @@ public class ApproachOfTheSecondSun extends CardImpl {
}
class ApproachOfTheSecondSunEffect extends OneShotEffect {
public ApproachOfTheSecondSunEffect() {
super(Outcome.Win);
this.staticText =
"If you cast {this} from you hand and you cast another spell named {this} this game, you win the game. " +
"If not, you gain 7 life and put {this} back into your library as the seventh card from the top.";
this.staticText
= "If {this} was cast from your hand and you've cast another spell named Approach of the Second Sun this game, you win the game. "
+ "Otherwise, put {this} into its owner's library seventh from the top and you gain 7 life.";
}
public ApproachOfTheSecondSunEffect(final ApproachOfTheSecondSunEffect effect) {
@ -62,10 +60,11 @@ class ApproachOfTheSecondSunEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
ApproachOfTheSecondSunWatcher watcher =
(ApproachOfTheSecondSunWatcher) game.getState().getWatchers().get("approachOfTheSecondSunWatcher", source.getControllerId());
if (watcher != null && watcher.getApproachesCast() > 1) {
Spell spell = game.getStack().getSpell(source.getSourceId());
if (controller != null && spell != null) {
ApproachOfTheSecondSunWatcher watcher
= (ApproachOfTheSecondSunWatcher) game.getState().getWatchers().get(ApproachOfTheSecondSunWatcher.class.getName());
if (watcher != null && watcher.getApproachesCast(controller.getId()) > 1 && spell.getFromZone() == Zone.HAND) {
// Win the game
controller.won(game);
} else {
@ -73,21 +72,32 @@ class ApproachOfTheSecondSunEffect extends OneShotEffect {
controller.gainLife(7, game);
// Put this into the library as the 7th from the top
List<Card> top6 = new ArrayList<>();
// Cut the top 6 cards off into a temporary array
for (int i = 0; i < 6 && controller.getLibrary().hasCards(); ++i) {
top6.add(controller.getLibrary().removeFromTop(game));
}
// Put this card (if the ability came from an ApproachOfTheSecondSun spell card) on top
Card sourceCard = game.getCard(source.getSourceId());
if (sourceCard != null) {
controller.getLibrary().putOnTop(sourceCard, game);
}
Card spellCard = game.getStack().getSpell(source.getSourceId()).getCard();
if (spellCard != null) {
List<Card> top6 = new ArrayList<>();
// Cut the top 6 cards off into a temporary array
for (int i = 0; i < 6 && controller.getLibrary().hasCards(); ++i) {
top6.add(controller.getLibrary().removeFromTop(game));
}
// put the top 6 we took earlier back on top (going in reverse order this time to get them back
// on top in the proper order)
for (int i = top6.size() - 1; i >= 0; --i) {
controller.getLibrary().putOnTop(top6.get(i), game);
// Is the library now empty, thus the rise is on the bottom (for the message to the players)?
boolean isOnBottom = !controller.getLibrary().hasCards();
// Put this card (if the ability came from an ApproachOfTheSecondSun spell card) on top
spellCard.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);
// put the top 6 we took earlier back on top (going in reverse order this time to get them back
// on top in the proper order)
for (int i = top6.size() - 1; i >= 0; --i) {
controller.getLibrary().putOnTop(top6.get(i), game);
}
// Inform the players
if (isOnBottom) {
game.informPlayers(controller.getLogName() + " puts " + spell.getLogName() + " on the bottom of his or her library.");
} else {
game.informPlayers(controller.getLogName() + " puts " + spell.getLogName() + " into his or her library 6th from the top.");
}
}
}
return true;
@ -96,28 +106,37 @@ class ApproachOfTheSecondSunEffect extends OneShotEffect {
}
}
class ApproachOfTheSecondSunWatcher extends Watcher {
private int approachesCast = 0;
private Map<UUID, Integer> approachesCast = new HashMap<>();
public ApproachOfTheSecondSunWatcher() {
super("approachOfTheSecondSunWatcher", WatcherScope.PLAYER);
super(ApproachOfTheSecondSunWatcher.class.getName(), WatcherScope.GAME);
}
public ApproachOfTheSecondSunWatcher(final ApproachOfTheSecondSunWatcher watcher) {
super(watcher);
approachesCast = watcher.approachesCast;
approachesCast = new HashMap<>(approachesCast);
}
@Override
public void watch(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.SPELL_CAST && event.getPlayerId().equals(this.getControllerId())) {
++approachesCast;
if (event.getType() == GameEvent.EventType.SPELL_CAST) {
Spell spell = game.getStack().getSpell(event.getSourceId());
if (spell != null && spell.getName().equals("Approach of the Second Sun")) {
int cast = getApproachesCast(event.getPlayerId());
approachesCast.put(event.getPlayerId(), cast + 1);
}
}
}
public int getApproachesCast() {
return approachesCast;
public int getApproachesCast(UUID player) {
Integer cast = approachesCast.get(player);
if (cast == null) {
return 0;
} else {
return cast;
}
}
@Override

View file

@ -25,9 +25,9 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.a;
import java.util.UUID;
import mage.abilities.effects.common.combat.MustBeBlockedByAllTargetEffect;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
@ -36,24 +36,17 @@ import mage.cards.CardSetInfo;
import mage.cards.SplitCard;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SpellAbilityType;
import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public class ArmedDangerous extends SplitCard {
public ArmedDangerous(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{1}{R}","{3}{G}",true);
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{R}", "{3}{G}", SpellAbilityType.SPLIT_FUSED);
// Armed
// Target creature gets +1/+1 and gains double strike until end of turn.
getLeftHalfCard().getSpellAbility().addEffect(new BoostTargetEffect(1,1, Duration.EndOfTurn));
getLeftHalfCard().getSpellAbility().addEffect(new BoostTargetEffect(1, 1, Duration.EndOfTurn));
getLeftHalfCard().getSpellAbility().addEffect(new GainAbilityTargetEffect(DoubleStrikeAbility.getInstance(), Duration.EndOfTurn));
getLeftHalfCard().getSpellAbility().addTarget(new TargetCreaturePermanent());

View file

@ -27,6 +27,7 @@
*/
package mage.cards.a;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
@ -42,8 +43,6 @@ import mage.game.permanent.Permanent;
import mage.target.common.TargetCreaturePermanent;
import mage.util.functions.ApplyToPermanent;
import java.util.UUID;
/**
*
* @author LevelX2
@ -51,7 +50,7 @@ import java.util.UUID;
public class ArtisanOfForms extends CardImpl {
public ArtisanOfForms(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{U}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}");
this.subtype.add("Human");
this.subtype.add("Wizard");
@ -79,7 +78,7 @@ public class ArtisanOfForms extends CardImpl {
class ArtisanOfFormsApplyToPermanent extends ApplyToPermanent {
@Override
public boolean apply(Game game, MageObject mageObject) {
public boolean apply(Game game, MageObject mageObject, Ability source, UUID copyToObjectId) {
Effect effect = new CopyPermanentEffect(new ArtisanOfFormsApplyToPermanent());
effect.setText("have {this} become a copy of target creature and gain this ability");
mageObject.getAbilities().add(new HeroicAbility(effect, true));
@ -87,7 +86,7 @@ class ArtisanOfFormsApplyToPermanent extends ApplyToPermanent {
}
@Override
public boolean apply(Game game, Permanent permanent) {
public boolean apply(Game game, Permanent permanent, Ability source, UUID copyToObjectId) {
Effect effect = new CopyPermanentEffect(new ArtisanOfFormsApplyToPermanent());
effect.setText("have {this} become a copy of target creature and gain this ability");
permanent.addAbility(new HeroicAbility(effect, true), game);

View file

@ -60,7 +60,7 @@ import mage.watchers.Watcher;
public class AsForetold extends CardImpl {
public AsForetold(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}");
// At the beginning of your upkeep, put a time counter on As Foretold.
addAbility(
@ -145,7 +145,7 @@ class AsForetoldAlternativeCost extends AlternativeCostSourceAbility {
class AsForetoldAddAltCostEffect extends ContinuousEffectImpl {
public AsForetoldAddAltCostEffect() {
super(Duration.WhileOnBattlefield, Outcome.Benefit);
staticText = "Once each turn, you may pay {0} rather than pay the mana cost for a spelly ou cast with converted mana cost X or less, where X is the number of time counters on {this}.";
staticText = "Once each turn, you may pay {0} rather than pay the mana cost for a spell you cast with converted mana cost X or less, where X is the number of time counters on {this}.";
}
public AsForetoldAddAltCostEffect(final AsForetoldAddAltCostEffect effect) {

View file

@ -25,30 +25,23 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.a;
import java.util.UUID;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.cards.CardSetInfo;
import mage.cards.SplitCard;
import mage.constants.CardType;
import mage.constants.SpellAbilityType;
import mage.game.permanent.token.ElephantToken;
import mage.target.common.TargetCreatureOrPlayer;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public class AssaultBattery extends SplitCard {
public AssaultBattery(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{R}","{3}{G}",false);
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{R}", "{3}{G}", SpellAbilityType.SPLIT);
// Assault
// Assault deals 2 damage to target creature or player.

View file

@ -35,15 +35,14 @@ import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.VigilanceAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.Effect;
import mage.abilities.keyword.EmbalmAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.v.Vigilance;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Zone;
import mage.filter.StaticFilters;
import mage.filter.predicate.permanent.TokenPredicate;
/**
*
@ -53,7 +52,7 @@ public class AvenWindGuide extends CardImpl {
public AvenWindGuide(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}{U}");
this.subtype.add("Bird");
this.subtype.add("Warrior");
this.power = new MageInt(2);
@ -66,18 +65,18 @@ public class AvenWindGuide extends CardImpl {
this.addAbility(VigilanceAbility.getInstance());
// Creature tokens you control have flying and vigilance.
Ability ability =
new SimpleStaticAbility(
Zone.BATTLEFIELD,
new GainAbilityControlledEffect(
Effect effect = new GainAbilityControlledEffect(
FlyingAbility.getInstance(),
Duration.WhileOnBattlefield,
StaticFilters.FILTER_CREATURE_TOKENS));
ability.addEffect(
new GainAbilityControlledEffect(
StaticFilters.FILTER_CREATURE_TOKENS);
effect.setText("Creature tokens you control have flying");
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, effect);
effect = new GainAbilityControlledEffect(
VigilanceAbility.getInstance(),
Duration.WhileOnBattlefield,
StaticFilters.FILTER_CREATURE_TOKENS));
StaticFilters.FILTER_CREATURE_TOKENS);
effect.setText("and vigilance");
ability.addEffect(effect);
this.addAbility(ability);
// Embalm {4}{W}{U}

View file

@ -27,6 +27,7 @@
*/
package mage.cards.b;
import java.util.UUID;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.abilities.effects.common.CreateTokenEffect;
@ -35,6 +36,7 @@ import mage.cards.CardSetInfo;
import mage.cards.SplitCard;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SpellAbilityType;
import mage.filter.common.FilterCreaturePermanent;
import mage.game.Game;
import mage.game.events.GameEvent;
@ -42,12 +44,10 @@ import mage.game.events.GameEvent.EventType;
import mage.game.permanent.Permanent;
import mage.game.permanent.token.BirdToken;
import java.util.UUID;
public class BeckCall extends SplitCard {
public BeckCall(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{G}{U}","{4}{W}{U}",true);
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{G}{U}", "{4}{W}{U}", SpellAbilityType.SPLIT_FUSED);
// Beck
// Whenever a creature enters the battlefield this turn, you may draw a card.

View file

@ -97,7 +97,7 @@ class BonePickerCostAdjustmentAbility extends SimpleStaticAbility implements Adj
@Override
public String getRule() {
return "If a creature died this turn, {this} costs 3 less to cast.";
return "If a creature died this turn, {this} costs {3} less to cast.";
}
@Override

View file

@ -61,7 +61,7 @@ import mage.watchers.common.CreaturesDiedWatcher;
*/
public class BontuTheGlorified extends CardImpl {
private static final FilterControlledPermanent filter = new FilterControlledPermanent();
private static final FilterControlledPermanent filter = new FilterControlledPermanent("another creature");
static {
filter.add(new AnotherPredicate());

View file

@ -27,19 +27,19 @@
*/
package mage.cards.b;
import java.util.UUID;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.DestroyAllEffect;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.cards.CardSetInfo;
import mage.cards.SplitCard;
import mage.constants.CardType;
import mage.constants.SpellAbilityType;
import mage.constants.TargetController;
import mage.filter.common.FilterLandPermanent;
import mage.filter.predicate.permanent.ControllerPredicate;
import mage.target.TargetPermanent;
import java.util.UUID;
public class BoomBust extends SplitCard {
private static final FilterLandPermanent filter1 = new FilterLandPermanent("land you control");
@ -51,7 +51,7 @@ public class BoomBust extends SplitCard {
}
public BoomBust(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{1}{R}","{5}{R}",false);
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{R}", "{5}{R}", SpellAbilityType.SPLIT);
// Boom
// Destroy target land you control and target land you don't control.

View file

@ -27,6 +27,7 @@
*/
package mage.cards.b;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
@ -40,6 +41,7 @@ import mage.cards.SplitCard;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.SpellAbilityType;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.FilterSpell;
@ -53,8 +55,6 @@ import mage.players.Player;
import mage.target.common.TargetCardInYourGraveyard;
import mage.target.common.TargetControlledPermanent;
import java.util.UUID;
/**
*
* @author LevelX2
@ -68,7 +68,7 @@ public class BoundDetermined extends SplitCard {
}
public BoundDetermined(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{3}{B}{G}","{G}{U}",false);
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{B}{G}", "{G}{U}", SpellAbilityType.SPLIT);
// Bound
// Sacrifice a creature. Return up to X cards from your graveyard to your hand, where X is the number of colors that creature was. Exile this card.

View file

@ -1,112 +1,116 @@
/*
* 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.cards.b;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import java.util.UUID;
import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfPreCombatMainTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.constants.Outcome;
import mage.constants.TargetController;
import mage.counters.CounterType;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
/**
*
* @author jeffwadsworth
*/
public class BountyOfTheLuxa extends CardImpl {
public BountyOfTheLuxa(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}{U}");
//At the beginning of your precombat main phase, remove all flood counters from Bounty of the Luxa. If no flood counters were removed this way, put a flood counter on Bounty of the Luxa and draw a card. Otherwise, add {C}{G}{U} to your mana pool.
this.addAbility(new BeginningOfPreCombatMainTriggeredAbility(new BountyOfTheLuxaEffect(), TargetController.YOU, false));
}
public BountyOfTheLuxa(final BountyOfTheLuxa card) {
super(card);
}
@Override
public BountyOfTheLuxa copy() {
return new BountyOfTheLuxa(this);
}
}
class BountyOfTheLuxaEffect extends OneShotEffect {
public BountyOfTheLuxaEffect() {
super(Outcome.Benefit);
staticText = "remove all flood counters from {this}. If no flood counters were removed this way, put a flood counter on {this} and draw a card. Otherwise, add {C}{G}{U} to your mana pool";
}
public BountyOfTheLuxaEffect(final BountyOfTheLuxaEffect effect) {
super(effect);
}
@Override
public BountyOfTheLuxaEffect copy() {
return new BountyOfTheLuxaEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Permanent bountyOfLuxa = game.getPermanent(source.getSourceId());
if (controller != null
&& bountyOfLuxa != null) {
if (bountyOfLuxa.getCounters(game).getCount(CounterType.FLOOD) > 0) {
bountyOfLuxa.removeCounters(CounterType.FLOOD.createInstance(bountyOfLuxa.getCounters(game).getCount(CounterType.FLOOD)), game);
if (bountyOfLuxa.getCounters(game).getCount(CounterType.FLOOD) == 0) {
Mana manaToAdd = new Mana();
manaToAdd.increaseColorless();
manaToAdd.increaseGreen();
manaToAdd.increaseBlue();
controller.getManaPool().addMana(manaToAdd, game, source);
}
} else {
new AddCountersSourceEffect(CounterType.FLOOD.createInstance()).apply(game, source);
new DrawCardSourceControllerEffect(1).apply(game, source);
}
return true;
}
return false;
}
}
/*
* 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.cards.b;
import java.util.UUID;
import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfPreCombatMainTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.TargetController;
import mage.counters.CounterType;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
/**
*
* @author jeffwadsworth
*/
public class BountyOfTheLuxa extends CardImpl {
public BountyOfTheLuxa(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}{U}");
//At the beginning of your precombat main phase, remove all flood counters from Bounty of the Luxa. If no counters were removed this way, put a flood counter on Bounty of the Luxa and draw a card. Otherwise, add {C}{G}{U} to your mana pool.
this.addAbility(new BeginningOfPreCombatMainTriggeredAbility(new BountyOfTheLuxaEffect(), TargetController.YOU, false));
}
public BountyOfTheLuxa(final BountyOfTheLuxa card) {
super(card);
}
@Override
public BountyOfTheLuxa copy() {
return new BountyOfTheLuxa(this);
}
}
class BountyOfTheLuxaEffect extends OneShotEffect {
public BountyOfTheLuxaEffect() {
super(Outcome.Benefit);
staticText = "remove all flood counters from {this}. If no counters were removed this way, put a flood counter on {this} and draw a card. Otherwise, add {C}{G}{U} to your mana pool";
}
public BountyOfTheLuxaEffect(final BountyOfTheLuxaEffect effect) {
super(effect);
}
@Override
public BountyOfTheLuxaEffect copy() {
return new BountyOfTheLuxaEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Permanent bountyOfLuxa = game.getPermanent(source.getSourceId());
if (bountyOfLuxa != null && bountyOfLuxa.getZoneChangeCounter(game) != source.getSourceObjectZoneChangeCounter()) {
bountyOfLuxa = null;
}
if (controller != null) {
if (bountyOfLuxa != null
&& bountyOfLuxa.getCounters(game).getCount(CounterType.FLOOD) > 0) {
bountyOfLuxa.removeCounters(CounterType.FLOOD.createInstance(bountyOfLuxa.getCounters(game).getCount(CounterType.FLOOD)), game);
if (bountyOfLuxa.getCounters(game).getCount(CounterType.FLOOD) == 0) {
Mana manaToAdd = new Mana();
manaToAdd.increaseColorless();
manaToAdd.increaseGreen();
manaToAdd.increaseBlue();
controller.getManaPool().addMana(manaToAdd, game, source);
}
} else {
if (bountyOfLuxa != null) {
new AddCountersSourceEffect(CounterType.FLOOD.createInstance()).apply(game, source);
}
controller.drawCards(1, game);
}
return true;
}
return false;
}
}

View file

@ -27,6 +27,7 @@
*/
package mage.cards.b;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
@ -39,6 +40,7 @@ import mage.cards.SplitCard;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.SpellAbilityType;
import mage.constants.Zone;
import mage.filter.common.FilterCreatureCard;
import mage.game.Game;
@ -48,12 +50,10 @@ import mage.target.TargetPlayer;
import mage.target.common.TargetCardInGraveyard;
import mage.target.targetpointer.FixedTarget;
import java.util.UUID;
public class BreakingEntering extends SplitCard {
public BreakingEntering(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{U}{B}","{4}{B}{R}",true);
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{U}{B}", "{4}{B}{R}", SpellAbilityType.SPLIT_FUSED);
// Breaking
// Target player puts the top eight cards of his or her library into his or her graveyard.

View file

@ -27,6 +27,9 @@
*/
package mage.cards.c;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
@ -39,6 +42,7 @@ import mage.cards.SplitCard;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.SpellAbilityType;
import mage.filter.FilterPermanent;
import mage.filter.common.*;
import mage.game.Game;
@ -48,14 +52,10 @@ import mage.target.Target;
import mage.target.TargetPermanent;
import mage.target.common.TargetControlledPermanent;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class CatchRelease extends SplitCard {
public CatchRelease(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{1}{U}{R}","{4}{R}{W}",true);
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{U}{R}", "{4}{R}{W}", SpellAbilityType.SPLIT_FUSED);
// Catch
// Gain control of target permanent until end of turn. Untap it. It gains haste until end of turn.

View file

@ -45,12 +45,6 @@ import mage.filter.predicate.permanent.AnotherPredicate;
*/
public class CombatCelebrant extends CardImpl {
private final static FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("other creatures you control");
static {
filter.add(new AnotherPredicate());
}
public CombatCelebrant(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}");
@ -60,7 +54,7 @@ public class CombatCelebrant extends CardImpl {
this.toughness = new MageInt(1);
// If Combat Celebrant hasn't been exerted this turn, you may exert it as it attacks. When you do, untap all other creatures you control and after this phase, there is an additional combat phase.
BecomesExertSourceTriggeredAbility ability = new BecomesExertSourceTriggeredAbility(new UntapAllControllerEffect(filter));
BecomesExertSourceTriggeredAbility ability = new BecomesExertSourceTriggeredAbility(new UntapAllControllerEffect(new FilterControlledCreaturePermanent(), null, false));
ability.addEffect(new AdditionalCombatPhaseEffect("and after this phase, there is an additional combat phase"));
this.addAbility(new ExertAbility(ability, true));
}

View file

@ -39,6 +39,7 @@ import mage.cards.CardSetInfo;
import mage.cards.SplitCard;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SpellAbilityType;
import mage.constants.Zone;
import mage.filter.common.FilterSpellOrPermanent;
import mage.filter.predicate.Predicates;
@ -62,7 +63,7 @@ public class CommitMemory extends SplitCard {
}
public CommitMemory(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, new CardType[]{CardType.SORCERY}, "{3}{U}", "{4}{U}{U}", false);
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, new CardType[]{CardType.SORCERY}, "{3}{U}", "{4}{U}{U}", SpellAbilityType.SPLIT_AFTERMATH);
// Commit
// Put target spell or nonland permanent into its owner's library second from the top.
@ -72,7 +73,7 @@ public class CommitMemory extends SplitCard {
// Memory
// Aftermath
// Each player shuffles his or her hand and graveyard into his or her library, then draws seven cards.
((CardImpl)(getRightHalfCard())).addAbility(new AftermathAbility());
((CardImpl) (getRightHalfCard())).addAbility(new AftermathAbility());
getRightHalfCard().getSpellAbility().addEffect(new MemoryEffect());
Effect effect = new DrawCardAllEffect(7);
effect.setText(", then draws seven cards");

View file

@ -1,87 +1,90 @@
/*
* 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.cards.c;
import java.util.UUID;
import mage.target.common.TargetCreaturePermanent;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.common.SacrificeSourceCost;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.effects.common.combat.CantAttackBlockAttachedEffect;
import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect;
import mage.constants.Outcome;
import mage.target.TargetPermanent;
import mage.abilities.keyword.EnchantAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.AttachmentType;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Zone;
/**
*
* @author Styxo
*/
public class CompulsoryRest extends CardImpl {
public CompulsoryRest(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}");
this.subtype.add("Aura");
// Enchant creature
TargetPermanent auraTarget = new TargetCreaturePermanent();
this.getSpellAbility().addTarget(auraTarget);
this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature));
Ability ability = new EnchantAbility(auraTarget.getTargetName());
this.addAbility(ability);
// Enchanted creature can't attack or block.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantAttackBlockAttachedEffect(AttachmentType.AURA)));
// Enchanted creature has "{2}, Sacrifice this creature: You gain 2 life."
Ability grantedAbility = new SimpleActivatedAbility(Zone.BATTLEFIELD, new GainLifeEffect(2), new GenericManaCost(2));
grantedAbility.addCost(new SacrificeSourceCost());
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(grantedAbility, AttachmentType.AURA, Duration.WhileOnBattlefield)));
}
public CompulsoryRest(final CompulsoryRest card) {
super(card);
}
@Override
public CompulsoryRest copy() {
return new CompulsoryRest(this);
}
}
/*
* 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.cards.c;
import java.util.UUID;
import mage.target.common.TargetCreaturePermanent;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.Cost;
import mage.abilities.costs.common.SacrificeSourceCost;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.effects.common.combat.CantAttackBlockAttachedEffect;
import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect;
import mage.constants.Outcome;
import mage.target.TargetPermanent;
import mage.abilities.keyword.EnchantAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.AttachmentType;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Zone;
/**
*
* @author Styxo
*/
public class CompulsoryRest extends CardImpl {
public CompulsoryRest(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}");
this.subtype.add("Aura");
// Enchant creature
TargetPermanent auraTarget = new TargetCreaturePermanent();
this.getSpellAbility().addTarget(auraTarget);
this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature));
Ability ability = new EnchantAbility(auraTarget.getTargetName());
this.addAbility(ability);
// Enchanted creature can't attack or block.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantAttackBlockAttachedEffect(AttachmentType.AURA)));
// Enchanted creature has "{2}, Sacrifice this creature: You gain 2 life."
Ability grantedAbility = new SimpleActivatedAbility(Zone.BATTLEFIELD, new GainLifeEffect(2), new GenericManaCost(2));
Cost cost = new SacrificeSourceCost();
cost.setText("Sacrifice this creature");
grantedAbility.addCost(cost);
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(grantedAbility, AttachmentType.AURA, Duration.WhileOnBattlefield)));
}
public CompulsoryRest(final CompulsoryRest card) {
super(card);
}
@Override
public CompulsoryRest copy() {
return new CompulsoryRest(this);
}
}

View file

@ -25,9 +25,9 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.c;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
@ -35,6 +35,7 @@ import mage.cards.CardSetInfo;
import mage.cards.SplitCard;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SpellAbilityType;
import mage.filter.FilterCard;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.CardTypePredicate;
@ -42,20 +43,17 @@ import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.common.TargetCardInOpponentsGraveyard;
import java.util.UUID;
public class CrimePunishment extends SplitCard {
private static final FilterCard filter = new FilterCard("creature or enchantment card from an opponent's graveyard");
static {
filter.add(Predicates.or(new CardTypePredicate(CardType.CREATURE),
new CardTypePredicate(CardType.ENCHANTMENT)));
new CardTypePredicate(CardType.ENCHANTMENT)));
}
public CrimePunishment(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{3}{W}{B}","{X}{B}{G}",false);
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{W}{B}", "{X}{B}{G}", SpellAbilityType.SPLIT);
// Crime
// Put target creature or enchantment card from an opponent's graveyard onto the battlefield under your control.
@ -79,29 +77,29 @@ public class CrimePunishment extends SplitCard {
}
class PunishmentEffect extends OneShotEffect {
PunishmentEffect() {
super(Outcome.DestroyPermanent);
this.staticText = "Destroy each artifact, creature, and enchantment with converted mana cost X";
}
PunishmentEffect(final PunishmentEffect effect) {
super(effect);
}
@Override
public PunishmentEffect copy() {
return new PunishmentEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
for (Permanent permanent : game.getBattlefield().getActivePermanents(source.getControllerId(), game)) {
if (permanent != null
&& permanent.getConvertedManaCost() == source.getManaCostsToPay().getX()
&& (permanent.isArtifact()
|| permanent.isCreature()
|| permanent.isEnchantment())) {
|| permanent.isCreature()
|| permanent.isEnchantment())) {
permanent.destroy(source.getSourceId(), game, false);
}
}

View file

@ -27,6 +27,7 @@
*/
package mage.cards.c;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
@ -44,8 +45,6 @@ import mage.game.permanent.Permanent;
import mage.target.common.TargetCreaturePermanent;
import mage.util.functions.ApplyToPermanent;
import java.util.UUID;
/**
* @author Loki
*/
@ -58,7 +57,7 @@ public class Cryptoplasm extends CardImpl {
}
public Cryptoplasm(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{U}{U}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}{U}");
this.subtype.add("Shapeshifter");
this.power = new MageInt(2);
@ -103,7 +102,7 @@ class CryptoplasmEffect extends OneShotEffect {
if (creatureToCopy != null) {
ApplyToPermanent applier = new ApplyToPermanent() {
@Override
public boolean apply(Game game, Permanent permanent) {
public boolean apply(Game game, Permanent permanent, Ability source, UUID copyToObjectId) {
Ability upkeepAbility = new BeginningOfUpkeepTriggeredAbility(new CryptoplasmEffect(), TargetController.YOU, true);
upkeepAbility.addTarget(new TargetCreaturePermanent());
permanent.addAbility(upkeepAbility, source.getSourceId(), game);
@ -111,7 +110,7 @@ class CryptoplasmEffect extends OneShotEffect {
}
@Override
public boolean apply(Game game, MageObject mageObject) {
public boolean apply(Game game, MageObject mageObject, Ability source, UUID copyToObjectId) {
Ability upkeepAbility = new BeginningOfUpkeepTriggeredAbility(new CryptoplasmEffect(), TargetController.YOU, true);
upkeepAbility.addTarget(new TargetCreaturePermanent());
mageObject.getAbilities().add(upkeepAbility);

View file

@ -1,5 +1,6 @@
package mage.cards.c;
import java.util.UUID;
import mage.abilities.dynamicvalue.common.ManacostVariableValue;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.effects.common.LoseLifeOpponentsEffect;
@ -8,17 +9,16 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.SplitCard;
import mage.constants.CardType;
import mage.constants.SpellAbilityType;
import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
/**
* @author Stravant
*/
public class CutRibbons extends SplitCard {
public CutRibbons(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{R}", "{X}{B}{B}", false);
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, new CardType[]{CardType.SORCERY}, "{1}{R}", "{X}{B}{B}", SpellAbilityType.SPLIT_AFTERMATH);
// Cut
// Cut deals 4 damage to target creature.
@ -26,7 +26,6 @@ public class CutRibbons extends SplitCard {
getLeftHalfCard().getSpellAbility().addEffect(new DamageTargetEffect(4));
// to
// Ribbons
// Each opponent loses X life.
((CardImpl) (getRightHalfCard())).addAbility(new AftermathAbility());

View file

@ -27,8 +27,10 @@
*/
package mage.cards.d;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.CopyPermanentEffect;
@ -42,8 +44,6 @@ import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.util.functions.ApplyToPermanent;
import java.util.UUID;
/**
*
* @author LevelX2
@ -51,7 +51,7 @@ import java.util.UUID;
public class DacksDuplicate extends CardImpl {
public DacksDuplicate(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{U}{R}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}{R}");
this.subtype.add("Shapeshifter");
this.power = new MageInt(0);
@ -76,7 +76,7 @@ public class DacksDuplicate extends CardImpl {
class DacksDuplicateApplyToPermanent extends ApplyToPermanent {
@Override
public boolean apply(Game game, Permanent permanent) {
public boolean apply(Game game, Permanent permanent, Ability source, UUID copyToObjectId) {
/**
* 29/05/2014 The ability of Dacks Duplicate doesnt target the
* creature.
@ -87,7 +87,7 @@ class DacksDuplicateApplyToPermanent extends ApplyToPermanent {
}
@Override
public boolean apply(Game game, MageObject mageObject) {
public boolean apply(Game game, MageObject mageObject, Ability source, UUID copyToObjectId) {
mageObject.getAbilities().add(new DethroneAbility());
mageObject.getAbilities().add(HasteAbility.getInstance());
return true;

View file

@ -1,30 +1,31 @@
package mage.cards.d;
import java.util.UUID;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.effects.common.ReturnToHandTargetEffect;
import mage.cards.Card;
import mage.cards.CardSetInfo;
import mage.cards.SplitCard;
import mage.constants.CardType;
import mage.constants.SpellAbilityType;
import mage.constants.TargetController;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.permanent.ControllerPredicate;
import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
/**
* @author dustinconrad
*/
public class DeadGone extends SplitCard {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature you don't control");
static {
filter.add(new ControllerPredicate(TargetController.NOT_YOU));
}
public DeadGone(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{R}","{2}{R}",false);
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{R}", "{2}{R}", SpellAbilityType.SPLIT);
// Dead
// Dead deals 2 damage to target creature.

View file

@ -47,7 +47,7 @@ public class Decompose extends CardImpl {
// Exile up to three target cards from a single graveyard.
this.getSpellAbility().addEffect(new ExileTargetEffect());
this.getSpellAbility().addTarget(new TargetCardInASingleGraveyard(0, 3, new FilterCard("cards")));
this.getSpellAbility().addTarget(new TargetCardInASingleGraveyard(0, 3, new FilterCard("cards from a single graveyard")));
}
public Decompose(final Decompose card) {

View file

@ -25,9 +25,9 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.d;
import java.util.UUID;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.combat.MustBeBlockedByAllTargetEffect;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
@ -39,20 +39,13 @@ import mage.cards.CardSetInfo;
import mage.cards.SplitCard;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SpellAbilityType;
import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
/**
*
* @author stravant
*/
public class DestinedLead extends SplitCard {
public DestinedLead(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT}, new CardType[]{CardType.SORCERY},"{1}{B}","{3}{G}",false);
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, new CardType[]{CardType.SORCERY}, "{1}{B}", "{3}{G}", SpellAbilityType.SPLIT_AFTERMATH);
// Destined
// Target creature gets +1/+0 and gains indestructible until end of turn.
@ -66,10 +59,9 @@ public class DestinedLead extends SplitCard {
getLeftHalfCard().getSpellAbility().addEffect(effect);
// to
// Lead
// All creatures able to block target creature this turn must do so.
((CardImpl)(getRightHalfCard())).addAbility(new AftermathAbility());
((CardImpl) (getRightHalfCard())).addAbility(new AftermathAbility());
getRightHalfCard().getSpellAbility().addTarget(new TargetCreaturePermanent());
getRightHalfCard().getSpellAbility().addEffect(new MustBeBlockedByAllTargetEffect(Duration.EndOfTurn));
}
@ -83,4 +75,3 @@ public class DestinedLead extends SplitCard {
return new DestinedLead(this);
}
}

View file

@ -1,78 +1,81 @@
/*
* 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.cards.d;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.BecomesExertSourceTriggeredAbility;
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
import mage.abilities.keyword.ExertAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.ComparisonType;
import mage.filter.common.FilterCreatureCard;
import mage.filter.predicate.mageobject.ConvertedManaCostPredicate;
import mage.target.common.TargetCardInYourGraveyard;
/**
*
* @author Styxo
*/
public class DevotedCropMate extends CardImpl {
private static final FilterCreatureCard filter = new FilterCreatureCard("creature card with converted mana cost 2 or less from your graveyard");
static {
filter.add(new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, 3));
}
public DevotedCropMate(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}");
this.subtype.add("Human");
this.subtype.add("Warrior");
this.power = new MageInt(3);
this.toughness = new MageInt(2);
// You may exert Devoted Crop-Mate as it attacks. When you do, return target creature card with converted mana cost 2 or less from your graveyard to the battlefield.
BecomesExertSourceTriggeredAbility ability = new BecomesExertSourceTriggeredAbility(new ReturnFromGraveyardToBattlefieldTargetEffect());
ability.addTarget(new TargetCardInYourGraveyard(filter));
addAbility(new ExertAbility(ability));
}
public DevotedCropMate(final DevotedCropMate card) {
super(card);
}
@Override
public DevotedCropMate copy() {
return new DevotedCropMate(this);
}
}
/*
* 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.cards.d;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.BecomesExertSourceTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
import mage.abilities.keyword.ExertAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.ComparisonType;
import mage.filter.common.FilterCreatureCard;
import mage.filter.predicate.mageobject.ConvertedManaCostPredicate;
import mage.target.common.TargetCardInYourGraveyard;
/**
*
* @author Styxo
*/
public class DevotedCropMate extends CardImpl {
private static final FilterCreatureCard filter = new FilterCreatureCard("creature card with converted mana cost 2 or less from your graveyard");
static {
filter.add(new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, 3));
}
public DevotedCropMate(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}");
this.subtype.add("Human");
this.subtype.add("Warrior");
this.power = new MageInt(3);
this.toughness = new MageInt(2);
// You may exert Devoted Crop-Mate as it attacks. When you do, return target creature card with converted mana cost 2 or less from your graveyard to the battlefield.
Effect effect = new ReturnFromGraveyardToBattlefieldTargetEffect();
effect.setText("return target creature card with converted mana cost 2 or less from your graveyard to the battlefield");
BecomesExertSourceTriggeredAbility ability = new BecomesExertSourceTriggeredAbility(effect);
ability.addTarget(new TargetCardInYourGraveyard(filter));
addAbility(new ExertAbility(ability));
}
public DevotedCropMate(final DevotedCropMate card) {
super(card);
}
@Override
public DevotedCropMate copy() {
return new DevotedCropMate(this);
}
}

View file

@ -27,6 +27,7 @@
*/
package mage.cards.d;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
@ -47,8 +48,6 @@ import mage.players.Player;
import mage.target.common.TargetCardInGraveyard;
import mage.util.functions.ApplyToPermanent;
import java.util.UUID;
/**
*
* @author jeffwadsworth
@ -110,7 +109,7 @@ class DimirDoppelgangerEffect extends OneShotEffect {
newBluePrint = new PermanentCard((Card) copyFromCard, source.getControllerId(), game);
newBluePrint.assignNewId();
ApplyToPermanent applier = new DimirDoppelgangerApplier();
applier.apply(game, newBluePrint);
applier.apply(game, newBluePrint, source, dimirDoppelganger.getId());
CopyEffect copyEffect = new CopyEffect(Duration.Custom, newBluePrint, dimirDoppelganger.getId());
copyEffect.newId();
copyEffect.setApplier(applier);
@ -127,7 +126,7 @@ class DimirDoppelgangerEffect extends OneShotEffect {
class DimirDoppelgangerApplier extends ApplyToPermanent {
@Override
public boolean apply(Game game, Permanent permanent) {
public boolean apply(Game game, Permanent permanent, Ability source, UUID copyToObjectId) {
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DimirDoppelgangerEffect(), new ManaCostsImpl("{1}{U}{B}"));
ability.addTarget(new TargetCardInGraveyard(new FilterCreatureCard("creature card in a graveyard")));
permanent.getAbilities().add(ability);
@ -135,7 +134,7 @@ class DimirDoppelgangerApplier extends ApplyToPermanent {
}
@Override
public boolean apply(Game game, MageObject mageObject) {
public boolean apply(Game game, MageObject mageObject, Ability source, UUID copyToObjectId) {
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DimirDoppelgangerEffect(), new ManaCostsImpl("{1}{U}{B}"));
ability.addTarget(new TargetCardInGraveyard(new FilterCreatureCard("creature card in a graveyard")));
mageObject.getAbilities().add(ability);

View file

@ -25,29 +25,22 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.d;
import java.util.UUID;
import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect;
import mage.abilities.effects.common.discard.DiscardTargetEffect;
import mage.cards.CardSetInfo;
import mage.cards.SplitCard;
import mage.constants.CardType;
import mage.constants.SpellAbilityType;
import mage.target.TargetPlayer;
import mage.target.common.TargetCardInYourGraveyard;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public class DownDirty extends SplitCard {
public DownDirty(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{3}{B}","{2}{G}",true);
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{B}", "{2}{G}", SpellAbilityType.SPLIT_FUSED);
// Down
// Target player discards two cards.

View file

@ -25,11 +25,11 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.d;
import java.util.Set;
import java.util.UUID;
import mage.abilities.Ability;
import mage.constants.ComparisonType;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DestroyAllEffect;
@ -39,7 +39,9 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.SplitCard;
import mage.constants.CardType;
import mage.constants.ComparisonType;
import mage.constants.Outcome;
import mage.constants.SpellAbilityType;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.common.FilterCreatureCard;
@ -48,23 +50,16 @@ import mage.filter.predicate.mageobject.PowerPredicate;
import mage.game.Game;
import mage.players.Player;
import java.util.Set;
import java.util.UUID;
/**
*
* @author stravant
*/
public class DuskDawn extends SplitCard {
private static final FilterCreaturePermanent filterCreatures3orGreater = new FilterCreaturePermanent("creatures with power greater than or equal to 3");
static {
filterCreatures3orGreater.add(new PowerPredicate(ComparisonType.MORE_THAN, 2));
}
public DuskDawn(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{2}{W}{W}","{3}{W}{W}",false);
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, new CardType[]{CardType.SORCERY}, "{2}{W}{W}", "{3}{W}{W}", SpellAbilityType.SPLIT_AFTERMATH);
// Dusk
// Destroy all creatures with power 3 or greater.
@ -74,7 +69,7 @@ public class DuskDawn extends SplitCard {
// Dawn
// Return all creature cards with power less than or equal to 2 from your graveyard to your hand.
((CardImpl)(getRightHalfCard())).addAbility(new AftermathAbility());
((CardImpl) (getRightHalfCard())).addAbility(new AftermathAbility());
getRightHalfCard().getSpellAbility().addEffect(new DawnEffect());
}
@ -92,6 +87,7 @@ public class DuskDawn extends SplitCard {
class DawnEffect extends OneShotEffect {
private static final FilterCard filter2orLess = new FilterCreatureCard("creatures with power less than or equal to 2");
static {
filter2orLess.add(new PowerPredicate(ComparisonType.FEWER_THAN, 3));
}

View file

@ -33,7 +33,6 @@ import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount;
import mage.abilities.effects.common.continuous.SetPowerSourceEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.TrampleAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
@ -59,7 +58,7 @@ public class EnigmaDrake extends CardImpl {
// Enigma Drakes's power is equal to the number of instant and sorcery cards in your graveyard.
this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetPowerSourceEffect(
new CardsInControllerGraveyardCount(new FilterInstantOrSorceryCard("instant and sorcery cards in your graveyard")), Duration.EndOfGame)));
new CardsInControllerGraveyardCount(new FilterInstantOrSorceryCard("instant and sorcery cards")), Duration.EndOfGame)));
}
public EnigmaDrake(final EnigmaDrake card) {

View file

@ -27,6 +27,7 @@
*/
package mage.cards.e;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
@ -49,8 +50,6 @@ import mage.game.permanent.Permanent;
import mage.target.common.TargetCreaturePermanent;
import mage.util.functions.ApplyToPermanent;
import java.util.UUID;
/**
*
* @author BetaSteward
@ -58,7 +57,7 @@ import java.util.UUID;
public class EvilTwin extends CardImpl {
public EvilTwin(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{U}{B}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}{B}");
this.subtype.add("Shapeshifter");
this.power = new MageInt(0);
@ -90,7 +89,7 @@ class EvilTwinApplyToPermanent extends ApplyToPermanent {
}
@Override
public boolean apply(Game game, Permanent permanent) {
public boolean apply(Game game, Permanent permanent, Ability source, UUID copyToObjectId) {
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DestroyTargetEffect(), new ManaCostsImpl("{U}{B}"));
ability.addCost(new TapSourceCost());
ability.addTarget(new TargetCreaturePermanent(filter));
@ -99,7 +98,7 @@ class EvilTwinApplyToPermanent extends ApplyToPermanent {
}
@Override
public boolean apply(Game game, MageObject mageObject) {
public boolean apply(Game game, MageObject mageObject, Ability source, UUID copyToObjectId) {
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DestroyTargetEffect(), new ManaCostsImpl("{U}{B}"));
ability.addCost(new TapSourceCost());
ability.addTarget(new TargetCreaturePermanent(filter));

View file

@ -29,22 +29,18 @@ package mage.cards.f;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.DiscardSourceCost;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.game.Game;
import mage.target.common.TargetCardInGraveyard;
import java.util.UUID;
import mage.abilities.effects.common.ExileTargetEffect;
/**
*
@ -53,7 +49,7 @@ import java.util.UUID;
public class FaerieMacabre extends CardImpl {
public FaerieMacabre(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{B}{B}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}{B}");
this.subtype.add("Faerie");
this.subtype.add("Rogue");
@ -63,7 +59,7 @@ public class FaerieMacabre extends CardImpl {
// Flying
this.addAbility(FlyingAbility.getInstance());
// Discard Faerie Macabre: Exile up to two target cards from graveyards.
Ability ability = new SimpleActivatedAbility(Zone.HAND, new FaerieMacabreExileTargetEffect(), new DiscardSourceCost());
Ability ability = new SimpleActivatedAbility(Zone.HAND, new ExileTargetEffect(), new DiscardSourceCost());
ability.addTarget(new TargetCardInGraveyard(0, 2, new FilterCard("cards from graveyards")));
this.addAbility(ability);
}
@ -77,35 +73,3 @@ public class FaerieMacabre extends CardImpl {
return new FaerieMacabre(this);
}
}
class FaerieMacabreExileTargetEffect extends OneShotEffect {
public FaerieMacabreExileTargetEffect() {
super(Outcome.Exile);
}
public FaerieMacabreExileTargetEffect(final FaerieMacabreExileTargetEffect effect) {
super(effect);
}
@Override
public FaerieMacabreExileTargetEffect copy() {
return new FaerieMacabreExileTargetEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
for(UUID uuid : source.getTargets().get(0).getTargets()){
Card card = game.getCard(uuid);
if (card != null) {
card.moveToExile(null, "Faerie Macabre", source.getSourceId(), game);
}
}
return true;
}
@Override
public String getText(Mode mode) {
return "Exile up to two target cards from graveyards";
}
}

View file

@ -27,7 +27,13 @@
*/
package mage.cards.f;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.NameACardEffect;
import mage.abilities.effects.common.ReturnToHandTargetEffect;
import mage.abilities.keyword.AftermathAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@ -35,16 +41,11 @@ import mage.cards.SplitCard;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.SpellAbilityType;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.target.TargetSpell;
import mage.abilities.effects.common.ReturnToHandTargetEffect;
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
import mage.MageObject;
import mage.game.events.GameEvent.EventType;
import mage.abilities.effects.common.NameACardEffect;
import java.util.UUID;
import mage.target.TargetSpell;
/**
* @author spjspj
@ -52,7 +53,7 @@ import java.util.UUID;
public class FailureComply extends SplitCard {
public FailureComply(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, new CardType[]{CardType.SORCERY}, "{1}{U}", "{W}", false);
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, new CardType[]{CardType.SORCERY}, "{1}{U}", "{W}", SpellAbilityType.SPLIT_AFTERMATH);
// Failure
// Return target spell to it's owner's hand
@ -63,7 +64,9 @@ public class FailureComply extends SplitCard {
// Comply
// Choose a card name. Until your next turn, your opponents can't cast spells with the chosen name
((CardImpl) (getRightHalfCard())).addAbility(new AftermathAbility());
getRightHalfCard().getSpellAbility().addEffect(new NameACardEffect(NameACardEffect.TypeOfName.ALL));
Effect effect = new NameACardEffect(NameACardEffect.TypeOfName.ALL);
effect.setText("Choose a card name");
getRightHalfCard().getSpellAbility().addEffect(effect);
getRightHalfCard().getSpellAbility().addEffect(new ComplyCantCastEffect());
}
@ -81,7 +84,7 @@ class ComplyCantCastEffect extends ContinuousRuleModifyingEffectImpl {
public ComplyCantCastEffect() {
super(Duration.UntilYourNextTurn, Outcome.Benefit);
staticText = "Your opponents can't cast spells with the chosen name";
staticText = "Until your next turn, your opponents can't cast spells with the chosen name";
}
public ComplyCantCastEffect(final ComplyCantCastEffect effect) {

View file

@ -56,9 +56,9 @@ public class FamishedGhoul extends CardImpl {
this.toughness = new MageInt(2);
// {1}{B}, Sacrifice Famished Ghoul: Exile up to two target cards from a single graveyard.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ExileTargetEffect("Exile up to two target cards from a single graveyard"), new ManaCostsImpl("{1}{B}"));
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ExileTargetEffect(), new ManaCostsImpl("{1}{B}"));
ability.addCost(new SacrificeSourceCost());
ability.addTarget(new TargetCardInASingleGraveyard(0, 2, new FilterCard()));
ability.addTarget(new TargetCardInASingleGraveyard(0, 2, new FilterCard("cards from a single graveyard")));
this.addAbility(ability);
}

View file

@ -25,30 +25,23 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.f;
import java.util.UUID;
import mage.abilities.effects.common.ReturnToHandTargetEffect;
import mage.abilities.effects.common.SacrificeEffect;
import mage.cards.CardSetInfo;
import mage.cards.SplitCard;
import mage.constants.CardType;
import mage.constants.SpellAbilityType;
import mage.filter.common.FilterCreaturePermanent;
import mage.target.TargetPlayer;
import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public class FarAway extends SplitCard {
public FarAway(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{U}","{2}{B}",true);
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}", "{2}{B}", SpellAbilityType.SPLIT_FUSED);
// Far
// Return target creature to its owner's hand.

View file

@ -25,9 +25,9 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.f;
import java.util.UUID;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.DamageMultiEffect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
@ -35,21 +35,14 @@ import mage.abilities.effects.common.TapTargetEffect;
import mage.cards.CardSetInfo;
import mage.cards.SplitCard;
import mage.constants.CardType;
import mage.constants.SpellAbilityType;
import mage.target.TargetPermanent;
import mage.target.common.TargetCreatureOrPlayerAmount;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public class FireIce extends SplitCard {
public FireIce(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{R}","{1}{U}",false);
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{R}", "{1}{U}", SpellAbilityType.SPLIT);
// Fire
// Fire deals 2 damage divided as you choose among one or two target creatures and/or players.

View file

@ -25,9 +25,9 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.f;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
@ -35,6 +35,7 @@ import mage.cards.CardSetInfo;
import mage.cards.SplitCard;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SpellAbilityType;
import mage.constants.Zone;
import mage.counters.CounterType;
import mage.filter.common.FilterCreatureCard;
@ -47,18 +48,10 @@ import mage.target.common.TargetControlledCreaturePermanent;
import mage.target.common.TargetCreatureOrPlayer;
import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public class FleshBlood extends SplitCard {
public FleshBlood(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{3}{B}{G}","{R}{G}",true);
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{B}{G}", "{R}{G}", SpellAbilityType.SPLIT_FUSED);
// Flesh
// Exile target creature card from a graveyard. Put X +1/+1 counters on target creature, where X is the power of the card you exiled.
@ -90,7 +83,7 @@ class FleshEffect extends OneShotEffect {
public FleshEffect() {
super(Outcome.BoostCreature);
staticText = "Exile target creature card from a graveyard. Put X +1/+1 counters on target creature, where X is the power of the card you exiled";
}
}
public FleshEffect(final FleshEffect effect) {
super(effect);
@ -125,7 +118,7 @@ class BloodEffect extends OneShotEffect {
public BloodEffect() {
super(Outcome.Damage);
staticText = "Target creature you control deals damage equal to its power to target creature or player";
}
}
public BloodEffect(final BloodEffect effect) {
super(effect);

View file

@ -0,0 +1,160 @@
/*
* 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.cards.g;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility;
import mage.abilities.condition.common.CardsInControllerGraveCondition;
import mage.abilities.costs.common.SacrificeSourceCost;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.decorator.ConditionalActivatedAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DrawDiscardControllerEffect;
import mage.abilities.effects.common.GainLifeEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.TargetController;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.common.FilterCreatureCard;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.NamePredicate;
import mage.filter.predicate.permanent.ControllerPredicate;
import mage.filter.predicate.permanent.TokenPredicate;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetCardInHand;
import mage.target.common.TargetCardInLibrary;
import mage.target.common.TargetCardInYourGraveyard;
/**
*
* @author LevelX2
*/
public class GateToTheAfterlife extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("a nontoken creature you control");
static {
filter.add(new ControllerPredicate(TargetController.YOU));
filter.add(Predicates.not(new TokenPredicate()));
}
public GateToTheAfterlife(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}");
// Whenever a nontoken creature you control dies, you gain 1 life. Then you may draw a card. If you do, discard a card.
Ability ability = new EntersBattlefieldControlledTriggeredAbility(Zone.BATTLEFIELD, new GainLifeEffect(1), filter, false);
Effect effect = new DrawDiscardControllerEffect(1, 1, true);
effect.setText("Then you may draw a card. If you do, discard a card");
ability.addEffect(effect);
this.addAbility(ability);
// {2}, {T}, Sacrifice Gate to the Afterlife: Search your graveyard, hand, and/or library for a card named God-Pharaoh's Gift and put it onto the battlefield. If you seearch your library this way, shuffle it. Activate this ability only if there are six or more creature cards in your graveyard.
ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD,
new GateToTheAfterlifeEffect(), new GenericManaCost(2), new CardsInControllerGraveCondition(6, new FilterCreatureCard()));
ability.addCost(new TapSourceCost());
ability.addCost(new SacrificeSourceCost());
ability.addEffect(effect);
this.addAbility(ability);
}
public GateToTheAfterlife(final GateToTheAfterlife card) {
super(card);
}
@Override
public GateToTheAfterlife copy() {
return new GateToTheAfterlife(this);
}
}
class GateToTheAfterlifeEffect extends OneShotEffect {
static private String cardName = "God-Pharaoh's Gift";
public GateToTheAfterlifeEffect() {
super(Outcome.Benefit);
this.staticText = "Search your graveyard, hand, and/or library for a card named "
+ cardName
+ " and put it onto the battlefield. If you search your library this way, shuffle it";
}
public GateToTheAfterlifeEffect(final GateToTheAfterlifeEffect effect) {
super(effect);
}
@Override
public GateToTheAfterlifeEffect copy() {
return new GateToTheAfterlifeEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller == null) {
return false;
}
FilterCard filter = new FilterCard("card named " + cardName);
filter.add(new NamePredicate(cardName));
Card card = null;
// Graveyard check
if (controller.chooseUse(Outcome.Benefit, "Do you want to search your graveyard for " + cardName + "?", source, game)) {
TargetCardInYourGraveyard target = new TargetCardInYourGraveyard(filter);
if (controller.choose(Outcome.PutCardInPlay, controller.getGraveyard(), target, game)) {
card = game.getCard(target.getFirstTarget());
}
}
// Hand check
if (card == null && controller.chooseUse(Outcome.Benefit, "Do you want to search your hand for " + cardName + "?", source, game)) {
TargetCardInHand target = new TargetCardInHand(filter);
if (controller.choose(Outcome.PutCardInPlay, controller.getHand(), target, game)) {
card = game.getCard(target.getFirstTarget());
}
}
// Library check
if (card == null && controller.chooseUse(Outcome.Benefit, "Do you want to search your library for " + cardName + "?", source, game)) {
TargetCardInLibrary target = new TargetCardInLibrary(filter);
if (controller.searchLibrary(target, game)) {
card = game.getCard(target.getFirstTarget());
}
controller.shuffleLibrary(source, game);
}
if (card != null) {
controller.moveCards(card, Zone.BATTLEFIELD, source, game);
}
return true;
}
}

View file

@ -34,8 +34,6 @@ import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.GetEmblemEffect;
@ -48,7 +46,6 @@ import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.common.FilterPlaneswalkerPermanent;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.filter.predicate.permanent.ControllerPredicate;
import mage.game.Game;
import mage.game.command.Emblem;
import mage.game.events.GameEvent;
@ -63,20 +60,22 @@ public class GideonOfTheTrials extends CardImpl {
public GideonOfTheTrials(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{1}{W}{W}");
this.subtype.add("Gideon");
//Starting Loyalty: 3
this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(3));
// +1: Until your next turn, prevent all damage target permanent would deal.
LoyaltyAbility ability = new LoyaltyAbility(new PreventDamageByTargetEffect(Duration.UntilYourNextTurn), 1);
Effect effect = new PreventDamageByTargetEffect(Duration.UntilYourNextTurn);
effect.setText("Until your next turn, prevent all damage target permanent would deal");
LoyaltyAbility ability = new LoyaltyAbility(effect, 1);
ability.addTarget(new TargetPermanent());
this.addAbility(ability);
// 0: Until end of turn, Gideon of the Trials becomes a 4/4 Human Soldier creature with indestructible that's still a planeswalker. Prevent all damage that would be dealt to him this turn.
ability = new LoyaltyAbility(new BecomesCreatureSourceEffect(new GideonOfTheTrialsToken(), "planeswalker", Duration.EndOfTurn), 0);
Effect effect = new PreventAllDamageToSourceEffect(Duration.EndOfTurn);
effect = new PreventAllDamageToSourceEffect(Duration.EndOfTurn);
effect.setText("Prevent all damage that would be dealt to him this turn");
ability.addEffect(effect);
this.addAbility(ability);
@ -106,7 +105,7 @@ class GideonOfTheTrialsCantLoseEffect extends ContinuousRuleModifyingEffectImpl
public GideonOfTheTrialsCantLoseEffect() {
super(Duration.EndOfGame, Outcome.Benefit);
staticText = "As long as you control a Gideon planeswalker, you can't lose the game and your opponent can't win the game";
staticText = "As long as you control a Gideon planeswalker, you can't lose the game and your opponents can't win the game";
}
public GideonOfTheTrialsCantLoseEffect(final GideonOfTheTrialsCantLoseEffect effect) {

View file

@ -33,6 +33,7 @@ import mage.abilities.Ability;
import mage.abilities.common.AsEntersBattlefieldAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.PreventionEffectImpl;
import mage.abilities.effects.common.NameACardEffect;
import mage.cards.CardImpl;
@ -56,7 +57,9 @@ public class GideonsIntervention extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}{W}");
// As Gideon's Intervention enters the battlefield, choose a card name.
this.addAbility(new AsEntersBattlefieldAbility(new NameACardEffect(NameACardEffect.TypeOfName.ALL)));
Effect effect = new NameACardEffect(NameACardEffect.TypeOfName.ALL);
effect.setText("choose a card name");
this.addAbility(new AsEntersBattlefieldAbility(effect));
// Your opponents can't cast spells with the chosen name.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GideonsInterventionCantCastEffect()));

View file

@ -27,6 +27,7 @@
*/
package mage.cards.g;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
@ -49,8 +50,6 @@ import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.util.functions.ApplyToPermanent;
import java.util.UUID;
/**
*
* @author fireshoes
@ -58,7 +57,7 @@ import java.util.UUID;
public class Gigantoplasm extends CardImpl {
public Gigantoplasm(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{U}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}");
this.subtype.add("Shapeshifter");
this.power = new MageInt(0);
this.toughness = new MageInt(0);
@ -82,7 +81,7 @@ public class Gigantoplasm extends CardImpl {
class GigantoplasmApplyToPermanent extends ApplyToPermanent {
@Override
public boolean apply(Game game, Permanent permanent) {
public boolean apply(Game game, Permanent permanent, Ability source, UUID copyToObjectId) {
DynamicValue variableMana = new ManacostVariableValue();
Effect effect = new SetPowerToughnessSourceEffect(variableMana, Duration.WhileOnBattlefield, SubLayer.SetPT_7b);
effect.setText("This creature has base power and toughness X/X");
@ -92,7 +91,7 @@ class GigantoplasmApplyToPermanent extends ApplyToPermanent {
}
@Override
public boolean apply(Game game, MageObject mageObject) {
public boolean apply(Game game, MageObject mageObject, Ability source, UUID copyToObjectId) {
DynamicValue variableMana = new ManacostVariableValue();
Effect effect = new SetPowerToughnessSourceEffect(variableMana, Duration.WhileOnBattlefield, SubLayer.SetPT_7b);
effect.setText("This creature has base power and toughness X/X");

View file

@ -27,6 +27,7 @@
*/
package mage.cards.g;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
@ -34,6 +35,7 @@ import mage.cards.CardSetInfo;
import mage.cards.SplitCard;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SpellAbilityType;
import mage.counters.CounterType;
import mage.game.Game;
import mage.game.permanent.Permanent;
@ -41,8 +43,6 @@ import mage.players.Player;
import mage.target.common.TargetControlledCreaturePermanent;
import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
/**
*
* @author LevelX2
@ -50,7 +50,7 @@ import java.util.UUID;
public class GiveTake extends SplitCard {
public GiveTake(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{2}{G}","{2}{U}",true);
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{G}", "{2}{U}", SpellAbilityType.SPLIT_FUSED);
// Give
// Put three +1/+1 counters on target creature.

View file

@ -52,7 +52,7 @@ import mage.target.targetpointer.FixedTarget;
public class HarshMentor extends CardImpl {
public HarshMentor(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "1{R}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}");
this.subtype.add("Human");
this.subtype.add("Cleric");

View file

@ -30,18 +30,27 @@ package mage.cards.h;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.costs.common.SacrificeTargetCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.dynamicvalue.common.SacrificeCostCreaturesPower;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.effects.common.DoIfCostPaid;
import mage.abilities.effects.common.InfoEffect;
import mage.abilities.effects.common.SendOptionUsedEventEffect;
import mage.abilities.keyword.EmbalmAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.permanent.AnotherPredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.Target;
import mage.target.common.TargetControlledCreaturePermanent;
import mage.target.common.TargetCreatureOrPlayer;
@ -51,12 +60,6 @@ import mage.target.common.TargetCreatureOrPlayer;
*/
public class HeartPiercerManticore extends CardImpl {
private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another creature");
static {
filter.add(new AnotherPredicate());
}
public HeartPiercerManticore(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}{R}");
@ -65,12 +68,12 @@ public class HeartPiercerManticore extends CardImpl {
this.toughness = new MageInt(3);
// When Heart-Piercer Manticore enters the battlefield, you may sacrifice another creature.
Ability firstAbility = new EntersBattlefieldTriggeredAbility(new HeartPiercerManticoreSacrificeEffect(), true);
this.addAbility(firstAbility);
// When you do, Heart-Piercer Manticore deals damage equal to that creature's power to target creature or player.
Ability ability = new EntersBattlefieldTriggeredAbility(new DoIfCostPaid(new DamageTargetEffect(new SacrificeCostCreaturesPower()),
new SacrificeTargetCost(new TargetControlledCreaturePermanent(filter))), true);
ability.addTarget(new TargetCreatureOrPlayer());
this.addAbility(ability);
Ability secondAbility = new HeartPiercerManticoreSacrificeTriggeredAbility(firstAbility.getOriginalId());
secondAbility.addTarget(new TargetCreatureOrPlayer());
this.addAbility(secondAbility);
// Embalm {5}{R}
this.addAbility(new EmbalmAbility(new ManaCostsImpl("{5}{R}"), this));
@ -85,3 +88,85 @@ public class HeartPiercerManticore extends CardImpl {
return new HeartPiercerManticore(this);
}
}
class HeartPiercerManticoreSacrificeEffect extends OneShotEffect {
private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another creature");
static {
filter.add(new AnotherPredicate());
}
public HeartPiercerManticoreSacrificeEffect() {
super(Outcome.Damage);
this.staticText = "you may sacrifice another creature";
}
public HeartPiercerManticoreSacrificeEffect(final HeartPiercerManticoreSacrificeEffect effect) {
super(effect);
}
@Override
public HeartPiercerManticoreSacrificeEffect copy() {
return new HeartPiercerManticoreSacrificeEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
Target target = new TargetControlledCreaturePermanent(1, 1, filter, true);
if (controller.choose(outcome, target, source.getSourceId(), game)) {
Permanent toSacrifice = game.getPermanent(target.getFirstTarget());
if (toSacrifice != null) {
toSacrifice.sacrifice(source.getSourceId(), game);
return new SendOptionUsedEventEffect(toSacrifice.getPower().getValue()).apply(game, source);
}
}
return true;
}
return false;
}
}
class HeartPiercerManticoreSacrificeTriggeredAbility extends TriggeredAbilityImpl {
private final UUID relatedTriggerdAbilityOriginalId;
public HeartPiercerManticoreSacrificeTriggeredAbility(UUID relatedTriggerdAbilityOriginalId) {
super(Zone.BATTLEFIELD, new InfoEffect("{this} deals damage equal to that creature's power to target creature or player"));
this.relatedTriggerdAbilityOriginalId = relatedTriggerdAbilityOriginalId;
}
public HeartPiercerManticoreSacrificeTriggeredAbility(final HeartPiercerManticoreSacrificeTriggeredAbility ability) {
super(ability);
this.relatedTriggerdAbilityOriginalId = ability.relatedTriggerdAbilityOriginalId;
}
@Override
public HeartPiercerManticoreSacrificeTriggeredAbility copy() {
return new HeartPiercerManticoreSacrificeTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == EventType.OPTION_USED;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (event.getPlayerId().equals(this.getControllerId())
&& event.getTargetId().equals(relatedTriggerdAbilityOriginalId)
&& event.getSourceId().equals(getSourceId())) {
getEffects().clear();
getEffects().add(new DamageTargetEffect(event.getAmount()));
return true;
}
return false;
}
@Override
public String getRule() {
return "When you do, {this} deals damage equal to that creature's power to target creature or player.";
}
}

View file

@ -9,6 +9,7 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.SplitCard;
import mage.constants.CardType;
import mage.constants.SpellAbilityType;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.AbilityPredicate;
@ -28,7 +29,7 @@ public class HeavenEarth extends SplitCard {
}
public HeavenEarth(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, new CardType[]{CardType.SORCERY}, "{X}{G}", "{X}{R}{R}", false);
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, new CardType[]{CardType.SORCERY}, "{X}{G}", "{X}{R}{R}", SpellAbilityType.SPLIT_AFTERMATH);
// Falling
// Falling deals X damage to each creature with flying.

View file

@ -25,7 +25,6 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.h;
import java.util.UUID;
@ -37,6 +36,7 @@ import mage.cards.CardSetInfo;
import mage.cards.SplitCard;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SpellAbilityType;
import mage.constants.Zone;
import mage.filter.common.FilterArtifactOrEnchantmentPermanent;
import mage.game.Game;
@ -52,7 +52,7 @@ import mage.target.common.TargetOpponent;
public class HideSeek extends SplitCard {
public HideSeek(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{R}{W}","{W}{B}",false);
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{R}{W}", "{W}{B}", SpellAbilityType.SPLIT);
// Hide
// Put target artifact or enchantment on the bottom of its owner's library.

View file

@ -37,6 +37,7 @@ import mage.cards.SplitCard;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.SpellAbilityType;
import mage.filter.common.FilterAttackingCreature;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.predicate.Predicates;
@ -55,7 +56,7 @@ import mage.target.targetpointer.FixedTarget;
public class HitRun extends SplitCard {
public HitRun(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{B}{R}","{3}{R}{G}",false);
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{B}{R}", "{3}{R}{G}", SpellAbilityType.SPLIT);
// Hit
// Target player sacrifices an artifact or creature. Hit deals damage to that player equal to that permanent's converted mana cost.

View file

@ -52,8 +52,7 @@ public class HoodedBrawler extends CardImpl {
this.toughness = new MageInt(2);
// You may exert Hooded Brawler as it attacks. When you do, it gets +2/+2 until end of turn.
BecomesExertSourceTriggeredAbility ability = new BecomesExertSourceTriggeredAbility(new BoostSourceEffect(2, 2, Duration.EndOfTurn));
this.addAbility(new ExertAbility(ability));
this.addAbility(new ExertAbility(new BecomesExertSourceTriggeredAbility(new BoostSourceEffect(2, 2, Duration.EndOfTurn))));
}
public HoodedBrawler(final HoodedBrawler card) {

View file

@ -34,6 +34,7 @@ import mage.cards.CardSetInfo;
import mage.cards.SplitCard;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SpellAbilityType;
import mage.target.Target;
import mage.target.common.TargetArtifactPermanent;
import mage.target.common.TargetSpellOrPermanent;
@ -42,11 +43,10 @@ import mage.target.common.TargetSpellOrPermanent;
*
* @author LevelX2
*/
public class IllusionReality extends SplitCard {
public IllusionReality(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{U}","{2}{G}",false);
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{U}", "{2}{G}", SpellAbilityType.SPLIT);
// Illusion
// Target spell or permanent becomes the color of your choice until end of turn.

View file

@ -1,10 +1,9 @@
package mage.cards.i;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.dynamicvalue.common.ManacostVariableValue;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.abilities.effects.common.LoseLifeOpponentsEffect;
import mage.abilities.effects.common.continuous.DamageCantBePreventedEffect;
import mage.abilities.keyword.AftermathAbility;
import mage.cards.CardImpl;
@ -13,9 +12,7 @@ import mage.cards.SplitCard;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.filter.Filter;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.mageobject.PowerPredicate;
import mage.constants.SpellAbilityType;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
@ -23,14 +20,13 @@ import mage.players.Player;
import mage.target.TargetPlayer;
import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
/**
* @author Stravant
*/
public class InsultInjury extends SplitCard {
public InsultInjury(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{2}{R}","{2}{R}",false);
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, new CardType[]{CardType.SORCERY}, "{2}{R}", "{2}{R}", SpellAbilityType.SPLIT_AFTERMATH);
// Insult
// Damage can't be prevented this turn. If a source you control would deal damage this turn it deals
@ -39,7 +35,6 @@ public class InsultInjury extends SplitCard {
getLeftHalfCard().getSpellAbility().addEffect(new InsultDoubleDamageEffect());
// to
// Injury
// Injury deals 2 damage to target creature and 2 damage to target player.
((CardImpl) (getRightHalfCard())).addAbility(new AftermathAbility());
@ -59,6 +54,7 @@ public class InsultInjury extends SplitCard {
}
class InsultDoubleDamageEffect extends ReplacementEffectImpl {
public InsultDoubleDamageEffect() {
super(Duration.EndOfTurn, Outcome.Damage);
staticText = "If a source you control would deal damage this turn, it deals double that damage to that creature or player instead.";
@ -98,6 +94,7 @@ class InsultDoubleDamageEffect extends ReplacementEffectImpl {
}
class InjuryEffect extends OneShotEffect {
InjuryEffect() {
super(Outcome.Damage);
this.staticText = "{this} deals 2 damage to target creature and 2 damage to target player";
@ -127,4 +124,4 @@ class InjuryEffect extends OneShotEffect {
public InjuryEffect copy() {
return new InjuryEffect(this);
}
}
}

View file

@ -109,7 +109,7 @@ class LazavDimirMastermindEffect extends OneShotEffect {
newBluePrint = new PermanentCard((Card) copyFromCard, source.getControllerId(), game);
newBluePrint.assignNewId();
ApplyToPermanent applier = new LazavDimirMastermindApplier();
applier.apply(game, newBluePrint);
applier.apply(game, newBluePrint, source, lazavDimirMastermind.getId());
CopyEffect copyEffect = new CopyEffect(Duration.Custom, newBluePrint, lazavDimirMastermind.getId());
copyEffect.newId();
copyEffect.setApplier(applier);
@ -126,7 +126,7 @@ class LazavDimirMastermindEffect extends OneShotEffect {
class LazavDimirMastermindApplier extends ApplyToPermanent {
@Override
public boolean apply(Game game, Permanent permanent) {
public boolean apply(Game game, Permanent permanent, Ability source, UUID copyToObjectId) {
Ability ability = new PutCardIntoGraveFromAnywhereAllTriggeredAbility(
new LazavDimirMastermindEffect(), true,
new FilterCreatureCard("a creature card"),
@ -139,7 +139,7 @@ class LazavDimirMastermindApplier extends ApplyToPermanent {
}
@Override
public boolean apply(Game game, MageObject mageObject) {
public boolean apply(Game game, MageObject mageObject, Ability source, UUID copyToObjectId) {
Ability ability = new PutCardIntoGraveFromAnywhereAllTriggeredAbility(
new LazavDimirMastermindEffect(), true,
new FilterCreatureCard("a creature card"),

View file

@ -38,6 +38,7 @@ import mage.cards.SplitCard;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.SpellAbilityType;
import mage.constants.Zone;
import mage.filter.common.FilterControlledLandPermanent;
import mage.filter.common.FilterCreatureCard;
@ -54,7 +55,7 @@ import mage.target.common.TargetCardInYourGraveyard;
public class LifeDeath extends SplitCard {
public LifeDeath(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{G}","{1}{B}",false);
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{G}", "{1}{B}", SpellAbilityType.SPLIT);
// Life
// All lands you control become 1/1 creatures until end of turn. They're still lands.

View file

@ -53,20 +53,27 @@ public class ManticoreOfTheGauntlet extends CardImpl {
public ManticoreOfTheGauntlet(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{R}");
this.subtype.add("Manticore");
this.power = new MageInt(5);
this.toughness = new MageInt(4);
// When Manticore of the Gauntlet enters the battlefield, put a -1/-1 counter on target creature you control. Manticore of the Gauntlet deals 3 damage to target opponent.
Effect counters = new AddCountersTargetEffect(CounterType.M1M1.createInstance(), new StaticValue(1));
Effect counters = new AddCountersTargetEffect(CounterType.M1M1.createInstance());
counters.setText("put a -1/-1 counter on target creature you control");
counters.setTargetPointer(new FirstTargetPointer());
Ability ability = new EntersBattlefieldTriggeredAbility(counters);
Effect damage = new DamageTargetEffect(new StaticValue(3), true, "", true);
damage.setText("{this} deals 3 damage to target opponent.");
damage.setTargetPointer(new SecondTargetPointer());
Ability ability = new EntersBattlefieldTriggeredAbility(counters);
ability.addEffect(damage);
ability.addTarget(new TargetControlledCreaturePermanent());
ability.addTarget(new TargetOpponent());
addAbility(ability);
this.addAbility(ability);
}
public ManticoreOfTheGauntlet(final ManticoreOfTheGauntlet card) {
@ -77,4 +84,4 @@ public class ManticoreOfTheGauntlet extends CardImpl {
public ManticoreOfTheGauntlet copy() {
return new ManticoreOfTheGauntlet(this);
}
}
}

View file

@ -69,7 +69,9 @@ public class MercilessJavelineer extends CardImpl {
new StaticValue(1),
Outcome.Removal),
new ManaCostsImpl("{2}"));
ability.addEffect(new CantBlockTargetEffect(Duration.EndOfTurn));
ability.addEffect(
new CantBlockTargetEffect(Duration.EndOfTurn)
.setText("That creature can't block this turn."));
ability.addCost(new DiscardCardCost());
ability.addTarget(new TargetCreaturePermanent());
addAbility(ability);

View file

@ -1,6 +1,6 @@
package mage.cards.m;
import mage.constants.ComparisonType;
import java.util.UUID;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.CreateTokenEffect;
@ -10,35 +10,36 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.SplitCard;
import mage.constants.CardType;
import mage.constants.ComparisonType;
import mage.constants.SpellAbilityType;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.mageobject.PowerPredicate;
import mage.game.permanent.token.HippoToken2;
import java.util.UUID;
/**
* @author Stravant
*/
public class MouthFeed extends SplitCard {
private static final FilterControlledCreaturePermanent filterCreaturesYouControlPower3orGreater
= new FilterControlledCreaturePermanent("creature you control with power 3 or greater.");
static {
filterCreaturesYouControlPower3orGreater.add(new PowerPredicate(ComparisonType.MORE_THAN, 2));
}
public MouthFeed(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{2}{G}","{3}{G}",false);
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, new CardType[]{CardType.SORCERY}, "{2}{G}", "{3}{G}", SpellAbilityType.SPLIT_AFTERMATH);
// Mouth
// Create a 3/3 green Hippo creature token
getLeftHalfCard().getSpellAbility().addEffect(new CreateTokenEffect(new HippoToken2()));
// to
// Feed
// Draw a card for each creature you control with power 3 or greater
((CardImpl) (getRightHalfCard())).addAbility(new AftermathAbility());
Effect draw = new DrawCardSourceControllerEffect(new PermanentsOnBattlefieldCount(filterCreaturesYouControlPower3orGreater));
Effect draw = new DrawCardSourceControllerEffect(new PermanentsOnBattlefieldCount(filterCreaturesYouControlPower3orGreater));
getRightHalfCard().getSpellAbility().addEffect(draw);
}
@ -51,4 +52,4 @@ public class MouthFeed extends SplitCard {
public MouthFeed copy() {
return new MouthFeed(this);
}
}
}

View file

@ -29,8 +29,9 @@ package mage.cards.n;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.LookLibraryAndPickControllerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@ -46,15 +47,15 @@ public class NagaOracle extends CardImpl {
public NagaOracle(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}");
this.subtype.add("Naga");
this.subtype.add("Cleric");
this.power = new MageInt(2);
this.toughness = new MageInt(4);
// When Naga Oracle enters the battlefield, look at the top three cards of your library. Put any number of them into your graveyard and the rest back on top of your library in any order.
addAbility(new EntersBattlefieldAbility(
new LookLibraryAndPickControllerEffect(
// When Naga Oracle enters the battlefield, look at the top three cards of your library. Put any number of them into your graveyard
// and the rest back on top of your library in any order.
Effect effect = new LookLibraryAndPickControllerEffect(
/* oh god, Microsoft looks conservative with their function parameters in comparison */
new StaticValue(3),
false,
@ -65,7 +66,10 @@ public class NagaOracle extends CardImpl {
false,
true,
Zone.GRAVEYARD,
false)));
false);
effect.setText("look at the top three cards of your library. Put any number of them into your graveyard "
+ "and the rest back on top of your library in any order");
addAbility(new EntersBattlefieldTriggeredAbility(effect));
}
public NagaOracle(final NagaOracle card) {

View file

@ -29,10 +29,14 @@ package mage.cards.n;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.BecomesExertSourceTriggeredAbility;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.abilities.keyword.ExertAbility;
import mage.abilities.keyword.TrampleAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
/**
*
@ -42,7 +46,7 @@ public class NefCropEntangler extends CardImpl {
public NefCropEntangler(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}");
this.subtype.add("Human");
this.subtype.add("Warrior");
this.power = new MageInt(2);
@ -52,6 +56,7 @@ public class NefCropEntangler extends CardImpl {
this.addAbility(TrampleAbility.getInstance());
// You may exert Nef-Crop Entangler as it attacks. When you do, it gets +1/+2 until end of turn.
this.addAbility(new ExertAbility(new BecomesExertSourceTriggeredAbility(new BoostSourceEffect(1, 2, Duration.EndOfTurn))));
}
public NefCropEntangler(final NefCropEntangler card) {

View file

@ -82,7 +82,7 @@ public class NehebTheWorthy extends CardImpl {
// As long as you have one or fewer cards in hand, Minotaurs you control get +2/+0.
Condition condition = new CardsInHandCondition(ComparisonType.FEWER_THAN, 2);
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(
new BoostControlledEffect(2, 0, Duration.WhileOnBattlefield, filter), condition, "As long as you have one or fewer cards in hand, Minotaurs you control gets +2/+0"));
new BoostControlledEffect(2, 0, Duration.WhileOnBattlefield, filter), condition, "As long as you have one or fewer cards in hand, Minotaurs you control get +2/+0"));
this.addAbility(ability);
// Whenever Neheb, the Worthy deals combat damage to a player, each player discards a card.

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