Merge pull request #2 from magefree/master

Update 10/9
This commit is contained in:
jmharmon 2018-10-09 20:08:21 -07:00 committed by GitHub
commit 4fca72e8e8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
766 changed files with 13082 additions and 3555 deletions

1
.gitignore vendored
View file

@ -91,6 +91,7 @@ Mage.Verify/AllCards.json.zip
Mage.Verify/AllSets.json.zip
Mage.Verify/AllCards.json
Mage.Verify/AllSets.json
/db
releases
Utils/author.txt

View file

@ -27,6 +27,7 @@
package mage.client.deckeditor.table;
import java.util.Comparator;
import mage.cards.MageCard;
import mage.view.CardView;
@ -94,8 +95,8 @@ public class MageCardComparator implements Comparator<CardView> {
break;
// Rarity
case 6:
aCom = a.getRarity().toString();
bCom = b.getRarity().toString();
aCom = a.getRarity().getSorting();
bCom = b.getRarity().getSorting();
break;
// Set name
case 7:

View file

@ -33,8 +33,8 @@ public final class Config {
static {
Properties p = new Properties();
try {
p.load(new FileInputStream(new File("config/config.properties")));
try(FileInputStream fis =new FileInputStream(new File("config/config.properties"))) {
p.load(fis);
} catch (IOException ex) {
logger.fatal("Config error ", ex);
}

View file

@ -1,14 +1,10 @@
package org.mage.plugins.card.dl.sources;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import mage.client.dialog.PreferencesDialog;
import org.mage.plugins.card.images.CardDownloadData;
import java.util.*;
/**
* @author Quercitron, JayDi85
*/
@ -129,7 +125,10 @@ public enum ScryfallImageSource implements CardImageSource {
supportedSets.add("WWK");
supportedSets.add("DDE");
supportedSets.add("ROE");
// duels of the planewalkers:
supportedSets.add("DPA");
supportedSets.add("DPAP");
//
supportedSets.add("ARC");
supportedSets.add("M11");
supportedSets.add("V10");
@ -231,6 +230,13 @@ public enum ScryfallImageSource implements CardImageSource {
supportedSets.add("M19");
supportedSets.add("GS1");
supportedSets.add("GRN");
supportedSets.add("GK1");
//
supportedSets.add("EURO");
supportedSets.add("GPX");
supportedSets.add("ATH");
supportedSets.add("GRC");
supportedSets.add("ANA");
}
@Override
@ -245,6 +251,24 @@ public enum ScryfallImageSource implements CardImageSource {
String baseUrl = null;
String alternativeUrl = null;
// direct links to images (non localization)
if (baseUrl == null) {
// set/card/number
String linkCode1 = card.getSet() + "/" + card.getName() + "/" + card.getCollectorId();
if (directDownloadLinks.containsKey(linkCode1)) {
baseUrl = directDownloadLinks.get(linkCode1);
alternativeUrl = null;
}
// set/card
String linkCode2 = card.getSet() + "/" + card.getName();
if (directDownloadLinks.containsKey(linkCode2)) {
baseUrl = directDownloadLinks.get(linkCode2);
alternativeUrl = null;
}
}
// special card number like "103a" already compatible
if (baseUrl == null && card.isCollectorIdWithStr()) {
baseUrl = "https://img.scryfall.com/cards/large/" + localizedCode + "/" + formatSetName(card.getSet()) + "/"
@ -330,6 +354,108 @@ public enum ScryfallImageSource implements CardImageSource {
put("MPS-AKH", "mp2");
put("MBP", "pmei");
put("WMCQ", "pwcq");
put("EURO", "pelp");
put("GPX", "pgpx");
}
};
private static final Map<String, String> directDownloadLinks = new HashMap<String, String>() {
{
// direct links to download images for special cards
// Duels of the Planeswalkers Promos -- xmage uses one set (DPAP), but scryfall store it by years
// 2009 - https://scryfall.com/sets/pdtp
put("DPAP/Garruk Wildspeaker", "https://img.scryfall.com/cards/large/en/pdtp/1.jpg");
// 2010 - https://scryfall.com/sets/pdp10
put("DPAP/Liliana Vess", "https://img.scryfall.com/cards/large/en/pdp10/1.jpg");
put("DPAP/Nissa Revane", "https://img.scryfall.com/cards/large/en/pdp10/2.jpg");
// 2011 - https://scryfall.com/sets/pdp11
put("DPAP/Frost Titan", "https://img.scryfall.com/cards/large/en/pdp11/1.jpg");
put("DPAP/Grave Titan", "https://img.scryfall.com/cards/large/en/pdp11/2.jpg");
put("DPAP/Inferno Titan", "https://img.scryfall.com/cards/large/en/pdp11/3.jpg");
// 2012 - https://scryfall.com/sets/pdp12
put("DPAP/Primordial Hydra", "https://img.scryfall.com/cards/large/en/pdp12/1.jpg");
put("DPAP/Serra Avatar", "https://img.scryfall.com/cards/large/en/pdp12/2.jpg");
put("DPAP/Vampire Nocturnus", "https://img.scryfall.com/cards/large/en/pdp12/3.jpg");
// 2013 - https://scryfall.com/sets/pdp13
put("DPAP/Bonescythe Sliver", "https://img.scryfall.com/cards/large/en/pdp13/1.jpg");
put("DPAP/Ogre Battledriver", "https://img.scryfall.com/cards/large/en/pdp13/2.jpg");
put("DPAP/Scavenging Ooze", "https://img.scryfall.com/cards/large/en/pdp13/3.jpg");
// 2014 - https://scryfall.com/sets/pdp14
put("DPAP/Soul of Ravnica", "https://img.scryfall.com/cards/large/en/pdp14/1.jpg");
put("DPAP/Soul of Zendikar", "https://img.scryfall.com/cards/large/en/pdp14/2.jpg");
// Gateway Promos -- xmage uses one set (GRC), but scryfall store it by years
// 2006 - https://scryfall.com/sets/pgtw
put("GRC/Fiery Temper", "https://img.scryfall.com/cards/large/en/pgtw/3.jpg");
put("GRC/Icatian Javelineers", "https://img.scryfall.com/cards/large/en/pgtw/2.jpg");
put("GRC/Wood Elves", "https://img.scryfall.com/cards/large/en/pgtw/1.jpg");
// 2007 - https://scryfall.com/sets/pg07
put("GRC/Boomerang", "https://img.scryfall.com/cards/large/en/pg07/4.jpg");
put("GRC/Calciderm", "https://img.scryfall.com/cards/large/en/pg07/5.jpg");
put("GRC/Dauntless Dourbark", "https://img.scryfall.com/cards/large/en/pg07/12.jpg");
put("GRC/Llanowar Elves", "https://img.scryfall.com/cards/large/en/pg07/9.jpg");
put("GRC/Mind Stone", "https://img.scryfall.com/cards/large/en/pg07/11.jpg");
put("GRC/Mogg Fanatic", "https://img.scryfall.com/cards/large/en/pg07/10.jpg");
put("GRC/Reckless Wurm", "https://img.scryfall.com/cards/large/en/pg07/6.jpg");
put("GRC/Yixlid Jailer", "https://img.scryfall.com/cards/large/en/pg07/7.jpg");
put("GRC/Zoetic Cavern", "https://img.scryfall.com/cards/large/en/pg07/8.jpg");
// 2008a - https://scryfall.com/sets/pg08
put("GRC/Boggart Ram-Gang", "https://img.scryfall.com/cards/large/en/pg08/17.jpg");
put("GRC/Cenn's Tactician", "https://img.scryfall.com/cards/large/en/pg08/14.jpg");
put("GRC/Duergar Hedge-Mage", "https://img.scryfall.com/cards/large/en/pg08/19.jpg");
put("GRC/Gravedigger", "https://img.scryfall.com/cards/large/en/pg08/16.jpg");
put("GRC/Lava Axe", "https://img.scryfall.com/cards/large/en/pg08/13.jpg");
put("GRC/Oona's Blackguard", "https://img.scryfall.com/cards/large/en/pg08/15.jpg");
put("GRC/Selkie Hedge-Mage", "https://img.scryfall.com/cards/large/en/pg08/20.jpg");
put("GRC/Wilt-Leaf Cavaliers", "https://img.scryfall.com/cards/large/en/pg08/18.jpg");
// Wizards Play Network Promos -- xmage uses one set (GRC), but scryfall store it by years
// 2008b - https://scryfall.com/sets/pwpn
put("GRC/Sprouting Thrinax", "https://img.scryfall.com/cards/large/en/pwpn/21.jpg");
put("GRC/Woolly Thoctar", "https://img.scryfall.com/cards/large/en/pwpn/22.jpg");
// 2009 - https://scryfall.com/sets/pwp09
put("GRC/Hellspark Elemental", "https://img.scryfall.com/cards/large/en/pwp09/25.jpg");
put("GRC/Kor Duelist", "https://img.scryfall.com/cards/large/en/pwp09/32.jpg");
put("GRC/Marisi's Twinclaws", "https://img.scryfall.com/cards/large/en/pwp09/26.jpg");
put("GRC/Mind Control", "https://img.scryfall.com/cards/large/en/pwp09/30.jpg");
put("GRC/Path to Exile", "https://img.scryfall.com/cards/large/en/pwp09/24.jpg");
put("GRC/Rise from the Grave", "https://img.scryfall.com/cards/large/en/pwp09/31.jpg");
put("GRC/Slave of Bolas", "https://img.scryfall.com/cards/large/en/pwp09/27.jpg");
put("GRC/Vampire Nighthawk", "https://img.scryfall.com/cards/large/en/pwp09/33.jpg");
// 2010 - https://scryfall.com/sets/pwp10
put("GRC/Kor Firewalker", "https://img.scryfall.com/cards/large/en/pwp10/36.jpg");
put("GRC/Leatherback Baloth", "https://img.scryfall.com/cards/large/en/pwp10/37.jpg");
put("GRC/Syphon Mind", "https://img.scryfall.com/cards/large/en/pwp10/40.jpg");
put("GRC/Pathrazer of Ulamog", "https://img.scryfall.com/cards/large/en/pwp10/46.jpg");
put("GRC/Curse of Wizardry", "https://img.scryfall.com/cards/large/en/pwp10/47.jpg");
put("GRC/Fling/50", "https://img.scryfall.com/cards/large/en/pwp10/50.jpg"); // same card but different year
put("GRC/Sylvan Ranger/51", "https://img.scryfall.com/cards/large/en/pwp10/51.jpg"); // same card but different year
put("GRC/Plague Stinger", "https://img.scryfall.com/cards/large/en/pwp10/59.jpg");
put("GRC/Golem's Heart", "https://img.scryfall.com/cards/large/en/pwp10/60.jpg");
put("GRC/Skinrender", "https://img.scryfall.com/cards/large/en/pwp10/63.jpg");
// 2011 - https://scryfall.com/sets/pwp11
put("GRC/Auramancer", "https://img.scryfall.com/cards/large/en/pwp11/77.jpg");
put("GRC/Bloodcrazed Neonate", "https://img.scryfall.com/cards/large/en/pwp11/83.jpg");
put("GRC/Boneyard Wurm", "https://img.scryfall.com/cards/large/en/pwp11/84.jpg");
put("GRC/Circle of Flame", "https://img.scryfall.com/cards/large/en/pwp11/78.jpg");
put("GRC/Curse of the Bloody Tome", "https://img.scryfall.com/cards/large/en/pwp11/80.jpg");
put("GRC/Fling/69", "https://img.scryfall.com/cards/large/en/pwp11/69.jpg"); // same card but different year
put("GRC/Master's Call", "https://img.scryfall.com/cards/large/en/pwp11/64.jpg");
put("GRC/Maul Splicer", "https://img.scryfall.com/cards/large/en/pwp11/72.jpg");
put("GRC/Plague Myr", "https://img.scryfall.com/cards/large/en/pwp11/65.jpg");
put("GRC/Shrine of Burning Rage", "https://img.scryfall.com/cards/large/en/pwp11/73.jpg");
put("GRC/Signal Pest", "https://img.scryfall.com/cards/large/en/pwp11/66.jpg");
put("GRC/Sylvan Ranger/70", "https://img.scryfall.com/cards/large/en/pwp11/70.jpg"); // same card but different year
put("GRC/Tormented Soul", "https://img.scryfall.com/cards/large/en/pwp11/76.jpg");
put("GRC/Vault Skirge", "https://img.scryfall.com/cards/large/en/pwp11/71.jpg");
// 2012 - https://scryfall.com/sets/pwp12
put("GRC/Curse of Thirst", "https://img.scryfall.com/cards/large/en/pwp12/81.jpg");
put("GRC/Gather the Townsfolk", "https://img.scryfall.com/cards/large/en/pwp12/79.jpg");
put("GRC/Nearheath Stalker", "https://img.scryfall.com/cards/large/en/pwp12/82.jpg");
// TODO: remove Grand Prix fix after scryfall fix image's link (that's link must be work: https://img.scryfall.com/cards/large/en/pgpx/2016b.jpg )
put("GPX/Sword of Feast and Famine", "https://img.scryfall.com/cards/large/en/pgpx/1%E2%98%85.jpg");
}
};

View file

@ -140,7 +140,7 @@ public enum WizardCardsImageSource implements CardImageSource {
supportedSets.add("WWK");
supportedSets.add("DDE");
supportedSets.add("ROE");
supportedSets.add("DPA");
//supportedSets.add("DPA");
supportedSets.add("ARC");
supportedSets.add("M11");
supportedSets.add("V10");

View file

@ -105,6 +105,8 @@
|Generate|PLANE:PCA|Plane - Truga Jungle|||TrugaJunglePlane|
|Generate|PLANE:PCA|Plane - Turri Island|||TurriIslandPlane|
|Generate|PLANE:PCA|Plane - Undercity Reaches|||UndercityReachesPlane|
|Generate|TOK:ANA|Goblin|||GoblinToken|
|Generate|TOK:ANA|Spirit|||SpiritWhiteToken|
|Generate|TOK:PCA|Eldrazi|||EldraziAnnihilatorToken|
|Generate|TOK:10E|Ape|||PongifyApeToken|
|Generate|TOK:10E|Dragon|||DragonToken2|

View file

@ -39,7 +39,7 @@ public class ActionData {
this.gameId = gameId;
}
public class CustomExclusionStrategy implements ExclusionStrategy {
static class CustomExclusionStrategy implements ExclusionStrategy {
// FIXME: Very crude way of whitelisting, as it applies to all levels of the JSON tree.
private final java.util.Set<String> KEEP = new java.util.HashSet<>(

View file

@ -14,7 +14,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 = 31;
public final static String MAGE_VERSION_MINOR_PATCH = "V1";
public final static String MAGE_VERSION_MINOR_PATCH = "V4";
public final static String MAGE_VERSION_INFO = "";
private final int major;

View file

@ -2,6 +2,7 @@ package mage.utils.properties;
import org.apache.log4j.Logger;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
@ -19,39 +20,36 @@ public final class PropertiesUtil {
private static Properties properties = new Properties();
static {
InputStream in = PropertiesUtil.class.getResourceAsStream("/xmage.properties");
if (in != null) {
try {
properties.load(in);
} catch (IOException e) {
logger.error("Couldn't load properties", e);
}
} else {
try (InputStream in = PropertiesUtil.class.getResourceAsStream("/xmage.properties")) {
properties.load(in);
} catch (FileNotFoundException fnfe) {
logger.warn("No xmage.properties were found on classpath");
} catch (IOException e) {
logger.error("Couldn't load properties");
e.printStackTrace();
}
}
/**
* Hide constructor
*/
/**
* Hide constructor
*/
private PropertiesUtil() {
}
public static String getDBLogUrl() {
String url = properties.getProperty(PropertyKeys.KEY_DB_LOG_URL, LOG_JDBC_URL);
if (url != null) {
return url.trim();
}
return null;
}
public static String getDBFeedbackUrl() {
String url = properties.getProperty(PropertyKeys.KEY_DB_FEEDBACK_URL, FEEDBACK_JDBC_URL);
if (url != null) {
return url.trim();
public static String getDBLogUrl () {
String url = properties.getProperty(PropertyKeys.KEY_DB_LOG_URL, LOG_JDBC_URL);
if (url != null) {
return url.trim();
}
return null;
}
public static String getDBFeedbackUrl () {
String url = properties.getProperty(PropertyKeys.KEY_DB_FEEDBACK_URL, FEEDBACK_JDBC_URL);
if (url != null) {
return url.trim();
}
return null;
}
return null;
}
}

View file

@ -76,8 +76,6 @@ public class AusHighlander extends Constructed {
pointMap.put("True-Name Nemesis", 1);
pointMap.put("Umezawas Jitte", 1);
pointMap.put("Wasteland", 1);
pointMap.put("Wheel of Fortune", 1);
pointMap.put("Worldly Tutor", 1);
pointMap.put("Yawgmoths Bargain", 1);
}

View file

@ -21,7 +21,7 @@ public class CanadianHighlander extends Constructed {
pointMap.put("Balance", 1);
pointMap.put("Birthing Pod", 3);
pointMap.put("Black Lotus", 7);
pointMap.put("Demonic Tutor", 4);
pointMap.put("Demonic Tutor", 3);
pointMap.put("Dig Through Time", 1);
pointMap.put("Enlightened Tutor", 1);
pointMap.put("Fastbond", 1);

View file

@ -1,19 +1,13 @@
package mage.deck;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import mage.cards.ExpansionSet;
import mage.cards.Sets;
import mage.cards.decks.Constructed;
import mage.constants.SetType;
import java.util.*;
/**
*
* @author BetaSteward_at_googlemail.com
*/
public class Standard extends Constructed {
@ -23,13 +17,7 @@ public class Standard extends Constructed {
setCodes.addAll(makeLegalSets());
banned.add("Attune with Aether"); // since 2018-01-15
banned.add("Aetherworks Marvel");
banned.add("Felidar Guardian");
banned.add("Rampaging Ferocidon"); // since 2018-01-15
banned.add("Ramunap Ruins"); // since 2018-01-15
banned.add("Rogue Refiner"); // since 2018-01-15
banned.add("Smuggler's Copter");
}
private static boolean isFallSet(ExpansionSet set) {

View file

@ -672,7 +672,7 @@ public class MageServerImpl implements MageServer {
} catch (Exception ex) {
handleException(ex);
}
return null;
return Optional.empty();
}
@Override

View file

@ -153,15 +153,15 @@ public final class Main {
for (ExtensionPackage pkg : extensions) {
Map<String, Class> draftCubes = pkg.getDraftCubes();
for (String name : draftCubes.keySet()) {
logger.info("Loading extension: [" + name + "] " + draftCubes.get(name).toString());
CubeFactory.instance.addDraftCube(name, draftCubes.get(name));
}
draftCubes.forEach((name, draftCube) -> {
logger.info("Loading extension: [" + name + "] " + draftCube.toString());
CubeFactory.instance.addDraftCube(name, draftCube);
});
Map<String, Class> deckTypes = pkg.getDeckTypes();
for (String name : deckTypes.keySet()) {
logger.info("Loading extension: [" + name + "] " + deckTypes.get(name));
DeckValidatorFactory.instance.addDeckType(name, deckTypes.get(name));
}
deckTypes.forEach((name, deckType) -> {
logger.info("Loading extension: [" + name + "] " + deckType);
DeckValidatorFactory.instance.addDeckType(name, deckType);
});
}
logger.info("Config - max seconds idle: " + config.getMaxSecondsIdle());

View file

@ -26,7 +26,7 @@ public enum SessionManager {
logger.trace("Session with sessionId " + sessionId + " is not found");
return Optional.empty();
}
if (session.getUserId() != null && UserManager.instance.getUser(session.getUserId()) == null) {
if (session.getUserId() != null && !UserManager.instance.getUser(session.getUserId()).isPresent()) {
logger.error("User for session " + sessionId + " with userId " + session.getUserId() + " is missing. Session removed.");
// can happen if user from same host signs in multiple time with multiple clients, after he disconnects with one client
disconnect(sessionId, DisconnectReason.ConnectingOtherInstance);

View file

@ -942,7 +942,7 @@ public class TableController {
if (!(table.getState() == TableState.WAITING || table.getState() == TableState.STARTING || table.getState() == TableState.READY_TO_START)) {
if (match == null) {
logger.warn("- Match table with no match:");
logger.warn("-- matchId:" + match.getId() + " [" + match.getName() + ']');
logger.warn("-- matchId:" + match.getId() + " , table : " + table.getId());
// return false;
} else if (match.isDoneSideboarding() && match.getGame() == null) {
// no sideboarding and not active game -> match seems to hang (maybe the Draw bug)

View file

@ -266,13 +266,13 @@ public class GameController implements GameCallback {
public void join(UUID userId) {
UUID playerId = userPlayerMap.get(userId);
Optional<User> user = UserManager.instance.getUser(userId);
if (userId == null || playerId == null) {
if (playerId == null) {
logger.fatal("Join game failed!");
logger.fatal("- gameId: " + game.getId());
logger.fatal("- userId: " + userId);
return;
}
Optional<User> user = UserManager.instance.getUser(userId);
if (!user.isPresent()) {
logger.fatal("User not found : " + userId);
return;

View file

@ -3,14 +3,14 @@ package mage.server.game;
import java.util.UUID;
import java.util.concurrent.Callable;
import mage.MageException;
import mage.game.Game;
import org.apache.log4j.Logger;
/**
*
* @author BetaSteward_at_googlemail.com
* @param <T>
* @author BetaSteward_at_googlemail.com
*/
public class GameWorker<T> implements Callable {
@ -40,12 +40,7 @@ public class GameWorker<T> implements Callable {
} catch (Exception e) {
LOGGER.fatal("GameWorker general exception [" + game.getId() + "] " + e.getMessage(), e);
if (e instanceof NullPointerException) {
if (e.getStackTrace() == null) {
LOGGER.info("Stack trace is null");
} else {
LOGGER.info("Null-Pointer-Exception: Stack trace");
LOGGER.info(e.getStackTrace());
}
LOGGER.info(e.getStackTrace());
}
} catch (Error err) {
LOGGER.fatal("GameWorker general error [" + game.getId() + "] " + err, err);

View file

@ -1,4 +1,3 @@
package mage.cards.a;
import java.util.HashMap;
@ -7,18 +6,18 @@ import java.util.Map.Entry;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.AsThoughEffectImpl;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneAllEffect;
import mage.abilities.keyword.CyclingAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.constants.AsThoughEffectType;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.TargetController;
import mage.constants.WatcherScope;
import mage.constants.Zone;
import mage.filter.FilterCard;
@ -42,7 +41,14 @@ public final class AbandonedSarcophagus extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}");
// You may cast nonland cards with cycling from your graveyard.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new AbandonedSarcophagusCastFromGraveyardEffect()));
FilterCard filter = new FilterCard("nonland cards with cycling");
filter.add(Predicates.not(new CardTypePredicate(CardType.LAND)));
filter.add(new AbilityPredicate(CyclingAbility.class));
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
new PlayFromNotOwnHandZoneAllEffect(filter,
Zone.GRAVEYARD, true, TargetController.YOU, Duration.WhileOnBattlefield)
.setText("You may cast nonland cards with cycling from your graveyard"))
);
// If a card with cycling would be put into your graveyard from anywhere and it wasn't cycled, exile it instead.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new AbandonedSarcophagusReplacementEffect()), new AbandonedSarcophagusWatcher());
@ -59,46 +65,6 @@ public final class AbandonedSarcophagus extends CardImpl {
}
}
class AbandonedSarcophagusCastFromGraveyardEffect extends AsThoughEffectImpl {
private static final FilterCard filter = new FilterCard("nonland cards with cycling");
static {
filter.add(Predicates.not(new CardTypePredicate(CardType.LAND)));
filter.add(new AbilityPredicate(CyclingAbility.class));
}
AbandonedSarcophagusCastFromGraveyardEffect() {
super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.WhileOnBattlefield, Outcome.Benefit);
staticText = "You may cast nonland cards with cycling from your graveyard";
}
AbandonedSarcophagusCastFromGraveyardEffect(final AbandonedSarcophagusCastFromGraveyardEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
return true;
}
@Override
public AbandonedSarcophagusCastFromGraveyardEffect copy() {
return new AbandonedSarcophagusCastFromGraveyardEffect(this);
}
@Override
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
Card card = game.getCard(objectId);
if (card != null) {
return (affectedControllerId.equals(source.getControllerId())
&& filter.match(card, game)
&& game.getState().getZone(card.getId()) == Zone.GRAVEYARD);
}
return false;
}
}
class AbandonedSarcophagusReplacementEffect extends ReplacementEffectImpl {
boolean cardHasCycling;

View file

@ -1,4 +1,3 @@
package mage.cards.a;
import java.util.UUID;
@ -8,6 +7,7 @@ import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.AsThoughEffectImpl;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect;
import mage.abilities.keyword.ProwessAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
@ -75,7 +75,7 @@ class AbbotOfKeralKeepExileEffect extends OneShotEffect {
if (card != null) {
String exileName = sourcePermanent.getIdName() + " <this card may be played the turn it was exiled>";
controller.moveCardsToExile(card, source, game, true, source.getSourceId(), exileName);
ContinuousEffect effect = new AbbotOfKeralKeepCastFromExileEffect();
ContinuousEffect effect = new PlayFromNotOwnHandZoneTargetEffect(Duration.EndOfTurn);
effect.setTargetPointer(new FixedTarget(card.getId(), card.getZoneChangeCounter(game)));
game.addEffect(effect, source);
}

View file

@ -2,6 +2,7 @@
package mage.cards.a;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
@ -12,26 +13,24 @@ import mage.abilities.keyword.TransformAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.p.PerfectedForm;
import mage.constants.*;
import mage.game.Game;
import mage.players.Player;
/**
*
* @author fireshoes
*/
public final class AberrantResearcher extends CardImpl {
public AberrantResearcher(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(SubType.HUMAN);
this.subtype.add(SubType.INSECT);
this.power = new MageInt(3);
this.toughness = new MageInt(2);
this.transformable = true;
this.secondSideCardClazz = PerfectedForm.class;
this.secondSideCardClazz = mage.cards.p.PerfectedForm.class;
// Flying
this.addAbility(FlyingAbility.getInstance());

View file

@ -2,6 +2,7 @@
package mage.cards.a;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.Mode;
@ -14,7 +15,6 @@ import mage.abilities.keyword.TransformAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.i.InfectiousCurse;
import mage.constants.*;
import mage.game.Game;
import mage.game.permanent.Permanent;
@ -23,7 +23,6 @@ import mage.target.Target;
import mage.util.CardUtil;
/**
*
* @author halljared
*/
public final class AccursedWitch extends CardImpl {
@ -36,7 +35,7 @@ public final class AccursedWitch extends CardImpl {
this.toughness = new MageInt(2);
this.transformable = true;
this.secondSideCardClazz = InfectiousCurse.class;
this.secondSideCardClazz = mage.cards.i.InfectiousCurse.class;
// Spells your opponents cast that target Accursed Witch cost {1} less to cast.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new AccursedWitchSpellsCostReductionEffect()));

View file

@ -0,0 +1,107 @@
package mage.cards.a;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ExileTargetEffect;
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
import mage.abilities.keyword.HasteAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.repository.CardRepository;
import mage.choices.ChoiceImpl;
import mage.constants.*;
import mage.filter.FilterCard;
import mage.filter.predicate.mageobject.NamePredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetCardInLibrary;
import mage.target.targetpointer.FixedTarget;
/**
*
* @author L_J
*/
public final class AchHansRun extends CardImpl {
public AchHansRun(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}{R}{G}{G}");
// At the beginning of your upkeep, you may say "Ach! Hans, run! Its the …" and the name of a creature card. If you do, search your library for a card with that name, put it onto the battlefield, then shuffle your library. That creature gains haste. Exile it at the beginning of the next end step.
this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new AchHansRunEffect(), TargetController.YOU, true));
}
public AchHansRun(final AchHansRun card) {
super(card);
}
@Override
public AchHansRun copy() {
return new AchHansRun(this);
}
}
class AchHansRunEffect extends OneShotEffect {
public AchHansRunEffect() {
super(Outcome.PutCreatureInPlay);
this.staticText = "you may say \"Ach! Hans, run! Its the …\" and the name of a creature card. If you do, search your library for a card with that name, put it onto the battlefield, then shuffle your library. That creature gains haste. Exile it at the beginning of the next end step";
}
public AchHansRunEffect(final AchHansRunEffect effect) {
super(effect);
}
@Override
public AchHansRunEffect copy() {
return new AchHansRunEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
ChoiceImpl cardChoice = new ChoiceImpl(true);
cardChoice.setChoices(CardRepository.instance.getCreatureNames());
cardChoice.setMessage("Choose a creature card name");
if (controller.choose(Outcome.Detriment, cardChoice, game)) {
String cardName = cardChoice.getChoice();
if (!game.isSimulation()) {
game.informPlayers(controller.getLogName() + ": \"Ach! Hans, run! It's the " + cardName + "!\"");
}
FilterCard nameFilter = new FilterCard();
nameFilter.add(new NamePredicate(cardName));
TargetCardInLibrary target = new TargetCardInLibrary(1, 1, nameFilter);
if (controller.searchLibrary(target, game)) {
Card card = controller.getLibrary().remove(target.getFirstTarget(), game);
if (card != null) {
if (card != null && controller.moveCards(card, Zone.BATTLEFIELD, source, game)) {
Permanent creature = game.getPermanent(card.getId());
if (creature != null) {
// gains haste
ContinuousEffect effect = new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn);
effect.setTargetPointer(new FixedTarget(creature, game));
game.addEffect(effect, source);
// Exile at begin of next end step
ExileTargetEffect exileEffect = new ExileTargetEffect(null, null, Zone.BATTLEFIELD);
exileEffect.setTargetPointer(new FixedTarget(creature, game));
DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(exileEffect);
game.addDelayedTriggeredAbility(delayedAbility, source);
}
}
}
controller.shuffleLibrary(source, game);
}
return true;
}
}
return false;
}
}

View file

@ -1,4 +1,3 @@
package mage.cards.a;
import java.util.HashSet;
@ -6,9 +5,9 @@ import java.util.Set;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.AsThoughEffectImpl;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@ -44,7 +43,7 @@ class ActOnImpulseExileEffect extends OneShotEffect {
public ActOnImpulseExileEffect() {
super(Outcome.Benefit);
this.staticText = "Exile the top three cards of your library. Until end of turn, you may play cards exiled this way.";
this.staticText = "Exile the top three cards of your library. Until end of turn, you may play cards exiled this way";
}
public ActOnImpulseExileEffect(final ActOnImpulseExileEffect effect) {
@ -71,7 +70,7 @@ class ActOnImpulseExileEffect extends OneShotEffect {
}
}
if (!cards.isEmpty()) {
ContinuousEffect effect = new ActOnImpulseMayPlayExiledEffect();
ContinuousEffect effect = new PlayFromNotOwnHandZoneTargetEffect(Zone.EXILED, Duration.EndOfTurn);
effect.setTargetPointer(new FixedTargets(cards, game));
game.addEffect(effect, source);
}
@ -82,31 +81,3 @@ class ActOnImpulseExileEffect extends OneShotEffect {
}
}
class ActOnImpulseMayPlayExiledEffect extends AsThoughEffectImpl {
public ActOnImpulseMayPlayExiledEffect() {
super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfTurn, Outcome.Benefit);
}
public ActOnImpulseMayPlayExiledEffect(final ActOnImpulseMayPlayExiledEffect effect) {
super(effect);
}
@Override
public ActOnImpulseMayPlayExiledEffect copy() {
return new ActOnImpulseMayPlayExiledEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
return true;
}
@Override
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
return affectedControllerId.equals(source.getControllerId())
&& getTargetPointer().getTargets(game, source).contains(objectId);
}
}

View file

@ -1,4 +1,3 @@
package mage.cards.a;
import java.util.UUID;
@ -6,18 +5,18 @@ import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.AsThoughEffectImpl;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.AsThoughEffectType;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Library;
@ -81,7 +80,7 @@ class AerialCaravanExileEffect extends OneShotEffect {
if (card != null) {
String exileName = sourcePermanent.getIdName() + " <this card may be played the turn it was exiled>";
controller.moveCardsToExile(card, source, game, true, source.getSourceId(), exileName);
ContinuousEffect effect = new AerialCaravanCastFromExileEffect();
ContinuousEffect effect = new PlayFromNotOwnHandZoneTargetEffect(Zone.EXILED, Duration.EndOfTurn);
effect.setTargetPointer(new FixedTarget(card.getId(), card.getZoneChangeCounter(game)));
game.addEffect(effect, source);
}
@ -90,31 +89,3 @@ class AerialCaravanExileEffect extends OneShotEffect {
return false;
}
}
class AerialCaravanCastFromExileEffect extends AsThoughEffectImpl {
public AerialCaravanCastFromExileEffect() {
super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfTurn, Outcome.Benefit);
staticText = "You may play the card from exile";
}
public AerialCaravanCastFromExileEffect(final AerialCaravanCastFromExileEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
return true;
}
@Override
public AerialCaravanCastFromExileEffect copy() {
return new AerialCaravanCastFromExileEffect(this);
}
@Override
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
return source.isControlledBy(affectedControllerId)
&& objectId.equals(getTargetPointer().getFirst(game, source));
}
}

View file

@ -2,6 +2,7 @@
package mage.cards.a;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.TriggeredAbility;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
@ -11,24 +12,22 @@ import mage.abilities.effects.common.TransformSourceEffect;
import mage.abilities.keyword.TransformAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.w.WerewolfRansacker;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.TargetController;
/**
*
* @author BetaSteward
*/
public final class AfflictedDeserter extends CardImpl {
public AfflictedDeserter(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{R}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.WEREWOLF);
this.transformable = true;
this.secondSideCardClazz = WerewolfRansacker.class;
this.secondSideCardClazz = mage.cards.w.WerewolfRansacker.class;
this.power = new MageInt(3);
this.toughness = new MageInt(2);

View file

@ -3,7 +3,7 @@ package mage.cards.a;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
import mage.abilities.effects.common.GetEmblemEffect;
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
@ -38,7 +38,7 @@ public final class AjaniAdversaryOfTyrants extends CardImpl {
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.AJANI);
this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(4));
this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(4));
// +1: Put a +1/+1 counter on each of up to two target creatures.
Ability ability = new LoyaltyAbility(new AddCountersTargetEffect(CounterType.P1P1.createInstance()), 1);

View file

@ -4,7 +4,7 @@ package mage.cards.a;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
import mage.abilities.dynamicvalue.common.ControllerLifeCount;
import mage.abilities.effects.Effect;
import mage.abilities.effects.Effects;
@ -34,7 +34,7 @@ public final class AjaniCallerOfThePride extends CardImpl {
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.AJANI);
this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(4));
this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(4));
// +1: Put a +1/+1 counter on up to one target creature.
Effect effect = new AddCountersTargetEffect(CounterType.P1P1.createInstance());
effect.setText("Put a +1/+1 counter on up to one target creature");

View file

@ -4,7 +4,7 @@ package mage.cards.a;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.effects.Effects;
@ -22,7 +22,6 @@ import mage.filter.common.FilterCreaturePermanent;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.game.permanent.token.TokenImpl;
import mage.game.permanent.token.Token;
import mage.players.Player;
/**
@ -36,7 +35,7 @@ public final class AjaniGoldmane extends CardImpl {
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.AJANI);
this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(4));
this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(4));
// +1: You gain 2 life.
this.addAbility(new LoyaltyAbility(new GainLifeEffect(2), 1));

View file

@ -4,7 +4,7 @@ package mage.cards.a;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.effects.common.LookLibraryAndPickControllerEffect;
import mage.abilities.effects.common.counter.DistributeCountersEffect;
@ -46,7 +46,7 @@ public final class AjaniMentorOfHeroes extends CardImpl {
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.AJANI);
this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(4));
this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(4));
// +1: Distribute three +1/+1 counters among one, two, or three target creatures you control
Ability ability = new LoyaltyAbility(new DistributeCountersEffect(CounterType.P1P1, 3, false, "one, two, or three target creatures you control"), 1);

View file

@ -3,7 +3,7 @@ package mage.cards.a;
import java.util.UUID;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.GetEmblemEffect;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
@ -45,7 +45,7 @@ public final class AjaniSteadfast extends CardImpl {
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.AJANI);
this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(4));
this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(4));
// +1: Until end of turn, up to one target creature gets +1/+1 and gains first strike, vigilance, and lifelink.
Effect effect = new BoostTargetEffect(1, 1, Duration.EndOfTurn);

View file

@ -3,7 +3,7 @@ package mage.cards.a;
import java.util.UUID;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
import mage.abilities.effects.common.ExileAndGainLifeEqualPowerTargetEffect;
import mage.abilities.effects.common.RevealLibraryPutIntoHandEffect;
import mage.abilities.effects.common.counter.AddCountersAllEffect;
@ -43,7 +43,7 @@ public final class AjaniUnyielding extends CardImpl {
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.AJANI);
this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(4));
this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(4));
// +2: Reveal the top three cards of your library. Put all nonland permanent cards revealed this way into your hand and the rest on the bottom of your library in any order.
this.addAbility(new LoyaltyAbility(new RevealLibraryPutIntoHandEffect(3, nonlandPermanentFilter, Zone.LIBRARY), 2));

View file

@ -4,7 +4,7 @@ package mage.cards.a;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
import mage.abilities.dynamicvalue.common.ControllerLifeCount;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.RevealCardsFromLibraryUntilEffect;
@ -33,7 +33,7 @@ public final class AjaniValiantProtector extends CardImpl {
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.AJANI);
this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(4));
this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(4));
// +2: Put two +1/+1 counters on up to one target creature.
Ability ability = new LoyaltyAbility(new AddCountersTargetEffect(CounterType.P1P1.createInstance(2)), 2);

View file

@ -3,7 +3,7 @@ package mage.cards.a;
import java.util.UUID;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
import mage.abilities.effects.Effects;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.effects.common.DestroyAllControlledTargetEffect;
@ -37,7 +37,7 @@ public final class AjaniVengeant extends CardImpl {
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.AJANI);
this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(3));
this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(3));
// +1: Target permanent doesn't untap during its controller's next untap step.
LoyaltyAbility ability1 = new LoyaltyAbility(new DontUntapInControllersNextUntapStepTargetEffect(), 1);

View file

@ -3,7 +3,7 @@ package mage.cards.a;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
import mage.abilities.dynamicvalue.common.ControllerLifeCount;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.common.GainLifeEffect;
@ -29,7 +29,7 @@ public final class AjaniWiseCounselor extends CardImpl {
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.AJANI);
this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(5));
this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(5));
// +2: You gain 1 life for each creature you control.
this.addAbility(new LoyaltyAbility(new GainLifeEffect(

View file

@ -1,4 +1,3 @@
package mage.cards.a;
import java.util.UUID;
@ -14,12 +13,12 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.constants.TargetAdjustment;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.StaticFilters;
import mage.target.TargetPermanent;
import mage.target.common.TargetCardInHand;
import mage.target.targetadjustment.XTargetsAdjuster;
/**
*
@ -40,7 +39,7 @@ public final class AlexiZephyrMage extends CardImpl {
ability.addCost(new TapSourceCost());
ability.addCost(new DiscardTargetCost(new TargetCardInHand(2, new FilterCard("two cards"))));
ability.addTarget(new TargetPermanent(StaticFilters.FILTER_PERMANENT_CREATURES));
ability.setTargetAdjustment(TargetAdjustment.X_TARGETS);
ability.setTargetAdjuster(XTargetsAdjuster.instance);
this.addAbility(ability);
}

View file

@ -3,7 +3,7 @@ package mage.cards.a;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.CanBeYourCommanderAbility;
import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ExileTargetForSourceEffect;
@ -48,7 +48,7 @@ public class AminatouTheFateShifter extends CardImpl {
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.AMINATOU);
this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(3));
this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(3));
// +1: Draw a card, then put a card from your hand on top of your library.
Ability ability = new LoyaltyAbility(new AminatouPlusEffect(), +1);

View file

@ -62,7 +62,7 @@ class AnZerrinRuinsDontUntapEffect extends DontUntapInControllersUntapStepAllEff
if (super.applies(event, source, game)) {
Permanent permanent = game.getPermanent(event.getTargetId());
if (permanent != null) {
if (permanent.hasSubtype(ChooseCreatureTypeEffect.getChoosenCreatureType(source.getSourceId(), game), game)) {
if (permanent.hasSubtype(ChooseCreatureTypeEffect.getChosenCreatureType(source.getSourceId(), game), game)) {
return true;
}
}

View file

@ -2,6 +2,7 @@
package mage.cards.a;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.ActivateAsSorceryActivatedAbility;
@ -15,7 +16,6 @@ import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.abilities.keyword.TransformAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.d.DarthVader;
import mage.constants.*;
import mage.counters.CounterType;
import mage.filter.StaticFilters;
@ -27,7 +27,6 @@ import mage.target.common.TargetControlledCreaturePermanent;
import mage.target.common.TargetCreaturePermanent;
/**
*
* @author Styxo
*/
public final class AnakinSkywalker extends CardImpl {
@ -41,7 +40,7 @@ public final class AnakinSkywalker extends CardImpl {
this.toughness = new MageInt(4);
this.transformable = true;
this.secondSideCardClazz = DarthVader.class;
this.secondSideCardClazz = mage.cards.d.DarthVader.class;
// Whenever another creature dies, put a +1/+1 counter on Anakin Skywalker.
this.addAbility(new DiesCreatureTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance()), false, true));

View file

@ -0,0 +1,53 @@
package mage.cards.a;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTappedAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.common.SacrificeSourceCost;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.continuous.BoostEnchantedEffect;
import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect;
import mage.abilities.keyword.EnchantAbility;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.TotemArmorAbility;
import mage.abilities.mana.AnyColorManaAbility;
import mage.abilities.mana.WhiteManaAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.target.TargetPermanent;
import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
/**
* @author JayDi85
*/
public final class AngelicReward extends CardImpl {
public AngelicReward(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{W}{W}");
this.subtype.add(SubType.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 gets +3/+3 and has flying.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEnchantedEffect(3, 3, Duration.WhileOnBattlefield)));
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(FlyingAbility.getInstance(), AttachmentType.AURA)));
}
public AngelicReward(final AngelicReward card) {
super(card);
}
@Override
public AngelicReward copy() {
return new AngelicReward(this);
}
}

View file

@ -1,10 +1,8 @@
package mage.cards.a;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.CreatureEntersBattlefieldTriggeredAbility;
import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
@ -12,10 +10,12 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
import mage.game.permanent.token.TokenImpl;
import mage.game.permanent.token.Token;
import mage.constants.Zone;
import mage.filter.StaticFilters;
import mage.game.permanent.token.custom.CreatureToken;
import java.util.UUID;
/**
* @author Loki
*/
@ -25,12 +25,18 @@ public final class AngelsTomb extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}");
// Whenever a creature enters the battlefield under your control, you may have Angel's Tomb become a 3/3 white Angel artifact creature with flying until end of turn.
this.addAbility(new CreatureEntersBattlefieldTriggeredAbility(new BecomesCreatureSourceEffect(
new CreatureToken(3, 3, "3/3 white Angel artifact creature with flying")
.withColor("W")
.withSubType(SubType.ANGEL)
.withAbility(FlyingAbility.getInstance()),
"", Duration.EndOfTurn), true));
Effect effect = new BecomesCreatureSourceEffect(new CreatureToken(3, 3, "3/3 white Angel artifact creature with flying")
.withColor("W")
.withSubType(SubType.ANGEL)
.withAbility(FlyingAbility.getInstance()),
"", Duration.EndOfTurn)
.setText("have {this} become a 3/3 white Angel artifact creature with flying until end of turn");
this.addAbility(new EntersBattlefieldControlledTriggeredAbility(
Zone.BATTLEFIELD,
effect,
StaticFilters.FILTER_PERMANENT_CREATURE_A,
true)
);
}
public AngelsTomb(final AngelsTomb card) {

View file

@ -4,7 +4,7 @@ package mage.cards.a;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
import mage.abilities.effects.Effects;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DamageAllControlledTargetEffect;
@ -39,7 +39,7 @@ public final class AngrathMinotaurPirate extends CardImpl {
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.ANGRATH);
this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(5));
this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(5));
// +2: Angrath, Minotaur Pirate deals 1 damage to target opponent and each creature that player controls.
Effects effects1 = new Effects();

View file

@ -5,7 +5,7 @@ import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.LoseLifeOpponentsEffect;
@ -41,7 +41,7 @@ public final class AngrathTheFlameChained extends CardImpl {
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.ANGRATH);
this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(4));
this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(4));
// +1: Each opponent discards a card and loses 2 life.
LoyaltyAbility ability = new LoyaltyAbility(new DiscardEachPlayerEffect(TargetController.OPPONENT), 1);

View file

@ -4,14 +4,13 @@ import java.util.Set;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.AsThoughEffectImpl;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect;
import mage.abilities.effects.mana.AddManaOfAnyColorEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.AsThoughEffectType;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
@ -79,7 +78,7 @@ class ApexOfPowerSpellEffect extends OneShotEffect {
if (card.isLand()) {
continue;
}
ContinuousEffect effect = new ApexOfPowerCastFromExileEffect();
ContinuousEffect effect = new PlayFromNotOwnHandZoneTargetEffect(Zone.EXILED, Duration.EndOfTurn);
effect.setTargetPointer(new FixedTarget(card.getId(), card.getZoneChangeCounter(game)));
game.addEffect(effect, source);
}
@ -87,34 +86,6 @@ class ApexOfPowerSpellEffect extends OneShotEffect {
}
}
class ApexOfPowerCastFromExileEffect extends AsThoughEffectImpl {
public ApexOfPowerCastFromExileEffect() {
super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfTurn, Outcome.Benefit);
staticText = "You may play the card from exile";
}
public ApexOfPowerCastFromExileEffect(final ApexOfPowerCastFromExileEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
return true;
}
@Override
public ApexOfPowerCastFromExileEffect copy() {
return new ApexOfPowerCastFromExileEffect(this);
}
@Override
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
return source.isControlledBy(affectedControllerId)
&& objectId.equals(getTargetPointer().getFirst(game, source));
}
}
class ApexOfPowerManaEffect extends OneShotEffect {
public ApexOfPowerManaEffect() {

View file

@ -64,7 +64,7 @@ class ConspyEffect extends ContinuousEffectImpl {
@Override
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
Player controller = game.getPlayer(source.getControllerId());
SubType subType = ChooseCreatureTypeEffect.getChoosenCreatureType(source.getSourceId(), game);
SubType subType = ChooseCreatureTypeEffect.getChosenCreatureType(source.getSourceId(), game);
if (controller != null && subType != null) {
// Creature cards you own that aren't on the battlefield
// in graveyard

View file

@ -1,9 +1,6 @@
package mage.cards.a;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
@ -15,24 +12,27 @@ import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.abilities.effects.common.CreateTokenCopyTargetEffect;
import mage.cards.Card;
import mage.constants.SubType;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.Target;
import mage.target.TargetCard;
import mage.target.TargetPlayer;
import mage.target.common.TargetCardInHand;
import mage.target.targetpointer.FixedTarget;
import mage.util.CardUtil;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
/**
*
* @author TheElk801
*/
public final class ArcaneArtisan extends CardImpl {
@ -46,10 +46,14 @@ public final class ArcaneArtisan extends CardImpl {
this.toughness = new MageInt(3);
// {2}{U}, {T}: Target player draws a card, then exiles a card from their hand. If a creature card is exiled this way, that player creates a token that's a copy of that card.
Ability ability = new SimpleActivatedAbility(new ArcaneArtisanCreateTokenEffect(), new ManaCostsImpl("{2}{U}"));
Ability ability = new SimpleActivatedAbility(
new ArcaneArtisanCreateTokenEffect(),
new ManaCostsImpl("{2}{U}")
);
ability.addCost(new TapSourceCost());
ability.addTarget(new TargetPlayer());
this.addAbility(ability);
// When Arcane Artisan leaves the battlefield, exile all tokens created with it at the beginning of the next end step.
this.addAbility(new ArcaneArtisanLeavesBattlefieldTriggeredAbility());
}
@ -66,13 +70,13 @@ public final class ArcaneArtisan extends CardImpl {
class ArcaneArtisanCreateTokenEffect extends OneShotEffect {
ArcaneArtisanCreateTokenEffect() {
public ArcaneArtisanCreateTokenEffect() {
super(Outcome.Benefit);
this.staticText = "Target player draws a card, then exiles a card from their hand. "
+ "If a creature card is exiled this way, that player creates a token that's a copy of that card.";
}
ArcaneArtisanCreateTokenEffect(final ArcaneArtisanCreateTokenEffect effect) {
public ArcaneArtisanCreateTokenEffect(final ArcaneArtisanCreateTokenEffect effect) {
super(effect);
}
@ -88,8 +92,8 @@ class ArcaneArtisanCreateTokenEffect extends OneShotEffect {
return false;
}
player.drawCards(1, game);
Target target = new TargetCardInHand(1, new FilterCard());
if (!player.chooseTarget(Outcome.Exile, target, source, game)) {
TargetCard target = new TargetCardInHand(1, StaticFilters.FILTER_CARD);
if (!player.chooseTarget(Outcome.Exile, player.getHand(), target, source, game)) {
return false;
}
Card card = game.getCard(target.getFirstTarget());
@ -119,14 +123,14 @@ class ArcaneArtisanCreateTokenEffect extends OneShotEffect {
class ArcaneArtisanLeavesBattlefieldTriggeredAbility extends ZoneChangeTriggeredAbility {
ArcaneArtisanLeavesBattlefieldTriggeredAbility() {
public ArcaneArtisanLeavesBattlefieldTriggeredAbility() {
super(Zone.BATTLEFIELD, null,
new CreateDelayedTriggeredAbilityEffect(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new ArcaneArtisanExileEffect())),
"", false
);
}
ArcaneArtisanLeavesBattlefieldTriggeredAbility(ArcaneArtisanLeavesBattlefieldTriggeredAbility ability) {
public ArcaneArtisanLeavesBattlefieldTriggeredAbility(ArcaneArtisanLeavesBattlefieldTriggeredAbility ability) {
super(ability);
}
@ -143,12 +147,12 @@ class ArcaneArtisanLeavesBattlefieldTriggeredAbility extends ZoneChangeTriggered
class ArcaneArtisanExileEffect extends OneShotEffect {
ArcaneArtisanExileEffect() {
public ArcaneArtisanExileEffect() {
super(Outcome.Benefit);
this.staticText = "exile all tokens created with {this}.";
}
ArcaneArtisanExileEffect(final ArcaneArtisanExileEffect effect) {
public ArcaneArtisanExileEffect(final ArcaneArtisanExileEffect effect) {
super(effect);
}

View file

@ -17,6 +17,7 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.TargetController;
import mage.constants.WatcherScope;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.stack.Spell;
@ -44,8 +45,9 @@ public final class ArclightPhoenix extends CardImpl {
// At the beginning of combat on your turn, if you cast 3 or more instants and/or sorceries this turn, you may return Arclight Phoenix from your graveyard to the battlefield.
this.addAbility(new ConditionalInterveningIfTriggeredAbility(
new BeginningOfCombatTriggeredAbility(
Zone.GRAVEYARD,
new ReturnSourceFromGraveyardToBattlefieldEffect(),
TargetController.YOU, true
TargetController.YOU, true, false
), ArclightPhoenixCondition.instance,
"At the beginning of combat on your turn, "
+ "if you've cast three or more instant "
@ -79,7 +81,7 @@ enum ArclightPhoenixCondition implements Condition {
class ArclightPhoenixWatcher extends Watcher {
private Map<UUID, Integer> instantSorceryCount = new HashMap();
private final Map<UUID, Integer> instantSorceryCount = new HashMap();
public ArclightPhoenixWatcher() {
super(ArclightPhoenixWatcher.class.getSimpleName(), WatcherScope.GAME);

View file

@ -2,6 +2,7 @@
package mage.cards.a;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
@ -14,14 +15,12 @@ import mage.abilities.effects.common.TransformSourceEffect;
import mage.abilities.keyword.TransformAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.t.TempleOfAclazotz;
import mage.constants.CardType;
import mage.constants.SuperType;
import mage.constants.TargetController;
import mage.constants.Zone;
/**
*
* @author TheElk801
*/
public final class ArguelsBloodFast extends CardImpl {
@ -31,7 +30,7 @@ public final class ArguelsBloodFast extends CardImpl {
addSuperType(SuperType.LEGENDARY);
this.transformable = true;
this.secondSideCardClazz = TempleOfAclazotz.class;
this.secondSideCardClazz = mage.cards.t.TempleOfAclazotz.class;
// {1}{B}, Pay 2 life: Draw a card.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), new ManaCostsImpl("{1}{B}"));

View file

@ -3,7 +3,7 @@ package mage.cards.a;
import java.util.UUID;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.TransformSourceEffect;
@ -35,7 +35,7 @@ public final class ArlinnKord extends CardImpl {
this.transformable = true;
this.secondSideCardClazz = ArlinnEmbracedByTheMoon.class;
this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(3));
this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(3));
// +1: Until end of turn, up to one target creature gets +2/+2 and gains vigilance and haste.
Effect effect = new BoostTargetEffect(2, 2, Duration.EndOfTurn);

View file

@ -8,6 +8,7 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.filter.common.FilterCreaturePermanent;
import mage.target.common.TargetCreaturePermanent;
/**
@ -16,6 +17,11 @@ import mage.target.common.TargetCreaturePermanent;
*/
public final class ArtfulTakedown extends CardImpl {
private static final FilterCreaturePermanent filter1
= new FilterCreaturePermanent("creature (to tap)");
private static final FilterCreaturePermanent filter2
= new FilterCreaturePermanent("creature (to shrink)");
public ArtfulTakedown(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{U}{B}");
@ -24,13 +30,17 @@ public final class ArtfulTakedown extends CardImpl {
this.getSpellAbility().getModes().setMaxModes(2);
// Tap target creature.
this.getSpellAbility().addEffect(new TapTargetEffect());
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
this.getSpellAbility().addEffect(
new TapTargetEffect().setText("target creature")
);
this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter1));
// Target creature gets -2/-4 until end of turn.
Mode mode = new Mode();
mode.getEffects().add(new BoostTargetEffect(-2, -4, Duration.EndOfTurn));
mode.getTargets().add(new TargetCreaturePermanent());
Mode mode = new Mode(
new BoostTargetEffect(-2, -4, Duration.EndOfTurn)
.setText("target creature gets -2/-4 until end of turn")
);
mode.addTarget(new TargetCreaturePermanent(filter2));
this.getSpellAbility().addMode(mode);
}

View file

@ -1,4 +1,3 @@
package mage.cards.a;
import java.util.UUID;
@ -6,6 +5,7 @@ import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.Cost;
import mage.abilities.costs.VariableCost;
import mage.abilities.costs.VariableCostImpl;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.common.TapTargetCost;
@ -16,17 +16,21 @@ import mage.abilities.keyword.VigilanceAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.ComparisonType;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.constants.TargetAdjustment;
import mage.constants.Zone;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.PowerPredicate;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.filter.predicate.permanent.TappedPredicate;
import mage.game.Game;
import mage.game.permanent.token.KnightToken;
import mage.target.common.TargetControlledPermanent;
import mage.target.common.TargetCreaturePermanent;
import mage.target.targetadjustment.TargetAdjuster;
/**
*
@ -57,9 +61,8 @@ public final class AryelKnightOfWindgrace extends CardImpl {
.setText("Destroy target creature with power X or less"), new ManaCostsImpl("{B}"));
ability.addCost(new TapSourceCost());
ability.addCost(new AryelTapXTargetCost());
ability.setTargetAdjustment(TargetAdjustment.CREATURE_POWER_X_OR_LESS);
ability.setTargetAdjuster(AryelKnightOfWindgraceAdjuster.instance);
this.addAbility(ability);
ability.getOriginalId();
}
public AryelKnightOfWindgrace(final AryelKnightOfWindgrace card) {
@ -106,3 +109,19 @@ class AryelTapXTargetCost extends VariableCostImpl {
return new TapTargetCost(target);
}
}
enum AryelKnightOfWindgraceAdjuster implements TargetAdjuster {
instance;
@Override
public void adjustTargets(Ability ability, Game game) {
int value = 0;
for (VariableCost cost : ability.getCosts().getVariableCosts()) {
value = cost.getAmount();
}
FilterCreaturePermanent filterCreaturePermanent = new FilterCreaturePermanent("creature with power " + value + " or less");
filterCreaturePermanent.add(new PowerPredicate(ComparisonType.FEWER_THAN, value + 1));
ability.getTargets().clear();
ability.addTarget(new TargetCreaturePermanent(filterCreaturePermanent));
}
}

View file

@ -57,7 +57,7 @@ class AshesOfTheFallenEffect extends ContinuousEffectImpl {
Player controller = game.getPlayer(source.getControllerId());
Permanent permanent = game.getPermanent(source.getSourceId());
if (controller != null && permanent != null) {
SubType subType = ChooseCreatureTypeEffect.getChoosenCreatureType(permanent.getId(), game);
SubType subType = ChooseCreatureTypeEffect.getChosenCreatureType(permanent.getId(), game);
if (subType != null) {
for (UUID cardId : controller.getGraveyard()) {
Card card = game.getCard(cardId);

View file

@ -5,7 +5,7 @@ import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
import mage.abilities.costs.Cost;
import mage.abilities.costs.common.PayVariableLoyaltyCost;
import mage.abilities.effects.ContinuousEffectImpl;
@ -35,7 +35,7 @@ public final class AshiokNightmareWeaver extends CardImpl {
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.ASHIOK);
this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(3));
this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(3));
// +2: Exile the top three cards of target opponent's library.
LoyaltyAbility ability = new LoyaltyAbility(new AshiokNightmareWeaverExileEffect(), 2);

View file

@ -5,7 +5,7 @@ import java.util.List;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DamageControllerEffect;
@ -37,7 +37,7 @@ public final class AurraSingBaneOfJedi extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{2}{B}{R}");
this.subtype.add(SubType.AURRA);
this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(3));
this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(3));
// +1:You may have {this} deal 2 damage to target creature. If you don't, {this} deals 1 damage to you.
Ability ability = new LoyaltyAbility(new AurraSingBaneOfJediEffect(), +1);

View file

@ -2,6 +2,7 @@
package mage.cards.a;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.BeginningOfEndStepTriggeredAbility;
import mage.abilities.condition.common.EquippedSourceCondition;
@ -9,27 +10,25 @@ import mage.abilities.effects.common.TransformSourceEffect;
import mage.abilities.keyword.TransformAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.l.LunarchInquisitors;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.TargetController;
import mage.constants.Zone;
/**
*
* @author fireshoes
*/
public final class AvacynianMissionaries extends CardImpl {
public AvacynianMissionaries(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{W}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.CLERIC);
this.power = new MageInt(3);
this.toughness = new MageInt(3);
this.transformable = true;
this.secondSideCardClazz = LunarchInquisitors.class;
this.secondSideCardClazz = mage.cards.l.LunarchInquisitors.class;
// At the beginning of your end step, if Avacynian Missionaries is equipped, transform it.
this.addAbility(new TransformAbility());

View file

@ -4,6 +4,7 @@ package mage.cards.a;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
@ -16,7 +17,6 @@ import mage.abilities.keyword.TransformAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.s.SanctumOfTheSun;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SuperType;
@ -28,7 +28,6 @@ import mage.target.common.TargetCardInHand;
import mage.util.CardUtil;
/**
*
* @author LevelX2
*/
public final class AzorsGateway extends CardImpl {
@ -38,7 +37,7 @@ public final class AzorsGateway extends CardImpl {
this.addSuperType(SuperType.LEGENDARY);
this.transformable = true;
this.secondSideCardClazz = SanctumOfTheSun.class;
this.secondSideCardClazz = mage.cards.s.SanctumOfTheSun.class;
// {1}, {T}: Draw a card, then exile a card from your hand. If cards with five or more different converted mana costs are exiled with Azor's Gateway, you gain 5 life, untap Azor's Gateway, and transform it.
this.addAbility(new TransformAbility());

View file

@ -0,0 +1,186 @@
package mage.cards.b;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.common.SpellCastAllTriggeredAbility;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.abilities.keyword.TrampleAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.SetTargetPointer;
import mage.constants.Zone;
import mage.counters.CounterType;
import mage.filter.FilterSpell;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.game.stack.Spell;
import mage.util.CardUtil;
/**
*
* @author L_J
*/
public final class BINGO extends CardImpl {
public BINGO(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{G}");
this.subtype.add(SubType.HOUND);
this.power = new MageInt(1);
this.toughness = new MageInt(1);
// Trample
this.addAbility(TrampleAbility.getInstance());
// Whenever a player casts a spell, put a chip counter on its converted mana cost.
this.addAbility(new SpellCastAllTriggeredAbility(new BingoEffect(), new FilterSpell("a spell"), false, SetTargetPointer.SPELL));
// B-I-N-G-O gets +9/+9 for each set of three numbers in a row with chip counters on them.
BingoCount count = new BingoCount();
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostSourceEffect(count, count, Duration.WhileOnBattlefield)));
}
public BINGO(final BINGO card) {
super(card);
}
@Override
public BINGO copy() {
return new BINGO(this);
}
}
class BingoEffect extends OneShotEffect {
public BingoEffect() {
super(Outcome.Neutral);
staticText = "put a chip counter on its converted mana cost";
}
public BingoEffect(final BingoEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Spell spell = game.getStack().getSpell(this.getTargetPointer().getFirst(game, source));
if (spell != null) {
if (spell.getConvertedManaCost() > 9) {
return true;
}
MageObject mageObject = game.getObject(source.getSourceId());
if (mageObject != null) {
Map<Integer, Integer> chipCounters = new HashMap<>(); // Map<number, amount of counters>
if (game.getState().getValue(mageObject.getId() + "_chip") != null) {
chipCounters.putAll((Map<Integer, Integer>) game.getState().getValue(mageObject.getId() + "_chip"));
}
chipCounters.putIfAbsent(spell.getConvertedManaCost(), 0);
chipCounters.put(spell.getConvertedManaCost(), chipCounters.get(spell.getConvertedManaCost()) + 1);
game.getState().setValue(mageObject.getId() + "_chip", chipCounters);
if (mageObject instanceof Permanent) {
StringBuilder sb = new StringBuilder();
int i = 0;
for (Map.Entry<Integer, Integer> entry : chipCounters.entrySet()) {
i++;
sb.append(entry.getKey());
if (i < chipCounters.size()) {
sb.append(", ");
}
}
((Permanent) mageObject).addInfo("chip counters", CardUtil.addToolTipMarkTags("Chip counters at: " + sb), game);
new AddCountersSourceEffect(CounterType.CHIP.createInstance()).apply(game, source);
}
return true;
}
}
return false;
}
@Override
public BingoEffect copy() {
return new BingoEffect(this);
}
}
class BingoCount implements DynamicValue {
public BingoCount() {
}
public BingoCount(final BingoCount countersCount) {
}
@Override
public int calculate(Game game, Ability sourceAbility, Effect effect) {
MageObject mageObject = game.getObject(sourceAbility.getSourceId());
if (mageObject instanceof Permanent) {
Permanent permanent = game.getPermanentOrLKIBattlefield(sourceAbility.getSourceId());
if (permanent != null && game.getState().getValue(mageObject.getId() + "_chip") != null) {
int rows = 0;
Set<Integer> nums = ((Map<Integer, Integer>) game.getState().getValue(mageObject.getId() + "_chip")).keySet();
// if (nums.size() <= permanent.getCounters(game).getCount(CounterType.CHIP)) {
// 1 4 7
// 8 5 3
// 2 0 6
if (nums.contains(1) && nums.contains(4) && nums.contains(7)) {
rows++;
}
if (nums.contains(1) && nums.contains(8) && nums.contains(2)) {
rows++;
}
if (nums.contains(1) && nums.contains(5) && nums.contains(6)) {
rows++;
}
if (nums.contains(8) && nums.contains(5) && nums.contains(3)) {
rows++;
}
if (nums.contains(4) && nums.contains(5) && nums.contains(0)) {
rows++;
}
if (nums.contains(2) && nums.contains(0) && nums.contains(6)) {
rows++;
}
if (nums.contains(7) && nums.contains(3) && nums.contains(6)) {
rows++;
}
if (nums.contains(2) && nums.contains(5) && nums.contains(7)) {
rows++;
}
return rows * 9;
// }
}
}
return 0;
}
@Override
public BingoCount copy() {
return new BingoCount(this);
}
@Override
public String toString() {
return "9";
}
@Override
public String getMessage() {
return "set of three numbers in a row with chip counters on them";
}
}

View file

@ -7,6 +7,7 @@ import mage.abilities.keyword.JumpStartAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.target.common.TargetCreaturePermanent;
/**
*
@ -23,6 +24,7 @@ public final class BeaconBolt extends CardImpl {
).setText("{this} deals damage to target creature equal to "
+ "the total number of instant and sorcery cards "
+ "you own in exile and in your graveyard"));
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
// Jump-start
this.addAbility(new JumpStartAbility(this));

View file

@ -0,0 +1,226 @@
package mage.cards.b;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.OneShotEffect;
import mage.constants.SubType;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterControlledPermanent;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.game.stack.Spell;
import mage.players.Player;
import mage.target.Target;
import mage.target.TargetPermanent;
import mage.target.targetpointer.FixedTarget;
/**
*
* @author TheElk801
*/
public final class BeamsplitterMage extends CardImpl {
public BeamsplitterMage(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{U}{R}");
this.subtype.add(SubType.VEDALKEN);
this.subtype.add(SubType.WIZARD);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// Whenever you cast an instant or sorcery spell that targets only Beamsplitter Mage, if you control one or more creatures that spell could target, choose one of those creatures. Copy that spell. The copy targets the chosen creature.
this.addAbility(new BeamsplitterMageTriggeredAbility());
}
public BeamsplitterMage(final BeamsplitterMage card) {
super(card);
}
@Override
public BeamsplitterMage copy() {
return new BeamsplitterMage(this);
}
}
class BeamsplitterMageTriggeredAbility extends TriggeredAbilityImpl {
public BeamsplitterMageTriggeredAbility() {
super(Zone.BATTLEFIELD, new BeamsplitterMageEffect(), false);
}
public BeamsplitterMageTriggeredAbility(final BeamsplitterMageTriggeredAbility ability) {
super(ability);
}
@Override
public BeamsplitterMageTriggeredAbility copy() {
return new BeamsplitterMageTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.SPELL_CAST;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (event.getPlayerId().equals(this.getControllerId())) {
Spell spell = game.getStack().getSpell(event.getTargetId());
if (!isControlledInstantOrSorcery(spell)) {
return false;
}
boolean targetsSource = false;
for (Ability ability : spell.getSpellAbilities()) {
for (UUID modeId : ability.getModes().getSelectedModes()) {
Mode mode = ability.getModes().get(modeId);
for (Target target : mode.getTargets()) {
if (!target.isNotTarget()) {
for (UUID targetId : target.getTargets()) {
if (targetId.equals(getSourceId())) {
targetsSource = true;
} else {
return false;
}
}
}
}
}
}
if (targetsSource) {
this.getEffects().get(0).setTargetPointer(new FixedTarget(spell.getId()));
return true;
}
}
return false;
}
private boolean isControlledInstantOrSorcery(Spell spell) {
return spell != null
&& (spell.isControlledBy(this.getControllerId()))
&& (spell.isInstant() || spell.isSorcery());
}
@Override
public String getRule() {
return "Whenever you cast an instant or sorcery spell that targets "
+ "only {this}, if you control one or more creatures "
+ "that spell could target, choose one of those creatures. "
+ "Copy that spell. The copy targets the chosen creature.";
}
}
class BeamsplitterMageEffect extends OneShotEffect {
public BeamsplitterMageEffect() {
super(Outcome.Detriment);
}
public BeamsplitterMageEffect(final BeamsplitterMageEffect effect) {
super(effect);
}
@Override
public BeamsplitterMageEffect copy() {
return new BeamsplitterMageEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Spell spell = game.getSpellOrLKIStack(this.getTargetPointer().getFirst(game, source));
Player controller = game.getPlayer(source.getControllerId());
if (spell != null && controller != null) {
// search the target that targets source
Target usedTarget = null;
setUsedTarget:
for (Ability ability : spell.getSpellAbilities()) {
for (UUID modeId : ability.getModes().getSelectedModes()) {
Mode mode = ability.getModes().get(modeId);
for (Target target : mode.getTargets()) {
if (!target.isNotTarget() && target.getFirstTarget().equals(source.getSourceId())) {
usedTarget = target.copy();
usedTarget.clearChosen();
break setUsedTarget;
}
}
}
}
if (usedTarget == null) {
return false;
}
FilterPermanent filter = new BeamsplitterMageFilter(usedTarget, source.getSourceId());
Target target1 = new TargetPermanent(filter);
target1.setNotTarget(true);
if (controller.choose(outcome, target1, source.getSourceId(), game)) {
Permanent creature = game.getPermanent(target1.getFirstTarget());
if (creature == null) {
return false;
}
Spell copy = spell.copySpell(source.getControllerId());
game.getStack().push(copy);
setTarget:
for (UUID modeId : copy.getSpellAbility().getModes().getSelectedModes()) {
Mode mode = copy.getSpellAbility().getModes().get(modeId);
for (Target target : mode.getTargets()) {
if (target.getClass().equals(usedTarget.getClass())) {
target.clearChosen(); // For targets with Max > 1 we need to clear before the text is comapred
if (target.getMessage().equals(usedTarget.getMessage())) {
target.addTarget(creature.getId(), copy.getSpellAbility(), game, false);
break setTarget;
}
}
}
}
game.fireEvent(new GameEvent(GameEvent.EventType.COPIED_STACKOBJECT, copy.getId(), spell.getId(), source.getControllerId()));
String activateMessage = copy.getActivatedMessage(game);
if (activateMessage.startsWith(" casts ")) {
activateMessage = activateMessage.substring(6);
}
if (!game.isSimulation()) {
game.informPlayers(controller.getLogName() + activateMessage);
}
}
return true;
}
return false;
}
}
class BeamsplitterMageFilter extends FilterControlledPermanent {
private final Target target;
private final UUID notId;
public BeamsplitterMageFilter(Target target, UUID notId) {
super("creature this spell could target");
this.target = target;
this.notId = notId;
}
public BeamsplitterMageFilter(final BeamsplitterMageFilter filter) {
super(filter);
this.target = filter.target;
this.notId = filter.notId;
}
@Override
public BeamsplitterMageFilter copy() {
return new BeamsplitterMageFilter(this);
}
@Override
public boolean match(Permanent permanent, UUID sourceId, UUID playerId, Game game) {
return super.match(permanent, game)
&& permanent.isCreature()
&& !permanent.getId().equals(notId)
&& target.canTarget(permanent.getId(), game);
}
}

View file

@ -0,0 +1,36 @@
package mage.cards.b;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.keyword.TrampleAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
/**
*
* @author L_J
*/
public final class BeastInShow extends CardImpl {
public BeastInShow(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{G}{G}");
this.subtype.add(SubType.BEAST);
this.power = new MageInt(6);
this.toughness = new MageInt(4);
// Trample
this.addAbility(TrampleAbility.getInstance());
}
public BeastInShow(final BeastInShow card) {
super(card);
}
@Override
public BeastInShow copy() {
return new BeastInShow(this);
}
}

View file

@ -0,0 +1,57 @@
package mage.cards.b;
import java.util.UUID;
import mage.abilities.condition.common.KickedCondition;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.decorator.ConditionalOneShotEffect;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.keyword.BuybackAbility;
import mage.abilities.keyword.CyclingAbility;
import mage.abilities.keyword.FlashbackAbility;
import mage.abilities.keyword.KickerAbility;
import mage.abilities.keyword.MadnessAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.TimingRule;
import mage.game.permanent.token.GoblinToken;
import mage.target.common.TargetAnyTarget;
/**
*
* @author L_J
*/
public final class BlastFromThePast extends CardImpl {
public BlastFromThePast (UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{R}");
// Madness {R}
this.addAbility(new MadnessAbility(this, new ManaCostsImpl("{R}")));
// Cycling {1}{R}
this.addAbility(new CyclingAbility(new ManaCostsImpl("{1}{R}")));
// Kicker {2}{R}
this.addAbility(new KickerAbility("{2}{R}"));
// Flashback {3}{R}
this.addAbility(new FlashbackAbility(new ManaCostsImpl("{3}{R}"), TimingRule.INSTANT));
// Buyback {4}{R}
this.addAbility(new BuybackAbility("{4}{R}"));
// Blast from the Past deals 2 damage to any target. If this spell was kicked, create a 1/1 red Goblin creature token.
this.getSpellAbility().addEffect(new DamageTargetEffect(2));
this.getSpellAbility().addTarget(new TargetAnyTarget());
this.getSpellAbility().addEffect(new ConditionalOneShotEffect(new CreateTokenEffect(new GoblinToken()), KickedCondition.instance));
}
public BlastFromThePast (final BlastFromThePast card) {
super(card);
}
@Override
public BlastFromThePast copy() {
return new BlastFromThePast(this);
}
}

View file

@ -0,0 +1,40 @@
package mage.cards.b;
import mage.abilities.effects.common.TapAllEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.ComparisonType;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.common.FilterOpponentsCreaturePermanent;
import mage.filter.predicate.mageobject.ToughnessPredicate;
import java.util.UUID;
/**
* @author JayDi85
*/
public final class BlindingRadiance extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterOpponentsCreaturePermanent("creatures your opponents control with toughness 2 or less");
static {
filter.add(new ToughnessPredicate(ComparisonType.FEWER_THAN, 3));
}
public BlindingRadiance(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{W}");
// Tap all creatures your opponents control with toughness 2 or less.
TapAllEffect effect = new TapAllEffect(filter);
this.getSpellAbility().addEffect(effect);
}
public BlindingRadiance(final BlindingRadiance card) {
super(card);
}
@Override
public BlindingRadiance copy() {
return new BlindingRadiance(this);
}
}

View file

@ -59,7 +59,7 @@ public final class BloodOperative extends CardImpl {
class BloodOperativeTriggeredAbility extends TriggeredAbilityImpl {
public BloodOperativeTriggeredAbility() {
super(Zone.BATTLEFIELD, new DoIfCostPaid(new ReturnSourceFromGraveyardToHandEffect(), new PayLifeCost(3)), false);
super(Zone.GRAVEYARD, new DoIfCostPaid(new ReturnSourceFromGraveyardToHandEffect(), new PayLifeCost(3)), false);
}
public BloodOperativeTriggeredAbility(final BloodOperativeTriggeredAbility ability) {

View file

@ -0,0 +1,110 @@
package mage.cards.b;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.StateTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DamageEverythingEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.common.FilterNonlandPermanent;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
/**
*
* @author L_J
*/
public final class Bloodletter extends CardImpl {
public Bloodletter(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{B}");
this.subtype.add(SubType.ZOMBIE);
this.power = new MageInt(2);
this.toughness = new MageInt(3);
// When the names of three or more nonland permanents begin with the same letter, sacrifice Bloodletter. If you do, it deals 2 damage to each creature and each player.
this.addAbility(new BloodletterStateTriggeredAbility());
}
public Bloodletter(final Bloodletter card) {
super(card);
}
@Override
public Bloodletter copy() {
return new Bloodletter(this);
}
}
class BloodletterStateTriggeredAbility extends StateTriggeredAbility {
public BloodletterStateTriggeredAbility() {
super(Zone.BATTLEFIELD, new BloodletterEffect());
}
public BloodletterStateTriggeredAbility(final BloodletterStateTriggeredAbility ability) {
super(ability);
}
@Override
public BloodletterStateTriggeredAbility copy() {
return new BloodletterStateTriggeredAbility(this);
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Map<Character, Integer> initialCount = new HashMap<>();
for (Permanent permanent : game.getBattlefield().getActivePermanents(new FilterNonlandPermanent(), getControllerId(), getSourceId(), game)) {
Character initial = permanent.getName().charAt(0);
initialCount.putIfAbsent(initial, 0);
initialCount.put(initial, initialCount.get(initial) + 1);
}
for (Map.Entry<Character, Integer> entry : initialCount.entrySet()) {
if (entry.getValue() >= 3) {
return true;
}
}
return false;
}
@Override
public String getRule() {
return "When the names of three or more nonland permanents begin with the same letter, " + super.getRule();
}
}
class BloodletterEffect extends OneShotEffect {
public BloodletterEffect() {
super(Outcome.Sacrifice);
staticText = "sacrifice {this}. If you do, it deals 2 damage to each creature and each player";
}
public BloodletterEffect(final BloodletterEffect effect) {
super(effect);
}
@Override
public BloodletterEffect copy() {
return new BloodletterEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent != null && permanent.sacrifice(source.getSourceId(), game)) {
return new DamageEverythingEffect(2).apply(game, source);
}
return false;
}
}

View file

@ -2,6 +2,7 @@
package mage.cards.b;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.ActivateIfConditionActivatedAbility;
@ -15,7 +16,6 @@ import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.TransformAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.l.LordOfLineage;
import mage.constants.CardType;
import mage.constants.ComparisonType;
import mage.constants.SubType;
@ -25,7 +25,6 @@ import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.game.permanent.token.VampireToken;
/**
*
* @author Loki
*/
public final class BloodlineKeeper extends CardImpl {
@ -44,7 +43,7 @@ public final class BloodlineKeeper extends CardImpl {
this.toughness = new MageInt(3);
this.transformable = true;
this.secondSideCardClazz = LordOfLineage.class;
this.secondSideCardClazz = mage.cards.l.LordOfLineage.class;
this.addAbility(FlyingAbility.getInstance());
// {T}: Create a 2/2 black Vampire creature token with flying.

View file

@ -55,7 +55,7 @@ public final class BlowflyInfestation extends CardImpl {
class BlowflyInfestationCondition implements Condition {
private static Permanent permanent;
private Permanent permanent;
@Override
public boolean apply(Game game, Ability source) {

View file

@ -31,8 +31,11 @@ public final class BoarUmbra extends CardImpl {
this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature));
Ability ability = new EnchantAbility(auraTarget.getTargetName());
this.addAbility(ability);
// Enchanted creature gets +3/+3.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEnchantedEffect(3, 3, Duration.WhileOnBattlefield)));
// Totem armor
this.addAbility(new TotemArmorAbility());
}

View file

@ -0,0 +1,106 @@
package mage.cards.b;
import java.util.HashSet;
import java.util.Set;
import java.util.List;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ChooseExpansionSetEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.CardsImpl;
import mage.cards.ExpansionSet;
import mage.cards.Sets;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetCard;
/**
*
* @author spjspj & L_J
*/
public final class BoosterTutor extends CardImpl {
public BoosterTutor(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{B}");
// Open a sealed Magic booster pack, reveal the cards, and put one of those cards into your hand.
this.getSpellAbility().addEffect(new BoosterTutorEffect());
}
public BoosterTutor(final BoosterTutor card) {
super(card);
}
@Override
public BoosterTutor copy() {
return new BoosterTutor(this);
}
}
class BoosterTutorEffect extends OneShotEffect {
public BoosterTutorEffect() {
super(Outcome.DestroyPermanent);
this.staticText = "Open a sealed Magic booster pack, reveal the cards, and put one of those cards into your hand";
}
public BoosterTutorEffect(final BoosterTutorEffect effect) {
super(effect);
}
@Override
public BoosterTutorEffect copy() {
return new BoosterTutorEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
ChooseExpansionSetEffect effect = new ChooseExpansionSetEffect(Outcome.UnboostCreature);
effect.apply(game, source);
Player controller = game.getPlayer(source.getControllerId());
String setChosen = null;
if (effect.getValue("setchosen") != null) {
setChosen = (String) effect.getValue("setchosen");
} else if (game.getState().getValue(this.getId() + "_set") != null) {
setChosen = (String) game.getState().getValue(this.getId() + "_set");
}
if (setChosen != null && controller != null) {
//ExpansionInfo set = ExpansionRepository.instance.getSetByName(setChosen);
ExpansionSet expansionSet = Sets.findSet(setChosen);
if (expansionSet != null) {
List<Card> boosterPack = expansionSet.create15CardBooster();
if (boosterPack != null) {
StringBuilder message = new StringBuilder(controller.getLogName()).append(" opened: ");
for (Card card : boosterPack) {
message.append(card.getName()).append(" ");
}
game.informPlayers(message.toString());
TargetCard targetCard = new TargetCard(Zone.ALL, new FilterCard());
Set<Card> cardsToLoad = new HashSet<Card>(boosterPack);
game.loadCards(cardsToLoad, controller.getId());
CardsImpl cards = new CardsImpl();
cards.addAll(boosterPack);
if (controller.choose(Outcome.Benefit, cards, targetCard, game)) {
Card card = game.getCard(targetCard.getFirstTarget());
if (card != null) {
controller.moveCards(card, Zone.HAND, source, game);
}
}
}
}
return true;
}
return false;
}
}

View file

@ -23,8 +23,8 @@ public final class BorosLocket extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}");
// {T}: Add {R} or {W}.
this.addAbility(new WhiteManaAbility());
this.addAbility(new RedManaAbility());
this.addAbility(new WhiteManaAbility());
// {R/W}{R/W}{R/W}{R/W}, {T}, Sacrifice Boros Locket: Draw two cards.
Ability ability = new SimpleActivatedAbility(

View file

@ -0,0 +1,47 @@
package mage.cards.b;
import java.util.UUID;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.filter.common.FilterCreaturePermanent;
import mage.target.common.TargetCreaturePermanent;
import mage.target.targetpointer.SecondTargetPointer;
import mage.target.targetpointer.ThirdTargetPointer;
/**
*
* @author Ryan-Saklad
*/
public final class BountyOfMight extends CardImpl {
public BountyOfMight(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{4}{G}{G}");
// Target creature gets +3/+3 until end of turn.
this.getSpellAbility().addEffect(new BoostTargetEffect(3, 3, Duration.EndOfTurn));
this.getSpellAbility().addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature (1st)")));
// Target creature gets +3/+3 until end of turn.
Effect effect = new BoostTargetEffect(3, 3, Duration.EndOfTurn).setText("<br>Target creature gets +3/+3 until end of turn.");
effect.setTargetPointer(new SecondTargetPointer());
this.getSpellAbility().addEffect(effect);
this.getSpellAbility().addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature (2nd)")));
// Target creature gets +3/+3 until end of turn.
effect = new BoostTargetEffect(3, 3, Duration.EndOfTurn).setText("<br>Target creature gets +3/+3 until end of turn.");
effect.setTargetPointer(new ThirdTargetPointer());
this.getSpellAbility().addEffect(effect);
this.getSpellAbility().addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature (3rd)")));
}
public BountyOfMight(final BountyOfMight card) {
super(card);
}
@Override
public BountyOfMight copy() {
return new BountyOfMight(this);
}
}

View file

@ -2,6 +2,7 @@
package mage.cards.b;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.TriggeredAbility;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
@ -11,25 +12,23 @@ import mage.abilities.effects.common.TransformSourceEffect;
import mage.abilities.keyword.TransformAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.n.NeckBreaker;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.TargetController;
/**
*
* @author fireshoes
*/
public final class BreakneckRider extends CardImpl {
public BreakneckRider(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{R}{R}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}{R}");
this.subtype.add(SubType.HUMAN, SubType.SCOUT, SubType.WEREWOLF);
this.power = new MageInt(3);
this.toughness = new MageInt(3);
this.transformable = true;
this.secondSideCardClazz = NeckBreaker.class;
this.secondSideCardClazz = mage.cards.n.NeckBreaker.class;
// At the beginning of each upkeep, if no spells were cast last turn, transform Breakneck Rider.
this.addAbility(new TransformAbility());

View file

@ -1,6 +1,5 @@
package mage.cards.b;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfCombatTriggeredAbility;
@ -11,13 +10,7 @@ import mage.abilities.effects.common.continuous.GainAbilityAllEffect;
import mage.abilities.keyword.HasteAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.constants.TargetController;
import mage.constants.Zone;
import mage.constants.*;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.predicate.permanent.TokenPredicate;
@ -28,8 +21,9 @@ import mage.players.Player;
import mage.target.common.TargetControlledPermanent;
import mage.util.functions.EmptyApplyToPermanent;
import java.util.UUID;
/**
*
* @author spjspj
*/
public final class BrudicladTelchorEngineer extends CardImpl {
@ -52,7 +46,7 @@ public final class BrudicladTelchorEngineer extends CardImpl {
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAllEffect(HasteAbility.getInstance(), Duration.WhileOnBattlefield, filter, true)));
// At the beginning of combat on your turn, create a 2/1 blue Myr artifact creature token. Then you may choose a token you control. If you do, each other token you control becomes a copy of that token.
this.addAbility(new BeginningOfCombatTriggeredAbility(new BrudicladTelchorCombatffect(), TargetController.YOU, false));
this.addAbility(new BeginningOfCombatTriggeredAbility(new BrudicladTelchorEngineerEffect(), TargetController.YOU, false));
}
public BrudicladTelchorEngineer(final BrudicladTelchorEngineer card) {
@ -65,26 +59,26 @@ public final class BrudicladTelchorEngineer extends CardImpl {
}
}
class BrudicladTelchorCombatffect extends OneShotEffect {
class BrudicladTelchorEngineerEffect extends OneShotEffect {
private static final FilterControlledPermanent filter = new FilterControlledPermanent(" token you control. If you do, each other token you control becomes a copy of that token");
private static final FilterControlledPermanent filter = new FilterControlledPermanent("token you control");
static {
filter.add(new TokenPredicate());
}
public BrudicladTelchorCombatffect() {
public BrudicladTelchorEngineerEffect() {
super(Outcome.Sacrifice);
this.staticText = " create a 2/1 blue Myr artifact creature token. Then you may choose a token you control. If you do, each other token you control becomes a copy of that token";
}
public BrudicladTelchorCombatffect(final BrudicladTelchorCombatffect effect) {
public BrudicladTelchorEngineerEffect(final BrudicladTelchorEngineerEffect effect) {
super(effect);
}
@Override
public BrudicladTelchorCombatffect copy() {
return new BrudicladTelchorCombatffect(this);
public BrudicladTelchorEngineerEffect copy() {
return new BrudicladTelchorEngineerEffect(this);
}
@Override
@ -95,7 +89,8 @@ class BrudicladTelchorCombatffect extends OneShotEffect {
if (effect.apply(game, source)) {
TargetControlledPermanent target = new TargetControlledPermanent(0, 1, filter, true);
target.setNotTarget(true);
if (controller.choose(Outcome.Neutral, target, source.getSourceId(), game)) {
if (controller.chooseUse(outcome, "Select a token to copy?", source, game)
&& controller.choose(Outcome.Neutral, target, source.getSourceId(), game)) {
Permanent toCopyFromPermanent = game.getPermanent(target.getFirstTarget());
if (toCopyFromPermanent != null) {

View file

@ -0,0 +1,235 @@
package mage.cards.b;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.BeginningOfEndStepTriggeredAbility;
import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
import mage.abilities.condition.Condition;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.FilterPlayer;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.other.PlayerIdPredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.Target;
import mage.target.TargetPlayer;
import mage.target.targetpointer.FixedTarget;
import mage.watchers.Watcher;
/**
*
* @author L_J
*/
public final class BurningCinderFuryOfCrimsonChaosFire extends CardImpl {
public BurningCinderFuryOfCrimsonChaosFire(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{R}");
// Whenever any player taps a permanent, that player choose one of their opponents. The chosen player gains control of that permanent at the beginning of the next end step.
this.addAbility(new BurningCinderFuryOfCrimsonChaosFireAbility());
// At the beginning of each players end step, if that player didnt tap any nonland permanents that turn, Burning Cinder Fury of Crimson Chaos Fire deals 3 damage to that player.
this.addAbility(new BeginningOfEndStepTriggeredAbility(Zone.BATTLEFIELD, new DamageTargetEffect(3).setText("{this} deals 3 damage to that player"),
TargetController.ANY, new BurningCinderFuryOfCrimsonChaosFireCondition(), false), new BurningCinderFuryOfCrimsonChaosFireWatcher());
}
public BurningCinderFuryOfCrimsonChaosFire(final BurningCinderFuryOfCrimsonChaosFire card) {
super(card);
}
@Override
public BurningCinderFuryOfCrimsonChaosFire copy() {
return new BurningCinderFuryOfCrimsonChaosFire(this);
}
}
class BurningCinderFuryOfCrimsonChaosFireAbility extends TriggeredAbilityImpl {
public BurningCinderFuryOfCrimsonChaosFireAbility() {
super(Zone.BATTLEFIELD, new BurningCinderFuryOfCrimsonChaosFireEffect(), false);
}
public BurningCinderFuryOfCrimsonChaosFireAbility(BurningCinderFuryOfCrimsonChaosFireAbility ability) {
super(ability);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.TAPPED;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Permanent permanent = game.getPermanent(event.getTargetId());
if (permanent != null) {
BurningCinderFuryOfCrimsonChaosFireEffect effect = (BurningCinderFuryOfCrimsonChaosFireEffect) this.getEffects().get(0);
effect.setTargetPointer(new FixedTarget(permanent, game));
effect.setFirstControllerId(permanent.getControllerId()); // it's necessary to remember the original controller, as the controller might change by the time the trigger resolves
return true;
}
return false;
}
@Override
public BurningCinderFuryOfCrimsonChaosFireAbility copy() {
return new BurningCinderFuryOfCrimsonChaosFireAbility(this);
}
@Override
public String getRule() {
return "Whenever any player taps a permanent, " + super.getRule();
}
}
class BurningCinderFuryOfCrimsonChaosFireEffect extends OneShotEffect {
private UUID firstControllerId = null;
public BurningCinderFuryOfCrimsonChaosFireEffect() {
super(Outcome.Detriment);
this.staticText = "that player choose one of their opponents. The chosen player gains control of that permanent at the beginning of the next end step";
}
public BurningCinderFuryOfCrimsonChaosFireEffect(final BurningCinderFuryOfCrimsonChaosFireEffect effect) {
super(effect);
this.firstControllerId = effect.firstControllerId;
}
@Override
public BurningCinderFuryOfCrimsonChaosFireEffect copy() {
return new BurningCinderFuryOfCrimsonChaosFireEffect(this);
}
public void setFirstControllerId(UUID newId) {
this.firstControllerId = newId;
}
@Override
public boolean apply(Game game, Ability source) {
Player tappingPlayer = game.getPlayer(firstControllerId);
Permanent permanentToControl = game.getPermanent(this.getTargetPointer().getFirst(game, source));
if (tappingPlayer != null && permanentToControl != null) {
// Create opponent filter list manually because otherwise opponent check prevents controller of this to be valid
FilterPlayer filter = new FilterPlayer("opponent to control " + permanentToControl.getIdName());
List<PlayerIdPredicate> opponentPredicates = new ArrayList<>();
for (UUID opponentId : game.getOpponents(firstControllerId)) {
opponentPredicates.add(new PlayerIdPredicate(opponentId));
}
filter.add(Predicates.or(opponentPredicates));
Target target = new TargetPlayer(1, 1, true, filter);
target.setTargetController(firstControllerId);
target.setAbilityController(source.getControllerId());
if (tappingPlayer.chooseTarget(outcome, target, source, game)) {
Player chosenOpponent = game.getPlayer(target.getFirstTarget());
if (chosenOpponent != null) {
game.informPlayers(tappingPlayer.getLogName() + " chose " + chosenOpponent.getLogName() + " to gain control of " + permanentToControl.getLogName() + " at the beginning of the next end step");
ContinuousEffect effect = new BurningCinderFuryOfCrimsonChaosFireCreatureGainControlEffect(Duration.Custom, chosenOpponent.getId());
effect.setTargetPointer(new FixedTarget(permanentToControl.getId()));
game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(effect), source);
return true;
}
}
}
return false;
}
}
class BurningCinderFuryOfCrimsonChaosFireCreatureGainControlEffect extends ContinuousEffectImpl {
private UUID controller;
public BurningCinderFuryOfCrimsonChaosFireCreatureGainControlEffect(Duration duration, UUID controller) {
super(duration, Layer.ControlChangingEffects_2, SubLayer.NA, Outcome.GainControl);
this.controller = controller;
this.staticText = "the chosen player gains control of that permanent";
}
public BurningCinderFuryOfCrimsonChaosFireCreatureGainControlEffect(final BurningCinderFuryOfCrimsonChaosFireCreatureGainControlEffect effect) {
super(effect);
this.controller = effect.controller;
}
@Override
public BurningCinderFuryOfCrimsonChaosFireCreatureGainControlEffect copy() {
return new BurningCinderFuryOfCrimsonChaosFireCreatureGainControlEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getFirstTarget());
if (targetPointer != null) {
permanent = game.getPermanent(targetPointer.getFirst(game, source));
}
if (permanent != null && controller != null) {
return permanent.changeControllerId(controller, game);
}
return false;
}
}
class BurningCinderFuryOfCrimsonChaosFireCondition implements Condition {
@Override
public boolean apply(Game game, Ability source) {
BurningCinderFuryOfCrimsonChaosFireWatcher watcher = (BurningCinderFuryOfCrimsonChaosFireWatcher) game.getState().getWatchers().get(BurningCinderFuryOfCrimsonChaosFireWatcher.class.getSimpleName());
if (watcher != null) {
return !watcher.tappedNonlandThisTurn(game.getActivePlayerId());
}
return false;
}
public String toString() {
return "if that player didnt tap any nonland permanents that turn";
}
}
class BurningCinderFuryOfCrimsonChaosFireWatcher extends Watcher {
private final Set<UUID> tappedActivePlayerIds = new HashSet<>();
public BurningCinderFuryOfCrimsonChaosFireWatcher() {
super(BurningCinderFuryOfCrimsonChaosFireWatcher.class.getSimpleName(), WatcherScope.GAME);
}
public BurningCinderFuryOfCrimsonChaosFireWatcher(final BurningCinderFuryOfCrimsonChaosFireWatcher watcher) {
super(watcher);
this.tappedActivePlayerIds.addAll(watcher.tappedActivePlayerIds);
}
@Override
public void watch(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.TAPPED) {
Permanent permanent = game.getPermanent(event.getTargetId());
if (permanent != null && !permanent.isLand()) {
tappedActivePlayerIds.add(permanent.getControllerId());
}
}
}
public boolean tappedNonlandThisTurn(UUID playerId) {
return tappedActivePlayerIds.contains(playerId);
}
@Override
public void reset() {
tappedActivePlayerIds.clear();
}
@Override
public BurningCinderFuryOfCrimsonChaosFireWatcher copy() {
return new BurningCinderFuryOfCrimsonChaosFireWatcher(this);
}
}

View file

@ -56,7 +56,7 @@ class CamaraderieEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getSourceId());
Player player = game.getPlayer(source.getControllerId());
if (player == null) {
return false;
}

View file

@ -1,4 +1,3 @@
package mage.cards.c;
import java.util.UUID;
@ -11,10 +10,10 @@ import mage.abilities.effects.common.UntapTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.TargetAdjustment;
import mage.constants.Zone;
import mage.filter.StaticFilters;
import mage.target.TargetPermanent;
import mage.target.targetadjustment.XTargetsAdjuster;
/**
*
@ -31,7 +30,7 @@ public final class CandelabraOfTawnos extends CardImpl {
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{X}"));
ability.addCost(new TapSourceCost());
ability.addTarget(new TargetPermanent(StaticFilters.FILTER_LANDS));
ability.setTargetAdjustment(TargetAdjustment.X_TARGETS);
ability.setTargetAdjuster(XTargetsAdjuster.instance);
this.addAbility(ability);
}

View file

@ -0,0 +1,59 @@
package mage.cards.c;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.continuous.BoostEnchantedEffect;
import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect;
import mage.abilities.keyword.EnchantAbility;
import mage.abilities.keyword.VigilanceAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.AttachmentType;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.target.TargetPermanent;
import mage.target.common.TargetCreaturePermanent;
/**
*
* @author Ryan-Saklad
*/
public final class CandlelightVigil extends CardImpl {
public CandlelightVigil(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{W}");
this.subtype.add(SubType.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 gets +3/+2 and has vigilance.
Effect effect = new BoostEnchantedEffect(3, 2, Duration.WhileOnBattlefield);
effect.setText("Enchanted creature gets +3/+2");
SimpleStaticAbility ability2 = new SimpleStaticAbility(Zone.BATTLEFIELD, effect);
effect = new GainAbilityAttachedEffect(VigilanceAbility.getInstance(), AttachmentType.AURA);
effect.setText("and has vigilance");
ability2.addEffect(effect);
this.addAbility(ability2);
}
public CandlelightVigil(final CandlelightVigil card) {
super(card);
}
@Override
public CandlelightVigil copy() {
return new CandlelightVigil(this);
}
}

View file

@ -1,11 +1,10 @@
package mage.cards.c;
import java.util.UUID;
import mage.abilities.condition.LockedInCondition;
import mage.abilities.Ability;
import mage.abilities.condition.common.ManaWasSpentCondition;
import mage.abilities.decorator.ConditionalContinuousEffect;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.InfoEffect;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.cards.CardImpl;
@ -13,8 +12,13 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.ColoredManaSymbol;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.filter.common.FilterCreaturePermanent;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetCreaturePermanent;
import mage.target.targetpointer.SecondTargetPointer;
import mage.target.targetpointer.FixedTarget;
import mage.watchers.common.ManaSpentToCastWatcher;
/**
@ -28,19 +32,9 @@ public final class CankerousThirst extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{B/G}");
// If {B} was spent to cast Cankerous Thirst, you may have target creature get -3/-3 until end of turn. If {G} was spent to cast Cankerous Thirst, you may have target creature get +3/+3 until end of turn.
this.getSpellAbility().addEffect(new ConditionalContinuousEffect(
new BoostTargetEffect(-3, -3, Duration.EndOfTurn),
new LockedInCondition(new ManaWasSpentCondition(ColoredManaSymbol.B)),
"If {B} was spent to cast {this}, you may have target creature get -3/-3 until end of turn"));
ContinuousEffect effect = new BoostTargetEffect(3, 3, Duration.EndOfTurn);
effect.setTargetPointer(new SecondTargetPointer());
this.getSpellAbility().addEffect(new ConditionalContinuousEffect(
effect,
new LockedInCondition(new ManaWasSpentCondition(ColoredManaSymbol.G)),
"If {G} was spent to cast {this}, you may have target creature get +3/+3 until end of turn"));
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
this.getSpellAbility().addEffect(new CankerousThirstEffect());
this.getSpellAbility().addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature (1th effect -3/-3)")));
this.getSpellAbility().addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature (2nd effect +3/+3)")));
this.getSpellAbility().addEffect(new InfoEffect("<i>(Do both if {B}{G} was spent.)</i>"));
this.getSpellAbility().addWatcher(new ManaSpentToCastWatcher());
}
@ -55,3 +49,45 @@ public final class CankerousThirst extends CardImpl {
}
}
class CankerousThirstEffect extends OneShotEffect {
public CankerousThirstEffect() {
super(Outcome.Benefit);
this.staticText = "If {B} was spent to cast {this}, you may have target creature get -3/-3 until end of turn. If {G} was spent to cast {this}, you may have target creature get +3/+3 until end of turn";
}
public CankerousThirstEffect(final CankerousThirstEffect effect) {
super(effect);
}
@Override
public CankerousThirstEffect copy() {
return new CankerousThirstEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
if (new ManaWasSpentCondition(ColoredManaSymbol.B).apply(game, source)) {
Permanent targetCreature1 = game.getPermanent(getTargetPointer().getFirst(game, source));
if (targetCreature1 != null && controller.chooseUse(Outcome.UnboostCreature, "Let " + targetCreature1.getIdName() + " get -3/-3 until end of turn?", source, game)) {
ContinuousEffect effect = new BoostTargetEffect(-3, -3, Duration.EndOfTurn);
effect.setTargetPointer(new FixedTarget(targetCreature1, game));
game.addEffect(effect, source);
}
}
if (new ManaWasSpentCondition(ColoredManaSymbol.G).apply(game, source)) {
Permanent targetCreature2 = game.getPermanent(source.getTargets().get(1).getFirstTarget());
if (targetCreature2 != null && controller.chooseUse(Outcome.UnboostCreature, "Let " + targetCreature2.getIdName() + " get +3/+3 until end of turn?", source, game)) {
ContinuousEffect effect = new BoostTargetEffect(+3, +3, Duration.EndOfTurn);
effect.setTargetPointer(new FixedTarget(targetCreature2, game));
game.addEffect(effect, source);
}
}
return true;
}
return false;
}
}

View file

@ -0,0 +1,57 @@
package mage.cards.c;
import java.util.UUID;
import mage.constants.SubType;
import mage.abilities.keyword.FlashAbility;
import mage.target.common.TargetCreaturePermanent;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.DontUntapInControllersUntapStepEnchantedEffect;
import mage.abilities.effects.common.TapEnchantedEffect;
import mage.constants.Outcome;
import mage.target.TargetPermanent;
import mage.abilities.keyword.EnchantAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Zone;
/**
*
* @author TheElk801
*/
public final class CaptureSphere extends CardImpl {
public CaptureSphere(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{U}");
this.subtype.add(SubType.AURA);
// Flash
this.addAbility(FlashAbility.getInstance());
// 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);
// When Capture Sphere enters the battlefield, tap enchanted creature.
this.addAbility(new EntersBattlefieldTriggeredAbility(new TapEnchantedEffect()));
// Enchanted creature doesn't untap during its controller's untap step.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new DontUntapInControllersUntapStepEnchantedEffect()));
}
public CaptureSphere(final CaptureSphere card) {
super(card);
}
@Override
public CaptureSphere copy() {
return new CaptureSphere(this);
}
}

View file

@ -1,27 +1,34 @@
package mage.cards.c;
import java.util.UUID;
import mage.abilities.common.CreatureEntersBattlefieldTriggeredAbility;
import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility;
import mage.abilities.effects.common.counter.AddCountersAllEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Zone;
import mage.counters.CounterType;
import mage.filter.StaticFilters;
import mage.filter.common.FilterControlledCreaturePermanent;
import java.util.UUID;
/**
*
* @author Loki
*/
public final class CatharsCrusade extends CardImpl {
public CatharsCrusade(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{3}{W}{W}");
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{W}{W}");
// Whenever a creature enters the battlefield under your control, put a +1/+1 counter on each creature you control.
this.addAbility(new CreatureEntersBattlefieldTriggeredAbility(new AddCountersAllEffect(CounterType.P1P1.createInstance(), new FilterControlledCreaturePermanent())));
this.addAbility(new EntersBattlefieldControlledTriggeredAbility(
Zone.BATTLEFIELD,
new AddCountersAllEffect(CounterType.P1P1.createInstance(), new FilterControlledCreaturePermanent()),
StaticFilters.FILTER_PERMANENT_CREATURE_A,
false)
);
}
public CatharsCrusade(final CatharsCrusade card) {

View file

@ -64,7 +64,7 @@ class CavernOfSoulsManaBuilder extends ConditionalManaBuilder {
@Override
public ConditionalManaBuilder setMana(Mana mana, Ability source, Game game) {
SubType subType = ChooseCreatureTypeEffect.getChoosenCreatureType(source.getSourceId(), game);
SubType subType = ChooseCreatureTypeEffect.getChosenCreatureType(source.getSourceId(), game);
if (subType != null) {
creatureType = subType;
}

View file

@ -1,5 +1,6 @@
package mage.cards.c;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldAbility;
@ -25,27 +26,27 @@ import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.common.TargetAnyTarget;
import java.util.UUID;
/**
*
* @author jmharmon
*/
public final class ChamberSentry extends CardImpl {
public ChamberSentry(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT,CardType.CREATURE}, "{X}");
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{X}");
this.subtype.add(SubType.CONSTRUCT);
this.power = new MageInt(0);
this.toughness = new MageInt(0);
// Chamber Sentry enters the battlefield with a +1/+1 counter on it for each color of mana spent to cast it.
this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance(), ColorsOfManaSpentToCastCount.getInstance(), true)));
this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance(), ColorsOfManaSpentToCastCount.getInstance(), true),
"with a +1/+1 counter on it for each color of mana spent to cast it"));
// {X}, {T}, Remove X +1/+1 counters from Chamber Sentry: It deals X damage to any target.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(new ManacostVariableValue()), new ManaCostsImpl("{X}"));
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(new ManacostVariableValue())
.setText("It deals X damage to any target"),
new ManaCostsImpl("{X}"));
ability.addCost(new TapSourceCost());
ability.addCost(new ChamberSentryRemoveVariableCountersSourceCost(CounterType.P1P1.createInstance()));
ability.addTarget(new TargetAnyTarget());
@ -55,7 +56,7 @@ public final class ChamberSentry extends CardImpl {
this.addAbility(new SimpleActivatedAbility(Zone.GRAVEYARD, new ReturnSourceFromGraveyardToHandEffect(), new ManaCostsImpl("{W}{U}{B}{R}{G}")));
}
public ChamberSentry(final ChamberSentry card) {
public ChamberSentry(final ChamberSentry card) {
super(card);
}
@ -75,7 +76,7 @@ class ChamberSentryRemoveVariableCountersSourceCost extends VariableCostImpl {
}
public ChamberSentryRemoveVariableCountersSourceCost(Counter counter, String text) {
this(counter, 0,text);
this(counter, 0, text);
}
public ChamberSentryRemoveVariableCountersSourceCost(Counter counter, int minimalCountersToPay) {

View file

@ -21,7 +21,7 @@ public final class ChanceForGlory extends CardImpl {
// Creatures you control gain indestructible. Take an extra turn after this one. At the beginning of that turn's end step, you lose the game.
this.getSpellAbility().addEffect(new GainAbilityControlledEffect(
IndestructibleAbility.getInstance(), Duration.EndOfGame
).setText("Creatures you control gain indestructible."));
).setText("Creatures you control gain indestructible"));
this.getSpellAbility().addEffect(new AddExtraTurnControllerEffect(true));
}

View file

@ -7,7 +7,7 @@ import mage.MageObjectReference;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DrawCardAllEffect;
@ -41,7 +41,7 @@ public final class ChandraAblaze extends CardImpl {
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.CHANDRA);
this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(5));
this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(5));
// +1: Discard a card. If a red card is discarded this way, Chandra Ablaze deals 4 damage to any target.
LoyaltyAbility ability = new LoyaltyAbility(new ChandraAblazeEffect1(), 1);

View file

@ -5,7 +5,7 @@ import java.util.UUID;
import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
import mage.abilities.effects.Effects;
import mage.abilities.effects.mana.BasicManaEffect;
import mage.abilities.effects.common.DamageAllControlledTargetEffect;
@ -30,7 +30,7 @@ public final class ChandraBoldPyromancer extends CardImpl {
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.CHANDRA);
this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(5));
this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(5));
// +1: Add {R}{R}. Chandra, Bold Pyromancer deals 2 damage to target player.
Ability ability = new LoyaltyAbility(new BasicManaEffect(Mana.RedMana(2)), +1);

View file

@ -5,7 +5,7 @@ import java.util.Set;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
import mage.abilities.costs.Cost;
import mage.abilities.costs.common.PayVariableLoyaltyCost;
import mage.abilities.dynamicvalue.DynamicValue;
@ -36,7 +36,7 @@ public final class ChandraFlamecaller extends CardImpl {
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.CHANDRA);
this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(4));
this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(4));
// +1: Create two 3/1 red Elemental creature tokens with haste. Exile them at the beginning of the next end step.
this.addAbility(new LoyaltyAbility(new ChandraElementalEffect(), 1));

View file

@ -4,7 +4,7 @@ package mage.cards.c;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
import mage.abilities.costs.Cost;
import mage.abilities.costs.common.PayVariableLoyaltyCost;
import mage.abilities.dynamicvalue.DynamicValue;
@ -33,7 +33,7 @@ public final class ChandraNalaar extends CardImpl {
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.CHANDRA);
this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(6));
this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(6));
// +1: Chandra Nalaar deals 1 damage to target player or planeswalker.
LoyaltyAbility ability1 = new LoyaltyAbility(new DamageTargetEffect(1), 1);

View file

@ -3,7 +3,7 @@ package mage.cards.c;
import java.util.UUID;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.Effects;
import mage.abilities.effects.common.DamageAllControlledTargetEffect;
@ -31,7 +31,7 @@ public final class ChandraPyrogenius extends CardImpl {
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.CHANDRA);
this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(5));
this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(5));
// +2: Chandra, Pyrogenius deals 2 damage to each opponent.
this.addAbility(new LoyaltyAbility(new DamagePlayersEffect(Outcome.Damage, new StaticValue(2), TargetController.OPPONENT), 2));

View file

@ -1,4 +1,3 @@
package mage.cards.c;
import java.util.HashSet;
@ -8,10 +7,10 @@ import mage.MageObject;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility;
import mage.abilities.effects.AsThoughEffectImpl;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect;
import mage.abilities.effects.common.combat.CantBlockTargetEffect;
import mage.cards.*;
import mage.constants.*;
@ -20,7 +19,6 @@ import mage.filter.common.FilterInstantOrSorceryCard;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.game.stack.StackObject;
import mage.players.Library;
import mage.players.Player;
import mage.target.Target;
import mage.target.TargetCard;
@ -38,7 +36,7 @@ public final class ChandraPyromaster extends CardImpl {
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.CHANDRA);
this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(4));
this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(4));
// +1: Chandra, Pyromaster deals 1 damage to target player and 1 damage to up to one target creature that player controls. That creature can't block this turn.
LoyaltyAbility ability1 = new LoyaltyAbility(new ChandraPyromasterEffect1(), 1);
@ -177,12 +175,13 @@ class ChandraPyromasterEffect2 extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
MageObject sourceObject = source.getSourceObject(game);
if (controller != null && sourceObject != null && controller.getLibrary().hasCards()) {
Library library = controller.getLibrary();
Card card = library.getFromTop(game);
if (controller != null && sourceObject != null) {
Card card = controller.getLibrary().getFromTop(game);
if (card != null) {
controller.moveCardToExileWithInfo(card, source.getSourceId(), sourceObject.getIdName() + " <this card may be played the turn it was exiled>", source.getSourceId(), game, Zone.LIBRARY, true);
game.addEffect(new ChandraPyromasterPlayEffect(new MageObjectReference(card, game)), source);
controller.moveCards(card, Zone.EXILED, source, game);
ContinuousEffect effect = new PlayFromNotOwnHandZoneTargetEffect(Zone.EXILED, Duration.EndOfTurn);
effect.setTargetPointer(new FixedTarget(card, game));
game.addEffect(effect, source);
}
return true;
}
@ -190,45 +189,6 @@ class ChandraPyromasterEffect2 extends OneShotEffect {
}
}
class ChandraPyromasterPlayEffect extends AsThoughEffectImpl {
private final MageObjectReference objectReference;
public ChandraPyromasterPlayEffect(MageObjectReference objectReference) {
super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfTurn, Outcome.Benefit);
this.objectReference = objectReference;
staticText = "you may play that card until end of turn";
}
public ChandraPyromasterPlayEffect(final ChandraPyromasterPlayEffect effect) {
super(effect);
this.objectReference = effect.objectReference;
}
@Override
public boolean apply(Game game, Ability source) {
return true;
}
@Override
public ChandraPyromasterPlayEffect copy() {
return new ChandraPyromasterPlayEffect(this);
}
@Override
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
if (objectReference.refersTo(objectId, game) && affectedControllerId.equals(source.getControllerId())) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
return true;
} else {
discard();
}
}
return false;
}
}
class ChandraPyromasterEffect3 extends OneShotEffect {
public ChandraPyromasterEffect3() {

View file

@ -6,7 +6,7 @@ import java.util.List;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.cards.CardImpl;
@ -36,7 +36,7 @@ public final class ChandraRoaringFlame extends CardImpl {
this.nightCard = true;
this.transformable = true;
this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(4));
this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(4));
// +1: Chandra, Roaring Flame deals 2 damage to target player.
LoyaltyAbility loyaltyAbility = new LoyaltyAbility(new DamageTargetEffect(2), 1);

View file

@ -4,7 +4,7 @@ package mage.cards.c;
import java.util.UUID;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.CopyTargetSpellEffect;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
@ -33,7 +33,7 @@ public final class ChandraTheFirebrand extends CardImpl {
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.CHANDRA);
this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(3));
this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(3));
// +1: Chandra, the Firebrand deals 1 damage to any target.
LoyaltyAbility ability1 = new LoyaltyAbility(new DamageTargetEffect(1), 1);

View file

@ -6,7 +6,7 @@ import mage.MageObjectReference;
import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DamagePlayersEffect;
@ -37,7 +37,7 @@ public final class ChandraTorchOfDefiance extends CardImpl {
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.CHANDRA);
this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(4));
this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(4));
// +1: Exile the top card of your library. You may cast that card. If you don't, Chandra, Torch of Defiance deals 2 damage to each opponent.
LoyaltyAbility ability = new LoyaltyAbility(new ChandraTorchOfDefianceEffect(), 1);

View file

@ -0,0 +1,119 @@
package mage.cards.c;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.CastOnlyIfConditionIsTrueAbility;
import mage.abilities.common.SpellCastAllTriggeredAbility;
import mage.abilities.condition.Condition;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SetTargetPointer;
import mage.filter.FilterSpell;
import mage.game.Game;
import mage.game.stack.Spell;
import mage.players.Player;
import mage.target.common.TargetCardInHand;
/**
*
* @author L_J
*/
public final class ChecksAndBalances extends CardImpl {
public ChecksAndBalances(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{U}");
// Cast this spell only if there are three or more players in the game.
this.addAbility(new CastOnlyIfConditionIsTrueAbility(ChecksAndBalancesCondition.instance, "Cast this spell only if there are three or more players in the game"));
// Whenever a player casts a spell, each of that players opponents may discard a card. If they do, counter that spell.
this.addAbility(new SpellCastAllTriggeredAbility(new ChecksAndBalancesEffect(), new FilterSpell("a spell"), false, SetTargetPointer.SPELL));
}
public ChecksAndBalances(final ChecksAndBalances card) {
super(card);
}
@Override
public ChecksAndBalances copy() {
return new ChecksAndBalances(this);
}
}
enum ChecksAndBalancesCondition implements Condition {
instance;
@Override
public boolean apply(Game game, Ability source) {
return game.getPlayerList().size() >= 3;
}
@Override
public String toString() {
return "there are three or more players in the game";
}
}
class ChecksAndBalancesEffect extends OneShotEffect {
public ChecksAndBalancesEffect() {
super(Outcome.Detriment);
staticText = "each of that players opponents may discard a card. If they do, counter that spell";
}
public ChecksAndBalancesEffect(final ChecksAndBalancesEffect effect) {
super(effect);
}
@Override
public ChecksAndBalancesEffect copy() {
return new ChecksAndBalancesEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Spell spell = game.getStack().getSpell(this.getTargetPointer().getFirst(game, source));
if (spell != null) {
for (UUID uuid : game.getOpponents(spell.getControllerId())) {
Player player = game.getPlayer(uuid);
if (player != null) {
if (player.getHand().isEmpty()) {
game.informPlayers(player.getLogName() + " doesn't have a card in hand to discard to counter " + spell.getLogName() + ", effect aborted.");
return true;
}
}
}
for (UUID uuid : game.getOpponents(spell.getControllerId())) {
Player player = game.getPlayer(uuid);
if (player != null) {
if (!player.chooseUse(outcome, "Do you wish to discard a card to counter " + spell.getLogName() + '?', source, game)) {
game.informPlayers(player.getLogName() + " refuses to discard a card to counter " + spell.getLogName());
return true;
} else {
game.informPlayers(player.getLogName() + " agrees to discard a card to counter " + spell.getLogName());
}
}
}
for (UUID uuid : game.getOpponents(spell.getControllerId())) {
Player player = game.getPlayer(uuid);
if (player != null && !player.getHand().isEmpty()) {
TargetCardInHand target = new TargetCardInHand();
if (player.choose(Outcome.Discard, target, source.getSourceId(), game)) {
Card card = game.getCard(target.getFirstTarget());
if (card != null) {
player.discard(card, source, game);
}
}
}
}
game.getStack().counter(spell.getId(), source.getSourceId(), game);
return true;
}
return false;
}
}

View file

@ -2,6 +2,7 @@
package mage.cards.c;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
@ -11,7 +12,6 @@ import mage.abilities.effects.common.TransformSourceEffect;
import mage.abilities.keyword.TransformAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.m.MarkovsServant;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Zone;
@ -22,7 +22,6 @@ import mage.filter.predicate.permanent.TappedPredicate;
import mage.target.common.TargetControlledPermanent;
/**
*
* @author Loki
*/
public final class ChosenOfMarkov extends CardImpl {
@ -34,14 +33,14 @@ public final class ChosenOfMarkov extends CardImpl {
}
public ChosenOfMarkov(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{B}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}");
this.subtype.add(SubType.HUMAN);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
this.transformable = true;
this.secondSideCardClazz = MarkovsServant.class;
this.secondSideCardClazz = mage.cards.m.MarkovsServant.class;
// {tap}, Tap an untapped Vampire you control: Transform Chosen of Markov.
this.addAbility(new TransformAbility());

View file

@ -1,7 +1,6 @@
package mage.cards.c;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.ObjectColor;
@ -13,13 +12,7 @@ import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.SuperType;
import mage.constants.Zone;
import mage.filter.FilterPlayer;
import mage.constants.*;
import mage.filter.FilterSpell;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.game.ExileZone;
@ -31,8 +24,9 @@ import mage.players.Player;
import mage.target.TargetPlayer;
import mage.util.CardUtil;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public final class CircuDimirLobotomist extends CardImpl {
@ -54,16 +48,16 @@ public final class CircuDimirLobotomist extends CardImpl {
this.power = new MageInt(2);
this.toughness = new MageInt(3);
// 10/1/2005 The first two abilities target libraries, not players.
// Target Library not supported yet - used as workaround target player
// Whenever you cast a blue spell, exile the top card of target library.
Ability ability = new SpellCastControllerTriggeredAbility(new CircuDimirLobotomistEffect(), filterBlue, false);
ability.addTarget(new TargetPlayer(1, 1, true, new FilterPlayer("target library")));
ability.addTarget(new TargetPlayer());
this.addAbility(ability);
// Whenever you cast a black spell, exile the top card of target library.
ability = new SpellCastControllerTriggeredAbility(new CircuDimirLobotomistEffect(), filterBlack, false);
ability.addTarget(new TargetPlayer(1, 1, true, new FilterPlayer("target library")));
ability.addTarget(new TargetPlayer());
this.addAbility(ability);
// Your opponents can't cast nonland cards with the same name as a card exiled with Circu, Dimir Lobotomist.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CircuDimirLobotomistRuleModifyingEffect()));
}
@ -82,7 +76,7 @@ class CircuDimirLobotomistEffect extends OneShotEffect {
public CircuDimirLobotomistEffect() {
super(Outcome.Detriment);
this.staticText = "exile the top card of target library";
this.staticText = "exile the top card of target player's library";
}
public CircuDimirLobotomistEffect(final CircuDimirLobotomistEffect effect) {

View file

@ -2,6 +2,7 @@
package mage.cards.c;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
@ -11,7 +12,6 @@ import mage.abilities.keyword.TransformAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.h.HomicidalBrute;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Outcome;
@ -29,12 +29,12 @@ import mage.watchers.Watcher;
public final class CivilizedScholar extends CardImpl {
public CivilizedScholar(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{U}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.ADVISOR);
this.transformable = true;
this.secondSideCardClazz = HomicidalBrute.class;
this.secondSideCardClazz = mage.cards.h.HomicidalBrute.class;
this.power = new MageInt(0);
this.toughness = new MageInt(1);

View file

@ -0,0 +1,92 @@
package mage.cards.c;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.players.Player;
/**
*
* @author L_J
*/
public final class ClamIAm extends CardImpl {
public ClamIAm(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}");
this.subtype.add(SubType.CLAMFOLK);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// If you roll a 3 on a six-sided die, you may reroll that die.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ClamIAmEffect()));
}
public ClamIAm(final ClamIAm card) {
super(card);
}
@Override
public ClamIAm copy() {
return new ClamIAm(this);
}
}
class ClamIAmEffect extends ReplacementEffectImpl {
ClamIAmEffect() {
super(Duration.WhileOnBattlefield, Outcome.Benefit);
staticText = "If you roll a 3 on a six-sided die, you may reroll that die";
}
ClamIAmEffect(final ClamIAmEffect effect) {
super(effect);
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
Player player = game.getPlayer(event.getPlayerId());
if (player != null) {
String data = event.getData();
int numSides = Integer.parseInt(data);
if (numSides == 6 && event.getAmount() == 3) {
if (player.chooseUse(outcome, "Reroll the die?", source, game)) {
game.informPlayers(player.getLogName() + " chose to reroll the die.");
event.setAmount(player.rollDice(game, 6));
}
}
}
return false;
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ROLL_DICE;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
return source.getControllerId().equals(event.getPlayerId());
}
@Override
public boolean apply(Game game, Ability source) {
return false;
}
@Override
public ClamIAmEffect copy() {
return new ClamIAmEffect(this);
}
}

View file

@ -0,0 +1,102 @@
package mage.cards.c;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.DealsDamageToAPlayerTriggeredAbility;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.GainControlTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.CardTypePredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.Target;
import mage.target.common.TargetControlledPermanent;
import mage.target.targetpointer.FixedTarget;
/**
*
* @author L_J
*/
public final class Clambassadors extends CardImpl {
public Clambassadors(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}");
this.subtype.add(SubType.CLAMFOLK);
this.power = new MageInt(4);
this.toughness = new MageInt(4);
// Whenever Clambassadors deals damage to a player, choose an artifact, creature, or land you control. That player gains control of that permanent.
this.addAbility(new DealsDamageToAPlayerTriggeredAbility(new ClambassadorsEffect(), false, true));
}
public Clambassadors(final Clambassadors card) {
super(card);
}
@Override
public Clambassadors copy() {
return new Clambassadors(this);
}
}
class ClambassadorsEffect extends OneShotEffect {
private static final FilterControlledPermanent filter = new FilterControlledPermanent("artifact, creature, or land you control");
static {
filter.add(Predicates.or(
new CardTypePredicate(CardType.ARTIFACT),
new CardTypePredicate(CardType.CREATURE),
new CardTypePredicate(CardType.LAND)));
}
static {
filter.add(Predicates.or(new CardTypePredicate(CardType.ARTIFACT), new CardTypePredicate(CardType.CREATURE), new CardTypePredicate(CardType.LAND)));
}
public ClambassadorsEffect() {
super(Outcome.Detriment);
this.staticText = "choose an artifact, creature, or land you control. That player gains control of that permanent";
}
public ClambassadorsEffect(final ClambassadorsEffect effect) {
super(effect);
}
@Override
public ClambassadorsEffect copy() {
return new ClambassadorsEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
Target target = new TargetControlledPermanent(1, 1, filter, true);
if (target.canChoose(source.getSourceId(), controller.getId(), game)) {
while (!target.isChosen() && target.canChoose(controller.getId(), game) && controller.canRespond()) {
controller.chooseTarget(outcome, target, source, game);
}
}
Permanent permanent = game.getPermanent(target.getFirstTarget());
Player opponent = game.getPlayer(this.getTargetPointer().getFirst(game, source));
if (permanent != null && opponent != null) {
ContinuousEffect effect = new GainControlTargetEffect(Duration.Custom, true, opponent.getId());
effect.setTargetPointer(new FixedTarget(permanent, game));
game.addEffect(effect, source);
game.informPlayers(opponent.getLogName() + " has gained control of " + permanent.getLogName());
return true;
}
}
return false;
}
}

View file

@ -2,32 +2,31 @@
package mage.cards.c;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.effects.common.TransformSourceEffect;
import mage.abilities.keyword.TransformAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.u.UnholyFiend;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.TargetController;
/**
*
* @author Loki
*/
public final class CloisteredYouth extends CardImpl {
public CloisteredYouth(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{W}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}");
this.subtype.add(SubType.HUMAN);
this.power = new MageInt(1);
this.toughness = new MageInt(1);
this.transformable = true;
this.secondSideCardClazz = UnholyFiend.class;
this.secondSideCardClazz = mage.cards.u.UnholyFiend.class;
// At the beginning of your upkeep, you may transform Cloistered Youth.
this.addAbility(new TransformAbility());

View file

@ -0,0 +1,42 @@
package mage.cards.c;
import java.util.UUID;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.ComparisonType;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.mageobject.ToughnessPredicate;
import mage.target.common.TargetCreaturePermanent;
/**
* @author Ryan-Saklad
*/
public final class CollarTheCulprit extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature with toughness 4 or greater");
static {
filter.add(new ToughnessPredicate(ComparisonType.MORE_THAN, 3));
}
public CollarTheCulprit(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{W}");
// Destroy target creature with toughness 4 or greater.
this.getSpellAbility().addEffect(new DestroyTargetEffect());
this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter));
}
public CollarTheCulprit(final CollarTheCulprit card) {
super(card);
}
@Override
public CollarTheCulprit copy() {
return new CollarTheCulprit(this);
}
}

View file

@ -1,4 +1,3 @@
package mage.cards.c;
import java.util.Set;
@ -23,7 +22,7 @@ import mage.util.CardUtil;
public final class CommuneWithLava extends CardImpl {
public CommuneWithLava(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{X}{R}{R}");
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{X}{R}{R}");
// Exile the top X cards of your library. Until the end of your next turn, you may play those cards.
this.getSpellAbility().addEffect(new CommuneWithLavaEffect());

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