Merge branch 'master' into master

This commit is contained in:
Evan Kranzler 2019-04-20 08:52:33 -04:00 committed by GitHub
commit 7cea71d6f2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
116 changed files with 3982 additions and 328 deletions

View file

@ -447,7 +447,7 @@ public class DeckEditorPanel extends javax.swing.JPanel {
}
}
});
refreshDeck();
refreshDeck(true);
if (mode == DeckEditorMode.FREE_BUILDING) {
setDropTarget(new DropTarget(this, new DnDDeckTargetListener() {

View file

@ -105,7 +105,7 @@ public class TablesPane extends MagePane {
@Override
public void activated() {
tablesPanel.startTasks();
tablesPanel.startUpdateTasks(false);
}
@Override

View file

@ -16,6 +16,7 @@ import mage.constants.*;
import mage.game.match.MatchOptions;
import mage.players.PlayerType;
import mage.remote.MageRemoteException;
import mage.util.RandomUtil;
import mage.view.MatchView;
import mage.view.RoomUsersView;
import mage.view.TableView;
@ -65,6 +66,7 @@ public class TablesPanel extends javax.swing.JPanel {
public static final int REFRESH_ACTIVE_TABLES_SECS = 5;
public static final int REFRESH_FINISHED_TABLES_SECS = 30;
public static final int REFRESH_PLAYERS_SECS = 10;
public static final double REFRESH_TIMEOUTS_INCREASE_FACTOR = 0.8; // can increase timeouts by 80% (0.8)
private final TablesTableModel tableModel;
private final MatchesTableModel matchesModel;
@ -211,6 +213,12 @@ public class TablesPanel extends javax.swing.JPanel {
return res;
}
public static int randomizeTimout(int minTimout) {
// randomize timeouts to fix calls waves -- slow server can creates queue and moves all clients to same call window
int increase = (int) (minTimout * REFRESH_TIMEOUTS_INCREASE_FACTOR);
return minTimout + RandomUtil.nextInt(increase);
}
/**
* Creates new form TablesPanel
@ -633,23 +641,31 @@ public class TablesPanel extends javax.swing.JPanel {
}
}
public void startTasks() {
public void startUpdateTasks(boolean refreshImmediately) {
if (SessionHandler.getSession() != null) {
if (updateTablesTask == null || updateTablesTask.isDone()) {
// active tables and server messages
if (updateTablesTask == null || updateTablesTask.isDone() || refreshImmediately) {
if (updateTablesTask != null) updateTablesTask.cancel(true);
updateTablesTask = new UpdateTablesTask(roomId, this);
updateTablesTask.execute();
}
if (updatePlayersTask == null || updatePlayersTask.isDone()) {
updatePlayersTask = new UpdatePlayersTask(roomId, this.chatPanelMain);
updatePlayersTask.execute();
}
// finished tables
if (this.btnStateFinished.isSelected()) {
if (updateMatchesTask == null || updateMatchesTask.isDone()) {
if (updateMatchesTask == null || updateMatchesTask.isDone() || refreshImmediately) {
if (updateMatchesTask != null) updateMatchesTask.cancel(true);
updateMatchesTask = new UpdateMatchesTask(roomId, this);
updateMatchesTask.execute();
}
} else if (updateMatchesTask != null) {
updateMatchesTask.cancel(true);
} else {
if (updateMatchesTask != null) updateMatchesTask.cancel(true);
}
// players list
if (updatePlayersTask == null || updatePlayersTask.isDone() || refreshImmediately) {
if (updatePlayersTask != null) updatePlayersTask.cancel(true);
updatePlayersTask = new UpdatePlayersTask(roomId, this.chatPanelMain);
updatePlayersTask.execute();
}
}
}
@ -688,7 +704,7 @@ public class TablesPanel extends javax.swing.JPanel {
}
if (chatRoomId != null) {
this.chatPanelMain.getUserChatPanel().connect(chatRoomId);
startTasks();
startUpdateTasks(true);
this.setVisible(true);
this.repaint();
} else {
@ -696,7 +712,7 @@ public class TablesPanel extends javax.swing.JPanel {
}
//tableModel.setSession(session);
reloadMessages();
reloadServerMessages();
MageFrame.getUI().addButton(MageComponents.NEW_GAME_BUTTON, btnNewTable);
@ -705,7 +721,7 @@ public class TablesPanel extends javax.swing.JPanel {
}
protected void reloadMessages() {
protected void reloadServerMessages() {
// reload server messages
java.util.List<String> serverMessages = SessionHandler.getServerMessages();
synchronized (this) {
@ -1581,7 +1597,7 @@ public class TablesPanel extends javax.swing.JPanel {
} else {
this.jSplitPaneTables.setDividerLocation(this.jPanelTables.getHeight());
}
this.startTasks();
this.startUpdateTasks(true);
}//GEN-LAST:event_btnStateFinishedActionPerformed
private void btnRatedbtnFilterActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRatedbtnFilterActionPerformed
@ -1666,6 +1682,7 @@ class UpdateTablesTask extends SwingWorker<Void, Collection<TableView>> {
private final UUID roomId;
private final TablesPanel panel;
private boolean isFirstRun = true;
private static final Logger logger = Logger.getLogger(UpdateTablesTask.class);
@ -1684,8 +1701,7 @@ class UpdateTablesTask extends SwingWorker<Void, Collection<TableView>> {
if (tables != null) {
this.publish(tables);
}
TimeUnit.SECONDS.sleep(TablesPanel.REFRESH_ACTIVE_TABLES_SECS);
TimeUnit.SECONDS.sleep(TablesPanel.randomizeTimout(TablesPanel.REFRESH_ACTIVE_TABLES_SECS));
}
return null;
}
@ -1693,10 +1709,13 @@ class UpdateTablesTask extends SwingWorker<Void, Collection<TableView>> {
@Override
protected void process(java.util.List<Collection<TableView>> view) {
panel.updateTables(view.get(0));
// update server messages
count++;
if (count > 60) {
if (isFirstRun || count > 60) {
count = 0;
panel.reloadMessages();
isFirstRun = false;
panel.reloadServerMessages();
}
}
@ -1729,7 +1748,7 @@ class UpdatePlayersTask extends SwingWorker<Void, Collection<RoomUsersView>> {
protected Void doInBackground() throws Exception {
while (!isCancelled()) {
this.publish(SessionHandler.getRoomUsers(roomId));
TimeUnit.SECONDS.sleep(TablesPanel.REFRESH_PLAYERS_SECS);
TimeUnit.SECONDS.sleep(TablesPanel.randomizeTimout(TablesPanel.REFRESH_PLAYERS_SECS));
}
return null;
}
@ -1766,11 +1785,8 @@ class UpdateMatchesTask extends SwingWorker<Void, Collection<MatchView>> {
@Override
protected Void doInBackground() throws Exception {
while (!isCancelled()) {
Collection<MatchView> matches = SessionHandler.getFinishedMatches(roomId);
if (!matches.isEmpty()) {
this.publish(matches);
}
TimeUnit.SECONDS.sleep(TablesPanel.REFRESH_FINISHED_TABLES_SECS);
this.publish(SessionHandler.getFinishedMatches(roomId));
TimeUnit.SECONDS.sleep(TablesPanel.randomizeTimout(TablesPanel.REFRESH_FINISHED_TABLES_SECS));
}
return null;
}

View file

@ -150,6 +150,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
if (target.getOriginalTarget() instanceof TargetPlayer) {
return setTargetPlayer(outcome, target, null, sourceId, abilityControllerId, randomOpponentId, game);
}
if (target.getOriginalTarget() instanceof TargetDiscard) {
findPlayables(game);
if (!unplayable.isEmpty()) {
@ -174,38 +175,43 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
return false;
}
if (target.getOriginalTarget() instanceof TargetControlledPermanent) {
List<Permanent> targets;
targets = threats(abilityControllerId, sourceId, ((TargetControlledPermanent) target).getFilter(), game, target.getTargets());
TargetControlledPermanent origTarget = (TargetControlledPermanent) target.getOriginalTarget();
targets = threats(abilityControllerId, sourceId, origTarget.getFilter(), game, target.getTargets());
if (!outcome.isGood()) {
Collections.reverse(targets);
}
for (Permanent permanent : targets) {
if (((TargetControlledPermanent) target).canTarget(abilityControllerId, permanent.getId(), sourceId, game, false) && !target.getTargets().contains(permanent.getId())) {
if (origTarget.canTarget(abilityControllerId, permanent.getId(), sourceId, game, false) && !target.getTargets().contains(permanent.getId())) {
target.add(permanent.getId(), game);
return true;
}
}
return false;
}
if (target.getOriginalTarget() instanceof TargetPermanent) {
TargetPermanent origTarget = (TargetPermanent) target.getOriginalTarget();
List<Permanent> targets;
if (outcome.isCanTargetAll()) {
targets = threats(null, sourceId, ((TargetPermanent) target).getFilter(), game, target.getTargets());
targets = threats(null, sourceId, origTarget.getFilter(), game, target.getTargets());
} else {
if (outcome.isGood()) {
targets = threats(abilityControllerId, sourceId, ((TargetPermanent) target).getFilter(), game, target.getTargets());
targets = threats(abilityControllerId, sourceId, origTarget.getFilter(), game, target.getTargets());
} else {
targets = threats(randomOpponentId, sourceId, ((TargetPermanent) target).getFilter(), game, target.getTargets());
targets = threats(randomOpponentId, sourceId, origTarget.getFilter(), game, target.getTargets());
}
if (targets.isEmpty() && target.isRequired()) {
if (!outcome.isGood()) {
targets = threats(abilityControllerId, sourceId, ((TargetPermanent) target).getFilter(), game, target.getTargets());
targets = threats(abilityControllerId, sourceId, origTarget.getFilter(), game, target.getTargets());
} else {
targets = threats(randomOpponentId, sourceId, ((TargetPermanent) target).getFilter(), game, target.getTargets());
targets = threats(randomOpponentId, sourceId, origTarget.getFilter(), game, target.getTargets());
}
}
}
for (Permanent permanent : targets) {
if (target.canTarget(abilityControllerId, permanent.getId(), null, game) && !target.getTargets().contains(permanent.getId())) {
// stop to add targets if not needed and outcome is no advantage for AI player
@ -246,17 +252,18 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
return target.isChosen();
}
if (target.getOriginalTarget() instanceof TargetAnyTarget) {
List<Permanent> targets;
TargetAnyTarget t = ((TargetAnyTarget) target);
TargetAnyTarget origTarget = (TargetAnyTarget) target.getOriginalTarget();
if (outcome.isGood()) {
targets = threats(abilityControllerId, sourceId, ((FilterCreaturePlayerOrPlaneswalker) t.getFilter()).getCreatureFilter(), game, target.getTargets());
targets = threats(abilityControllerId, sourceId, ((FilterCreaturePlayerOrPlaneswalker) origTarget.getFilter()).getCreatureFilter(), game, target.getTargets());
} else {
targets = threats(randomOpponentId, sourceId, ((FilterCreaturePlayerOrPlaneswalker) t.getFilter()).getCreatureFilter(), game, target.getTargets());
targets = threats(randomOpponentId, sourceId, ((FilterCreaturePlayerOrPlaneswalker) origTarget.getFilter()).getCreatureFilter(), game, target.getTargets());
}
for (Permanent permanent : targets) {
List<UUID> alreadyTargetted = target.getTargets();
if (t.canTarget(abilityControllerId, permanent.getId(), null, game)) {
if (target.canTarget(abilityControllerId, permanent.getId(), null, game)) {
if (alreadyTargetted != null && !alreadyTargetted.contains(permanent.getId())) {
target.add(permanent.getId(), game);
return true;
@ -276,17 +283,18 @@ public class ComputerPlayer extends PlayerImpl implements Player {
return false;
}
}
if (target.getOriginalTarget() instanceof TargetCreatureOrPlayer) {
List<Permanent> targets;
TargetCreatureOrPlayer t = ((TargetCreatureOrPlayer) target);
TargetCreatureOrPlayer origTarget = (TargetCreatureOrPlayer) target.getOriginalTarget();
if (outcome.isGood()) {
targets = threats(abilityControllerId, sourceId, ((FilterCreatureOrPlayer) t.getFilter()).getCreatureFilter(), game, target.getTargets());
targets = threats(abilityControllerId, sourceId, ((FilterCreatureOrPlayer) origTarget.getFilter()).getCreatureFilter(), game, target.getTargets());
} else {
targets = threats(randomOpponentId, sourceId, ((FilterCreatureOrPlayer) t.getFilter()).getCreatureFilter(), game, target.getTargets());
targets = threats(randomOpponentId, sourceId, ((FilterCreatureOrPlayer) origTarget.getFilter()).getCreatureFilter(), game, target.getTargets());
}
for (Permanent permanent : targets) {
List<UUID> alreadyTargeted = target.getTargets();
if (t.canTarget(abilityControllerId, permanent.getId(), null, game)) {
if (target.canTarget(abilityControllerId, permanent.getId(), null, game)) {
if (alreadyTargeted != null && !alreadyTargeted.contains(permanent.getId())) {
target.add(permanent.getId(), game);
return true;
@ -309,9 +317,9 @@ public class ComputerPlayer extends PlayerImpl implements Player {
if (target.getOriginalTarget() instanceof TargetPermanentOrPlayer) {
List<Permanent> targets;
TargetPermanentOrPlayer t = ((TargetPermanentOrPlayer) target);
List<Permanent> ownedTargets = threats(abilityControllerId, sourceId, ((FilterPermanentOrPlayer) t.getFilter()).getPermanentFilter(), game, target.getTargets());
List<Permanent> opponentTargets = threats(randomOpponentId, sourceId, ((FilterPermanentOrPlayer) t.getFilter()).getPermanentFilter(), game, target.getTargets());
TargetPermanentOrPlayer origTarget = (TargetPermanentOrPlayer) target.getOriginalTarget();
List<Permanent> ownedTargets = threats(abilityControllerId, sourceId, ((FilterPermanentOrPlayer) origTarget.getFilter()).getPermanentFilter(), game, target.getTargets());
List<Permanent> opponentTargets = threats(randomOpponentId, sourceId, ((FilterPermanentOrPlayer) origTarget.getFilter()).getPermanentFilter(), game, target.getTargets());
if (outcome.isGood()) {
targets = ownedTargets;
} else {
@ -319,7 +327,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
for (Permanent permanent : targets) {
List<UUID> alreadyTargeted = target.getTargets();
if (t.canTarget(permanent.getId(), game)) {
if (target.canTarget(permanent.getId(), game)) {
if (alreadyTargeted != null && !alreadyTargeted.contains(permanent.getId())) {
target.add(permanent.getId(), game);
return true;
@ -353,7 +361,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
for (Permanent permanent : targets) {
List<UUID> alreadyTargeted = target.getTargets();
if (t.canTarget(permanent.getId(), game)) {
if (target.canTarget(permanent.getId(), game)) {
if (alreadyTargeted != null && !alreadyTargeted.contains(permanent.getId())) {
target.add(permanent.getId(), game);
return true;
@ -362,6 +370,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
return false;
}
if (target.getOriginalTarget() instanceof TargetCardInGraveyard) {
List<Card> cards = new ArrayList<>();
for (Player player : game.getPlayers().values()) {
@ -395,15 +404,15 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
return false;
}
if (target.getOriginalTarget() instanceof TargetSource) {
Set<UUID> targets;
TargetSource t = ((TargetSource) target);
targets = t.possibleTargets(sourceId, abilityControllerId, game);
targets = target.possibleTargets(sourceId, abilityControllerId, game);
for (UUID targetId : targets) {
MageObject targetObject = game.getObject(targetId);
if (targetObject != null) {
List<UUID> alreadyTargeted = target.getTargets();
if (t.canTarget(targetObject.getId(), game)) {
if (target.canTarget(targetObject.getId(), game)) {
if (alreadyTargeted != null && !alreadyTargeted.contains(targetObject.getId())) {
target.add(targetObject.getId(), game);
return true;
@ -444,8 +453,10 @@ public class ComputerPlayer extends PlayerImpl implements Player {
return setTargetPlayer(outcome, target, source, source.getSourceId(), abilityControllerId, randomOpponentId, game);
}
if (target.getOriginalTarget() instanceof TargetDiscard || target.getOriginalTarget() instanceof TargetCardInHand) {
if (target.getOriginalTarget() instanceof TargetDiscard
|| target.getOriginalTarget() instanceof TargetCardInHand) {
if (outcome.isGood()) {
// good
Cards cards = new CardsImpl(target.possibleTargets(source.getSourceId(), getId(), game));
ArrayList<Card> cardsInHand = new ArrayList<>(cards.getCards(game));
while (!target.isChosen()
@ -463,6 +474,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
}
} else {
// bad
findPlayables(game);
if (!unplayable.isEmpty()) {
for (int i = unplayable.size() - 1; i >= 0; i--) {
@ -487,9 +499,11 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
return false;
}
if (target.getOriginalTarget() instanceof TargetControlledPermanent) {
TargetControlledPermanent origTarget = (TargetControlledPermanent) target.getOriginalTarget();
List<Permanent> targets;
targets = threats(abilityControllerId, source.getSourceId(), ((TargetControlledPermanent) target).getFilter(), game, target.getTargets());
targets = threats(abilityControllerId, source.getSourceId(), origTarget.getFilter(), game, target.getTargets());
if (!outcome.isGood()) {
Collections.reverse(targets);
}
@ -504,9 +518,10 @@ public class ComputerPlayer extends PlayerImpl implements Player {
return target.isChosen();
}
if (target.getOriginalTarget() instanceof TargetPermanent) {
List<Permanent> targets;
TargetPermanent t = (TargetPermanent) target.getOriginalTarget();
TargetPermanent origTarget = (TargetPermanent) target.getOriginalTarget();
boolean outcomeTargets = true;
if (outcome.isGood()) {
targets = threats(abilityControllerId, source == null ? null : source.getSourceId(), ((TargetPermanent) target).getFilter(), game, target.getTargets());
@ -520,7 +535,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
//targets = game.getBattlefield().getActivePermanents(((TargetPermanent)target).getFilter(), playerId, game);
}
if (targets.isEmpty() && target.isRequired()) {
targets = game.getBattlefield().getActivePermanents(t.getFilter(), playerId, game);
targets = game.getBattlefield().getActivePermanents(origTarget.getFilter(), playerId, game);
}
for (Permanent permanent : targets) {
if (target.canTarget(abilityControllerId, permanent.getId(), source, game)) {
@ -532,13 +547,14 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
return target.isChosen();
}
if (target.getOriginalTarget() instanceof TargetCreatureOrPlayer) {
List<Permanent> targets;
TargetCreatureOrPlayer t = ((TargetCreatureOrPlayer) target);
TargetCreatureOrPlayer origTarget = ((TargetCreatureOrPlayer) target);
if (outcome.isGood()) {
targets = threats(abilityControllerId, source.getSourceId(), ((FilterCreatureOrPlayer) t.getFilter()).getCreatureFilter(), game, target.getTargets());
targets = threats(abilityControllerId, source.getSourceId(), ((FilterCreatureOrPlayer) origTarget.getFilter()).getCreatureFilter(), game, target.getTargets());
} else {
targets = threats(randomOpponentId, source.getSourceId(), ((FilterCreatureOrPlayer) t.getFilter()).getCreatureFilter(), game, target.getTargets());
targets = threats(randomOpponentId, source.getSourceId(), ((FilterCreatureOrPlayer) origTarget.getFilter()).getCreatureFilter(), game, target.getTargets());
}
if (targets.isEmpty()) {
@ -552,11 +568,11 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
if (targets.isEmpty() && target.isRequired(source)) {
targets = game.getBattlefield().getActivePermanents(((FilterCreatureOrPlayer) t.getFilter()).getCreatureFilter(), playerId, game);
targets = game.getBattlefield().getActivePermanents(((FilterCreatureOrPlayer) origTarget.getFilter()).getCreatureFilter(), playerId, game);
}
for (Permanent permanent : targets) {
List<UUID> alreadyTargeted = target.getTargets();
if (t.canTarget(abilityControllerId, permanent.getId(), source, game)) {
if (target.canTarget(abilityControllerId, permanent.getId(), source, game)) {
if (alreadyTargeted != null && !alreadyTargeted.contains(permanent.getId())) {
return tryAddTarget(target, permanent.getId(), source, game);
}
@ -574,13 +590,14 @@ public class ComputerPlayer extends PlayerImpl implements Player {
//if (!target.isRequired())
return false;
}
if (target.getOriginalTarget() instanceof TargetAnyTarget) {
List<Permanent> targets;
TargetAnyTarget t = ((TargetAnyTarget) target);
TargetAnyTarget origTarget = ((TargetAnyTarget) target);
if (outcome.isGood()) {
targets = threats(abilityControllerId, source.getSourceId(), ((FilterCreaturePlayerOrPlaneswalker) t.getFilter()).getCreatureFilter(), game, target.getTargets());
targets = threats(abilityControllerId, source.getSourceId(), ((FilterCreaturePlayerOrPlaneswalker) origTarget.getFilter()).getCreatureFilter(), game, target.getTargets());
} else {
targets = threats(randomOpponentId, source.getSourceId(), ((FilterCreaturePlayerOrPlaneswalker) t.getFilter()).getCreatureFilter(), game, target.getTargets());
targets = threats(randomOpponentId, source.getSourceId(), ((FilterCreaturePlayerOrPlaneswalker) origTarget.getFilter()).getCreatureFilter(), game, target.getTargets());
}
if (targets.isEmpty()) {
@ -594,11 +611,11 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
if (targets.isEmpty() && target.isRequired(source)) {
targets = game.getBattlefield().getActivePermanents(((FilterCreaturePlayerOrPlaneswalker) t.getFilter()).getCreatureFilter(), playerId, game);
targets = game.getBattlefield().getActivePermanents(((FilterCreaturePlayerOrPlaneswalker) origTarget.getFilter()).getCreatureFilter(), playerId, game);
}
for (Permanent permanent : targets) {
List<UUID> alreadyTargeted = target.getTargets();
if (t.canTarget(abilityControllerId, permanent.getId(), source, game)) {
if (target.canTarget(abilityControllerId, permanent.getId(), source, game)) {
if (alreadyTargeted != null && !alreadyTargeted.contains(permanent.getId())) {
tryAddTarget(target, permanent.getId(), source, game);
}
@ -616,13 +633,14 @@ public class ComputerPlayer extends PlayerImpl implements Player {
//if (!target.isRequired())
return false;
}
if (target.getOriginalTarget() instanceof TargetPermanentOrPlayer) {
List<Permanent> targets;
TargetPermanentOrPlayer t = ((TargetPermanentOrPlayer) target);
TargetPermanentOrPlayer origTarget = ((TargetPermanentOrPlayer) target);
if (outcome.isGood()) {
targets = threats(abilityControllerId, source.getSourceId(), ((FilterPermanentOrPlayer) t.getFilter()).getPermanentFilter(), game, target.getTargets());
targets = threats(abilityControllerId, source.getSourceId(), ((FilterPermanentOrPlayer) origTarget.getFilter()).getPermanentFilter(), game, target.getTargets());
} else {
targets = threats(randomOpponentId, source.getSourceId(), ((FilterPermanentOrPlayer) t.getFilter()).getPermanentFilter(), game, target.getTargets());
targets = threats(randomOpponentId, source.getSourceId(), ((FilterPermanentOrPlayer) origTarget.getFilter()).getPermanentFilter(), game, target.getTargets());
}
if (targets.isEmpty()) {
@ -636,11 +654,11 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
if (targets.isEmpty() && target.isRequired(source)) {
targets = game.getBattlefield().getActivePermanents(((FilterPermanentOrPlayer) t.getFilter()).getPermanentFilter(), playerId, game);
targets = game.getBattlefield().getActivePermanents(((FilterPermanentOrPlayer) origTarget.getFilter()).getPermanentFilter(), playerId, game);
}
for (Permanent permanent : targets) {
List<UUID> alreadyTargeted = target.getTargets();
if (t.canTarget(abilityControllerId, permanent.getId(), source, game)) {
if (target.canTarget(abilityControllerId, permanent.getId(), source, game)) {
if (alreadyTargeted != null && !alreadyTargeted.contains(permanent.getId())) {
return tryAddTarget(target, permanent.getId(), source, game);
}
@ -650,11 +668,11 @@ public class ComputerPlayer extends PlayerImpl implements Player {
if (target.getOriginalTarget() instanceof TargetPlayerOrPlaneswalker) {
List<Permanent> targets;
TargetPlayerOrPlaneswalker t = ((TargetPlayerOrPlaneswalker) target);
TargetPlayerOrPlaneswalker origTarget = ((TargetPlayerOrPlaneswalker) target);
if (outcome.isGood()) {
targets = threats(abilityControllerId, source.getSourceId(), ((FilterPermanentOrPlayer) t.getFilter()).getPermanentFilter(), game, target.getTargets());
targets = threats(abilityControllerId, source.getSourceId(), ((FilterPermanentOrPlayer) target.getFilter()).getPermanentFilter(), game, target.getTargets());
} else {
targets = threats(randomOpponentId, source.getSourceId(), ((FilterPermanentOrPlayer) t.getFilter()).getPermanentFilter(), game, target.getTargets());
targets = threats(randomOpponentId, source.getSourceId(), ((FilterPermanentOrPlayer) target.getFilter()).getPermanentFilter(), game, target.getTargets());
}
if (targets.isEmpty()) {
@ -668,11 +686,11 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
if (targets.isEmpty() && target.isRequired(source)) {
targets = game.getBattlefield().getActivePermanents(((TargetPlayerOrPlaneswalker) t.getFilter()).getFilterPermanent(), playerId, game);
targets = game.getBattlefield().getActivePermanents(((TargetPlayerOrPlaneswalker) origTarget.getFilter()).getFilterPermanent(), playerId, game);
}
for (Permanent permanent : targets) {
List<UUID> alreadyTargeted = target.getTargets();
if (t.canTarget(abilityControllerId, permanent.getId(), source, game)) {
if (target.canTarget(abilityControllerId, permanent.getId(), source, game)) {
if (alreadyTargeted != null && !alreadyTargeted.contains(permanent.getId())) {
return tryAddTarget(target, permanent.getId(), source, game);
}
@ -703,6 +721,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
//if (!target.isRequired())
return false;
}
if (target.getOriginalTarget() instanceof TargetCardInLibrary) {
List<Card> cards = new ArrayList<>(game.getPlayer(abilityControllerId).getLibrary().getCards(game));
Card card = pickTarget(cards, outcome, target, source, game);
@ -711,6 +730,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
return false;
}
if (target.getOriginalTarget() instanceof TargetCardInYourGraveyard) {
List<Card> cards = new ArrayList<>(game.getPlayer(abilityControllerId).getGraveyard().getCards((FilterCard) target.getFilter(), game));
while (!target.isChosen() && !cards.isEmpty()) {
@ -722,6 +742,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
return target.isChosen();
}
if (target.getOriginalTarget() instanceof TargetSpell) {
if (!game.getStack().isEmpty()) {
for (StackObject o : game.getStack()) {
@ -732,17 +753,19 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
return false;
}
if (target.getOriginalTarget() instanceof TargetSpellOrPermanent) {
// TODO: Also check if a spell should be selected
TargetSpellOrPermanent origTarget = (TargetSpellOrPermanent) target.getOriginalTarget();
List<Permanent> targets;
boolean outcomeTargets = true;
if (outcome.isGood()) {
targets = threats(abilityControllerId, source == null ? null : source.getSourceId(), ((TargetSpellOrPermanent) target).getPermanentFilter(), game, target.getTargets());
targets = threats(abilityControllerId, source == null ? null : source.getSourceId(), origTarget.getPermanentFilter(), game, target.getTargets());
} else {
targets = threats(randomOpponentId, source == null ? null : source.getSourceId(), ((TargetSpellOrPermanent) target).getPermanentFilter(), game, target.getTargets());
targets = threats(randomOpponentId, source == null ? null : source.getSourceId(), origTarget.getPermanentFilter(), game, target.getTargets());
}
if (targets.isEmpty() && target.isRequired(source)) {
targets = threats(null, source == null ? null : source.getSourceId(), ((TargetSpellOrPermanent) target).getPermanentFilter(), game, target.getTargets());
targets = threats(null, source == null ? null : source.getSourceId(), origTarget.getPermanentFilter(), game, target.getTargets());
Collections.reverse(targets);
outcomeTargets = false;
}
@ -765,6 +788,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
return false;
}
if (target.getOriginalTarget() instanceof TargetCardInOpponentsGraveyard) {
List<Card> cards = new ArrayList<>();
for (UUID uuid : game.getOpponents(abilityControllerId)) {
@ -780,6 +804,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
//if (!target.isRequired())
return false;
}
if (target.getOriginalTarget() instanceof TargetDefender) {
// TODO: Improve, now planeswalker is always chosen if it exits
List<Permanent> targets;
@ -834,6 +859,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
return target.isChosen();
}
if (target.getOriginalTarget() instanceof TargetActivatedAbility) {
List<StackObject> stackObjects = new ArrayList<>();
for (UUID uuid : target.possibleTargets(source.getSourceId(), source.getControllerId(), game)) {
@ -924,6 +950,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
return false;
}
if (target.getOriginalTarget() instanceof TargetCreatureOrPlaneswalkerAmount) {
List<Permanent> targets;
if (outcome.isGood()) {
@ -965,6 +992,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
}
}
log.warn("No proper AI target handling: " + target.getClass().getName());
return false;
}

View file

@ -44,7 +44,7 @@ public final class AjaniTheGreathearted extends CardImpl {
this.addAbility(new SimpleStaticAbility(new GainAbilityControlledEffect(
VigilanceAbility.getInstance(),
Duration.WhileOnBattlefield,
StaticFilters.FILTER_CONTROLLED_CREATURES
StaticFilters.FILTER_PERMANENT_CREATURES
)));
// +1: You gain 3 life.

View file

@ -30,11 +30,11 @@ public final class AngrathCaptainOfChaos extends CardImpl {
// Creatures you control have menace.
this.addAbility(new SimpleStaticAbility(new GainAbilityControlledEffect(
new MenaceAbility(), Duration.WhileOnBattlefield,
new MenaceAbility(false), Duration.WhileOnBattlefield,
StaticFilters.FILTER_PERMANENT_CREATURES
)));
// -2: Amass 2.
// -2: Amass 2. (Put two +1/+1 counters on an Army you control. If you dont control one, create a 0/0 black Zombie Army creature token first.)
this.addAbility(new LoyaltyAbility(new AmassEffect(2), -2));
}

View file

@ -0,0 +1,45 @@
package mage.cards.a;
import mage.MageInt;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.common.PutCardFromHandOntoBattlefieldEffect;
import mage.abilities.keyword.ReachAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.filter.StaticFilters;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class ArborealGrazer extends CardImpl {
public ArborealGrazer(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}");
this.subtype.add(SubType.BEAST);
this.power = new MageInt(0);
this.toughness = new MageInt(3);
// Reach
this.addAbility(ReachAbility.getInstance());
// When Arboreal Grazer enters the battlefield, you may put a land card from your hand onto the battlefield tapped.
this.addAbility(new EntersBattlefieldTriggeredAbility(new PutCardFromHandOntoBattlefieldEffect(
StaticFilters.FILTER_CARD_LAND_A, false, true
), false));
}
private ArborealGrazer(final ArborealGrazer card) {
super(card);
}
@Override
public ArborealGrazer copy() {
return new ArborealGrazer(this);
}
}

View file

@ -0,0 +1,43 @@
package mage.cards.a;
import mage.MageInt;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.keyword.AmassEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class AvenEternal extends CardImpl {
public AvenEternal(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}");
this.subtype.add(SubType.ZOMBIE);
this.subtype.add(SubType.BIRD);
this.subtype.add(SubType.WARRIOR);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// Flying
this.addAbility(FlyingAbility.getInstance());
// When Aven Eternal enters the battlefield, amass 1.
this.addAbility(new EntersBattlefieldTriggeredAbility(new AmassEffect(1)));
}
private AvenEternal(final AvenEternal card) {
super(card);
}
@Override
public AvenEternal copy() {
return new AvenEternal(this);
}
}

View file

@ -0,0 +1,41 @@
package mage.cards.b;
import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
import mage.abilities.keyword.FirstStrikeAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.counters.CounterType;
import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class BattlefieldPromotion extends CardImpl {
public BattlefieldPromotion(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}");
// Put a +1/+1 counter on target creature. That creature gains first strike until end of turn. You gain 2 life.
this.getSpellAbility().addEffect(new AddCountersTargetEffect(CounterType.P1P1.createInstance()));
this.getSpellAbility().addEffect(new GainAbilityTargetEffect(
FirstStrikeAbility.getInstance(), Duration.EndOfTurn
).setText("That creature gains first strike until end of turn."));
this.getSpellAbility().addEffect(new GainLifeEffect(2));
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
}
private BattlefieldPromotion(final BattlefieldPromotion card) {
super(card);
}
@Override
public BattlefieldPromotion copy() {
return new BattlefieldPromotion(this);
}
}

View file

@ -0,0 +1,36 @@
package mage.cards.b;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.abilities.effects.keyword.AmassEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class BleedingEdge extends CardImpl {
public BleedingEdge(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{B}{B}");
// Up to one target creature gets -2/-2 until end of turn. Amass 2.
this.getSpellAbility().addEffect(new BoostTargetEffect(-2, -2, Duration.EndOfTurn));
this.getSpellAbility().addTarget(new TargetCreaturePermanent(0, 1));
this.getSpellAbility().addEffect(new AmassEffect(2));
}
private BleedingEdge(final BleedingEdge card) {
super(card);
}
@Override
public BleedingEdge copy() {
return new BleedingEdge(this);
}
}
// It's nanotech, you like it?

View file

@ -23,7 +23,7 @@ public final class BloomHulk extends CardImpl {
this.power = new MageInt(4);
this.toughness = new MageInt(4);
// When Bloom Hulk enters the battlefield, proliferate.
// When Bloom Hulk enters the battlefield, proliferate. (Choose any number of permanents and/or players, then give each another counter of each kind already there.)
this.addAbility(new EntersBattlefieldTriggeredAbility(new ProliferateEffect()));
}

View file

@ -0,0 +1,36 @@
package mage.cards.c;
import mage.abilities.effects.common.ReturnToHandTargetEffect;
import mage.abilities.effects.keyword.AmassEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.target.common.TargetNonlandPermanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class CallousDismissal extends CardImpl {
public CallousDismissal(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{U}");
// Return target nonland permanent to its owner's hand.
this.getSpellAbility().addEffect(new ReturnToHandTargetEffect());
this.getSpellAbility().addTarget(new TargetNonlandPermanent());
// Amass 1.
this.getSpellAbility().addEffect(new AmassEffect(1).concatBy("<br>"));
}
private CallousDismissal(final CallousDismissal card) {
super(card);
}
@Override
public CallousDismissal copy() {
return new CallousDismissal(this);
}
}

View file

@ -0,0 +1,37 @@
package mage.cards.c;
import mage.MageInt;
import mage.abilities.keyword.LifelinkAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class CharityExtractor extends CardImpl {
public CharityExtractor(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.KNIGHT);
this.power = new MageInt(1);
this.toughness = new MageInt(5);
// Lifelink
this.addAbility(LifelinkAbility.getInstance());
}
private CharityExtractor(final CharityExtractor card) {
super(card);
}
@Override
public CharityExtractor copy() {
return new CharityExtractor(this);
}
}

View file

@ -0,0 +1,56 @@
package mage.cards.c;
import mage.MageInt;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.common.counter.AddCountersAllEffect;
import mage.abilities.keyword.LifelinkAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.counters.CounterType;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.mageobject.NamePredicate;
import mage.filter.predicate.permanent.AnotherPredicate;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class CharmedStray extends CardImpl {
private static final FilterPermanent filter
= new FilterControlledCreaturePermanent("other creature you control named Charmed Stray");
static {
filter.add(new NamePredicate("Charmed Stray"));
filter.add(AnotherPredicate.instance);
}
public CharmedStray(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}");
this.subtype.add(SubType.CAT);
this.power = new MageInt(1);
this.toughness = new MageInt(1);
// Lifelink
this.addAbility(LifelinkAbility.getInstance());
// Whenever Charmed Stray enters the battlefield, put a +1/+1 counter on each other creature you control named Charmed Stray.
this.addAbility(new EntersBattlefieldTriggeredAbility(
new AddCountersAllEffect(CounterType.P1P1.createInstance(), filter)
));
}
private CharmedStray(final CharmedStray card) {
super(card);
}
@Override
public CharmedStray copy() {
return new CharmedStray(this);
}
}

View file

@ -1,4 +1,3 @@
package mage.cards.c;
import mage.abilities.Ability;
@ -36,9 +35,9 @@ public final class ContagionEngine extends CardImpl {
this.addAbility(ability);
// {4}, {T}: Proliferate, then proliferate again. (You choose any number of permanents and/or players with counters on them, then give each another counter of a kind already there. Then do it again.)
ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ProliferateEffect().setText("proliferate,"), new GenericManaCost(4));
ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ProliferateEffect("", false), new GenericManaCost(4));
ability.addCost(new TapSourceCost());
ability.addEffect(new ProliferateEffect().setText("then proliferate again <i>(Choose any number of permanents and/or players, then give each another counter of each kind already there. Then do it again.)</i>"));
ability.addEffect(new ProliferateEffect(" again", true).concatBy(", then"));
this.addAbility(ability);
}

View file

@ -1,23 +1,22 @@
package mage.cards.c;
import java.util.UUID;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.counter.ProliferateEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.abilities.effects.common.counter.ProliferateEffect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import java.util.UUID;
/**
*
* @author antoni-g
*/
public final class ContentiousPlan extends CardImpl {
public ContentiousPlan(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{U}");
// Proliferate.
// Proliferate. (Choose any number of permanents and/or players, then give each another counter of each kind already there.)
this.getSpellAbility().addEffect(new ProliferateEffect());
// Draw a card.
this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1));

View file

@ -1,8 +1,5 @@
package mage.cards.c;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.DiesTriggeredAbility;
import mage.abilities.effects.common.counter.ProliferateEffect;
@ -12,22 +9,27 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import java.util.UUID;
/**
*
* @author Loki
*/
public final class CoreProwler extends CardImpl {
public CoreProwler (UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{4}");
public CoreProwler(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{4}");
this.subtype.add(SubType.HORROR);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// Infect (This creature deals damage to creatures in the form of -1/-1 counters and to players in the form of poison counters.)
this.addAbility(InfectAbility.getInstance());
// When Core Prowler dies, proliferate. (You choose any number of permanents and/or players with counters on them, then give each another counter of a kind already there.)
this.addAbility(new DiesTriggeredAbility(new ProliferateEffect()));
}
public CoreProwler (final CoreProwler card) {
public CoreProwler(final CoreProwler card) {
super(card);
}

View file

@ -18,7 +18,7 @@ public final class CourageInCrisis extends CardImpl {
public CourageInCrisis(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{G}");
// Put a +1/+1 counter on target creature, then proliferate.
// Put a +1/+1 counter on target creature, then proliferate. (Choose any number of permanents and/or players, then give each another counter of each kind already there.)
this.getSpellAbility().addEffect(new AddCountersTargetEffect(CounterType.P1P1.createInstance()));
this.getSpellAbility().addEffect(new ProliferateEffect().concatBy(", then"));
this.getSpellAbility().addTarget(new TargetCreaturePermanent());

View file

@ -0,0 +1,42 @@
package mage.cards.d;
import mage.abilities.effects.common.ExileTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.ComparisonType;
import mage.filter.FilterPermanent;
import mage.filter.predicate.mageobject.ConvertedManaCostPredicate;
import mage.target.TargetPermanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class Despark extends CardImpl {
private static final FilterPermanent filter
= new FilterPermanent("permanent with converted mana cost 4 or greater");
static {
filter.add(new ConvertedManaCostPredicate(ComparisonType.MORE_THAN, 3));
}
public Despark(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{W}{B}");
// Exile target permanent with converted mana cost 4 or greater.
this.getSpellAbility().addEffect(new ExileTargetEffect());
this.getSpellAbility().addTarget(new TargetPermanent(filter));
}
private Despark(final Despark card) {
super(card);
}
@Override
public Despark copy() {
return new Despark(this);
}
}

View file

@ -0,0 +1,32 @@
package mage.cards.d;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.target.common.TargetAttackingOrBlockingCreature;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class DivineArrow extends CardImpl {
public DivineArrow(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}");
// Divine Arrow deals 4 damage to target attacking or blocking creature.
this.getSpellAbility().addEffect(new DamageTargetEffect(4));
this.getSpellAbility().addTarget(new TargetAttackingOrBlockingCreature());
}
private DivineArrow(final DivineArrow card) {
super(card);
}
@Override
public DivineArrow copy() {
return new DivineArrow(this);
}
}

View file

@ -0,0 +1,66 @@
package mage.cards.d;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.SacrificeTargetCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.abilities.keyword.MenaceAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.counters.CounterType;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.CardTypePredicate;
import mage.filter.predicate.permanent.AnotherPredicate;
import mage.target.common.TargetControlledPermanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class Dreadmalkin extends CardImpl {
private static final FilterControlledPermanent filter
= new FilterControlledPermanent("another creature or planeswalker");
static {
filter.add(Predicates.or(
new CardTypePredicate(CardType.PLANESWALKER),
new CardTypePredicate(CardType.CREATURE)
));
filter.add(AnotherPredicate.instance);
}
public Dreadmalkin(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B}");
this.subtype.add(SubType.ZOMBIE);
this.subtype.add(SubType.CAT);
this.power = new MageInt(1);
this.toughness = new MageInt(1);
// Menace
this.addAbility(new MenaceAbility());
// {2}{B}, Sacrifice another creature or planeswalker: Put two +1/+1 counters on Dreadmalkin.
Ability ability = new SimpleActivatedAbility(
new AddCountersSourceEffect(CounterType.P1P1.createInstance(2)), new ManaCostsImpl("{2}{B}")
);
ability.addCost(new SacrificeTargetCost(new TargetControlledPermanent(filter)));
this.addAbility(ability);
}
private Dreadmalkin(final Dreadmalkin card) {
super(card);
}
@Override
public Dreadmalkin copy() {
return new Dreadmalkin(this);
}
}

View file

@ -0,0 +1,51 @@
package mage.cards.d;
import mage.MageInt;
import mage.abilities.common.SimpleEvasionAbility;
import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.ComparisonType;
import mage.constants.Duration;
import mage.constants.SubType;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.mageobject.PowerPredicate;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class DuskmantleOperative extends CardImpl {
private static final FilterCreaturePermanent filter
= new FilterCreaturePermanent("creatures with power 4 or greater");
static {
filter.add(new PowerPredicate(ComparisonType.MORE_THAN, 3));
}
public DuskmantleOperative(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.ROGUE);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// Duskmantle Operative can't be blocked by creatures with power 4 or greater.
this.addAbility(new SimpleEvasionAbility(new CantBeBlockedByCreaturesSourceEffect(
filter, Duration.WhileOnBattlefield
)));
}
private DuskmantleOperative(final DuskmantleOperative card) {
super(card);
}
@Override
public DuskmantleOperative copy() {
return new DuskmantleOperative(this);
}
}

View file

@ -0,0 +1,46 @@
package mage.cards.e;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class EliteGuardmage extends CardImpl {
public EliteGuardmage(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}{U}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.WIZARD);
this.power = new MageInt(2);
this.toughness = new MageInt(3);
// Flying
this.addAbility(FlyingAbility.getInstance());
// When Elite Guardmage enters the battlefield, you can 3 life and draw a card.
Ability ability = new EntersBattlefieldTriggeredAbility(new GainLifeEffect(3));
ability.addEffect(new DrawCardSourceControllerEffect(1).concatBy("and"));
this.addAbility(ability);
}
private EliteGuardmage(final EliteGuardmage card) {
super(card);
}
@Override
public EliteGuardmage copy() {
return new EliteGuardmage(this);
}
}

View file

@ -0,0 +1,36 @@
package mage.cards.e;
import mage.MageInt;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class EnforcerGriffin extends CardImpl {
public EnforcerGriffin(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{W}");
this.subtype.add(SubType.GRIFFIN);
this.power = new MageInt(3);
this.toughness = new MageInt(4);
// Flying
this.addAbility(FlyingAbility.getInstance());
}
private EnforcerGriffin(final EnforcerGriffin card) {
super(card);
}
@Override
public EnforcerGriffin copy() {
return new EnforcerGriffin(this);
}
}

View file

@ -29,7 +29,7 @@ public final class EvolutionSage extends CardImpl {
this.power = new MageInt(3);
this.toughness = new MageInt(2);
// Whenever a land enters the battlefield under your control, proliferate.
// Whenever a land enters the battlefield under your control, proliferate. (Choose any number of permanents and/or players, then give each another counter of each kind already there.)
this.addAbility(new EntersBattlefieldAllTriggeredAbility(
Zone.BATTLEFIELD, new ProliferateEffect(), filter,
false, null, true

View file

@ -0,0 +1,91 @@
package mage.cards.f;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.ComparisonType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.FilterPermanent;
import mage.filter.StaticFilters;
import mage.filter.predicate.mageobject.ToughnessPredicate;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetPermanent;
import mage.target.targetadjustment.TargetAdjuster;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class FinaleOfEternity extends CardImpl {
public FinaleOfEternity(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{B}{B}");
// Destroy up to three target creatures with toughness X or less. If X is 10 or more, return all creature cards from your graveyard to the battlefield.
this.getSpellAbility().addEffect(new FinaleOfEternityEffect());
this.getSpellAbility().setTargetAdjuster(FinaleOfEternityAdjuster.instance);
}
private FinaleOfEternity(final FinaleOfEternity card) {
super(card);
}
@Override
public FinaleOfEternity copy() {
return new FinaleOfEternity(this);
}
}
enum FinaleOfEternityAdjuster implements TargetAdjuster {
instance;
@Override
public void adjustTargets(Ability ability, Game game) {
int xValue = ability.getManaCostsToPay().getX();
FilterPermanent filter = new FilterPermanent("creatures with toughness " + xValue + " or less");
filter.add(new ToughnessPredicate(ComparisonType.FEWER_THAN, xValue + 1));
ability.getTargets().clear();
ability.addTarget(new TargetPermanent(0, 3, filter, false));
}
}
class FinaleOfEternityEffect extends OneShotEffect {
FinaleOfEternityEffect() {
super(Outcome.Benefit);
staticText = "Destroy up to three target creatures with toughness X or less. " +
"If X is 10 or more, return all creature cards from your graveyard to the battlefield.";
}
private FinaleOfEternityEffect(final FinaleOfEternityEffect effect) {
super(effect);
}
@Override
public FinaleOfEternityEffect copy() {
return new FinaleOfEternityEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
new DestroyTargetEffect(false, true).apply(game, source);
if (source.getManaCostsToPay().getX() < 10) {
return true;
}
Player player = game.getPlayer(source.getControllerId());
if (player == null) {
return false;
}
return player.moveCards(
player.getGraveyard().getCards(
StaticFilters.FILTER_CARD_CREATURE, game
), Zone.BATTLEFIELD, source, game
);
}
}

View file

@ -24,7 +24,7 @@ public final class FluxChanneler extends CardImpl {
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// Whenever you cast a noncreature spell, proliferate.
// Whenever you cast a noncreature spell, proliferate. (Choose any number of permanents and/or players, then give each another counter of each kind already there.)
this.addAbility(new SpellCastControllerTriggeredAbility(
new ProliferateEffect(), StaticFilters.FILTER_SPELL_NON_CREATURE, false
));

View file

@ -1,8 +1,5 @@
package mage.cards.f;
import java.util.UUID;
import mage.abilities.effects.common.CounterTargetEffect;
import mage.abilities.effects.common.counter.ProliferateEffect;
import mage.cards.CardImpl;
@ -10,21 +7,23 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.target.TargetSpell;
import java.util.UUID;
/**
*
* @author Loki
*/
public final class FuelForTheCause extends CardImpl {
public FuelForTheCause (UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{U}{U}");
public FuelForTheCause(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{U}{U}");
// Counter target spell, then proliferate. (You choose any number of permanents and/or players with counters on them, then give each another counter of a kind already there.)
this.getSpellAbility().addTarget(new TargetSpell());
this.getSpellAbility().addEffect(new CounterTargetEffect());
this.getSpellAbility().addEffect(new ProliferateEffect());
this.getSpellAbility().addEffect(new ProliferateEffect().concatBy(", then"));
}
public FuelForTheCause (final FuelForTheCause card) {
public FuelForTheCause(final FuelForTheCause card) {
super(card);
}

View file

@ -1,7 +1,5 @@
package mage.cards.f;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.ZoneChangeTriggeredAbility;
import mage.abilities.effects.Effect;
@ -23,14 +21,15 @@ import mage.target.TargetPermanent;
import mage.target.common.TargetCreaturePermanent;
import mage.target.targetpointer.FixedTarget;
import java.util.UUID;
/**
*
* @author L_J
*/
public final class FuneralMarch extends CardImpl {
public FuneralMarch(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{B}{B}");
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{B}{B}");
this.subtype.add(SubType.AURA);
// Enchant creature
@ -73,17 +72,19 @@ class FuneralMarchTriggeredAbility extends ZoneChangeTriggeredAbility {
public boolean checkTrigger(GameEvent event, Game game) {
Permanent enchantment = game.getPermanentOrLKIBattlefield(this.getSourceId());
if (enchantment != null && enchantment.getAttachedTo() != null && event.getTargetId().equals(enchantment.getAttachedTo())) {
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
if ((fromZone == null || zEvent.getFromZone() == fromZone) && (toZone == null || zEvent.getToZone() == toZone)) {
for (Effect effect : getEffects()) {
if (zEvent.getTarget() != null) {
Permanent attachedTo = (Permanent) game.getLastKnownInformation(enchantment.getAttachedTo(), Zone.BATTLEFIELD, enchantment.getAttachedToZoneChangeCounter());
if (attachedTo != null) {
effect.setTargetPointer(new FixedTarget(attachedTo.getControllerId()));
if (event.getType() == GameEvent.EventType.ZONE_CHANGE) {
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
if ((fromZone == null || zEvent.getFromZone() == fromZone) && (toZone == null || zEvent.getToZone() == toZone)) {
for (Effect effect : getEffects()) {
if (zEvent.getTarget() != null) {
Permanent attachedTo = (Permanent) game.getLastKnownInformation(enchantment.getAttachedTo(), Zone.BATTLEFIELD, enchantment.getAttachedToZoneChangeCounter());
if (attachedTo != null) {
effect.setTargetPointer(new FixedTarget(attachedTo.getControllerId()));
}
}
}
}
return true;
}
return true;
}
}
return false;

View file

@ -0,0 +1,166 @@
package mage.cards.g;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.common.MyTurnCondition;
import mage.abilities.decorator.ConditionalContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ExileTargetEffect;
import mage.abilities.effects.common.PreventAllDamageToSourceEffect;
import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect;
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
import mage.abilities.keyword.IndestructibleAbility;
import mage.abilities.keyword.LifelinkAbility;
import mage.abilities.keyword.VigilanceAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.choices.Choice;
import mage.choices.ChoiceImpl;
import mage.constants.*;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.permanent.AnotherPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.game.permanent.token.TokenImpl;
import mage.players.Player;
import mage.target.TargetPermanent;
import mage.target.common.TargetNonlandPermanent;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class GideonBlackblade extends CardImpl {
private static final FilterPermanent filter = new FilterControlledCreaturePermanent("another other creature you control");
static {
filter.add(AnotherPredicate.instance);
}
public GideonBlackblade(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{1}{W}{W}");
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.GIDEON);
this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(4));
// As long as it's your turn, Gideon Blackblade is a 4/4 Human Soldier creature with indestructible that's still a planeswalker.
this.addAbility(new SimpleStaticAbility(new ConditionalContinuousEffect(
new BecomesCreatureSourceEffect(
new GideonBlackbladeToken(), "planeswalker", Duration.WhileOnBattlefield
), MyTurnCondition.instance, "As long as it's your turn, " +
"{this} is a 4/4 Human Soldier creature with indestructible that's still a planeswalker."
)));
// Prevent all damage that would be dealt to Gideon Blackblade during your turn.
this.addAbility(new SimpleStaticAbility(new ConditionalContinuousEffect(
new PreventAllDamageToSourceEffect(Duration.WhileOnBattlefield),
MyTurnCondition.instance, "Prevent all damage that would be dealt to {this} during your turn."
)));
// +1: Up to one other target creature you control gains your choice of vigilance, lifelink, or indestructible until end of turn.
Ability ability = new LoyaltyAbility(new GideonBlackbladeEffect(), 1);
ability.addTarget(new TargetPermanent(0, 1, filter, false));
this.addAbility(ability);
// -6: Exile target nonland permanent.
ability = new LoyaltyAbility(new ExileTargetEffect(), -6);
ability.addTarget(new TargetNonlandPermanent());
this.addAbility(ability);
}
private GideonBlackblade(final GideonBlackblade card) {
super(card);
}
@Override
public GideonBlackblade copy() {
return new GideonBlackblade(this);
}
}
class GideonBlackbladeToken extends TokenImpl {
GideonBlackbladeToken() {
super("", "4/4 Human Soldier creature");
cardType.add(CardType.CREATURE);
subtype.add(SubType.HUMAN);
subtype.add(SubType.SOLDIER);
power = new MageInt(4);
toughness = new MageInt(4);
addAbility(IndestructibleAbility.getInstance());
}
private GideonBlackbladeToken(final GideonBlackbladeToken token) {
super(token);
}
@Override
public GideonBlackbladeToken copy() {
return new GideonBlackbladeToken(this);
}
}
class GideonBlackbladeEffect extends OneShotEffect {
private static final Set<String> choices = new HashSet();
static {
choices.add("Vigilance");
choices.add("Lifelink");
choices.add("Indestructible");
}
GideonBlackbladeEffect() {
super(Outcome.Benefit);
staticText = "Up to one other target creature you control gains your choice of " +
"vigilance, lifelink, or indestructible until end of turn.";
}
private GideonBlackbladeEffect(final GideonBlackbladeEffect effect) {
super(effect);
}
@Override
public GideonBlackbladeEffect copy() {
return new GideonBlackbladeEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
Permanent permanent = game.getPermanent(source.getFirstTarget());
if (player == null || permanent == null) {
return false;
}
Choice choice = new ChoiceImpl(true);
choice.setMessage("Choose an ability to give to " + permanent.getLogName());
choice.setChoices(choices);
if (!player.choose(outcome, choice, game)) {
return false;
}
Ability ability = null;
switch (choice.getChoice()) {
case "Vigilance":
ability = VigilanceAbility.getInstance();
break;
case "Lifelink":
ability = LifelinkAbility.getInstance();
break;
case "Indestructible":
ability = IndestructibleAbility.getInstance();
break;
}
if (ability != null) {
game.addEffect(new GainAbilityTargetEffect(ability, Duration.EndOfTurn), source);
}
return true;
}
}

View file

@ -0,0 +1,181 @@
package mage.cards.g;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.CardTypePredicate;
import mage.game.Game;
import mage.game.events.DamageEvent;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.Target;
import mage.target.TargetPermanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class GideonsSacrifice extends CardImpl {
public GideonsSacrifice(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{W}");
// Choose a creature or planeswalker you control. All damage that would be dealt this turn to you and permanents you control is dealt to the chosen permanent instead.
this.getSpellAbility().addEffect(new GideonsSacrificeEffect());
}
private GideonsSacrifice(final GideonsSacrifice card) {
super(card);
}
@Override
public GideonsSacrifice copy() {
return new GideonsSacrifice(this);
}
}
class GideonsSacrificeEffect extends OneShotEffect {
private static final FilterPermanent filter
= new FilterControlledPermanent("creature or planeswalker you controls");
static {
filter.add(Predicates.or(
new CardTypePredicate(CardType.PLANESWALKER),
new CardTypePredicate(CardType.CREATURE)
));
}
GideonsSacrificeEffect() {
super(Outcome.Benefit);
staticText = "Choose a creature or planeswalker you control. " +
"All damage that would be dealt this turn to you " +
"and permanents you control is dealt to the chosen permanent instead.";
}
private GideonsSacrificeEffect(final GideonsSacrificeEffect effect) {
super(effect);
}
@Override
public GideonsSacrificeEffect copy() {
return new GideonsSacrificeEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player == null) {
return false;
}
Target target = new TargetPermanent(filter);
target.setNotTarget(true);
if (!player.choose(outcome, target, source.getSourceId(), game)) {
return false;
}
game.addEffect(new GideonsSacrificeEffectReplacementEffect(
new MageObjectReference(target.getFirstTarget(), game)
), source);
return true;
}
}
class GideonsSacrificeEffectReplacementEffect extends ReplacementEffectImpl {
private final MageObjectReference mor;
GideonsSacrificeEffectReplacementEffect(MageObjectReference mor) {
super(Duration.EndOfTurn, Outcome.RedirectDamage);
this.mor = mor;
}
private GideonsSacrificeEffectReplacementEffect(final GideonsSacrificeEffectReplacementEffect effect) {
super(effect);
this.mor = effect.mor;
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
switch (event.getType()) {
case DAMAGE_CREATURE:
case DAMAGE_PLAYER:
case DAMAGE_PLANESWALKER:
return true;
default:
return false;
}
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (event.getType() == GameEvent.EventType.DAMAGE_PLAYER
&& event.getPlayerId().equals(source.getControllerId())) {
return true;
}
if (event.getType() == GameEvent.EventType.DAMAGE_CREATURE
|| event.getType() == GameEvent.EventType.DAMAGE_PLANESWALKER) {
Permanent targetPermanent = game.getPermanent(event.getTargetId());
if (targetPermanent != null
&& targetPermanent.isControlledBy(source.getControllerId())) {
return true;
}
}
return false;
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
DamageEvent damageEvent = (DamageEvent) event;
Permanent permanent = mor.getPermanent(game);
if (permanent == null) {
return false;
}
// Name of old target
Permanent targetPermanent = game.getPermanent(event.getTargetId());
StringBuilder message = new StringBuilder();
message.append(permanent.getName()).append(": gets ");
message.append(damageEvent.getAmount()).append(" damage redirected from ");
if (targetPermanent != null) {
message.append(targetPermanent.getName());
} else {
Player targetPlayer = game.getPlayer(event.getTargetId());
if (targetPlayer != null) {
message.append(targetPlayer.getLogName());
} else {
message.append("unknown");
}
}
game.informPlayers(message.toString());
// Redirect damage
permanent.damage(
damageEvent.getAmount(), damageEvent.getSourceId(), game,
damageEvent.isCombatDamage(), damageEvent.isPreventable(), event.getAppliedEffects()
);
return true;
}
@Override
public boolean apply(Game game, Ability source) {
return true;
}
@Override
public GideonsSacrificeEffectReplacementEffect copy() {
return new GideonsSacrificeEffectReplacementEffect(this);
}
}

View file

@ -34,6 +34,7 @@ public final class GideonsTriumph extends CardImpl {
// Target opponent sacrifices a creature that attacked or blocked this turn. If you control a Gideon planeswalker, that player sacrifices two of those creatures instead.
this.getSpellAbility().addEffect(new GideonsTriumphEffect());
this.getSpellAbility().addTarget(new TargetOpponent());
this.getSpellAbility().addWatcher(new GideonsTriumphWatcher());
}
private GideonsTriumph(final GideonsTriumph card) {

View file

@ -0,0 +1,54 @@
package mage.cards.g;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.BlocksOrBecomesBlockedTriggeredAbility;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.effects.common.continuous.BoostEnchantedEffect;
import mage.abilities.keyword.EnchantAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
import mage.constants.Outcome;
import mage.target.TargetPermanent;
import mage.target.common.TargetCreaturePermanent;
/**
*
* @author Ketsuban
*/
public final class GiftOfTheWoods extends CardImpl {
public GiftOfTheWoods(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[] { CardType.ENCHANTMENT }, "{G}");
this.subtype.add(SubType.AURA);
// Enchant creature
TargetPermanent auraTarget = new TargetCreaturePermanent();
this.getSpellAbility().addEffect(new AttachEffect(Outcome.Benefit));
this.getSpellAbility().addTarget(auraTarget);
Ability ability = new EnchantAbility(auraTarget.getTargetName());
this.addAbility(ability);
// Whenever enchanted creature blocks or becomes blocked, it gets +0/+3 until
// end of turn and you gain 1 life.
Ability ability2 = new BlocksOrBecomesBlockedTriggeredAbility(
new BoostEnchantedEffect(0, 3, Duration.EndOfTurn), false);
ability2.addEffect(new GainLifeEffect(1).concatBy("and"));
this.addAbility(ability2);
}
public GiftOfTheWoods(final GiftOfTheWoods card) {
super(card);
}
@Override
public GiftOfTheWoods copy() {
return new GiftOfTheWoods(this);
}
}

View file

@ -0,0 +1,53 @@
package mage.cards.g;
import mage.MageInt;
import mage.abilities.common.GodEternalDiesTriggeredAbility;
import mage.abilities.common.SpellCastControllerTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.keyword.DoubleStrikeAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.filter.StaticFilters;
import mage.game.permanent.token.GodEternalOketraToken;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class GodEternalOketra extends CardImpl {
public GodEternalOketra(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}{W}");
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.ZOMBIE);
this.subtype.add(SubType.GOD);
this.power = new MageInt(3);
this.toughness = new MageInt(6);
// Double strike
this.addAbility(DoubleStrikeAbility.getInstance());
// Whenever you cast a creature spell, create a 4/4 black Zombie Warrior creature token with vigilance.
this.addAbility(new SpellCastControllerTriggeredAbility(
new CreateTokenEffect(new GodEternalOketraToken()),
StaticFilters.FILTER_SPELL_A_CREATURE, false
));
// When God-Eternal Oketra dies or is put into exile from the battlefield, you may put it into its owner's library third from the top.
this.addAbility(new GodEternalDiesTriggeredAbility());
}
private GodEternalOketra(final GodEternalOketra card) {
super(card);
}
@Override
public GodEternalOketra copy() {
return new GodEternalOketra(this);
}
}

View file

@ -87,8 +87,7 @@ class GodEternalRhonasEffect extends OneShotEffect {
}
ContinuousEffect effect = new BoostTargetEffect(
permanent.getPower().getValue(),
permanent.getToughness().getValue(),
Duration.EndOfTurn
0, Duration.EndOfTurn
);
effect.setTargetPointer(new FixedTarget(permanent, game));
game.addEffect(effect, source);

View file

@ -26,7 +26,7 @@ public final class GratefulApparition extends CardImpl {
// Flying
this.addAbility(FlyingAbility.getInstance());
// Whenever Grateful Apparition deals combat damage to a player or planeswalker, proliferate.
// Whenever Grateful Apparition deals combat damage to a player or planeswalker, proliferate. (Choose any number of permanents and/or players, then give each another counter of each kind already there.)
this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(
new ProliferateEffect(), false
).setOrPlaneswalker(true));

View file

@ -1,4 +1,3 @@
package mage.cards.g;
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
@ -19,9 +18,10 @@ public final class GrimAffliction extends CardImpl {
public GrimAffliction(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{B}");
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
// Put a -1/-1 counter on target creature, then proliferate. (You choose any number of permanents and/or players with counters on them, then give each another counter of a kind already there.)
this.getSpellAbility().addEffect(new AddCountersTargetEffect(CounterType.M1M1.createInstance()));
this.getSpellAbility().addEffect(new ProliferateEffect().concatBy(", then"));
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
}
public GrimAffliction(final GrimAffliction card) {

View file

@ -0,0 +1,116 @@
package mage.cards.g;
import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.costs.common.SacrificeSourceCost;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.ManaEffect;
import mage.abilities.mana.SimpleManaAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.choices.ChoiceColor;
import mage.constants.CardType;
import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class GuildGlobe extends CardImpl {
public GuildGlobe(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}");
// When Guild Globe enters the battlefield, draw a card.
this.addAbility(new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1)));
// {2}, {T}, Sacrifice Guild Globe: Add two mana of different colors.
Ability ability = new SimpleManaAbility(
Zone.BATTLEFIELD, new GuildGlobeManaEffect(), new GenericManaCost(2)
);
ability.addCost(new TapSourceCost());
ability.addCost(new SacrificeSourceCost());
this.addAbility(ability);
}
private GuildGlobe(final GuildGlobe card) {
super(card);
}
@Override
public GuildGlobe copy() {
return new GuildGlobe(this);
}
}
class GuildGlobeManaEffect extends ManaEffect {
GuildGlobeManaEffect() {
super();
staticText = "Add two mana of different colors.";
}
private GuildGlobeManaEffect(final GuildGlobeManaEffect effect) {
super(effect);
}
@Override
public Mana produceMana(boolean netMana, Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player == null) {
return null;
}
ChoiceColor color1 = new ChoiceColor(true, "Choose color 1");
if (!player.choose(outcome, color1, game) || color1.getColor() == null) {
return null;
}
ChoiceColor color2 = new ChoiceColor(true, "Choose color 2");
color2.removeColorFromChoices(color1.getChoice());
if (!player.choose(outcome, color2, game) || color2.getColor() == null) {
return null;
}
if (color1.getColor().equals(color2.getColor())) {
game.informPlayers("Player " + player.getName() + " is cheating with mana choices.");
return null;
}
Mana mana = new Mana();
mana.add(color1.getMana(1));
mana.add(color2.getMana(1));
return mana;
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player != null) {
checkToFirePossibleEvents(getMana(game, source), game, source);
player.getManaPool().addMana(getMana(game, source), game, source);
return true;
}
return false;
}
@Override
public List<Mana> getNetMana(Game game, Ability source) {
ArrayList<Mana> netMana = new ArrayList<>();
netMana.add(new Mana(0, 0, 0, 0, 0, 0, 2, 0));
return netMana;
}
@Override
public GuildGlobeManaEffect copy() {
return new GuildGlobeManaEffect(this);
}
}

View file

@ -27,7 +27,7 @@ public final class GuildpactInformant extends CardImpl {
// Flying
this.addAbility(FlyingAbility.getInstance());
// Whenever Guildpact Informant deals combat damage to a player or planeswalker, proliferate.
// Whenever Guildpact Informant deals combat damage to a player or planeswalker, proliferate. (Choose any number of permanents and/or players, then give each another counter of each kind already there.)
this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(
new ProliferateEffect(), false
).setOrPlaneswalker(true));

View file

@ -0,0 +1,65 @@
package mage.cards.h;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.game.Game;
import mage.players.Player;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class HeartwarmingRedemption extends CardImpl {
public HeartwarmingRedemption(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{R}{W}");
// Discard all the cards in your hand, then draw that many cards plus one. You gain life equal to the number of cards in your hand.
this.getSpellAbility().addEffect(new HeartwarmingRedemptionEffect());
}
private HeartwarmingRedemption(final HeartwarmingRedemption card) {
super(card);
}
@Override
public HeartwarmingRedemption copy() {
return new HeartwarmingRedemption(this);
}
}
class HeartwarmingRedemptionEffect extends OneShotEffect {
HeartwarmingRedemptionEffect() {
super(Outcome.Benefit);
staticText = "Discard all the cards in your hand, then draw that many cards plus one. " +
"You gain life equal to the number of cards in your hand.";
}
private HeartwarmingRedemptionEffect(final HeartwarmingRedemptionEffect effect) {
super(effect);
}
@Override
public HeartwarmingRedemptionEffect copy() {
return new HeartwarmingRedemptionEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player == null) {
return false;
}
int discarded = player.discard(player.getHand().size(), false, source, game).size();
player.drawCards(discarded + 1, game);
player.gainLife(player.getHand().size(), game, source);
return true;
}
}
// Good night, sweet prince :(

View file

@ -26,7 +26,7 @@ public final class HuatlisRaptor extends CardImpl {
// Vigilance
this.addAbility(VigilanceAbility.getInstance());
// When Huatli's Raptor enters the battlefield, proliferate.
// When Huatli's Raptor enters the battlefield, proliferate. (Choose any number of permanents and/or players, then give each another counter of each kind already there.)
this.addAbility(new EntersBattlefieldTriggeredAbility(new ProliferateEffect()));
}

View file

@ -1,28 +1,26 @@
package mage.cards.i;
import java.util.UUID;
import mage.abilities.common.SpellCastControllerTriggeredAbility;
import mage.abilities.effects.common.counter.ProliferateEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import java.util.UUID;
/**
*
* @author Loki, North
*/
public final class InexorableTide extends CardImpl {
public InexorableTide (UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{3}{U}{U}");
public InexorableTide(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{U}{U}");
// Whenever you cast a spell, proliferate. (You choose any number of permanents and/or players with counters on them, then give each another counter of a kind already there.)
this.addAbility(new SpellCastControllerTriggeredAbility(new ProliferateEffect(), false));
}
public InexorableTide (final InexorableTide card) {
public InexorableTide(final InexorableTide card) {
super(card);
}

View file

@ -0,0 +1,32 @@
package mage.cards.i;
import mage.MageInt;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class IroncladKrovod extends CardImpl {
public IroncladKrovod(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}");
this.subtype.add(SubType.BEAST);
this.power = new MageInt(2);
this.toughness = new MageInt(5);
}
private IroncladKrovod(final IroncladKrovod card) {
super(card);
}
@Override
public IroncladKrovod copy() {
return new IroncladKrovod(this);
}
}

View file

@ -23,7 +23,7 @@ public final class KarnsBastion extends CardImpl {
// {T}: Add {C}.
this.addAbility(new ColorlessManaAbility());
// {4}, {T}: Proliferate.
// {4}, {T}: Proliferate. (Choose any number of permanents and/or players, then give each another counter of each kind already there.)
Ability ability = new SimpleActivatedAbility(new ProliferateEffect(), new GenericManaCost(4));
ability.addCost(new TapSourceCost());
this.addAbility(ability);

View file

@ -22,7 +22,7 @@ public final class KiorasDambreaker extends CardImpl {
this.power = new MageInt(5);
this.toughness = new MageInt(6);
// When Kiora's Dreammaker enters the battlefield, proliferate.
// When Kiora's Dreammaker enters the battlefield, proliferate. (Choose any number of permanents and/or players, then give each a counter of each kind already there.)
this.addAbility(new EntersBattlefieldTriggeredAbility(new ProliferateEffect()));
}

View file

@ -0,0 +1,64 @@
package mage.cards.k;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.continuous.BoostEnchantedEffect;
import mage.abilities.keyword.EnchantAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.permanent.AnotherEnchantedPredicate;
import mage.target.TargetPermanent;
import mage.target.common.TargetCreaturePermanent;
/**
*
* @author Ketsuban
*/
public final class KjeldoranPride extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature other than enchanted creature");
static {
filter.add(new AnotherEnchantedPredicate());
}
public KjeldoranPride(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[] { CardType.ENCHANTMENT }, "{1}{W}");
this.subtype.add(SubType.AURA);
// Enchant creature
TargetPermanent auraTarget = new TargetCreaturePermanent();
this.getSpellAbility().addTarget(auraTarget);
this.getSpellAbility().addEffect(new AttachEffect(Outcome.Benefit));
Ability enchantAbility = new EnchantAbility(auraTarget.getTargetName());
this.addAbility(enchantAbility);
// Enchanted creature gets +1/+2.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEnchantedEffect(1, 2)));
// 2U: Attach Kjeldoran Pride to target creature other than enchanted creature.
Ability ability = new SimpleActivatedAbility(new AttachEffect(Outcome.Benefit), new ManaCostsImpl<>("{2}{U}"));
ability.addTarget(new TargetCreaturePermanent(filter));
this.addAbility(ability);
}
public KjeldoranPride(final KjeldoranPride card) {
super(card);
}
@Override
public KjeldoranPride copy() {
return new KjeldoranPride(this);
}
}

View file

@ -0,0 +1,37 @@
package mage.cards.k;
import mage.MageInt;
import mage.abilities.keyword.DeathtouchAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class KraulStinger extends CardImpl {
public KraulStinger(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}");
this.subtype.add(SubType.INSECT);
this.subtype.add(SubType.ASSASSIN);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// Deathtouch
this.addAbility(DeathtouchAbility.getInstance());
}
private KraulStinger(final KraulStinger card) {
super(card);
}
@Override
public KraulStinger copy() {
return new KraulStinger(this);
}
}

View file

@ -0,0 +1,67 @@
package mage.cards.k;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.LimitedTimesPerTurnActivatedAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.SacrificeSourceCost;
import mage.abilities.costs.common.SacrificeTargetCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.FilterCard;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.mageobject.NamePredicate;
import mage.target.common.TargetCardInLibrary;
import mage.target.common.TargetControlledCreaturePermanent;
import java.util.UUID;
/**
*
* @author jmharmon
*/
public final class KyscuDrake extends CardImpl {
private static final FilterCard filter = new FilterCard("card named Viashivan Dragon");
private static final FilterControlledCreaturePermanent filterSpitting = new FilterControlledCreaturePermanent("creature named Spitting Drake");
static {
filter.add(new NamePredicate("Viashivan Dragon"));
filterSpitting.add(new NamePredicate("Spitting Drake"));
}
public KyscuDrake(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}");
this.subtype.add(SubType.DRAKE);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// Flying
this.addAbility(FlyingAbility.getInstance());
// {G}: Kyscu Drake gets +0/+1 until end of turn. Activate this ability only once each turn.
this.addAbility(new LimitedTimesPerTurnActivatedAbility(Zone.BATTLEFIELD, new BoostSourceEffect(0, 1, Duration.EndOfTurn), new ManaCostsImpl("{G}")));
// Sacrifice Kyscu Drake and a creature named Spitting Drake: Search your library for a card named Viashivan Dragon and put that card onto the battlefield. Then shuffle your library.
TargetCardInLibrary target = new TargetCardInLibrary(1, 1, new FilterCard(filter));
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new SearchLibraryPutInPlayEffect(target,true,true, Outcome.PutCardInPlay), new SacrificeSourceCost());
ability.addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent(1, 1, filterSpitting, false)));
this.addAbility(ability);
}
public KyscuDrake(final KyscuDrake card) {
super(card);
}
@Override
public KyscuDrake copy() {
return new KyscuDrake(this);
}
}

View file

@ -0,0 +1,35 @@
package mage.cards.m;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.keyword.ScryEffect;
import mage.abilities.mana.AnyColorManaAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class ManaGeode extends CardImpl {
public ManaGeode(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}");
// When Mana Geode enters the battlefield, scry 1.
this.addAbility(new EntersBattlefieldTriggeredAbility(new ScryEffect(1)));
// {T}: Add one mana of any color.
this.addAbility(new AnyColorManaAbility());
}
private ManaGeode(final ManaGeode card) {
super(card);
}
@Override
public ManaGeode copy() {
return new ManaGeode(this);
}
}

View file

@ -23,7 +23,7 @@ public final class MartyrForTheCause extends CardImpl {
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// When Martyr for the Cause dies, proliferate.
// When Martyr for the Cause dies, proliferate. (Choose any number of permanents and/or players, then give each another counter of each kind already there.)
this.addAbility(new DiesTriggeredAbility(new ProliferateEffect()));
}

View file

@ -40,7 +40,7 @@ public final class MerfolkSkydiver extends CardImpl {
ability.addTarget(new TargetControlledCreaturePermanent());
this.addAbility(ability);
// {3}{G}{U}: Proliferate.
// {3}{G}{U}: Proliferate. (Choose any number of permanents and/or players, then give each another counter of each kind already there.)
this.addAbility(new SimpleActivatedAbility(new ProliferateEffect(), new ManaCostsImpl("{3}{G}{U}")));
}

View file

@ -1,7 +1,5 @@
package mage.cards.m;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.AsThoughEffectImpl;
import mage.abilities.effects.ContinuousEffect;
@ -19,8 +17,9 @@ import mage.players.Player;
import mage.target.targetpointer.FixedTargets;
import mage.util.CardUtil;
import java.util.UUID;
/**
*
* @author emerald000
*/
public final class MindsDesire extends CardImpl {
@ -68,11 +67,14 @@ class MindsDesireEffect extends OneShotEffect {
controller.shuffleLibrary(source, game);
Card card = controller.getLibrary().getFromTop(game);
if (card != null) {
UUID exileId = UUID.randomUUID();
controller.moveCardsToExile(card, source, game, true, exileId, CardUtil.createObjectRealtedWindowTitle(source, game, null));
ContinuousEffect effect = new MindsDesireCastFromExileEffect();
effect.setTargetPointer(new FixedTargets(game.getExile().getExileZone(exileId).getCards(game), game));
game.addEffect(effect, source);
UUID exileId = CardUtil.getExileZoneId(controller.getId().toString() + "-" + game.getState().getTurnNum() + "-" + MindsDesire.class.toString(), game);
String exileName = "Mind's Desire free cast on " + game.getState().getTurnNum() + " turn for " + controller.getName();
game.getExile().createZone(exileId, exileName).setCleanupOnEndTurn(true);
if (controller.moveCardsToExile(card, source, game, true, exileId, exileName)) {
ContinuousEffect effect = new MindsDesireCastFromExileEffect();
effect.setTargetPointer(new FixedTargets(game.getExile().getExileZone(exileId).getCards(game), game));
game.addEffect(effect, source);
}
}
return true;
}

View file

@ -0,0 +1,94 @@
package mage.cards.n;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
import mage.abilities.effects.common.LookLibraryAndPickControllerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.FilterCard;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.CardTypePredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.players.Player;
import mage.watchers.common.CardsAmountDrawnThisTurnWatcher;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class NarsetParterOfVeils extends CardImpl {
private static final FilterCard filter = new FilterCard("noncreature, nonland card");
static {
filter.add(Predicates.not(new CardTypePredicate(CardType.CREATURE)));
filter.add(Predicates.not(new CardTypePredicate(CardType.LAND)));
}
public NarsetParterOfVeils(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{1}{U}{U}");
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.NARSET);
this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(5));
// Each opponent can't draw more than one card each turn.
this.addAbility(new SimpleStaticAbility(new NarsetParterOfVeilsEffect()), new CardsAmountDrawnThisTurnWatcher());
// -2: Look at the top four cards of your library. You may reveal a noncreature, nonland card from among them and put it into your hand. Put the rest on the bottom of your library in a random order.
this.addAbility(new LoyaltyAbility(new LookLibraryAndPickControllerEffect(
new StaticValue(4), false, new StaticValue(1), filter,
Zone.LIBRARY, false, true, false, Zone.HAND,
true, false, false
).setBackInRandomOrder(true).setText("Look at the top four cards of your library. " +
"You may reveal a noncreature, nonland card from among them and put it into your hand. " +
"Put the rest on the bottom of your library in a random order."
), -2));
}
private NarsetParterOfVeils(final NarsetParterOfVeils card) {
super(card);
}
@Override
public NarsetParterOfVeils copy() {
return new NarsetParterOfVeils(this);
}
}
class NarsetParterOfVeilsEffect extends ContinuousRuleModifyingEffectImpl {
NarsetParterOfVeilsEffect() {
super(Duration.WhileOnBattlefield, Outcome.Detriment, false, false);
staticText = "Each opponent can't draw more than one card each turn";
}
private NarsetParterOfVeilsEffect(final NarsetParterOfVeilsEffect effect) {
super(effect);
}
@Override
public NarsetParterOfVeilsEffect copy() {
return new NarsetParterOfVeilsEffect(this);
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DRAW_CARD;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
CardsAmountDrawnThisTurnWatcher watcher = game.getState().getWatcher(CardsAmountDrawnThisTurnWatcher.class);
Player controller = game.getPlayer(source.getControllerId());
return watcher != null && controller != null && watcher.getAmountCardsDrawn(event.getPlayerId()) >= 1
&& game.isOpponent(controller, event.getPlayerId());
}
}

View file

@ -0,0 +1,37 @@
package mage.cards.n;
import mage.abilities.effects.common.CopyTargetSpellEffect;
import mage.abilities.effects.common.ReturnToHandTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.filter.StaticFilters;
import mage.target.TargetSpell;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class NarsetsReversal extends CardImpl {
public NarsetsReversal(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{U}{U}");
// Copy target instant or sorcery spell, then return it to its owner's hand. You may choose new targets for the copy.
this.getSpellAbility().addEffect(new CopyTargetSpellEffect()
.setText("Copy target instant or sorcery spell,"));
this.getSpellAbility().addEffect(new ReturnToHandTargetEffect()
.setText("then return it to its owner's hand. You may choose new targets for the copy."));
this.getSpellAbility().addTarget(new TargetSpell(StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY));
}
private NarsetsReversal(final NarsetsReversal card) {
super(card);
}
@Override
public NarsetsReversal copy() {
return new NarsetsReversal(this);
}
}

View file

@ -0,0 +1,109 @@
package mage.cards.o;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.effects.common.GainLifeEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SuperType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.target.common.TargetAnyTarget;
import mage.target.targetpointer.FixedTarget;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class OathOfKaya extends CardImpl {
public OathOfKaya(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}{B}");
this.addSuperType(SuperType.LEGENDARY);
// When Oath of Kaya enters the battlefield, it deals 3 damage to any target and you gain 3 life.
Ability ability = new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(3, "it"));
ability.addEffect(new GainLifeEffect(3).concatBy("and"));
ability.addTarget(new TargetAnyTarget());
this.addAbility(ability);
// Whenever an opponent attacks a planeswalker you control with one or more creatures, Oath of Kaya deals 2 damage to that player and you gain 2 life.
this.addAbility(new OathOfKayaTriggeredAbility());
}
private OathOfKaya(final OathOfKaya card) {
super(card);
}
@Override
public OathOfKaya copy() {
return new OathOfKaya(this);
}
}
class OathOfKayaTriggeredAbility extends TriggeredAbilityImpl {
private final Set<UUID> attackedThisCombat = new HashSet();
OathOfKayaTriggeredAbility() {
super(Zone.BATTLEFIELD, null, false);
}
private OathOfKayaTriggeredAbility(final OathOfKayaTriggeredAbility ability) {
super(ability);
this.attackedThisCombat.addAll(ability.attackedThisCombat);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ATTACKER_DECLARED
|| event.getType() == GameEvent.EventType.DECLARE_ATTACKERS_STEP_POST;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.DECLARE_ATTACKERS_STEP_POST) {
this.attackedThisCombat.clear();
return false;
}
for (UUID attackerId : game.getCombat().getAttackers()) {
Permanent attacker = game.getPermanent(attackerId);
if (attacker == null) {
continue;
}
UUID defendingPlayerId = game.getCombat().getDefendingPlayerId(attackerId, game);
UUID defenderId = game.getCombat().getDefenderId(attackerId);
if (defendingPlayerId.equals(defenderId) || attackedThisCombat.contains(defenderId)) {
continue;
}
attackedThisCombat.add(defenderId);
this.getEffects().clear();
Effect effect = new DamageTargetEffect(2);
effect.setTargetPointer(new FixedTarget(defendingPlayerId, game));
this.addEffect(effect);
this.addEffect(new GainLifeEffect(2));
return true;
}
return false;
}
@Override
public OathOfKayaTriggeredAbility copy() {
return new OathOfKayaTriggeredAbility(this);
}
@Override
public String getRule() {
return "Whenever an opponent attacks a planeswalker you control with one or more creatures, " +
"{this} deals 2 damage to that player and you gain 2 life.";
}
}

View file

@ -1,8 +1,5 @@
package mage.cards.p;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
@ -13,24 +10,27 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import java.util.UUID;
/**
*
* @author Loki
*/
public final class PhyrexianRager extends CardImpl {
public PhyrexianRager (UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{B}");
public PhyrexianRager(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}");
this.subtype.add(SubType.HORROR);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
Ability ability = new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1), false);
ability.addEffect(new LoseLifeSourceControllerEffect(1));
Ability ability = new EntersBattlefieldTriggeredAbility(
new DrawCardSourceControllerEffect(1), false
);
ability.addEffect(new LoseLifeSourceControllerEffect(1).concatBy("and"));
this.addAbility(ability);
}
public PhyrexianRager (final PhyrexianRager card) {
public PhyrexianRager(final PhyrexianRager card) {
super(card);
}

View file

@ -1,7 +1,5 @@
package mage.cards.p;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
@ -13,11 +11,13 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Zone;
import static mage.filter.StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT;
import mage.target.common.TargetControlledCreaturePermanent;
import java.util.UUID;
import static mage.filter.StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT;
/**
*
* @author Loki
*/
public final class PlaguemawBeast extends CardImpl {
@ -28,6 +28,8 @@ public final class PlaguemawBeast extends CardImpl {
this.power = new MageInt(4);
this.toughness = new MageInt(3);
// {T}, Sacrifice a creature: Proliferate. (You choose any number of permanents and/or players with counters on them, then give each another counter of a kind already there.)
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ProliferateEffect(), new TapSourceCost());
ability.addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent(FILTER_CONTROLLED_CREATURE_SHORT_TEXT)));
this.addAbility(ability);

View file

@ -0,0 +1,56 @@
package mage.cards.p;
import mage.abilities.Mode;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.effects.common.ReturnToHandTargetEffect;
import mage.abilities.effects.common.counter.ProliferateEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.filter.FilterCard;
import mage.filter.common.FilterPermanentCard;
import mage.game.permanent.token.PlanewideCelebrationToken;
import mage.target.common.TargetCardInYourGraveyard;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class PlanewideCelebration extends CardImpl {
private static final FilterCard filter = new FilterPermanentCard("permanent card from your graveyard");
public PlanewideCelebration(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{5}{G}{G}");
// Choose four. You may choose the same mode more than once.
this.getSpellAbility().getModes().setMinModes(4);
this.getSpellAbility().getModes().setMaxModes(4);
this.getSpellAbility().getModes().setEachModeMoreThanOnce(true);
// Create a 2/2 Citizen creature token that's all colors.
this.getSpellAbility().addEffect(new CreateTokenEffect(new PlanewideCelebrationToken()));
// Return target permanent card from your graveyard to your hand.
Mode mode = new Mode(new ReturnToHandTargetEffect());
mode.addTarget(new TargetCardInYourGraveyard(filter));
this.getSpellAbility().addMode(mode);
// Proliferate.
this.getSpellAbility().addMode(new Mode(new ProliferateEffect(false)));
// You gain 4 life.
this.getSpellAbility().addMode(new Mode(new GainLifeEffect(4)));
}
private PlanewideCelebration(final PlanewideCelebration card) {
super(card);
}
@Override
public PlanewideCelebration copy() {
return new PlanewideCelebration(this);
}
}

View file

@ -35,7 +35,7 @@ public final class PollenbrightDruid extends CardImpl {
);
ability.addTarget(new TargetCreaturePermanent());
// Proliferate.
// Proliferate. (Choose any number of permanents and/or players, then give each another counter of each kind already there.)
ability.addMode(new Mode(new ProliferateEffect()));
this.addAbility(ability);
}

View file

@ -0,0 +1,132 @@
package mage.cards.p;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.filter.FilterOpponent;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterPermanentOrPlayer;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.CardTypePredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetPermanentOrPlayer;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class PriceOfBetrayal extends CardImpl {
private static final FilterPermanent filter = new FilterPermanent();
static {
filter.add(Predicates.or(
new CardTypePredicate(CardType.ARTIFACT),
new CardTypePredicate(CardType.CREATURE),
new CardTypePredicate(CardType.PLANESWALKER)
));
}
private static final FilterPermanentOrPlayer filter2 = new FilterPermanentOrPlayer("artifact, creature, planeswalker, or opponent", filter, new FilterOpponent());
public PriceOfBetrayal(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{B}");
// Remove up to five counters from target artifact, creature, planeswalker, or opponent.
this.getSpellAbility().addEffect(new PriceOfBetrayalEffect());
this.getSpellAbility().addTarget(new TargetPermanentOrPlayer(1, 1, filter2, false));
}
private PriceOfBetrayal(final PriceOfBetrayal card) {
super(card);
}
@Override
public PriceOfBetrayal copy() {
return new PriceOfBetrayal(this);
}
}
class PriceOfBetrayalEffect extends OneShotEffect {
PriceOfBetrayalEffect() {
super(Outcome.Benefit);
staticText = "Remove up to five counters from target artifact, creature, planeswalker, or opponent.";
}
private PriceOfBetrayalEffect(final PriceOfBetrayalEffect effect) {
super(effect);
}
@Override
public PriceOfBetrayalEffect copy() {
return new PriceOfBetrayalEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller == null) {
return false;
}
Permanent permanent = game.getPermanent(source.getFirstTarget());
if (permanent != null) {
int toRemove = 5;
int removed = 0;
String[] counterNames = permanent.getCounters(game).keySet().toArray(new String[0]);
for (String counterName : counterNames) {
if (controller.chooseUse(Outcome.Neutral, "Do you want to remove " + counterName + " counters?", source, game)) {
if (permanent.getCounters(game).get(counterName).getCount() == 1 || toRemove == 1) {
permanent.removeCounters(counterName, 1, game);
removed++;
} else {
int amount = controller.getAmount(1, Math.min(permanent.getCounters(game).get(counterName).getCount(), toRemove - removed), "How many?", game);
if (amount > 0) {
removed += amount;
permanent.removeCounters(counterName, amount, game);
}
}
}
if (removed >= toRemove) {
break;
}
}
game.addEffect(new BoostSourceEffect(removed, 0, Duration.EndOfTurn), source);
return true;
}
Player player = game.getPlayer(source.getFirstTarget());
if (player != null) {
int toRemove = 5;
int removed = 0;
String[] counterNames = player.getCounters().keySet().toArray(new String[0]);
for (String counterName : counterNames) {
if (controller.chooseUse(Outcome.Neutral, "Do you want to remove " + counterName + " counters?", source, game)) {
if (player.getCounters().get(counterName).getCount() == 1 || toRemove == 1) {
player.removeCounters(counterName, 1, source, game);
removed++;
} else {
int amount = controller.getAmount(1, Math.min(player.getCounters().get(counterName).getCount(), toRemove - removed), "How many?", game);
if (amount > 0) {
removed += amount;
player.removeCounters(counterName, amount, source, game);
}
}
}
if (removed >= toRemove) {
break;
}
}
game.addEffect(new BoostSourceEffect(removed, 0, Duration.EndOfTurn), source);
return true;
}
return false;
}
}

View file

@ -0,0 +1,37 @@
package mage.cards.p;
import mage.MageInt;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.mana.AnyColorManaAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class Prismite extends CardImpl {
public Prismite(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{2}");
this.subtype.add(SubType.GOLEM);
this.power = new MageInt(2);
this.toughness = new MageInt(1);
// {2}: Add one mana of any color.
this.addAbility(new AnyColorManaAbility(new GenericManaCost(2)));
}
private Prismite(final Prismite card) {
super(card);
}
@Override
public Prismite copy() {
return new Prismite(this);
}
}

View file

@ -0,0 +1,55 @@
package mage.cards.p;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.delayed.OnLeaveReturnExiledToBattlefieldAbility;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.abilities.effects.common.ExileUntilSourceLeavesEffect;
import mage.abilities.effects.keyword.ScryEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.TargetController;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterCreatureOrPlaneswalkerPermanent;
import mage.filter.predicate.permanent.ControllerPredicate;
import mage.target.TargetPermanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class PrisonRealm extends CardImpl {
private static final FilterPermanent filter
= new FilterCreatureOrPlaneswalkerPermanent("creature or planeswalker an opponent controls");
static {
filter.add(new ControllerPredicate(TargetController.OPPONENT));
}
public PrisonRealm(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}");
// When Prison Realm enters the battlefield, exile target creature or planeswalker an opponent controls until Prison Realm leaves the battlefield.
Ability ability = new EntersBattlefieldTriggeredAbility(
new ExileUntilSourceLeavesEffect(filter.getMessage())
);
ability.addTarget(new TargetPermanent(filter));
ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new OnLeaveReturnExiledToBattlefieldAbility()));
this.addAbility(ability);
// When Prison Realm enters the battlefield, scry 1.
this.addAbility(new EntersBattlefieldTriggeredAbility(new ScryEffect(1)));
}
private PrisonRealm(final PrisonRealm card) {
super(card);
}
@Override
public PrisonRealm copy() {
return new PrisonRealm(this);
}
}

View file

@ -0,0 +1,47 @@
package mage.cards.r;
import mage.abilities.Mode;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.abilities.effects.common.ExileTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.target.common.TargetArtifactPermanent;
import mage.target.common.TargetCardInGraveyard;
import mage.target.common.TargetEnchantmentPermanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class ReturnToNature extends CardImpl {
public ReturnToNature(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{G}");
// Choose one
// Destroy target artifact.
this.getSpellAbility().addEffect(new DestroyTargetEffect());
this.getSpellAbility().addTarget(new TargetArtifactPermanent());
// Destroy target enchantment.
Mode mode = new Mode(new DestroyTargetEffect());
mode.addTarget(new TargetEnchantmentPermanent());
this.getSpellAbility().addMode(mode);
// Exile target card from a graveyard.
mode = new Mode(new ExileTargetEffect());
mode.addTarget(new TargetCardInGraveyard());
this.getSpellAbility().addMode(mode);
}
private ReturnToNature(final ReturnToNature card) {
super(card);
}
@Override
public ReturnToNature copy() {
return new ReturnToNature(this);
}
}

View file

@ -55,12 +55,9 @@ public final class RoaleskApexHybrid extends CardImpl {
ability.addTarget(new TargetPermanent(filter));
this.addAbility(ability);
// When Roalsk dies, proliferate, then proliferate again.
ability = new DiesTriggeredAbility(new ProliferateEffect().setText("proliferate,"));
ability.addEffect(new ProliferateEffect().setText(
"then proliferate again <i>(Choose any number of permanents and/or players, " +
"then give each another counter of each kind already there. Then do it again.)</i>"
));
// When Roalsk dies, proliferate, then proliferate again. (Choose any number of permanents and/or players, then give each another counter of each kind already there. Then do it again.)
ability = new DiesTriggeredAbility(new ProliferateEffect(false));
ability.addEffect(new ProliferateEffect(" again", true).concatBy(", then"));
this.addAbility(ability);
}

View file

@ -0,0 +1,80 @@
package mage.cards.r;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.effects.common.UntapSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetPlayer;
/**
*
* @author North
*/
public final class RodOfSpanking extends CardImpl {
public RodOfSpanking(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[] { CardType.ARTIFACT }, "{1}");
// 2, T: Rod of Spanking deals 1 damage to target player. Then untap Rod of
// Spanking unless that player says "Thank you, sir. May I have another?"
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new RodOfSpankingEffect(), new GenericManaCost(2));
ability.addCost(new TapSourceCost());
ability.addTarget(new TargetPlayer());
this.addAbility(ability);
}
public RodOfSpanking(final RodOfSpanking card) {
super(card);
}
@Override
public RodOfSpanking copy() {
return new RodOfSpanking(this);
}
}
class RodOfSpankingEffect extends OneShotEffect {
public RodOfSpankingEffect() {
super(Outcome.Benefit);
staticText = "{this} deals 1 damage to target player. Then untap {this} unless that player says \"Thank you, sir. May I have another?\"";
}
public RodOfSpankingEffect(final RodOfSpankingEffect effect) {
super(effect);
}
@Override
public RodOfSpankingEffect copy() {
return new RodOfSpankingEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player target = game.getPlayer(source.getFirstTarget());
new DamageTargetEffect(1).apply(game, source);
if (target != null) {
if (target.chooseUse(Outcome.Untap, "Say \"Thank you, sir. May I have another?\"", source, game)) {
game.informPlayers(target.getLogName() + ": Thank you, sir. May I have another?");
} else {
new UntapSourceEffect().apply(game, source);
}
return true;
}
return false;
}
}

View file

@ -0,0 +1,103 @@
package mage.cards.r;
import java.util.Set;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.costs.Cost;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.RemoveAllCountersSourceEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.TargetController;
import mage.counters.CounterType;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.Target;
import mage.target.common.TargetOpponent;
/**
*
* @author Ketsuban
*/
public class RogueSkycaptain extends CardImpl {
public RogueSkycaptain(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[] { CardType.CREATURE }, "{2}{R}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.ROGUE);
this.subtype.add(SubType.MERCENARY);
this.power = new MageInt(3);
this.toughness = new MageInt(4);
// Flying
this.addAbility(FlyingAbility.getInstance());
// At the beginning of your upkeep, put a wage counter on Rogue Skycaptain. You
// may pay 2 for each wage counter on it. If you don't, remove all wage counters
// from Rogue Skycaptain and an opponent gains control of it.
this.addAbility(new BeginningOfUpkeepTriggeredAbility(new RogueSkycaptainEffect(), TargetController.YOU, false));
}
@Override
public Card copy() {
return null;
}
}
class RogueSkycaptainEffect extends OneShotEffect {
public RogueSkycaptainEffect() {
super(Outcome.GainControl);
staticText = "put a wage counter on {this}. You may pay {2} for each wage counter on it. If you don't, remove all wage counters from {this} and an opponent gains control of it";
}
public RogueSkycaptainEffect(final RogueSkycaptainEffect effect) {
super(effect);
}
@Override
public Effect copy() {
return new RogueSkycaptainEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Permanent permanent = game.getPermanentOrLKIBattlefield(source.getSourceId());
if (controller != null && permanent != null) {
new AddCountersSourceEffect(CounterType.WAGE.createInstance(), true).apply(game, source);
Cost cost = new GenericManaCost(2 * permanent.getCounters(game).getCount(CounterType.WAGE));
if (!cost.pay(source, game, controller.getId(), controller.getId(), false)) {
new RemoveAllCountersSourceEffect(CounterType.WAGE).apply(game, source);
Player opponent;
Set<UUID> opponents = game.getOpponents(controller.getId());
if (opponents.size() == 1) {
opponent = game.getPlayer(opponents.iterator().next());
} else {
Target target = new TargetOpponent(true);
target.setNotTarget(true);
target.choose(Outcome.GainControl, source.getControllerId(), source.getSourceId(), game);
opponent = game.getPlayer(target.getFirstTarget());
}
if (opponent != null) {
permanent.changeControllerId(opponent.getId(), game);
}
}
return true;
}
return false;
}
}

View file

@ -0,0 +1,48 @@
package mage.cards.r;
import mage.MageInt;
import mage.abilities.common.AttacksTriggeredAbility;
import mage.abilities.dynamicvalue.common.GreatestPowerAmongControlledCreaturesValue;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.abilities.keyword.HasteAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class RubblebeltRioters extends CardImpl {
public RubblebeltRioters(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}{G}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.BERSERKER);
this.power = new MageInt(0);
this.toughness = new MageInt(4);
// Haste
this.addAbility(HasteAbility.getInstance());
// Whenever Rubblebelt Rioters attacks, it gets +X/+0 until end of turn, where X is the greatest power among creatures you control.
this.addAbility(new AttacksTriggeredAbility(new BoostSourceEffect(
GreatestPowerAmongControlledCreaturesValue.instance, new StaticValue(0),
Duration.EndOfTurn, true
), false));
}
private RubblebeltRioters(final RubblebeltRioters card) {
super(card);
}
@Override
public RubblebeltRioters copy() {
return new RubblebeltRioters(this);
}
}

View file

@ -0,0 +1,165 @@
package mage.cards.s;
import mage.MageObjectReference;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.AttacksAllTriggeredAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.game.permanent.token.DragonToken;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class SarkhanTheMasterless extends CardImpl {
public SarkhanTheMasterless(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{3}{R}{R}");
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.SARKHAN);
this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(5));
// Whenever a creature attacks you or a planeswalker you control, each Dragon you control deals 1 damage to that creature.
this.addAbility(new AttacksAllTriggeredAbility(
new SarkhanTheMasterlessDamageEffect(),
false, StaticFilters.FILTER_PERMANENT_A_CREATURE,
SetTargetPointer.PERMANENT, true
));
// +1: Until end of turn, each planeswalker you control becomes a 4/4 red Dragon creature and gains flying.
this.addAbility(new LoyaltyAbility(new SarkhanTheMasterlessBecomeDragonEffect(), 1));
// -3: Create a 4/4 red Dragon creature token with flying.
this.addAbility(new LoyaltyAbility(new CreateTokenEffect(new DragonToken()), -3));
}
private SarkhanTheMasterless(final SarkhanTheMasterless card) {
super(card);
}
@Override
public SarkhanTheMasterless copy() {
return new SarkhanTheMasterless(this);
}
}
class SarkhanTheMasterlessDamageEffect extends OneShotEffect {
SarkhanTheMasterlessDamageEffect() {
super(Outcome.Benefit);
staticText = "each Dragon you control deals 1 damage to that creature.";
}
private SarkhanTheMasterlessDamageEffect(final SarkhanTheMasterlessDamageEffect effect) {
super(effect);
}
@Override
public SarkhanTheMasterlessDamageEffect copy() {
return new SarkhanTheMasterlessDamageEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent creature = game.getPermanent(targetPointer.getFirst(game, source));
if (creature == null) {
return false;
}
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(source.getControllerId())) {
if (permanent != null && permanent.hasSubtype(SubType.DRAGON, game)) {
creature.damage(1, permanent.getId(), game);
}
}
return true;
}
}
class SarkhanTheMasterlessBecomeDragonEffect extends ContinuousEffectImpl {
SarkhanTheMasterlessBecomeDragonEffect() {
super(Duration.EndOfTurn, Outcome.BecomeCreature);
staticText = "Until end of turn, each planeswalker you control becomes a 4/4 red Dragon creature and gains flying.";
}
private SarkhanTheMasterlessBecomeDragonEffect(final SarkhanTheMasterlessBecomeDragonEffect effect) {
super(effect);
}
@Override
public SarkhanTheMasterlessBecomeDragonEffect copy() {
return new SarkhanTheMasterlessBecomeDragonEffect(this);
}
@Override
public void init(Ability source, Game game) {
super.init(source, game);
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(source.getControllerId())) {
if (permanent != null && permanent.isPlaneswalker()) {
affectedObjectList.add(new MageObjectReference(permanent, game));
}
}
}
@Override
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
boolean flag = false;
for (MageObjectReference mor : affectedObjectList) {
Permanent permanent = mor.getPermanent(game);
if (permanent == null) {
continue;
}
flag = true;
switch (layer) {
case TypeChangingEffects_4:
if (sublayer == SubLayer.NA) {
permanent.getCardType().clear();
permanent.addCardType(CardType.CREATURE);
permanent.getSubtype(game).clear();
permanent.getSubtype(game).add(SubType.DRAGON);
permanent.getSuperType().clear();
}
break;
case ColorChangingEffects_5:
permanent.getColor(game).setColor(ObjectColor.RED);
break;
case AbilityAddingRemovingEffects_6:
if (sublayer == SubLayer.NA) {
permanent.addAbility(FlyingAbility.getInstance(), source.getSourceId(), game);
}
break;
case PTChangingEffects_7:
if (sublayer == SubLayer.SetPT_7b) {
permanent.getPower().setValue(4);
permanent.getToughness().setValue(4);
}
}
}
return flag;
}
@Override
public boolean apply(Game game, Ability source) {
return false;
}
@Override
public boolean hasLayer(Layer layer) {
return layer == Layer.PTChangingEffects_7
|| layer == Layer.AbilityAddingRemovingEffects_6
|| layer == Layer.ColorChangingEffects_5
|| layer == Layer.TypeChangingEffects_4;
}
}

View file

@ -0,0 +1,46 @@
package mage.cards.s;
import mage.MageInt;
import mage.abilities.common.SpellCastControllerTriggeredAbility;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
import mage.filter.StaticFilters;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class SkyTheaterStrix extends CardImpl {
public SkyTheaterStrix(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}");
this.subtype.add(SubType.BIRD);
this.power = new MageInt(1);
this.toughness = new MageInt(2);
// Flying
this.addAbility(FlyingAbility.getInstance());
// Whenever you cast a noncreature spell, Sky Theater Strix gets +1/+0 until end of turn.
this.addAbility(new SpellCastControllerTriggeredAbility(
new BoostSourceEffect(1, 0, Duration.EndOfTurn),
StaticFilters.FILTER_SPELL_A_NON_CREATURE, false
));
}
private SkyTheaterStrix(final SkyTheaterStrix card) {
super(card);
}
@Override
public SkyTheaterStrix copy() {
return new SkyTheaterStrix(this);
}
}

View file

@ -0,0 +1,78 @@
package mage.cards.s;
import mage.MageInt;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.ReachAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class Snarespinner extends CardImpl {
public Snarespinner(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}");
this.subtype.add(SubType.SPIDER);
this.power = new MageInt(1);
this.toughness = new MageInt(3);
// Reach
this.addAbility(ReachAbility.getInstance());
// Whenever Snarespinner blocks a creature with flying, Snarespinner gets +2/+0 until end of turn.
this.addAbility(new SnarespinnerTriggeredAbility());
}
private Snarespinner(final Snarespinner card) {
super(card);
}
@Override
public Snarespinner copy() {
return new Snarespinner(this);
}
}
class SnarespinnerTriggeredAbility extends TriggeredAbilityImpl {
SnarespinnerTriggeredAbility() {
super(Zone.BATTLEFIELD, new BoostSourceEffect(2, 0, Duration.EndOfTurn), false);
}
private SnarespinnerTriggeredAbility(final SnarespinnerTriggeredAbility ability) {
super(ability);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.BLOCKER_DECLARED;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
return event.getSourceId().equals(this.getSourceId())
&& game.getPermanent(event.getTargetId()).getAbilities().containsKey(FlyingAbility.getInstance().getId());
}
@Override
public String getRule() {
return "Whenever {this} blocks a creature with flying, {} gets +2/+0 until end of turn";
}
@Override
public SnarespinnerTriggeredAbility copy() {
return new SnarespinnerTriggeredAbility(this);
}
}

View file

@ -0,0 +1,68 @@
package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.common.RegenerateSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetOpponent;
/**
*
* @author Ketsuban
*/
public final class SoldeviSentry extends CardImpl {
public SoldeviSentry(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[] { CardType.ARTIFACT, CardType.CREATURE }, "{1}");
this.subtype.add(SubType.SOLDIER);
this.power = new MageInt(1);
this.toughness = new MageInt(1);
// 1: Choose target opponent. Regenerate Soldevi Sentry. When it regenerates
// this way, that player may draw a card.
Ability ability = new SimpleActivatedAbility(new SoldeviSentryEffect(), new GenericManaCost(1));
ability.addTarget(new TargetOpponent());
this.addAbility(ability);
}
public SoldeviSentry(final SoldeviSentry card) {
super(card);
}
@Override
public SoldeviSentry copy() {
return new SoldeviSentry(this);
}
}
class SoldeviSentryEffect extends RegenerateSourceEffect {
@Override
public boolean apply(Game game, Ability source) {
//20110204 - 701.11
Player opponent = game.getPlayer(source.getFirstTarget());
Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent != null && permanent.regenerate(this.getId(), game)) {
if (opponent != null) {
if (opponent.chooseUse(Outcome.DrawCard, "Draw a card?", source, game)) {
opponent.drawCards(1, game);
}
}
this.used = true;
return true;
}
return false;
}
}

View file

@ -0,0 +1,83 @@
package mage.cards.s;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.SacrificeTargetEffect;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.filter.FilterCard;
import mage.filter.predicate.mageobject.CardTypePredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.common.TargetControlledCreaturePermanent;
import mage.target.targetpointer.FixedTarget;
/*
*
* @author Ketsuban
*/
public class Soulshriek extends CardImpl {
protected static final FilterCard filterCard = new FilterCard("creature cards");
static {
filterCard.add(new CardTypePredicate(CardType.CREATURE));
}
public Soulshriek(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{B}");
// Target creature you control gets +X/+0 until end of turn, where X is the number of creature cards in your graveyard. Sacrifice that creature at the beginning of the next end step.
this.getSpellAbility().addEffect(new SoulshriekEffect());
this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent());
}
@Override
public Card copy() {
return null;
}
}
class SoulshriekEffect extends OneShotEffect {
public SoulshriekEffect() {
super(Outcome.DestroyPermanent);
this.staticText = "Target creature you control gets +X/+0 until end of turn, where X is the number of creature cards in your graveyard. Sacrifice that creature at the beginning of the next end step";
}
public SoulshriekEffect(final SoulshriekEffect effect) {
super(effect);
}
@Override
public SoulshriekEffect copy() {
return new SoulshriekEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getFirstTarget());
if (permanent != null) {
ContinuousEffect boost = new BoostTargetEffect(new CardsInControllerGraveyardCount(Soulshriek.filterCard), new StaticValue(0), Duration.EndOfTurn);
boost.setTargetPointer(new FixedTarget(permanent, game));
game.addEffect(boost, source);
Effect sacrifice = new SacrificeTargetEffect("Sacrifice that creature at the beginning of the next end step", source.getControllerId());
sacrifice.setTargetPointer(new FixedTarget(permanent, game));
game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(sacrifice), source);
return true;
}
return false;
}
}

View file

@ -1,8 +1,5 @@
package mage.cards.s;
import java.util.UUID;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.abilities.effects.common.counter.ProliferateEffect;
import mage.cards.CardImpl;
@ -10,21 +7,23 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
/**
*
* @author Loki
*/
public final class SpreadTheSickness extends CardImpl {
public SpreadTheSickness (UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{4}{B}");
public SpreadTheSickness(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{B}");
// Destroy target creature, then proliferate. (You choose any number of permanents and/or players with counters on them, then give each another counter of a kind already there.)
this.getSpellAbility().addEffect(new DestroyTargetEffect());
this.getSpellAbility().addEffect(new ProliferateEffect());
this.getSpellAbility().addEffect(new ProliferateEffect().concatBy(", then"));
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
}
public SpreadTheSickness (final SpreadTheSickness card) {
public SpreadTheSickness(final SpreadTheSickness card) {
super(card);
}

View file

@ -52,7 +52,11 @@ class TemporalApertureEffect extends OneShotEffect {
public TemporalApertureEffect() {
super(Outcome.Neutral);
staticText = "Shuffle your library, then reveal the top card. Until end of turn, for as long as that card remains on top of your library, play with the top card of your library revealed and you may play that card without paying its mana cost";
staticText = "Shuffle your library, then reveal the top card. "
+ "Until end of turn, for as long as that card remains on "
+ "top of your library, play with the top card of your "
+ "library revealed and you may play that card without "
+ "paying its mana cost";
}
public TemporalApertureEffect(final TemporalApertureEffect effect) {
@ -89,7 +93,8 @@ class TemporalApertureTopCardCastEffect extends AsThoughEffectImpl {
public TemporalApertureTopCardCastEffect(Card card) {
super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfTurn, Outcome.Benefit);
this.card = card;
staticText = "Until end of turn, for as long as that card is on top of your library, you may cast it without paying its mana costs";
staticText = "Until end of turn, for as long as that card is on top "
+ "of your library, you may cast it without paying its mana costs";
}
public TemporalApertureTopCardCastEffect(final TemporalApertureTopCardCastEffect effect) {
@ -118,7 +123,8 @@ class TemporalApertureTopCardCastEffect extends AsThoughEffectImpl {
if (controller.getLibrary().getFromTop(game).equals(card)) {
if (objectCard == card
&& objectCard.getSpellAbility() != null
&& objectCard.getSpellAbility().spellCanBeActivatedRegularlyNow(controller.getId(), game)) {
&& objectCard.getSpellAbility().spellCanBeActivatedRegularlyNow(controller.getId(), game)
|| objectCard.isLand()) {
controller.setCastSourceIdWithAlternateMana(objectId, null, null);
return true;
}

View file

@ -1,24 +1,24 @@
package mage.cards.t;
import java.util.UUID;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.counter.ProliferateEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import java.util.UUID;
/**
*
* @author North
*/
public final class TezzeretsGambit extends CardImpl {
public TezzeretsGambit(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{3}{U/P}");
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{U/P}");
// Draw two cards, then proliferate. (You choose any number of permanents and/or players with counters on them, then give each another counter of a kind already there.)
this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(2));
this.getSpellAbility().addEffect(new ProliferateEffect());
this.getSpellAbility().addEffect(new ProliferateEffect().concatBy(", then"));
}
public TezzeretsGambit(final TezzeretsGambit card) {

View file

@ -1,8 +1,5 @@
package mage.cards.t;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.SacrificeTargetCost;
@ -16,8 +13,9 @@ import mage.filter.common.FilterControlledPermanent;
import mage.filter.predicate.mageobject.CardTypePredicate;
import mage.target.common.TargetControlledPermanent;
import java.util.UUID;
/**
*
* @author Loki
*/
public final class ThroneOfGeth extends CardImpl {
@ -30,9 +28,9 @@ public final class ThroneOfGeth extends CardImpl {
public ThroneOfGeth(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{2}");
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}");
// {T}, Sacrifice an artifact: Proliferate.
// {T}, Sacrifice an artifact: Proliferate. (You choose any number of permanents and/or players with counters on them, then give each another counter of a kind already there.)
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ProliferateEffect(), new TapSourceCost());
ability.addCost(new SacrificeTargetCost(new TargetControlledPermanent(filter)));
this.addAbility(ability);

View file

@ -1,8 +1,5 @@
package mage.cards.t;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
import mage.abilities.effects.common.counter.ProliferateEffect;
@ -12,20 +9,25 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import java.util.UUID;
/**
* @author Loki, nantuko, North
*/
public final class Thrummingbird extends CardImpl {
public Thrummingbird(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{U}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}");
this.subtype.add(SubType.BIRD);
this.subtype.add(SubType.HORROR);
this.power = new MageInt(1);
this.toughness = new MageInt(1);
// Flying
this.addAbility(FlyingAbility.getInstance());
// Whenever Thrummingbird deals combat damage to a player, proliferate. (You choose any number of permanents and/or players with counters on them, then give each another counter of a kind already there.)
this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new ProliferateEffect(), false));
}

View file

@ -0,0 +1,84 @@
package mage.cards.t;
import mage.MageInt;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.counters.CounterType;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.watchers.common.CastSpellLastTurnWatcher;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class ThunderDrake extends CardImpl {
public ThunderDrake(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}");
this.subtype.add(SubType.ELEMENTAL);
this.subtype.add(SubType.DRAKE);
this.power = new MageInt(2);
this.toughness = new MageInt(3);
// Flying
this.addAbility(FlyingAbility.getInstance());
// Whenever you cast you cast your second spell each turn, put a +1/+1 counter on Thunder Drake.
this.addAbility(new ThunderDrakeTriggeredAbility(), new CastSpellLastTurnWatcher());
}
private ThunderDrake(final ThunderDrake card) {
super(card);
}
@Override
public ThunderDrake copy() {
return new ThunderDrake(this);
}
}
class ThunderDrakeTriggeredAbility extends TriggeredAbilityImpl {
ThunderDrakeTriggeredAbility() {
super(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.P1P1.createInstance()));
}
private ThunderDrakeTriggeredAbility(final ThunderDrakeTriggeredAbility ability) {
super(ability);
}
@Override
public ThunderDrakeTriggeredAbility copy() {
return new ThunderDrakeTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.SPELL_CAST;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (event.getPlayerId().equals(controllerId)) {
CastSpellLastTurnWatcher watcher = game.getState().getWatcher(CastSpellLastTurnWatcher.class);
if (watcher != null && watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(event.getPlayerId()) == 2) {
return true;
}
}
return false;
}
@Override
public String getRule() {
return "Whenever you cast your second spell each turn, put a +1/+1 counter on {this}";
}
}

View file

@ -0,0 +1,44 @@
package mage.cards.t;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.LoseLifeSourceControllerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class TithebearerGiant extends CardImpl {
public TithebearerGiant(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{B}");
this.subtype.add(SubType.GIANT);
this.subtype.add(SubType.WARRIOR);
this.power = new MageInt(4);
this.toughness = new MageInt(5);
// When Tithebearer Giant enters the battlefield, you draw a card and you lose 1 life.
Ability ability = new EntersBattlefieldTriggeredAbility(
new DrawCardSourceControllerEffect(1), false
);
ability.addEffect(new LoseLifeSourceControllerEffect(1).concatBy("and"));
this.addAbility(ability);
}
private TithebearerGiant(final TithebearerGiant card) {
super(card);
}
@Override
public TithebearerGiant copy() {
return new TithebearerGiant(this);
}
}

View file

@ -0,0 +1,62 @@
package mage.cards.t;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.AttacksTriggeredAbility;
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterAttackingCreature;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.AbilityPredicate;
import mage.target.TargetPermanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class TrustedPegasus extends CardImpl {
private static final FilterPermanent filter
= new FilterAttackingCreature("attacking creature without flying");
static {
filter.add(Predicates.not(new AbilityPredicate(FlyingAbility.class)));
}
public TrustedPegasus(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}");
this.subtype.add(SubType.PEGASUS);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// Flying
this.addAbility(FlyingAbility.getInstance());
// Whenever Trusted Pegasus attacks, target attacking creature without flying gains flying until end of turn.
Ability ability = new AttacksTriggeredAbility(
new GainAbilityTargetEffect(
FlyingAbility.getInstance(),
Duration.EndOfTurn
), false
);
ability.addTarget(new TargetPermanent(filter));
addAbility(ability);
}
private TrustedPegasus(final TrustedPegasus card) {
super(card);
}
@Override
public TrustedPegasus copy() {
return new TrustedPegasus(this);
}
}

View file

@ -0,0 +1,52 @@
package mage.cards.t;
import mage.abilities.Mode;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.abilities.effects.common.ReturnToHandTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.ComparisonType;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.mageobject.ConvertedManaCostPredicate;
import mage.target.TargetPermanent;
import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class TyrantsScorn extends CardImpl {
private static final FilterPermanent filter
= new FilterCreaturePermanent("creature with converted mana cost 3 or less");
static {
filter.add(new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, 4));
}
public TyrantsScorn(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{U}{B}");
// Choose one
// Destroy target creature with converted mana cost 3 or less.
this.getSpellAbility().addEffect(new DestroyTargetEffect());
this.getSpellAbility().addTarget(new TargetPermanent(filter));
// Return target creature to its owner's hand.
Mode mode = new Mode(new ReturnToHandTargetEffect());
mode.addTarget(new TargetCreaturePermanent());
this.getSpellAbility().addMode(mode);
}
private TyrantsScorn(final TyrantsScorn card) {
super(card);
}
@Override
public TyrantsScorn copy() {
return new TyrantsScorn(this);
}
}

View file

@ -0,0 +1,161 @@
package mage.cards.u;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.abilities.effects.common.ReturnToHandTargetEffect;
import mage.abilities.effects.common.cost.SpellsCostReductionControllerEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.FilterCard;
import mage.filter.FilterPermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.ColorlessPredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.Permanent;
import mage.game.permanent.token.Token;
import mage.game.permanent.token.UginTheIneffableToken;
import mage.players.Player;
import mage.target.TargetPermanent;
import mage.target.targetpointer.FixedTarget;
import java.util.UUID;
import static mage.constants.Outcome.Benefit;
/**
* @author TheElk801
*/
public final class UginTheIneffable extends CardImpl {
private static final FilterCard filter = new FilterCard();
private static final FilterPermanent filter2 = new FilterPermanent("permanent that's one or more colors");
static {
filter.add(ColorlessPredicate.instance);
filter2.add(Predicates.not(ColorlessPredicate.instance));
}
public UginTheIneffable(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{6}");
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.UGIN);
this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(4));
// Colorless spells you cast cost {2} less to cast.
this.addAbility(new SimpleStaticAbility(new SpellsCostReductionControllerEffect(
filter, 2
).setText("Colorless spells you cast cost {2} less to cast.")));
// +1: Exile the top card of your library face down and look at it. Create a 2/2 colorless Spirit creature token. When that token leaves the battlefield, put the exiled card into your hand.
this.addAbility(new LoyaltyAbility(new UginTheIneffableEffect(), 1));
// -3: Destroy target permanent that's one or more colors.
Ability ability = new LoyaltyAbility(new DestroyTargetEffect(), -3);
ability.addTarget(new TargetPermanent());
this.addAbility(ability);
}
private UginTheIneffable(final UginTheIneffable card) {
super(card);
}
@Override
public UginTheIneffable copy() {
return new UginTheIneffable(this);
}
}
class UginTheIneffableEffect extends OneShotEffect {
UginTheIneffableEffect() {
super(Benefit);
staticText = "Exile the top card of your library face down and look at it. " +
"Create a 2/2 colorless Spirit creature token. When that token leaves the battlefield, " +
"put the exiled card into your hand.";
}
private UginTheIneffableEffect(final UginTheIneffableEffect effect) {
super(effect);
}
@Override
public UginTheIneffableEffect copy() {
return new UginTheIneffableEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId());
Player player = game.getPlayer(source.getControllerId());
if (player == null) {
return false;
}
Card card = player.getLibrary().getFromTop(game);
player.lookAtCards(sourcePermanent.getIdName(), card, game);
player.moveCards(card, Zone.EXILED, source, game);
card.turnFaceDown(game, source.getControllerId());
Token token = new UginTheIneffableToken();
token.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId());
game.addDelayedTriggeredAbility(new UginTheIneffableDelayedTriggeredAbility(
new MageObjectReference(token.getLastAddedToken(), game), new MageObjectReference(card, game)
), source);
return true;
}
}
class UginTheIneffableDelayedTriggeredAbility extends DelayedTriggeredAbility {
private final MageObjectReference tokenRef;
private final MageObjectReference cardRef;
UginTheIneffableDelayedTriggeredAbility(MageObjectReference token, MageObjectReference card) {
super(null, Duration.Custom, true);
this.tokenRef = token;
this.cardRef = card;
}
private UginTheIneffableDelayedTriggeredAbility(final UginTheIneffableDelayedTriggeredAbility ability) {
super(ability);
this.tokenRef = ability.tokenRef;
this.cardRef = ability.cardRef;
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ZONE_CHANGE;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (tokenRef.refersTo(((ZoneChangeEvent) event).getTarget(), game)) {
this.getEffects().clear();
Effect effect = new ReturnToHandTargetEffect();
effect.setTargetPointer(new FixedTarget(cardRef));
this.addEffect(effect);
return true;
}
return false;
}
@Override
public UginTheIneffableDelayedTriggeredAbility copy() {
return new UginTheIneffableDelayedTriggeredAbility(this);
}
@Override
public String getRule() {
return "When this token leaves the battlefield, put the exiled card into your hand.";
}
}

View file

@ -0,0 +1,40 @@
package mage.cards.u;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
import mage.abilities.keyword.IndestructibleAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class UnlikelyAid extends CardImpl {
public UnlikelyAid(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{B}");
// Target creature gets +2/+0 and gains indestructible until end of turn.
this.getSpellAbility().addEffect(new BoostTargetEffect(
2, 0, Duration.EndOfTurn
).setText("Target creature gets +2/+0"));
this.getSpellAbility().addEffect(new GainAbilityTargetEffect(
IndestructibleAbility.getInstance(), Duration.EndOfTurn
).setText("and gains indestructable until end of turn"));
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
}
private UnlikelyAid(final UnlikelyAid card) {
super(card);
}
@Override
public UnlikelyAid copy() {
return new UnlikelyAid(this);
}
}

View file

@ -0,0 +1,81 @@
package mage.cards.u;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.SacrificeSourceCost;
import mage.abilities.costs.common.SacrificeTargetCost;
import mage.abilities.costs.mana.ColoredManaCost;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.ColoredManaSymbol;
import mage.constants.SubType;
import mage.filter.FilterCard;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.common.FilterCreatureCard;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.mageobject.NamePredicate;
import mage.filter.predicate.permanent.BlockingAttackerIdPredicate;
import mage.target.common.TargetCardInLibrary;
import mage.target.common.TargetControlledCreaturePermanent;
import mage.target.common.TargetCreaturePermanent;
/**
*
* @author Ketsuban
*/
public class UrborgPanther extends CardImpl {
private static final FilterControlledCreaturePermanent filter1 = new FilterControlledCreaturePermanent("creature named Feral Shadow");
private static final FilterControlledCreaturePermanent filter2 = new FilterControlledCreaturePermanent("creature named Breathstealer");
private static final FilterCard filterCard = new FilterCreatureCard("card named Spirit of the Night");
static {
filter1.add(new NamePredicate("Feral Shadow"));
filter2.add(new NamePredicate("Breathstealer"));
filterCard.add(new NamePredicate("Spirit of the Night"));
}
public UrborgPanther(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[] { CardType.CREATURE }, "{2}{B}");
this.subtype.add(SubType.NIGHTSTALKER);
this.subtype.add(SubType.CAT);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// B, Sacrifice Urborg Panther: Destroy target creature blocking Urborg Panther.
Ability ability1 = new SimpleActivatedAbility(new DestroyTargetEffect(),
new ColoredManaCost(ColoredManaSymbol.B));
ability1.addCost(new SacrificeSourceCost());
FilterCreaturePermanent filter = new FilterCreaturePermanent("creature blocking {this}");
filter.add(new BlockingAttackerIdPredicate(this.getId()));
ability1.addTarget(new TargetCreaturePermanent(filter));
this.addAbility(ability1);
// Sacrifice a creature named Feral Shadow, a creature named Breathstealer, and
// Urborg Panther: Search your library for a card named Spirit of the Night and
// put that card onto the battlefield. Then shuffle your library.
Ability ability2 = new SimpleActivatedAbility(
new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(1, 1, new FilterCard(filterCard))),
new SacrificeTargetCost(new TargetControlledCreaturePermanent(1, 1, filter1, true)));
ability2.addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent(1, 1, filter2, true)));
ability2.addCost(new SacrificeSourceCost());
this.addAbility(ability2);
}
public UrborgPanther(final UrborgPanther card) {
super(card);
}
@Override
public UrborgPanther copy() {
return new UrborgPanther(this);
}
}

View file

@ -0,0 +1,44 @@
package mage.cards.v;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.effects.common.LoseLifeOpponentsEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class VampireOpportunist extends CardImpl {
public VampireOpportunist(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}");
this.subtype.add(SubType.VAMPIRE);
this.power = new MageInt(2);
this.toughness = new MageInt(1);
// {6}{B}: Each opponent loses 2 life and you gain 2 life.
Ability ability = new SimpleActivatedAbility(
new LoseLifeOpponentsEffect(2), new ManaCostsImpl("{6}{B}")
);
ability.addEffect(new GainLifeEffect(2).concatBy("and"));
this.addAbility(ability);
}
private VampireOpportunist(final VampireOpportunist card) {
super(card);
}
@Override
public VampireOpportunist copy() {
return new VampireOpportunist(this);
}
}

View file

@ -1,7 +1,5 @@
package mage.cards.v;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
@ -14,21 +12,27 @@ import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Zone;
import java.util.UUID;
/**
*
* @author North
*/
public final class ViralDrake extends CardImpl {
public ViralDrake(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{U}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}");
this.subtype.add(SubType.DRAKE);
this.power = new MageInt(1);
this.toughness = new MageInt(4);
// Flying
this.addAbility(FlyingAbility.getInstance());
// Infect (This creature deals damage to creatures in the form of -1/-1 counters and to players in the form of poison counters.)
this.addAbility(InfectAbility.getInstance());
// {3}{U}: Proliferate. (You choose any number of permanents and/or players with counters on them, then give each another counter of a kind already there.)
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new ProliferateEffect(), new ManaCostsImpl("{3}{U}")));
}

View file

@ -1,7 +1,5 @@
package mage.cards.v;
import java.util.UUID;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.effects.common.counter.ProliferateEffect;
import mage.cards.CardImpl;
@ -9,19 +7,20 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.target.common.TargetAnyTarget;
import java.util.UUID;
/**
*
* @author North
*/
public final class VoltCharge extends CardImpl {
public VoltCharge(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{R}");
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{R}");
this.getSpellAbility().addTarget(new TargetAnyTarget());
// Volt Charge deals 3 damage to any target. Proliferate. (You choose any number of permanents and/or players with counters on them, then give each another counter of a kind already there.)
this.getSpellAbility().addEffect(new DamageTargetEffect(3));
this.getSpellAbility().addEffect(new ProliferateEffect());
this.getSpellAbility().addTarget(new TargetAnyTarget());
}
public VoltCharge(final VoltCharge card) {

View file

@ -0,0 +1,41 @@
package mage.cards.w;
import mage.MageInt;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.keyword.ScryEffect;
import mage.abilities.keyword.DefenderAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class WallOfRunes extends CardImpl {
public WallOfRunes(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{U}");
this.subtype.add(SubType.WALL);
this.power = new MageInt(0);
this.toughness = new MageInt(4);
// Defender
this.addAbility(DefenderAbility.getInstance());
// When Wall of Runes enters the battlefield, scry 1.
this.addAbility(new EntersBattlefieldTriggeredAbility(new ScryEffect(1)));
}
private WallOfRunes(final WallOfRunes card) {
super(card);
}
@Override
public WallOfRunes copy() {
return new WallOfRunes(this);
}
}

View file

@ -20,10 +20,7 @@ public final class WanderersStrike extends CardImpl {
// Exile target creature, then proliferate.
this.getSpellAbility().addEffect(new ExileTargetEffect());
this.getSpellAbility().addEffect(new ProliferateEffect().setText(
"then proliferate <i>(Choose any number of permanents and/or players, " +
"then give each another counter of each kind already there.)</i>"
));
this.getSpellAbility().addEffect(new ProliferateEffect().concatBy("then"));
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
}

View file

@ -56,9 +56,7 @@ class WidespreadBrutalityEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
AmassEffect amassEffect = new AmassEffect(2);
if (!amassEffect.apply(game, source)) {
return false;
}
amassEffect.apply(game, source);
Permanent amassedArmy = game.getPermanent(amassEffect.getAmassedCreatureId());
if (amassedArmy == null) {
return false;

View file

@ -1,38 +1,33 @@
package mage.cards.w;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.Cost;
import mage.abilities.costs.common.SacrificeTargetCost;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.TargetController;
import mage.constants.Zone;
import mage.constants.*;
import mage.filter.common.FilterControlledLandPermanent;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.game.events.GameEvent;
import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetControlledPermanent;
import java.util.UUID;
/**
*
* @author L_J
*/
public final class WormsOfTheEarth extends CardImpl {
public WormsOfTheEarth(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{B}{B}{B}");
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{B}{B}{B}");
// Players can't play lands.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new WormsOfTheEarthPlayEffect()));
@ -60,7 +55,7 @@ class WormsOfTheEarthPlayEffect extends ContinuousRuleModifyingEffectImpl {
super(Duration.WhileOnBattlefield, Outcome.Neutral);
this.staticText = "Players can't play lands";
}
public WormsOfTheEarthPlayEffect(final WormsOfTheEarthPlayEffect effect) {
super(effect);
}
@ -69,7 +64,7 @@ class WormsOfTheEarthPlayEffect extends ContinuousRuleModifyingEffectImpl {
public WormsOfTheEarthPlayEffect copy() {
return new WormsOfTheEarthPlayEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
return true;
@ -104,7 +99,7 @@ class WormsOfTheEarthEnterEffect extends ContinuousRuleModifyingEffectImpl {
@Override
public boolean checksEventType(GameEvent event, Game game) {
return GameEvent.EventType.ZONE_CHANGE == event.getType();
return event.getType() == GameEvent.EventType.ZONE_CHANGE;
}
@Override
@ -112,9 +107,7 @@ class WormsOfTheEarthEnterEffect extends ContinuousRuleModifyingEffectImpl {
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
if (zEvent.getToZone() == Zone.BATTLEFIELD) {
Card card = game.getCard(zEvent.getTargetId());
if (card != null && card.isLand()) {
return true;
}
return card != null && card.isLand();
}
return false;
}
@ -142,7 +135,7 @@ class WormsOfTheEarthDestroyEffect extends OneShotEffect {
if (player != null) {
if (player.chooseUse(outcome, "Do you want to destroy " + sourcePermanent.getLogName() + "? (sacrifice two lands or have it deal 5 damage to you)", source, game)) {
cost.clearPaid();
if (cost.canPay(source, source.getSourceId(), player.getId(), game)
if (cost.canPay(source, source.getSourceId(), player.getId(), game)
&& player.chooseUse(Outcome.Sacrifice, "Will you sacrifice two lands? (otherwise you'll be dealt 5 damage)", source, game)) {
if (!cost.pay(source, game, source.getSourceId(), player.getId(), false, null)) {
player.damage(5, source.getSourceId(), game, false, true);

View file

@ -83,6 +83,8 @@ public final class Alliances extends ExpansionSet {
cards.add(new SetCardInfo("Fyndhorn Druid", "90a", Rarity.COMMON, mage.cards.f.FyndhornDruid.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Fyndhorn Druid", "90b", Rarity.COMMON, mage.cards.f.FyndhornDruid.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Gargantuan Gorilla", 91, Rarity.RARE, mage.cards.g.GargantuanGorilla.class));
cards.add(new SetCardInfo("Gift of the Woods", "92a", Rarity.COMMON, mage.cards.g.GiftOfTheWoods.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Gift of the Woods", "92b", Rarity.COMMON, mage.cards.g.GiftOfTheWoods.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Gorilla Berserkers", "93a", Rarity.COMMON, mage.cards.g.GorillaBerserkers.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Gorilla Berserkers", "93b", Rarity.COMMON, mage.cards.g.GorillaBerserkers.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Gorilla Chieftain", "94a", Rarity.COMMON, mage.cards.g.GorillaChieftain.class, NON_FULL_USE_VARIOUS));
@ -106,6 +108,8 @@ public final class Alliances extends ExpansionSet {
cards.add(new SetCardInfo("Keeper of Tresserhorn", 52, Rarity.RARE, mage.cards.k.KeeperOfTresserhorn.class));
cards.add(new SetCardInfo("Kjeldoran Escort", "7a", Rarity.COMMON, mage.cards.k.KjeldoranEscort.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Kjeldoran Escort", "7b", Rarity.COMMON, mage.cards.k.KjeldoranEscort.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Kjeldoran Pride", "9a", Rarity.COMMON, mage.cards.k.KjeldoranPride.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Kjeldoran Pride", "9b", Rarity.COMMON, mage.cards.k.KjeldoranPride.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Kjeldoran Home Guard", 8, Rarity.UNCOMMON, mage.cards.k.KjeldoranHomeGuard.class));
cards.add(new SetCardInfo("Kjeldoran Outpost", 139, Rarity.RARE, mage.cards.k.KjeldoranOutpost.class));
cards.add(new SetCardInfo("Krovikan Horror", 53, Rarity.RARE, mage.cards.k.KrovikanHorror.class));
@ -149,6 +153,7 @@ public final class Alliances extends ExpansionSet {
cards.add(new SetCardInfo("Reprisal", "13a", Rarity.COMMON, mage.cards.r.Reprisal.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Reprisal", "13b", Rarity.COMMON, mage.cards.r.Reprisal.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Ritual of the Machine", 59, Rarity.RARE, mage.cards.r.RitualOfTheMachine.class));
cards.add(new SetCardInfo("Rogue Skycaptain", 79, Rarity.RARE, mage.cards.r.RogueSkycaptain.class));
cards.add(new SetCardInfo("Royal Decree", 14, Rarity.RARE, mage.cards.r.RoyalDecree.class));
cards.add(new SetCardInfo("Royal Herbalist", "15a", Rarity.COMMON, mage.cards.r.RoyalHerbalist.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Royal Herbalist", "15b", Rarity.COMMON, mage.cards.r.RoyalHerbalist.class, NON_FULL_USE_VARIOUS));
@ -166,6 +171,8 @@ public final class Alliances extends ExpansionSet {
cards.add(new SetCardInfo("Soldevi Heretic", "33b", Rarity.COMMON, mage.cards.s.SoldeviHeretic.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Soldevi Sage", "34a", Rarity.COMMON, mage.cards.s.SoldeviSage.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Soldevi Sage", "34b", Rarity.COMMON, mage.cards.s.SoldeviSage.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Soldevi Sentry", "132a", Rarity.COMMON, mage.cards.s.SoldeviSentry.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Soldevi Sentry", "132b", Rarity.COMMON, mage.cards.s.SoldeviSentry.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Soldevi Steam Beast", "133a", Rarity.COMMON, mage.cards.s.SoldeviSteamBeast.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Soldevi Steam Beast", "133b", Rarity.COMMON, mage.cards.s.SoldeviSteamBeast.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Soldier of Fortune", 80, Rarity.UNCOMMON, mage.cards.s.SoldierOfFortune.class));

View file

@ -152,7 +152,7 @@ public final class MastersEditionII extends ExpansionSet {
cards.add(new SetCardInfo("Leaping Lizard", 171, Rarity.COMMON, mage.cards.l.LeapingLizard.class));
cards.add(new SetCardInfo("Lim-Dul's High Guard", 103, Rarity.UNCOMMON, mage.cards.l.LimDulsHighGuard.class));
cards.add(new SetCardInfo("Lodestone Bauble", 213, Rarity.RARE, mage.cards.l.LodestoneBauble.class));
cards.add(new SetCardInfo("Lost Order of Jarkeld", 24, Rarity.RARE, mage.cards.l.LostOrderOfJarkeld.class));
cards.add(new SetCardInfo("Lost Order of Jarkeld", 24, Rarity.RARE, mage.cards.l.LostOrderOfJarkeld.class));
cards.add(new SetCardInfo("Magus of the Unseen", 53, Rarity.RARE, mage.cards.m.MagusOfTheUnseen.class));
cards.add(new SetCardInfo("Mana Crypt", 214, Rarity.RARE, mage.cards.m.ManaCrypt.class));
cards.add(new SetCardInfo("Marjhan", 54, Rarity.RARE, mage.cards.m.Marjhan.class));
@ -195,6 +195,7 @@ public final class MastersEditionII extends ExpansionSet {
cards.add(new SetCardInfo("Ritual of Subdual", 174, Rarity.RARE, mage.cards.r.RitualOfSubdual.class));
cards.add(new SetCardInfo("Ritual of the Machine", 109, Rarity.RARE, mage.cards.r.RitualOfTheMachine.class));
cards.add(new SetCardInfo("Roterothopter", 218, Rarity.COMMON, mage.cards.r.Roterothopter.class));
cards.add(new SetCardInfo("Rogue Skycaptain", 149, Rarity.RARE, mage.cards.r.RogueSkycaptain.class));
cards.add(new SetCardInfo("Royal Decree", 31, Rarity.RARE, mage.cards.r.RoyalDecree.class));
cards.add(new SetCardInfo("Royal Trooper", 32, Rarity.COMMON, mage.cards.r.RoyalTrooper.class));
cards.add(new SetCardInfo("Ruins of Trokair", 234, Rarity.UNCOMMON, mage.cards.r.RuinsOfTrokair.class));

View file

@ -279,6 +279,7 @@ public final class Mirage extends ExpansionSet {
cards.add(new SetCardInfo("Soar", 93, Rarity.COMMON, mage.cards.s.Soar.class));
cards.add(new SetCardInfo("Soul Echo", 40, Rarity.RARE, mage.cards.s.SoulEcho.class));
cards.add(new SetCardInfo("Soul Rend", 144, Rarity.UNCOMMON, mage.cards.s.SoulRend.class));
cards.add(new SetCardInfo("Soulshriek", 145, Rarity.COMMON, mage.cards.s.Soulshriek.class));
cards.add(new SetCardInfo("Spectral Guardian", 41, Rarity.RARE, mage.cards.s.SpectralGuardian.class));
cards.add(new SetCardInfo("Spirit of the Night", 146, Rarity.RARE, mage.cards.s.SpiritOfTheNight.class));
cards.add(new SetCardInfo("Spitting Earth", 193, Rarity.COMMON, mage.cards.s.SpittingEarth.class));
@ -314,6 +315,7 @@ public final class Mirage extends ExpansionSet {
cards.add(new SetCardInfo("Unseen Walker", 249, Rarity.UNCOMMON, mage.cards.u.UnseenWalker.class));
cards.add(new SetCardInfo("Unyaro Bee Sting", 250, Rarity.UNCOMMON, mage.cards.u.UnyaroBeeSting.class));
cards.add(new SetCardInfo("Unyaro Griffin", 44, Rarity.UNCOMMON, mage.cards.u.UnyaroGriffin.class));
cards.add(new SetCardInfo("Urborg Panther", 150, Rarity.COMMON, mage.cards.u.UrborgPanther.class));
cards.add(new SetCardInfo("Vaporous Djinn", 101, Rarity.UNCOMMON, mage.cards.v.VaporousDjinn.class));
cards.add(new SetCardInfo("Ventifact Bottle", 323, Rarity.RARE, mage.cards.v.VentifactBottle.class));
cards.add(new SetCardInfo("Viashino Warrior", 200, Rarity.COMMON, mage.cards.v.ViashinoWarrior.class));

View file

@ -43,6 +43,7 @@ public final class Unhinged extends ExpansionSet {
cards.add(new SetCardInfo("Old Fogey", 106, Rarity.RARE, mage.cards.o.OldFogey.class));
cards.add(new SetCardInfo("Plains", 136, Rarity.LAND, mage.cards.basiclands.Plains.class, new CardGraphicInfo(FrameStyle.UNH_FULL_ART_BASIC, false)));
cards.add(new SetCardInfo("Rare-B-Gone", 119, Rarity.RARE, mage.cards.r.RareBGone.class));
cards.add(new SetCardInfo("Rod of Spanking", 127, Rarity.UNCOMMON, mage.cards.r.RodOfSpanking.class));
cards.add(new SetCardInfo("Six-y Beast", 89, Rarity.UNCOMMON, mage.cards.s.SixyBeast.class));
cards.add(new SetCardInfo("Swamp", 138, Rarity.LAND, mage.cards.basiclands.Swamp.class, new CardGraphicInfo(FrameStyle.UNH_FULL_ART_BASIC, false)));
cards.add(new SetCardInfo("Symbol Status", 114, Rarity.UNCOMMON, mage.cards.s.SymbolStatus.class));

View file

@ -99,6 +99,7 @@ public final class Visions extends ExpansionSet {
cards.add(new SetCardInfo("Knight of the Mists", 36, Rarity.COMMON, mage.cards.k.KnightOfTheMists.class));
cards.add(new SetCardInfo("Knight of Valor", 11, Rarity.COMMON, mage.cards.k.KnightOfValor.class));
cards.add(new SetCardInfo("Kookus", 86, Rarity.RARE, mage.cards.k.Kookus.class));
cards.add(new SetCardInfo("Kyscu Drake", 111, Rarity.RARE, mage.cards.k.KyscuDrake.class));
cards.add(new SetCardInfo("Lead-Belly Chimera", 148, Rarity.UNCOMMON, mage.cards.l.LeadBellyChimera.class));
cards.add(new SetCardInfo("Lichenthrope", 112, Rarity.RARE, mage.cards.l.Lichenthrope.class));
cards.add(new SetCardInfo("Lightning Cloud", 87, Rarity.RARE, mage.cards.l.LightningCloud.class));

View file

@ -30,16 +30,20 @@ public final class WarOfTheSpark extends ExpansionSet {
cards.add(new SetCardInfo("Ajani, the Greathearted", 184, Rarity.RARE, mage.cards.a.AjaniTheGreathearted.class));
cards.add(new SetCardInfo("Angrath's Rampage", 185, Rarity.UNCOMMON, mage.cards.a.AngrathsRampage.class));
cards.add(new SetCardInfo("Angrath, Captain of Chaos", 227, Rarity.UNCOMMON, mage.cards.a.AngrathCaptainOfChaos.class));
cards.add(new SetCardInfo("Arboreal Grazer", 149, Rarity.COMMON, mage.cards.a.ArborealGrazer.class));
cards.add(new SetCardInfo("Arlinn's Wolf", 151, Rarity.COMMON, mage.cards.a.ArlinnsWolf.class));
cards.add(new SetCardInfo("Arlinn, Voice of the Pack", 150, Rarity.UNCOMMON, mage.cards.a.ArlinnVoiceOfThePack.class));
cards.add(new SetCardInfo("Ashiok's Skulker", 40, Rarity.COMMON, mage.cards.a.AshioksSkulker.class));
cards.add(new SetCardInfo("Ashiok, Dream Render", 228, Rarity.UNCOMMON, mage.cards.a.AshiokDreamRender.class));
cards.add(new SetCardInfo("Augur of Bolas", 41, Rarity.UNCOMMON, mage.cards.a.AugurOfBolas.class));
cards.add(new SetCardInfo("Aven Eternal", 42, Rarity.COMMON, mage.cards.a.AvenEternal.class));
cards.add(new SetCardInfo("Awakening of Vitu-Ghazi", 152, Rarity.RARE, mage.cards.a.AwakeningOfVituGhazi.class));
cards.add(new SetCardInfo("Band Together", 153, Rarity.COMMON, mage.cards.b.BandTogether.class));
cards.add(new SetCardInfo("Banehound", 77, Rarity.COMMON, mage.cards.b.Banehound.class));
cards.add(new SetCardInfo("Battlefield Promotion", 5, Rarity.COMMON, mage.cards.b.BattlefieldPromotion.class));
cards.add(new SetCardInfo("Bioessence Hydra", 186, Rarity.RARE, mage.cards.b.BioessenceHydra.class));
cards.add(new SetCardInfo("Blast Zone", 244, Rarity.RARE, mage.cards.b.BlastZone.class));
cards.add(new SetCardInfo("Bleeding Edge", 78, Rarity.UNCOMMON, mage.cards.b.BleedingEdge.class));
cards.add(new SetCardInfo("Blindblast", 114, Rarity.COMMON, mage.cards.b.Blindblast.class));
cards.add(new SetCardInfo("Bloom Hulk", 154, Rarity.COMMON, mage.cards.b.BloomHulk.class));
cards.add(new SetCardInfo("Bolas's Citadel", 79, Rarity.RARE, mage.cards.b.BolassCitadel.class));
@ -51,6 +55,7 @@ public final class WarOfTheSpark extends ExpansionSet {
cards.add(new SetCardInfo("Bond of Revival", 80, Rarity.UNCOMMON, mage.cards.b.BondOfRevival.class));
cards.add(new SetCardInfo("Bulwark Giant", 7, Rarity.COMMON, mage.cards.b.BulwarkGiant.class));
cards.add(new SetCardInfo("Burning Prophet", 117, Rarity.COMMON, mage.cards.b.BurningProphet.class));
cards.add(new SetCardInfo("Callous Dismissal", 44, Rarity.COMMON, mage.cards.c.CallousDismissal.class));
cards.add(new SetCardInfo("Casualties of War", 187, Rarity.RARE, mage.cards.c.CasualtiesOfWar.class));
cards.add(new SetCardInfo("Centaur Nurturer", 156, Rarity.COMMON, mage.cards.c.CentaurNurturer.class));
cards.add(new SetCardInfo("Chainwhip Cyclops", 118, Rarity.COMMON, mage.cards.c.ChainwhipCyclops.class));
@ -58,6 +63,8 @@ public final class WarOfTheSpark extends ExpansionSet {
cards.add(new SetCardInfo("Chandra's Pyrohelix", 120, Rarity.COMMON, mage.cards.c.ChandrasPyrohelix.class));
cards.add(new SetCardInfo("Chandra's Triumph", 121, Rarity.UNCOMMON, mage.cards.c.ChandrasTriumph.class));
cards.add(new SetCardInfo("Chandra, Fire Artisan", 119, Rarity.RARE, mage.cards.c.ChandraFireArtisan.class));
cards.add(new SetCardInfo("Charity Extractor", 81, Rarity.COMMON, mage.cards.c.CharityExtractor.class));
cards.add(new SetCardInfo("Charmed Stray", 8, Rarity.COMMON, mage.cards.c.CharmedStray.class));
cards.add(new SetCardInfo("Command the Dreadhorde", 82, Rarity.RARE, mage.cards.c.CommandTheDreadhorde.class));
cards.add(new SetCardInfo("Commence the Endgame", 45, Rarity.RARE, mage.cards.c.CommenceTheEndgame.class));
cards.add(new SetCardInfo("Contentious Plan", 46, Rarity.COMMON, mage.cards.c.ContentiousPlan.class));
@ -71,8 +78,10 @@ public final class WarOfTheSpark extends ExpansionSet {
cards.add(new SetCardInfo("Defiant Strike", 9, Rarity.COMMON, mage.cards.d.DefiantStrike.class));
cards.add(new SetCardInfo("Deliver Unto Evil", 85, Rarity.RARE, mage.cards.d.DeliverUntoEvil.class));
cards.add(new SetCardInfo("Demolish", 123, Rarity.COMMON, mage.cards.d.Demolish.class));
cards.add(new SetCardInfo("Despark", 190, Rarity.UNCOMMON, mage.cards.d.Despark.class));
cards.add(new SetCardInfo("Desperate Lunge", 266, Rarity.COMMON, mage.cards.d.DesperateLunge.class));
cards.add(new SetCardInfo("Devouring Hellion", 124, Rarity.UNCOMMON, mage.cards.d.DevouringHellion.class));
cards.add(new SetCardInfo("Divine Arrow", 10, Rarity.COMMON, mage.cards.d.DivineArrow.class));
cards.add(new SetCardInfo("Domri's Ambush", 192, Rarity.UNCOMMON, mage.cards.d.DomrisAmbush.class));
cards.add(new SetCardInfo("Domri, Anarch of Bolas", 191, Rarity.RARE, mage.cards.d.DomriAnarchOfBolas.class));
cards.add(new SetCardInfo("Dovin's Veto", 193, Rarity.UNCOMMON, mage.cards.d.DovinsVeto.class));
@ -81,7 +90,11 @@ public final class WarOfTheSpark extends ExpansionSet {
cards.add(new SetCardInfo("Dreadhorde Butcher", 194, Rarity.RARE, mage.cards.d.DreadhordeButcher.class));
cards.add(new SetCardInfo("Dreadhorde Invasion", 86, Rarity.RARE, mage.cards.d.DreadhordeInvasion.class));
cards.add(new SetCardInfo("Dreadhorde Twins", 126, Rarity.UNCOMMON, mage.cards.d.DreadhordeTwins.class));
cards.add(new SetCardInfo("Dreadmalkin", 87, Rarity.UNCOMMON, mage.cards.d.Dreadmalkin.class));
cards.add(new SetCardInfo("Duskmantle Operative", 88, Rarity.COMMON, mage.cards.d.DuskmantleOperative.class));
cards.add(new SetCardInfo("Elite Guardmage", 195, Rarity.UNCOMMON, mage.cards.e.EliteGuardmage.class));
cards.add(new SetCardInfo("Emergence Zone", 245, Rarity.UNCOMMON, mage.cards.e.EmergenceZone.class));
cards.add(new SetCardInfo("Enforcer Griffin", 11, Rarity.COMMON, mage.cards.e.EnforcerGriffin.class));
cards.add(new SetCardInfo("Enter the God-Eternals", 196, Rarity.RARE, mage.cards.e.EnterTheGodEternals.class));
cards.add(new SetCardInfo("Erratic Visionary", 48, Rarity.COMMON, mage.cards.e.ErraticVisionary.class));
cards.add(new SetCardInfo("Eternal Skylord", 49, Rarity.UNCOMMON, mage.cards.e.EternalSkylord.class));
@ -90,6 +103,7 @@ public final class WarOfTheSpark extends ExpansionSet {
cards.add(new SetCardInfo("Fblthp, the Lost", 50, Rarity.RARE, mage.cards.f.FblthpTheLost.class));
cards.add(new SetCardInfo("Feather, the Redeemed", 197, Rarity.RARE, mage.cards.f.FeatherTheRedeemed.class));
cards.add(new SetCardInfo("Finale of Devastation", 160, Rarity.MYTHIC, mage.cards.f.FinaleOfDevastation.class));
cards.add(new SetCardInfo("Finale of Eternity", 91, Rarity.MYTHIC, mage.cards.f.FinaleOfEternity.class));
cards.add(new SetCardInfo("Finale of Glory", 12, Rarity.MYTHIC, mage.cards.f.FinaleOfGlory.class));
cards.add(new SetCardInfo("Finale of Revelation", 51, Rarity.MYTHIC, mage.cards.f.FinaleOfRevelation.class));
cards.add(new SetCardInfo("Firemind Vessel", 237, Rarity.UNCOMMON, mage.cards.f.FiremindVessel.class));
@ -98,21 +112,27 @@ public final class WarOfTheSpark extends ExpansionSet {
cards.add(new SetCardInfo("Forest", 262, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Forest", 263, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Forest", 264, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Gateway Plaza", 246, Rarity.COMMON, mage.cards.g.GatewayPlaza.class));
cards.add(new SetCardInfo("Giant Growth", 162, Rarity.COMMON, mage.cards.g.GiantGrowth.class));
cards.add(new SetCardInfo("Gideon Blackblade", 13, Rarity.MYTHIC, mage.cards.g.GideonBlackblade.class));
cards.add(new SetCardInfo("Gideon's Battle Cry", 267, Rarity.RARE, mage.cards.g.GideonsBattleCry.class));
cards.add(new SetCardInfo("Gideon's Company", 268, Rarity.UNCOMMON, mage.cards.g.GideonsCompany.class));
cards.add(new SetCardInfo("Gideon's Sacrifice", 14, Rarity.COMMON, mage.cards.g.GideonsSacrifice.class));
cards.add(new SetCardInfo("Gideon's Triumph", 15, Rarity.UNCOMMON, mage.cards.g.GideonsTriumph.class));
cards.add(new SetCardInfo("Gideon, the Oathsworn", 265, Rarity.MYTHIC, mage.cards.g.GideonTheOathsworn.class));
cards.add(new SetCardInfo("Gleaming Overseer", 198, Rarity.UNCOMMON, mage.cards.g.GleamingOverseer.class));
cards.add(new SetCardInfo("Goblin Assailant", 128, Rarity.COMMON, mage.cards.g.GoblinAssailant.class));
cards.add(new SetCardInfo("Goblin Assault Team", 129, Rarity.COMMON, mage.cards.g.GoblinAssaultTeam.class));
cards.add(new SetCardInfo("God-Eternal Bontu", 92, Rarity.MYTHIC, mage.cards.g.GodEternalBontu.class));
cards.add(new SetCardInfo("God-Eternal Oketra", 16, Rarity.MYTHIC, mage.cards.g.GodEternalOketra.class));
cards.add(new SetCardInfo("God-Eternal Rhonas", 163, Rarity.MYTHIC, mage.cards.g.GodEternalRhonas.class));
cards.add(new SetCardInfo("God-Pharaoh's Statue", 238, Rarity.UNCOMMON, mage.cards.g.GodPharaohsStatue.class));
cards.add(new SetCardInfo("Grateful Apparition", 17, Rarity.UNCOMMON, mage.cards.g.GratefulApparition.class));
cards.add(new SetCardInfo("Grim Initiate", 130, Rarity.COMMON, mage.cards.g.GrimInitiate.class));
cards.add(new SetCardInfo("Guild Globe", 239, Rarity.COMMON, mage.cards.g.GuildGlobe.class));
cards.add(new SetCardInfo("Guildpact Informant", 271, Rarity.COMMON, mage.cards.g.GuildpactInformant.class));
cards.add(new SetCardInfo("Heartfire", 131, Rarity.COMMON, mage.cards.h.Heartfire.class));
cards.add(new SetCardInfo("Heartwarming Redemption", 199, Rarity.UNCOMMON, mage.cards.h.HeartwarmingRedemption.class));
cards.add(new SetCardInfo("Herald of the Dreadhorde", 93, Rarity.COMMON, mage.cards.h.HeraldOfTheDreadhorde.class));
cards.add(new SetCardInfo("Honor the God-Pharaoh", 132, Rarity.COMMON, mage.cards.h.HonorTheGodPharaoh.class));
cards.add(new SetCardInfo("Huatli's Raptor", 200, Rarity.UNCOMMON, mage.cards.h.HuatlisRaptor.class));
@ -123,6 +143,7 @@ public final class WarOfTheSpark extends ExpansionSet {
cards.add(new SetCardInfo("Invade the City", 201, Rarity.UNCOMMON, mage.cards.i.InvadeTheCity.class));
cards.add(new SetCardInfo("Invading Manticore", 134, Rarity.COMMON, mage.cards.i.InvadingManticore.class));
cards.add(new SetCardInfo("Iron Bully", 240, Rarity.COMMON, mage.cards.i.IronBully.class));
cards.add(new SetCardInfo("Ironclad Krovod", 19, Rarity.COMMON, mage.cards.i.IroncladKrovod.class));
cards.add(new SetCardInfo("Island", 253, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Island", 254, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Island", 255, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS));
@ -142,6 +163,7 @@ public final class WarOfTheSpark extends ExpansionSet {
cards.add(new SetCardInfo("Kaya, Bane of the Dead", 231, Rarity.UNCOMMON, mage.cards.k.KayaBaneOfTheDead.class));
cards.add(new SetCardInfo("Kiora's Dambreaker", 58, Rarity.COMMON, mage.cards.k.KiorasDambreaker.class));
cards.add(new SetCardInfo("Kiora, Behemoth Beckoner", 232, Rarity.UNCOMMON, mage.cards.k.KioraBehemothBeckoner.class));
cards.add(new SetCardInfo("Kraul Stinger", 165, Rarity.COMMON, mage.cards.k.KraulStinger.class));
cards.add(new SetCardInfo("Krenko, Tin Street Kingpin", 137, Rarity.RARE, mage.cards.k.KrenkoTinStreetKingpin.class));
cards.add(new SetCardInfo("Kronch Wrangler", 166, Rarity.COMMON, mage.cards.k.KronchWrangler.class));
cards.add(new SetCardInfo("Law-Rune Enforcer", 20, Rarity.COMMON, mage.cards.l.LawRuneEnforcer.class));
@ -154,6 +176,7 @@ public final class WarOfTheSpark extends ExpansionSet {
cards.add(new SetCardInfo("Living Twister", 203, Rarity.RARE, mage.cards.l.LivingTwister.class));
cards.add(new SetCardInfo("Loxodon Sergeant", 21, Rarity.COMMON, mage.cards.l.LoxodonSergeant.class));
cards.add(new SetCardInfo("Makeshift Battalion", 22, Rarity.COMMON, mage.cards.m.MakeshiftBattalion.class));
cards.add(new SetCardInfo("Mana Geode", 241, Rarity.COMMON, mage.cards.m.ManaGeode.class));
cards.add(new SetCardInfo("Martyr for the Cause", 23, Rarity.COMMON, mage.cards.m.MartyrForTheCause.class));
cards.add(new SetCardInfo("Massacre Girl", 99, Rarity.RARE, mage.cards.m.MassacreGirl.class));
cards.add(new SetCardInfo("Mayhem Devil", 204, Rarity.UNCOMMON, mage.cards.m.MayhemDevil.class));
@ -167,13 +190,17 @@ public final class WarOfTheSpark extends ExpansionSet {
cards.add(new SetCardInfo("Naga Eternal", 60, Rarity.COMMON, mage.cards.n.NagaEternal.class));
cards.add(new SetCardInfo("Nahiri's Stoneblades", 139, Rarity.COMMON, mage.cards.n.NahirisStoneblades.class));
cards.add(new SetCardInfo("Nahiri, Storm of Stone", 233, Rarity.UNCOMMON, mage.cards.n.NahiriStormOfStone.class));
cards.add(new SetCardInfo("Narset's Reversal", 62, Rarity.RARE, mage.cards.n.NarsetsReversal.class));
cards.add(new SetCardInfo("Narset, Parter of Veils", 61, Rarity.UNCOMMON, mage.cards.n.NarsetParterOfVeils.class));
cards.add(new SetCardInfo("Neheb, Dreadhorde Champion", 140, Rarity.RARE, mage.cards.n.NehebDreadhordeChampion.class));
cards.add(new SetCardInfo("Neoform", 206, Rarity.UNCOMMON, mage.cards.n.Neoform.class));
cards.add(new SetCardInfo("New Horizons", 168, Rarity.COMMON, mage.cards.n.NewHorizons.class));
cards.add(new SetCardInfo("Nicol Bolas, Dragon-God", 207, Rarity.MYTHIC, mage.cards.n.NicolBolasDragonGod.class));
cards.add(new SetCardInfo("Nissa's Triumph", 170, Rarity.UNCOMMON, mage.cards.n.NissasTriumph.class));
cards.add(new SetCardInfo("Nissa, Who Shakes the World", 169, Rarity.RARE, mage.cards.n.NissaWhoShakesTheWorld.class));
cards.add(new SetCardInfo("Niv-Mizzet Reborn", 208, Rarity.MYTHIC, mage.cards.n.NivMizzetReborn.class));
cards.add(new SetCardInfo("No Escape", 63, Rarity.COMMON, mage.cards.n.NoEscape.class));
cards.add(new SetCardInfo("Oath of Kaya", 209, Rarity.RARE, mage.cards.o.OathOfKaya.class));
cards.add(new SetCardInfo("Ob Nixilis's Cruelty", 101, Rarity.COMMON, mage.cards.o.ObNixilissCruelty.class));
cards.add(new SetCardInfo("Ob Nixilis, the Hate-Twisted", 100, Rarity.UNCOMMON, mage.cards.o.ObNixilisTheHateTwisted.class));
cards.add(new SetCardInfo("Orzhov Guildgate", 269, Rarity.COMMON, mage.cards.o.OrzhovGuildgate.class));
@ -182,10 +209,14 @@ public final class WarOfTheSpark extends ExpansionSet {
cards.add(new SetCardInfo("Plains", 250, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Plains", 251, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Plains", 252, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Planewide Celebration", 172, Rarity.RARE, mage.cards.p.PlanewideCelebration.class));
cards.add(new SetCardInfo("Pledge of Unity", 210, Rarity.UNCOMMON, mage.cards.p.PledgeOfUnity.class));
cards.add(new SetCardInfo("Pollenbright Druid", 173, Rarity.COMMON, mage.cards.p.PollenbrightDruid.class));
cards.add(new SetCardInfo("Pouncing Lynx", 25, Rarity.COMMON, mage.cards.p.PouncingLynx.class));
cards.add(new SetCardInfo("Price of Betrayal", 102, Rarity.UNCOMMON, mage.cards.p.PriceOfBetrayal.class));
cards.add(new SetCardInfo("Primordial Wurm", 174, Rarity.COMMON, mage.cards.p.PrimordialWurm.class));
cards.add(new SetCardInfo("Prismite", 242, Rarity.COMMON, mage.cards.p.Prismite.class));
cards.add(new SetCardInfo("Prison Realm", 26, Rarity.UNCOMMON, mage.cards.p.PrisonRealm.class));
cards.add(new SetCardInfo("Raging Kronch", 141, Rarity.COMMON, mage.cards.r.RagingKronch.class));
cards.add(new SetCardInfo("Ral's Outburst", 212, Rarity.UNCOMMON, mage.cards.r.RalsOutburst.class));
cards.add(new SetCardInfo("Ral, Storm Conduit", 211, Rarity.RARE, mage.cards.r.RalStormConduit.class));
@ -193,17 +224,23 @@ public final class WarOfTheSpark extends ExpansionSet {
cards.add(new SetCardInfo("Ravnica at War", 28, Rarity.RARE, mage.cards.r.RavnicaAtWar.class));
cards.add(new SetCardInfo("Relentless Advance", 64, Rarity.COMMON, mage.cards.r.RelentlessAdvance.class));
cards.add(new SetCardInfo("Rescuer Sphinx", 65, Rarity.UNCOMMON, mage.cards.r.RescuerSphinx.class));
cards.add(new SetCardInfo("Return to Nature", 175, Rarity.COMMON, mage.cards.r.ReturnToNature.class));
cards.add(new SetCardInfo("Rising Populace", 29, Rarity.COMMON, mage.cards.r.RisingPopulace.class));
cards.add(new SetCardInfo("Roalesk, Apex Hybrid", 213, Rarity.MYTHIC, mage.cards.r.RoaleskApexHybrid.class));
cards.add(new SetCardInfo("Role Reversal", 214, Rarity.RARE, mage.cards.r.RoleReversal.class));
cards.add(new SetCardInfo("Rubblebelt Rioters", 215, Rarity.UNCOMMON, mage.cards.r.RubblebeltRioters.class));
cards.add(new SetCardInfo("Saheeli's Silverwing", 243, Rarity.COMMON, mage.cards.s.SaheelisSilverwing.class));
cards.add(new SetCardInfo("Saheeli, Sublime Artificer", 234, Rarity.UNCOMMON, mage.cards.s.SaheeliSublimeArtificer.class));
cards.add(new SetCardInfo("Samut's Sprint", 142, Rarity.COMMON, mage.cards.s.SamutsSprint.class));
cards.add(new SetCardInfo("Samut, Tyrant Smasher", 235, Rarity.UNCOMMON, mage.cards.s.SamutTyrantSmasher.class));
cards.add(new SetCardInfo("Sarkhan the Masterless", 143, Rarity.RARE, mage.cards.s.SarkhanTheMasterless.class));
cards.add(new SetCardInfo("Sarkhan's Catharsis", 144, Rarity.COMMON, mage.cards.s.SarkhansCatharsis.class));
cards.add(new SetCardInfo("Shriekdiver", 103, Rarity.COMMON, mage.cards.s.Shriekdiver.class));
cards.add(new SetCardInfo("Silent Submersible", 66, Rarity.RARE, mage.cards.s.SilentSubmersible.class));
cards.add(new SetCardInfo("Simic Guildgate", 274, Rarity.COMMON, mage.cards.s.SimicGuildgate.class));
cards.add(new SetCardInfo("Single Combat", 30, Rarity.RARE, mage.cards.s.SingleCombat.class));
cards.add(new SetCardInfo("Sky Theater Strix", 67, Rarity.COMMON, mage.cards.s.SkyTheaterStrix.class));
cards.add(new SetCardInfo("Snarespinner", 176, Rarity.COMMON, mage.cards.s.Snarespinner.class));
cards.add(new SetCardInfo("Solar Blaze", 216, Rarity.RARE, mage.cards.s.SolarBlaze.class));
cards.add(new SetCardInfo("Sorin's Thirst", 104, Rarity.COMMON, mage.cards.s.SorinsThirst.class));
cards.add(new SetCardInfo("Sorin, Vengeful Bloodlord", 217, Rarity.RARE, mage.cards.s.SorinVengefulBloodlord.class));
@ -230,23 +267,31 @@ public final class WarOfTheSpark extends ExpansionSet {
cards.add(new SetCardInfo("Tezzeret, Master of the Bridge", 275, Rarity.MYTHIC, mage.cards.t.TezzeretMasterOfTheBridge.class));
cards.add(new SetCardInfo("The Elderspell", 89, Rarity.RARE, mage.cards.t.TheElderspell.class));
cards.add(new SetCardInfo("The Wanderer", 37, Rarity.UNCOMMON, mage.cards.t.TheWanderer.class));
cards.add(new SetCardInfo("Thunder Drake", 73, Rarity.COMMON, mage.cards.t.ThunderDrake.class));
cards.add(new SetCardInfo("Thundering Ceratok", 179, Rarity.COMMON, mage.cards.t.ThunderingCeratok.class));
cards.add(new SetCardInfo("Tibalt's Rager", 147, Rarity.UNCOMMON, mage.cards.t.TibaltsRager.class));
cards.add(new SetCardInfo("Tibalt, Rakish Instigator", 146, Rarity.UNCOMMON, mage.cards.t.TibaltRakishInstigator.class));
cards.add(new SetCardInfo("Time Wipe", 223, Rarity.RARE, mage.cards.t.TimeWipe.class));
cards.add(new SetCardInfo("Tithebearer Giant", 107, Rarity.COMMON, mage.cards.t.TithebearerGiant.class));
cards.add(new SetCardInfo("Toll of the Invasion", 108, Rarity.COMMON, mage.cards.t.TollOfTheInvasion.class));
cards.add(new SetCardInfo("Tolsimir, Friend to Wolves", 224, Rarity.RARE, mage.cards.t.TolsimirFriendToWolves.class));
cards.add(new SetCardInfo("Tomik, Distinguished Advokist", 34, Rarity.RARE, mage.cards.t.TomikDistinguishedAdvokist.class));
cards.add(new SetCardInfo("Topple the Statue", 35, Rarity.COMMON, mage.cards.t.ToppleTheStatue.class));
cards.add(new SetCardInfo("Totally Lost", 74, Rarity.COMMON, mage.cards.t.TotallyLost.class));
cards.add(new SetCardInfo("Trusted Pegasus", 36, Rarity.COMMON, mage.cards.t.TrustedPegasus.class));
cards.add(new SetCardInfo("Turret Ogre", 148, Rarity.COMMON, mage.cards.t.TurretOgre.class));
cards.add(new SetCardInfo("Tyrant's Scorn", 225, Rarity.UNCOMMON, mage.cards.t.TyrantsScorn.class));
cards.add(new SetCardInfo("Ugin's Conjurant", 3, Rarity.UNCOMMON, mage.cards.u.UginsConjurant.class));
cards.add(new SetCardInfo("Ugin, the Ineffable", 2, Rarity.RARE, mage.cards.u.UginTheIneffable.class));
cards.add(new SetCardInfo("Unlikely Aid", 109, Rarity.COMMON, mage.cards.u.UnlikelyAid.class));
cards.add(new SetCardInfo("Vampire Opportunist", 110, Rarity.COMMON, mage.cards.v.VampireOpportunist.class));
cards.add(new SetCardInfo("Vivien's Arkbow", 181, Rarity.RARE, mage.cards.v.ViviensArkbow.class));
cards.add(new SetCardInfo("Vivien's Grizzly", 182, Rarity.COMMON, mage.cards.v.ViviensGrizzly.class));
cards.add(new SetCardInfo("Vivien, Champion of the Wilds", 180, Rarity.RARE, mage.cards.v.VivienChampionOfTheWilds.class));
cards.add(new SetCardInfo("Vizier of the Scorpion", 111, Rarity.UNCOMMON, mage.cards.v.VizierOfTheScorpion.class));
cards.add(new SetCardInfo("Vraska's Finisher", 112, Rarity.COMMON, mage.cards.v.VraskasFinisher.class));
cards.add(new SetCardInfo("Vraska, Swarm's Eminence", 236, Rarity.UNCOMMON, mage.cards.v.VraskaSwarmsEminence.class));
cards.add(new SetCardInfo("Wall of Runes", 75, Rarity.COMMON, mage.cards.w.WallOfRunes.class));
cards.add(new SetCardInfo("Wanderer's Strike", 38, Rarity.COMMON, mage.cards.w.WanderersStrike.class));
cards.add(new SetCardInfo("War Screecher", 39, Rarity.COMMON, mage.cards.w.WarScreecher.class));
cards.add(new SetCardInfo("Wardscale Crocodile", 183, Rarity.COMMON, mage.cards.w.WardscaleCrocodile.class));

View file

@ -602,7 +602,7 @@ public class VerifyCardDataTest {
//checkNumbers(card, ref); // TODO: load data from allsets.json and check it (allcards.json do not have card numbers)
checkBasicLands(card, ref);
checkMissingAbilities(card, ref);
//checkWrongCosts(card, ref);
checkWrongAbilitiesText(card, ref);
}
private void checkColors(Card card, JsonCard ref) {
@ -734,13 +734,23 @@ public class VerifyCardDataTest {
card.getRules().stream().forEach(System.out::println);
}
private void checkWrongCosts(Card card, JsonCard ref) {
// checks missing or wrong cost
if (!card.getExpansionSetCode().equals("RNA")) {
private void checkWrongAbilitiesText(Card card, JsonCard ref) {
// checks missing or wrong text
if (!card.getExpansionSetCode().equals("WAR")) {
return;
}
String[] refRules = ref.text.split("[\\$\\\n]"); // ref card's abilities can be splited by \n or $ chars
if (ref.text == null || ref.text.isEmpty()) {
return;
}
String refText = ref.text;
// lands fix
if (refText.startsWith("(") && refText.endsWith(")")) {
refText = refText.substring(1, refText.length() - 1);
}
String[] refRules = refText.split("[\\$\\\n]"); // ref card's abilities can be splited by \n or $ chars
for (int i = 0; i < refRules.length; i++) {
refRules[i] = prepareRule(card.getName(), refRules[i]);
}
@ -752,17 +762,15 @@ public class VerifyCardDataTest {
for (String cardRule : cardRules) {
boolean isAbilityFounded = false;
boolean isCostOk = false;
for (String refRule : refRules) {
if (cardRule.equals(refRule)) {
isAbilityFounded = true;
isCostOk = true;
break;
}
}
if (!isCostOk) {
fail(card, "abilities", "card ability have cost, but can't find in ref [" + "xxx" + ": " + card.getRules() + "]");
if (!isAbilityFounded) {
warn(card, "card ability can't be found in ref [" + card.getName() + ": " + cardRule + "]");
}
}
}

View file

@ -335,26 +335,31 @@ public class Modes extends LinkedHashMap<UUID, Mode> {
if (this.getMaxModesFilter() != null) {
sb.append("choose one or more. Each mode must target ").append(getMaxModesFilter().getMessage());
} else if (this.getMinModes() == 0 && this.getMaxModes() == 1) {
sb.append("choose up to one ");
sb.append("choose up to one");
} else if (this.getMinModes() == 1 && this.getMaxModes() > 2) {
sb.append("choose one or more ");
sb.append("choose one or more");
} else if (this.getMinModes() == 1 && this.getMaxModes() == 2) {
sb.append("choose one or both ");
sb.append("choose one or both");
} else if (this.getMinModes() == 2 && this.getMaxModes() == 2) {
sb.append("choose two ");
sb.append("choose two");
} else if (this.getMinModes() == 3 && this.getMaxModes() == 3) {
sb.append("choose three ");
sb.append("choose three");
} else if (this.getMinModes() == 4 && this.getMaxModes() == 4) {
sb.append("choose four");
} else {
sb.append("choose one ");
sb.append("choose one");
}
if (isEachModeOnlyOnce()) {
sb.append("that hasn't been chosen ");
sb.append(" that hasn't been chosen");
}
if (isEachModeMoreThanOnce()) {
sb.append(". You may choose the same mode more than once.<br>");
} else {
sb.append("&mdash;<br>");
sb.append(" &mdash;<br>");
}
for (Mode mode : this.values()) {
sb.append("&bull ");
sb.append(mode.getEffects().getTextStartingUpperCase(mode));

View file

@ -1,4 +1,3 @@
package mage.abilities.common;
import mage.MageObjectReference;
@ -28,10 +27,12 @@ public class GodEternalDiesTriggeredAbility extends TriggeredAbilityImpl {
@Override
public boolean checkEventType(GameEvent event, Game game) {
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
return zEvent.getFromZone() == Zone.BATTLEFIELD
&& (zEvent.getToZone() == Zone.GRAVEYARD
|| zEvent.getToZone() == Zone.EXILED);
if (event.getType() == GameEvent.EventType.ZONE_CHANGE) {
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
return zEvent.getFromZone() == Zone.BATTLEFIELD
&& (zEvent.getToZone() == Zone.GRAVEYARD || zEvent.getToZone() == Zone.EXILED);
}
return false;
}
@Override

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