mirror of
https://github.com/correl/mage.git
synced 2024-12-24 11:50:45 +00:00
Merge https://github.com/magefree/mage into text
This commit is contained in:
commit
352637d411
62 changed files with 2785 additions and 58565 deletions
|
@ -305,10 +305,11 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
this.players.clear();
|
||||
this.playersWhoLeft.clear();
|
||||
|
||||
jLayeredPane.remove(abilityPicker);
|
||||
if (jLayeredPane!= null) {
|
||||
jLayeredPane.remove(abilityPicker);
|
||||
jLayeredPane.remove(DialogManager.getManager(gameId));
|
||||
}
|
||||
this.abilityPicker.cleanUp();
|
||||
|
||||
jLayeredPane.remove(DialogManager.getManager(gameId));
|
||||
DialogManager.removeGame(gameId);
|
||||
|
||||
if (pickNumber != null) {
|
||||
|
|
|
@ -38,7 +38,7 @@ public class GathererSets implements Iterable<DownloadJob> {
|
|||
"MED", "ME2", "ME3", "ME4",
|
||||
"POR", "PO2", "PTK",
|
||||
"ARC", "DD3EVG",
|
||||
"W16"};
|
||||
"W16", "W17"};
|
||||
|
||||
private static final String[] withMythics = {"M10", "M11", "M12", "M13", "M14", "M15", "ORI",
|
||||
"ANB",
|
||||
|
|
|
@ -133,6 +133,7 @@ public enum MagicCardsImageSource implements CardImageSource {
|
|||
put("V16", "from-the-vault-lore");
|
||||
put("VMA", "vintage-masters");
|
||||
put("W16", "welcome-deck-2016");
|
||||
put("W17", "welcome-deck-2017");
|
||||
put("WMCQ", "world-magic-cup-qualifier");
|
||||
put("WWK", "worldwake");
|
||||
put("ZEN", "zendikar");
|
||||
|
|
|
@ -42,7 +42,6 @@ import java.util.concurrent.ExecutorService;
|
|||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.prefs.Preferences;
|
||||
|
||||
import mage.client.MageFrame;
|
||||
import mage.client.dialog.PreferencesDialog;
|
||||
import mage.remote.Connection;
|
||||
|
@ -247,6 +246,7 @@ public enum WizardCardsImageSource implements CardImageSource {
|
|||
setsAliases.put("VIS", "Visions");
|
||||
setsAliases.put("VMA", "Vintage Masters");
|
||||
setsAliases.put("W16", "Welcome Deck 2016");
|
||||
setsAliases.put("W17", "Welcome Deck 2017");
|
||||
setsAliases.put("WMCQ", "World Magic Cup Qualifier");
|
||||
setsAliases.put("WTH", "Weatherlight");
|
||||
setsAliases.put("WWK", "Worldwake");
|
||||
|
|
|
@ -331,6 +331,23 @@
|
|||
|Generate|TOK:CHK|Snake|||SnakeToken|
|
||||
|Generate|TOK:CHK|Spirit|||SpiritToken|
|
||||
|Generate|TOK:CHR|Snake|||SerpentGeneratorSnakeToken|
|
||||
|Generate|TOK:CMA|Beast|1||BeastToken|
|
||||
|Generate|TOK:CMA|Beast|2||BeastToken2|
|
||||
|Generate|TOK:CMA|Dragon|||DragonToken2|
|
||||
|Generate|TOK:CMA|Drake|||LeafdrakeRoostDrakeToken|
|
||||
|Generate|TOK:CMA|Elemental|||TitaniaProtectorOfArgothElementalToken|
|
||||
|Generate|TOK:CMA|Elephant|||ElephantToken|
|
||||
|Generate|TOK:C14|Elf Druid|||FreyaliseLlanowarsFuryToken|
|
||||
|Generate|TOK:C14|Elf Druid|||LlanowarElvesToken|
|
||||
|Generate|TOK:CMA|Elf Warrior||
|
||||
|Generate|TOK:CMA|Gargoyle|||GargoyleToken|
|
||||
|Generate|TOK:CMA|Kithkin Soldier|||KithkinToken|
|
||||
|Generate|TOK:CMA|Knight|||KnightToken|
|
||||
|Generate|TOK:CMA|Saproling|||SaprolingToken|
|
||||
|Generate|TOK:CMA|Spirit|||SpiritWhiteToken|
|
||||
|Generate|TOK:CMA|Treefolk|||SylvanOfferingTreefolkToken|
|
||||
|Generate|TOK:CMA|Wolf|||WolfToken|
|
||||
|Generate|TOK:CMA|Zombie|||ZombieToken|
|
||||
|Generate|TOK:CMD|Beast|||BeastToken2|
|
||||
|Generate|TOK:CMD|Beast|||BeastToken|
|
||||
|Generate|TOK:CMD|Dragon|||DragonToken2|
|
||||
|
@ -479,6 +496,11 @@
|
|||
|Generate|TOK:DTK|Warrior|||WarriorToken|
|
||||
|Generate|TOK:DTK|Zombie Horror|||CorpseweftZombieToken|
|
||||
|Generate|TOK:DTK|Zombie|||ZombieToken|
|
||||
|Generate|TOK:E01|Beast|1||BeastToken|
|
||||
|Generate|TOK:E01|Beast|2||BeastToken2|
|
||||
|Generate|TOK:E01|Soldier|||SoldierToken|
|
||||
|Generate|TOK:E01|Spirit|||SpiritWhiteToken|
|
||||
|Generate|TOK:E01|Zombie|||ZombieToken|
|
||||
|Generate|TOK:EMA|Assembly-Worker|||AssemblyWorkerToken|
|
||||
|Generate|TOK:EMA|Beast|||CarnivoreToken|
|
||||
|Generate|TOK:EMA|Carnivore||
|
||||
|
|
|
@ -74,6 +74,6 @@ dd3evg=ddaevg
|
|||
dd3gvl=ddagvl
|
||||
dd3jvc=ddajvc
|
||||
# Remove setname as soon as the images can be downloaded
|
||||
ignore.urls=TOK,PCA,ANB,HOU,C17,IMA
|
||||
ignore.urls=TOK,PCA,C17,IMA
|
||||
# sets ordered by release time (newest goes first)
|
||||
token.lookup.order=IMA,C17,ANB,HOU,MM3,DDS,AKH,DD3DVD,DD3EVG,DD3GVL,DD3JVC,H09,AER,PCA,C16,V16,MPS,KLD,DDR,CN2,EMN,EMA,SOI,DDQ,CP,CMA,ARENA,SUS,APAC,EURO,UGIN,C15,OGW,EXP,DDP,BFZ,DRB,V09,V10,V11,V12,V13,V14,V15,TPR,MPRP,DD3,DDO,ORI,MM2,PTC,DTK,FRF,KTK,M15,VMA,CNS,JOU,BNG,THS,DDL,M14,MMA,DGM,GTC,RTR,M13,AVR,DDI,DKA,ISD,M12,NPH,MBS,SOM,M11,ROE,DDE,WWK,ZEN,M10,GVL,ARB,DVD,CFX,JVC,ALA,EVE,SHM,EVG,MOR,LRW,10E,CLS,CHK,GRC
|
||||
token.lookup.order=IMA,C17,E01,CMA,HOU,MM3,DDS,AKH,DD3DVD,DD3EVG,DD3GVL,DD3JVC,H09,AER,PCA,C16,V16,MPS,KLD,DDR,CN2,EMN,EMA,SOI,DDQ,CP,CMA,ARENA,SUS,APAC,EURO,UGIN,C15,OGW,EXP,DDP,BFZ,DRB,V09,V10,V11,V12,V13,V14,V15,TPR,MPRP,DD3,DDO,ORI,MM2,PTC,DTK,FRF,KTK,M15,VMA,CNS,JOU,BNG,THS,DDL,M14,MMA,DGM,GTC,RTR,M13,AVR,DDI,DKA,ISD,M12,NPH,MBS,SOM,M11,ROE,DDE,WWK,ZEN,M10,GVL,ARB,DVD,CFX,JVC,ALA,EVE,SHM,EVG,MOR,LRW,10E,CLS,CHK,GRC
|
|
@ -137,7 +137,7 @@ public interface MageServer {
|
|||
|
||||
void joinGame(UUID gameId, String sessionId) throws MageException;
|
||||
|
||||
void watchGame(UUID gameId, String sessionId) throws MageException;
|
||||
boolean watchGame(UUID gameId, String sessionId) throws MageException;
|
||||
|
||||
void stopWatching(UUID gameId, String sessionId) throws MageException;
|
||||
|
||||
|
|
|
@ -1016,8 +1016,7 @@ public class SessionImpl implements Session {
|
|||
public boolean watchGame(UUID gameId) {
|
||||
try {
|
||||
if (isConnected()) {
|
||||
server.watchGame(gameId, sessionId);
|
||||
return true;
|
||||
return server.watchGame(gameId, sessionId);
|
||||
}
|
||||
} catch (MageException ex) {
|
||||
handleMageException(ex);
|
||||
|
|
|
@ -879,14 +879,23 @@ public class MageServerImpl implements MageServer {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void watchGame(final UUID gameId, final String sessionId) throws MageException {
|
||||
execute("watchGame", sessionId, () -> {
|
||||
Optional<Session> session = SessionManager.instance.getSession(sessionId);
|
||||
if (!session.isPresent()) {
|
||||
logger.error("Session not found : " + sessionId);
|
||||
} else {
|
||||
UUID userId = session.get().getUserId();
|
||||
GameManager.instance.watchGame(gameId, userId);
|
||||
public boolean watchGame(final UUID gameId, final String sessionId) throws MageException {
|
||||
return executeWithResult("watchGame", sessionId, new ActionWithResult<Boolean>() {
|
||||
@Override
|
||||
public Boolean execute() throws MageException {
|
||||
Optional<Session> session = SessionManager.instance.getSession(sessionId);
|
||||
if (!session.isPresent()) {
|
||||
logger.error("Session not found : " + sessionId);
|
||||
return false;
|
||||
} else {
|
||||
UUID userId = session.get().getUserId();
|
||||
return GameManager.instance.watchGame(gameId, userId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean negativeResult() {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -421,12 +421,16 @@ public class TableController {
|
|||
}
|
||||
|
||||
public void updateDeck(UUID userId, DeckCardLists deckList) throws MageException {
|
||||
boolean validDeck;
|
||||
UUID playerId = userPlayerMap.get(userId);
|
||||
if (table.getState() != TableState.SIDEBOARDING && table.getState() != TableState.CONSTRUCTING) {
|
||||
return;
|
||||
}
|
||||
Deck deck = Deck.load(deckList, false, false);
|
||||
updateDeck(userId, playerId, deck);
|
||||
validDeck = updateDeck(userId, playerId, deck);
|
||||
if (!validDeck) {
|
||||
logger.warn(" userId: " + userId + " - Modified deck card list!");
|
||||
}
|
||||
}
|
||||
|
||||
private void submitDeck(UUID userId, UUID playerId, Deck deck) {
|
||||
|
@ -439,18 +443,20 @@ public class TableController {
|
|||
}
|
||||
}
|
||||
|
||||
private void updateDeck(UUID userId, UUID playerId, Deck deck) {
|
||||
private boolean updateDeck(UUID userId, UUID playerId, Deck deck) {
|
||||
boolean validDeck = true;
|
||||
if (table.isTournament()) {
|
||||
if (tournament != null) {
|
||||
TournamentManager.instance.updateDeck(tournament.getId(), playerId, deck);
|
||||
validDeck = TournamentManager.instance.updateDeck(tournament.getId(), playerId, deck);
|
||||
} else {
|
||||
logger.fatal("Tournament == null table: " + table.getId() + " userId: " + userId);
|
||||
}
|
||||
} else if (TableState.SIDEBOARDING == table.getState()) {
|
||||
match.updateDeck(playerId, deck);
|
||||
validDeck = match.updateDeck(playerId, deck);
|
||||
} else {
|
||||
// deck was meanwhile submitted so the autoupdate can be ignored
|
||||
}
|
||||
return validDeck;
|
||||
}
|
||||
|
||||
public boolean watchTable(UUID userId) {
|
||||
|
@ -472,13 +478,6 @@ public class TableController {
|
|||
}
|
||||
}
|
||||
|
||||
// public boolean replayTable(UUID userId) {
|
||||
// if (table.getState() != TableState.FINISHED) {
|
||||
// return false;
|
||||
// }
|
||||
// ReplayManager.instance.replayGame(table.getId(), userId);
|
||||
// return true;
|
||||
// }
|
||||
private Optional<Player> createPlayer(String name, PlayerType playerType, int skill) {
|
||||
Optional<Player> playerOpt;
|
||||
if (options == null) {
|
||||
|
@ -605,6 +604,7 @@ public class TableController {
|
|||
table.initGame();
|
||||
GameOptions gameOptions = new GameOptions();
|
||||
gameOptions.rollbackTurnsAllowed = match.getOptions().isRollbackTurnsAllowed();
|
||||
gameOptions.bannedUsers = match.getOptions().getBannedUsers();
|
||||
match.getGame().setGameOptions(gameOptions);
|
||||
GameManager.instance.createGameSession(match.getGame(), userPlayerMap, table.getId(), choosingPlayerId, gameOptions);
|
||||
String creator = null;
|
||||
|
|
|
@ -391,14 +391,22 @@ public class GameController implements GameCallback {
|
|||
return true;
|
||||
}
|
||||
|
||||
public void watch(UUID userId) {
|
||||
public boolean watch(UUID userId) {
|
||||
if (userPlayerMap.containsKey(userId)) {
|
||||
// You can't watch a game if you already a player in it
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
if (watchers.containsKey(userId)) {
|
||||
// You can't watch a game if you already watch it
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
if (!isAllowedToWatch(userId)) {
|
||||
// Dont want people on our ignore list to stalk us
|
||||
UserManager.instance.getUser(userId).ifPresent(user -> {
|
||||
user.showUserMessage("Not allowed", "You are banned from watching this game");
|
||||
ChatManager.instance.broadcast(chatId, user.getName(), " tried to join, but is banned", MessageColor.BLUE, true, ChatMessage.MessageType.STATUS, null);
|
||||
});
|
||||
return false;
|
||||
}
|
||||
UserManager.instance.getUser(userId).ifPresent(user -> {
|
||||
GameSessionWatcher gameWatcher = new GameSessionWatcher(userId, game, false);
|
||||
|
@ -407,6 +415,7 @@ public class GameController implements GameCallback {
|
|||
user.addGameWatchInfo(game.getId());
|
||||
ChatManager.instance.broadcast(chatId, user.getName(), " has started watching", MessageColor.BLUE, true, ChatMessage.MessageType.STATUS, null);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
public void stopWatching(UUID userId) {
|
||||
|
@ -1011,4 +1020,13 @@ public class GameController implements GameCallback {
|
|||
}
|
||||
return sb.append(']').toString();
|
||||
}
|
||||
|
||||
public boolean isAllowedToWatch(UUID userId) {
|
||||
Optional<User> user = UserManager.instance.getUser(userId);
|
||||
if (user.isPresent()) {
|
||||
return !gameOptions.bannedUsers.contains(user.get().getName());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -117,11 +117,12 @@ public enum GameManager {
|
|||
}
|
||||
}
|
||||
|
||||
public void watchGame(UUID gameId, UUID userId) {
|
||||
public boolean watchGame(UUID gameId, UUID userId) {
|
||||
GameController gameController = gameControllers.get(gameId);
|
||||
if (gameController != null) {
|
||||
gameController.watch(userId);
|
||||
return gameController.watch(userId);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void stopWatching(UUID gameId, UUID userId) {
|
||||
|
|
|
@ -349,10 +349,11 @@ public class TournamentController {
|
|||
}
|
||||
}
|
||||
|
||||
public void updateDeck(UUID playerId, Deck deck) {
|
||||
public boolean updateDeck(UUID playerId, Deck deck) {
|
||||
if (tournamentSessions.containsKey(playerId)) {
|
||||
tournamentSessions.get(playerId).updateDeck(deck);
|
||||
return tournamentSessions.get(playerId).updateDeck(deck);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void timeout(UUID userId) {
|
||||
|
|
|
@ -24,14 +24,12 @@
|
|||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
*/
|
||||
package mage.server.tournament;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import mage.cards.decks.Deck;
|
||||
import mage.game.tournament.Tournament;
|
||||
import mage.view.TournamentView;
|
||||
|
@ -74,8 +72,8 @@ public enum TournamentManager {
|
|||
controllers.get(tournamentId).submitDeck(playerId, deck);
|
||||
}
|
||||
|
||||
public void updateDeck(UUID tournamentId, UUID playerId, Deck deck) {
|
||||
controllers.get(tournamentId).updateDeck(playerId, deck);
|
||||
public boolean updateDeck(UUID tournamentId, UUID playerId, Deck deck) {
|
||||
return controllers.get(tournamentId).updateDeck(playerId, deck);
|
||||
}
|
||||
|
||||
public TournamentView getTournamentView(UUID tournamentId) {
|
||||
|
@ -87,13 +85,12 @@ public enum TournamentManager {
|
|||
}
|
||||
|
||||
public Optional<UUID> getChatId(UUID tournamentId) {
|
||||
if(controllers.containsKey(tournamentId)) {
|
||||
if (controllers.containsKey(tournamentId)) {
|
||||
return Optional.of(controllers.get(tournamentId).getChatId());
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
|
||||
public void removeTournament(UUID tournamentId) {
|
||||
TournamentController tournamentController = controllers.get(tournamentId);
|
||||
if (tournamentController != null) {
|
||||
|
|
|
@ -24,10 +24,14 @@
|
|||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
*/
|
||||
package mage.server.tournament;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import mage.cards.decks.Deck;
|
||||
import mage.game.tournament.Tournament;
|
||||
import mage.interfaces.callback.ClientCallback;
|
||||
|
@ -38,16 +42,11 @@ import mage.server.util.ThreadExecutor;
|
|||
import mage.view.TournamentView;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
public class TournamentSession {
|
||||
|
||||
protected final static Logger logger = Logger.getLogger(TournamentSession.class);
|
||||
|
||||
protected final UUID userId;
|
||||
|
@ -79,16 +78,16 @@ public class TournamentSession {
|
|||
|
||||
public void update() {
|
||||
if (!killed) {
|
||||
UserManager.instance.getUser(userId).ifPresent(user ->
|
||||
user.fireCallback(new ClientCallback(ClientCallbackMethod.TOURNAMENT_UPDATE, tournament.getId(), getTournamentView())));
|
||||
UserManager.instance.getUser(userId).ifPresent(user
|
||||
-> user.fireCallback(new ClientCallback(ClientCallbackMethod.TOURNAMENT_UPDATE, tournament.getId(), getTournamentView())));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void gameOver(final String message) {
|
||||
if (!killed) {
|
||||
UserManager.instance.getUser(userId).ifPresent(user ->
|
||||
user.fireCallback(new ClientCallback(ClientCallbackMethod.TOURNAMENT_OVER, tournament.getId(), message)));
|
||||
UserManager.instance.getUser(userId).ifPresent(user
|
||||
-> user.fireCallback(new ClientCallback(ClientCallbackMethod.TOURNAMENT_OVER, tournament.getId(), message)));
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -108,8 +107,8 @@ public class TournamentSession {
|
|||
tournament.submitDeck(playerId, deck);
|
||||
}
|
||||
|
||||
public void updateDeck(Deck deck) {
|
||||
tournament.updateDeck(playerId, deck);
|
||||
public boolean updateDeck(Deck deck) {
|
||||
return tournament.updateDeck(playerId, deck);
|
||||
}
|
||||
|
||||
public void setKilled() {
|
||||
|
@ -171,9 +170,8 @@ public class TournamentSession {
|
|||
}
|
||||
|
||||
private void removeTournamentForUser() {
|
||||
UserManager.instance.getUser(userId).ifPresent(user ->
|
||||
user.removeTournament(playerId));
|
||||
|
||||
UserManager.instance.getUser(userId).ifPresent(user
|
||||
-> user.removeTournament(playerId));
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
*/
|
||||
package mage.cards.d;
|
||||
|
||||
import mage.ConditionalMana;
|
||||
import mage.Mana;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
|
@ -93,7 +94,16 @@ class DoublingCubeEffect extends ManaEffect {
|
|||
int greenMana = pool.getGreen();
|
||||
int redMana = pool.getRed();
|
||||
int colorlessMana = pool.getColorless();
|
||||
Mana mana = new Mana(redMana, greenMana, blueMana, whiteMana, blackMana, colorlessMana, 0, 0);
|
||||
|
||||
for(ConditionalMana conditionalMana : pool.getConditionalMana()){
|
||||
blackMana += conditionalMana.getBlack();
|
||||
whiteMana += conditionalMana.getWhite();
|
||||
blueMana += conditionalMana.getBlue();
|
||||
greenMana += conditionalMana.getGreen();
|
||||
redMana += conditionalMana.getRed();
|
||||
colorlessMana += conditionalMana.getColorless();
|
||||
}
|
||||
Mana mana = new Mana(redMana, greenMana, blueMana, whiteMana, blackMana, 0, 0, colorlessMana);
|
||||
checkToFirePossibleEvents(mana, game, source);
|
||||
pool.addMana(mana, game, source);
|
||||
return true;
|
||||
|
|
244
Mage.Sets/src/mage/cards/n/NicolBolasGodPharoh.java
Normal file
244
Mage.Sets/src/mage/cards/n/NicolBolasGodPharoh.java
Normal file
|
@ -0,0 +1,244 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.cards.n;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.LoyaltyAbility;
|
||||
import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility;
|
||||
import mage.abilities.effects.AsThoughEffectImpl;
|
||||
import mage.abilities.effects.ContinuousEffect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.DamageTargetEffect;
|
||||
import mage.abilities.effects.common.ExileAllEffect;
|
||||
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.Zone;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.common.FilterNonlandPermanent;
|
||||
import mage.filter.predicate.permanent.ControllerPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.players.Library;
|
||||
import mage.players.Player;
|
||||
import mage.target.Target;
|
||||
import mage.target.common.TargetCardInHand;
|
||||
import mage.target.common.TargetCreatureOrPlayer;
|
||||
import mage.target.common.TargetOpponent;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Will
|
||||
*/
|
||||
public class NicolBolasGodPharoh extends CardImpl {
|
||||
|
||||
private UUID exileId = UUID.randomUUID();
|
||||
private static final FilterPermanent opponentsNonlandPermanentsFilter = new FilterNonlandPermanent("non-land permanents your opponents control");
|
||||
static {
|
||||
opponentsNonlandPermanentsFilter.add(new ControllerPredicate(TargetController.OPPONENT));
|
||||
}
|
||||
public NicolBolasGodPharoh(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId,setInfo,new CardType[]{CardType.PLANESWALKER},"{4}{U}{B}{R}");
|
||||
this.subtype.add("Bolas");
|
||||
|
||||
this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(7));
|
||||
|
||||
// +2: Target opponent exiles cards from the top of his or her library until he or she exiles a nonland card. Until end of turn, you may cast that card without paying its mana cost.
|
||||
LoyaltyAbility ability = new LoyaltyAbility(new NicolBolasGodPharohPlusTwoEffect(exileId), 2);
|
||||
ability.addTarget(new TargetOpponent());
|
||||
this.addAbility(ability);
|
||||
|
||||
// +1: Each opponent exiles two cards from his or her hand.
|
||||
this.addAbility(new LoyaltyAbility(new NicolBolasGodPharohPlusOneEffect(exileId), 1));
|
||||
|
||||
// -4: Nicol Bolas, God-Pharoh deals 7 damage to target creature or player.
|
||||
ability = new LoyaltyAbility(new DamageTargetEffect(7), -2);
|
||||
ability.addTarget(new TargetCreatureOrPlayer());
|
||||
this.addAbility(ability);
|
||||
|
||||
// -12: Exile each nonland permanent your opponents control.
|
||||
this.addAbility(new LoyaltyAbility(new ExileAllEffect(opponentsNonlandPermanentsFilter, exileId, this.getIdName()), -12));
|
||||
}
|
||||
|
||||
public NicolBolasGodPharoh(final NicolBolasGodPharoh card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NicolBolasGodPharoh copy() {
|
||||
return new NicolBolasGodPharoh(this);
|
||||
}
|
||||
}
|
||||
|
||||
class NicolBolasGodPharohPlusOneEffect extends OneShotEffect {
|
||||
|
||||
private UUID exileId;
|
||||
|
||||
NicolBolasGodPharohPlusOneEffect(UUID exileId) {
|
||||
super(Outcome.Exile);
|
||||
this.exileId = exileId;
|
||||
this.staticText = "Each opponent exiles two cards from his or her hand.";
|
||||
}
|
||||
|
||||
NicolBolasGodPharohPlusOneEffect(final NicolBolasGodPharohPlusOneEffect effect) {
|
||||
super(effect);
|
||||
this.exileId = effect.exileId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NicolBolasGodPharohPlusOneEffect copy() {
|
||||
return new NicolBolasGodPharohPlusOneEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
// Store for each player the cards to exile, that's important because all exile shall happen at the same time
|
||||
HashMap<UUID, Cards> cardsToExile = new HashMap<>();
|
||||
// Each player chooses 2 cards to discard
|
||||
for (UUID playerId : game.getOpponents(source.getControllerId())) {
|
||||
Player player = game.getPlayer(playerId);
|
||||
if (player == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int numberOfCardsToExile = Math.min(2, player.getHand().size());
|
||||
Cards cards = new CardsImpl();
|
||||
|
||||
Target target = new TargetCardInHand(numberOfCardsToExile, new FilterCard());
|
||||
|
||||
player.chooseTarget(Outcome.Exile, target, source, game);
|
||||
cards.addAll(target.getTargets());
|
||||
cardsToExile.put(playerId, cards);
|
||||
}
|
||||
// Exile all choosen cards
|
||||
for (UUID playerId : game.getOpponents(source.getControllerId())) {
|
||||
Player player = game.getPlayer(playerId);
|
||||
if (player == null) {
|
||||
continue;
|
||||
}
|
||||
Cards cardsPlayerChoseToExile = cardsToExile.get(playerId);
|
||||
if (cardsPlayerChoseToExile == null) {
|
||||
continue;
|
||||
}
|
||||
player.moveCardsToExile(cardsPlayerChoseToExile.getCards(game), source, game, true, exileId, source.getSourceObject(game).getIdName());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class NicolBolasGodPharohPlusTwoEffect extends OneShotEffect {
|
||||
|
||||
private UUID exileId;
|
||||
|
||||
public NicolBolasGodPharohPlusTwoEffect(UUID exileId) {
|
||||
super(Outcome.Detriment);
|
||||
this.exileId = exileId;
|
||||
this.staticText = "Target opponent exiles cards from the top of his or her library until he or she exiles a nonland card. Until end of turn, you may cast that card without paying its mana cost";
|
||||
}
|
||||
|
||||
public NicolBolasGodPharohPlusTwoEffect(final NicolBolasGodPharohPlusTwoEffect effect) {
|
||||
super(effect);
|
||||
this.exileId = effect.exileId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NicolBolasGodPharohPlusTwoEffect copy() {
|
||||
return new NicolBolasGodPharohPlusTwoEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player opponent = game.getPlayer(targetPointer.getFirst(game, source));
|
||||
MageObject sourceObject = source.getSourceObject(game);
|
||||
if (opponent != null && opponent.getLibrary().hasCards() && sourceObject != null) {
|
||||
Library library = opponent.getLibrary();
|
||||
Card card;
|
||||
do {
|
||||
card = library.removeFromTop(game);
|
||||
if (card != null) {
|
||||
opponent.moveCardsToExile(card, source, game, true, exileId, sourceObject.getIdName());
|
||||
}
|
||||
} while (library.hasCards() && card != null && card.isLand());
|
||||
|
||||
if (card != null) {
|
||||
ContinuousEffect effect = new NicolBolasGodPharohFromExileEffect();
|
||||
effect.setTargetPointer(new FixedTarget(card.getId(), card.getZoneChangeCounter(game)));
|
||||
game.addEffect(effect, source);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class NicolBolasGodPharohFromExileEffect extends AsThoughEffectImpl {
|
||||
|
||||
public NicolBolasGodPharohFromExileEffect() {
|
||||
super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfTurn, Outcome.Benefit);
|
||||
staticText = "You may cast card from exile";
|
||||
}
|
||||
|
||||
public NicolBolasGodPharohFromExileEffect(final NicolBolasGodPharohFromExileEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NicolBolasGodPharohFromExileEffect copy() {
|
||||
return new NicolBolasGodPharohFromExileEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) {
|
||||
if (sourceId != null && sourceId.equals(getTargetPointer().getFirst(game, source))
|
||||
&& affectedControllerId.equals(source.getControllerId())) {
|
||||
Card card = game.getCard(sourceId);
|
||||
if (card != null && game.getState().getZone(sourceId) == Zone.EXILED) {
|
||||
Player player = game.getPlayer(affectedControllerId);
|
||||
player.setCastSourceIdWithAlternateMana(sourceId, null, card.getSpellAbility().getCosts());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
172
Mage.Sets/src/mage/cards/o/OKagachiVengefulKami.java
Normal file
172
Mage.Sets/src/mage/cards/o/OKagachiVengefulKami.java
Normal file
|
@ -0,0 +1,172 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.cards.o;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.abilities.keyword.TrampleAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SuperType;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.DamagedPlayerEvent;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.GameEvent.EventType;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.watchers.common.PlayersAttackedLastTurnWatcher;
|
||||
import mage.abilities.effects.common.ExileTargetEffect;
|
||||
import mage.filter.common.FilterNonlandPermanent;
|
||||
import mage.filter.predicate.permanent.ControllerIdPredicate;
|
||||
import mage.target.TargetPermanent;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author spjspj
|
||||
*/
|
||||
public class OKagachiVengefulKami extends CardImpl {
|
||||
|
||||
public OKagachiVengefulKami(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}{U}{B}{R}{G}");
|
||||
|
||||
addSuperType(SuperType.LEGENDARY);
|
||||
this.subtype.add("Dragon");
|
||||
this.subtype.add("Spirit");
|
||||
this.power = new MageInt(6);
|
||||
this.toughness = new MageInt(6);
|
||||
|
||||
// Flying
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
|
||||
// Trample
|
||||
this.addAbility(TrampleAbility.getInstance());
|
||||
|
||||
// Whenever O-Kagachi, Vengeful Kami deals combat damage to a player, if that player attacked you during his or her last turn, exile target nonland permanent that player controls
|
||||
OKagachiVengefulKamiTriggeredAbility ability = new OKagachiVengefulKamiTriggeredAbility();
|
||||
ability.addWatcher(new PlayersAttackedLastTurnWatcher());
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
public OKagachiVengefulKami(final OKagachiVengefulKami card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OKagachiVengefulKami copy() {
|
||||
return new OKagachiVengefulKami(this);
|
||||
}
|
||||
}
|
||||
|
||||
class OKagachiVengefulKamiTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
private boolean madeDamge = false;
|
||||
private Set<UUID> damagedPlayers = new HashSet<>();
|
||||
|
||||
public OKagachiVengefulKamiTriggeredAbility() {
|
||||
super(Zone.BATTLEFIELD, new OKagachiVengefulKamiEffect(), false);
|
||||
}
|
||||
|
||||
public OKagachiVengefulKamiTriggeredAbility(final OKagachiVengefulKamiTriggeredAbility ability) {
|
||||
super(ability);
|
||||
this.madeDamge = ability.madeDamge;
|
||||
this.damagedPlayers = new HashSet<>();
|
||||
this.damagedPlayers.addAll(ability.damagedPlayers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OKagachiVengefulKamiTriggeredAbility copy() {
|
||||
return new OKagachiVengefulKamiTriggeredAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == EventType.DAMAGED_PLAYER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
if (event.getType() == EventType.DAMAGED_PLAYER) {
|
||||
DamagedPlayerEvent damageEvent = (DamagedPlayerEvent) event;
|
||||
UUID damagedPlayerId = game.getCombat().getDefenderId(sourceId);
|
||||
UUID you = this.getControllerId();
|
||||
Permanent p = game.getPermanent(event.getSourceId());
|
||||
if (damageEvent.isCombatDamage() && p != null) {
|
||||
PlayersAttackedLastTurnWatcher watcher = (PlayersAttackedLastTurnWatcher) game.getState().getWatchers().get(PlayersAttackedLastTurnWatcher.class.getSimpleName());
|
||||
if (watcher != null && watcher.attackedLastTurn(damagedPlayerId, you)) {
|
||||
FilterNonlandPermanent filter = new FilterNonlandPermanent("nonland permanent defending player controls");
|
||||
filter.add(new ControllerIdPredicate(damagedPlayerId));
|
||||
this.getTargets().clear();
|
||||
TargetPermanent target = new TargetPermanent(filter);
|
||||
this.addTarget(target);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "Whenever {this} deals combat damage to a player, if that player attacked you during his or her last turn, exile target nonland permanent that player controls";
|
||||
}
|
||||
}
|
||||
|
||||
class OKagachiVengefulKamiEffect extends OneShotEffect {
|
||||
|
||||
public OKagachiVengefulKamiEffect() {
|
||||
super(Outcome.Benefit);
|
||||
this.staticText = "if that player attacked you during his or her last turn, exile target nonland permanent that player controls";
|
||||
}
|
||||
|
||||
public OKagachiVengefulKamiEffect(final OKagachiVengefulKamiEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OKagachiVengefulKamiEffect copy() {
|
||||
return new OKagachiVengefulKamiEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||
if (permanent != null) {
|
||||
return new ExileTargetEffect().apply(game, source);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
134
Mage.Sets/src/mage/cards/r/RamosDragonEngine.java
Normal file
134
Mage.Sets/src/mage/cards/r/RamosDragonEngine.java
Normal file
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.cards.r;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.Mana;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SpellCastControllerTriggeredAbility;
|
||||
import mage.abilities.costs.common.RemoveCountersSourceCost;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.BasicManaEffect;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.abilities.mana.ActivateOncePerTurnManaAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SuperType;
|
||||
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.players.Player;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author spjspj
|
||||
*/
|
||||
public class RamosDragonEngine extends CardImpl {
|
||||
|
||||
public RamosDragonEngine(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{6}");
|
||||
|
||||
addSuperType(SuperType.LEGENDARY);
|
||||
this.subtype.add("Dragon");
|
||||
this.power = new MageInt(4);
|
||||
this.toughness = new MageInt(4);
|
||||
|
||||
// Flying
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
// Whenever you cast a spell, put a +1/+1 counter on Ramos, Dragon Engine for each of that spell's colors.
|
||||
this.addAbility(new SpellCastControllerTriggeredAbility(new RamosDragonEngineAddCountersEffect(), new FilterSpell("a spell"), false, true));
|
||||
|
||||
// Remove five +1/+1 counters from Ramos: Add {W}{W}{U}{U}{B}{B}{R}{R}{G}{G} to your mana pool. Activate this ability only once each turn.
|
||||
Ability ability = new ActivateOncePerTurnManaAbility(Zone.BATTLEFIELD, new BasicManaEffect(new Mana(2, 2, 2, 2, 2, 0, 0, 0)), new RemoveCountersSourceCost(CounterType.P1P1.createInstance(5)));
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
public RamosDragonEngine(final RamosDragonEngine card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RamosDragonEngine copy() {
|
||||
return new RamosDragonEngine(this);
|
||||
}
|
||||
}
|
||||
|
||||
class RamosDragonEngineAddCountersEffect extends OneShotEffect {
|
||||
|
||||
public RamosDragonEngineAddCountersEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "put a +1/+1 counter on {this} for each of that spell's colors";
|
||||
}
|
||||
|
||||
public RamosDragonEngineAddCountersEffect(final RamosDragonEngineAddCountersEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player you = game.getPlayer(source.getControllerId());
|
||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||
if (you != null && permanent != null) {
|
||||
Spell spell = game.getStack().getSpell(this.getTargetPointer().getFirst(game, source));
|
||||
if (spell != null) {
|
||||
int amount = 0;
|
||||
if (spell.getColor(game).isWhite()) {
|
||||
++amount;
|
||||
}
|
||||
if (spell.getColor(game).isBlue()) {
|
||||
++amount;
|
||||
}
|
||||
if (spell.getColor(game).isBlack()) {
|
||||
++amount;
|
||||
}
|
||||
if (spell.getColor(game).isRed()) {
|
||||
++amount;
|
||||
}
|
||||
if (spell.getColor(game).isGreen()) {
|
||||
++amount;
|
||||
}
|
||||
if (amount > 0) {
|
||||
permanent.addCounters(CounterType.P1P1.createInstance(amount), source, game);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RamosDragonEngineAddCountersEffect copy() {
|
||||
return new RamosDragonEngineAddCountersEffect(this);
|
||||
}
|
||||
}
|
91
Mage.Sets/src/mage/cards/s/SamutTheTested.java
Normal file
91
Mage.Sets/src/mage/cards/s/SamutTheTested.java
Normal file
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.cards.s;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.LoyaltyAbility;
|
||||
import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.common.DamageMultiEffect;
|
||||
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
|
||||
import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect;
|
||||
import mage.abilities.keyword.DoubleStrikeAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.filter.predicate.mageobject.CardTypePredicate;
|
||||
import mage.target.common.TargetCardInLibrary;
|
||||
import mage.target.common.TargetCreatureOrPlayerAmount;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
|
||||
/**
|
||||
* @author Will
|
||||
*/
|
||||
public class SamutTheTested extends CardImpl {
|
||||
|
||||
public SamutTheTested(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{2}{R}{G}");
|
||||
this.subtype.add("Samut");
|
||||
|
||||
this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(4));
|
||||
|
||||
// +1: Up to one target creature gains double strike until end of turn.
|
||||
Effect effect = new GainAbilityTargetEffect(DoubleStrikeAbility.getInstance(), Duration.EndOfTurn);
|
||||
LoyaltyAbility ability = new LoyaltyAbility(effect, 1);
|
||||
ability.addTarget(new TargetCreaturePermanent(0, 1));
|
||||
this.addAbility(ability);
|
||||
|
||||
// -2: Samut, the Tested deals 2 damage divided as you choose among one or two target creatures and/or players.
|
||||
effect = new DamageMultiEffect(2);
|
||||
ability = new LoyaltyAbility(effect, -2);
|
||||
ability.addTarget(new TargetCreatureOrPlayerAmount(2));
|
||||
this.addAbility(ability);
|
||||
|
||||
// -7: Search your library or up to two creature and/or planeswalkercards, put them onto the battlefield, then shuffle your library.
|
||||
FilterCard filterCard = new FilterCard("creature or planeswalker card");
|
||||
filterCard.add(Predicates.or(
|
||||
new CardTypePredicate(CardType.CREATURE),
|
||||
new CardTypePredicate(CardType.PLANESWALKER)
|
||||
));
|
||||
effect = new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(0, 2, filterCard), false, true);
|
||||
ability = new LoyaltyAbility(effect, -7);
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
public SamutTheTested(final SamutTheTested card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SamutTheTested copy() {
|
||||
return new SamutTheTested(this);
|
||||
}
|
||||
}
|
|
@ -28,6 +28,7 @@
|
|||
package mage.sets;
|
||||
|
||||
import mage.cards.ExpansionSet;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.SetType;
|
||||
|
||||
/**
|
||||
|
@ -44,8 +45,21 @@ public class ArchenemyNicolBolas extends ExpansionSet {
|
|||
}
|
||||
|
||||
private ArchenemyNicolBolas() {
|
||||
super("Archenemy: Nicol Bolas", "ANB", ExpansionSet.buildDate(2017, 6, 16), SetType.SUPPLEMENTAL);
|
||||
super("Archenemy: Nicol Bolas", "E01", ExpansionSet.buildDate(2017, 6, 16), SetType.SUPPLEMENTAL);
|
||||
this.blockName = "Command Zone";
|
||||
cards.add(new SetCardInfo("Aegis Angel", 1, Rarity.RARE, mage.cards.a.AegisAngel.class));
|
||||
cards.add(new SetCardInfo("Aerial Responder", 2, Rarity.UNCOMMON, mage.cards.a.AerialResponder.class));
|
||||
cards.add(new SetCardInfo("Anointer of Champions", 3, Rarity.UNCOMMON, mage.cards.a.AnointerOfChampions.class));
|
||||
cards.add(new SetCardInfo("Chandra, Pyromaster", 42, Rarity.MYTHIC, mage.cards.c.ChandraPyromaster.class));
|
||||
cards.add(new SetCardInfo("Doomed Traveler", 4, Rarity.COMMON, mage.cards.d.DoomedTraveler.class));
|
||||
cards.add(new SetCardInfo("Excoriate", 5, Rarity.COMMON, mage.cards.e.Excoriate.class));
|
||||
cards.add(new SetCardInfo("Expedition Raptor", 6, Rarity.COMMON, mage.cards.e.ExpeditionRaptor.class));
|
||||
cards.add(new SetCardInfo("Fencing Ace", 7, Rarity.UNCOMMON, mage.cards.f.FencingAce.class));
|
||||
cards.add(new SetCardInfo("Fiendslayer Paladin", 8, Rarity.RARE, mage.cards.f.FiendslayerPaladin.class));
|
||||
cards.add(new SetCardInfo("Flickerwisp", 9, Rarity.UNCOMMON, mage.cards.f.Flickerwisp.class));
|
||||
cards.add(new SetCardInfo("Gideon Jura", 10, Rarity.MYTHIC, mage.cards.g.GideonJura.class));
|
||||
cards.add(new SetCardInfo("Nicol Bolas, Planeswalker", 85, Rarity.MYTHIC, mage.cards.n.NicolBolasPlaneswalker.class));
|
||||
cards.add(new SetCardInfo("Nissa, Worldwaker", 68, Rarity.MYTHIC, mage.cards.n.NissaWorldwaker.class));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
package mage.sets;
|
||||
|
||||
import mage.cards.ExpansionSet;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.SetType;
|
||||
|
||||
/**
|
||||
|
@ -46,5 +47,8 @@ public class Commander2017 extends ExpansionSet {
|
|||
super("Commander 2017 Edition", "C17", ExpansionSet.buildDate(2017, 8, 25), SetType.SUPPLEMENTAL);
|
||||
this.blockName = "Command Zone";
|
||||
|
||||
cards.add(new SetCardInfo("O-Kagachi, Vengeful Kami", 3, Rarity.MYTHIC, mage.cards.o.OKagachiVengefulKami.class));
|
||||
cards.add(new SetCardInfo("Ramos, Dragon Engine", 55, Rarity.MYTHIC, mage.cards.r.RamosDragonEngine.class));
|
||||
|
||||
}
|
||||
}
|
|
@ -27,7 +27,9 @@
|
|||
*/
|
||||
package mage.sets;
|
||||
|
||||
import mage.cards.CardGraphicInfo;
|
||||
import mage.cards.ExpansionSet;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.SetType;
|
||||
|
||||
/**
|
||||
|
@ -45,5 +47,324 @@ public class CommanderAnthology extends ExpansionSet {
|
|||
super("Commander Anthology", "CMA", ExpansionSet.buildDate(2017, 6, 9), SetType.SUPPLEMENTAL);
|
||||
this.blockName = "Commander Anthology";
|
||||
this.hasBasicLands = false;
|
||||
cards.add(new SetCardInfo("Acidic Slime", 90, Rarity.UNCOMMON, mage.cards.a.AcidicSlime.class));
|
||||
cards.add(new SetCardInfo("Aerie Mystics", 1, Rarity.UNCOMMON, mage.cards.a.AerieMystics.class));
|
||||
cards.add(new SetCardInfo("Aethermage's Touch", 172, Rarity.RARE, mage.cards.a.AethermagesTouch.class));
|
||||
cards.add(new SetCardInfo("Akoum Refuge", 238, Rarity.UNCOMMON, mage.cards.a.AkoumRefuge.class));
|
||||
cards.add(new SetCardInfo("Akroma's Vengeance", 2, Rarity.RARE, mage.cards.a.AkromasVengeance.class));
|
||||
cards.add(new SetCardInfo("Akroma, Angel of Fury", 75, Rarity.RARE, mage.cards.a.AkromaAngelOfFury.class));
|
||||
cards.add(new SetCardInfo("Altar's Reap", 45, Rarity.COMMON, mage.cards.a.AltarsReap.class));
|
||||
cards.add(new SetCardInfo("Ambition's Cost", 46, Rarity.UNCOMMON, mage.cards.a.AmbitionsCost.class));
|
||||
cards.add(new SetCardInfo("Angel of Despair", 173, Rarity.RARE, mage.cards.a.AngelOfDespair.class));
|
||||
cards.add(new SetCardInfo("Angel of Finality", 3, Rarity.RARE, mage.cards.a.AngelOfFinality.class));
|
||||
cards.add(new SetCardInfo("Angelic Arbiter", 4, Rarity.RARE, mage.cards.a.AngelicArbiter.class));
|
||||
cards.add(new SetCardInfo("Anger", 76, Rarity.UNCOMMON, mage.cards.a.Anger.class));
|
||||
cards.add(new SetCardInfo("Arcane Denial", 30, Rarity.COMMON, mage.cards.a.ArcaneDenial.class));
|
||||
cards.add(new SetCardInfo("Archangel of Strife", 5, Rarity.RARE, mage.cards.a.ArchangelOfStrife.class));
|
||||
cards.add(new SetCardInfo("Armillary Sphere", 207, Rarity.COMMON, mage.cards.a.ArmillarySphere.class));
|
||||
cards.add(new SetCardInfo("Assault Suit", 208, Rarity.UNCOMMON, mage.cards.a.AssaultSuit.class));
|
||||
cards.add(new SetCardInfo("Avatar of Slaughter", 77, Rarity.RARE, mage.cards.a.AvatarOfSlaughter.class));
|
||||
cards.add(new SetCardInfo("Azami, Lady of Scrolls", 31, Rarity.RARE, mage.cards.a.AzamiLadyOfScrolls.class));
|
||||
cards.add(new SetCardInfo("Azorius Chancery", 239, Rarity.COMMON, mage.cards.a.AzoriusChancery.class));
|
||||
cards.add(new SetCardInfo("Azorius Guildgate", 240, Rarity.COMMON, mage.cards.a.AzoriusGuildgate.class));
|
||||
cards.add(new SetCardInfo("Azorius Keyrune", 209, Rarity.UNCOMMON, mage.cards.a.AzoriusKeyrune.class));
|
||||
cards.add(new SetCardInfo("Bane of Progress", 91, Rarity.RARE, mage.cards.b.BaneOfProgress.class));
|
||||
cards.add(new SetCardInfo("Banshee of the Dread Choir", 47, Rarity.UNCOMMON, mage.cards.b.BansheeOfTheDreadChoir.class));
|
||||
cards.add(new SetCardInfo("Bant Panorama", 241, Rarity.COMMON, mage.cards.b.BantPanorama.class));
|
||||
cards.add(new SetCardInfo("Barren Moor", 242, Rarity.COMMON, mage.cards.b.BarrenMoor.class));
|
||||
cards.add(new SetCardInfo("Barter in Blood", 48, Rarity.UNCOMMON, mage.cards.b.BarterInBlood.class));
|
||||
cards.add(new SetCardInfo("Basalt Monolith", 210, Rarity.UNCOMMON, mage.cards.b.BasaltMonolith.class));
|
||||
cards.add(new SetCardInfo("Basandra, Battle Seraph", 174, Rarity.RARE, mage.cards.b.BasandraBattleSeraph.class));
|
||||
cards.add(new SetCardInfo("Bathe in Light", 6, Rarity.UNCOMMON, mage.cards.b.BatheInLight.class));
|
||||
cards.add(new SetCardInfo("Beastmaster Ascension", 92, Rarity.RARE, mage.cards.b.BeastmasterAscension.class));
|
||||
cards.add(new SetCardInfo("Bladewing the Risen", 175, Rarity.RARE, mage.cards.b.BladewingTheRisen.class));
|
||||
cards.add(new SetCardInfo("Blood Bairn", 49, Rarity.COMMON, mage.cards.b.BloodBairn.class));
|
||||
cards.add(new SetCardInfo("Bloodspore Thrinax", 93, Rarity.RARE, mage.cards.b.BloodsporeThrinax.class));
|
||||
cards.add(new SetCardInfo("Blue Sun's Zenith", 32, Rarity.RARE, mage.cards.b.BlueSunsZenith.class));
|
||||
cards.add(new SetCardInfo("Bojuka Bog", 243, Rarity.COMMON, mage.cards.b.BojukaBog.class));
|
||||
cards.add(new SetCardInfo("Bonehoard", 211, Rarity.RARE, mage.cards.b.Bonehoard.class));
|
||||
cards.add(new SetCardInfo("Boros Garrison", 244, Rarity.COMMON, mage.cards.b.BorosGarrison.class));
|
||||
cards.add(new SetCardInfo("Boros Guildmage", 199, Rarity.UNCOMMON, mage.cards.b.BorosGuildmage.class));
|
||||
cards.add(new SetCardInfo("Boros Signet", 212, Rarity.COMMON, mage.cards.b.BorosSignet.class));
|
||||
cards.add(new SetCardInfo("Borrowing 100,000 Arrows", 33, Rarity.UNCOMMON, mage.cards.b.Borrowing100000Arrows.class));
|
||||
cards.add(new SetCardInfo("Butcher of Malakir", 50, Rarity.RARE, mage.cards.b.ButcherOfMalakir.class));
|
||||
cards.add(new SetCardInfo("Caller of the Pack", 94, Rarity.UNCOMMON, mage.cards.c.CallerOfThePack.class));
|
||||
cards.add(new SetCardInfo("Centaur Vinecrasher", 95, Rarity.RARE, mage.cards.c.CentaurVinecrasher.class));
|
||||
cards.add(new SetCardInfo("Champion of Stray Souls", 51, Rarity.MYTHIC, mage.cards.c.ChampionOfStraySouls.class));
|
||||
cards.add(new SetCardInfo("Cleansing Beam", 78, Rarity.UNCOMMON, mage.cards.c.CleansingBeam.class));
|
||||
cards.add(new SetCardInfo("Cloudthresher", 96, Rarity.RARE, mage.cards.c.Cloudthresher.class));
|
||||
cards.add(new SetCardInfo("Collective Unconscious", 97, Rarity.RARE, mage.cards.c.CollectiveUnconscious.class));
|
||||
cards.add(new SetCardInfo("Comet Storm", 79, Rarity.MYTHIC, mage.cards.c.CometStorm.class));
|
||||
cards.add(new SetCardInfo("Command Tower", 245, Rarity.COMMON, mage.cards.c.CommandTower.class));
|
||||
cards.add(new SetCardInfo("Commander's Sphere", 213, Rarity.COMMON, mage.cards.c.CommandersSphere.class));
|
||||
cards.add(new SetCardInfo("Congregate", 7, Rarity.COMMON, mage.cards.c.Congregate.class));
|
||||
cards.add(new SetCardInfo("Conjurer's Closet", 214, Rarity.RARE, mage.cards.c.ConjurersCloset.class));
|
||||
cards.add(new SetCardInfo("Control Magic", 34, Rarity.UNCOMMON, mage.cards.c.ControlMagic.class));
|
||||
cards.add(new SetCardInfo("Corpse Augur", 52, Rarity.UNCOMMON, mage.cards.c.CorpseAugur.class));
|
||||
cards.add(new SetCardInfo("Creeperhulk", 98, Rarity.RARE, mage.cards.c.Creeperhulk.class));
|
||||
cards.add(new SetCardInfo("Crystal Vein", 246, Rarity.UNCOMMON, mage.cards.c.CrystalVein.class));
|
||||
cards.add(new SetCardInfo("Curse of Inertia", 35, Rarity.UNCOMMON, mage.cards.c.CurseOfInertia.class));
|
||||
cards.add(new SetCardInfo("Curse of Predation", 99, Rarity.UNCOMMON, mage.cards.c.CurseOfPredation.class));
|
||||
cards.add(new SetCardInfo("Curse of the Forsaken", 8, Rarity.UNCOMMON, mage.cards.c.CurseOfTheForsaken.class));
|
||||
cards.add(new SetCardInfo("Darksteel Ingot", 215, Rarity.UNCOMMON, mage.cards.d.DarksteelIngot.class));
|
||||
cards.add(new SetCardInfo("Darksteel Mutation", 9, Rarity.UNCOMMON, mage.cards.d.DarksteelMutation.class));
|
||||
cards.add(new SetCardInfo("Death by Dragons", 80, Rarity.UNCOMMON, mage.cards.d.DeathByDragons.class));
|
||||
cards.add(new SetCardInfo("Deceiver Exarch", 36, Rarity.UNCOMMON, mage.cards.d.DeceiverExarch.class));
|
||||
cards.add(new SetCardInfo("Derevi, Empyrial Tactician", 176, Rarity.MYTHIC, mage.cards.d.DereviEmpyrialTactician.class));
|
||||
cards.add(new SetCardInfo("Desert Twister", 100, Rarity.UNCOMMON, mage.cards.d.DesertTwister.class));
|
||||
cards.add(new SetCardInfo("Diabolic Servitude", 53, Rarity.UNCOMMON, mage.cards.d.DiabolicServitude.class));
|
||||
cards.add(new SetCardInfo("Diabolic Tutor", 54, Rarity.UNCOMMON, mage.cards.d.DiabolicTutor.class));
|
||||
cards.add(new SetCardInfo("Diviner Spirit", 37, Rarity.UNCOMMON, mage.cards.d.DivinerSpirit.class));
|
||||
cards.add(new SetCardInfo("Djinn of Infinite Deceits", 38, Rarity.RARE, mage.cards.d.DjinnOfInfiniteDeceits.class));
|
||||
cards.add(new SetCardInfo("Dragon Whelp", 81, Rarity.UNCOMMON, mage.cards.d.DragonWhelp.class));
|
||||
cards.add(new SetCardInfo("Dread Cacodemon", 55, Rarity.RARE, mage.cards.d.DreadCacodemon.class));
|
||||
cards.add(new SetCardInfo("Dread Summons", 56, Rarity.RARE, mage.cards.d.DreadSummons.class));
|
||||
cards.add(new SetCardInfo("Drove of Elves", 101, Rarity.UNCOMMON, mage.cards.d.DroveOfElves.class));
|
||||
cards.add(new SetCardInfo("Duergar Hedge-Mage", 200, Rarity.UNCOMMON, mage.cards.d.DuergarHedgeMage.class));
|
||||
cards.add(new SetCardInfo("Dungeon Geists", 39, Rarity.RARE, mage.cards.d.DungeonGeists.class));
|
||||
cards.add(new SetCardInfo("Earthquake", 82, Rarity.RARE, mage.cards.e.Earthquake.class));
|
||||
cards.add(new SetCardInfo("Eater of Hope", 57, Rarity.RARE, mage.cards.e.EaterOfHope.class));
|
||||
cards.add(new SetCardInfo("Eldrazi Monument", 216, Rarity.MYTHIC, mage.cards.e.EldraziMonument.class));
|
||||
cards.add(new SetCardInfo("Elvish Archdruid", 102, Rarity.RARE, mage.cards.e.ElvishArchdruid.class));
|
||||
cards.add(new SetCardInfo("Elvish Mystic", 103, Rarity.COMMON, mage.cards.e.ElvishMystic.class));
|
||||
cards.add(new SetCardInfo("Elvish Skysweeper", 104, Rarity.COMMON, mage.cards.e.ElvishSkysweeper.class));
|
||||
cards.add(new SetCardInfo("Elvish Visionary", 105, Rarity.COMMON, mage.cards.e.ElvishVisionary.class));
|
||||
cards.add(new SetCardInfo("Emerald Medallion", 217, Rarity.RARE, mage.cards.e.EmeraldMedallion.class));
|
||||
cards.add(new SetCardInfo("Essence Warden", 106, Rarity.COMMON, mage.cards.e.EssenceWarden.class));
|
||||
cards.add(new SetCardInfo("Eternal Witness", 107, Rarity.UNCOMMON, mage.cards.e.EternalWitness.class));
|
||||
cards.add(new SetCardInfo("Evincar's Justice", 58, Rarity.COMMON, mage.cards.e.EvincarsJustice.class));
|
||||
cards.add(new SetCardInfo("Evolving Wilds", 247, Rarity.COMMON, mage.cards.e.EvolvingWilds.class));
|
||||
cards.add(new SetCardInfo("Extractor Demon", 59, Rarity.RARE, mage.cards.e.ExtractorDemon.class));
|
||||
cards.add(new SetCardInfo("Ezuri, Renegade Leader", 108, Rarity.RARE, mage.cards.e.EzuriRenegadeLeader.class));
|
||||
cards.add(new SetCardInfo("Faerie Conclave", 248, Rarity.UNCOMMON, mage.cards.f.FaerieConclave.class));
|
||||
cards.add(new SetCardInfo("Fallen Angel", 60, Rarity.RARE, mage.cards.f.FallenAngel.class));
|
||||
cards.add(new SetCardInfo("Farhaven Elf", 109, Rarity.COMMON, mage.cards.f.FarhavenElf.class));
|
||||
cards.add(new SetCardInfo("Fiend Hunter", 10, Rarity.UNCOMMON, mage.cards.f.FiendHunter.class));
|
||||
cards.add(new SetCardInfo("Flickerform", 11, Rarity.RARE, mage.cards.f.Flickerform.class));
|
||||
cards.add(new SetCardInfo("Flickerwisp", 12, Rarity.UNCOMMON, mage.cards.f.Flickerwisp.class));
|
||||
cards.add(new SetCardInfo("Forest", 309, Rarity.LAND, mage.cards.basiclands.Forest.class, new CardGraphicInfo(null, true)));
|
||||
cards.add(new SetCardInfo("Forest", 310, Rarity.LAND, mage.cards.basiclands.Forest.class, new CardGraphicInfo(null, true)));
|
||||
cards.add(new SetCardInfo("Forest", 311, Rarity.LAND, mage.cards.basiclands.Forest.class, new CardGraphicInfo(null, true)));
|
||||
cards.add(new SetCardInfo("Forest", 312, Rarity.LAND, mage.cards.basiclands.Forest.class, new CardGraphicInfo(null, true)));
|
||||
cards.add(new SetCardInfo("Forest", 313, Rarity.LAND, mage.cards.basiclands.Forest.class, new CardGraphicInfo(null, true)));
|
||||
cards.add(new SetCardInfo("Forest", 314, Rarity.LAND, mage.cards.basiclands.Forest.class, new CardGraphicInfo(null, true)));
|
||||
cards.add(new SetCardInfo("Forest", 315, Rarity.LAND, mage.cards.basiclands.Forest.class, new CardGraphicInfo(null, true)));
|
||||
cards.add(new SetCardInfo("Forest", 316, Rarity.LAND, mage.cards.basiclands.Forest.class, new CardGraphicInfo(null, true)));
|
||||
cards.add(new SetCardInfo("Forest", 317, Rarity.LAND, mage.cards.basiclands.Forest.class, new CardGraphicInfo(null, true)));
|
||||
cards.add(new SetCardInfo("Forest", 318, Rarity.LAND, mage.cards.basiclands.Forest.class, new CardGraphicInfo(null, true)));
|
||||
cards.add(new SetCardInfo("Forest", 319, Rarity.LAND, mage.cards.basiclands.Forest.class, new CardGraphicInfo(null, true)));
|
||||
cards.add(new SetCardInfo("Forest", 320, Rarity.LAND, mage.cards.basiclands.Forest.class, new CardGraphicInfo(null, true)));
|
||||
cards.add(new SetCardInfo("Forgotten Cave", 249, Rarity.COMMON, mage.cards.f.ForgottenCave.class));
|
||||
cards.add(new SetCardInfo("Fresh Meat", 110, Rarity.RARE, mage.cards.f.FreshMeat.class));
|
||||
cards.add(new SetCardInfo("Freyalise, Llanowar's Fury", 111, Rarity.MYTHIC, mage.cards.f.FreyaliseLlanowarsFury.class));
|
||||
cards.add(new SetCardInfo("Furnace Whelp", 83, Rarity.UNCOMMON, mage.cards.f.FurnaceWhelp.class));
|
||||
cards.add(new SetCardInfo("Gargoyle Castle", 250, Rarity.RARE, mage.cards.g.GargoyleCastle.class));
|
||||
cards.add(new SetCardInfo("Ghost Quarter", 251, Rarity.UNCOMMON, mage.cards.g.GhostQuarter.class));
|
||||
cards.add(new SetCardInfo("Golgari Charm", 177, Rarity.UNCOMMON, mage.cards.g.GolgariCharm.class));
|
||||
cards.add(new SetCardInfo("Golgari Guildgate", 252, Rarity.COMMON, mage.cards.g.GolgariGuildgate.class));
|
||||
cards.add(new SetCardInfo("Golgari Rot Farm", 253, Rarity.COMMON, mage.cards.g.GolgariRotFarm.class));
|
||||
cards.add(new SetCardInfo("Golgari Signet", 218, Rarity.COMMON, mage.cards.g.GolgariSignet.class));
|
||||
cards.add(new SetCardInfo("Grave Sifter", 112, Rarity.RARE, mage.cards.g.GraveSifter.class));
|
||||
cards.add(new SetCardInfo("Great Oak Guardian", 113, Rarity.UNCOMMON, mage.cards.g.GreatOakGuardian.class));
|
||||
cards.add(new SetCardInfo("Grim Backwoods", 254, Rarity.RARE, mage.cards.g.GrimBackwoods.class));
|
||||
cards.add(new SetCardInfo("Grim Flowering", 114, Rarity.UNCOMMON, mage.cards.g.GrimFlowering.class));
|
||||
cards.add(new SetCardInfo("Grisly Salvage", 178, Rarity.COMMON, mage.cards.g.GrislySalvage.class));
|
||||
cards.add(new SetCardInfo("Gwyllion Hedge-Mage", 201, Rarity.UNCOMMON, mage.cards.g.GwyllionHedgeMage.class));
|
||||
cards.add(new SetCardInfo("Hada Spy Patrol", 40, Rarity.UNCOMMON, mage.cards.h.HadaSpyPatrol.class));
|
||||
cards.add(new SetCardInfo("Harrow", 115, Rarity.COMMON, mage.cards.h.Harrow.class));
|
||||
cards.add(new SetCardInfo("Haunted Fengraf", 255, Rarity.COMMON, mage.cards.h.HauntedFengraf.class));
|
||||
cards.add(new SetCardInfo("Havenwood Battleground", 256, Rarity.UNCOMMON, mage.cards.h.HavenwoodBattleground.class));
|
||||
cards.add(new SetCardInfo("High Market", 257, Rarity.RARE, mage.cards.h.HighMarket.class));
|
||||
cards.add(new SetCardInfo("Hunting Triad", 116, Rarity.UNCOMMON, mage.cards.h.HuntingTriad.class));
|
||||
cards.add(new SetCardInfo("Immaculate Magistrate", 117, Rarity.RARE, mage.cards.i.ImmaculateMagistrate.class));
|
||||
cards.add(new SetCardInfo("Imperious Perfect", 118, Rarity.RARE, mage.cards.i.ImperiousPerfect.class));
|
||||
cards.add(new SetCardInfo("Indrik Stomphowler", 119, Rarity.UNCOMMON, mage.cards.i.IndrikStomphowler.class));
|
||||
cards.add(new SetCardInfo("Island", 293, Rarity.LAND, mage.cards.basiclands.Island.class, new CardGraphicInfo(null, true)));
|
||||
cards.add(new SetCardInfo("Island", 294, Rarity.LAND, mage.cards.basiclands.Island.class, new CardGraphicInfo(null, true)));
|
||||
cards.add(new SetCardInfo("Island", 295, Rarity.LAND, mage.cards.basiclands.Island.class, new CardGraphicInfo(null, true)));
|
||||
cards.add(new SetCardInfo("Island", 296, Rarity.LAND, mage.cards.basiclands.Island.class, new CardGraphicInfo(null, true)));
|
||||
cards.add(new SetCardInfo("Jarad, Golgari Lich Lord", 179, Rarity.MYTHIC, mage.cards.j.JaradGolgariLichLord.class));
|
||||
cards.add(new SetCardInfo("Joraga Warcaller", 120, Rarity.RARE, mage.cards.j.JoragaWarcaller.class));
|
||||
cards.add(new SetCardInfo("Jungle Basin", 258, Rarity.UNCOMMON, mage.cards.j.JungleBasin.class));
|
||||
cards.add(new SetCardInfo("Jungle Hollow", 259, Rarity.COMMON, mage.cards.j.JungleHollow.class));
|
||||
cards.add(new SetCardInfo("Kaalia of the Vast", 180, Rarity.MYTHIC, mage.cards.k.KaaliaOfTheVast.class));
|
||||
cards.add(new SetCardInfo("Karmic Guide", 13, Rarity.RARE, mage.cards.k.KarmicGuide.class));
|
||||
cards.add(new SetCardInfo("Kazandu Tuskcaller", 121, Rarity.RARE, mage.cards.k.KazanduTuskcaller.class));
|
||||
cards.add(new SetCardInfo("Kessig Cagebreakers", 122, Rarity.RARE, mage.cards.k.KessigCagebreakers.class));
|
||||
cards.add(new SetCardInfo("Kirtar's Wrath", 14, Rarity.RARE, mage.cards.k.KirtarsWrath.class));
|
||||
cards.add(new SetCardInfo("Korozda Guildmage", 181, Rarity.UNCOMMON, mage.cards.k.KorozdaGuildmage.class));
|
||||
cards.add(new SetCardInfo("Krosan Grip", 123, Rarity.UNCOMMON, mage.cards.k.KrosanGrip.class));
|
||||
cards.add(new SetCardInfo("Leafdrake Roost", 182, Rarity.UNCOMMON, mage.cards.l.LeafdrakeRoost.class));
|
||||
cards.add(new SetCardInfo("Leonin Bladetrap", 219, Rarity.UNCOMMON, mage.cards.l.LeoninBladetrap.class));
|
||||
cards.add(new SetCardInfo("Lifeblood Hydra", 124, Rarity.RARE, mage.cards.l.LifebloodHydra.class));
|
||||
cards.add(new SetCardInfo("Lightkeeper of Emeria", 15, Rarity.UNCOMMON, mage.cards.l.LightkeeperOfEmeria.class));
|
||||
cards.add(new SetCardInfo("Lightning Greaves", 220, Rarity.UNCOMMON, mage.cards.l.LightningGreaves.class));
|
||||
cards.add(new SetCardInfo("Llanowar Elves", 125, Rarity.COMMON, mage.cards.l.LlanowarElves.class));
|
||||
cards.add(new SetCardInfo("Loreseeker's Stone", 221, Rarity.UNCOMMON, mage.cards.l.LoreseekersStone.class));
|
||||
cards.add(new SetCardInfo("Lotleth Troll", 183, Rarity.RARE, mage.cards.l.LotlethTroll.class));
|
||||
cards.add(new SetCardInfo("Lu Xun, Scholar General", 41, Rarity.RARE, mage.cards.l.LuXunScholarGeneral.class));
|
||||
cards.add(new SetCardInfo("Lys Alana Huntmaster", 126, Rarity.COMMON, mage.cards.l.LysAlanaHuntmaster.class));
|
||||
cards.add(new SetCardInfo("Malfegor", 184, Rarity.MYTHIC, mage.cards.m.Malfegor.class));
|
||||
cards.add(new SetCardInfo("Mana-Charged Dragon", 84, Rarity.RARE, mage.cards.m.ManaChargedDragon.class));
|
||||
cards.add(new SetCardInfo("Masked Admirers", 127, Rarity.UNCOMMON, mage.cards.m.MaskedAdmirers.class));
|
||||
cards.add(new SetCardInfo("Mazirek, Kraul Death Priest", 185, Rarity.MYTHIC, mage.cards.m.MazirekKraulDeathPriest.class));
|
||||
cards.add(new SetCardInfo("Meren of Clan Nel Toth", 186, Rarity.MYTHIC, mage.cards.m.MerenOfClanNelToth.class));
|
||||
cards.add(new SetCardInfo("Mirror Entity", 16, Rarity.RARE, mage.cards.m.MirrorEntity.class));
|
||||
cards.add(new SetCardInfo("Mistmeadow Witch", 203, Rarity.UNCOMMON, mage.cards.m.MistmeadowWitch.class));
|
||||
cards.add(new SetCardInfo("Molten Slagheap", 260, Rarity.UNCOMMON, mage.cards.m.MoltenSlagheap.class));
|
||||
cards.add(new SetCardInfo("Mortify", 187, Rarity.UNCOMMON, mage.cards.m.Mortify.class));
|
||||
cards.add(new SetCardInfo("Moss Diamond", 222, Rarity.UNCOMMON, mage.cards.m.MossDiamond.class));
|
||||
cards.add(new SetCardInfo("Mother of Runes", 17, Rarity.UNCOMMON, mage.cards.m.MotherOfRunes.class));
|
||||
cards.add(new SetCardInfo("Mountain", 305, Rarity.LAND, mage.cards.basiclands.Mountain.class, new CardGraphicInfo(null, true)));
|
||||
cards.add(new SetCardInfo("Mountain", 306, Rarity.LAND, mage.cards.basiclands.Mountain.class, new CardGraphicInfo(null, true)));
|
||||
cards.add(new SetCardInfo("Mountain", 307, Rarity.LAND, mage.cards.basiclands.Mountain.class, new CardGraphicInfo(null, true)));
|
||||
cards.add(new SetCardInfo("Mountain", 308, Rarity.LAND, mage.cards.basiclands.Mountain.class, new CardGraphicInfo(null, true)));
|
||||
cards.add(new SetCardInfo("Mulch", 128, Rarity.COMMON, mage.cards.m.Mulch.class));
|
||||
cards.add(new SetCardInfo("Murkfiend Liege", 204, Rarity.RARE, mage.cards.m.MurkfiendLiege.class));
|
||||
cards.add(new SetCardInfo("Mycoloth", 129, Rarity.RARE, mage.cards.m.Mycoloth.class));
|
||||
cards.add(new SetCardInfo("Myriad Landscape", 261, Rarity.UNCOMMON, mage.cards.m.MyriadLandscape.class));
|
||||
cards.add(new SetCardInfo("Oni of Wild Places", 85, Rarity.UNCOMMON, mage.cards.o.OniOfWildPlaces.class));
|
||||
cards.add(new SetCardInfo("Opal Palace", 262, Rarity.COMMON, mage.cards.o.OpalPalace.class));
|
||||
cards.add(new SetCardInfo("Oran-Rief, the Vastwood", 263, Rarity.RARE, mage.cards.o.OranRiefTheVastwood.class));
|
||||
cards.add(new SetCardInfo("Orim's Thunder", 18, Rarity.COMMON, mage.cards.o.OrimsThunder.class));
|
||||
cards.add(new SetCardInfo("Oros, the Avenger", 188, Rarity.RARE, mage.cards.o.OrosTheAvenger.class));
|
||||
cards.add(new SetCardInfo("Orzhov Basilica", 264, Rarity.COMMON, mage.cards.o.OrzhovBasilica.class));
|
||||
cards.add(new SetCardInfo("Orzhov Guildmage", 205, Rarity.UNCOMMON, mage.cards.o.OrzhovGuildmage.class));
|
||||
cards.add(new SetCardInfo("Orzhov Signet", 223, Rarity.COMMON, mage.cards.o.OrzhovSignet.class));
|
||||
cards.add(new SetCardInfo("Overrun", 130, Rarity.UNCOMMON, mage.cards.o.Overrun.class));
|
||||
cards.add(new SetCardInfo("Overwhelming Stampede", 131, Rarity.RARE, mage.cards.o.OverwhelmingStampede.class));
|
||||
cards.add(new SetCardInfo("Path to Exile", 19, Rarity.UNCOMMON, mage.cards.p.PathToExile.class));
|
||||
cards.add(new SetCardInfo("Pathbreaker Ibex", 132, Rarity.RARE, mage.cards.p.PathbreakerIbex.class));
|
||||
cards.add(new SetCardInfo("Phantom Nantuko", 133, Rarity.RARE, mage.cards.p.PhantomNantuko.class));
|
||||
cards.add(new SetCardInfo("Phyrexian Plaguelord", 61, Rarity.RARE, mage.cards.p.PhyrexianPlaguelord.class));
|
||||
cards.add(new SetCardInfo("Phyrexian Rager", 62, Rarity.COMMON, mage.cards.p.PhyrexianRager.class));
|
||||
cards.add(new SetCardInfo("Pilgrim's Eye", 224, Rarity.COMMON, mage.cards.p.PilgrimsEye.class));
|
||||
cards.add(new SetCardInfo("Plains", 285, Rarity.LAND, mage.cards.basiclands.Plains.class, new CardGraphicInfo(null, true)));
|
||||
cards.add(new SetCardInfo("Plains", 286, Rarity.LAND, mage.cards.basiclands.Plains.class, new CardGraphicInfo(null, true)));
|
||||
cards.add(new SetCardInfo("Plains", 287, Rarity.LAND, mage.cards.basiclands.Plains.class, new CardGraphicInfo(null, true)));
|
||||
cards.add(new SetCardInfo("Plains", 288, Rarity.LAND, mage.cards.basiclands.Plains.class, new CardGraphicInfo(null, true)));
|
||||
cards.add(new SetCardInfo("Plains", 289, Rarity.LAND, mage.cards.basiclands.Plains.class, new CardGraphicInfo(null, true)));
|
||||
cards.add(new SetCardInfo("Plains", 290, Rarity.LAND, mage.cards.basiclands.Plains.class, new CardGraphicInfo(null, true)));
|
||||
cards.add(new SetCardInfo("Plains", 291, Rarity.LAND, mage.cards.basiclands.Plains.class, new CardGraphicInfo(null, true)));
|
||||
cards.add(new SetCardInfo("Plains", 292, Rarity.LAND, mage.cards.basiclands.Plains.class, new CardGraphicInfo(null, true)));
|
||||
cards.add(new SetCardInfo("Polluted Mire", 265, Rarity.COMMON, mage.cards.p.PollutedMire.class));
|
||||
cards.add(new SetCardInfo("Praetor's Counsel", 134, Rarity.MYTHIC, mage.cards.p.PraetorsCounsel.class));
|
||||
cards.add(new SetCardInfo("Predator, Flagship", 225, Rarity.RARE, mage.cards.p.PredatorFlagship.class));
|
||||
cards.add(new SetCardInfo("Presence of Gond", 135, Rarity.COMMON, mage.cards.p.PresenceOfGond.class));
|
||||
cards.add(new SetCardInfo("Priest of Titania", 136, Rarity.COMMON, mage.cards.p.PriestOfTitania.class));
|
||||
cards.add(new SetCardInfo("Primal Growth", 137, Rarity.COMMON, mage.cards.p.PrimalGrowth.class));
|
||||
cards.add(new SetCardInfo("Primordial Sage", 138, Rarity.RARE, mage.cards.p.PrimordialSage.class));
|
||||
cards.add(new SetCardInfo("Putrefy", 189, Rarity.UNCOMMON, mage.cards.p.Putrefy.class));
|
||||
cards.add(new SetCardInfo("Pyrohemia", 86, Rarity.UNCOMMON, mage.cards.p.Pyrohemia.class));
|
||||
cards.add(new SetCardInfo("Rakdos Carnarium", 266, Rarity.COMMON, mage.cards.r.RakdosCarnarium.class));
|
||||
cards.add(new SetCardInfo("Rakdos Signet", 226, Rarity.COMMON, mage.cards.r.RakdosSignet.class));
|
||||
cards.add(new SetCardInfo("Rampaging Baloths", 139, Rarity.MYTHIC, mage.cards.r.RampagingBaloths.class));
|
||||
cards.add(new SetCardInfo("Razorjaw Oni", 63, Rarity.UNCOMMON, mage.cards.r.RazorjawOni.class));
|
||||
cards.add(new SetCardInfo("Reclamation Sage", 140, Rarity.UNCOMMON, mage.cards.r.ReclamationSage.class));
|
||||
cards.add(new SetCardInfo("Reiver Demon", 64, Rarity.RARE, mage.cards.r.ReiverDemon.class));
|
||||
cards.add(new SetCardInfo("Restore", 141, Rarity.UNCOMMON, mage.cards.r.Restore.class));
|
||||
cards.add(new SetCardInfo("Return to Dust", 20, Rarity.UNCOMMON, mage.cards.r.ReturnToDust.class));
|
||||
cards.add(new SetCardInfo("Righteous Cause", 21, Rarity.UNCOMMON, mage.cards.r.RighteousCause.class));
|
||||
cards.add(new SetCardInfo("Rise from the Grave", 65, Rarity.UNCOMMON, mage.cards.r.RiseFromTheGrave.class));
|
||||
cards.add(new SetCardInfo("Roon of the Hidden Realm", 190, Rarity.MYTHIC, mage.cards.r.RoonOfTheHiddenRealm.class));
|
||||
cards.add(new SetCardInfo("Rubinia Soulsinger", 191, Rarity.RARE, mage.cards.r.RubiniaSoulsinger.class));
|
||||
cards.add(new SetCardInfo("Rupture Spire", 267, Rarity.COMMON, mage.cards.r.RuptureSpire.class));
|
||||
cards.add(new SetCardInfo("Sakura-Tribe Elder", 142, Rarity.COMMON, mage.cards.s.SakuraTribeElder.class));
|
||||
cards.add(new SetCardInfo("Saltcrusted Steppe", 268, Rarity.UNCOMMON, mage.cards.s.SaltcrustedSteppe.class));
|
||||
cards.add(new SetCardInfo("Satyr Wayfinder", 143, Rarity.COMMON, mage.cards.s.SatyrWayfinder.class));
|
||||
cards.add(new SetCardInfo("Scourge of Nel Toth", 66, Rarity.RARE, mage.cards.s.ScourgeOfNelToth.class));
|
||||
cards.add(new SetCardInfo("Seaside Citadel", 269, Rarity.UNCOMMON, mage.cards.s.SeasideCitadel.class));
|
||||
cards.add(new SetCardInfo("Secluded Steppe", 270, Rarity.COMMON, mage.cards.s.SecludedSteppe.class));
|
||||
cards.add(new SetCardInfo("Seer's Sundial", 227, Rarity.RARE, mage.cards.s.SeersSundial.class));
|
||||
cards.add(new SetCardInfo("Sejiri Refuge", 271, Rarity.UNCOMMON, mage.cards.s.SejiriRefuge.class));
|
||||
cards.add(new SetCardInfo("Selesnya Charm", 192, Rarity.UNCOMMON, mage.cards.s.SelesnyaCharm.class));
|
||||
cards.add(new SetCardInfo("Selesnya Guildgate", 272, Rarity.COMMON, mage.cards.s.SelesnyaGuildgate.class));
|
||||
cards.add(new SetCardInfo("Selesnya Guildmage", 206, Rarity.UNCOMMON, mage.cards.s.SelesnyaGuildmage.class));
|
||||
cards.add(new SetCardInfo("Selesnya Sanctuary", 273, Rarity.COMMON, mage.cards.s.SelesnyaSanctuary.class));
|
||||
cards.add(new SetCardInfo("Selesnya Signet", 228, Rarity.COMMON, mage.cards.s.SelesnyaSignet.class));
|
||||
cards.add(new SetCardInfo("Serra Angel", 22, Rarity.UNCOMMON, mage.cards.s.SerraAngel.class));
|
||||
cards.add(new SetCardInfo("Sever the Bloodline", 67, Rarity.RARE, mage.cards.s.SeverTheBloodline.class));
|
||||
cards.add(new SetCardInfo("Shattered Angel", 23, Rarity.UNCOMMON, mage.cards.s.ShatteredAngel.class));
|
||||
cards.add(new SetCardInfo("Shriekmaw", 68, Rarity.UNCOMMON, mage.cards.s.Shriekmaw.class));
|
||||
cards.add(new SetCardInfo("Siege Behemoth", 144, Rarity.RARE, mage.cards.s.SiegeBehemoth.class));
|
||||
cards.add(new SetCardInfo("Silklash Spider", 145, Rarity.RARE, mage.cards.s.SilklashSpider.class));
|
||||
cards.add(new SetCardInfo("Simic Guildgate", 274, Rarity.COMMON, mage.cards.s.SimicGuildgate.class));
|
||||
cards.add(new SetCardInfo("Simic Signet", 229, Rarity.COMMON, mage.cards.s.SimicSignet.class));
|
||||
cards.add(new SetCardInfo("Skullclamp", 230, Rarity.UNCOMMON, mage.cards.s.Skullclamp.class));
|
||||
cards.add(new SetCardInfo("Skullwinder", 146, Rarity.UNCOMMON, mage.cards.s.Skullwinder.class));
|
||||
cards.add(new SetCardInfo("Skyward Eye Prophets", 193, Rarity.UNCOMMON, mage.cards.s.SkywardEyeProphets.class));
|
||||
cards.add(new SetCardInfo("Slippery Karst", 275, Rarity.COMMON, mage.cards.s.SlipperyKarst.class));
|
||||
cards.add(new SetCardInfo("Sol Ring", 231, Rarity.UNCOMMON, mage.cards.s.SolRing.class));
|
||||
cards.add(new SetCardInfo("Song of the Dryads", 147, Rarity.RARE, mage.cards.s.SongOfTheDryads.class));
|
||||
cards.add(new SetCardInfo("Soul Snare", 24, Rarity.UNCOMMON, mage.cards.s.SoulSnare.class));
|
||||
cards.add(new SetCardInfo("Soul of the Harvest", 148, Rarity.RARE, mage.cards.s.SoulOfTheHarvest.class));
|
||||
cards.add(new SetCardInfo("Spider Spawning", 149, Rarity.UNCOMMON, mage.cards.s.SpiderSpawning.class));
|
||||
cards.add(new SetCardInfo("Stonecloaker", 25, Rarity.UNCOMMON, mage.cards.s.Stonecloaker.class));
|
||||
cards.add(new SetCardInfo("Stranglehold", 87, Rarity.RARE, mage.cards.s.Stranglehold.class));
|
||||
cards.add(new SetCardInfo("Sulfurous Blast", 88, Rarity.UNCOMMON, mage.cards.s.SulfurousBlast.class));
|
||||
cards.add(new SetCardInfo("Surveyor's Scope", 232, Rarity.RARE, mage.cards.s.SurveyorsScope.class));
|
||||
cards.add(new SetCardInfo("Swamp", 297, Rarity.LAND, mage.cards.basiclands.Swamp.class, new CardGraphicInfo(null, true)));
|
||||
cards.add(new SetCardInfo("Swamp", 298, Rarity.LAND, mage.cards.basiclands.Swamp.class, new CardGraphicInfo(null, true)));
|
||||
cards.add(new SetCardInfo("Swamp", 299, Rarity.LAND, mage.cards.basiclands.Swamp.class, new CardGraphicInfo(null, true)));
|
||||
cards.add(new SetCardInfo("Swamp", 300, Rarity.LAND, mage.cards.basiclands.Swamp.class, new CardGraphicInfo(null, true)));
|
||||
cards.add(new SetCardInfo("Swamp", 301, Rarity.LAND, mage.cards.basiclands.Swamp.class, new CardGraphicInfo(null, true)));
|
||||
cards.add(new SetCardInfo("Swamp", 302, Rarity.LAND, mage.cards.basiclands.Swamp.class, new CardGraphicInfo(null, true)));
|
||||
cards.add(new SetCardInfo("Swamp", 303, Rarity.LAND, mage.cards.basiclands.Swamp.class, new CardGraphicInfo(null, true)));
|
||||
cards.add(new SetCardInfo("Swamp", 304, Rarity.LAND, mage.cards.basiclands.Swamp.class, new CardGraphicInfo(null, true)));
|
||||
cards.add(new SetCardInfo("Swiftfoot Boots", 233, Rarity.UNCOMMON, mage.cards.s.SwiftfootBoots.class));
|
||||
cards.add(new SetCardInfo("Sword of the Paruns", 234, Rarity.RARE, mage.cards.s.SwordOfTheParuns.class));
|
||||
cards.add(new SetCardInfo("Sylvan Offering", 150, Rarity.RARE, mage.cards.s.SylvanOffering.class));
|
||||
cards.add(new SetCardInfo("Sylvan Ranger", 151, Rarity.COMMON, mage.cards.s.SylvanRanger.class));
|
||||
cards.add(new SetCardInfo("Sylvan Safekeeper", 152, Rarity.RARE, mage.cards.s.SylvanSafekeeper.class));
|
||||
cards.add(new SetCardInfo("Syphon Flesh", 69, Rarity.UNCOMMON, mage.cards.s.SyphonFlesh.class));
|
||||
cards.add(new SetCardInfo("Syphon Mind", 70, Rarity.COMMON, mage.cards.s.SyphonMind.class));
|
||||
cards.add(new SetCardInfo("Tainted Wood", 276, Rarity.UNCOMMON, mage.cards.t.TaintedWood.class));
|
||||
cards.add(new SetCardInfo("Tariel, Reckoner of Souls", 194, Rarity.MYTHIC, mage.cards.t.TarielReckonerOfSouls.class));
|
||||
cards.add(new SetCardInfo("Temple of the False God", 277, Rarity.UNCOMMON, mage.cards.t.TempleOfTheFalseGod.class));
|
||||
cards.add(new SetCardInfo("Tempt with Glory", 26, Rarity.RARE, mage.cards.t.TemptWithGlory.class));
|
||||
cards.add(new SetCardInfo("Terastodon", 153, Rarity.RARE, mage.cards.t.Terastodon.class));
|
||||
cards.add(new SetCardInfo("Terminate", 195, Rarity.COMMON, mage.cards.t.Terminate.class));
|
||||
cards.add(new SetCardInfo("Terramorphic Expanse", 278, Rarity.COMMON, mage.cards.t.TerramorphicExpanse.class));
|
||||
cards.add(new SetCardInfo("Thief of Blood", 71, Rarity.UNCOMMON, mage.cards.t.ThiefOfBlood.class));
|
||||
cards.add(new SetCardInfo("Thornweald Archer", 154, Rarity.COMMON, mage.cards.t.ThornwealdArcher.class));
|
||||
cards.add(new SetCardInfo("Thornwind Faeries", 42, Rarity.COMMON, mage.cards.t.ThornwindFaeries.class));
|
||||
cards.add(new SetCardInfo("Thought Vessel", 235, Rarity.COMMON, mage.cards.t.ThoughtVessel.class));
|
||||
cards.add(new SetCardInfo("Thousand-Year Elixir", 236, Rarity.RARE, mage.cards.t.ThousandYearElixir.class));
|
||||
cards.add(new SetCardInfo("Thunderfoot Baloth", 155, Rarity.RARE, mage.cards.t.ThunderfootBaloth.class));
|
||||
cards.add(new SetCardInfo("Thunderstaff", 237, Rarity.UNCOMMON, mage.cards.t.Thunderstaff.class));
|
||||
cards.add(new SetCardInfo("Timberwatch Elf", 156, Rarity.COMMON, mage.cards.t.TimberwatchElf.class));
|
||||
cards.add(new SetCardInfo("Titania's Chosen", 158, Rarity.UNCOMMON, mage.cards.t.TitaniasChosen.class));
|
||||
cards.add(new SetCardInfo("Titania, Protector of Argoth", 157, Rarity.MYTHIC, mage.cards.t.TitaniaProtectorOfArgoth.class));
|
||||
cards.add(new SetCardInfo("Tornado Elemental", 159, Rarity.RARE, mage.cards.t.TornadoElemental.class));
|
||||
cards.add(new SetCardInfo("Tranquil Thicket", 279, Rarity.COMMON, mage.cards.t.TranquilThicket.class));
|
||||
cards.add(new SetCardInfo("Transguild Promenade", 280, Rarity.COMMON, mage.cards.t.TransguildPromenade.class));
|
||||
cards.add(new SetCardInfo("Tribute to the Wild", 160, Rarity.UNCOMMON, mage.cards.t.TributeToTheWild.class));
|
||||
cards.add(new SetCardInfo("Unexpectedly Absent", 27, Rarity.RARE, mage.cards.u.UnexpectedlyAbsent.class));
|
||||
cards.add(new SetCardInfo("Verdant Force", 161, Rarity.RARE, mage.cards.v.VerdantForce.class));
|
||||
cards.add(new SetCardInfo("Victimize", 72, Rarity.UNCOMMON, mage.cards.v.Victimize.class));
|
||||
cards.add(new SetCardInfo("Viridian Emissary", 162, Rarity.COMMON, mage.cards.v.ViridianEmissary.class));
|
||||
cards.add(new SetCardInfo("Viridian Zealot", 163, Rarity.RARE, mage.cards.v.ViridianZealot.class));
|
||||
cards.add(new SetCardInfo("Vivid Grove", 281, Rarity.UNCOMMON, mage.cards.v.VividGrove.class));
|
||||
cards.add(new SetCardInfo("Vivid Marsh", 282, Rarity.UNCOMMON, mage.cards.v.VividMarsh.class));
|
||||
cards.add(new SetCardInfo("Vivid Meadow", 283, Rarity.UNCOMMON, mage.cards.v.VividMeadow.class));
|
||||
cards.add(new SetCardInfo("Voice of All", 28, Rarity.RARE, mage.cards.v.VoiceOfAll.class));
|
||||
cards.add(new SetCardInfo("Vow of Duty", 29, Rarity.UNCOMMON, mage.cards.v.VowOfDuty.class));
|
||||
cards.add(new SetCardInfo("Vow of Lightning", 89, Rarity.UNCOMMON, mage.cards.v.VowOfLightning.class));
|
||||
cards.add(new SetCardInfo("Vow of Malice", 73, Rarity.UNCOMMON, mage.cards.v.VowOfMalice.class));
|
||||
cards.add(new SetCardInfo("Vulturous Zombie", 196, Rarity.RARE, mage.cards.v.VulturousZombie.class));
|
||||
cards.add(new SetCardInfo("Wall of Blossoms", 164, Rarity.UNCOMMON, mage.cards.w.WallOfBlossoms.class));
|
||||
cards.add(new SetCardInfo("Wash Out", 43, Rarity.UNCOMMON, mage.cards.w.WashOut.class));
|
||||
cards.add(new SetCardInfo("Wave of Vitriol", 165, Rarity.RARE, mage.cards.w.WaveOfVitriol.class));
|
||||
cards.add(new SetCardInfo("Wellwisher", 166, Rarity.COMMON, mage.cards.w.Wellwisher.class));
|
||||
cards.add(new SetCardInfo("Whirlwind", 167, Rarity.RARE, mage.cards.w.Whirlwind.class));
|
||||
cards.add(new SetCardInfo("Winged Coatl", 197, Rarity.COMMON, mage.cards.w.WingedCoatl.class));
|
||||
cards.add(new SetCardInfo("Wolfbriar Elemental", 168, Rarity.RARE, mage.cards.w.WolfbriarElemental.class));
|
||||
cards.add(new SetCardInfo("Wolfcaller's Howl", 169, Rarity.RARE, mage.cards.w.WolfcallersHowl.class));
|
||||
cards.add(new SetCardInfo("Wonder", 44, Rarity.UNCOMMON, mage.cards.w.Wonder.class));
|
||||
cards.add(new SetCardInfo("Wood Elves", 170, Rarity.COMMON, mage.cards.w.WoodElves.class));
|
||||
cards.add(new SetCardInfo("Wrecking Ball", 198, Rarity.COMMON, mage.cards.w.WreckingBall.class));
|
||||
cards.add(new SetCardInfo("Wren's Run Packmaster", 171, Rarity.RARE, mage.cards.w.WrensRunPackmaster.class));
|
||||
cards.add(new SetCardInfo("Wretched Confluence", 74, Rarity.RARE, mage.cards.w.WretchedConfluence.class));
|
||||
cards.add(new SetCardInfo("Zoetic Cavern", 284, Rarity.UNCOMMON, mage.cards.z.ZoeticCavern.class));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -117,6 +117,7 @@ public class FridayNightMagic extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Fact or Fiction", 61, Rarity.UNCOMMON, mage.cards.f.FactOrFiction.class));
|
||||
cards.add(new SetCardInfo("Fanatic of Xenagos", 173, Rarity.UNCOMMON, mage.cards.f.FanaticOfXenagos.class));
|
||||
cards.add(new SetCardInfo("Farseek", 154, Rarity.COMMON, mage.cards.f.Farseek.class));
|
||||
cards.add(new SetCardInfo("Fatal Push", 208, Rarity.SPECIAL, mage.cards.f.FatalPush.class));
|
||||
cards.add(new SetCardInfo("Fiery Temper", 198, Rarity.UNCOMMON, mage.cards.f.FieryTemper.class));
|
||||
cards.add(new SetCardInfo("Fireblast", 18, Rarity.COMMON, mage.cards.f.Fireblast.class));
|
||||
cards.add(new SetCardInfo("Firebolt", 80, Rarity.UNCOMMON, mage.cards.f.Firebolt.class));
|
||||
|
@ -193,7 +194,9 @@ public class FridayNightMagic extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Reanimate", 53, Rarity.UNCOMMON, mage.cards.r.Reanimate.class));
|
||||
cards.add(new SetCardInfo("Reliquary Tower", 153, Rarity.UNCOMMON, mage.cards.r.ReliquaryTower.class));
|
||||
cards.add(new SetCardInfo("Remand", 92, Rarity.UNCOMMON, mage.cards.r.Remand.class));
|
||||
cards.add(new SetCardInfo("Renegade Rallier", 207, Rarity.SPECIAL, mage.cards.r.RenegadeRallier.class));
|
||||
cards.add(new SetCardInfo("Resurrection", 97, Rarity.UNCOMMON, mage.cards.r.Resurrection.class));
|
||||
cards.add(new SetCardInfo("Reverse Engineer", 206, Rarity.SPECIAL, mage.cards.r.ReverseEngineer.class));
|
||||
cards.add(new SetCardInfo("Rhox War Monk", 133, Rarity.UNCOMMON, mage.cards.r.RhoxWarMonk.class));
|
||||
cards.add(new SetCardInfo("Rift Bolt", 125, Rarity.COMMON, mage.cards.r.RiftBolt.class));
|
||||
cards.add(new SetCardInfo("Rise from the Tides", 197, Rarity.UNCOMMON, mage.cards.r.RiseFromTheTides.class));
|
||||
|
|
|
@ -27,7 +27,13 @@
|
|||
*/
|
||||
package mage.sets;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import mage.cards.ExpansionSet;
|
||||
import mage.constants.Rarity;
|
||||
import mage.cards.repository.CardCriteria;
|
||||
import mage.cards.repository.CardInfo;
|
||||
import mage.cards.repository.CardRepository;
|
||||
import mage.constants.SetType;
|
||||
|
||||
/**
|
||||
|
@ -42,6 +48,8 @@ public class HourOfDevastation extends ExpansionSet {
|
|||
return instance;
|
||||
}
|
||||
|
||||
protected final List<CardInfo> savedSpecialLand = new ArrayList<>();
|
||||
|
||||
private HourOfDevastation() {
|
||||
super("Hour of Devastation", "HOU", ExpansionSet.buildDate(2017, 7, 14), SetType.EXPANSION);
|
||||
this.blockName = "Amonkhet";
|
||||
|
@ -53,6 +61,23 @@ public class HourOfDevastation extends ExpansionSet {
|
|||
this.numBoosterUncommon = 3;
|
||||
this.numBoosterRare = 1;
|
||||
this.ratioBoosterMythic = 8;
|
||||
this.ratioBoosterSpecialLand = 144;
|
||||
|
||||
cards.add(new SetCardInfo("Samut, the Tested", 144, Rarity.MYTHIC, mage.cards.s.SamutTheTested.class));
|
||||
cards.add(new SetCardInfo("Nicol Bolas, God-Pharoh", 140, Rarity.MYTHIC, mage.cards.n.NicolBolasGodPharoh.class));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CardInfo> getSpecialLand() {
|
||||
if (savedSpecialLand.isEmpty()) {
|
||||
CardCriteria criteria = new CardCriteria();
|
||||
criteria.setCodes("MPS-AKH");
|
||||
criteria.minCardNumber(31);
|
||||
criteria.maxCardNumber(54);
|
||||
savedSpecialLand.addAll(CardRepository.instance.findCards(criteria));
|
||||
}
|
||||
|
||||
return new ArrayList<>(savedSpecialLand);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ import mage.constants.SetType;
|
|||
|
||||
/**
|
||||
*
|
||||
* @author escplan9 (Derek Monturo - dmontur1 at gmail dot com)
|
||||
* @author escplan9
|
||||
*/
|
||||
public class WelcomeDeck2016 extends ExpansionSet {
|
||||
private static final WelcomeDeck2016 instance = new WelcomeDeck2016();
|
||||
|
|
82
Mage.Sets/src/mage/sets/WelcomeDeck2017.java
Normal file
82
Mage.Sets/src/mage/sets/WelcomeDeck2017.java
Normal file
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
package mage.sets;
|
||||
|
||||
import mage.cards.ExpansionSet;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.SetType;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author escplan9
|
||||
*/
|
||||
public class WelcomeDeck2017 extends ExpansionSet {
|
||||
private static final WelcomeDeck2017 instance = new WelcomeDeck2017();
|
||||
|
||||
public static WelcomeDeck2017 getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private WelcomeDeck2017() {
|
||||
super("Welcome Deck 2017", "W17", ExpansionSet.buildDate(2017, 4, 15), SetType.SUPPLEMENTAL_STANDARD_LEGAL);
|
||||
this.hasBasicLands = false;
|
||||
this.hasBoosters = false;
|
||||
|
||||
cards.add(new SetCardInfo("Divine Verdict", 1, Rarity.COMMON, mage.cards.d.DivineVerdict.class));
|
||||
cards.add(new SetCardInfo("Glory Seeker", 2, Rarity.COMMON, mage.cards.g.GlorySeeker.class));
|
||||
cards.add(new SetCardInfo("Serra Angel", 3, Rarity.UNCOMMON, mage.cards.s.SerraAngel.class));
|
||||
cards.add(new SetCardInfo("Standing Troops", 4, Rarity.COMMON, mage.cards.s.StandingTroops.class));
|
||||
cards.add(new SetCardInfo("Stormfront Pegasus", 5, Rarity.UNCOMMON, mage.cards.s.StormfrontPegasus.class));
|
||||
cards.add(new SetCardInfo("Victory's Herald", 6, Rarity.RARE, mage.cards.v.VictorysHerald.class));
|
||||
cards.add(new SetCardInfo("Air Elemental", 7, Rarity.UNCOMMON, mage.cards.a.AirElemental.class));
|
||||
cards.add(new SetCardInfo("Coral Merfolk", 8, Rarity.COMMON, mage.cards.c.CoralMerfolk.class));
|
||||
cards.add(new SetCardInfo("Drag Under", 9, Rarity.COMMON, mage.cards.d.DragUnder.class));
|
||||
cards.add(new SetCardInfo("Inspiration", 10, Rarity.COMMON, mage.cards.i.Inspiration.class));
|
||||
cards.add(new SetCardInfo("Sleep Paralysis", 11, Rarity.COMMON, mage.cards.s.SleepParalysis.class));
|
||||
cards.add(new SetCardInfo("Sphinx of Magosi", 12, Rarity.RARE, mage.cards.s.SphinxOfMagosi.class));
|
||||
cards.add(new SetCardInfo("Stealer of Secrets", 13, Rarity.COMMON, mage.cards.s.StealerOfSecrets.class));
|
||||
cards.add(new SetCardInfo("Tricks of the Trade", 14, Rarity.COMMON, mage.cards.t.TricksOfTheTrade.class));
|
||||
cards.add(new SetCardInfo("Bloodhunter Bat", 15, Rarity.COMMON, mage.cards.b.BloodhunterBat.class));
|
||||
cards.add(new SetCardInfo("Certain Death", 16, Rarity.COMMON, mage.cards.c.CertainDeath.class));
|
||||
cards.add(new SetCardInfo("Nightmare", 17, Rarity.RARE, mage.cards.n.Nightmare.class));
|
||||
cards.add(new SetCardInfo("Raise Dead", 18, Rarity.COMMON, mage.cards.r.RaiseDead.class));
|
||||
cards.add(new SetCardInfo("Sengir Vampire", 19, Rarity.UNCOMMON, mage.cards.s.SengirVampire.class));
|
||||
cards.add(new SetCardInfo("Untamed Hunger", 20, Rarity.COMMON, mage.cards.u.UntamedHunger.class));
|
||||
cards.add(new SetCardInfo("Falkenrath Reaver", 21, Rarity.COMMON, mage.cards.f.FalkenrathReaver.class));
|
||||
cards.add(new SetCardInfo("Shivan Dragon", 22, Rarity.RARE, mage.cards.s.ShivanDragon.class));
|
||||
cards.add(new SetCardInfo("Thundering Giant", 23, Rarity.COMMON, mage.cards.t.ThunderingGiant.class));
|
||||
cards.add(new SetCardInfo("Garruk's Horde", 24, Rarity.RARE, mage.cards.g.GarruksHorde.class));
|
||||
cards.add(new SetCardInfo("Oakenform", 25, Rarity.COMMON, mage.cards.o.Oakenform.class));
|
||||
cards.add(new SetCardInfo("Rabid Bite", 26, Rarity.COMMON, mage.cards.r.RabidBite.class));
|
||||
cards.add(new SetCardInfo("Rootwalla", 27, Rarity.COMMON, mage.cards.r.Rootwalla.class));
|
||||
cards.add(new SetCardInfo("Stalking Tiger", 28, Rarity.COMMON, mage.cards.s.StalkingTiger.class));
|
||||
cards.add(new SetCardInfo("Stampeding Rhino", 29, Rarity.COMMON, mage.cards.s.StampedingRhino.class));
|
||||
cards.add(new SetCardInfo("Wing Snare", 30, Rarity.UNCOMMON, mage.cards.w.WingSnare.class));
|
||||
}
|
||||
}
|
|
@ -154,7 +154,6 @@ public class NestOfScarabsTest extends CardTestPlayerBase {
|
|||
}
|
||||
|
||||
/*
|
||||
* NOTE: test is failing due to bug in code. See issue #3402
|
||||
Reported bug: Nest of Scarabs not triggering off infect damage dealt by creatures such as Blight Mamba
|
||||
*/
|
||||
@Test
|
||||
|
@ -179,4 +178,30 @@ public class NestOfScarabsTest extends CardTestPlayerBase {
|
|||
assertCounterCount(playerB, wOmens, CounterType.M1M1, 1);
|
||||
assertPermanentCount(playerA, "Insect", 1);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Reported bug: Nest of Scarabs not triggering off wither damage dealt by creatures such as Sickle Ripper
|
||||
*/
|
||||
@Test
|
||||
public void scarab_witherDamageTriggers() {
|
||||
|
||||
String sickleRipper = "Sickle Ripper"; // {1}{B} 2/1 Creature - Elemental Warrior, Wither
|
||||
String wOmens = "Wall of Omens"; // {1}{W} 0/4 defender ETB: draw a card
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, nestScarabs);
|
||||
addCard(Zone.BATTLEFIELD, playerA, sickleRipper);
|
||||
addCard(Zone.BATTLEFIELD, playerB, wOmens);
|
||||
|
||||
attack(3, playerA, sickleRipper);
|
||||
block(3, playerB, wOmens, sickleRipper);
|
||||
|
||||
setStopAt(3, PhaseStep.END_COMBAT);
|
||||
execute();
|
||||
|
||||
assertLife(playerB, 20);
|
||||
assertPowerToughness(playerB, wOmens, -2, 2); // 0/4 with two -1/-1 counters
|
||||
assertCounterCount(playerB, wOmens, CounterType.M1M1, 2);
|
||||
assertPermanentCount(playerA, "Insect", 2);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
package org.mage.test.cards.mana;
|
||||
|
||||
import mage.abilities.costs.mana.ColorlessManaCost;
|
||||
import mage.constants.ManaType;
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
import org.mage.test.serverside.base.impl.CardTestAPIImpl;
|
||||
|
||||
public class DoublingCubeTest extends CardTestPlayerBase {
|
||||
|
||||
// {3}, {T}: Double the amount of each type of mana in your mana pool.
|
||||
String cube = "Doubling Cube";
|
||||
// {T}: Add {C}{C} to your mana pool. Spend this mana only to cast colorless Eldrazi spells or activate abilities of colorless Eldrazi.
|
||||
String temple = "Eldrazi Temple";
|
||||
// Mana pools don't empty as steps and phases end.
|
||||
String upwelling = "Upwelling";
|
||||
|
||||
//issue 3443
|
||||
@Test
|
||||
public void DoublingCubeEldraziTemple() {
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, temple);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 3);
|
||||
addCard(Zone.BATTLEFIELD, playerA, cube);
|
||||
addCard(Zone.BATTLEFIELD, playerA, upwelling);
|
||||
|
||||
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {G} to your mana pool");
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {G} to your mana pool");
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {G} to your mana pool");
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {C}{C}");
|
||||
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{3},{T}:");
|
||||
|
||||
setStopAt(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
execute();
|
||||
assertManaPool(playerA, ManaType.COLORLESS, 4);
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -119,4 +119,34 @@ public class GameIsADrawTest extends CardTestPlayerBase {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that a simple triggered ability does not trigger the infinite loop
|
||||
* request to players
|
||||
*/
|
||||
@Test
|
||||
public void GameDrawByInfiniteLoopNot() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 43);
|
||||
|
||||
// Whenever a creature enters the battlefield under your control, you gain life equal to its toughness.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Angelic Chorus", 1); // Enchantment {5}
|
||||
|
||||
// Create X 4/4 white Angel creature tokens with flying.
|
||||
// Miracle (You may cast this card for its miracle cost when you draw it if it's the first card you drew this turn.)
|
||||
addCard(Zone.HAND, playerA, "Entreat the Angels", 1); // Sorcery {X}{X}{W}{W}{W}
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Entreat the Angels");
|
||||
|
||||
setChoice(playerA, "X=20");
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerA, "Angel", 20);
|
||||
Assert.assertFalse("Game should not have ended.", currentGame.hasEnded());
|
||||
assertLife(playerA, 100);
|
||||
|
||||
Assert.assertFalse("No inifinite loop detected, game has be no draw.", currentGame.isADraw());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package org.mage.test.serverside.base.impl;
|
||||
|
||||
import mage.Mana;
|
||||
import mage.abilities.Ability;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.decks.Deck;
|
||||
|
@ -7,10 +8,7 @@ import mage.cards.decks.importer.DeckImporterUtil;
|
|||
import mage.cards.repository.CardInfo;
|
||||
import mage.cards.repository.CardRepository;
|
||||
import mage.cards.repository.CardScanner;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.RangeOfInfluence;
|
||||
import mage.constants.Zone;
|
||||
import mage.constants.*;
|
||||
import mage.counters.CounterType;
|
||||
import mage.filter.Filter;
|
||||
import mage.filter.FilterCard;
|
||||
|
@ -22,6 +20,7 @@ import mage.game.GameOptions;
|
|||
import mage.game.command.CommandObject;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.permanent.PermanentCard;
|
||||
import mage.players.ManaPool;
|
||||
import mage.players.Player;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
|
@ -833,6 +832,31 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
|
|||
Assert.assertEquals("(Hand) Card counts for card " + cardName + " for " + player.getName() + " are not equal ", count, actual);
|
||||
}
|
||||
|
||||
|
||||
public void assertManaPool(Player player, ManaType color, int amount){
|
||||
ManaPool manaPool = currentGame.getPlayer(player.getId()).getManaPool();
|
||||
switch (color){
|
||||
case COLORLESS:
|
||||
Assert.assertEquals(manaPool.getColorless() + manaPool.getConditionalMana().stream().mapToInt(Mana::getColorless).sum(), amount);
|
||||
break;
|
||||
case RED:
|
||||
Assert.assertEquals(manaPool.getRed() + manaPool.getConditionalMana().stream().mapToInt(Mana::getRed).sum(), amount);
|
||||
break;
|
||||
case BLUE:
|
||||
Assert.assertEquals(manaPool.getBlue() + manaPool.getConditionalMana().stream().mapToInt(Mana::getBlue).sum(), amount);
|
||||
break;
|
||||
case WHITE:
|
||||
Assert.assertEquals(manaPool.getWhite() + manaPool.getConditionalMana().stream().mapToInt(Mana::getWhite).sum(), amount);
|
||||
break;
|
||||
case GREEN:
|
||||
Assert.assertEquals(manaPool.getGreen() + manaPool.getConditionalMana().stream().mapToInt(Mana::getGreen).sum(), amount);
|
||||
break;
|
||||
case BLACK:
|
||||
Assert.assertEquals(manaPool.getBlack() + manaPool.getConditionalMana().stream().mapToInt(Mana::getBlack).sum(), amount);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert card count in player's graveyard.
|
||||
*
|
||||
|
|
|
@ -27,6 +27,10 @@
|
|||
*/
|
||||
package org.mage.test.stub;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import mage.cards.ExpansionSet;
|
||||
import mage.cards.decks.Deck;
|
||||
import mage.game.draft.Draft;
|
||||
|
@ -38,11 +42,6 @@ import mage.game.tournament.*;
|
|||
import mage.players.Player;
|
||||
import mage.players.PlayerType;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Quercitron
|
||||
|
@ -112,8 +111,8 @@ public class TournamentStub implements Tournament {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void updateDeck(UUID playerId, Deck deck) {
|
||||
|
||||
public boolean updateDeck(UUID playerId, Deck deck) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -48,6 +48,7 @@ public class Deck implements Serializable {
|
|||
private DeckCardLayout cardsLayout;
|
||||
private DeckCardLayout sideboardLayout;
|
||||
private long deckHashCode = 0;
|
||||
private long deckCompleteHashCode = 0;
|
||||
|
||||
public static Deck load(DeckCardLists deckCardLists) throws GameException {
|
||||
return Deck.load(deckCardLists, false);
|
||||
|
@ -90,11 +91,13 @@ public class Deck implements Serializable {
|
|||
for (DeckCardInfo deckCardInfo : deckCardLists.getCards()) {
|
||||
Card card = createCard(deckCardInfo, mockCards);
|
||||
if (card != null) {
|
||||
if (totalCards < 1000) {
|
||||
deck.cards.add(card);
|
||||
deckCardNames.add(card.getName());
|
||||
totalCards++;
|
||||
if (totalCards > 1000) {
|
||||
break;
|
||||
}
|
||||
deck.cards.add(card);
|
||||
deckCardNames.add(card.getName());
|
||||
totalCards++;
|
||||
|
||||
} else if (!ignoreErrors) {
|
||||
throw createCardNotFoundGameException(deckCardInfo, deckCardLists.getName());
|
||||
}
|
||||
|
@ -103,11 +106,12 @@ public class Deck implements Serializable {
|
|||
for (DeckCardInfo deckCardInfo : deckCardLists.getSideboard()) {
|
||||
Card card = createCard(deckCardInfo, mockCards);
|
||||
if (card != null) {
|
||||
if (totalCards < 1000) {
|
||||
deck.sideboard.add(card);
|
||||
sbCardNames.add(card.getName());
|
||||
totalCards++;
|
||||
if (totalCards > 1000) {
|
||||
break;
|
||||
}
|
||||
deck.sideboard.add(card);
|
||||
sbCardNames.add(card.getName());
|
||||
totalCards++;
|
||||
} else if (!ignoreErrors) {
|
||||
throw createCardNotFoundGameException(deckCardInfo, deckCardLists.getName());
|
||||
}
|
||||
|
@ -116,6 +120,15 @@ public class Deck implements Serializable {
|
|||
Collections.sort(sbCardNames);
|
||||
String deckString = deckCardNames.toString() + sbCardNames.toString();
|
||||
deck.setDeckHashCode(DeckUtil.fixedHash(deckString));
|
||||
if (sbCardNames.isEmpty()) {
|
||||
deck.setDeckCompleteHashCode(deck.getDeckHashCode());
|
||||
} else {
|
||||
List<String> deckAllCardNames = new ArrayList<>();
|
||||
deckAllCardNames.addAll(deckCardNames);
|
||||
deckAllCardNames.addAll(sbCardNames);
|
||||
Collections.sort(deckAllCardNames);
|
||||
deck.setDeckCompleteHashCode(DeckUtil.fixedHash(deckAllCardNames.toString()));
|
||||
}
|
||||
return deck;
|
||||
}
|
||||
|
||||
|
@ -206,6 +219,14 @@ public class Deck implements Serializable {
|
|||
this.deckHashCode = deckHashCode;
|
||||
}
|
||||
|
||||
public long getDeckCompleteHashCode() {
|
||||
return deckCompleteHashCode;
|
||||
}
|
||||
|
||||
public void setDeckCompleteHashCode(long deckHashCode) {
|
||||
this.deckCompleteHashCode = deckHashCode;
|
||||
}
|
||||
|
||||
public void clearLayouts() {
|
||||
this.cardsLayout = null;
|
||||
this.sideboardLayout = null;
|
||||
|
|
|
@ -28,7 +28,7 @@ public enum ExpansionRepository {
|
|||
private static final String JDBC_URL = "jdbc:h2:file:./db/cards.h2;AUTO_SERVER=TRUE";
|
||||
private static final String VERSION_ENTITY_NAME = "expansion";
|
||||
private static final long EXPANSION_DB_VERSION = 5;
|
||||
private static final long EXPANSION_CONTENT_VERSION = 12;
|
||||
private static final long EXPANSION_CONTENT_VERSION = 13;
|
||||
|
||||
private Dao<ExpansionInfo, Object> expansionDao;
|
||||
|
||||
|
|
|
@ -177,6 +177,8 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
protected PlayerList playerList;
|
||||
|
||||
private int infiniteLoopCounter; // used to check if the game is in an infinite loop
|
||||
private int lastNumberOfAbilitiesOnTheStack; // used to check how long no new ability was put to stack
|
||||
private final LinkedList<UUID> stackObjectsCheck = new LinkedList<>(); // used to check if different sources used the stack
|
||||
// used to set the counters a permanent adds the battlefield (if no replacement effect is used e.g. Persist)
|
||||
protected Map<UUID, Counters> enterWithCounters = new HashMap<>();
|
||||
|
||||
|
@ -1289,7 +1291,6 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
}
|
||||
if (allPassed()) {
|
||||
if (!state.getStack().isEmpty()) {
|
||||
checkInfiniteLoop();
|
||||
//20091005 - 115.4
|
||||
resolve();
|
||||
applyEffects();
|
||||
|
@ -1298,7 +1299,6 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
resetShortLivingLKI();
|
||||
break;
|
||||
} else {
|
||||
infiniteLoopCounter = 0;
|
||||
resetLKI();
|
||||
return;
|
||||
}
|
||||
|
@ -1346,6 +1346,7 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
if (top != null) {
|
||||
state.getStack().remove(top); // seems partly redundant because move card from stack to grave is already done and the stack removed
|
||||
rememberLKI(top.getSourceId(), Zone.STACK, top);
|
||||
checkInfiniteLoop(top.getSourceId());
|
||||
if (!getTurn().isEndTurnRequested()) {
|
||||
while (state.hasSimultaneousEvents()) {
|
||||
state.handleSimultaneousEvent(this);
|
||||
|
@ -1357,40 +1358,44 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
|
||||
/**
|
||||
* This checks if the stack gets filled iterated, without ever getting empty
|
||||
* If the defined number of iterations is reached, the players in range of
|
||||
* the stackObject get asked to confirm a draw. If they do, all confirming
|
||||
* players get set to a draw.
|
||||
* If the defined number of iterations with not more than 4 different
|
||||
* sourceIds for the removed stack Objects is reached, the players in range
|
||||
* of the stackObject get asked to confirm a draw. If they do, all
|
||||
* confirming players get set to a draw.
|
||||
*
|
||||
* Possible to improve: check that always the same set of stackObjects are
|
||||
* again aand again on the stack
|
||||
* @param removedStackObjectSourceId
|
||||
*/
|
||||
protected void checkInfiniteLoop() {
|
||||
if (getStack().size() < 4) { // to prevent that this also pops up, if e.g. 20 triggers resolve at once
|
||||
protected void checkInfiniteLoop(UUID removedStackObjectSourceId) {
|
||||
if (stackObjectsCheck.contains(removedStackObjectSourceId)
|
||||
&& getStack().size() >= lastNumberOfAbilitiesOnTheStack) {
|
||||
infiniteLoopCounter++;
|
||||
if (infiniteLoopCounter > 15) {
|
||||
StackObject stackObject = getStack().getFirst();
|
||||
if (stackObject != null) {
|
||||
Player controller = getPlayer(stackObject.getControllerId());
|
||||
if (controller != null) {
|
||||
for (UUID playerId : getState().getPlayersInRange(controller.getId(), this)) {
|
||||
Player player = getPlayer(playerId);
|
||||
if (!player.chooseUse(Outcome.Detriment, "Draw game because of infinite looping?", null, this)) {
|
||||
informPlayers(controller.getLogName() + " has NOT confirmed that the game is a draw because of infinite looping.");
|
||||
infiniteLoopCounter = 0;
|
||||
return;
|
||||
}
|
||||
informPlayers(controller.getLogName() + " has confirmed that the game is a draw because of infinite looping.");
|
||||
Player controller = getPlayer(getControllerId(removedStackObjectSourceId));
|
||||
if (controller != null) {
|
||||
for (UUID playerId : getState().getPlayersInRange(controller.getId(), this)) {
|
||||
Player player = getPlayer(playerId);
|
||||
if (!player.chooseUse(Outcome.Detriment, "Draw game because of infinite looping?", null, this)) {
|
||||
informPlayers(controller.getLogName() + " has NOT confirmed that the game is a draw because of infinite looping.");
|
||||
infiniteLoopCounter = 0;
|
||||
return;
|
||||
}
|
||||
for (UUID playerId : getState().getPlayersInRange(controller.getId(), this)) {
|
||||
Player player = getPlayer(playerId);
|
||||
if (player != null) {
|
||||
player.drew(this);
|
||||
}
|
||||
informPlayers(controller.getLogName() + " has confirmed that the game is a draw because of infinite looping.");
|
||||
}
|
||||
for (UUID playerId : getState().getPlayersInRange(controller.getId(), this)) {
|
||||
Player player = getPlayer(playerId);
|
||||
if (player != null) {
|
||||
player.drew(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
stackObjectsCheck.add(removedStackObjectSourceId);
|
||||
if (stackObjectsCheck.size() > 4) {
|
||||
stackObjectsCheck.removeFirst();
|
||||
}
|
||||
}
|
||||
lastNumberOfAbilitiesOnTheStack = getStack().size();
|
||||
}
|
||||
|
||||
protected boolean allPassed() {
|
||||
|
@ -2618,6 +2623,8 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
public void resetLKI() {
|
||||
lki.clear();
|
||||
lkiExtended.clear();
|
||||
infiniteLoopCounter = 0;
|
||||
stackObjectsCheck.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
package mage.game;
|
||||
|
||||
import java.io.Serializable;
|
||||
import mage.constants.PhaseStep;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Game options for Mage game. Mainly used in tests to configure
|
||||
* {@link GameImpl} with specific params.
|
||||
|
@ -42,4 +45,10 @@ public class GameOptions implements Serializable {
|
|||
* If true, players can rollback turn if all players agree
|
||||
*/
|
||||
public boolean rollbackTurnsAllowed = true;
|
||||
|
||||
/**
|
||||
* Names of users banned from participating in the game
|
||||
*/
|
||||
public Set<String> bannedUsers = Collections.emptySet();
|
||||
|
||||
}
|
||||
|
|
|
@ -25,21 +25,19 @@
|
|||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
package mage.game.match;
|
||||
|
||||
import mage.cards.decks.Deck;
|
||||
import mage.game.Game;
|
||||
import mage.game.GameException;
|
||||
import mage.game.events.Listener;
|
||||
import mage.game.events.TableEvent;
|
||||
import mage.players.Player;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import mage.cards.decks.Deck;
|
||||
import mage.game.Game;
|
||||
import mage.game.GameException;
|
||||
import mage.game.GameInfo;
|
||||
import mage.game.events.Listener;
|
||||
import mage.game.events.TableEvent;
|
||||
import mage.game.result.ResultProtos.MatchProto;
|
||||
import mage.players.Player;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -50,46 +48,73 @@ public interface Match {
|
|||
int SIDEBOARD_TIME = 180;
|
||||
|
||||
UUID getId();
|
||||
|
||||
String getName();
|
||||
|
||||
boolean hasEnded();
|
||||
|
||||
boolean hasStarted();
|
||||
|
||||
boolean checkIfMatchEnds();
|
||||
|
||||
List<MatchPlayer> getPlayers();
|
||||
|
||||
MatchPlayer getPlayer(UUID playerId);
|
||||
|
||||
void addPlayer(Player player, Deck deck);
|
||||
|
||||
boolean quitMatch(UUID playerId);
|
||||
|
||||
void submitDeck(UUID playerId, Deck deck);
|
||||
void updateDeck(UUID playerId, Deck deck);
|
||||
|
||||
boolean updateDeck(UUID playerId, Deck deck);
|
||||
|
||||
void startMatch();
|
||||
|
||||
void startGame() throws GameException;
|
||||
|
||||
void sideboard();
|
||||
|
||||
void endGame();
|
||||
|
||||
Game getGame();
|
||||
|
||||
List<Game> getGames();
|
||||
|
||||
int getWinsNeeded();
|
||||
|
||||
int getFreeMulligans();
|
||||
|
||||
void addDraw();
|
||||
|
||||
int getDraws();
|
||||
|
||||
int getNumGames();
|
||||
|
||||
void addGame();
|
||||
|
||||
boolean isDoneSideboarding();
|
||||
|
||||
UUID getChooser();
|
||||
|
||||
MatchOptions getOptions();
|
||||
|
||||
void addTableEventListener(Listener<TableEvent> listener);
|
||||
|
||||
void fireSideboardEvent(UUID playerId, Deck deck);
|
||||
|
||||
// match times
|
||||
Date getStartTime();
|
||||
|
||||
Date getEndTime();
|
||||
|
||||
/**
|
||||
* Can the games of the match be replayed
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
boolean isReplayAvailable();
|
||||
|
||||
void setReplayAvailable(boolean replayAvailable);
|
||||
|
||||
/**
|
||||
|
@ -111,6 +136,7 @@ public interface Match {
|
|||
List<GameInfo> getGamesInfo();
|
||||
|
||||
void setTableId(UUID tableId);
|
||||
|
||||
void setTournamentRound(int round);
|
||||
|
||||
MatchProto toProto();
|
||||
|
|
|
@ -409,11 +409,18 @@ public abstract class MatchImpl implements Match {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void updateDeck(UUID playerId, Deck deck) {
|
||||
public boolean updateDeck(UUID playerId, Deck deck) {
|
||||
boolean validDeck = true;
|
||||
MatchPlayer player = getPlayer(playerId);
|
||||
if (player != null) {
|
||||
// Check if the cards included in the deck are the same as in the original deck
|
||||
validDeck = (player.getDeck().getDeckCompleteHashCode() == deck.getDeckCompleteHashCode());
|
||||
if (validDeck == false) {
|
||||
deck.getCards().clear(); // Clear the deck so the player cheating looses the game
|
||||
}
|
||||
player.updateDeck(deck);
|
||||
}
|
||||
return validDeck;
|
||||
}
|
||||
|
||||
protected String createGameStartMessage() {
|
||||
|
@ -502,10 +509,10 @@ public abstract class MatchImpl implements Match {
|
|||
.setMatchOptions(this.getOptions().toProto())
|
||||
.setEndTimeMs((this.getEndTime() != null ? this.getEndTime() : new Date()).getTime());
|
||||
for (MatchPlayer matchPlayer : this.getPlayers()) {
|
||||
MatchQuitStatus status = !matchPlayer.hasQuit() ? MatchQuitStatus.NO_MATCH_QUIT :
|
||||
matchPlayer.getPlayer().hasTimerTimeout() ? MatchQuitStatus.TIMER_TIMEOUT :
|
||||
matchPlayer.getPlayer().hasIdleTimeout() ? MatchQuitStatus.IDLE_TIMEOUT :
|
||||
MatchQuitStatus.QUIT;
|
||||
MatchQuitStatus status = !matchPlayer.hasQuit() ? MatchQuitStatus.NO_MATCH_QUIT
|
||||
: matchPlayer.getPlayer().hasTimerTimeout() ? MatchQuitStatus.TIMER_TIMEOUT
|
||||
: matchPlayer.getPlayer().hasIdleTimeout() ? MatchQuitStatus.IDLE_TIMEOUT
|
||||
: MatchQuitStatus.QUIT;
|
||||
builder.addPlayersBuilder()
|
||||
.setName(matchPlayer.getName())
|
||||
.setHuman(matchPlayer.getPlayer().isHuman())
|
||||
|
|
|
@ -98,6 +98,7 @@ public class MatchPlayer implements Serializable {
|
|||
if (this.deck != null) {
|
||||
// preserver deck name, important for Tiny Leaders format
|
||||
deck.setName(this.getDeck().getName());
|
||||
// preserve the original deck hash code before sideboarding to give no information if cards were swapped
|
||||
deck.setDeckHashCode(this.getDeck().getDeckHashCode());
|
||||
}
|
||||
this.deck = deck;
|
||||
|
|
|
@ -42,7 +42,7 @@ public class BeastToken extends Token {
|
|||
final static private List<String> tokenImageSets = new ArrayList<>();
|
||||
|
||||
static {
|
||||
tokenImageSets.addAll(Arrays.asList("C14", "LRW", "M15", "M14", "DDL", "M13", "M12", "DD3GVL", "NPH", "M11", "M10", "EVE", "MM3"));
|
||||
tokenImageSets.addAll(Arrays.asList("C14", "LRW", "M15", "M14", "DDL", "M13", "M12", "DD3GVL", "NPH", "M11", "M10", "EVE", "MM3", "CMA", "E01"));
|
||||
}
|
||||
|
||||
public BeastToken() {
|
||||
|
|
|
@ -42,7 +42,7 @@ public class BeastToken2 extends Token {
|
|||
final static private List<String> tokenImageSets = new ArrayList<>();
|
||||
|
||||
static {
|
||||
tokenImageSets.addAll(Arrays.asList("ZEN", "C14", "DDD", "C15", "DD3GVL", "MM3"));
|
||||
tokenImageSets.addAll(Arrays.asList("ZEN", "C14", "DDD", "C15", "DD3GVL", "MM3", "CMA", "E01"));
|
||||
}
|
||||
|
||||
public BeastToken2() {
|
||||
|
|
|
@ -43,7 +43,7 @@ public class DragonToken2 extends Token {
|
|||
final static private List<String> tokenImageSets = new ArrayList<>();
|
||||
|
||||
static {
|
||||
tokenImageSets.addAll(Arrays.asList("WWK", "10E", "BFZ", "C15", "CN2"));
|
||||
tokenImageSets.addAll(Arrays.asList("WWK", "10E", "BFZ", "C15", "CN2", "CMA"));
|
||||
}
|
||||
|
||||
public DragonToken2() {
|
||||
|
|
|
@ -43,7 +43,7 @@ public class ElephantToken extends Token {
|
|||
final static private List<String> tokenImageSets = new ArrayList<>();
|
||||
|
||||
static {
|
||||
tokenImageSets.addAll(Arrays.asList("C14", "CNS", "DDD", "MM2", "WWK", "OGW", "C15", "DD3GVL", "MM3"));
|
||||
tokenImageSets.addAll(Arrays.asList("C14", "CNS", "DDD", "MM2", "WWK", "OGW", "C15", "DD3GVL", "MM3", "CMA"));
|
||||
}
|
||||
|
||||
public ElephantToken() {
|
||||
|
|
|
@ -27,6 +27,9 @@
|
|||
*/
|
||||
|
||||
package mage.game.permanent.token;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import mage.constants.CardType;
|
||||
import mage.MageInt;
|
||||
import mage.ObjectColor;
|
||||
|
@ -38,9 +41,24 @@ import mage.abilities.mana.GreenManaAbility;
|
|||
*/
|
||||
public class FreyaliseLlanowarsFuryToken extends Token {
|
||||
|
||||
final static private List<String> tokenImageSets = new ArrayList<>();
|
||||
|
||||
static {
|
||||
tokenImageSets.addAll(Arrays.asList("C14", "CMA"));
|
||||
}
|
||||
|
||||
public FreyaliseLlanowarsFuryToken() {
|
||||
this(null, 0);
|
||||
}
|
||||
|
||||
public FreyaliseLlanowarsFuryToken(String setCode) {
|
||||
this(setCode, 0);
|
||||
}
|
||||
|
||||
public FreyaliseLlanowarsFuryToken(String setCode, int tokenType) {
|
||||
super("Elf Druid", "1/1 green Elf Druid creature token with \"{T}: Add {G} to your mana pool.\"");
|
||||
this.setOriginalExpansionSetCode("C14");
|
||||
availableImageSetCodes = tokenImageSets;
|
||||
setOriginalExpansionSetCode(setCode);
|
||||
this.cardType.add(CardType.CREATURE);
|
||||
this.color = ObjectColor.GREEN;
|
||||
this.subtype.add("Elf");
|
||||
|
|
|
@ -16,7 +16,7 @@ public class KnightToken extends Token {
|
|||
final static private List<String> tokenImageSets = new ArrayList<>();
|
||||
|
||||
static {
|
||||
tokenImageSets.addAll(Arrays.asList("ORI", "RTR", "C15"));
|
||||
tokenImageSets.addAll(Arrays.asList("ORI", "RTR", "C15", "CMA"));
|
||||
}
|
||||
|
||||
public KnightToken() {
|
||||
|
|
|
@ -27,6 +27,9 @@
|
|||
*/
|
||||
|
||||
package mage.game.permanent.token;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import mage.constants.CardType;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
|
@ -37,8 +40,24 @@ import mage.abilities.keyword.FlyingAbility;
|
|||
*/
|
||||
public class LeafdrakeRoostDrakeToken extends Token {
|
||||
|
||||
final static private List<String> tokenImageSets = new ArrayList<>();
|
||||
|
||||
static {
|
||||
tokenImageSets.addAll(Arrays.asList("C13", "CMA"));
|
||||
}
|
||||
|
||||
public LeafdrakeRoostDrakeToken() {
|
||||
this(null, 0);
|
||||
}
|
||||
|
||||
public LeafdrakeRoostDrakeToken(String setCode) {
|
||||
this(setCode, 0);
|
||||
}
|
||||
|
||||
public LeafdrakeRoostDrakeToken(String setCode, int tokenType) {
|
||||
super("Drake", "2/2 green and blue Drake creature token with flying");
|
||||
availableImageSetCodes = tokenImageSets;
|
||||
setOriginalExpansionSetCode(setCode);
|
||||
cardType.add(CardType.CREATURE);
|
||||
color.setGreen(true);
|
||||
color.setBlue(true);
|
||||
|
|
|
@ -44,7 +44,7 @@ public class SaprolingToken extends Token {
|
|||
final static private List<String> tokenImageSets = new ArrayList<>();
|
||||
|
||||
static {
|
||||
tokenImageSets.addAll(Arrays.asList("10E", "ALA", "DDE", "DDH", "DDJ", "M12", "M13", "M14", "MM2", "MMA", "RTR", "C15", "MM3", "C16"));
|
||||
tokenImageSets.addAll(Arrays.asList("10E", "ALA", "DDE", "DDH", "DDJ", "M12", "M13", "M14", "MM2", "MMA", "RTR", "C15", "MM3", "C16", "CMA"));
|
||||
}
|
||||
|
||||
public SaprolingToken() {
|
||||
|
|
|
@ -44,7 +44,7 @@ public class SoldierToken extends Token {
|
|||
|
||||
static {
|
||||
tokenImageSets.addAll(Arrays.asList("10E", "M15", "C14", "ORI", "ALA", "DDF", "THS", "M12", "M13", "MM2", "MMA", "RTR",
|
||||
"SOM", "DDO", "M10", "ORI", "EMN", "EMA", "CN2", "C16", "MM3"));
|
||||
"SOM", "DDO", "M10", "ORI", "EMN", "EMA", "CN2", "C16", "MM3", "E01"));
|
||||
}
|
||||
|
||||
public SoldierToken() {
|
||||
|
|
|
@ -42,7 +42,7 @@ public class SpiritWhiteToken extends Token {
|
|||
final static private List<String> tokenImageSets = new ArrayList<>();
|
||||
|
||||
static {
|
||||
tokenImageSets.addAll(Arrays.asList("AVR", "C14", "CNS", "DDC", "DDK", "FRF", "ISD", "KTK", "M15", "MM2", "SHM", "SOI", "EMA", "C16", "MM3"));
|
||||
tokenImageSets.addAll(Arrays.asList("AVR", "C14", "CNS", "DDC", "DDK", "FRF", "ISD", "KTK", "M15", "MM2", "SHM", "SOI", "EMA", "C16", "MM3", "CMA", "E01"));
|
||||
}
|
||||
|
||||
public SpiritWhiteToken() {
|
||||
|
|
|
@ -27,6 +27,9 @@
|
|||
*/
|
||||
|
||||
package mage.game.permanent.token;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import mage.constants.CardType;
|
||||
import mage.MageInt;
|
||||
import mage.ObjectColor;
|
||||
|
@ -37,13 +40,27 @@ import mage.ObjectColor;
|
|||
*/
|
||||
public class TitaniaProtectorOfArgothElementalToken extends Token {
|
||||
|
||||
final static private List<String> tokenImageSets = new ArrayList<>();
|
||||
|
||||
static {
|
||||
tokenImageSets.addAll(Arrays.asList("C14", "CMA"));
|
||||
}
|
||||
|
||||
public TitaniaProtectorOfArgothElementalToken() {
|
||||
this(null, 0);
|
||||
}
|
||||
|
||||
public TitaniaProtectorOfArgothElementalToken(String setCode) {
|
||||
this(setCode, 0);
|
||||
}
|
||||
|
||||
public TitaniaProtectorOfArgothElementalToken(String setCode, int tokenType) {
|
||||
super("Elemental", "5/3 green Elemental creature token");
|
||||
this.setOriginalExpansionSetCode("C14");
|
||||
availableImageSetCodes = tokenImageSets;
|
||||
this.setOriginalExpansionSetCode(setCode);
|
||||
this.cardType.add(CardType.CREATURE);
|
||||
this.color = ObjectColor.GREEN;
|
||||
this.subtype.add("Elemental");
|
||||
|
||||
this.power = new MageInt(5);
|
||||
this.toughness = new MageInt(3);
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ public class ZombieToken extends Token {
|
|||
|
||||
static {
|
||||
tokenImageSets.addAll(Arrays.asList("10E", "M10", "M11", "M12", "M13", "M14", "M15", "MBS", "ALA", "ISD", "C14", "C15", "C16", "CNS",
|
||||
"MMA", "BNG", "KTK", "DTK", "ORI", "OGW", "SOI", "EMN", "EMA", "MM3", "AKH"));
|
||||
"MMA", "BNG", "KTK", "DTK", "ORI", "OGW", "SOI", "EMN", "EMA", "MM3", "AKH", "CMA", "E01"));
|
||||
}
|
||||
|
||||
public ZombieToken() {
|
||||
|
|
|
@ -27,6 +27,10 @@
|
|||
*/
|
||||
package mage.game.tournament;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import mage.cards.ExpansionSet;
|
||||
import mage.cards.decks.Deck;
|
||||
import mage.game.draft.Draft;
|
||||
|
@ -37,11 +41,6 @@ import mage.game.result.ResultProtos.TourneyProto;
|
|||
import mage.players.Player;
|
||||
import mage.players.PlayerType;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
|
@ -76,7 +75,7 @@ public interface Tournament {
|
|||
|
||||
void submitDeck(UUID playerId, Deck deck);
|
||||
|
||||
void updateDeck(UUID playerId, Deck deck);
|
||||
boolean updateDeck(UUID playerId, Deck deck);
|
||||
|
||||
void autoSubmit(UUID playerId, Deck deck);
|
||||
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
*/
|
||||
package mage.game.tournament;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import mage.cards.ExpansionSet;
|
||||
import mage.cards.decks.Deck;
|
||||
import mage.constants.TournamentPlayerState;
|
||||
|
@ -37,14 +39,16 @@ import mage.game.events.TableEvent.EventType;
|
|||
import mage.game.match.Match;
|
||||
import mage.game.match.MatchPlayer;
|
||||
import mage.game.result.ResultProtos.*;
|
||||
import mage.game.result.ResultProtos.MatchPlayerProto;
|
||||
import mage.game.result.ResultProtos.MatchProto;
|
||||
import mage.game.result.ResultProtos.MatchQuitStatus;
|
||||
import mage.game.result.ResultProtos.TourneyProto;
|
||||
import mage.game.result.ResultProtos.TourneyRoundProto;
|
||||
import mage.players.Player;
|
||||
import mage.players.PlayerType;
|
||||
import mage.util.RandomUtil;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
|
@ -168,10 +172,11 @@ public abstract class TournamentImpl implements Tournament {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void updateDeck(UUID playerId, Deck deck) {
|
||||
public boolean updateDeck(UUID playerId, Deck deck) {
|
||||
if (players.containsKey(playerId)) {
|
||||
players.get(playerId).updateDeck(deck);
|
||||
return players.get(playerId).updateDeck(deck);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected Round createRoundRandom() {
|
||||
|
@ -588,10 +593,10 @@ public abstract class TournamentImpl implements Tournament {
|
|||
|
||||
private MatchPlayerProto matchToProto(Match match, TournamentPlayer player) {
|
||||
MatchPlayer matchPlayer = match.getPlayer(player.getPlayer().getId());
|
||||
MatchQuitStatus quit = !matchPlayer.hasQuit() ? MatchQuitStatus.NO_MATCH_QUIT :
|
||||
matchPlayer.getPlayer().hasIdleTimeout() ? MatchQuitStatus.IDLE_TIMEOUT :
|
||||
matchPlayer.getPlayer().hasTimerTimeout() ? MatchQuitStatus.TIMER_TIMEOUT :
|
||||
MatchQuitStatus.QUIT;
|
||||
MatchQuitStatus quit = !matchPlayer.hasQuit() ? MatchQuitStatus.NO_MATCH_QUIT
|
||||
: matchPlayer.getPlayer().hasIdleTimeout() ? MatchQuitStatus.IDLE_TIMEOUT
|
||||
: matchPlayer.getPlayer().hasTimerTimeout() ? MatchQuitStatus.TIMER_TIMEOUT
|
||||
: MatchQuitStatus.QUIT;
|
||||
return MatchPlayerProto.newBuilder()
|
||||
.setName(player.getPlayer().getName())
|
||||
.setHuman(player.getPlayer().isHuman())
|
||||
|
|
|
@ -25,9 +25,9 @@
|
|||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
package mage.game.tournament;
|
||||
|
||||
import java.util.Set;
|
||||
import mage.cards.decks.Deck;
|
||||
import mage.constants.TournamentPlayerState;
|
||||
import mage.game.result.ResultProtos.TourneyPlayerProto;
|
||||
|
@ -36,8 +36,6 @@ import mage.players.Player;
|
|||
import mage.players.PlayerType;
|
||||
import mage.util.TournamentUtil;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
|
@ -117,8 +115,14 @@ public class TournamentPlayer {
|
|||
this.setState(TournamentPlayerState.WAITING);
|
||||
}
|
||||
|
||||
public void updateDeck(Deck deck) {
|
||||
public boolean updateDeck(Deck deck) {
|
||||
// Check if the cards included in the deck are the same as in the original deck
|
||||
boolean validDeck = (getDeck().getDeckCompleteHashCode() == deck.getDeckCompleteHashCode());
|
||||
if (validDeck == false) {
|
||||
deck.getCards().clear(); // Clear the deck so the player cheating looses the game
|
||||
}
|
||||
this.deck = deck;
|
||||
return validDeck;
|
||||
}
|
||||
|
||||
public Deck generateDeck() {
|
||||
|
@ -144,8 +148,6 @@ public class TournamentPlayer {
|
|||
return deck;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public boolean isDoneConstructing() {
|
||||
return this.doneConstructing;
|
||||
}
|
||||
|
@ -239,4 +241,3 @@ public class TournamentPlayer {
|
|||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.watchers.common;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.constants.WatcherScope;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.watchers.Watcher;
|
||||
import mage.players.PlayerList;
|
||||
|
||||
/**
|
||||
* @author spjspj
|
||||
*/
|
||||
public class PlayersAttackedLastTurnWatcher extends Watcher {
|
||||
|
||||
// Store how many players each player attacked in their last turn
|
||||
private final Map<UUID, PlayerList> playersAttackedInLastTurn = new HashMap<>();
|
||||
|
||||
public PlayersAttackedLastTurnWatcher() {
|
||||
super(PlayersAttackedLastTurnWatcher.class.getSimpleName(), WatcherScope.GAME);
|
||||
}
|
||||
|
||||
public PlayersAttackedLastTurnWatcher(final PlayersAttackedLastTurnWatcher watcher) {
|
||||
super(watcher);
|
||||
for (Map.Entry<UUID, PlayerList> entry : watcher.playersAttackedInLastTurn.entrySet()) {
|
||||
this.playersAttackedInLastTurn.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlayersAttackedLastTurnWatcher copy() {
|
||||
return new PlayersAttackedLastTurnWatcher(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void watch(GameEvent event, Game game) {
|
||||
if (event.getType() == GameEvent.EventType.BEGINNING_PHASE_PRE) {
|
||||
playersAttackedInLastTurn.remove(event.getPlayerId());
|
||||
}
|
||||
|
||||
if (event.getType() == GameEvent.EventType.ATTACKER_DECLARED) {
|
||||
PlayerList playersAttacked = playersAttackedInLastTurn.get(event.getPlayerId());
|
||||
if (playersAttacked == null) {
|
||||
playersAttacked = new PlayerList();
|
||||
}
|
||||
UUID defender = game.getCombat().getDefendingPlayerId(event.getSourceId(), game);
|
||||
if (defender != null) {
|
||||
playersAttacked.add(defender);
|
||||
}
|
||||
playersAttackedInLastTurn.put(event.getPlayerId(), playersAttacked);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean attackedLastTurn(UUID playerId, UUID otherPlayerId) {
|
||||
if (playersAttackedInLastTurn.get(playerId) != null) {
|
||||
return playersAttackedInLastTurn.get(playerId).contains(otherPlayerId);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -112,7 +112,7 @@ close CARD;
|
|||
print ("Unimplemented cards are here: " . lc($sets{$setName}) ."_unimplemented.txt\n");
|
||||
|
||||
open ISSUE_TRACKER, "> " . lc($sets{$setName}) ."_issue_tracker.txt";
|
||||
print ISSUE_TRACKER "# Cards in set:\n- [x] [Example Card Name] (example URL here)\n";
|
||||
print ISSUE_TRACKER "# Cards in set:\n";
|
||||
|
||||
|
||||
my $cn;
|
||||
|
@ -125,7 +125,7 @@ foreach $cn (sort keys (%cardNames))
|
|||
}
|
||||
my $cn2 = $cn;
|
||||
$cn2 =~ s/ /+/g;
|
||||
print ISSUE_TRACKER "- $x_or_not [$cn] (https://www.google.com.au/search?q=$cn2+MTG&tbm=isch)\n";
|
||||
print ISSUE_TRACKER "- $x_or_not [$cn](https://www.google.com.au/search?q=$cn2+MTG&tbm=isch)\n";
|
||||
}
|
||||
close ISSUE_TRACKER;
|
||||
print ("Tracking Issue text for a new Github issue (similar to https://github.com/magefree/mage/issues/2215): " . lc($sets{$setName}) ."_issue_tracker.txt\n");
|
||||
|
|
|
@ -181,6 +181,7 @@ Vintage Masters|VintageMasters|
|
|||
Visions|Visions|
|
||||
Weatherlight|Weatherlight|
|
||||
Welcome Deck 2016|WelcomeDeck2016|
|
||||
Welcome Deck 2017|WelcomeDeck2017|
|
||||
World Magic Cup Qualifier|WorldMagicCupQualifier|
|
||||
Worldwake|Worldwake|
|
||||
WPN Gateway|WPNGateway|
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -12,7 +12,6 @@ Aether Revolt|AER|
|
|||
Amonkhet|AKH|
|
||||
Shards of Alara|ALA|
|
||||
Alliances|ALL|
|
||||
Archenemy: Nicol Bolas|ANB|
|
||||
Asia Pacific Land Program|APAC|
|
||||
Apocalypse|APC|
|
||||
Alara Reborn|ARB|
|
||||
|
@ -72,6 +71,7 @@ From the Vault: Dragons|DRB|
|
|||
The Dark|DRK|
|
||||
Darksteel|DST|
|
||||
Dragons of Tarkir|DTK|
|
||||
Archenemy: Nicol Bolas|E01|
|
||||
Eternal Masters|EMA|
|
||||
Eldritch Moon|EMN|
|
||||
European Land Program|EURO|
|
||||
|
@ -189,6 +189,7 @@ MTGO Vanguard|VGO|
|
|||
Visions|VIS|
|
||||
Vintage Masters|VMA|
|
||||
Welcome Deck 2016|W16|
|
||||
Welcome Deck 2017|W17|
|
||||
World Magic Cup Qualifier|WMCQ|
|
||||
Weatherlight|WTH|
|
||||
Worldwake|WWK|
|
||||
|
|
Loading…
Reference in a new issue