Merge pull request #1 from magefree/master

up to date
This commit is contained in:
Oleg Agafonov 2017-11-10 23:46:48 +04:00 committed by GitHub
commit 39ae4d6562
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
227 changed files with 13282 additions and 1121 deletions

2
.gitignore vendored
View file

@ -44,6 +44,7 @@ Mage.Server.Plugins/Mage.Game.CommanderDuel/target
Mage.Server.Plugins/Mage.Game.CommanderFreeForAll/target/ Mage.Server.Plugins/Mage.Game.CommanderFreeForAll/target/
Mage.Server.Plugins/Mage.Game.FreeForAll/target Mage.Server.Plugins/Mage.Game.FreeForAll/target
Mage.Server.Plugins/Mage.Game.MomirDuel/target Mage.Server.Plugins/Mage.Game.MomirDuel/target
Mage.Server.Plugins/Mage.Game.MomirGame/target/
Mage.Server.Plugins/Mage.Game.PennyDreadfulCommanderFreeForAll/target Mage.Server.Plugins/Mage.Game.PennyDreadfulCommanderFreeForAll/target
Mage.Server.Plugins/Mage.Game.TinyLeadersDuel/target Mage.Server.Plugins/Mage.Game.TinyLeadersDuel/target
Mage.Server.Plugins/Mage.Game.TwoPlayerDuel/target Mage.Server.Plugins/Mage.Game.TwoPlayerDuel/target
@ -132,3 +133,4 @@ Mage.Client/serverlist.txt
client_secrets.json client_secrets.json
dependency-reduced-pom.xml dependency-reduced-pom.xml
mage-bundle

View file

@ -5,19 +5,6 @@
*/ */
package org.mage.card.arcane; package org.mage.card.arcane;
import mage.ObjectColor;
import mage.cards.ArtRect;
import mage.cards.FrameStyle;
import mage.client.dialog.PreferencesDialog;
import mage.constants.CardType;
import mage.constants.MageObjectType;
import mage.constants.SubType;
import mage.util.SubTypeList;
import mage.view.CardView;
import mage.view.PermanentView;
import org.apache.log4j.Logger;
import javax.swing.*;
import java.awt.*; import java.awt.*;
import java.awt.font.*; import java.awt.font.*;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
@ -31,6 +18,18 @@ import java.text.CharacterIterator;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import javax.swing.*;
import mage.ObjectColor;
import mage.cards.ArtRect;
import mage.cards.FrameStyle;
import mage.client.dialog.PreferencesDialog;
import mage.constants.CardType;
import mage.constants.MageObjectType;
import mage.constants.SubType;
import mage.util.SubTypeList;
import mage.view.CardView;
import mage.view.PermanentView;
import org.apache.log4j.Logger;
/* /*
@ -77,9 +76,9 @@ public class ModernCardRenderer extends CardRenderer {
} }
private static Font loadFont(String name) { private static Font loadFont(String name) {
try(InputStream in = ModernCardRenderer.class.getResourceAsStream("/cardrender/" + name + ".ttf")) { try (InputStream in = ModernCardRenderer.class.getResourceAsStream("/cardrender/" + name + ".ttf")) {
return Font.createFont( return Font.createFont(
Font.TRUETYPE_FONT,in); Font.TRUETYPE_FONT, in);
} catch (IOException e) { } catch (IOException e) {
LOGGER.info("Failed to load font `" + name + "`, couldn't find resource."); LOGGER.info("Failed to load font `" + name + "`, couldn't find resource.");
} catch (FontFormatException e) { } catch (FontFormatException e) {
@ -353,7 +352,7 @@ public class ModernCardRenderer extends CardRenderer {
if (useInventionFrame()) { if (useInventionFrame()) {
drawArtIntoRect(g, drawArtIntoRect(g,
borderWidth, borderWidth, borderWidth, borderWidth,
cardWidth - 2*borderWidth, cardHeight - 2*borderWidth, cardWidth - 2 * borderWidth, cardHeight - 2 * borderWidth,
getArtRect(), false); getArtRect(), false);
} }
@ -367,11 +366,11 @@ public class ModernCardRenderer extends CardRenderer {
// each filling half of the art rect // each filling half of the art rect
drawArtIntoRect(g, drawArtIntoRect(g,
totalContentInset + 1, totalContentInset + boxHeight, totalContentInset + 1, totalContentInset + boxHeight,
contentWidth - 2, (typeLineY - totalContentInset - boxHeight)/2, contentWidth - 2, (typeLineY - totalContentInset - boxHeight) / 2,
ArtRect.SPLIT_LEFT.rect, useInventionFrame()); ArtRect.SPLIT_LEFT.rect, useInventionFrame());
drawArtIntoRect(g, drawArtIntoRect(g,
totalContentInset + 1, totalContentInset + boxHeight + (typeLineY - totalContentInset - boxHeight)/2, totalContentInset + 1, totalContentInset + boxHeight + (typeLineY - totalContentInset - boxHeight) / 2,
contentWidth - 2, (typeLineY - totalContentInset - boxHeight)/2, contentWidth - 2, (typeLineY - totalContentInset - boxHeight) / 2,
ArtRect.SPLIT_RIGHT.rect, useInventionFrame()); ArtRect.SPLIT_RIGHT.rect, useInventionFrame());
return; return;
} else if (rect != ArtRect.NORMAL) { } else if (rect != ArtRect.NORMAL) {
@ -849,6 +848,9 @@ public class ModernCardRenderer extends CardRenderer {
inset = cardWidth / 12; inset = cardWidth / 12;
} }
int availWidth = w - inset; int availWidth = w - inset;
if (availWidth < 0) {
return 0;
}
FontRenderContext frc = g.getFontRenderContext(); FontRenderContext frc = g.getFontRenderContext();
AttributedCharacterIterator textIter = text.getIterator(); AttributedCharacterIterator textIter = text.getIterator();

View file

@ -184,7 +184,7 @@ public final class CardImageUtils {
String imageName; String imageName;
String type = card.getType() != 0 ? ' ' + Integer.toString(card.getType()) : ""; String type = card.getType() != 0 ? ' ' + Integer.toString(card.getType()) : "";
String name = card.getFileName().isEmpty() ? card.getName().replace(":", "").replace("//", "-") : card.getFileName(); String name = card.getFileName().isEmpty() ? card.getName().replace(":", "").replace("\"", "").replace("//", "-") : card.getFileName();
if (card.getUsesVariousArt()) { if (card.getUsesVariousArt()) {
imageName = name + '.' + card.getCollectorId() + ".full.jpg"; imageName = name + '.' + card.getCollectorId() + ".full.jpg";

View file

@ -41,7 +41,7 @@ public class MageVersion implements Serializable, Comparable<MageVersion> {
public final static int MAGE_VERSION_MAJOR = 1; public final static int MAGE_VERSION_MAJOR = 1;
public final static int MAGE_VERSION_MINOR = 4; public final static int MAGE_VERSION_MINOR = 4;
public final static int MAGE_VERSION_PATCH = 26; public final static int MAGE_VERSION_PATCH = 26;
public final static String MAGE_VERSION_MINOR_PATCH = "V7"; public final static String MAGE_VERSION_MINOR_PATCH = "V8";
public final static String MAGE_VERSION_INFO = ""; public final static String MAGE_VERSION_INFO = "";
private final int major; private final int major;

View file

@ -92,15 +92,14 @@ public class CanadianHighlander extends Constructed {
String cn = entry.getKey(); String cn = entry.getKey();
if (cn.equals("Balance") if (cn.equals("Balance")
|| cn.equals("Dig Through Time") || cn.equals("Dig Through Time")
|| cn.equals("Doomsday")
|| cn.equals("Enlightened Tutor") || cn.equals("Enlightened Tutor")
|| cn.equals("Fastbond") || cn.equals("Fastbond")
|| cn.equals("Intuition") || cn.equals("Intuition")
|| cn.equals("Library of Alexandria") || cn.equals("Library of Alexandria")
|| cn.equals("Lim-Dul's Vault")
|| cn.equals("Mana Vault") || cn.equals("Mana Vault")
|| cn.equals("Merchant Scroll") || cn.equals("Merchant Scroll")
|| cn.equals("Mind Twist") || cn.equals("Mind Twist")
|| cn.equals("Oath of Druids")
|| cn.equals("Personal Tutor") || cn.equals("Personal Tutor")
|| cn.equals("Stoneforge Mystic") || cn.equals("Stoneforge Mystic")
|| cn.equals("Tainted Pact") || cn.equals("Tainted Pact")
@ -112,32 +111,32 @@ public class CanadianHighlander extends Constructed {
totalPoints += 1; totalPoints += 1;
invalid.put(entry.getKey(), " 1 point " + cn); invalid.put(entry.getKey(), " 1 point " + cn);
} }
if (cn.equals("Doomsday") if (cn.equals("Gifts Ungiven")
|| cn.equals("Gifts Ungiven") || cn.equals("Hermit Druid")
|| cn.equals("Imperial Seal") || cn.equals("Imperial Seal")
|| cn.equals("Mana Crypt") || cn.equals("Mana Crypt")
|| cn.equals("Mystical Tutor") || cn.equals("Mystical Tutor")
|| cn.equals("Strip Mine") || cn.equals("Strip Mine")
|| cn.equals("Summoner's Pact") || cn.equals("Summoners Pact")
|| cn.equals("Survival of the Fittest") || cn.equals("Survival of the Fittest")
|| cn.equals("Umezawa's Jitte")) { || cn.equals("Umezawas Jitte")) {
totalPoints += 2; totalPoints += 2;
invalid.put(entry.getKey(), " 2 points " + cn); invalid.put(entry.getKey(), " 2 points " + cn);
} }
if (cn.equals("Birthing Pod") if (cn.equals("Birthing Pod")
|| cn.equals("Hermit Druid")
|| cn.equals("Mox Emerald") || cn.equals("Mox Emerald")
|| cn.equals("Mox Jet") || cn.equals("Mox Jet")
|| cn.equals("Mox Pearl") || cn.equals("Mox Pearl")
|| cn.equals("Mox Ruby") || cn.equals("Mox Ruby")
|| cn.equals("Mox Sapphire") || cn.equals("Mox Sapphire")
|| cn.equals("Protean Hulk") || cn.equals("Protean Hulk")
|| cn.equals("Sol Ring")
|| cn.equals("Vampiric Tutor")) { || cn.equals("Vampiric Tutor")) {
totalPoints += 3; totalPoints += 3;
invalid.put(entry.getKey(), " 3 points " + cn); invalid.put(entry.getKey(), " 3 points " + cn);
} }
if (cn.equals("Demonic Tutor") if (cn.equals("Demonic Tutor")
|| cn.equals("Sol Ring")) { || cn.equals("Tinker")) {
totalPoints += 4; totalPoints += 4;
invalid.put(entry.getKey(), " 4 points " + cn); invalid.put(entry.getKey(), " 4 points " + cn);
} }
@ -147,13 +146,12 @@ public class CanadianHighlander extends Constructed {
invalid.put(entry.getKey(), " 5 points " + cn); invalid.put(entry.getKey(), " 5 points " + cn);
} }
if (cn.equals("Ancestral Recall") if (cn.equals("Ancestral Recall")
|| cn.equals("Time Walk")) { || cn.equals("Time Vault")) {
totalPoints += 6; totalPoints += 6;
invalid.put(entry.getKey(), " 5 points " + cn); invalid.put(entry.getKey(), " 6 points " + cn);
} }
if (cn.equals("Black Lotus") if (cn.equals("Black Lotus")
|| cn.equals("Flash") || cn.equals("Flash")) {
|| cn.equals("Time Vault")) {
totalPoints += 7; totalPoints += 7;
invalid.put(entry.getKey(), " 7 points " + cn); invalid.put(entry.getKey(), " 7 points " + cn);
} }

View file

@ -0,0 +1,55 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.26</version>
</parent>
<artifactId>mage-game-momirfreeforall</artifactId>
<packaging>jar</packaging>
<name>Mage Game Momir Basic Free for All</name>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>mage</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>mage-game-freeforall</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
<finalName>mage-game-momir</finalName>
</build>
<properties/>
</project>

View file

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

View file

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

View file

@ -0,0 +1,105 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.game;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.InfoEffect;
import mage.cards.repository.CardInfo;
import mage.cards.repository.CardRepository;
import mage.constants.MultiplayerAttackOption;
import mage.constants.PhaseStep;
import mage.constants.RangeOfInfluence;
import mage.constants.Zone;
import mage.game.command.emblems.MomirEmblem;
import mage.game.match.MatchType;
import mage.game.turn.TurnMod;
import mage.players.Player;
/**
*
* @author nigelzor
*/
public class MomirGame extends FreeForAll {
private int numPlayers;
public MomirGame(MultiplayerAttackOption attackOption, RangeOfInfluence range, int freeMulligans, int startLife) {
super(attackOption, range, freeMulligans, startLife);
}
public MomirGame(final MomirGame game) {
super(game);
}
@Override
public MatchType getGameType() {
return new MomirFreeForAllType();
}
@Override
public int getNumPlayers() {
return numPlayers;
}
@Override
protected void init(UUID choosingPlayerId) {
Ability ability = new SimpleStaticAbility(Zone.COMMAND, new InfoEffect("Vanguard effects"));
for (UUID playerId : state.getPlayerList(startingPlayerId)) {
Player player = getPlayer(playerId);
if (player != null) {
CardInfo cardInfo = CardRepository.instance.findCard("Momir Vig, Simic Visionary");
addEmblem(new MomirEmblem(), cardInfo.getCard(), playerId);
}
}
getState().addAbility(ability, null);
super.init(choosingPlayerId);
state.getTurnMods().add(new TurnMod(startingPlayerId, PhaseStep.DRAW));
}
@Override
public Set<UUID> getOpponents(UUID playerId) {
Set<UUID> opponents = new HashSet<>();
for (UUID opponentId : this.getPlayer(playerId).getInRange()) {
if (!opponentId.equals(playerId)) {
opponents.add(opponentId);
}
}
return opponents;
}
@Override
public MomirGame copy() {
return new MomirGame(this);
}
}

View file

@ -1,5 +1,5 @@
#Generated by Maven #Generated by Maven
#Fri Sep 15 22:14:29 CEST 2017 #Sun Oct 22 00:34:49 EDT 2017
version=1.4.26 version=1.4.26
groupId=org.mage groupId=org.mage
artifactId=mage-game-pennydreadfulcommanderfreeforall artifactId=mage-game-pennydreadfulcommanderfreeforall

View file

@ -519,7 +519,7 @@ public class ComputerPlayer6 extends ComputerPlayer /*implements Player*/ {
logger.trace("interrupted - " + val); logger.trace("interrupted - " + val);
return val; return val;
} }
if (depth <= 0 || SimulationNode2.nodeCount > maxNodes || game.gameOver(null)) { if (depth <= 0 || SimulationNode2.nodeCount > maxNodes || game.checkIfGameIsOver()) {
logger.trace("Add actions -- reached end state, node count=" + SimulationNode2.nodeCount + ", depth=" + depth); logger.trace("Add actions -- reached end state, node count=" + SimulationNode2.nodeCount + ", depth=" + depth);
val = GameStateEvaluator2.evaluate(playerId, game); val = GameStateEvaluator2.evaluate(playerId, game);
UUID currentPlayerId = node.getGame().getPlayerList().get(); UUID currentPlayerId = node.getGame().getPlayerList().get();
@ -540,7 +540,7 @@ public class ComputerPlayer6 extends ComputerPlayer /*implements Player*/ {
} }
} }
if (game.gameOver(null)) { if (game.checkIfGameIsOver()) {
val = GameStateEvaluator2.evaluate(playerId, game); val = GameStateEvaluator2.evaluate(playerId, game);
} else if (!node.getChildren().isEmpty()) { } else if (!node.getChildren().isEmpty()) {
//declared attackers or blockers or triggered abilities //declared attackers or blockers or triggered abilities
@ -588,7 +588,7 @@ public class ComputerPlayer6 extends ComputerPlayer /*implements Player*/ {
logger.debug("Sim Prio [" + depth + "] -- repeated action: " + action.toString()); logger.debug("Sim Prio [" + depth + "] -- repeated action: " + action.toString());
continue; continue;
} }
if (!sim.gameOver(null) && action.isUsesStack()) { if (!sim.checkIfGameIsOver() && action.isUsesStack()) {
// only pass if the last action uses the stack // only pass if the last action uses the stack
UUID nextPlayerId = sim.getPlayerList().get(); UUID nextPlayerId = sim.getPlayerList().get();
do { do {
@ -864,7 +864,7 @@ public class ComputerPlayer6 extends ComputerPlayer /*implements Player*/ {
break; break;
case CLEANUP: case CLEANUP:
game.getPhase().getStep().beginStep(game, activePlayerId); game.getPhase().getStep().beginStep(game, activePlayerId);
if (!game.checkStateAndTriggered() && !game.gameOver(null)) { if (!game.checkStateAndTriggered() && !game.checkIfGameIsOver()) {
game.getState().setActivePlayerId(game.getState().getPlayerList(game.getActivePlayerId()).getNext()); game.getState().setActivePlayerId(game.getState().getPlayerList(game.getActivePlayerId()).getNext());
game.getTurn().setPhase(new BeginningPhase()); game.getTurn().setPhase(new BeginningPhase());
game.getPhase().setStep(new UntapStep()); game.getPhase().setStep(new UntapStep());

View file

@ -161,10 +161,9 @@ public class ComputerPlayer7 extends ComputerPlayer6 {
Game sim = createSimulation(game); Game sim = createSimulation(game);
SimulationNode2.resetCount(); SimulationNode2.resetCount();
root = new SimulationNode2(null, sim, maxDepth, playerId); root = new SimulationNode2(null, sim, maxDepth, playerId);
addActionsTimed(); addActionsTimed();
if (root.children != null && !root.children.isEmpty()) {
logger.trace("After add actions timed: root.children.size = " + root.children.size()); logger.trace("After add actions timed: root.children.size = " + root.children.size());
if (!root.children.isEmpty()) {
root = root.children.get(0); root = root.children.get(0);
// int bestScore = root.getScore(); // int bestScore = root.getScore();
// if (bestScore > currentScore || allowBadMoves) { // if (bestScore > currentScore || allowBadMoves) {
@ -233,7 +232,7 @@ public class ComputerPlayer7 extends ComputerPlayer6 {
return GameStateEvaluator2.evaluate(playerId, game); return GameStateEvaluator2.evaluate(playerId, game);
} }
// Condition to stop deeper simulation // Condition to stop deeper simulation
if (depth <= 0 || SimulationNode2.nodeCount > maxNodes || game.gameOver(null)) { if (depth <= 0 || SimulationNode2.nodeCount > maxNodes || game.checkIfGameIsOver()) {
val = GameStateEvaluator2.evaluate(playerId, game); val = GameStateEvaluator2.evaluate(playerId, game);
if (logger.isTraceEnabled()) { if (logger.isTraceEnabled()) {
StringBuilder sb = new StringBuilder("Add Actions -- reached end state <").append(val).append('>'); StringBuilder sb = new StringBuilder("Add Actions -- reached end state <").append(val).append('>');
@ -267,7 +266,7 @@ public class ComputerPlayer7 extends ComputerPlayer6 {
} }
} }
if (game.gameOver(null)) { if (game.checkIfGameIsOver()) {
val = GameStateEvaluator2.evaluate(playerId, game); val = GameStateEvaluator2.evaluate(playerId, game);
} else if (stepFinished) { } else if (stepFinished) {
logger.debug("Step finished"); logger.debug("Step finished");
@ -481,7 +480,7 @@ public class ComputerPlayer7 extends ComputerPlayer6 {
sim.fireEvent(GameEvent.getEvent(GameEvent.EventType.DECLARE_BLOCKERS_STEP_POST, sim.getActivePlayerId(), sim.getActivePlayerId())); sim.fireEvent(GameEvent.getEvent(GameEvent.EventType.DECLARE_BLOCKERS_STEP_POST, sim.getActivePlayerId(), sim.getActivePlayerId()));
Combat simCombat = sim.getCombat().copy(); Combat simCombat = sim.getCombat().copy();
finishCombat(sim); finishCombat(sim);
if (sim.gameOver(null)) { if (sim.checkIfGameIsOver()) {
val = GameStateEvaluator2.evaluate(playerId, sim); val = GameStateEvaluator2.evaluate(playerId, sim);
} else if (!counter) { } else if (!counter) {
val = simulatePostCombatMain(sim, newNode, depth - 1, alpha, beta); val = simulatePostCombatMain(sim, newNode, depth - 1, alpha, beta);
@ -549,7 +548,7 @@ public class ComputerPlayer7 extends ComputerPlayer6 {
logger.debug("interrupted"); logger.debug("interrupted");
return; return;
} }
if (!game.gameOver(null)) { if (!game.checkIfGameIsOver()) {
game.getPhase().setStep(step); game.getPhase().setStep(step);
if (!step.skipStep(game, game.getActivePlayerId())) { if (!step.skipStep(game, game.getActivePlayerId())) {
step.beginStep(game, game.getActivePlayerId()); step.beginStep(game, game.getActivePlayerId());
@ -598,7 +597,7 @@ public class ComputerPlayer7 extends ComputerPlayer6 {
logger.debug("interrupted"); logger.debug("interrupted");
return; return;
} }
if (!game.gameOver(null)) { if (!game.checkIfGameIsOver()) {
game.getTurn().getPhase().endPhase(game, game.getActivePlayerId()); game.getTurn().getPhase().endPhase(game, game.getActivePlayerId());
game.getTurn().setPhase(new EndPhase()); game.getTurn().setPhase(new EndPhase());
if (game.getTurn().getPhase().beginPhase(game, game.getActivePlayerId())) { if (game.getTurn().getPhase().beginPhase(game, game.getActivePlayerId())) {

View file

@ -33,7 +33,7 @@ public final class GameStateEvaluator2 {
public static int evaluate(UUID playerId, Game game) { public static int evaluate(UUID playerId, Game game) {
Player player = game.getPlayer(playerId); Player player = game.getPlayer(playerId);
Player opponent = game.getPlayer(game.getOpponents(playerId).iterator().next()); Player opponent = game.getPlayer(game.getOpponents(playerId).iterator().next());
if (game.gameOver(null)) { if (game.checkIfGameIsOver()) {
if (player.hasLost() || opponent.hasWon()) { if (player.hasLost() || opponent.hasWon()) {
return LOSE_GAME_SCORE; return LOSE_GAME_SCORE;
} }

View file

@ -61,7 +61,7 @@ public class ActionSimulator {
public int evaluateState() { public int evaluateState() {
Player opponent = game.getPlayer(game.getOpponents(player.getId()).iterator().next()); Player opponent = game.getPlayer(game.getOpponents(player.getId()).iterator().next());
if (game.gameOver(null)) { if (game.checkIfGameIsOver()) {
if (player.hasLost() || opponent.hasWon()) { if (player.hasLost() || opponent.hasWon()) {
return Integer.MIN_VALUE; return Integer.MIN_VALUE;
} }

View file

@ -79,7 +79,7 @@ public class MCTSNode {
this.game = game; this.game = game;
this.stateValue = game.getState().getValue(game, targetPlayer); this.stateValue = game.getState().getValue(game, targetPlayer);
this.fullStateValue = game.getState().getValue(true, game); this.fullStateValue = game.getState().getValue(true, game);
this.terminal = game.gameOver(null); this.terminal = game.checkIfGameIsOver();
setPlayer(); setPlayer();
nodeCount = 1; nodeCount = 1;
// logger.info(this.stateValue); // logger.info(this.stateValue);
@ -90,7 +90,7 @@ public class MCTSNode {
this.game = game; this.game = game;
this.stateValue = game.getState().getValue(game, targetPlayer); this.stateValue = game.getState().getValue(game, targetPlayer);
this.fullStateValue = game.getState().getValue(true, game); this.fullStateValue = game.getState().getValue(true, game);
this.terminal = game.gameOver(null); this.terminal = game.checkIfGameIsOver();
this.parent = parent; this.parent = parent;
this.action = action; this.action = action;
setPlayer(); setPlayer();
@ -104,7 +104,7 @@ public class MCTSNode {
this.combat = combat; this.combat = combat;
this.stateValue = game.getState().getValue(game, targetPlayer); this.stateValue = game.getState().getValue(game, targetPlayer);
this.fullStateValue = game.getState().getValue(true, game); this.fullStateValue = game.getState().getValue(true, game);
this.terminal = game.gameOver(null); this.terminal = game.checkIfGameIsOver();
this.parent = parent; this.parent = parent;
setPlayer(); setPlayer();
nodeCount++; nodeCount++;

View file

@ -330,7 +330,7 @@ public class ComputerPlayer2 extends ComputerPlayer implements Player {
return GameStateEvaluator.evaluate(playerId, game); return GameStateEvaluator.evaluate(playerId, game);
} }
int val; int val;
if (node.depth > maxDepth || game.gameOver(null)) { if (node.depth > maxDepth || game.checkIfGameIsOver()) {
logger.debug(indent(node.depth) + "simulating -- reached end state"); logger.debug(indent(node.depth) + "simulating -- reached end state");
val = GameStateEvaluator.evaluate(playerId, game); val = GameStateEvaluator.evaluate(playerId, game);
} }
@ -357,7 +357,7 @@ public class ComputerPlayer2 extends ComputerPlayer implements Player {
} }
} }
if (game.gameOver(null)) { if (game.checkIfGameIsOver()) {
val = GameStateEvaluator.evaluate(playerId, game); val = GameStateEvaluator.evaluate(playerId, game);
} }
else if (!node.getChildren().isEmpty()) { else if (!node.getChildren().isEmpty()) {
@ -403,7 +403,7 @@ public class ComputerPlayer2 extends ComputerPlayer implements Player {
logger.debug(indent(node.depth) + "found useless action: " + action); logger.debug(indent(node.depth) + "found useless action: " + action);
continue; continue;
} }
if (!sim.gameOver(null) && action.isUsesStack()) { if (!sim.checkIfGameIsOver() && action.isUsesStack()) {
// only pass if the last action uses the stack // only pass if the last action uses the stack
sim.getPlayer(currentPlayer.getId()).pass(game); sim.getPlayer(currentPlayer.getId()).pass(game);
sim.getPlayerList().getNext(); sim.getPlayerList().getNext();
@ -588,7 +588,7 @@ public class ComputerPlayer2 extends ComputerPlayer implements Player {
break; break;
case CLEANUP: case CLEANUP:
game.getPhase().getStep().beginStep(game, activePlayerId); game.getPhase().getStep().beginStep(game, activePlayerId);
if (!game.checkStateAndTriggered() && !game.gameOver(null)) { if (!game.checkStateAndTriggered() && !game.checkIfGameIsOver()) {
game.getState().setActivePlayerId(game.getState().getPlayerList(game.getActivePlayerId()).getNext()); game.getState().setActivePlayerId(game.getState().getPlayerList(game.getActivePlayerId()).getNext());
game.getTurn().setPhase(new BeginningPhase()); game.getTurn().setPhase(new BeginningPhase());
game.getPhase().setStep(new UntapStep()); game.getPhase().setStep(new UntapStep());

View file

@ -184,7 +184,7 @@ public class ComputerPlayer3 extends ComputerPlayer2 implements Player {
logger.debug(indent(node.depth) + "interrupted"); logger.debug(indent(node.depth) + "interrupted");
return GameStateEvaluator.evaluate(playerId, game); return GameStateEvaluator.evaluate(playerId, game);
} }
if (node.depth > maxDepth || game.gameOver(null)) { if (node.depth > maxDepth || game.checkIfGameIsOver()) {
logger.debug(indent(node.depth) + "simulating -- reached end state"); logger.debug(indent(node.depth) + "simulating -- reached end state");
val = GameStateEvaluator.evaluate(playerId, game); val = GameStateEvaluator.evaluate(playerId, game);
} }
@ -204,7 +204,7 @@ public class ComputerPlayer3 extends ComputerPlayer2 implements Player {
} }
} }
if (game.gameOver(null)) { if (game.checkIfGameIsOver()) {
val = GameStateEvaluator.evaluate(playerId, game); val = GameStateEvaluator.evaluate(playerId, game);
} }
else if (stepFinished) { else if (stepFinished) {
@ -408,7 +408,7 @@ public class ComputerPlayer3 extends ComputerPlayer2 implements Player {
sim.fireEvent(GameEvent.getEvent(GameEvent.EventType.DECLARE_BLOCKERS_STEP_POST, sim.getActivePlayerId(), sim.getActivePlayerId())); sim.fireEvent(GameEvent.getEvent(GameEvent.EventType.DECLARE_BLOCKERS_STEP_POST, sim.getActivePlayerId(), sim.getActivePlayerId()));
Combat simCombat = sim.getCombat().copy(); Combat simCombat = sim.getCombat().copy();
finishCombat(sim); finishCombat(sim);
if (sim.gameOver(null)) { if (sim.checkIfGameIsOver()) {
val = GameStateEvaluator.evaluate(playerId, sim); val = GameStateEvaluator.evaluate(playerId, sim);
} }
else if (!counter) { else if (!counter) {
@ -450,7 +450,7 @@ public class ComputerPlayer3 extends ComputerPlayer2 implements Player {
return GameStateEvaluator.evaluate(playerId, game); return GameStateEvaluator.evaluate(playerId, game);
} }
Integer val = null; Integer val = null;
if (!game.gameOver(null)) { if (!game.checkIfGameIsOver()) {
logger.debug(indent(node.depth) + "simulating -- ending turn"); logger.debug(indent(node.depth) + "simulating -- ending turn");
simulateToEnd(game); simulateToEnd(game);
game.getState().setActivePlayerId(game.getState().getPlayerList(game.getActivePlayerId()).getNext()); game.getState().setActivePlayerId(game.getState().getPlayerList(game.getActivePlayerId()).getNext());
@ -478,7 +478,7 @@ public class ComputerPlayer3 extends ComputerPlayer2 implements Player {
logger.debug("interrupted"); logger.debug("interrupted");
return; return;
} }
if (!game.gameOver(null)) { if (!game.checkIfGameIsOver()) {
game.getPhase().setStep(step); game.getPhase().setStep(step);
if (!step.skipStep(game, game.getActivePlayerId())) { if (!step.skipStep(game, game.getActivePlayerId())) {
step.beginStep(game, game.getActivePlayerId()); step.beginStep(game, game.getActivePlayerId());
@ -526,7 +526,7 @@ public class ComputerPlayer3 extends ComputerPlayer2 implements Player {
logger.debug("interrupted"); logger.debug("interrupted");
return; return;
} }
if (!game.gameOver(null)) { if (!game.checkIfGameIsOver()) {
game.getTurn().getPhase().endPhase(game, game.getActivePlayerId()); game.getTurn().getPhase().endPhase(game, game.getActivePlayerId());
game.getTurn().setPhase(new EndPhase()); game.getTurn().setPhase(new EndPhase());
if (game.getTurn().getPhase().beginPhase(game, game.getActivePlayerId())) { if (game.getTurn().getPhase().beginPhase(game, game.getActivePlayerId())) {

View file

@ -70,7 +70,7 @@ public final class GameStateEvaluator {
public static int evaluate(UUID playerId, Game game, boolean ignoreTapped) { public static int evaluate(UUID playerId, Game game, boolean ignoreTapped) {
Player player = game.getPlayer(playerId); Player player = game.getPlayer(playerId);
Player opponent = game.getPlayer(game.getOpponents(playerId).iterator().next()); Player opponent = game.getPlayer(game.getOpponents(playerId).iterator().next());
if (game.gameOver(null)) { if (game.checkIfGameIsOver()) {
if (player.hasLost() || opponent.hasWon()) if (player.hasLost() || opponent.hasWon())
return LOSE_SCORE; return LOSE_SCORE;
if (opponent.hasLost() || player.hasWon()) if (opponent.hasLost() || player.hasWon())

View file

@ -53,6 +53,7 @@ import mage.filter.common.FilterCreatureForCombat;
import mage.filter.common.FilterCreatureForCombatBlock; import mage.filter.common.FilterCreatureForCombatBlock;
import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.filter.predicate.permanent.ControllerIdPredicate;
import mage.game.Game; import mage.game.Game;
import mage.game.GameImpl;
import mage.game.combat.CombatGroup; import mage.game.combat.CombatGroup;
import mage.game.draft.Draft; import mage.game.draft.Draft;
import mage.game.events.GameEvent; import mage.game.events.GameEvent;
@ -186,6 +187,9 @@ public class HumanPlayer extends PlayerImpl {
response.clear(); response.clear();
logger.debug("Waiting response from player: " + getId()); logger.debug("Waiting response from player: " + getId());
game.resumeTimer(getTurnControlledBy()); game.resumeTimer(getTurnControlledBy());
boolean loop = true;
while (loop) {
loop = false;
synchronized (response) { synchronized (response) {
try { try {
response.wait(); response.wait();
@ -195,6 +199,17 @@ public class HumanPlayer extends PlayerImpl {
game.pauseTimer(getTurnControlledBy()); game.pauseTimer(getTurnControlledBy());
} }
} }
if (response.getResponseConcedeCheck()) {
((GameImpl) game).checkConcede();
if (game.hasEnded()) {
return;
}
response.clear();
if (isInGame()) {
loop = true;
}
}
}
if (recordingMacro && !macroTriggeredSelectionFlag) { if (recordingMacro && !macroTriggeredSelectionFlag) {
// logger.info("Adding an action " + response); // logger.info("Adding an action " + response);
actionQueueSaved.add(new PlayerResponse(response)); actionQueueSaved.add(new PlayerResponse(response));
@ -1706,6 +1721,15 @@ public class HumanPlayer extends PlayerImpl {
} }
} }
@Override
public void signalPlayerConcede() {
synchronized (response) {
response.setResponseConcedeCheck();
response.notifyAll();
logger.debug("Set check concede for waiting player: " + getId());
}
}
@Override @Override
public void skip() { public void skip() {
synchronized (response) { synchronized (response) {

View file

@ -43,6 +43,7 @@ public class PlayerResponse implements Serializable {
private Integer responseInteger; private Integer responseInteger;
private ManaType responseManaType; private ManaType responseManaType;
private UUID responseManaTypePlayerId; private UUID responseManaTypePlayerId;
private Boolean responseConcedeCheck;
public PlayerResponse() { public PlayerResponse() {
clear(); clear();
@ -55,7 +56,8 @@ public class PlayerResponse implements Serializable {
+ ',' + responseBoolean + ',' + responseBoolean
+ ',' + responseInteger + ',' + responseInteger
+ ',' + responseManaType + ',' + responseManaType
+ ',' + responseManaTypePlayerId; + ',' + responseManaTypePlayerId
+ ',' + responseConcedeCheck;
} }
public PlayerResponse(PlayerResponse other) { public PlayerResponse(PlayerResponse other) {
@ -69,6 +71,7 @@ public class PlayerResponse implements Serializable {
responseInteger = other.responseInteger; responseInteger = other.responseInteger;
responseManaType = other.responseManaType; responseManaType = other.responseManaType;
responseManaTypePlayerId = other.responseManaTypePlayerId; responseManaTypePlayerId = other.responseManaTypePlayerId;
responseConcedeCheck = other.responseConcedeCheck;
} }
public void clear() { public void clear() {
@ -78,6 +81,7 @@ public class PlayerResponse implements Serializable {
responseInteger = null; responseInteger = null;
responseManaType = null; responseManaType = null;
responseManaTypePlayerId = null; responseManaTypePlayerId = null;
responseConcedeCheck = null;
} }
public String getString() { public String getString() {
@ -104,6 +108,17 @@ public class PlayerResponse implements Serializable {
this.responseBoolean = responseBoolean; this.responseBoolean = responseBoolean;
} }
public Boolean getResponseConcedeCheck() {
if (responseConcedeCheck == null) {
return false;
}
return responseConcedeCheck;
}
public void setResponseConcedeCheck() {
this.responseConcedeCheck = true;
}
public Integer getInteger() { public Integer getInteger() {
return responseInteger; return responseInteger;
} }

View file

@ -35,9 +35,9 @@ import mage.game.draft.DraftCube;
*/ */
public class AdamStyborskisPauperCube extends DraftCube { public class AdamStyborskisPauperCube extends DraftCube {
public AdamStyborskisPauperCube() { public AdamStyborskisPauperCube() {
super("Adam Styborkski's Pauper Cube"); // https://docs.google.com/spreadsheets/d/12iQhC4bHqFW7hEWxPBjyC8yBDehFZ0_4DkqzyA8EL3o/edit#gid=0 super("Adam Styborkski's Pauper Cube"); // https://docs.google.com/spreadsheets/d/12iQhC4bHqFW7hEWxPBjyC8yBDehFZ0_4DkqzyA8EL3o/edit#gid=0
// last updated with Amonkhet 6/12/17 // last updated with Hour of Devastation, Iconic Masters and Ixalan 10/18/17
cubeCards.add(new CardIdentity("Act of Treason", "")); cubeCards.add(new CardIdentity("Act of Treason", ""));
cubeCards.add(new CardIdentity("Adventuring Gear", "")); cubeCards.add(new CardIdentity("Adventuring Gear", ""));
cubeCards.add(new CardIdentity("Aerie Ouphes", "")); cubeCards.add(new CardIdentity("Aerie Ouphes", ""));
@ -45,6 +45,7 @@ public AdamStyborskisPauperCube() {
cubeCards.add(new CardIdentity("Aethersnipe", "")); cubeCards.add(new CardIdentity("Aethersnipe", ""));
cubeCards.add(new CardIdentity("Agony Warp", "")); cubeCards.add(new CardIdentity("Agony Warp", ""));
cubeCards.add(new CardIdentity("Aim High", "")); cubeCards.add(new CardIdentity("Aim High", ""));
cubeCards.add(new CardIdentity("Ambuscade", ""));
cubeCards.add(new CardIdentity("Ambush Viper", "")); cubeCards.add(new CardIdentity("Ambush Viper", ""));
cubeCards.add(new CardIdentity("Angelic Purge", "")); cubeCards.add(new CardIdentity("Angelic Purge", ""));
cubeCards.add(new CardIdentity("Arachnus Web", "")); cubeCards.add(new CardIdentity("Arachnus Web", ""));
@ -55,18 +56,18 @@ public AdamStyborskisPauperCube() {
cubeCards.add(new CardIdentity("Ashes to Ashes", "")); cubeCards.add(new CardIdentity("Ashes to Ashes", ""));
cubeCards.add(new CardIdentity("Assault Zeppelid", "")); cubeCards.add(new CardIdentity("Assault Zeppelid", ""));
cubeCards.add(new CardIdentity("Attended Knight", "")); cubeCards.add(new CardIdentity("Attended Knight", ""));
cubeCards.add(new CardIdentity("Augur of Bolas", ""));
cubeCards.add(new CardIdentity("Auger Spree", "")); cubeCards.add(new CardIdentity("Auger Spree", ""));
cubeCards.add(new CardIdentity("Augur of Bolas", ""));
cubeCards.add(new CardIdentity("Aven Riftwatcher", "")); cubeCards.add(new CardIdentity("Aven Riftwatcher", ""));
cubeCards.add(new CardIdentity("Aven Surveyor", "")); cubeCards.add(new CardIdentity("Aven Surveyor", ""));
cubeCards.add(new CardIdentity("Azorius Guildgate", "")); cubeCards.add(new CardIdentity("Azorius Guildgate", ""));
cubeCards.add(new CardIdentity("Baleful Eidolon", "")); cubeCards.add(new CardIdentity("Baleful Eidolon", ""));
cubeCards.add(new CardIdentity("Barbed Lightning", "")); cubeCards.add(new CardIdentity("Barbed Lightning", ""));
cubeCards.add(new CardIdentity("Barren Moor", ""));
cubeCards.add(new CardIdentity("Basking Rootwalla", "")); cubeCards.add(new CardIdentity("Basking Rootwalla", ""));
cubeCards.add(new CardIdentity("Battle Screech", "")); cubeCards.add(new CardIdentity("Battle Screech", ""));
cubeCards.add(new CardIdentity("Beetleback Chief", "")); cubeCards.add(new CardIdentity("Beetleback Chief", ""));
cubeCards.add(new CardIdentity("Beetleform Mage", "")); cubeCards.add(new CardIdentity("Beetleform Mage", ""));
cubeCards.add(new CardIdentity("Beneath the Sands", ""));
cubeCards.add(new CardIdentity("Blastoderm", "")); cubeCards.add(new CardIdentity("Blastoderm", ""));
cubeCards.add(new CardIdentity("Blazing Torch", "")); cubeCards.add(new CardIdentity("Blazing Torch", ""));
cubeCards.add(new CardIdentity("Blightning", "")); cubeCards.add(new CardIdentity("Blightning", ""));
@ -78,8 +79,9 @@ public AdamStyborskisPauperCube() {
cubeCards.add(new CardIdentity("Bonesplitter", "")); cubeCards.add(new CardIdentity("Bonesplitter", ""));
cubeCards.add(new CardIdentity("Borderland Marauder", "")); cubeCards.add(new CardIdentity("Borderland Marauder", ""));
cubeCards.add(new CardIdentity("Boros Guildgate", "")); cubeCards.add(new CardIdentity("Boros Guildgate", ""));
cubeCards.add(new CardIdentity("Borrowed Grave", "")); cubeCards.add(new CardIdentity("Borrowed Grace", ""));
cubeCards.add(new CardIdentity("Branching Bolt", "")); cubeCards.add(new CardIdentity("Branching Bolt", ""));
cubeCards.add(new CardIdentity("Brazen Buccaneers", ""));
cubeCards.add(new CardIdentity("Brazen Wolves", "")); cubeCards.add(new CardIdentity("Brazen Wolves", ""));
cubeCards.add(new CardIdentity("Burning-Tree Emissary", "")); cubeCards.add(new CardIdentity("Burning-Tree Emissary", ""));
cubeCards.add(new CardIdentity("Burst Lightning", "")); cubeCards.add(new CardIdentity("Burst Lightning", ""));
@ -97,6 +99,7 @@ public AdamStyborskisPauperCube() {
cubeCards.add(new CardIdentity("Chain Lightning", "")); cubeCards.add(new CardIdentity("Chain Lightning", ""));
cubeCards.add(new CardIdentity("Chainer's Edict", "")); cubeCards.add(new CardIdentity("Chainer's Edict", ""));
cubeCards.add(new CardIdentity("Chatter of the Squirrel", "")); cubeCards.add(new CardIdentity("Chatter of the Squirrel", ""));
cubeCards.add(new CardIdentity("Cinder Barrens", ""));
cubeCards.add(new CardIdentity("Citanul Woodreaders", "")); cubeCards.add(new CardIdentity("Citanul Woodreaders", ""));
cubeCards.add(new CardIdentity("Claustrophobia", "")); cubeCards.add(new CardIdentity("Claustrophobia", ""));
cubeCards.add(new CardIdentity("Clay Statue", "")); cubeCards.add(new CardIdentity("Clay Statue", ""));
@ -108,15 +111,12 @@ public AdamStyborskisPauperCube() {
cubeCards.add(new CardIdentity("Compulsive Research", "")); cubeCards.add(new CardIdentity("Compulsive Research", ""));
cubeCards.add(new CardIdentity("Compulsory Rest", "")); cubeCards.add(new CardIdentity("Compulsory Rest", ""));
cubeCards.add(new CardIdentity("Consume Strength", "")); cubeCards.add(new CardIdentity("Consume Strength", ""));
cubeCards.add(new CardIdentity("Corpse Churn", ""));
cubeCards.add(new CardIdentity("Corrupted Zendikon", "")); cubeCards.add(new CardIdentity("Corrupted Zendikon", ""));
cubeCards.add(new CardIdentity("Counterspell", "")); cubeCards.add(new CardIdentity("Counterspell", ""));
cubeCards.add(new CardIdentity("Crippling Fatigue", "")); cubeCards.add(new CardIdentity("Crippling Fatigue", ""));
cubeCards.add(new CardIdentity("Crow of Dark Tidings", "")); cubeCards.add(new CardIdentity("Crow of Dark Tidings", ""));
cubeCards.add(new CardIdentity("Crypt Rats", "")); cubeCards.add(new CardIdentity("Crypt Rats", ""));
cubeCards.add(new CardIdentity("Crystallization", "")); cubeCards.add(new CardIdentity("Crystallization", ""));
cubeCards.add(new CardIdentity("Cultist's Staff", ""));
cubeCards.add(new CardIdentity("Cultivate", ""));
cubeCards.add(new CardIdentity("Cunning Strike", "")); cubeCards.add(new CardIdentity("Cunning Strike", ""));
cubeCards.add(new CardIdentity("Curse of Chains", "")); cubeCards.add(new CardIdentity("Curse of Chains", ""));
cubeCards.add(new CardIdentity("Custodi Squire", "")); cubeCards.add(new CardIdentity("Custodi Squire", ""));
@ -124,9 +124,11 @@ public AdamStyborskisPauperCube() {
cubeCards.add(new CardIdentity("Dauntless Cathar", "")); cubeCards.add(new CardIdentity("Dauntless Cathar", ""));
cubeCards.add(new CardIdentity("Dead Reveler", "")); cubeCards.add(new CardIdentity("Dead Reveler", ""));
cubeCards.add(new CardIdentity("Dead Weight", "")); cubeCards.add(new CardIdentity("Dead Weight", ""));
cubeCards.add(new CardIdentity("Deadeye Tormentor", ""));
cubeCards.add(new CardIdentity("Death Denied", "")); cubeCards.add(new CardIdentity("Death Denied", ""));
cubeCards.add(new CardIdentity("Deep Analysis", "")); cubeCards.add(new CardIdentity("Deep Analysis", ""));
cubeCards.add(new CardIdentity("Deprive", "")); cubeCards.add(new CardIdentity("Deprive", ""));
cubeCards.add(new CardIdentity("Depths of Desire", ""));
cubeCards.add(new CardIdentity("Deputy of Acquittals", "")); cubeCards.add(new CardIdentity("Deputy of Acquittals", ""));
cubeCards.add(new CardIdentity("Desert", "")); cubeCards.add(new CardIdentity("Desert", ""));
cubeCards.add(new CardIdentity("Desperate Sentry", "")); cubeCards.add(new CardIdentity("Desperate Sentry", ""));
@ -134,6 +136,7 @@ public AdamStyborskisPauperCube() {
cubeCards.add(new CardIdentity("Diabolic Edict", "")); cubeCards.add(new CardIdentity("Diabolic Edict", ""));
cubeCards.add(new CardIdentity("Dimir Guildgate", "")); cubeCards.add(new CardIdentity("Dimir Guildgate", ""));
cubeCards.add(new CardIdentity("Dinrova Horror", "")); cubeCards.add(new CardIdentity("Dinrova Horror", ""));
cubeCards.add(new CardIdentity("Dire Fleet Hoarder", ""));
cubeCards.add(new CardIdentity("Disfigure", "")); cubeCards.add(new CardIdentity("Disfigure", ""));
cubeCards.add(new CardIdentity("Dismal Backwater", "")); cubeCards.add(new CardIdentity("Dismal Backwater", ""));
cubeCards.add(new CardIdentity("Disowned Ancestor", "")); cubeCards.add(new CardIdentity("Disowned Ancestor", ""));
@ -152,20 +155,21 @@ public AdamStyborskisPauperCube() {
cubeCards.add(new CardIdentity("Epic Confrontation", "")); cubeCards.add(new CardIdentity("Epic Confrontation", ""));
cubeCards.add(new CardIdentity("Errant Ephemeron", "")); cubeCards.add(new CardIdentity("Errant Ephemeron", ""));
cubeCards.add(new CardIdentity("Esper Cormorants", "")); cubeCards.add(new CardIdentity("Esper Cormorants", ""));
cubeCards.add(new CardIdentity("Essence Scatter", ""));
cubeCards.add(new CardIdentity("Evincar's Justice", "")); cubeCards.add(new CardIdentity("Evincar's Justice", ""));
cubeCards.add(new CardIdentity("Evolving Wilds", "")); cubeCards.add(new CardIdentity("Evolving Wilds", ""));
cubeCards.add(new CardIdentity("Faceless Butcher", "")); cubeCards.add(new CardIdentity("Faceless Butcher", ""));
cubeCards.add(new CardIdentity("Faith's Fetters", "")); cubeCards.add(new CardIdentity("Faith's Fetters", ""));
cubeCards.add(new CardIdentity("Falkenrath Noble", ""));
cubeCards.add(new CardIdentity("Feeling of Dread", "")); cubeCards.add(new CardIdentity("Feeling of Dread", ""));
cubeCards.add(new CardIdentity("Fertile Thicket", ""));
cubeCards.add(new CardIdentity("Fervent Cathar", "")); cubeCards.add(new CardIdentity("Fervent Cathar", ""));
cubeCards.add(new CardIdentity("Firebolt", "")); cubeCards.add(new CardIdentity("Firebolt", ""));
cubeCards.add(new CardIdentity("Fireslinger", "")); cubeCards.add(new CardIdentity("Fireslinger", ""));
cubeCards.add(new CardIdentity("Flayer Husk", "")); cubeCards.add(new CardIdentity("Flayer Husk", ""));
cubeCards.add(new CardIdentity("Flurry of Horns", "")); cubeCards.add(new CardIdentity("Flurry of Horns", ""));
cubeCards.add(new CardIdentity("Forked Bolt", "")); cubeCards.add(new CardIdentity("Forked Bolt", ""));
cubeCards.add(new CardIdentity("Forsaken Sanctuary", ""));
cubeCards.add(new CardIdentity("Fortify", "")); cubeCards.add(new CardIdentity("Fortify", ""));
cubeCards.add(new CardIdentity("Foul Orchard", ""));
cubeCards.add(new CardIdentity("Frilled Oculus", "")); cubeCards.add(new CardIdentity("Frilled Oculus", ""));
cubeCards.add(new CardIdentity("Frostburn Weird", "")); cubeCards.add(new CardIdentity("Frostburn Weird", ""));
cubeCards.add(new CardIdentity("Gathan Raiders", "")); cubeCards.add(new CardIdentity("Gathan Raiders", ""));
@ -182,21 +186,22 @@ public AdamStyborskisPauperCube() {
cubeCards.add(new CardIdentity("Gods Willing", "")); cubeCards.add(new CardIdentity("Gods Willing", ""));
cubeCards.add(new CardIdentity("Goldmeadow Harrier", "")); cubeCards.add(new CardIdentity("Goldmeadow Harrier", ""));
cubeCards.add(new CardIdentity("Golgari Guildgate", "")); cubeCards.add(new CardIdentity("Golgari Guildgate", ""));
cubeCards.add(new CardIdentity("Grapple with the Past", ""));
cubeCards.add(new CardIdentity("Gravedigger", "")); cubeCards.add(new CardIdentity("Gravedigger", ""));
cubeCards.add(new CardIdentity("Gray Merchant of Asphodel", "")); cubeCards.add(new CardIdentity("Gray Merchant of Asphodel", ""));
cubeCards.add(new CardIdentity("Grazing Whiptail", ""));
cubeCards.add(new CardIdentity("Grim Contest", "")); cubeCards.add(new CardIdentity("Grim Contest", ""));
cubeCards.add(new CardIdentity("Grisly Salvage", "")); cubeCards.add(new CardIdentity("Grisly Salvage", ""));
cubeCards.add(new CardIdentity("Grixis Slavedriver", "")); cubeCards.add(new CardIdentity("Grixis Slavedriver", ""));
cubeCards.add(new CardIdentity("Gruul Guildgate", "")); cubeCards.add(new CardIdentity("Gruul Guildgate", ""));
cubeCards.add(new CardIdentity("Gryff Vanguard", "")); cubeCards.add(new CardIdentity("Gryff Vanguard", ""));
cubeCards.add(new CardIdentity("Guardian Automaton", "")); cubeCards.add(new CardIdentity("Guardian Automaton", ""));
cubeCards.add(new CardIdentity("Guardian Idol", ""));
cubeCards.add(new CardIdentity("Guardian of the Guildpact", "")); cubeCards.add(new CardIdentity("Guardian of the Guildpact", ""));
cubeCards.add(new CardIdentity("Gurmag Angler", "")); cubeCards.add(new CardIdentity("Gurmag Angler", ""));
cubeCards.add(new CardIdentity("Halimar Depths", ""));
cubeCards.add(new CardIdentity("Halimar Wavewatch", "")); cubeCards.add(new CardIdentity("Halimar Wavewatch", ""));
cubeCards.add(new CardIdentity("Harrow", "")); cubeCards.add(new CardIdentity("Harrow", ""));
cubeCards.add(new CardIdentity("Harsh Sustenance", "")); cubeCards.add(new CardIdentity("Harsh Sustenance", ""));
cubeCards.add(new CardIdentity("Highland Lake", ""));
cubeCards.add(new CardIdentity("Hissing Iguanar", "")); cubeCards.add(new CardIdentity("Hissing Iguanar", ""));
cubeCards.add(new CardIdentity("Hooting Mandrills", "")); cubeCards.add(new CardIdentity("Hooting Mandrills", ""));
cubeCards.add(new CardIdentity("Humble", "")); cubeCards.add(new CardIdentity("Humble", ""));
@ -206,6 +211,7 @@ public AdamStyborskisPauperCube() {
cubeCards.add(new CardIdentity("Insolent Neonate", "")); cubeCards.add(new CardIdentity("Insolent Neonate", ""));
cubeCards.add(new CardIdentity("Into the Roil", "")); cubeCards.add(new CardIdentity("Into the Roil", ""));
cubeCards.add(new CardIdentity("Isolation Zone", "")); cubeCards.add(new CardIdentity("Isolation Zone", ""));
cubeCards.add(new CardIdentity("Ivy Elemental", ""));
cubeCards.add(new CardIdentity("Izzet Chronarch", "")); cubeCards.add(new CardIdentity("Izzet Chronarch", ""));
cubeCards.add(new CardIdentity("Izzet Guildgate", "")); cubeCards.add(new CardIdentity("Izzet Guildgate", ""));
cubeCards.add(new CardIdentity("Jilt", "")); cubeCards.add(new CardIdentity("Jilt", ""));
@ -214,7 +220,6 @@ public AdamStyborskisPauperCube() {
cubeCards.add(new CardIdentity("Kabuto Moth", "")); cubeCards.add(new CardIdentity("Kabuto Moth", ""));
cubeCards.add(new CardIdentity("Keldon Marauders", "")); cubeCards.add(new CardIdentity("Keldon Marauders", ""));
cubeCards.add(new CardIdentity("Kingpin's Pet", "")); cubeCards.add(new CardIdentity("Kingpin's Pet", ""));
cubeCards.add(new CardIdentity("Kodama's Reach", ""));
cubeCards.add(new CardIdentity("Kor Skyfisher", "")); cubeCards.add(new CardIdentity("Kor Skyfisher", ""));
cubeCards.add(new CardIdentity("Kozilek's Channeler", "")); cubeCards.add(new CardIdentity("Kozilek's Channeler", ""));
cubeCards.add(new CardIdentity("Krenko's Command", "")); cubeCards.add(new CardIdentity("Krenko's Command", ""));
@ -222,25 +227,24 @@ public AdamStyborskisPauperCube() {
cubeCards.add(new CardIdentity("Kruin Striker", "")); cubeCards.add(new CardIdentity("Kruin Striker", ""));
cubeCards.add(new CardIdentity("Lash Out", "")); cubeCards.add(new CardIdentity("Lash Out", ""));
cubeCards.add(new CardIdentity("Last Gasp", "")); cubeCards.add(new CardIdentity("Last Gasp", ""));
cubeCards.add(new CardIdentity("Lawless Broker", "")); cubeCards.add(new CardIdentity("Leave in the Dust", ""));
cubeCards.add(new CardIdentity("Leonin Bola", "")); cubeCards.add(new CardIdentity("Leonin Bola", ""));
cubeCards.add(new CardIdentity("Leonin Scimitar", "")); cubeCards.add(new CardIdentity("Lifecraft Cavalry", ""));
cubeCards.add(new CardIdentity("Lightning Bolt", "")); cubeCards.add(new CardIdentity("Lightning Bolt", ""));
cubeCards.add(new CardIdentity("Liliana's Specter", "")); cubeCards.add(new CardIdentity("Liliana's Specter", ""));
cubeCards.add(new CardIdentity("Looming Spires", ""));
cubeCards.add(new CardIdentity("Lotus Path Djinn", "")); cubeCards.add(new CardIdentity("Lotus Path Djinn", ""));
cubeCards.add(new CardIdentity("Loyal Pegasus", "")); cubeCards.add(new CardIdentity("Loyal Pegasus", ""));
cubeCards.add(new CardIdentity("Lurking Automaton", "")); cubeCards.add(new CardIdentity("Lurking Automaton", ""));
cubeCards.add(new CardIdentity("Magma Jet", "")); cubeCards.add(new CardIdentity("Magma Jet", ""));
cubeCards.add(new CardIdentity("Makeshift Mauler", "")); cubeCards.add(new CardIdentity("Makeshift Mauler", ""));
cubeCards.add(new CardIdentity("Man-o'-War", ""));
cubeCards.add(new CardIdentity("Mana Leak", "")); cubeCards.add(new CardIdentity("Mana Leak", ""));
cubeCards.add(new CardIdentity("Manticore of the Gauntlet", "")); cubeCards.add(new CardIdentity("Manticore of the Gauntlet", ""));
cubeCards.add(new CardIdentity("Man-o'-War", ""));
cubeCards.add(new CardIdentity("Mardu Hordechief", "")); cubeCards.add(new CardIdentity("Mardu Hordechief", ""));
cubeCards.add(new CardIdentity("Mardu Skullhunter", "")); cubeCards.add(new CardIdentity("Mardu Skullhunter", ""));
cubeCards.add(new CardIdentity("Maul Splicer", "")); cubeCards.add(new CardIdentity("Maul Splicer", ""));
cubeCards.add(new CardIdentity("Maulfist Squad", ""));
cubeCards.add(new CardIdentity("Maze of Ith", "")); cubeCards.add(new CardIdentity("Maze of Ith", ""));
cubeCards.add(new CardIdentity("Meandering River", ""));
cubeCards.add(new CardIdentity("Mental Note", "")); cubeCards.add(new CardIdentity("Mental Note", ""));
cubeCards.add(new CardIdentity("Midnight Scavengers", "")); cubeCards.add(new CardIdentity("Midnight Scavengers", ""));
cubeCards.add(new CardIdentity("Mind Stone", "")); cubeCards.add(new CardIdentity("Mind Stone", ""));
@ -249,6 +253,7 @@ public AdamStyborskisPauperCube() {
cubeCards.add(new CardIdentity("Mishra's Factory", "")); cubeCards.add(new CardIdentity("Mishra's Factory", ""));
cubeCards.add(new CardIdentity("Mist Raven", "")); cubeCards.add(new CardIdentity("Mist Raven", ""));
cubeCards.add(new CardIdentity("Mistral Charger", "")); cubeCards.add(new CardIdentity("Mistral Charger", ""));
cubeCards.add(new CardIdentity("Mobile Garrison", ""));
cubeCards.add(new CardIdentity("Mogg Fanatic", "")); cubeCards.add(new CardIdentity("Mogg Fanatic", ""));
cubeCards.add(new CardIdentity("Mogg Flunkies", "")); cubeCards.add(new CardIdentity("Mogg Flunkies", ""));
cubeCards.add(new CardIdentity("Mogg War Marshal", "")); cubeCards.add(new CardIdentity("Mogg War Marshal", ""));
@ -260,17 +265,17 @@ public AdamStyborskisPauperCube() {
cubeCards.add(new CardIdentity("Narcolepsy", "")); cubeCards.add(new CardIdentity("Narcolepsy", ""));
cubeCards.add(new CardIdentity("Necromancer's Assistant", "")); cubeCards.add(new CardIdentity("Necromancer's Assistant", ""));
cubeCards.add(new CardIdentity("Nessian Asp", "")); cubeCards.add(new CardIdentity("Nessian Asp", ""));
cubeCards.add(new CardIdentity("Nest Robber", ""));
cubeCards.add(new CardIdentity("Nezumi Cutthroat", "")); cubeCards.add(new CardIdentity("Nezumi Cutthroat", ""));
cubeCards.add(new CardIdentity("Night's Whisper", "")); cubeCards.add(new CardIdentity("Night's Whisper", ""));
cubeCards.add(new CardIdentity("Nightscape Familiar", "")); cubeCards.add(new CardIdentity("Nightscape Familiar", ""));
cubeCards.add(new CardIdentity("Ninja of the Deep Hours", "")); cubeCards.add(new CardIdentity("Ninja of the Deep Hours", ""));
cubeCards.add(new CardIdentity("Oblivion Ring", "")); cubeCards.add(new CardIdentity("Oblivion Ring", ""));
cubeCards.add(new CardIdentity("Oona's Grace", "")); cubeCards.add(new CardIdentity("Oona's Grace", ""));
cubeCards.add(new CardIdentity("Orcish Oriflamme", ""));
cubeCards.add(new CardIdentity("Orzhov Guildgate", "")); cubeCards.add(new CardIdentity("Orzhov Guildgate", ""));
cubeCards.add(new CardIdentity("Otherworldly Journey", "")); cubeCards.add(new CardIdentity("Otherworldly Journey", ""));
cubeCards.add(new CardIdentity("Pacifism", "")); cubeCards.add(new CardIdentity("Pacifism", ""));
cubeCards.add(new CardIdentity("Palace Sentinels", "")); cubeCards.add(new CardIdentity("Paladin of the Bloodstained", ""));
cubeCards.add(new CardIdentity("Peema Outrider", "")); cubeCards.add(new CardIdentity("Peema Outrider", ""));
cubeCards.add(new CardIdentity("Penumbra Spider", "")); cubeCards.add(new CardIdentity("Penumbra Spider", ""));
cubeCards.add(new CardIdentity("Peregrine Drake", "")); cubeCards.add(new CardIdentity("Peregrine Drake", ""));
@ -287,7 +292,7 @@ public AdamStyborskisPauperCube() {
cubeCards.add(new CardIdentity("Plated Geopede", "")); cubeCards.add(new CardIdentity("Plated Geopede", ""));
cubeCards.add(new CardIdentity("Plover Knights", "")); cubeCards.add(new CardIdentity("Plover Knights", ""));
cubeCards.add(new CardIdentity("Porcelain Legionnaire", "")); cubeCards.add(new CardIdentity("Porcelain Legionnaire", ""));
cubeCards.add(new CardIdentity("Pouncing Kavu", "")); cubeCards.add(new CardIdentity("Pounce", ""));
cubeCards.add(new CardIdentity("Predatory Nightstalker", "")); cubeCards.add(new CardIdentity("Predatory Nightstalker", ""));
cubeCards.add(new CardIdentity("Preordain", "")); cubeCards.add(new CardIdentity("Preordain", ""));
cubeCards.add(new CardIdentity("Prey Upon", "")); cubeCards.add(new CardIdentity("Prey Upon", ""));
@ -316,27 +321,27 @@ public AdamStyborskisPauperCube() {
cubeCards.add(new CardIdentity("Renegade Freighter", "")); cubeCards.add(new CardIdentity("Renegade Freighter", ""));
cubeCards.add(new CardIdentity("Rift Bolt", "")); cubeCards.add(new CardIdentity("Rift Bolt", ""));
cubeCards.add(new CardIdentity("Rishadan Airship", "")); cubeCards.add(new CardIdentity("Rishadan Airship", ""));
cubeCards.add(new CardIdentity("River Serpent", ""));
cubeCards.add(new CardIdentity("Ronin Houndmaster", "")); cubeCards.add(new CardIdentity("Ronin Houndmaster", ""));
cubeCards.add(new CardIdentity("Rugged Highlands", "")); cubeCards.add(new CardIdentity("Rugged Highlands", ""));
cubeCards.add(new CardIdentity("Runed Servitor", "")); cubeCards.add(new CardIdentity("Runed Servitor", ""));
cubeCards.add(new CardIdentity("Rushing River", "")); cubeCards.add(new CardIdentity("Rushing River", ""));
cubeCards.add(new CardIdentity("Sailor of Means", ""));
cubeCards.add(new CardIdentity("Sakura-Tribe Elder", "")); cubeCards.add(new CardIdentity("Sakura-Tribe Elder", ""));
cubeCards.add(new CardIdentity("Sandsteppe Outcast", "")); cubeCards.add(new CardIdentity("Sandsteppe Outcast", ""));
cubeCards.add(new CardIdentity("Sangrite Backlash", "")); cubeCards.add(new CardIdentity("Sangrite Backlash", ""));
cubeCards.add(new CardIdentity("Sarkhan's Rage", "")); cubeCards.add(new CardIdentity("Sarkhan's Rage", ""));
cubeCards.add(new CardIdentity("Savage Punch", "")); cubeCards.add(new CardIdentity("Savage Punch", ""));
cubeCards.add(new CardIdentity("Savage Surge", ""));
cubeCards.add(new CardIdentity("Scatter the Seeds", "")); cubeCards.add(new CardIdentity("Scatter the Seeds", ""));
cubeCards.add(new CardIdentity("Scion of the Wild", ""));
cubeCards.add(new CardIdentity("Scion Summoner", "")); cubeCards.add(new CardIdentity("Scion Summoner", ""));
cubeCards.add(new CardIdentity("Scion of the Wild", ""));
cubeCards.add(new CardIdentity("Scoured Barrens", "")); cubeCards.add(new CardIdentity("Scoured Barrens", ""));
cubeCards.add(new CardIdentity("Scourge Devil", "")); cubeCards.add(new CardIdentity("Scourge Devil", ""));
cubeCards.add(new CardIdentity("Screeching Skaab", "")); cubeCards.add(new CardIdentity("Screeching Skaab", ""));
cubeCards.add(new CardIdentity("Scuzzback Marauders", "")); cubeCards.add(new CardIdentity("Scuzzback Marauders", ""));
cubeCards.add(new CardIdentity("Search for Tomorrow", ""));
cubeCards.add(new CardIdentity("Searing Blaze", "")); cubeCards.add(new CardIdentity("Searing Blaze", ""));
cubeCards.add(new CardIdentity("Seeker of Insight", "")); cubeCards.add(new CardIdentity("Seeker of Insight", ""));
cubeCards.add(new CardIdentity("Sejiri Steppe", "")); cubeCards.add(new CardIdentity("Seeker of the Way", ""));
cubeCards.add(new CardIdentity("Selesnya Guildgate", "")); cubeCards.add(new CardIdentity("Selesnya Guildgate", ""));
cubeCards.add(new CardIdentity("Sentinel Spider", "")); cubeCards.add(new CardIdentity("Sentinel Spider", ""));
cubeCards.add(new CardIdentity("Separatist Voidmage", "")); cubeCards.add(new CardIdentity("Separatist Voidmage", ""));
@ -349,7 +354,6 @@ public AdamStyborskisPauperCube() {
cubeCards.add(new CardIdentity("Sigil Blessing", "")); cubeCards.add(new CardIdentity("Sigil Blessing", ""));
cubeCards.add(new CardIdentity("Silent Departure", "")); cubeCards.add(new CardIdentity("Silent Departure", ""));
cubeCards.add(new CardIdentity("Simic Guildgate", "")); cubeCards.add(new CardIdentity("Simic Guildgate", ""));
cubeCards.add(new CardIdentity("Skinthinner", ""));
cubeCards.add(new CardIdentity("Skirk Marauder", "")); cubeCards.add(new CardIdentity("Skirk Marauder", ""));
cubeCards.add(new CardIdentity("Skyknight Legionnaire", "")); cubeCards.add(new CardIdentity("Skyknight Legionnaire", ""));
cubeCards.add(new CardIdentity("Slash Panther", "")); cubeCards.add(new CardIdentity("Slash Panther", ""));
@ -362,21 +366,21 @@ public AdamStyborskisPauperCube() {
cubeCards.add(new CardIdentity("Spined Thopter", "")); cubeCards.add(new CardIdentity("Spined Thopter", ""));
cubeCards.add(new CardIdentity("Splatter Thug", "")); cubeCards.add(new CardIdentity("Splatter Thug", ""));
cubeCards.add(new CardIdentity("Staggershock", "")); cubeCards.add(new CardIdentity("Staggershock", ""));
cubeCards.add(new CardIdentity("Stave Off", "")); cubeCards.add(new CardIdentity("Star Compass", ""));
cubeCards.add(new CardIdentity("Stitched Drake", "")); cubeCards.add(new CardIdentity("Stitched Drake", ""));
cubeCards.add(new CardIdentity("Stone Quarry", ""));
cubeCards.add(new CardIdentity("Storm Fleet Pyromancer", ""));
cubeCards.add(new CardIdentity("Stormfront Pegasus", "")); cubeCards.add(new CardIdentity("Stormfront Pegasus", ""));
cubeCards.add(new CardIdentity("Stormscape Apprentice", "")); cubeCards.add(new CardIdentity("Stormscape Apprentice", ""));
cubeCards.add(new CardIdentity("Strip Mine", "")); cubeCards.add(new CardIdentity("Strip Mine", ""));
cubeCards.add(new CardIdentity("Striped Riverwinder", ""));
cubeCards.add(new CardIdentity("Submerged Boneyard", ""));
cubeCards.add(new CardIdentity("Sultai Scavenger", "")); cubeCards.add(new CardIdentity("Sultai Scavenger", ""));
cubeCards.add(new CardIdentity("Suppression Bonds", "")); cubeCards.add(new CardIdentity("Suppression Bonds", ""));
cubeCards.add(new CardIdentity("Swift Spinner", ""));
cubeCards.add(new CardIdentity("Swiftwater Cliffs", "")); cubeCards.add(new CardIdentity("Swiftwater Cliffs", ""));
cubeCards.add(new CardIdentity("Sylvan Might", "")); cubeCards.add(new CardIdentity("Sylvan Might", ""));
cubeCards.add(new CardIdentity("Sylvok Lifestaff", "")); cubeCards.add(new CardIdentity("Sylvok Lifestaff", ""));
cubeCards.add(new CardIdentity("Tah-Crop Elite", "")); cubeCards.add(new CardIdentity("Tah-Crop Elite", ""));
cubeCards.add(new CardIdentity("Tajuru Pathwarden", ""));
cubeCards.add(new CardIdentity("Talruum Minotaur", ""));
cubeCards.add(new CardIdentity("Tandem Lookout", ""));
cubeCards.add(new CardIdentity("Temporal Isolation", "")); cubeCards.add(new CardIdentity("Temporal Isolation", ""));
cubeCards.add(new CardIdentity("Tenement Crasher", "")); cubeCards.add(new CardIdentity("Tenement Crasher", ""));
cubeCards.add(new CardIdentity("Terminate", "")); cubeCards.add(new CardIdentity("Terminate", ""));
@ -387,25 +391,26 @@ public AdamStyborskisPauperCube() {
cubeCards.add(new CardIdentity("Thornwood Falls", "")); cubeCards.add(new CardIdentity("Thornwood Falls", ""));
cubeCards.add(new CardIdentity("Thought Scour", "")); cubeCards.add(new CardIdentity("Thought Scour", ""));
cubeCards.add(new CardIdentity("Thraben Inspector", "")); cubeCards.add(new CardIdentity("Thraben Inspector", ""));
cubeCards.add(new CardIdentity("Thrill-Kill Assassin", ""));
cubeCards.add(new CardIdentity("Thundering Giant", "")); cubeCards.add(new CardIdentity("Thundering Giant", ""));
cubeCards.add(new CardIdentity("Thundering Tanadon", "")); cubeCards.add(new CardIdentity("Thundering Tanadon", ""));
cubeCards.add(new CardIdentity("Thunderous Wrath", "")); cubeCards.add(new CardIdentity("Thunderous Wrath", ""));
cubeCards.add(new CardIdentity("Timber Gorge", ""));
cubeCards.add(new CardIdentity("Time to Feed", "")); cubeCards.add(new CardIdentity("Time to Feed", ""));
cubeCards.add(new CardIdentity("Tithe Drinker", "")); cubeCards.add(new CardIdentity("Tithe Drinker", ""));
cubeCards.add(new CardIdentity("Totem-Guide Hartebeest", "")); cubeCards.add(new CardIdentity("Totem-Guide Hartebeest", ""));
cubeCards.add(new CardIdentity("Tragic Slip", "")); cubeCards.add(new CardIdentity("Tragic Slip", ""));
cubeCards.add(new CardIdentity("Tranquil Cove", "")); cubeCards.add(new CardIdentity("Tranquil Cove", ""));
cubeCards.add(new CardIdentity("Tranquil Expanse", ""));
cubeCards.add(new CardIdentity("Travel Preparations", "")); cubeCards.add(new CardIdentity("Travel Preparations", ""));
cubeCards.add(new CardIdentity("Treasure Cruise", "")); cubeCards.add(new CardIdentity("Treasure Cruise", ""));
cubeCards.add(new CardIdentity("Triplicate Spirits", "")); cubeCards.add(new CardIdentity("Triplicate Spirits", ""));
cubeCards.add(new CardIdentity("Tumble Magnet", ""));
cubeCards.add(new CardIdentity("Typhoid Rats", "")); cubeCards.add(new CardIdentity("Typhoid Rats", ""));
cubeCards.add(new CardIdentity("Ulamog's Crusher", "")); cubeCards.add(new CardIdentity("Ulamog's Crusher", ""));
cubeCards.add(new CardIdentity("Ulvenwald Captive", "")); cubeCards.add(new CardIdentity("Ulvenwald Captive", ""));
cubeCards.add(new CardIdentity("Undying Rage", "")); cubeCards.add(new CardIdentity("Undying Rage", ""));
cubeCards.add(new CardIdentity("Unearth", "")); cubeCards.add(new CardIdentity("Unearth", ""));
cubeCards.add(new CardIdentity("Unmake", "")); cubeCards.add(new CardIdentity("Unmake", ""));
cubeCards.add(new CardIdentity("Unnatural Aggression", ""));
cubeCards.add(new CardIdentity("Vampire Interloper", "")); cubeCards.add(new CardIdentity("Vampire Interloper", ""));
cubeCards.add(new CardIdentity("Vault Skirge", "")); cubeCards.add(new CardIdentity("Vault Skirge", ""));
cubeCards.add(new CardIdentity("Viashino Firstblade", "")); cubeCards.add(new CardIdentity("Viashino Firstblade", ""));
@ -424,7 +429,6 @@ public AdamStyborskisPauperCube() {
cubeCards.add(new CardIdentity("Wasteland Scorpion", "")); cubeCards.add(new CardIdentity("Wasteland Scorpion", ""));
cubeCards.add(new CardIdentity("Wayfarer's Bauble", "")); cubeCards.add(new CardIdentity("Wayfarer's Bauble", ""));
cubeCards.add(new CardIdentity("Werebear", "")); cubeCards.add(new CardIdentity("Werebear", ""));
cubeCards.add(new CardIdentity("Whirlpool Whelm", ""));
cubeCards.add(new CardIdentity("Whitemane Lion", "")); cubeCards.add(new CardIdentity("Whitemane Lion", ""));
cubeCards.add(new CardIdentity("Wild Instincts", "")); cubeCards.add(new CardIdentity("Wild Instincts", ""));
cubeCards.add(new CardIdentity("Wild Mongrel", "")); cubeCards.add(new CardIdentity("Wild Mongrel", ""));
@ -435,6 +439,7 @@ public AdamStyborskisPauperCube() {
cubeCards.add(new CardIdentity("Winds of Rebuke", "")); cubeCards.add(new CardIdentity("Winds of Rebuke", ""));
cubeCards.add(new CardIdentity("Winged Coatl", "")); cubeCards.add(new CardIdentity("Winged Coatl", ""));
cubeCards.add(new CardIdentity("Wojek Halberdiers", "")); cubeCards.add(new CardIdentity("Wojek Halberdiers", ""));
cubeCards.add(new CardIdentity("Woodland Stream", ""));
cubeCards.add(new CardIdentity("Wrecking Ball", "")); cubeCards.add(new CardIdentity("Wrecking Ball", ""));
cubeCards.add(new CardIdentity("Wretched Gryff", "")); cubeCards.add(new CardIdentity("Wretched Gryff", ""));
cubeCards.add(new CardIdentity("Yavimaya Elder", "")); cubeCards.add(new CardIdentity("Yavimaya Elder", ""));

View file

@ -21,6 +21,7 @@
<module>Mage.Game.CommanderFreeForAll</module> <module>Mage.Game.CommanderFreeForAll</module>
<module>Mage.Game.FreeForAll</module> <module>Mage.Game.FreeForAll</module>
<module>Mage.Game.MomirDuel</module> <module>Mage.Game.MomirDuel</module>
<module>Mage.Game.MomirGame</module>
<module>Mage.Game.TinyLeadersDuel</module> <module>Mage.Game.TinyLeadersDuel</module>
<module>Mage.Game.CanadianHighlanderDuel</module> <module>Mage.Game.CanadianHighlanderDuel</module>
<module>Mage.Game.PennyDreadfulCommanderFreeForAll</module> <module>Mage.Game.PennyDreadfulCommanderFreeForAll</module>

View file

@ -77,6 +77,7 @@
<gameType name="Canadian Highlander Two Player Duel" jar="mage-game-canadianhighlanderduel.jar" className="mage.game.CanadianHighlanderDuelMatch" typeName="mage.game.CanadianHighlanderDuelType"/> <gameType name="Canadian Highlander Two Player Duel" jar="mage-game-canadianhighlanderduel.jar" className="mage.game.CanadianHighlanderDuelMatch" typeName="mage.game.CanadianHighlanderDuelType"/>
<gameType name="Penny Dreadful Commander Free For All" jar="mage-game-pennydreadfulcommanderfreeforall.jar" className="mage.game.PennyDreadfulCommanderFreeForAllMatch" typeName="mage.game.PennyDreadfulCommanderFreeForAllType"/> <gameType name="Penny Dreadful Commander Free For All" jar="mage-game-pennydreadfulcommanderfreeforall.jar" className="mage.game.PennyDreadfulCommanderFreeForAllMatch" typeName="mage.game.PennyDreadfulCommanderFreeForAllType"/>
<gameType name="Momir Basic Two Player Duel" jar="mage-game-momirduel.jar" className="mage.game.MomirDuelMatch" typeName="mage.game.MomirDuelType"/> <gameType name="Momir Basic Two Player Duel" jar="mage-game-momirduel.jar" className="mage.game.MomirDuelMatch" typeName="mage.game.MomirDuelType"/>
<gameType name="Momir Basic Free For All" jar="mage-game-momir.jar" className="mage.game.MomirFreeForAllMatch" typeName="mage.game.MomirFreeForAllType"/>
</gameTypes> </gameTypes>
<tournamentTypes> <tournamentTypes>
<tournamentType name="Constructed Elimination" jar="mage-tournament-constructed.jar" className="mage.tournament.ConstructedEliminationTournament" typeName="mage.tournament.ConstructedEliminationTournamentType"/> <tournamentType name="Constructed Elimination" jar="mage-tournament-constructed.jar" className="mage.tournament.ConstructedEliminationTournament" typeName="mage.tournament.ConstructedEliminationTournamentType"/>

View file

@ -160,6 +160,12 @@
<version>${project.version}</version> <version>${project.version}</version>
<scope>runtime</scope> <scope>runtime</scope>
</dependency> </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>mage-game-momirfreeforall</artifactId>
<version>${project.version}</version>
<scope>runtime</scope>
</dependency>
<dependency> <dependency>
<groupId>org.apache.shiro</groupId> <groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId> <artifactId>shiro-core</artifactId>

View file

@ -0,0 +1,85 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.a;
import java.util.UUID;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.common.CastOnlyDuringPhaseStepSourceAbility;
import mage.abilities.condition.common.AttackedThisStepCondition;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.PhaseStep;
import mage.constants.TurnPhase;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.filter.predicate.permanent.AttackingPredicate;
import mage.target.common.TargetCreaturePermanent;
import mage.watchers.common.PlayerAttackedStepWatcher;
/**
*
* @author TheElk801
*/
public class AssassinsBlade extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nonblack attacking creature");
static {
filter.add(Predicates.not(new ColorPredicate(ObjectColor.BLACK)));
filter.add(new AttackingPredicate());
}
public AssassinsBlade(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{B}");
// Cast Assassin's Blade only during the declare attackers step and only if you've been attacked this step.
Ability ability = new CastOnlyDuringPhaseStepSourceAbility(
TurnPhase.COMBAT, PhaseStep.DECLARE_ATTACKERS, AttackedThisStepCondition.instance,
"Cast {this} only during the declare attackers step and only if you've been attacked this step."
);
ability.addWatcher(new PlayerAttackedStepWatcher());
this.addAbility(ability);
// Destroy target nonblack attacking creature.
this.getSpellAbility().addEffect(new DestroyTargetEffect());
this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter));
}
public AssassinsBlade(final AssassinsBlade card) {
super(card);
}
@Override
public AssassinsBlade copy() {
return new AssassinsBlade(this);
}
}

View file

@ -31,16 +31,22 @@ import java.util.UUID;
import mage.ObjectColor; import mage.ObjectColor;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ChooseColorEffect;
import mage.abilities.effects.common.continuous.GainProtectionFromColorTargetEffect; import mage.abilities.effects.common.continuous.GainProtectionFromColorTargetEffect;
import mage.abilities.keyword.ProtectionAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.choices.ChoiceColor;
import mage.constants.AbilityWord; import mage.constants.AbilityWord;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Duration; import mage.constants.Duration;
import mage.constants.Layer;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.constants.SubLayer;
import mage.filter.FilterObject;
import mage.filter.StaticFilters; import mage.filter.StaticFilters;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.players.Player; import mage.players.Player;
@ -49,7 +55,7 @@ import mage.target.targetpointer.FixedTarget;
/** /**
* *
* @author LevelX2 * @author LevelX2 & L_J
*/ */
public class BatheInLight extends CardImpl { public class BatheInLight extends CardImpl {
@ -57,7 +63,6 @@ public class BatheInLight extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}"); super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}");
// Radiance - Choose a color. Target creature and each other creature that shares a color with it gain protection from the chosen color until end of turn. // Radiance - Choose a color. Target creature and each other creature that shares a color with it gain protection from the chosen color until end of turn.
this.getSpellAbility().addEffect(new ChooseColorEffect(Outcome.Benefit));
this.getSpellAbility().addEffect(new BatheInLightEffect()); this.getSpellAbility().addEffect(new BatheInLightEffect());
this.getSpellAbility().addTarget(new TargetCreaturePermanent()); this.getSpellAbility().addTarget(new TargetCreaturePermanent());
this.getSpellAbility().setAbilityWord(AbilityWord.RADIANCE); this.getSpellAbility().setAbilityWord(AbilityWord.RADIANCE);
@ -95,12 +100,19 @@ class BatheInLightEffect extends OneShotEffect {
if (controller != null) { if (controller != null) {
Permanent target = game.getPermanent(getTargetPointer().getFirst(game, source)); Permanent target = game.getPermanent(getTargetPointer().getFirst(game, source));
if (target != null) { if (target != null) {
ChoiceColor colorChoice = new ChoiceColor();
if (controller.choose(Outcome.Benefit, colorChoice, game)) {
game.informPlayers(target.getName() + ": " + controller.getLogName() + " has chosen " + colorChoice.getChoice());
game.getState().setValue(target.getId() + "_color", colorChoice.getColor());
ObjectColor protectColor = (ObjectColor) game.getState().getValue(target.getId() + "_color"); ObjectColor protectColor = (ObjectColor) game.getState().getValue(target.getId() + "_color");
if (protectColor != null) { if (protectColor != null) {
ContinuousEffect effect = new ProtectionChosenColorTargetEffect();
game.addEffect(effect, source);
ObjectColor color = target.getColor(game); ObjectColor color = target.getColor(game);
for (Permanent permanent : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), source.getSourceId(), game)) { for (Permanent permanent : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), source.getSourceId(), game)) {
if (permanent.getColor(game).shares(color)) { if (permanent != target && permanent.getColor(game).shares(color)) {
ContinuousEffect effect = new GainProtectionFromColorTargetEffect(Duration.EndOfTurn, protectColor); game.getState().setValue(permanent.getId() + "_color", colorChoice.getColor());
effect.setTargetPointer(new FixedTarget(permanent, game)); effect.setTargetPointer(new FixedTarget(permanent, game));
game.addEffect(effect, source); game.addEffect(effect, source);
} }
@ -109,6 +121,51 @@ class BatheInLightEffect extends OneShotEffect {
} }
return true; return true;
} }
}
return false;
}
}
class ProtectionChosenColorTargetEffect extends ContinuousEffectImpl {
protected ObjectColor chosenColor;
protected ProtectionAbility protectionAbility;
public ProtectionChosenColorTargetEffect() {
super(Duration.EndOfTurn, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility);
}
public ProtectionChosenColorTargetEffect(final ProtectionChosenColorTargetEffect effect) {
super(effect);
if (effect.chosenColor != null) {
this.chosenColor = effect.chosenColor.copy();
}
if (effect.protectionAbility != null) {
this.protectionAbility = effect.protectionAbility.copy();
}
}
@Override
public ProtectionChosenColorTargetEffect copy() {
return new ProtectionChosenColorTargetEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
if (permanent != null) {
ObjectColor color = (ObjectColor) game.getState().getValue(permanent.getId() + "_color");
if (color != null && (protectionAbility == null || !color.equals(chosenColor))) {
chosenColor = color;
FilterObject protectionFilter = new FilterObject(chosenColor.getDescription());
protectionFilter.add(new ColorPredicate(chosenColor));
protectionAbility = new ProtectionAbility(protectionFilter);
}
if (protectionAbility != null) {
permanent.addAbility(protectionAbility, source.getSourceId(), game);
return true;
}
}
return false; return false;
} }
} }

View file

@ -33,7 +33,8 @@ import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl; import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.ReplacementEffectImpl; import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.effects.common.LoseLifeTargetEffect; import mage.abilities.effects.common.LoseLifeTargetEffect;
import mage.abilities.effects.common.combat.BlocksIfAbleAllEffect; import mage.abilities.effects.common.combat.BlocksIfAbleAllEffect;
@ -47,6 +48,7 @@ import mage.game.events.GameEvent;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.players.Player; import mage.players.Player;
import mage.target.targetpointer.FixedTarget; import mage.target.targetpointer.FixedTarget;
import mage.watchers.common.ChooseBlockersRedundancyWatcher;
/** /**
* *
@ -71,7 +73,9 @@ public class BrutalHordechief extends CardImpl {
// {3}{R/W}{R/W}: Creatures your opponents control block this turn if able, and you choose how those creatures block. // {3}{R/W}{R/W}: Creatures your opponents control block this turn if able, and you choose how those creatures block.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BlocksIfAbleAllEffect(filter, Duration.EndOfTurn), new ManaCostsImpl("{3}{R/W}{R/W}")); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BlocksIfAbleAllEffect(filter, Duration.EndOfTurn), new ManaCostsImpl("{3}{R/W}{R/W}"));
ability.addEffect(new BrutalHordechiefReplacementEffect()); ability.addEffect(new BrutalHordechiefChooseBlockersEffect());
ability.addWatcher(new ChooseBlockersRedundancyWatcher());
ability.addEffect(new ChooseBlockersRedundancyWatcherIncrementEffect());
this.addAbility(ability); this.addAbility(ability);
} }
@ -83,6 +87,32 @@ public class BrutalHordechief extends CardImpl {
public BrutalHordechief copy() { public BrutalHordechief copy() {
return new BrutalHordechief(this); return new BrutalHordechief(this);
} }
private class ChooseBlockersRedundancyWatcherIncrementEffect extends OneShotEffect {
ChooseBlockersRedundancyWatcherIncrementEffect() {
super(Outcome.Neutral);
}
ChooseBlockersRedundancyWatcherIncrementEffect(final ChooseBlockersRedundancyWatcherIncrementEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
ChooseBlockersRedundancyWatcher watcher = (ChooseBlockersRedundancyWatcher) game.getState().getWatchers().get(ChooseBlockersRedundancyWatcher.class.getSimpleName());
if (watcher != null) {
watcher.increment();
return true;
}
return false;
}
@Override
public ChooseBlockersRedundancyWatcherIncrementEffect copy() {
return new ChooseBlockersRedundancyWatcherIncrementEffect(this);
}
}
} }
class BrutalHordechiefTriggeredAbility extends TriggeredAbilityImpl { class BrutalHordechiefTriggeredAbility extends TriggeredAbilityImpl {
@ -123,20 +153,20 @@ class BrutalHordechiefTriggeredAbility extends TriggeredAbilityImpl {
} }
} }
class BrutalHordechiefReplacementEffect extends ReplacementEffectImpl { class BrutalHordechiefChooseBlockersEffect extends ContinuousRuleModifyingEffectImpl {
public BrutalHordechiefReplacementEffect() { public BrutalHordechiefChooseBlockersEffect() {
super(Duration.EndOfCombat, Outcome.Benefit); super(Duration.EndOfTurn, Outcome.Benefit, false, false);
staticText = ", and you choose how those creatures block"; staticText = "You choose which creatures block this turn and how those creatures block";
} }
public BrutalHordechiefReplacementEffect(final BrutalHordechiefReplacementEffect effect) { public BrutalHordechiefChooseBlockersEffect(final BrutalHordechiefChooseBlockersEffect effect) {
super(effect); super(effect);
} }
@Override @Override
public BrutalHordechiefReplacementEffect copy() { public BrutalHordechiefChooseBlockersEffect copy() {
return new BrutalHordechiefReplacementEffect(this); return new BrutalHordechiefChooseBlockersEffect(this);
} }
@Override @Override
@ -151,11 +181,13 @@ class BrutalHordechiefReplacementEffect extends ReplacementEffectImpl {
@Override @Override
public boolean applies(GameEvent event, Ability source, Game game) { public boolean applies(GameEvent event, Ability source, Game game) {
return event.getPlayerId().equals(source.getControllerId()); ChooseBlockersRedundancyWatcher watcher = (ChooseBlockersRedundancyWatcher) game.getState().getWatchers().get(ChooseBlockersRedundancyWatcher.class.getSimpleName());
watcher.decrement();
if (watcher.copyCountApply > 0) {
game.informPlayers(source.getSourceObject(game).getIdName() + " didn't apply");
return false;
} }
watcher.copyCountApply = watcher.copyCount;
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
Player blockController = game.getPlayer(source.getControllerId()); Player blockController = game.getPlayer(source.getControllerId());
if (blockController != null) { if (blockController != null) {
game.getCombat().selectBlockers(blockController, game); game.getCombat().selectBlockers(blockController, game);

View file

@ -28,16 +28,14 @@
package mage.cards.c; package mage.cards.c;
import java.util.UUID; import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl; import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.effects.Effect; import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.CounterTargetEffect;
import mage.abilities.effects.common.EntersBattlefieldWithXCountersEffect; import mage.abilities.effects.common.EntersBattlefieldWithXCountersEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone; import mage.constants.Zone;
import mage.counters.CounterType; import mage.counters.CounterType;
import mage.game.Game; import mage.game.Game;
@ -53,7 +51,7 @@ import mage.target.targetpointer.FixedTarget;
public class ChaliceOfTheVoid extends CardImpl { public class ChaliceOfTheVoid extends CardImpl {
public ChaliceOfTheVoid(UUID ownerId, CardSetInfo setInfo) { public ChaliceOfTheVoid(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{X}{X}"); super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{X}{X}");
// Chalice of the Void enters the battlefield with X charge counters on it. // Chalice of the Void enters the battlefield with X charge counters on it.
this.addAbility(new EntersBattlefieldAbility(new EntersBattlefieldWithXCountersEffect(CounterType.CHARGE.createInstance()))); this.addAbility(new EntersBattlefieldAbility(new EntersBattlefieldWithXCountersEffect(CounterType.CHARGE.createInstance())));
@ -75,7 +73,7 @@ public class ChaliceOfTheVoid extends CardImpl {
class ChaliceOfTheVoidTriggeredAbility extends TriggeredAbilityImpl { class ChaliceOfTheVoidTriggeredAbility extends TriggeredAbilityImpl {
public ChaliceOfTheVoidTriggeredAbility() { public ChaliceOfTheVoidTriggeredAbility() {
super(Zone.BATTLEFIELD, new CounterEffect()); super(Zone.BATTLEFIELD, new CounterTargetEffect());
} }
public ChaliceOfTheVoidTriggeredAbility(final ChaliceOfTheVoidTriggeredAbility abiltity) { public ChaliceOfTheVoidTriggeredAbility(final ChaliceOfTheVoidTriggeredAbility abiltity) {
@ -110,25 +108,3 @@ class ChaliceOfTheVoidTriggeredAbility extends TriggeredAbilityImpl {
return "Whenever a player casts a spell with converted mana cost equal to the number of charge counters on {this}, counter that spell."; return "Whenever a player casts a spell with converted mana cost equal to the number of charge counters on {this}, counter that spell.";
} }
} }
class CounterEffect extends OneShotEffect {
public CounterEffect() {
super(Outcome.Detriment);
}
public CounterEffect(final CounterEffect effect) {
super(effect);
}
@Override
public CounterEffect copy() {
return new CounterEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
return game.getStack().counter(this.getTargetPointer().getFirst(game, source), source.getSourceId(), game);
}
}

View file

@ -0,0 +1,73 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.c;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.CastOnlyDuringPhaseStepSourceAbility;
import mage.abilities.condition.common.AttackedThisStepCondition;
import mage.abilities.effects.common.ReturnToHandTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.PhaseStep;
import mage.constants.TurnPhase;
import mage.target.common.TargetAttackingCreature;
import mage.watchers.common.PlayerAttackedStepWatcher;
/**
*
* @author TheElk801
*/
public class ChampionsVictory extends CardImpl {
public ChampionsVictory(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{U}");
// Cast Champion's Victory only during the declare attackers step and only if you've been attacked this step.
Ability ability = new CastOnlyDuringPhaseStepSourceAbility(
TurnPhase.COMBAT, PhaseStep.DECLARE_ATTACKERS, AttackedThisStepCondition.instance,
"Cast {this} only during the declare attackers step and only if you've been attacked this step."
);
ability.addWatcher(new PlayerAttackedStepWatcher());
this.addAbility(ability);
// Return target attacking creature to its owner's hand.
this.getSpellAbility().addEffect(new ReturnToHandTargetEffect());
this.getSpellAbility().addTarget(new TargetAttackingCreature());
}
public ChampionsVictory(final ChampionsVictory card) {
super(card);
}
@Override
public ChampionsVictory copy() {
return new ChampionsVictory(this);
}
}

View file

@ -0,0 +1,74 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.c;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.CastOnlyDuringPhaseStepSourceAbility;
import mage.abilities.condition.common.AttackedThisStepCondition;
import mage.abilities.effects.common.ReturnToHandTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.PhaseStep;
import mage.constants.TurnPhase;
import mage.filter.common.FilterAttackingCreature;
import mage.target.common.TargetAttackingCreature;
import mage.watchers.common.PlayerAttackedStepWatcher;
/**
*
* @author TheElk801
*/
public class CommandOfUnsummoning extends CardImpl {
public CommandOfUnsummoning(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{U}");
// Cast Command of Unsummoning only during the declare attackers step and only if you've been attacked this step.
Ability ability = new CastOnlyDuringPhaseStepSourceAbility(
TurnPhase.COMBAT, PhaseStep.DECLARE_ATTACKERS, AttackedThisStepCondition.instance,
"Cast {this} only during the declare attackers step and only if you've been attacked this step."
);
ability.addWatcher(new PlayerAttackedStepWatcher());
this.addAbility(ability);
// Return one or two target attacking creatures to their owner's hand.
this.getSpellAbility().addEffect(new ReturnToHandTargetEffect().setText("Return one or two target attacking creatures to their owner's hand."));
this.getSpellAbility().addTarget(new TargetAttackingCreature(1, 2, new FilterAttackingCreature(), false));
}
public CommandOfUnsummoning(final CommandOfUnsummoning card) {
super(card);
}
@Override
public CommandOfUnsummoning copy() {
return new CommandOfUnsummoning(this);
}
}

View file

@ -60,21 +60,25 @@ public class ConfusionInTheRanks extends CardImpl {
filter.add(Predicates.or( filter.add(Predicates.or(
new CardTypePredicate(CardType.ARTIFACT), new CardTypePredicate(CardType.ARTIFACT),
new CardTypePredicate(CardType.CREATURE), new CardTypePredicate(CardType.CREATURE),
new CardTypePredicate(CardType.ENCHANTMENT))); new CardTypePredicate(CardType.ENCHANTMENT)
));
} }
private final UUID originalId; private final UUID originalId;
public ConfusionInTheRanks(UUID ownerId, CardSetInfo setInfo) { public ConfusionInTheRanks(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{3}{R}{R}"); super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{R}{R}");
// Whenever an artifact, creature, or enchantment enters the battlefield, its controller chooses target permanent another player controls that shares a card type with it. Exchange control of those permanents. // Whenever an artifact, creature, or enchantment enters the battlefield, its controller chooses target permanent another player controls that shares a card type with it. Exchange control of those permanents.
Ability ability = new EntersBattlefieldAllTriggeredAbility( Ability ability = new EntersBattlefieldAllTriggeredAbility(
Zone.BATTLEFIELD, Zone.BATTLEFIELD,
new ExchangeControlTargetEffect(Duration.EndOfGame, "its controller chooses target permanent another player controls that shares a card type with it. Exchange control of those permanents"), new ExchangeControlTargetEffect(
filter, Duration.EndOfGame,
false, "its controller chooses target permanent "
SetTargetPointer.PERMANENT, + "another player controls that shares a card type with it. "
null); + "Exchange control of those permanents"
),
filter, false, SetTargetPointer.PERMANENT, null
);
ability.addTarget(new TargetPermanent()); ability.addTarget(new TargetPermanent());
originalId = ability.getOriginalId(); originalId = ability.getOriginalId();
this.addAbility(ability); this.addAbility(ability);
@ -92,10 +96,13 @@ public class ConfusionInTheRanks extends CardImpl {
for (Effect effect : ability.getEffects()) { for (Effect effect : ability.getEffects()) {
enteringPermanentId = effect.getTargetPointer().getFirst(game, ability); enteringPermanentId = effect.getTargetPointer().getFirst(game, ability);
} }
if (enteringPermanentId != null) { if (enteringPermanentId == null) {
return;
}
Permanent enteringPermanent = game.getPermanent(enteringPermanentId); Permanent enteringPermanent = game.getPermanent(enteringPermanentId);
if (enteringPermanent != null) { if (enteringPermanent == null) {
ability.setControllerId(enteringPermanent.getControllerId()); return;
}
ability.getTargets().clear(); ability.getTargets().clear();
FilterPermanent filterTarget = new FilterPermanent(); FilterPermanent filterTarget = new FilterPermanent();
String message = ""; String message = "";
@ -109,11 +116,11 @@ public class ConfusionInTheRanks extends CardImpl {
message += cardTypeEntering.toString().toLowerCase() + ' '; message += cardTypeEntering.toString().toLowerCase() + ' ';
} }
filterTarget.add(Predicates.or(cardTypesPredicates)); filterTarget.add(Predicates.or(cardTypesPredicates));
message += "you do not control"; message += "you don't control";
filterTarget.setMessage(message); filterTarget.setMessage(message);
ability.getTargets().add(new TargetPermanent(filterTarget)); TargetPermanent target = new TargetPermanent(filterTarget);
} target.setTargetController(enteringPermanent.getControllerId());
} ability.getTargets().add(target);
} }
} }

View file

@ -29,7 +29,9 @@ package mage.cards.c;
import java.util.UUID; import java.util.UUID;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.*; import mage.constants.*;
@ -38,6 +40,7 @@ import mage.filter.predicate.mageobject.AnotherTargetPredicate;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetCreaturePermanent;
import mage.target.targetpointer.FixedTarget;
/** /**
* *
@ -46,8 +49,7 @@ import mage.target.common.TargetCreaturePermanent;
public class ConsumeStrength extends CardImpl { public class ConsumeStrength extends CardImpl {
public ConsumeStrength(UUID ownerId, CardSetInfo setInfo) { public ConsumeStrength(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{B}{G}"); super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{B}{G}");
// Target creature gets +2/+2 until end of turn. Another target creature gets -2/-2 until end of turn. // Target creature gets +2/+2 until end of turn. Another target creature gets -2/-2 until end of turn.
this.getSpellAbility().addEffect(new ConsumeStrengthEffect()); this.getSpellAbility().addEffect(new ConsumeStrengthEffect());
@ -74,10 +76,10 @@ public class ConsumeStrength extends CardImpl {
} }
} }
class ConsumeStrengthEffect extends ContinuousEffectImpl { class ConsumeStrengthEffect extends OneShotEffect {
public ConsumeStrengthEffect() { public ConsumeStrengthEffect() {
super(Duration.EndOfTurn, Layer.PTChangingEffects_7, SubLayer.ModifyPT_7c, Outcome.BoostCreature); super(Outcome.BoostCreature);
this.staticText = "Target creature gets +2/+2 until end of turn. Another target creature gets -2/-2 until end of turn"; this.staticText = "Target creature gets +2/+2 until end of turn. Another target creature gets -2/-2 until end of turn";
} }
@ -94,13 +96,15 @@ class ConsumeStrengthEffect extends ContinuousEffectImpl {
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getFirstTarget()); Permanent permanent = game.getPermanent(source.getFirstTarget());
if (permanent != null) { if (permanent != null) {
permanent.addPower(2); ContinuousEffect effect = new BoostTargetEffect(2, 2, Duration.EndOfTurn);
permanent.addToughness(2); effect.setTargetPointer(new FixedTarget(permanent, game));
game.addEffect(effect, source);
} }
permanent = game.getPermanent(source.getTargets().get(1).getFirstTarget()); permanent = game.getPermanent(source.getTargets().get(1).getFirstTarget());
if (permanent != null) { if (permanent != null) {
permanent.addPower(-2); ContinuousEffect effect = new BoostTargetEffect(-2, -2, Duration.EndOfTurn);
permanent.addToughness(-2); effect.setTargetPointer(new FixedTarget(permanent, game));
game.addEffect(effect, source);
} }
return true; return true;
} }

View file

@ -101,6 +101,7 @@ class ConundrumSphinxEffect extends OneShotEffect {
if (player != null) { if (player != null) {
if (player.getLibrary().hasCards()) { if (player.getLibrary().hasCards()) {
cardChoice.clearChoice(); cardChoice.clearChoice();
cardChoice.setMessage("Name a card");
while (!player.choose(Outcome.DrawCard, cardChoice, game) && player.canRespond()) { while (!player.choose(Outcome.DrawCard, cardChoice, game) && player.canRespond()) {
if (!player.canRespond()) { if (!player.canRespond()) {
continue Players; continue Players;

View file

@ -0,0 +1,67 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.c;
import java.util.UUID;
import mage.abilities.common.ActivateAsSorceryActivatedAbility;
import mage.abilities.costs.common.ExileFromGraveCost;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.common.discard.DiscardTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Zone;
import mage.filter.common.FilterCreatureCard;
import mage.target.TargetPlayer;
import mage.target.common.TargetCardInYourGraveyard;
/**
*
* @author LevelX2 & L_J
*/
public class Cryptwailing extends CardImpl {
public Cryptwailing(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{3}{B}");
// {1}, Exile two creature cards from your graveyard: Target player discards a card. Activate this ability only any time you could cast a sorcery.
ActivateAsSorceryActivatedAbility ability = new ActivateAsSorceryActivatedAbility(Zone.BATTLEFIELD, new DiscardTargetEffect(1), new GenericManaCost(1));
ability.addCost(new ExileFromGraveCost(new TargetCardInYourGraveyard(2,2, new FilterCreatureCard("two creature cards from your graveyard"))));
ability.addTarget(new TargetPlayer());
this.addAbility(ability);
}
public Cryptwailing(final Cryptwailing card) {
super(card);
}
@Override
public Cryptwailing copy() {
return new Cryptwailing(this);
}
}

View file

@ -0,0 +1,136 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.c;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.AttacksTriggeredAbility;
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
import mage.abilities.keyword.MeleeAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.FilterCard;
import mage.filter.common.FilterCreatureCard;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.CardTypePredicate;
import mage.filter.predicate.mageobject.ConvertedManaCostPredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.permanent.Permanent;
import mage.target.common.TargetCardInYourGraveyard;
import mage.watchers.Watcher;
/**
*
* @author L_J
*/
public class CustodiSoulcaller extends CardImpl {
public CustodiSoulcaller(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{W}{W}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.CLERIC);
this.power = new MageInt(1);
this.toughness = new MageInt(2);
// Melee
this.addAbility(new MeleeAbility());
// Whenever Custodi Soulcaller attacks, return target creature card with converted mana cost X or less from your graveyard to the battlefield, where X is the number of players you attacked with a creature this combat.
Ability ability = new AttacksTriggeredAbility(new ReturnFromGraveyardToBattlefieldTargetEffect(), false);
ability.addWatcher(new CustodiSoulcallerWatcher());
ability.addTarget(new TargetCardInYourGraveyard(new FilterCreatureCard("creature card with converted mana cost X or less from your graveyard, where X is the number of players you attacked with a creature this combat")));
this.addAbility(ability);
}
@Override
public void adjustTargets(Ability ability, Game game) {
if (ability.getClass().equals(AttacksTriggeredAbility.class)) {
ability.getTargets().clear();
CustodiSoulcallerWatcher watcher = (CustodiSoulcallerWatcher) game.getState().getWatchers().get(CustodiSoulcallerWatcher.class.getSimpleName());
Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(ability.getSourceId());
if (watcher != null && watcher.playersAttacked != null) {
int xValue = watcher.getNumberOfAttackedPlayers(sourcePermanent.getControllerId());
FilterCard filter = new FilterCard("creature card with converted mana cost " + xValue + " or less");
filter.add(new CardTypePredicate(CardType.CREATURE));
filter.add(Predicates.or(new ConvertedManaCostPredicate(ComparisonType.EQUAL_TO, xValue), new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, xValue)));
ability.getTargets().add(new TargetCardInYourGraveyard(filter));
}
}
}
public CustodiSoulcaller(final CustodiSoulcaller card) {
super(card);
}
@Override
public CustodiSoulcaller copy() {
return new CustodiSoulcaller(this);
}
}
class CustodiSoulcallerWatcher extends Watcher {
protected final HashMap<UUID, Set<UUID>> playersAttacked = new HashMap<>(0);
CustodiSoulcallerWatcher() {
super("CustodiSoulcallerWatcher", WatcherScope.GAME);
}
CustodiSoulcallerWatcher(final CustodiSoulcallerWatcher watcher) {
super(watcher);
this.playersAttacked.putAll(watcher.playersAttacked);
}
@Override
public void watch(GameEvent event, Game game) {
if (event.getType() == EventType.BEGIN_COMBAT_STEP_PRE) {
this.playersAttacked.clear();
}
else if (event.getType() == EventType.ATTACKER_DECLARED) {
Set<UUID> attackedPlayers = this.playersAttacked.getOrDefault(event.getPlayerId(), new HashSet<>(1));
attackedPlayers.add(event.getTargetId());
this.playersAttacked.put(event.getPlayerId(), attackedPlayers);
}
}
public int getNumberOfAttackedPlayers(UUID attackerId) {
return this.playersAttacked.get(attackerId).size();
}
@Override
public CustodiSoulcallerWatcher copy() {
return new CustodiSoulcallerWatcher(this);
}
}

View file

@ -53,7 +53,7 @@ import mage.target.common.TargetCreaturePermanent;
public class DarksteelMutation extends CardImpl { public class DarksteelMutation extends CardImpl {
public DarksteelMutation(UUID ownerId, CardSetInfo setInfo) { public DarksteelMutation(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{W}"); super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}");
this.subtype.add(SubType.AURA); this.subtype.add(SubType.AURA);
// Enchant creature // Enchant creature
@ -67,7 +67,7 @@ public class DarksteelMutation extends CardImpl {
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
new BecomesCreatureAttachedEffect(new DarksteelMutationInsectToken(), new BecomesCreatureAttachedEffect(new DarksteelMutationInsectToken(),
"Enchanted creature is an Insect artifact creature with base power and toughness 0/1 and has indestructible, and it loses all other abilities, card types, and creature types.", "Enchanted creature is an Insect artifact creature with base power and toughness 0/1 and has indestructible, and it loses all other abilities, card types, and creature types.",
Duration.WhileOnBattlefield, BecomesCreatureAttachedEffect.LoseType.ALL))); Duration.WhileOnBattlefield, BecomesCreatureAttachedEffect.LoseType.ALL_BUT_COLOR)));
} }

View file

@ -45,6 +45,7 @@ import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.mageobject.ColorPredicate; import mage.filter.predicate.mageobject.ColorPredicate;
import mage.game.Game; import mage.game.Game;
import mage.game.events.GameEvent; import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.target.TargetPermanent; import mage.target.TargetPermanent;
import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetCreaturePermanent;
@ -71,7 +72,6 @@ public class DaughterOfAutumn extends CardImpl {
// {W}: The next 1 damage that would be dealt to target white creature this turn is dealt to Daughter of Autumn instead. // {W}: The next 1 damage that would be dealt to target white creature this turn is dealt to Daughter of Autumn instead.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DaughterOfAutumnPreventDamageTargetEffect(Duration.EndOfTurn, 1), new ManaCostsImpl("{W}")); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DaughterOfAutumnPreventDamageTargetEffect(Duration.EndOfTurn, 1), new ManaCostsImpl("{W}"));
ability.addTarget(new TargetCreaturePermanent(filter)); ability.addTarget(new TargetCreaturePermanent(filter));
this.addAbility(ability);
} }
public DaughterOfAutumn(final DaughterOfAutumn card) { public DaughterOfAutumn(final DaughterOfAutumn card) {
@ -86,6 +86,8 @@ public class DaughterOfAutumn extends CardImpl {
class DaughterOfAutumnPreventDamageTargetEffect extends RedirectionEffect { class DaughterOfAutumnPreventDamageTargetEffect extends RedirectionEffect {
private static FilterCreaturePermanent filter = new FilterCreaturePermanent();
public DaughterOfAutumnPreventDamageTargetEffect(Duration duration, int amount) { public DaughterOfAutumnPreventDamageTargetEffect(Duration duration, int amount) {
super(duration, amount, true); super(duration, amount, true);
staticText = "The next " + amount + " damage that would be dealt to target white creature this turn is dealt to {this} instead"; staticText = "The next " + amount + " damage that would be dealt to target white creature this turn is dealt to {this} instead";
@ -102,13 +104,19 @@ class DaughterOfAutumnPreventDamageTargetEffect extends RedirectionEffect {
@Override @Override
public boolean applies(GameEvent event, Ability source, Game game) { public boolean applies(GameEvent event, Ability source, Game game) {
Permanent permanent = game.getBattlefield().getPermanent(source.getSourceId());
if (permanent != null) {
if (filter.match(permanent, permanent.getId(), permanent.getControllerId(), game)) {
if (event.getTargetId().equals(getTargetPointer().getFirst(game, source))) { if (event.getTargetId().equals(getTargetPointer().getFirst(game, source))) {
if (event.getTargetId() != null) {
TargetPermanent target = new TargetPermanent(); TargetPermanent target = new TargetPermanent();
target.add(source.getSourceId(), game); target.add(source.getSourceId(), game);
redirectTarget = target; redirectTarget = target;
return true; return true;
} }
}
}
}
return false; return false;
} }
} }

View file

@ -0,0 +1,118 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.d;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.CastOnlyDuringPhaseStepSourceAbility;
import mage.abilities.common.delayed.AtTheBeginOfNextUpkeepDelayedTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.PhaseStep;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.permanent.AttackingPredicate;
import mage.filter.predicate.permanent.BlockedPredicate;
import mage.game.Game;
import mage.game.combat.CombatGroup;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetCreaturePermanent;
/**
*
* @author LevelX2 & L_J
*/
public class DazzlingBeauty extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("unblocked attacking creature");
static {
filter.add(new AttackingPredicate());
filter.add(Predicates.not(new BlockedPredicate()));
}
public DazzlingBeauty(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{W}");
// Cast Dazzling Beauty only during the declare blockers step.
this.addAbility(new CastOnlyDuringPhaseStepSourceAbility(null, PhaseStep.DECLARE_BLOCKERS, null, "Cast Dazzling Beauty only during the declare blockers step"));
// Target unblocked attacking creature becomes blocked.
this.getSpellAbility().addEffect(new DazzlingBeautyEffect());
this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter));
// Draw a card at the beginning of the next turn's upkeep.
this.getSpellAbility().addEffect(new CreateDelayedTriggeredAbilityEffect(new AtTheBeginOfNextUpkeepDelayedTriggeredAbility(new DrawCardSourceControllerEffect(1)), false));
}
public DazzlingBeauty(final DazzlingBeauty card) {
super(card);
}
@Override
public DazzlingBeauty copy() {
return new DazzlingBeauty(this);
}
}
class DazzlingBeautyEffect extends OneShotEffect {
public DazzlingBeautyEffect() {
super(Outcome.Benefit);
this.staticText = "Target unblocked attacking creature becomes blocked";
}
public DazzlingBeautyEffect(final DazzlingBeautyEffect effect) {
super(effect);
}
@Override
public DazzlingBeautyEffect copy() {
return new DazzlingBeautyEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
if (controller != null && permanent != null) {
CombatGroup combatGroup = game.getCombat().findGroup(permanent.getId());
if (combatGroup != null) {
combatGroup.setBlocked(true);
return true;
}
}
return false;
}
}

View file

@ -0,0 +1,176 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.d;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbility;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.EquipAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.combat.CombatGroup;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.target.targetpointer.FixedTargets;
/**
*
* @author jerekwilson
*/
public class DeadIronSledge extends CardImpl {
public DeadIronSledge(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}");
this.subtype.add(SubType.EQUIPMENT);
// Whenever equipped creature blocks or becomes blocked by a creature, destroy both creatures.
this.addAbility(new DeadIronSledgeTriggeredAbility());
// Equip {2}
this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(2)));
}
public DeadIronSledge(final DeadIronSledge card) {
super(card);
}
@Override
public DeadIronSledge copy() {
return new DeadIronSledge(this);
}
}
class DeadIronSledgeTriggeredAbility extends TriggeredAbilityImpl {
private Set<UUID> possibleTargets = new HashSet<>();
DeadIronSledgeTriggeredAbility() {
super(Zone.BATTLEFIELD, new DeadIronSledgeDestroyEffect(), false);
}
DeadIronSledgeTriggeredAbility(final DeadIronSledgeTriggeredAbility ability) {
super(ability);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DECLARED_BLOCKERS;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
List<Permanent> targetPermanents = new ArrayList<>();
Permanent equipment = game.getPermanentOrLKIBattlefield((this.getSourceId()));
if (equipment != null && equipment.getAttachedTo() != null) {
Permanent equippedPermanent = game.getPermanentOrLKIBattlefield((equipment.getAttachedTo()));
if (equippedPermanent != null) {
possibleTargets.clear();
if (equippedPermanent.isBlocked(game)) {
possibleTargets.add(equippedPermanent.getId()); //add equipped creature to target list
}
if (equippedPermanent.isAttacking()) {
for (CombatGroup group : game.getCombat().getGroups()) {
if (group.getAttackers().contains(equippedPermanent.getId())) {
possibleTargets.addAll(group.getBlockers());
}
}
} else if (equippedPermanent.getBlocking() > 0) {
for (CombatGroup group : game.getCombat().getGroups()) {
if (group.getBlockers().contains(equippedPermanent.getId())) {
possibleTargets.addAll(group.getAttackers());
}
}
}
if (!possibleTargets.isEmpty()) {
this.getTargets().clear();
for (UUID creatureId : possibleTargets) {
Permanent target = game.getPermanentOrLKIBattlefield(creatureId);
targetPermanents.add(target);
}
this.getEffects().get(0).setTargetPointer(new FixedTargets(targetPermanents, game));
return true;
}
}
}
return false;
}
@Override
public TriggeredAbility copy() {
return new DeadIronSledgeTriggeredAbility(this);
}
@Override
public String getRule() {
return "Whenever equipped creature blocks or becomes blocked by a creature, destroy both creatures.";
}
}
class DeadIronSledgeDestroyEffect extends OneShotEffect {
public DeadIronSledgeDestroyEffect() {
super(Outcome.DestroyPermanent);
this.staticText = "destroy both creatures";
}
public DeadIronSledgeDestroyEffect(final DeadIronSledgeDestroyEffect effect) {
super(effect);
}
@Override
public DeadIronSledgeDestroyEffect copy() {
return new DeadIronSledgeDestroyEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
for (UUID targetId : this.getTargetPointer().getTargets(game, source)) {
Permanent permanent = game.getPermanent(targetId);
if (permanent != null) {
permanent.destroy(targetId, game, false);
}
}
return true;
}
}

View file

@ -30,9 +30,8 @@ package mage.cards.d;
import java.util.UUID; import java.util.UUID;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.CycleTriggeredAbility; import mage.abilities.common.CycleTriggeredAbility;
import mage.abilities.costs.Cost;
import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.costs.mana.ManaCost;
import mage.abilities.costs.mana.ManaCosts;
import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.dynamicvalue.common.ManacostVariableValue; import mage.abilities.dynamicvalue.common.ManacostVariableValue;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
@ -55,10 +54,9 @@ import mage.players.Player;
public class DecreeOfJustice extends CardImpl { public class DecreeOfJustice extends CardImpl {
public DecreeOfJustice(UUID ownerId, CardSetInfo setInfo) { public DecreeOfJustice(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{X}{X}{2}{W}{W}"); super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{X}{2}{W}{W}");
// Create X 4/4 white Angel creature tokens with flying.
// create X 4/4 white Angel creature tokens with flying.
this.getSpellAbility().addEffect(new CreateTokenEffect(new AngelToken(), new ManacostVariableValue())); this.getSpellAbility().addEffect(new CreateTokenEffect(new AngelToken(), new ManacostVariableValue()));
// Cycling {2}{W} // Cycling {2}{W}
@ -98,13 +96,13 @@ class DecreeOfJusticeCycleEffect extends OneShotEffect {
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId()); Player player = game.getPlayer(source.getControllerId());
ManaCosts<ManaCost> cost = new ManaCostsImpl<>("{X}");
if (player != null) { if (player != null) {
int costX = player.announceXMana(0, Integer.MAX_VALUE, "Announce the value for {X}", game, source); int X = player.announceXMana(0, Integer.MAX_VALUE, "Announce the value for {X}", game, source);
cost.add(new GenericManaCost(costX)); Cost cost = new GenericManaCost(X);
if (cost.pay(source, game, source.getSourceId(), source.getControllerId(), false, null)) { if (cost.pay(source, game, source.getSourceId(), source.getControllerId(), false)) {
Token token = new SoldierToken(); Token token = new SoldierToken();
token.putOntoBattlefield(costX, game, source.getSourceId(), source.getControllerId()); token.putOntoBattlefield(X, game, source.getSourceId(), source.getControllerId());
return true;
} }
} }
return false; return false;

View file

@ -0,0 +1,76 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.d;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.CastOnlyDuringPhaseStepSourceAbility;
import mage.abilities.condition.common.AttackedThisStepCondition;
import mage.abilities.effects.common.UntapTargetEffect;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.PhaseStep;
import mage.constants.TurnPhase;
import mage.target.common.TargetCreaturePermanent;
import mage.watchers.common.PlayerAttackedStepWatcher;
/**
*
* @author TheElk801
*/
public class DefiantStand extends CardImpl {
public DefiantStand(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}");
// Cast Defiant Stand only during the declare attackers step and only if you've been attacked this step.
Ability ability = new CastOnlyDuringPhaseStepSourceAbility(
TurnPhase.COMBAT, PhaseStep.DECLARE_ATTACKERS, AttackedThisStepCondition.instance,
"Cast {this} only during the declare attackers step and only if you've been attacked this step."
);
ability.addWatcher(new PlayerAttackedStepWatcher());
this.addAbility(ability);
// Target creature gets +1/+3 until end of turn. Untap that creature.
this.getSpellAbility().addEffect(new BoostTargetEffect(1, 3, Duration.EndOfTurn));
this.getSpellAbility().addEffect(new UntapTargetEffect().setText("Untap that creature"));
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
}
public DefiantStand(final DefiantStand card) {
super(card);
}
@Override
public DefiantStand copy() {
return new DefiantStand(this);
}
}

View file

@ -60,7 +60,7 @@ import mage.target.TargetPermanent;
public class DereviEmpyrialTactician extends CardImpl { public class DereviEmpyrialTactician extends CardImpl {
public DereviEmpyrialTactician(UUID ownerId, CardSetInfo setInfo) { public DereviEmpyrialTactician(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{G}{W}{U}"); super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}{W}{U}");
addSuperType(SuperType.LEGENDARY); addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.BIRD); this.subtype.add(SubType.BIRD);
this.subtype.add(SubType.WIZARD); this.subtype.add(SubType.WIZARD);
@ -132,7 +132,7 @@ class DereviEmpyrialTacticianTriggeredAbility extends TriggeredAbilityImpl {
} }
} }
class DereviEmpyrialTacticianAbility extends ActivatedAbilityImpl { class DereviEmpyrialTacticianAbility extends ActivatedAbilityImpl {
public DereviEmpyrialTacticianAbility() { public DereviEmpyrialTacticianAbility() {
super(Zone.COMMAND, new PutCommanderOnBattlefieldEffect(), new ManaCostsImpl("{1}{G}{W}{U}")); super(Zone.COMMAND, new PutCommanderOnBattlefieldEffect(), new ManaCostsImpl("{1}{G}{W}{U}"));
@ -182,7 +182,7 @@ class PutCommanderOnBattlefieldEffect extends OneShotEffect {
} }
Card card = game.getCard(source.getSourceId()); Card card = game.getCard(source.getSourceId());
if (card != null) { if (card != null) {
card.putOntoBattlefield(game, Zone.COMMAND, source.getSourceId(), source.getControllerId()); player.moveCards(card, Zone.BATTLEFIELD, source, game);
return true; return true;
} }
return false; return false;

View file

@ -0,0 +1,231 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.d;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.PreventionEffectImpl;
import mage.abilities.effects.common.PreventDamageBySourceEffect;
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.game.Game;
import mage.game.events.DamageEvent;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.game.stack.StackObject;
import mage.filter.FilterObject;
import mage.filter.predicate.permanent.ControllerPredicate;
import mage.players.Player;
import mage.target.TargetSource;
/**
*
* @author L_J
*/
public class DesperateGambit extends CardImpl {
public DesperateGambit(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{R}");
// Choose a source you control and flip a coin. If you win the flip, the next time that source would deal damage this turn, it deals double that damage instead. If you lose the flip, the next time it would deal damage this turn, prevent that damage.
this.getSpellAbility().addEffect(new DesperateGambitEffect());
}
public DesperateGambit(final DesperateGambit card) {
super(card);
}
@Override
public DesperateGambit copy() {
return new DesperateGambit(this);
}
}
class DesperateGambitEffect extends PreventionEffectImpl {
private final TargetSource target;
private boolean wonFlip;
public DesperateGambitEffect() {
super(Duration.EndOfTurn, Integer.MAX_VALUE, false);
staticText = "Choose a source you control and flip a coin. If you win the flip, the next time that source would deal damage this turn, it deals double that damage instead. If you lose the flip, the next time it would deal damage this turn, prevent that damage";
this.target = new TargetControlledSource();
}
public DesperateGambitEffect(final DesperateGambitEffect effect) {
super(effect);
this.target = effect.target.copy();
}
@Override
public void init(Ability source, Game game) {
this.target.choose(Outcome.Benefit, source.getControllerId(), source.getSourceId(), game);
this.wonFlip = game.getPlayer(source.getControllerId()).flipCoin(game);
super.init(source, game);
}
@Override
public DesperateGambitEffect copy() {
return new DesperateGambitEffect(this);
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DAMAGE_CREATURE ||
event.getType() == GameEvent.EventType.DAMAGE_PLANESWALKER ||
event.getType() == GameEvent.EventType.DAMAGE_PLAYER;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (event.getSourceId().equals(target.getFirstTarget())) {
// check source
MageObject object = game.getObject(event.getSourceId());
if (object == null) {
game.informPlayers("Couldn't find source of damage");
return false;
}
return true;
}
return false;
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
MageObject object = game.getObject(event.getSourceId());
Player controller = game.getPlayer(source.getControllerId());
if (controller != null && object != null) {
if (super.applies(event, source, game) && event instanceof DamageEvent && event.getAmount() > 0) {
if (wonFlip) {
event.setAmount(event.getAmount() * 2);
this.discard();
} else {
preventDamageAction(event, source, game);
this.discard();
return true;
}
}
}
return false;
}
}
class TargetControlledSource extends TargetSource {
public TargetControlledSource() {
super(1, 1, new FilterObject("source you control"));
}
public TargetControlledSource(final TargetControlledSource target) {
super(target);
}
@Override
public boolean canChoose(UUID sourceControllerId, Game game) {
int count = 0;
for (StackObject stackObject: game.getStack()) {
if (game.getState().getPlayersInRange(sourceControllerId, game).contains(stackObject.getControllerId())
&& stackObject.getControllerId() == sourceControllerId) {
count++;
if (count >= this.minNumberOfTargets) {
return true;
}
}
}
for (Permanent permanent: game.getBattlefield().getActivePermanents(sourceControllerId, game)) {
if (permanent.getControllerId() == sourceControllerId) {
count++;
if (count >= this.minNumberOfTargets) {
return true;
}
}
}
for (Player player : game.getPlayers().values()) {
if (player == game.getPlayer(sourceControllerId)) {
for (Card card : player.getGraveyard().getCards(game)) {
count++;
if (count >= this.minNumberOfTargets) {
return true;
}
}
// 108.4a If anything asks for the controller of a card that doesnt have one (because its not a permanent or spell), use its owner instead.
for (Card card : game.getExile().getAllCards(game)) {
if (card.getOwnerId() == sourceControllerId) {
count++;
if (count >= this.minNumberOfTargets) {
return true;
}
}
}
}
}
return false;
}
@Override
public Set<UUID> possibleTargets(UUID sourceControllerId, Game game) {
Set<UUID> possibleTargets = new HashSet<>();
for (StackObject stackObject: game.getStack()) {
if (game.getState().getPlayersInRange(sourceControllerId, game).contains(stackObject.getControllerId())
&& stackObject.getControllerId() == sourceControllerId) {
possibleTargets.add(stackObject.getId());
}
}
for (Permanent permanent: game.getBattlefield().getActivePermanents(sourceControllerId, game)) {
if (permanent.getControllerId() == sourceControllerId) {
possibleTargets.add(permanent.getId());
}
}
for (Player player : game.getPlayers().values()) {
if (player == game.getPlayer(sourceControllerId)) {
for (Card card : player.getGraveyard().getCards(game)) {
possibleTargets.add(card.getId());
}
// 108.4a If anything asks for the controller of a card that doesnt have one (because its not a permanent or spell), use its owner instead.
for (Card card : game.getExile().getAllCards(game)) {
if (card.getOwnerId() == sourceControllerId) {
possibleTargets.add(card.getId());
}
}
}
}
return possibleTargets;
}
@Override
public TargetControlledSource copy() {
return new TargetControlledSource(this);
}
}

View file

@ -0,0 +1,128 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.d;
import java.util.UUID;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DontUntapInControllersUntapStepAllEffect;
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.filter.common.FilterControlledCreaturePermanent;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.filter.predicate.permanent.TappedPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.Target;
import mage.target.common.TargetControlledCreaturePermanent;
/**
*
* @author spjspj & L_J
*/
public class DreamTides extends CardImpl {
public DreamTides(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}{U}");
// Creatures don't untap during their controllers' untap steps.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new DontUntapInControllersUntapStepAllEffect(Duration.WhileOnBattlefield, TargetController.ANY, new FilterCreaturePermanent("Creatures"))));
// At the beginning of each player's upkeep, that player may choose any number of tapped nongreen creatures he or she controls and pay {2} for each creature chosen this way. If the player does, untap those creatures.
this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new DreamTidesEffect(), TargetController.ANY, false));
}
public DreamTides(final DreamTides card) {
super(card);
}
@Override
public DreamTides copy() {
return new DreamTides(this);
}
}
class DreamTidesEffect extends OneShotEffect {
private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("tapped nongreen creature");
static {
filter.add(Predicates.not(new ColorPredicate(ObjectColor.GREEN)));
filter.add(new TappedPredicate());
}
DreamTidesEffect() {
super(Outcome.Benefit);
staticText = "that player may choose any number of tapped nongreen creatures he or she controls and pay {2} for each creature chosen this way. If the player does, untap those creatures";
}
DreamTidesEffect(DreamTidesEffect effect) {
super(effect);
}
@Override
public DreamTidesEffect copy() {
return new DreamTidesEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(targetPointer.getFirst(game, source));
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
if (player != null && sourcePermanent != null) {
int countBattlefield = game.getBattlefield().getAllActivePermanents(filter, game.getActivePlayerId(), game).size();
while (player.canRespond() && countBattlefield > 0 && player.chooseUse(Outcome.AIDontUseIt, "Pay {2} and untap a tapped nongreen creature under your control?", source, game)) {
Target tappedCreatureTarget = new TargetControlledCreaturePermanent(1, 1, filter, true);
if (player.choose(Outcome.Detriment, tappedCreatureTarget, source.getSourceId(), game)) {
GenericManaCost cost = new GenericManaCost(2);
Permanent tappedCreature = game.getPermanent(tappedCreatureTarget.getFirstTarget());
if (cost.pay(source, game, source.getSourceId(), player.getId(), false)) {
tappedCreature.untap(game);
}
}
countBattlefield = game.getBattlefield().getAllActivePermanents(filter, game.getActivePlayerId(), game).size();
}
return true;
}
return false;
}
}

View file

@ -0,0 +1,73 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.e;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.CastOnlyDuringPhaseStepSourceAbility;
import mage.abilities.condition.common.AttackedThisStepCondition;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.PhaseStep;
import mage.constants.TurnPhase;
import mage.target.common.TargetAttackingCreature;
import mage.watchers.common.PlayerAttackedStepWatcher;
/**
*
* @author TheElk801
*/
public class EightfoldMaze extends CardImpl {
public EightfoldMaze(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{W}");
// Cast Eightfold Maze only during the declare attackers step and only if you've been attacked this step.
Ability ability = new CastOnlyDuringPhaseStepSourceAbility(
TurnPhase.COMBAT, PhaseStep.DECLARE_ATTACKERS, AttackedThisStepCondition.instance,
"Cast {this} only during the declare attackers step and only if you've been attacked this step."
);
ability.addWatcher(new PlayerAttackedStepWatcher());
this.addAbility(ability);
// Destroy target attacking creature.
this.getSpellAbility().addEffect(new DestroyTargetEffect());
this.getSpellAbility().addTarget(new TargetAttackingCreature());
}
public EightfoldMaze(final EightfoldMaze card) {
super(card);
}
@Override
public EightfoldMaze copy() {
return new EightfoldMaze(this);
}
}

View file

@ -0,0 +1,186 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.e;
import java.util.Set;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
import mage.abilities.effects.AsThoughEffectImpl;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.AsThoughEffectType;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.SuperType;
import mage.constants.TargetController;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.filter.FilterCard;
import mage.players.Player;
import mage.target.targetpointer.FixedTarget;
import mage.util.RandomUtil;
/**
*
* @author L_J
*/
public class ElkinLair extends CardImpl {
public ElkinLair(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{R}");
addSuperType(SuperType.WORLD);
// At the beginning of each player's upkeep, that player exiles a card at random from his or her hand. The player may play that card this turn. At the beginning of the next end step, if the player hasn't played the card, he or she puts it into his or her graveyard.
this.addAbility(new BeginningOfUpkeepTriggeredAbility(new ElkinLairUpkeepEffect(), TargetController.ANY, false));
}
public ElkinLair(final ElkinLair card) {
super(card);
}
@Override
public ElkinLair copy() {
return new ElkinLair(this);
}
}
class ElkinLairUpkeepEffect extends OneShotEffect {
public ElkinLairUpkeepEffect() {
super(Outcome.Benefit);
this.staticText = "that player exiles a card at random from his or her hand. The player may play that card this turn. At the beginning of the next end step, if the player hasn't played the card, he or she puts it into his or her graveyard";
}
public ElkinLairUpkeepEffect(final ElkinLairUpkeepEffect effect) {
super(effect);
}
@Override
public ElkinLairUpkeepEffect copy() {
return new ElkinLairUpkeepEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(game.getActivePlayerId());
Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId());
if (player != null && sourcePermanent != null) {
Card[] cards = player.getHand().getCards(new FilterCard(), game).toArray(new Card[0]);
if (cards.length > 0) {
Card card = cards[RandomUtil.nextInt(cards.length)];
if (card != null) {
String exileName = sourcePermanent.getIdName() + " <this card may be played the turn it was exiled";
player.moveCardsToExile(card, source, game, true, source.getSourceId(), exileName);
if (game.getState().getZone(card.getId()) == Zone.EXILED) {
ContinuousEffect effect = new ElkinLairPlayExiledEffect(Duration.EndOfTurn);
effect.setTargetPointer(new FixedTarget(card.getId(), card.getZoneChangeCounter(game)));
game.addEffect(effect, source);
DelayedTriggeredAbility delayed = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new ElkinLairPutIntoGraveyardEffect());
game.addDelayedTriggeredAbility(delayed, source);
}
}
return true;
}
}
return false;
}
}
class ElkinLairPlayExiledEffect extends AsThoughEffectImpl {
public ElkinLairPlayExiledEffect(Duration duration) {
super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, duration, Outcome.Benefit);
staticText = "The player may play that card this turn";
}
public ElkinLairPlayExiledEffect(final ElkinLairPlayExiledEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
return true;
}
@Override
public ElkinLairPlayExiledEffect copy() {
return new ElkinLairPlayExiledEffect(this);
}
@Override
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
Card card = game.getCard(objectId);
if (card != null
&& affectedControllerId.equals(card.getOwnerId())
&& game.getState().getZone(card.getId()) == Zone.EXILED) {
return true;
}
return false;
}
}
class ElkinLairPutIntoGraveyardEffect extends OneShotEffect {
public ElkinLairPutIntoGraveyardEffect() {
super(Outcome.Neutral);
staticText = "if the player hasn't played the card, he or she puts it into his or her graveyard";
}
public ElkinLairPutIntoGraveyardEffect(final ElkinLairPutIntoGraveyardEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(game.getActivePlayerId());
if (player != null) {
Set<Card> cardsInExile = game.getExile().getExileZone(source.getSourceId()).getCards(game);
if (cardsInExile != null) {
player.moveCardsToGraveyardWithInfo(cardsInExile, source, game, Zone.EXILED);
return true;
}
}
return false;
}
@Override
public ElkinLairPutIntoGraveyardEffect copy() {
return new ElkinLairPutIntoGraveyardEffect(this);
}
}

View file

@ -0,0 +1,69 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.e;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.ActivateAsSorceryActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.InfoEffect;
import mage.abilities.effects.common.ReturnToHandTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.TargetController;
import mage.constants.Zone;
import mage.filter.common.FilterCreatureCard;
import mage.target.common.TargetCardInGraveyard;
/**
*
* @author L_J
*/
public class EndbringersRevel extends CardImpl {
public EndbringersRevel(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{B}");
// {4}: Return target creature card from a graveyard to its owner's hand. Any player may activate this ability but only any time he or she could cast a sorcery.
ActivateAsSorceryActivatedAbility ability = new ActivateAsSorceryActivatedAbility(Zone.BATTLEFIELD, new ReturnToHandTargetEffect(), new ManaCostsImpl("{4}"));
ability.addTarget(new TargetCardInGraveyard(new FilterCreatureCard("creature card in a graveyard")));
ability.setMayActivate(TargetController.ANY);
ability.addEffect(new InfoEffect("Any player may activate this ability"));
this.addAbility(ability);
}
public EndbringersRevel(final EndbringersRevel card) {
super(card);
}
@Override
public EndbringersRevel copy() {
return new EndbringersRevel(this);
}
}

View file

@ -27,11 +27,13 @@
*/ */
package mage.cards.e; package mage.cards.e;
import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.UUID; import java.util.UUID;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.PhaseOutAllEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
@ -55,8 +57,7 @@ import mage.target.TargetPlayer;
public class Equipoise extends CardImpl { public class Equipoise extends CardImpl {
public Equipoise(UUID ownerId, CardSetInfo setInfo) { public Equipoise(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{W}"); super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}");
// At the beginning of your upkeep, for each land target player controls in excess of the number you control, choose a land he or she controls, then the chosen permanents phase out. Repeat this process for artifacts and creatures. // At the beginning of your upkeep, for each land target player controls in excess of the number you control, choose a land he or she controls, then the chosen permanents phase out. Repeat this process for artifacts and creatures.
Ability ability = new BeginningOfUpkeepTriggeredAbility(new EquipoiseEffect(), TargetController.YOU, false); Ability ability = new BeginningOfUpkeepTriggeredAbility(new EquipoiseEffect(), TargetController.YOU, false);
@ -112,17 +113,12 @@ class EquipoiseEffect extends OneShotEffect {
int numberTargetPlayer = game.getBattlefield().count(filter, source.getSourceId(), targetPlayer.getId(), game); int numberTargetPlayer = game.getBattlefield().count(filter, source.getSourceId(), targetPlayer.getId(), game);
int excess = numberTargetPlayer - numberController; int excess = numberTargetPlayer - numberController;
if (excess > 0) { if (excess > 0) {
FilterPermanent filterChoose = new FilterPermanent(cardType.toString().toLowerCase() + (excess > 1 ? "s":"") +" of target player"); FilterPermanent filterChoose = new FilterPermanent(cardType.toString().toLowerCase() + (excess > 1 ? "s" : "") + " of target player");
filterChoose.add(new ControllerIdPredicate(targetPlayer.getId())); filterChoose.add(new ControllerIdPredicate(targetPlayer.getId()));
filterChoose.add(new CardTypePredicate(cardType)); filterChoose.add(new CardTypePredicate(cardType));
Target target = new TargetPermanent(excess, excess, filterChoose, true); Target target = new TargetPermanent(excess, excess, filterChoose, true);
controller.chooseTarget(outcome, target, source, game); controller.chooseTarget(outcome, target, source, game);
for (UUID permanentId:target.getTargets()) { new PhaseOutAllEffect(target.getTargets()).apply(game, source);
Permanent permanent = game.getPermanent(permanentId);
if (permanent != null) {
permanent.phaseOut(game);
}
}
} }
} }
} }

View file

@ -0,0 +1,137 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.e;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.Cost;
import mage.abilities.costs.common.SacrificeTargetCost;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.Target;
import mage.target.TargetCard;
import mage.target.common.TargetControlledCreaturePermanent;
/**
*
* @author L_J
*/
public class EyeOfYawgmoth extends CardImpl {
public EyeOfYawgmoth(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{3}");
// {3}, {T}, Sacrifice a creature: Reveal a number of cards from the top of your library equal to the sacrificed creature's power. Put one into your hand and exile the rest.
SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new EyeOfYawgmothEffect(), new GenericManaCost(3));
ability.addCost(new TapSourceCost());
ability.addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent(1, 1, new FilterControlledCreaturePermanent("a creature"), true)));
this.addAbility(ability);
}
public EyeOfYawgmoth(final EyeOfYawgmoth card) {
super(card);
}
@Override
public EyeOfYawgmoth copy() {
return new EyeOfYawgmoth(this);
}
}
class EyeOfYawgmothEffect extends OneShotEffect {
EyeOfYawgmothEffect() {
super(Outcome.Benefit);
this.staticText = "Reveal a number of cards from the top of your library equal to the sacrificed creature's power. Put one into your hand and exile the rest";
}
EyeOfYawgmothEffect(final EyeOfYawgmothEffect effect) {
super(effect);
}
@Override
public EyeOfYawgmothEffect copy() {
return new EyeOfYawgmothEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller == null) {
return false;
}
int power = 0;
for (Cost cost: source.getCosts()) {
if (cost instanceof SacrificeTargetCost && !((SacrificeTargetCost) cost).getPermanents().isEmpty()) {
power = ((SacrificeTargetCost)cost).getPermanents().get(0).getPower().getValue();
break;
}
}
if (power > 0) {
Cards cards = new CardsImpl();
int count = Math.min(controller.getLibrary().size(), power);
for (int i = 0; i < count; i++) {
Card card = controller.getLibrary().removeFromTop(game);
if (card != null) {
cards.add(card);
}
}
controller.revealCards(source.getSourceObject(game).getIdName(), cards, game);
TargetCard target = new TargetCard(Zone.LIBRARY, new FilterCard("card to put into your hand"));
if (controller.choose(Outcome.DrawCard, cards, target, game)) {
Card card = cards.get(target.getFirstTarget(), game);
if (card != null) {
cards.remove(card);
card.moveToZone(Zone.HAND, source.getSourceId(), game, false);
game.informPlayers(source.getSourceObject(game).getIdName() + ": " + controller.getLogName() + " puts " + card.getIdName() + " into his or her hand");
}
}
for (UUID cardId : cards) {
Card card = game.getCard(cardId);
card.moveToExile(null, "", source.getSourceId(), game);
}
}
return true;
}
}

View file

@ -0,0 +1,158 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.f;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.common.AttacksOrBlocksTriggeredAbility;
import mage.abilities.common.delayed.AtTheEndOfCombatDelayedTriggeredAbility;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.Target;
import mage.target.common.TargetOpponent;
import mage.target.targetpointer.FixedTarget;
/**
*
* @author L_J
*/
public class FickleEfreet extends CardImpl {
public FickleEfreet(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{R}");
this.subtype.add(SubType.EFREET);
this.power = new MageInt(5);
this.toughness = new MageInt(2);
// Whenever Fickle Efreet attacks or blocks, flip a coin at end of combat. If you lose the flip, an opponent gains control of Fickle Efreet.
this.addAbility(new AttacksOrBlocksTriggeredAbility(new CreateDelayedTriggeredAbilityEffect(
new AtTheEndOfCombatDelayedTriggeredAbility(new FickleEfreetChangeControlEffect()), true), false));
}
public FickleEfreet(final FickleEfreet card) {
super(card);
}
@Override
public FickleEfreet copy() {
return new FickleEfreet(this);
}
}
class FickleEfreetChangeControlEffect extends OneShotEffect {
public FickleEfreetChangeControlEffect() {
super(Outcome.Benefit);
this.staticText = "flip a coin at end of combat. If you lose the flip, choose one of your opponents. That player gains control of {this}";
}
public FickleEfreetChangeControlEffect(final FickleEfreetChangeControlEffect effect) {
super(effect);
}
@Override
public FickleEfreetChangeControlEffect copy() {
return new FickleEfreetChangeControlEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
if (controller != null) {
if (!controller.flipCoin(game)) {
if (sourcePermanent != null) {
Target target = new TargetOpponent(true);
if (target.canChoose(source.getSourceId(), controller.getId(), game)) {
while (!target.isChosen() && target.canChoose(controller.getId(), game) && controller.canRespond()) {
controller.chooseTarget(outcome, target, source, game);
}
}
Player chosenOpponent = game.getPlayer(target.getFirstTarget());
if (chosenOpponent != null) {
ContinuousEffect effect = new FickleEfreetGainControlEffect(Duration.Custom, target.getFirstTarget());
effect.setTargetPointer(new FixedTarget(sourcePermanent.getId()));
game.addEffect(effect, source);
game.informPlayers(chosenOpponent.getLogName() + " has gained control of " + sourcePermanent.getLogName());
return true;
}
}
}
}
return false;
}
}
class FickleEfreetGainControlEffect extends ContinuousEffectImpl {
UUID controller;
public FickleEfreetGainControlEffect(Duration duration, UUID controller) {
super(duration, Layer.ControlChangingEffects_2, SubLayer.NA, Outcome.GainControl);
this.controller = controller;
}
public FickleEfreetGainControlEffect(final FickleEfreetGainControlEffect effect) {
super(effect);
this.controller = effect.controller;
}
@Override
public FickleEfreetGainControlEffect copy() {
return new FickleEfreetGainControlEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getFirstTarget());
if (targetPointer != null) {
permanent = game.getPermanent(targetPointer.getFirst(game, source));
}
if (permanent != null) {
return permanent.changeControllerId(controller, game);
}
return false;
}
@Override
public String getText(Mode mode) {
return "That player gains control of {this}";
}
}

View file

@ -0,0 +1,86 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.f;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect;
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.counters.CounterType;
import mage.filter.FilterCard;
import mage.filter.StaticFilters;
import mage.target.common.TargetCardInOpponentsGraveyard;
import mage.target.common.TargetCreaturePermanent;
import mage.target.targetpointer.SecondTargetPointer;
/**
*
* @author L_J
*/
public class ForcemageAdvocate extends CardImpl {
public ForcemageAdvocate(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}");
this.subtype.add(SubType.CENTAUR);
this.subtype.add(SubType.SHAMAN);
this.power = new MageInt(2);
this.toughness = new MageInt(1);
// {tap}: Return target card from an opponent's graveyard to his or her hand. Put a +1/+1 counter on target creature.
Effect effect = new ReturnFromGraveyardToHandTargetEffect();
effect.setText("Return target card from an opponent's graveyard to his or her hand");
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new TapSourceCost());
effect = new AddCountersTargetEffect(CounterType.P1P1.createInstance());
effect.setText("Put a +1/+1 counter on target creature");
effect.setTargetPointer(new SecondTargetPointer());
ability.addEffect(effect);
ability.addTarget(new TargetCardInOpponentsGraveyard(1, 1, new FilterCard(), true));
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability);
}
public ForcemageAdvocate(final ForcemageAdvocate card) {
super(card);
}
@Override
public ForcemageAdvocate copy() {
return new ForcemageAdvocate(this);
}
}

View file

@ -0,0 +1,126 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.g;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.RedirectionEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.game.stack.Spell;
import mage.players.Player;
import mage.target.TargetSource;
import mage.target.common.TargetControlledCreaturePermanent;
/**
*
* @author L_J
*/
public class GeneralsRegalia extends CardImpl {
public GeneralsRegalia(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{3}");
// {3}: The next time a source of your choice would deal damage to you this turn, that damage is dealt to target creature you control instead.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new GeneralsRegaliaEffect(), new GenericManaCost(3));
ability.addTarget(new TargetControlledCreaturePermanent());
this.addAbility(ability);
}
public GeneralsRegalia(final GeneralsRegalia card) {
super(card);
}
@Override
public GeneralsRegalia copy() {
return new GeneralsRegalia(this);
}
}
class GeneralsRegaliaEffect extends RedirectionEffect {
private final TargetSource damageSource;
public GeneralsRegaliaEffect() {
super(Duration.EndOfTurn, Integer.MAX_VALUE, true);
staticText = "The next time a source of your choice would deal damage to you this turn, that damage is dealt to target creature you control instead";
this.damageSource = new TargetSource();
}
public GeneralsRegaliaEffect(final GeneralsRegaliaEffect effect) {
super(effect);
this.damageSource = effect.damageSource.copy();
}
@Override
public GeneralsRegaliaEffect copy() {
return new GeneralsRegaliaEffect(this);
}
@Override
public void init(Ability source, Game game) {
this.damageSource.choose(Outcome.PreventDamage, source.getControllerId(), source.getSourceId(), game);
super.init(source, game);
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
// check source
MageObject object = game.getObject(event.getSourceId());
if (object == null) {
game.informPlayers("Couldn't find source of damage");
return false;
}
if (!object.getId().equals(damageSource.getFirstTarget())
&& (!(object instanceof Spell) || !((Spell) object).getSourceId().equals(damageSource.getFirstTarget()))) {
return false;
}
this.redirectTarget = source.getTargets().get(0);
// check player
Player player = game.getPlayer(event.getTargetId());
if (player != null) {
if (player.getId().equals(source.getControllerId())) {
return true;
}
}
return false;
}
}

View file

@ -33,7 +33,6 @@ import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.ExileSourceEffect; import mage.abilities.effects.common.ExileSourceEffect;
import mage.abilities.effects.common.ExileTargetEffect; import mage.abilities.effects.common.ExileTargetEffect;
import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.FlyingAbility;
@ -42,11 +41,9 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.SubType; import mage.constants.SubType;
import mage.constants.Zone; import mage.constants.Zone;
import mage.filter.common.FilterAttackingCreature;
import mage.filter.predicate.Predicates; import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.AbilityPredicate; import mage.filter.predicate.mageobject.AbilityPredicate;
import mage.game.Game; import mage.target.common.FilterCreatureAttackingYou;
import mage.game.permanent.Permanent;
import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetCreaturePermanent;
/** /**
@ -55,7 +52,7 @@ import mage.target.common.TargetCreaturePermanent;
*/ */
public class GiantTrapDoorSpider extends CardImpl { public class GiantTrapDoorSpider extends CardImpl {
private static final HuntingKavuFilter filter = new HuntingKavuFilter(); private static final FilterCreatureAttackingYou filter = new FilterCreatureAttackingYou("creature without flying that's attacking you");
static { static {
filter.add(Predicates.not(new AbilityPredicate(FlyingAbility.class))); filter.add(Predicates.not(new AbilityPredicate(FlyingAbility.class)));
@ -71,7 +68,7 @@ public class GiantTrapDoorSpider extends CardImpl {
// {1}{R}{G}, {tap}: Exile Giant Trap Door Spider and target creature without flying that's attacking you. // {1}{R}{G}, {tap}: Exile Giant Trap Door Spider and target creature without flying that's attacking you.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ExileSourceEffect(), new ManaCostsImpl("{1}{R}{G}")); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ExileSourceEffect(), new ManaCostsImpl("{1}{R}{G}"));
ability.addCost(new TapSourceCost()); ability.addCost(new TapSourceCost());
ability.addEffect(new ExileTargetEffect()); ability.addEffect(new ExileTargetEffect().setText("and target creature without flying that's attacking you"));
ability.addTarget(new TargetCreaturePermanent(filter)); ability.addTarget(new TargetCreaturePermanent(filter));
this.addAbility(ability); this.addAbility(ability);
} }
@ -85,26 +82,3 @@ public class GiantTrapDoorSpider extends CardImpl {
return new GiantTrapDoorSpider(this); return new GiantTrapDoorSpider(this);
} }
} }
class HuntingKavuFilter extends FilterAttackingCreature {
public HuntingKavuFilter() {
super("creature without flying that's attacking you");
}
public HuntingKavuFilter(final HuntingKavuFilter filter) {
super(filter);
}
@Override
public HuntingKavuFilter copy() {
return new HuntingKavuFilter(this);
}
@Override
public boolean match(Permanent permanent, UUID sourceId, UUID playerId, Game game) {
return super.match(permanent, sourceId, playerId, game)
&& permanent.isAttacking() // to prevent unneccessary combat checking if not attacking
&& playerId.equals(game.getCombat().getDefenderId(permanent.getId()));
}
}

View file

@ -78,7 +78,7 @@ public class GleamOfAuthority extends CardImpl {
ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(VigilanceAbility.getInstance(), AttachmentType.AURA)); ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(VigilanceAbility.getInstance(), AttachmentType.AURA));
Ability gainedAbility = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BolsterEffect(1), new ManaCostsImpl("{W}")); Ability gainedAbility = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BolsterEffect(1), new ManaCostsImpl("{W}"));
gainedAbility.addCost(new TapSourceCost()); gainedAbility.addCost(new TapSourceCost());
ability.addEffect(new GainAbilityAttachedEffect(ability, AttachmentType.AURA).setText("and \"{W}, {T}: Bloster 1.\"")); ability.addEffect(new GainAbilityAttachedEffect(gainedAbility, AttachmentType.AURA).setText("and \"{W}, {T}: Bloster 1.\""));
this.addAbility(ability); this.addAbility(ability);
} }

View file

@ -48,7 +48,7 @@ import mage.target.common.TargetControlledCreaturePermanent;
public class GlenElendraPranksters extends CardImpl { public class GlenElendraPranksters extends CardImpl {
public GlenElendraPranksters(UUID ownerId, CardSetInfo setInfo) { public GlenElendraPranksters(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.FAERIE); this.subtype.add(SubType.FAERIE);
this.subtype.add(SubType.WIZARD); this.subtype.add(SubType.WIZARD);
this.power = new MageInt(1); this.power = new MageInt(1);
@ -57,8 +57,10 @@ public class GlenElendraPranksters extends CardImpl {
// Flying // Flying
this.addAbility(FlyingAbility.getInstance()); this.addAbility(FlyingAbility.getInstance());
// Whenever you cast a spell during an opponent's turn, you may return target creature you control to its owner's hand. // Whenever you cast a spell during an opponent's turn, you may return target creature you control to its owner's hand.
Ability ability = new ConditionalTriggeredAbility(new SpellCastControllerTriggeredAbility(new ReturnToHandTargetEffect(), true), OnOpponentsTurnCondition.instance, Ability ability = new ConditionalTriggeredAbility(
"Whenever you cast a spell during an opponent's turn, you may have target creature get -1/-1 until end of turn."); new SpellCastControllerTriggeredAbility(new ReturnToHandTargetEffect(), true), OnOpponentsTurnCondition.instance,
"Whenever you cast a spell during an opponent's turn, you may return target creature you control to its owner's hand."
);
ability.addTarget(new TargetControlledCreaturePermanent()); ability.addTarget(new TargetControlledCreaturePermanent());
this.addAbility(ability); this.addAbility(ability);
} }

View file

@ -31,7 +31,6 @@ import java.util.UUID;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.Mode; import mage.abilities.Mode;
import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.ContinuousEffectImpl;
@ -93,18 +92,27 @@ class GoblinFestivalChangeControlEffect extends OneShotEffect {
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId()); Player controller = game.getPlayer(source.getControllerId());
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
if (controller != null) { if (controller != null) {
if (!controller.flipCoin(game)) { if (!controller.flipCoin(game)) {
Target target = new TargetOpponent(); if (sourcePermanent != null) {
target.setNotTarget(true); Target target = new TargetOpponent(true);
if (controller.chooseTarget(outcome, target, source, game)) { if (target.canChoose(source.getSourceId(), controller.getId(), game)) {
ContinuousEffect effect = new GoblinFestivalGainControlEffect(Duration.Custom, target.getFirstTarget()); while (!target.isChosen() && target.canChoose(controller.getId(), game) && controller.canRespond()) {
effect.setTargetPointer(new FixedTarget(source.getSourceId())); controller.chooseTarget(outcome, target, source, game);
}
}
Player chosenOpponent = game.getPlayer(target.getFirstTarget());
if (chosenOpponent != null) {
ContinuousEffect effect = new GoblinFestivalGainControlEffect(Duration.Custom, chosenOpponent.getId());
effect.setTargetPointer(new FixedTarget(sourcePermanent.getId()));
game.addEffect(effect, source); game.addEffect(effect, source);
game.informPlayers(chosenOpponent.getLogName() + " has gained control of " + sourcePermanent.getLogName());
return true; return true;
} }
} }
} }
}
return false; return false;
} }
} }

View file

@ -0,0 +1,106 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.g;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.SacrificeSourceCost;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.dynamicvalue.common.PermanentsTargetOpponentControlsCount;
import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.common.FilterCreaturePermanent;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetOpponent;
/**
*
* @author L_J
*/
public class GoblinLyre extends CardImpl {
public GoblinLyre(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{3}");
// Sacrifice Goblin Lyre: Flip a coin. If you win the flip, Goblin Lyre deals damage to target opponent equal to the number of creatures you control. If you lose the flip, Goblin Lyre deals damage to you equal to the number of creatures that opponent controls.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new GoblinLyreEffect(), new SacrificeSourceCost());
ability.addTarget(new TargetOpponent());
this.addAbility(ability);
}
public GoblinLyre(final GoblinLyre card) {
super(card);
}
@Override
public GoblinLyre copy() {
return new GoblinLyre(this);
}
}
class GoblinLyreEffect extends OneShotEffect {
public GoblinLyreEffect() {
super(Outcome.Damage);
this.staticText = "Flip a coin. If you win the flip, {this} deals damage to target opponent equal to the number of creatures you control. If you lose the flip, {this} deals damage to you equal to the number of creatures that opponent controls";
}
public GoblinLyreEffect(final GoblinLyreEffect effect) {
super(effect);
}
@Override
public GoblinLyreEffect copy() {
return new GoblinLyreEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Player opponent = game.getPlayer(getTargetPointer().getFirst(game, source));
if (controller != null) {
if (controller.flipCoin(game)) {
if (opponent != null) {
opponent.damage(new PermanentsOnBattlefieldCount(new FilterControlledCreaturePermanent()).calculate(game, source, this), source.getSourceId(), game, false, true);
return true;
}
} else {
controller.damage(new PermanentsTargetOpponentControlsCount(new FilterCreaturePermanent()).calculate(game, source, this), source.getSourceId(), game, false, true);
return true;
}
}
return false;
}
}

View file

@ -0,0 +1,122 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.g;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.cards.Card;
import mage.constants.SubType;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.game.Game;
import mage.players.Library;
import mage.players.Player;
/**
*
* @author TheElk801
*/
public class GoblinMachinist extends CardImpl {
public GoblinMachinist(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{R}");
this.subtype.add(SubType.GOBLIN);
this.power = new MageInt(0);
this.toughness = new MageInt(5);
// {2}{R}: Reveal cards from the top of your library until you reveal a nonland card. Goblin Machinist gets +X/+0 until end of turn, where X is that card's converted mana cost. Put the revealed cards on the bottom of your library in any order.
this.addAbility(new SimpleActivatedAbility(new GoblinMachinistEffect(), new ManaCostsImpl("{2}{R}")));
}
public GoblinMachinist(final GoblinMachinist card) {
super(card);
}
@Override
public GoblinMachinist copy() {
return new GoblinMachinist(this);
}
}
class GoblinMachinistEffect extends OneShotEffect {
public GoblinMachinistEffect() {
super(Outcome.DrawCard);
this.staticText = "Reveal cards from the top of your library until you reveal a nonland card. {this} gets +X/+0 until end of turn, where X is that card's converted mana cost. Put the revealed cards on the bottom of your library in any order";
}
public GoblinMachinistEffect(final GoblinMachinistEffect effect) {
super(effect);
}
@Override
public GoblinMachinistEffect copy() {
return new GoblinMachinistEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
MageObject sourceObject = source.getSourceObject(game);
if (controller != null && sourceObject != null) {
if (controller.getLibrary().hasCards()) {
CardsImpl cards = new CardsImpl();
Library library = controller.getLibrary();
Card card = null;
do {
card = library.removeFromTop(game);
if (card != null) {
cards.add(card);
}
} while (library.hasCards() && card != null && card.isLand());
if (!cards.isEmpty()) {
controller.revealCards(sourceObject.getIdName(), cards, game);
}
boolean retVal = false;
if (card != null) {
retVal = new BoostSourceEffect(card.getConvertedManaCost(), 0, Duration.EndOfTurn).apply(game, source);
}
return controller.putCardsOnBottomOfLibrary(cards, game, source, true) && retVal;
}
return true;
}
return false;
}
}

View file

@ -0,0 +1,136 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.g;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.AttacksOrBlocksTriggeredAbility;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.game.Game;
import mage.game.events.DamageEvent;
import mage.game.events.GameEvent;
import mage.players.Player;
/**
*
* @author L_J
*/
public class GoblinPsychopath extends CardImpl {
public GoblinPsychopath(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{R}");
this.subtype.add(SubType.GOBLIN);
this.subtype.add(SubType.MUTANT);
this.power = new MageInt(5);
this.toughness = new MageInt(5);
// Whenever Goblin Psychopath attacks or blocks, flip a coin. If you lose the flip, the next time it would deal combat damage this turn, it deals that damage to you instead.
this.addAbility(new AttacksOrBlocksTriggeredAbility(new GoblinPsychopathEffect(), false));
}
public GoblinPsychopath(final GoblinPsychopath card) {
super(card);
}
@Override
public GoblinPsychopath copy() {
return new GoblinPsychopath(this);
}
}
class GoblinPsychopathEffect extends ReplacementEffectImpl {
private boolean wonFlip;
public GoblinPsychopathEffect() {
super(Duration.EndOfTurn, Outcome.RedirectDamage);
staticText = "flip a coin. If you lose the flip, the next time it would deal combat damage this turn, it deals that damage to you instead";
}
public GoblinPsychopathEffect(final GoblinPsychopathEffect effect) {
super(effect);
}
@Override
public void init(Ability source, Game game) {
this.wonFlip = game.getPlayer(source.getControllerId()).flipCoin(game);
super.init(source, game);
}
@Override
public GoblinPsychopathEffect copy() {
return new GoblinPsychopathEffect(this);
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DAMAGE_CREATURE ||
event.getType() == GameEvent.EventType.DAMAGE_PLANESWALKER ||
event.getType() == GameEvent.EventType.DAMAGE_PLAYER;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
MageObject object = game.getObject(event.getSourceId());
if (object == null) {
game.informPlayers("Couldn't find source of damage");
return false;
}
return event.getSourceId().equals(source.getSourceId());
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
MageObject object = game.getObject(event.getSourceId());
Player controller = game.getPlayer(source.getControllerId());
if (controller != null && object != null) {
if (this.applies(event, source, game) && event instanceof DamageEvent && event.getAmount() > 0) {
DamageEvent damageEvent = (DamageEvent) event;
if (damageEvent.isCombatDamage()) {
if (!wonFlip) {
// TODO: make this redirect damage from all blockers
controller.damage(event.getAmount(), source.getSourceId(), game, false, true);
String sourceLogName = source != null ? game.getObject(source.getSourceId()).getLogName() + ": " : "";
game.informPlayers(sourceLogName + "Redirected " + event.getAmount() + " damage to " + controller.getLogName());
this.discard();
return true;
}
}
}
}
return false;
}
}

View file

@ -0,0 +1,118 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.h;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.Cost;
import mage.abilities.costs.common.ExileFromHandCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ReturnToHandTargetEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.game.Game;
import mage.target.common.TargetCardInHand;
import mage.target.common.TargetCardInYourGraveyard;
import mage.target.targetpointer.FixedTarget;
/**
*
* @author L_J
*/
public class HolisticWisdom extends CardImpl {
public HolisticWisdom(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{G}{G}");
// {2}, Exile a card from your hand: Return target card from your graveyard to your hand if it shares a card type with the card exiled this way.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new HolisticWisdomEffect(), new ManaCostsImpl("{2}"));
ability.addCost(new ExileFromHandCost(new TargetCardInHand(new FilterCard("a card from your hand"))));
ability.addTarget(new TargetCardInYourGraveyard());
this.addAbility(ability);
}
public HolisticWisdom(final HolisticWisdom card) {
super(card);
}
@Override
public HolisticWisdom copy() {
return new HolisticWisdom(this);
}
}
class HolisticWisdomEffect extends OneShotEffect {
public HolisticWisdomEffect() {
super(Outcome.ReturnToHand);
this.staticText = "Return target card from your graveyard to your hand if it shares a card type with the card exiled this way";
}
public HolisticWisdomEffect(final HolisticWisdomEffect effect) {
super(effect);
}
@Override
public HolisticWisdomEffect copy() {
return new HolisticWisdomEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Card card = game.getCard(source.getFirstTarget());
if (card != null && game.getState().getZone(card.getId()) == Zone.GRAVEYARD) {
for (Cost cost : source.getCosts()) {
if (cost instanceof ExileFromHandCost) {
List<CardType> cardtypes = new ArrayList<>();
ExileFromHandCost exileCost = (ExileFromHandCost) cost;
for (CardType cardtype : exileCost.getCards().get(0).getCardType()) {
cardtypes.add(cardtype);
}
for (CardType cardtype : card.getCardType()) {
if (cardtypes.contains(cardtype)) {
Effect effect = new ReturnToHandTargetEffect();
effect.setTargetPointer(new FixedTarget(card.getId()));
return effect.apply(game, source);
}
}
}
}
}
return false;
}
}

View file

@ -33,7 +33,6 @@ import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.ExileSourceEffect; import mage.abilities.effects.common.ExileSourceEffect;
import mage.abilities.effects.common.ExileTargetEffect; import mage.abilities.effects.common.ExileTargetEffect;
import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.FlyingAbility;
@ -42,11 +41,9 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.SubType; import mage.constants.SubType;
import mage.constants.Zone; import mage.constants.Zone;
import mage.filter.common.FilterAttackingCreature;
import mage.filter.predicate.Predicates; import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.AbilityPredicate; import mage.filter.predicate.mageobject.AbilityPredicate;
import mage.game.Game; import mage.target.common.FilterCreatureAttackingYou;
import mage.game.permanent.Permanent;
import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetCreaturePermanent;
/** /**
@ -55,7 +52,7 @@ import mage.target.common.TargetCreaturePermanent;
*/ */
public class HuntingKavu extends CardImpl { public class HuntingKavu extends CardImpl {
private static final HuntingKavuFilter filter = new HuntingKavuFilter(); private static final FilterCreatureAttackingYou filter = new FilterCreatureAttackingYou("creature without flying that's attacking you");
static { static {
filter.add(Predicates.not(new AbilityPredicate(FlyingAbility.class))); filter.add(Predicates.not(new AbilityPredicate(FlyingAbility.class)));
@ -71,7 +68,7 @@ public class HuntingKavu extends CardImpl {
// {1}{R}{G}, {tap}: Exile Hunting Kavu and target creature without flying that's attacking you. // {1}{R}{G}, {tap}: Exile Hunting Kavu and target creature without flying that's attacking you.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ExileSourceEffect(), new ManaCostsImpl("{1}{R}{G}")); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ExileSourceEffect(), new ManaCostsImpl("{1}{R}{G}"));
ability.addCost(new TapSourceCost()); ability.addCost(new TapSourceCost());
ability.addEffect(new ExileTargetEffect()); ability.addEffect(new ExileTargetEffect().setText("nd target creature without flying that's attacking you"));
ability.addTarget(new TargetCreaturePermanent(filter)); ability.addTarget(new TargetCreaturePermanent(filter));
this.addAbility(ability); this.addAbility(ability);
} }
@ -85,26 +82,3 @@ public class HuntingKavu extends CardImpl {
return new HuntingKavu(this); return new HuntingKavu(this);
} }
} }
class HuntingKavuFilter extends FilterAttackingCreature {
public HuntingKavuFilter() {
super("creature without flying that's attacking you");
}
public HuntingKavuFilter(final HuntingKavuFilter filter) {
super(filter);
}
@Override
public HuntingKavuFilter copy() {
return new HuntingKavuFilter(this);
}
@Override
public boolean match(Permanent permanent, UUID sourceId, UUID playerId, Game game) {
return super.match(permanent, sourceId, playerId, game)
&& permanent.isAttacking() // to prevent unneccessary combat checking if not attacking
&& playerId.equals(game.getCombat().getDefenderId(permanent.getId()));
}
}

View file

@ -0,0 +1,81 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.i;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SkipUntapOptionalAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.effects.common.DontUntapAsLongAsSourceTappedEffect;
import mage.abilities.effects.common.TapTargetEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Zone;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.AbilityPredicate;
import mage.target.common.FilterCreatureAttackingYou;
import mage.target.common.TargetCreaturePermanent;
/**
*
*
* @author TheElk801
*/
public class IceFloe extends CardImpl {
private static final FilterCreatureAttackingYou filter = new FilterCreatureAttackingYou("creature without flying that's attacking you");
static {
filter.add(Predicates.not(new AbilityPredicate(FlyingAbility.class)));
}
public IceFloe(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.LAND}, "");
// You may choose not to untap Ice Floe during your untap step.
this.addAbility(new SkipUntapOptionalAbility());
// {T}: Tap target creature without flying that's attacking you. It doesn't untap during its controller's untap step for as long as Ice Floe remains tapped.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TapTargetEffect(), new TapSourceCost());
ability.addTarget(new TargetCreaturePermanent(filter));
ability.addEffect(new DontUntapAsLongAsSourceTappedEffect());
this.addAbility(ability);
}
public IceFloe(final IceFloe card) {
super(card);
}
@Override
public IceFloe copy() {
return new IceFloe(this);
}
}

View file

@ -0,0 +1,106 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.i;
import java.util.UUID;
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.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.permanent.ControllerIdPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.Target;
import mage.target.TargetPermanent;
import mage.target.common.TargetOpponent;
/**
*
* @author TheElk801
*/
public class ImperialEdict extends CardImpl {
public ImperialEdict(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{B}");
// Target opponent chooses a creature he or she controls. Destroy it.
this.getSpellAbility().addEffect(new ImperialEdictEffect());
this.getSpellAbility().addTarget(new TargetOpponent());
}
public ImperialEdict(final ImperialEdict card) {
super(card);
}
@Override
public ImperialEdict copy() {
return new ImperialEdict(this);
}
}
class ImperialEdictEffect extends OneShotEffect {
ImperialEdictEffect() {
super(Outcome.Benefit);
this.staticText = "Target opponent chooses a creature he or she controls. Destroy it.";
}
ImperialEdictEffect(final ImperialEdictEffect effect) {
super(effect);
}
@Override
public ImperialEdictEffect copy() {
return new ImperialEdictEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getFirstTarget());
if (player == null) {
return false;
}
FilterCreaturePermanent filter = new FilterCreaturePermanent("creature you control");
filter.add(new ControllerIdPredicate(player.getId()));
Target target = new TargetPermanent(1, 1, filter, true);
if (target.canChoose(source.getSourceId(), player.getId(), game)) {
while (!target.isChosen() && target.canChoose(player.getId(), game) && player.canRespond()) {
player.chooseTarget(Outcome.DestroyPermanent, target, source, game);
}
Permanent permanent = game.getPermanent(target.getFirstTarget());
if (permanent != null) {
permanent.destroy(source.getSourceId(), game, false);
}
}
return true;
}
}

View file

@ -0,0 +1,136 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.i;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.AttacksAllTriggeredAbility;
import mage.abilities.effects.PreventionEffectImpl;
import mage.abilities.effects.common.PreventDamageBySourceEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SetTargetPointer;
import mage.game.Game;
import mage.game.events.DamageEvent;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.filter.StaticFilters;
import mage.filter.predicate.permanent.ControllerPredicate;
import mage.players.Player;
/**
*
* @author L_J
*/
public class ImpulsiveManeuvers extends CardImpl {
public ImpulsiveManeuvers(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{R}{R}");
// Whenever a creature attacks, flip a coin. If you win the flip, the next time that creature would deal combat damage this turn, it deals double that damage instead. If you lose the flip, the next time that creature would deal combat damage this turn, prevent that damage.
this.addAbility(new AttacksAllTriggeredAbility(new ImpulsiveManeuversEffect(), false, StaticFilters.FILTER_PERMANENT_CREATURE,
SetTargetPointer.PERMANENT, false));
}
public ImpulsiveManeuvers(final ImpulsiveManeuvers card) {
super(card);
}
@Override
public ImpulsiveManeuvers copy() {
return new ImpulsiveManeuvers(this);
}
}
class ImpulsiveManeuversEffect extends PreventionEffectImpl {
private boolean wonFlip;
public ImpulsiveManeuversEffect() {
super(Duration.EndOfTurn, Integer.MAX_VALUE, false);
staticText = "flip a coin. If you win the flip, the next time that creature would deal combat damage this turn, it deals double that damage instead. If you lose the flip, the next time that creature would deal combat damage this turn, prevent that damage";
}
public ImpulsiveManeuversEffect(final ImpulsiveManeuversEffect effect) {
super(effect);
}
@Override
public void init(Ability source, Game game) {
this.wonFlip = game.getPlayer(source.getControllerId()).flipCoin(game);
super.init(source, game);
}
@Override
public ImpulsiveManeuversEffect copy() {
return new ImpulsiveManeuversEffect(this);
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DAMAGE_CREATURE ||
event.getType() == GameEvent.EventType.DAMAGE_PLANESWALKER ||
event.getType() == GameEvent.EventType.DAMAGE_PLAYER;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
MageObject object = game.getObject(event.getSourceId());
if (object == null) {
game.informPlayers("Couldn't find source of damage");
return false;
}
return event.getSourceId().equals(this.getTargetPointer().getFirst(game, source));
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
MageObject object = game.getObject(event.getSourceId());
Player controller = game.getPlayer(source.getControllerId());
if (controller != null && object != null) {
if (super.applies(event, source, game) && event instanceof DamageEvent && event.getAmount() > 0) {
DamageEvent damageEvent = (DamageEvent) event;
if (damageEvent.isCombatDamage()) {
if (wonFlip) {
event.setAmount(event.getAmount() * 2);
this.discard();
} else {
preventDamageAction(event, source, game);
this.discard();
return true;
}
}
}
}
return false;
}
}

View file

@ -37,10 +37,7 @@ import mage.cards.CardSetInfo;
import mage.constants.*; import mage.constants.*;
import mage.game.Game; import mage.game.Game;
import mage.game.events.GameEvent; import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.permanent.Permanent;
import mage.players.Player; import mage.players.Player;
import mage.players.PlayerList;
import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURES; import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURES;
/** /**
@ -71,7 +68,8 @@ public class InvasionPlans extends CardImpl {
class InvasionPlansEffect extends ContinuousRuleModifyingEffectImpl { class InvasionPlansEffect extends ContinuousRuleModifyingEffectImpl {
public InvasionPlansEffect() { public InvasionPlansEffect() {
super(Duration.WhileOnBattlefield, Outcome.Benefit, true, false); super(Duration.WhileOnBattlefield, Outcome.Benefit, false, false);
staticText = "The attacking player chooses how each creature blocks each turn";
} }
public InvasionPlansEffect(final InvasionPlansEffect effect) { public InvasionPlansEffect(final InvasionPlansEffect effect) {
@ -103,4 +101,3 @@ class InvasionPlansEffect extends ContinuousRuleModifyingEffectImpl {
return false; return false;
} }
} }

View file

@ -0,0 +1,153 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.j;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
import mage.abilities.common.DealtDamageToSourceTriggeredAbility;
import mage.abilities.condition.common.HellbentCondition;
import mage.abilities.decorator.ConditionalTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.AbilityWord;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
/**
*
* @author jerekwilson
*/
public class JaggedPoppet extends CardImpl {
public JaggedPoppet(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}{R}");
this.subtype.add(SubType.OGRE);
this.subtype.add(SubType.WARRIOR);
this.power = new MageInt(3);
this.toughness = new MageInt(4);
// Whenever Jagged Poppet is dealt damage, discard that many cards.
this.addAbility(new DealtDamageToSourceTriggeredAbility(Zone.BATTLEFIELD, new JaggedPoppetDealtDamageEffect(), false, false, true));
// Hellbent - Whenever Jagged Poppet deals combat damage to a player, if you have no cards in hand, that player discards cards equal to the damage.
Ability hellbentAbility = new ConditionalTriggeredAbility(
new DealsCombatDamageToAPlayerTriggeredAbility(new JaggedPoppetDealsDamageEffect(), false, true),
HellbentCondition.instance,
"<i>Hellbent</i> - Whenever {this} deals combat damage to a player, if you have no cards in hand, that player discards cards equal to the damage.");
hellbentAbility.setAbilityWord(AbilityWord.HELLBENT);
this.addAbility(hellbentAbility);
}
public JaggedPoppet(final JaggedPoppet card) {
super(card);
}
@Override
public JaggedPoppet copy() {
return new JaggedPoppet(this);
}
}
class JaggedPoppetDealsDamageEffect extends OneShotEffect {
public JaggedPoppetDealsDamageEffect() {
super(Outcome.Discard);
//staticText = "it deals that much damage to each creature that player controls";
}
public JaggedPoppetDealsDamageEffect(final JaggedPoppetDealsDamageEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
//According to the Balefire Dragon code, This statement gets the player that was dealt the combat damage
Player player = game.getPlayer(targetPointer.getFirst(game, source));
if (player != null) {
//Call the getValue method of the Effect class to retrieve the amount of damage
int amount = (Integer) getValue("damage");
if (amount > 0) {
//Call the player discard function discarding cards equal to damage
player.discard(amount, false, source, game);
}
return true;
}
return false;
}
@Override
public JaggedPoppetDealsDamageEffect copy() {
return new JaggedPoppetDealsDamageEffect(this);
}
}
class JaggedPoppetDealtDamageEffect extends OneShotEffect {
public JaggedPoppetDealtDamageEffect() {
super(Outcome.Discard);
staticText = "discard that many cards";
}
public JaggedPoppetDealtDamageEffect(final JaggedPoppetDealtDamageEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
//According to the Firedrinker Satyr code, This statement gets the player that controls Jagged Poppet
Player player = game.getPlayer(source.getControllerId());
if (player != null) {
//Call the getValue method of the Effect class to retrieve the amount of damage
int amount = (Integer) getValue("damage");
if (amount > 0) {
//Call the player discard function discarding cards equal to damage
player.discard(amount, false, source, game);
}
return true;
}
return false;
}
@Override
public JaggedPoppetDealtDamageEffect copy() {
return new JaggedPoppetDealtDamageEffect(this);
}
}

View file

@ -0,0 +1,87 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.j;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.common.BeginningOfCombatTriggeredAbility;
import mage.abilities.condition.CompoundCondition;
import mage.abilities.condition.Condition;
import mage.abilities.condition.InvertCondition;
import mage.abilities.condition.common.SourceOnBattlefieldCondition;
import mage.abilities.condition.common.SourceTappedCondition;
import mage.abilities.decorator.ConditionalContinuousEffect;
import mage.abilities.effects.common.combat.CantAttackSourceEffect;
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
import mage.abilities.keyword.special.JohanVigilanceAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.SuperType;
import mage.constants.TargetController;
import mage.filter.common.FilterControlledCreaturePermanent;
/**
*
* @author L_J
*/
public class Johan extends CardImpl {
public Johan(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}{G}{W}");
addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.WIZARD);
this.power = new MageInt(5);
this.toughness = new MageInt(4);
// At the beginning of combat on your turn, you may have Johan gain "Johan can't attack" until end of combat. If you do, attacking doesn't cause creatures you control to tap this combat if Johan is untapped.
Condition condition = new CompoundCondition("if {this} is untapped",
new InvertCondition(SourceTappedCondition.instance),
SourceOnBattlefieldCondition.instance);
Ability ability = new BeginningOfCombatTriggeredAbility(new CantAttackSourceEffect(Duration.EndOfCombat).setText("you may have {this} gain \"{this} can't attack\" until end of combat"), TargetController.YOU, true);
ability.addEffect(new ConditionalContinuousEffect(
new GainAbilityControlledEffect(JohanVigilanceAbility.getInstance(), Duration.EndOfCombat, new FilterControlledCreaturePermanent("creatures")),
condition,
"If you do, attacking doesn't cause creatures you control to tap this combat if {this} is untapped"));
this.addAbility(ability);
}
public Johan(final Johan card) {
super(card);
}
@Override
public Johan copy() {
return new Johan(this);
}
}

View file

@ -30,6 +30,7 @@ package mage.cards.k;
import java.util.UUID; import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.SpellAbility; import mage.abilities.SpellAbility;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.cost.CostModificationEffectImpl; import mage.abilities.effects.common.cost.CostModificationEffectImpl;
@ -111,7 +112,9 @@ class KopalaWardenOfWavesCostReductionEffect extends CostModificationEffectImpl
public boolean applies(Ability abilityToModify, Ability source, Game game) { public boolean applies(Ability abilityToModify, Ability source, Game game) {
if (abilityToModify.getAbilityType() == AbilityType.SPELL) { if (abilityToModify.getAbilityType() == AbilityType.SPELL) {
if (game.getOpponents(source.getControllerId()).contains(abilityToModify.getControllerId())) { if (game.getOpponents(source.getControllerId()).contains(abilityToModify.getControllerId())) {
for (Target target : abilityToModify.getTargets()) { for (UUID modeId : abilityToModify.getModes().getSelectedModes()) {
Mode mode = abilityToModify.getModes().get(modeId);
for (Target target : mode.getTargets()) {
for (UUID targetUUID : target.getTargets()) { for (UUID targetUUID : target.getTargets()) {
Permanent creature = game.getPermanent(targetUUID); Permanent creature = game.getPermanent(targetUUID);
if (creature != null if (creature != null
@ -123,6 +126,7 @@ class KopalaWardenOfWavesCostReductionEffect extends CostModificationEffectImpl
} }
} }
} }
}
return false; return false;
} }

View file

@ -0,0 +1,114 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.k;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfEndStepTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.condition.Condition;
import mage.abilities.costs.common.SacrificeTargetCost;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.effects.common.ReturnSourceFromGraveyardToHandEffect;
import mage.cards.Card;
import mage.constants.SubType;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.TargetController;
import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetControlledCreaturePermanent;
import mage.target.common.TargetCreatureOrPlayer;
/**
*
* @author TheElk801
*/
public class KrovikanHorror extends CardImpl {
public KrovikanHorror(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}");
this.subtype.add(SubType.HORROR);
this.subtype.add(SubType.SPIRIT);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// At the beginning of the end step, if Krovikan Horror is in your graveyard with a creature card directly above it, you may return Krovikan Horror to your hand.
this.addAbility(new BeginningOfEndStepTriggeredAbility(
Zone.GRAVEYARD, new ReturnSourceFromGraveyardToHandEffect(),
TargetController.ANY, KrovikanHorrorCondition.instance, true
));
// {1}, Sacrifice a creature: Krovikan Horror deals 1 damage to target creature or player.
SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(1), new GenericManaCost(1));
ability.addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent()));
ability.addTarget(new TargetCreatureOrPlayer());
this.addAbility(ability);
}
public KrovikanHorror(final KrovikanHorror card) {
super(card);
}
@Override
public KrovikanHorror copy() {
return new KrovikanHorror(this);
}
}
enum KrovikanHorrorCondition implements Condition {
instance;
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
boolean nextCard = false;
for (Card card : controller.getGraveyard().getCards(game)) {
if (nextCard) {
return card.isCreature();
}
if (card.getId().equals(source.getSourceId())) {
nextCard = true;
}
}
}
return false;
}
@Override
public String toString() {
return "{this} is in your graveyard with a creature card directly above it";
}
}

View file

@ -0,0 +1,112 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.l;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.BecomesBlockedTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.AssignNoCombatDamageSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetCreaturePermanent;
/**
*
* @author L_J
*/
public class LaccolithGrunt extends CardImpl {
public LaccolithGrunt(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}");
this.subtype.add(SubType.BEAST);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// Whenever Laccolith Grunt becomes blocked, you may have it deal damage equal to its power to target creature. If you do, Laccolith Grunt assigns no combat damage this turn.
Ability ability = new BecomesBlockedTriggeredAbility(new LaccolithEffect().setText("you may have it deal damage equal to its power to target creature"), true);
ability.addEffect(new AssignNoCombatDamageSourceEffect(Duration.EndOfTurn, true));
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability);
}
public LaccolithGrunt(final LaccolithGrunt card) {
super(card);
}
@Override
public LaccolithGrunt copy() {
return new LaccolithGrunt(this);
}
class LaccolithEffect extends OneShotEffect {
public LaccolithEffect() {
super(Outcome.Damage);
staticText = "{this} deals damage equal to its power to target creature";
}
public LaccolithEffect(final LaccolithEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
if (sourcePermanent == null) {
sourcePermanent = (Permanent) game.getLastKnownInformation(source.getSourceId(), Zone.BATTLEFIELD);
}
if (sourcePermanent == null) {
return false;
}
int damage = sourcePermanent.getPower().getValue();
Permanent permanent = game.getPermanent(source.getFirstTarget());
if (permanent != null) {
permanent.damage(damage, sourcePermanent.getId(), game, false, true);
return true;
}
return false;
}
@Override
public LaccolithEffect copy() {
return new LaccolithEffect(this);
}
}
}

View file

@ -0,0 +1,161 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.l;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.BecomesBlockedTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.continuous.AssignNoCombatDamageSourceEffect;
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
import mage.abilities.keyword.EnchantAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.TargetPermanent;
import mage.target.common.TargetCreaturePermanent;
import mage.target.targetpointer.FixedTarget;
/**
*
* @author L_J
*/
public class LaccolithRig extends CardImpl {
public LaccolithRig(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{R}");
this.subtype.add(SubType.AURA);
// Enchant creature
TargetPermanent auraTarget = new TargetCreaturePermanent();
this.getSpellAbility().addTarget(auraTarget);
this.getSpellAbility().addEffect(new AttachEffect(Outcome.Detriment));
Ability ability = new EnchantAbility(auraTarget.getTargetName());
this.addAbility(ability);
// Whenever enchanted creature becomes blocked, you may have it deal damage equal to its power to target creature. If you do, the first creature assigns no combat damage this turn.
Ability ability2 = new LaccolithRigTriggeredAbility(new LaccolithRigEffect(), true);
ability2.addTarget(new TargetCreaturePermanent());
Effect effect = new GainAbilityTargetEffect(new SimpleStaticAbility(Zone.BATTLEFIELD, new AssignNoCombatDamageSourceEffect(Duration.Custom, true).setText("")), Duration.EndOfTurn, "If you do, the first creature assigns no combat damage this turn");
ability2.addEffect(effect);
this.addAbility(ability2);
}
public LaccolithRig(final LaccolithRig card) {
super(card);
}
@Override
public LaccolithRig copy() {
return new LaccolithRig(this);
}
}
class LaccolithRigTriggeredAbility extends TriggeredAbilityImpl {
public LaccolithRigTriggeredAbility(Effect effect, boolean optional) {
super(Zone.BATTLEFIELD, effect, optional);
}
public LaccolithRigTriggeredAbility(final LaccolithRigTriggeredAbility ability) {
super(ability);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == EventType.CREATURE_BLOCKED;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Permanent equipment = game.getPermanent(sourceId);
if (equipment != null && equipment.getAttachedTo() != null) {
Permanent equipped = game.getPermanent(equipment.getAttachedTo());
if (equipped.getId().equals(event.getTargetId())) {
getEffects().get(1).setTargetPointer(new FixedTarget(equipped.getId()));
return true;
}
}
return false;
}
@Override
public String getRule() {
return "Whenever enchanted creature becomes blocked by a creature, " + super.getRule();
}
@Override
public LaccolithRigTriggeredAbility copy() {
return new LaccolithRigTriggeredAbility(this);
}
}
class LaccolithRigEffect extends OneShotEffect {
public LaccolithRigEffect() {
super(Outcome.Damage);
this.staticText = "you may have it deal damage equal to its power to target creature";
}
public LaccolithRigEffect(final LaccolithRigEffect effect) {
super(effect);
}
@Override
public LaccolithRigEffect copy() {
return new LaccolithRigEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent enchantment = game.getPermanentOrLKIBattlefield(source.getSourceId());
Permanent ownCreature = game.getPermanent(enchantment.getAttachedTo());
if (ownCreature != null) {
int damage = ownCreature.getPower().getValue();
Permanent targetCreature = game.getPermanent(source.getFirstTarget());
if (targetCreature != null) {
targetCreature.damage(damage, ownCreature.getId(), game, false, true);
return true;
}
}
return false;
}
}

View file

@ -0,0 +1,112 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.l;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.BecomesBlockedTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.AssignNoCombatDamageSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetCreaturePermanent;
/**
*
* @author L_J
*/
public class LaccolithTitan extends CardImpl {
public LaccolithTitan(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{R}{R}");
this.subtype.add(SubType.BEAST);
this.power = new MageInt(6);
this.toughness = new MageInt(6);
// Whenever Laccolith Grunt becomes blocked, you may have it deal damage equal to its power to target creature. If you do, Laccolith Grunt assigns no combat damage this turn.
Ability ability = new BecomesBlockedTriggeredAbility(new LaccolithEffect().setText("you may have it deal damage equal to its power to target creature"), true);
ability.addEffect(new AssignNoCombatDamageSourceEffect(Duration.EndOfTurn, true));
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability);
}
public LaccolithTitan(final LaccolithTitan card) {
super(card);
}
@Override
public LaccolithTitan copy() {
return new LaccolithTitan(this);
}
class LaccolithEffect extends OneShotEffect {
public LaccolithEffect() {
super(Outcome.Damage);
staticText = "{this} deals damage equal to its power to target creature";
}
public LaccolithEffect(final LaccolithEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
if (sourcePermanent == null) {
sourcePermanent = (Permanent) game.getLastKnownInformation(source.getSourceId(), Zone.BATTLEFIELD);
}
if (sourcePermanent == null) {
return false;
}
int damage = sourcePermanent.getPower().getValue();
Permanent permanent = game.getPermanent(source.getFirstTarget());
if (permanent != null) {
permanent.damage(damage, sourcePermanent.getId(), game, false, true);
return true;
}
return false;
}
@Override
public LaccolithEffect copy() {
return new LaccolithEffect(this);
}
}
}

View file

@ -0,0 +1,113 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.l;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.BecomesBlockedTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.AssignNoCombatDamageSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetCreaturePermanent;
/**
*
* @author L_J
*/
public class LaccolithWarrior extends CardImpl {
public LaccolithWarrior(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}{R}");
this.subtype.add(SubType.BEAST);
this.subtype.add(SubType.WARRIOR);
this.power = new MageInt(3);
this.toughness = new MageInt(3);
// Whenever Laccolith Grunt becomes blocked, you may have it deal damage equal to its power to target creature. If you do, Laccolith Grunt assigns no combat damage this turn.
Ability ability = new BecomesBlockedTriggeredAbility(new LaccolithEffect().setText("you may have it deal damage equal to its power to target creature"), true);
ability.addEffect(new AssignNoCombatDamageSourceEffect(Duration.EndOfTurn, true));
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability);
}
public LaccolithWarrior(final LaccolithWarrior card) {
super(card);
}
@Override
public LaccolithWarrior copy() {
return new LaccolithWarrior(this);
}
class LaccolithEffect extends OneShotEffect {
public LaccolithEffect() {
super(Outcome.Damage);
staticText = "{this} deals damage equal to its power to target creature";
}
public LaccolithEffect(final LaccolithEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
if (sourcePermanent == null) {
sourcePermanent = (Permanent) game.getLastKnownInformation(source.getSourceId(), Zone.BATTLEFIELD);
}
if (sourcePermanent == null) {
return false;
}
int damage = sourcePermanent.getPower().getValue();
Permanent permanent = game.getPermanent(source.getFirstTarget());
if (permanent != null) {
permanent.damage(damage, sourcePermanent.getId(), game, false, true);
return true;
}
return false;
}
@Override
public LaccolithEffect copy() {
return new LaccolithEffect(this);
}
}
}

View file

@ -0,0 +1,112 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.l;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.BecomesBlockedTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.AssignNoCombatDamageSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetCreaturePermanent;
/**
*
* @author L_J
*/
public class LaccolithWhelp extends CardImpl {
public LaccolithWhelp(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{R}");
this.subtype.add(SubType.BEAST);
this.power = new MageInt(1);
this.toughness = new MageInt(1);
// Whenever Laccolith Grunt becomes blocked, you may have it deal damage equal to its power to target creature. If you do, Laccolith Grunt assigns no combat damage this turn.
Ability ability = new BecomesBlockedTriggeredAbility(new LaccolithEffect().setText("you may have it deal damage equal to its power to target creature"), true);
ability.addEffect(new AssignNoCombatDamageSourceEffect(Duration.EndOfTurn, true));
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability);
}
public LaccolithWhelp(final LaccolithWhelp card) {
super(card);
}
@Override
public LaccolithWhelp copy() {
return new LaccolithWhelp(this);
}
class LaccolithEffect extends OneShotEffect {
public LaccolithEffect() {
super(Outcome.Damage);
staticText = "{this} deals damage equal to its power to target creature";
}
public LaccolithEffect(final LaccolithEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
if (sourcePermanent == null) {
sourcePermanent = (Permanent) game.getLastKnownInformation(source.getSourceId(), Zone.BATTLEFIELD);
}
if (sourcePermanent == null) {
return false;
}
int damage = sourcePermanent.getPower().getValue();
Permanent permanent = game.getPermanent(source.getFirstTarget());
if (permanent != null) {
permanent.damage(damage, sourcePermanent.getId(), game, false, true);
return true;
}
return false;
}
@Override
public LaccolithEffect copy() {
return new LaccolithEffect(this);
}
}
}

View file

@ -0,0 +1,129 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.l;
import java.util.UUID;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.abilities.keyword.EnchantAbility;
import mage.abilities.keyword.FlashAbility;
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.FilterPermanent;
import mage.filter.predicate.mageobject.CardTypePredicate;
import mage.filter.predicate.permanent.ControllerIdPredicate;
import mage.game.Game;
import mage.game.events.DamagedPlayerEvent;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.TargetPermanent;
import mage.target.common.TargetCreaturePermanent;
/**
*
* @author L_J
*/
public class LatullasOrders extends CardImpl {
public LatullasOrders(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{R}");
this.subtype.add(SubType.AURA);
// Flash
this.addAbility(FlashAbility.getInstance());
// Enchant creature
TargetPermanent auraTarget = new TargetCreaturePermanent();
this.getSpellAbility().addTarget(auraTarget);
this.getSpellAbility().addEffect(new AttachEffect(Outcome.Protect));
this.addAbility(new EnchantAbility(auraTarget.getTargetName()));
// Whenever enchanted creature deals combat damage to defending player, you may destroy target artifact that player controls.
this.addAbility(new LatullasOrdersTriggeredAbility());
}
public LatullasOrders(final LatullasOrders card) {
super(card);
}
@Override
public LatullasOrders copy() {
return new LatullasOrders(this);
}
}
class LatullasOrdersTriggeredAbility extends TriggeredAbilityImpl {
public LatullasOrdersTriggeredAbility() {
super(Zone.BATTLEFIELD, new DestroyTargetEffect(), true);
}
public LatullasOrdersTriggeredAbility(final LatullasOrdersTriggeredAbility ability) {
super(ability);
}
@Override
public LatullasOrdersTriggeredAbility copy() {
return new LatullasOrdersTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == EventType.DAMAGED_PLAYER;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Permanent enchantment = game.getPermanentOrLKIBattlefield(this.getSourceId());
if (event.getSourceId().equals(enchantment.getAttachedTo()) && ((DamagedPlayerEvent) event).isCombatDamage()) {
Player player = game.getPlayer(event.getTargetId());
if (player != null) {
FilterPermanent filter = new FilterPermanent("an artifact controlled by " + player.getLogName());
filter.add(new CardTypePredicate(CardType.ARTIFACT));
filter.add(new ControllerIdPredicate(event.getTargetId()));
this.getTargets().clear();
this.addTarget(new TargetPermanent(filter));
return true;
}
}
return false;
}
@Override
public String getRule() {
return "Whenever enchanted creature deals combat damage to defending player, you may destroy target artifact that player controls.";
}
}

View file

@ -36,9 +36,7 @@ import mage.abilities.keyword.LeylineAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.*; import mage.constants.*;
import mage.filter.FilterPermanent; import mage.filter.common.FilterNonlandPermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.CardTypePredicate;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
@ -48,21 +46,14 @@ import mage.game.permanent.Permanent;
*/ */
public class LeylineOfSingularity extends CardImpl { public class LeylineOfSingularity extends CardImpl {
private static final FilterPermanent filter = new FilterPermanent("nonland permanents");
static {
filter.add(Predicates.not(new CardTypePredicate(CardType.LAND)));
}
public LeylineOfSingularity(UUID ownerId, CardSetInfo setInfo) { public LeylineOfSingularity(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{U}{U}"); super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}{U}");
// If Leyline of Singularity is in your opening hand, you may begin the game with it on the battlefield. // If Leyline of Singularity is in your opening hand, you may begin the game with it on the battlefield.
this.addAbility(LeylineAbility.getInstance()); this.addAbility(LeylineAbility.getInstance());
// All nonland permanents are legendary. // All nonland permanents are legendary.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SetSupertypeAllEffect(Duration.WhileOnBattlefield, filter))); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SetSupertypeAllEffect()));
} }
public LeylineOfSingularity(final LeylineOfSingularity card) { public LeylineOfSingularity(final LeylineOfSingularity card) {
@ -75,19 +66,16 @@ public class LeylineOfSingularity extends CardImpl {
} }
} }
class SetSupertypeAllEffect extends ContinuousEffectImpl { class SetSupertypeAllEffect extends ContinuousEffectImpl {
private final FilterPermanent filter; private static final FilterNonlandPermanent filter = new FilterNonlandPermanent();
public SetSupertypeAllEffect(Duration duration, FilterPermanent filter) { public SetSupertypeAllEffect() {
super(duration, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Detriment); super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Detriment);
this.filter = filter;
} }
public SetSupertypeAllEffect(final SetSupertypeAllEffect effect) { public SetSupertypeAllEffect(final SetSupertypeAllEffect effect) {
super(effect); super(effect);
this.filter = effect.filter;
} }
@Override @Override
@ -97,9 +85,8 @@ class SetSupertypeAllEffect extends ContinuousEffectImpl {
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
for (Permanent permanent: game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) { for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) {
permanent.addSuperType(SuperType.LEGENDARY); permanent.addSuperType(SuperType.LEGENDARY);
} }
return true; return true;
} }

View file

@ -0,0 +1,143 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.l;
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.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.SplitCard;
import mage.cards.repository.CardRepository;
import mage.choices.Choice;
import mage.choices.ChoiceImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetOpponent;
/**
*
* @author L_J
*/
public class LiarsPendulum extends CardImpl {
public LiarsPendulum(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{1}");
// {2}, {T}: Choose a card name. Target opponent guesses whether a card with that name is in your hand. You may reveal your hand. If you do and your opponent guessed wrong, draw a card.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new LiarsPendulumEffect(), new GenericManaCost(2));
ability.addCost(new TapSourceCost());
ability.addTarget(new TargetOpponent());
this.addAbility(ability);
}
public LiarsPendulum(final LiarsPendulum card) {
super(card);
}
@Override
public LiarsPendulum copy() {
return new LiarsPendulum(this);
}
}
class LiarsPendulumEffect extends OneShotEffect {
public LiarsPendulumEffect() {
super(Outcome.DrawCard);
this.staticText = "Choose a card name. Target opponent guesses whether a card with that name is in your hand. You may reveal your hand. If you do and your opponent guessed wrong, draw a card";
}
public LiarsPendulumEffect(final LiarsPendulumEffect effect) {
super(effect);
}
@Override
public LiarsPendulumEffect copy() {
return new LiarsPendulumEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Player opponent = game.getPlayer(this.getTargetPointer().getFirst(game, source));
if (controller != null && opponent != null) {
// Name a card.
Choice choice = new ChoiceImpl();
choice.setChoices(CardRepository.instance.getNames());
choice.setMessage("Choose a card name");
while (!controller.choose(Outcome.Benefit, choice, game)) {
if (!controller.canRespond()) {
return false;
}
}
String cardName = choice.getChoice();
game.informPlayers("Card named: " + cardName);
boolean opponentGuess = false;
if (opponent.chooseUse(Outcome.Neutral, "Is the chosen card (" + cardName + ") in " + controller.getLogName() + "'s hand?", source, game)) {
opponentGuess = true;
}
boolean rightGuess = !opponentGuess;
for (Card card : controller.getHand().getCards(game)) {
if (card.isSplitCard()){
SplitCard splitCard = (SplitCard) card;
if (splitCard.getLeftHalfCard().getName().equals(cardName)){
rightGuess = opponentGuess;
}
else if (splitCard.getRightHalfCard().getName().equals(cardName)){
rightGuess = opponentGuess;
}
}
if (card.getName().equals(cardName)) {
rightGuess = opponentGuess;
}
}
game.informPlayers(opponent.getLogName() + " guesses that " + cardName + " is " + (opponentGuess ? "" : "not") + " in " + controller.getLogName() + "'s hand");
if (controller.chooseUse(outcome, "Reveal your hand?", source, game)) {
controller.revealCards("hand of " + controller.getName(), controller.getHand(), game);
if (!rightGuess) {
controller.drawCards(1, game);
}
}
return true;
}
return false;
}
}

View file

@ -0,0 +1,132 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.l;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.effects.OneShotEffect;
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.game.Game;
import mage.game.permanent.Permanent;
import mage.target.Target;
import mage.target.common.TargetCreaturePermanentAmount;
/**
*
* @author LevelX2 & L_J
*/
public class LivingInferno extends CardImpl {
private final UUID originalId;
public LivingInferno(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{6}{R}{R}");
this.subtype.add(SubType.ELEMENTAL);
this.power = new MageInt(8);
this.toughness = new MageInt(5);
// {T}: Living Inferno deals damage equal to its power divided as you choose among any number of target creatures. Each of those creatures deals damage equal to its power to Living Inferno.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new LivingInfernoEffect(), new TapSourceCost());
ability.addTarget(new TargetCreaturePermanentAmount(1));
this.addAbility(ability);
originalId = ability.getOriginalId();
}
@Override
public void adjustTargets(Ability ability, Game game) {
if(ability.getOriginalId().equals(originalId)) {
Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(ability.getSourceId());
if (sourcePermanent != null) {
int xValue = sourcePermanent.getPower().getValue();
ability.getTargets().clear();
ability.addTarget(new TargetCreaturePermanentAmount(xValue));
}
}
}
public LivingInferno(final LivingInferno card) {
super(card);
this.originalId = card.originalId;
}
@Override
public LivingInferno copy() {
return new LivingInferno(this);
}
}
class LivingInfernoEffect extends OneShotEffect {
public LivingInfernoEffect() {
super(Outcome.Benefit);
this.staticText = "{this} deals damage equal to its power divided as you choose among any number of target creatures. Each of those creatures deals damage equal to its power to {this}";
}
public LivingInfernoEffect(final LivingInfernoEffect effect) {
super(effect);
}
@Override
public LivingInfernoEffect copy() {
return new LivingInfernoEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
if (!source.getTargets().isEmpty()) {
Target multiTarget = source.getTargets().get(0);
Set<Permanent> permanents = new HashSet<>();
for (UUID target : multiTarget.getTargets()) {
Permanent permanent = game.getPermanent(target);
if (permanent != null) {
permanents.add(permanent);
permanent.damage(multiTarget.getTargetAmount(target), source.getSourceId(), game, false, true);
}
}
// Each of those creatures deals damage equal to its power to Living Inferno
Permanent sourceCreature = game.getPermanent(source.getSourceId());
if (sourceCreature != null) {
for (Permanent permanent : permanents) {
sourceCreature.damage(permanent.getPower().getValue(), permanent.getId(), game, false, true);
}
}
return true;
}
return false;
}
}

View file

@ -0,0 +1,162 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.l;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.GainControlTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.TargetController;
import mage.filter.FilterPlayer;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.other.PlayerIdPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.TargetPlayer;
import mage.target.targetpointer.FixedTarget;
/**
*
* @author L_J
*/
public class LoxodonPeacekeeper extends CardImpl {
public LoxodonPeacekeeper(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{W}");
this.subtype.add(SubType.ELEPHANT);
this.subtype.add(SubType.SOLDIER);
this.power = new MageInt(4);
this.toughness = new MageInt(4);
// At the beginning of your upkeep, the player with the lowest life total gains control of Loxodon Peacekeeper. If two or more players are tied for lowest life total, you choose one of them, and that player gains control of Loxodon Peacekeeper.
this.addAbility(new BeginningOfUpkeepTriggeredAbility(new LoxodonPeacekeeperEffect(), TargetController.YOU, false));
}
public LoxodonPeacekeeper(final LoxodonPeacekeeper card) {
super(card);
}
@Override
public LoxodonPeacekeeper copy() {
return new LoxodonPeacekeeper(this);
}
}
class LoxodonPeacekeeperEffect extends OneShotEffect {
public LoxodonPeacekeeperEffect() {
super(Outcome.Benefit);
this.staticText = "the player with the lowest life total gains control of {this}. If two or more players are tied for lowest life total, you choose one of them, and that player gains control of {this}";
}
public LoxodonPeacekeeperEffect(final LoxodonPeacekeeperEffect effect) {
super(effect);
}
@Override
public LoxodonPeacekeeperEffect copy() {
return new LoxodonPeacekeeperEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
if (sourcePermanent != null) {
int lowLife = Integer.MAX_VALUE;
Set<UUID> tiedPlayers = new HashSet<>();
for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) {
Player player = game.getPlayer(playerId);
if (player != null) {
if (player.getLife() < lowLife) {
lowLife = player.getLife();
}
}
}
for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) {
Player player = game.getPlayer(playerId);
if (player != null) {
if (player.getLife() == lowLife) {
tiedPlayers.add(playerId);
}
}
}
if (tiedPlayers.size() > 0) {
UUID newControllerId = null;
if (tiedPlayers.size() > 1) {
FilterPlayer filter = new FilterPlayer("a player tied for lowest life total");
for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) {
if (!tiedPlayers.contains(playerId)) {
filter.add(Predicates.not(new PlayerIdPredicate(playerId)));
}
}
TargetPlayer target = new TargetPlayer(1, 1, true, filter);
if (target.canChoose(source.getSourceId(), controller.getId(), game)) {
while (!target.isChosen() && target.canChoose(controller.getId(), game) && controller.canRespond()) {
controller.chooseTarget(outcome, target, source, game);
}
} else {
return false;
}
newControllerId = game.getPlayer(target.getFirstTarget()).getId();
} else {
for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) {
if (tiedPlayers.contains(playerId)) {
newControllerId = playerId;
break;
}
}
}
if (newControllerId != null) {
ContinuousEffect effect = new GainControlTargetEffect(Duration.Custom, newControllerId);
effect.setTargetPointer(new FixedTarget(sourcePermanent, game));
game.addEffect(effect, source);
game.informPlayers(game.getPlayer(newControllerId).getLogName() + " has gained control of " + sourcePermanent.getLogName());
return true;
}
}
}
}
return false;
}
}

View file

@ -0,0 +1,111 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.l;
import java.util.UUID;
import mage.MageInt;
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.cards.Card;
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.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.TargetPlayer;
/**
*
* @author L_J
*/
public class LumengridAugur extends CardImpl {
public LumengridAugur(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{U}");
this.subtype.add(SubType.VEDALKEN);
this.subtype.add(SubType.WIZARD);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// {1}, {T}: Target player draws a card, then discards a card. If that player discards an artifact card this way, untap Lumengrid Augur.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new LumengridAugurEffect(), new GenericManaCost(1));
ability.addCost(new TapSourceCost());
ability.addTarget(new TargetPlayer());
this.addAbility(ability);
}
public LumengridAugur(final LumengridAugur card) {
super(card);
}
@Override
public LumengridAugur copy() {
return new LumengridAugur(this);
}
}
class LumengridAugurEffect extends OneShotEffect {
public LumengridAugurEffect() {
super(Outcome.DrawCard);
staticText = "Target player draws a card, then discards a card. If that player discards an artifact card this way, untap {this}";
}
public LumengridAugurEffect(final LumengridAugurEffect effect) {
super(effect);
}
@Override
public LumengridAugurEffect copy() {
return new LumengridAugurEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(getTargetPointer().getFirst(game, source));
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
if (player != null) {
player.drawCards(1, game);
Card discardedCard = player.discardOne(false, source, game);
if (discardedCard != null && discardedCard.isArtifact()) {
if (sourcePermanent != null) {
sourcePermanent.untap(game);
}
}
return true;
}
return false;
}
}

View file

@ -0,0 +1,200 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.m;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
import mage.abilities.condition.Condition;
import mage.abilities.condition.InvertCondition;
import mage.abilities.condition.common.TargetAttackedThisTurnCondition;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.decorator.ConditionalActivatedAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.combat.AttacksIfAbleAllEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.filter.predicate.permanent.ControllerPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.watchers.common.AttackedThisTurnWatcher;
/**
*
* @author L_J
*/
public class MaddeningImp extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("non-Wall creatures");
static {
filter.add(Predicates.not(new SubtypePredicate(SubType.WALL)));
filter.add(new ControllerPredicate(TargetController.ACTIVE));
filter.setMessage("non-Wall creatures the active player controls");
}
public MaddeningImp(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}");
this.subtype.add(SubType.IMP);
this.power = new MageInt(1);
this.toughness = new MageInt(1);
// Flying
this.addAbility(FlyingAbility.getInstance());
// {T}: Non-Wall creatures the active player controls attack this turn if able. At the beginning of the next end step, destroy each of those creatures that didn't attack this turn. Activate this ability only during an opponent's turn and only before combat.
Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, new AttacksIfAbleAllEffect(filter, Duration.EndOfTurn),
new TapSourceCost(), new MaddeningImpTurnCondition(),
"{T}: Non-Wall creatures the active player controls attack this turn if able. "
+ "At the beginning of the next end step, destroy each of those creatures that didn't attack this turn. "
+ "Activate this ability only during an opponent's turn and only before combat.");
ability.addEffect(new MaddeningImpCreateDelayedTriggeredAbilityEffect());
this.addAbility(ability, new AttackedThisTurnWatcher());
}
public MaddeningImp(final MaddeningImp card) {
super(card);
}
@Override
public MaddeningImp copy() {
return new MaddeningImp(this);
}
}
class MaddeningImpTurnCondition implements Condition {
@Override
public boolean apply(Game game, Ability source) {
Player activePlayer = game.getPlayer(game.getActivePlayerId());
return activePlayer != null && activePlayer.hasOpponent(source.getControllerId(), game) && game.getPhase().getStep().getType().getIndex() < 5;
}
@Override
public String toString() {
return "";
}
}
class MaddeningImpCreateDelayedTriggeredAbilityEffect extends OneShotEffect {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent();
static {
filter.add(Predicates.not(new SubtypePredicate(SubType.WALL)));
filter.add(new ControllerPredicate(TargetController.ACTIVE));
}
public MaddeningImpCreateDelayedTriggeredAbilityEffect() {
super(Outcome.DestroyPermanent);
this.staticText = "At the beginning of the next end step, destroy each of those creatures that didn't attack this turn";
}
public MaddeningImpCreateDelayedTriggeredAbilityEffect(final MaddeningImpCreateDelayedTriggeredAbilityEffect effect) {
super(effect);
}
@Override
public MaddeningImpCreateDelayedTriggeredAbilityEffect copy() {
return new MaddeningImpCreateDelayedTriggeredAbilityEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(game.getActivePlayerId());
if (player != null) {
Set<MageObjectReference> activeCreatures = new HashSet<>();
for (Permanent creature : game.getBattlefield().getAllActivePermanents(filter, player.getId(), game)) {
if (creature != null) {
activeCreatures.add(new MageObjectReference(creature, game));
}
}
AtTheBeginOfNextEndStepDelayedTriggeredAbility delayedAbility
= new AtTheBeginOfNextEndStepDelayedTriggeredAbility(Zone.ALL, new MaddeningImpDelayedDestroyEffect(activeCreatures), TargetController.ANY, new InvertCondition(TargetAttackedThisTurnCondition.instance));
delayedAbility.getDuration();
game.addDelayedTriggeredAbility(delayedAbility, source);
return true;
}
return false;
}
}
class MaddeningImpDelayedDestroyEffect extends OneShotEffect {
private Set<MageObjectReference> activeCreatures;
MaddeningImpDelayedDestroyEffect(Set<MageObjectReference> activeCreatures) {
super(Outcome.DestroyPermanent);
this.activeCreatures = activeCreatures;
this.staticText = "At the beginning of the next end step, destroy each of those creatures that didn't attack this turn";
}
MaddeningImpDelayedDestroyEffect(final MaddeningImpDelayedDestroyEffect effect) {
super(effect);
this.activeCreatures = effect.activeCreatures;
}
@Override
public MaddeningImpDelayedDestroyEffect copy() {
return new MaddeningImpDelayedDestroyEffect(this);
}
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(game.getActivePlayerId());
if (player != null) {
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(player.getId())) {
MageObjectReference mor = new MageObjectReference(permanent, game);
// Only affect permanents present when the ability resolved
if (!activeCreatures.contains(mor)) {
continue;
}
// Creatures that attacked are safe.
AttackedThisTurnWatcher watcher = (AttackedThisTurnWatcher) game.getState().getWatchers().get(AttackedThisTurnWatcher.class.getSimpleName());
if (watcher != null && watcher.getAttackedThisTurnCreatures().contains(mor)) {
continue;
}
// Destroy the rest.
permanent.destroy(source.getSourceId(), game, false);
}
return true;
}
return false;
}
}

View file

@ -29,9 +29,8 @@ package mage.cards.m;
import java.util.UUID; import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.continuous.GainAbilityAllEffect; import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
import mage.abilities.mana.AnyColorManaAbility; import mage.abilities.mana.AnyColorManaAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
@ -39,7 +38,7 @@ import mage.constants.CardType;
import mage.constants.SubType; import mage.constants.SubType;
import mage.constants.Duration; import mage.constants.Duration;
import mage.constants.Zone; import mage.constants.Zone;
import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent;
/** /**
* *
@ -47,6 +46,8 @@ import mage.filter.StaticFilters;
*/ */
public class ManaweftSliver extends CardImpl { public class ManaweftSliver extends CardImpl {
public static final FilterCreaturePermanent filter = new FilterCreaturePermanent(SubType.SLIVER, "Sliver creatures");
public ManaweftSliver(UUID ownerId, CardSetInfo setInfo) { public ManaweftSliver(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}"); super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}");
this.subtype.add(SubType.SLIVER); this.subtype.add(SubType.SLIVER);
@ -55,11 +56,11 @@ public class ManaweftSliver extends CardImpl {
this.toughness = new MageInt(1); this.toughness = new MageInt(1);
// Sliver creatures you control have "{T}: Add one mana of any color to your mana pool." // Sliver creatures you control have "{T}: Add one mana of any color to your mana pool."
Ability ability = new AnyColorManaAbility(); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityControlledEffect(
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new AnyColorManaAbility(),
new GainAbilityAllEffect(ability, Duration.WhileOnBattlefield,
Duration.WhileOnBattlefield, StaticFilters.FILTER_PERMANENT_CREATURE_SLIVERS, filter
"Sliver creatures you control have \"{T}: Add one mana of any color to your mana pool.\""))); )));
} }
public ManaweftSliver(final ManaweftSliver card) { public ManaweftSliver(final ManaweftSliver card) {

View file

@ -0,0 +1,192 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.m;
import java.util.UUID;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.ActivatedAbilityImpl;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.Effects;
import mage.abilities.effects.RedirectionEffect;
import mage.abilities.effects.common.RedirectDamageFromSourceToTargetEffect;
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.EffectType;
import mage.constants.Layer;
import mage.constants.Outcome;
import mage.constants.SubLayer;
import mage.constants.TargetController;
import mage.constants.Zone;
import mage.filter.common.FilterCreaturePermanent;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetControlledCreaturePermanent;
import mage.target.common.TargetCreatureOrPlayer;
/**
*
* @author L_J
*/
public class Martyrdom extends CardImpl {
public Martyrdom(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{W}{W}");
// Until end of turn, target creature you control gains "{0}: The next 1 damage that would be dealt to target creature or player this turn is dealt to this creature instead." Only you may activate this ability.
this.getSpellAbility().addEffect(new MartyrdomGainAbilityTargetEffect());
this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent());
}
public Martyrdom(final Martyrdom card) {
super(card);
}
@Override
public Martyrdom copy() {
return new Martyrdom(this);
}
}
class MartyrdomGainAbilityTargetEffect extends ContinuousEffectImpl {
public MartyrdomGainAbilityTargetEffect() {
super(Duration.EndOfTurn, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility);
this.staticText = "Until end of turn, target creature you control gains \"{0}: The next 1 damage that would be dealt to target creature or player this turn is dealt to this creature instead.\" Only you may activate this ability";
}
public MartyrdomGainAbilityTargetEffect(final MartyrdomGainAbilityTargetEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
if (permanent != null) {
ActivatedAbilityImpl ability = new MartyrdomActivatedAbility(source.getControllerId());
ability.setMayActivate(TargetController.ANY);
permanent.addAbility(ability, source.getSourceId(), game, false);
return true;
}
return false;
}
@Override
public MartyrdomGainAbilityTargetEffect copy() {
return new MartyrdomGainAbilityTargetEffect(this);
}
}
class MartyrdomActivatedAbility extends ActivatedAbilityImpl {
private static FilterCreaturePermanent filter = new FilterCreaturePermanent();
private UUID caster;
public MartyrdomActivatedAbility(UUID caster) {
super(Zone.BATTLEFIELD, new MartyrdomRedirectDamageTargetEffect(Duration.EndOfTurn, 1), new GenericManaCost(0));
this.addTarget(new TargetCreatureOrPlayer());
this.caster = caster;
}
private MartyrdomActivatedAbility(final MartyrdomActivatedAbility ability) {
super(ability);
this.caster = ability.caster;
}
@Override
public Effects getEffects(Game game, EffectType effectType) {
return super.getEffects(game, effectType);
}
@Override
public boolean canActivate(UUID playerId, Game game) {
if (playerId == caster) {
Permanent permanent = game.getBattlefield().getPermanent(this.getSourceId());
if (permanent != null) {
if (filter.match(permanent, permanent.getId(), permanent.getControllerId(), game)) {
return super.canActivate(playerId, game);
}
}
}
return false;
}
@Override
public MartyrdomActivatedAbility copy() {
return new MartyrdomActivatedAbility(this);
}
@Override
public String getRule() {
return "{0}: The next 1 damage that would be dealt to target creature or player this turn is dealt to {this} instead.";
}
}
class MartyrdomRedirectDamageTargetEffect extends RedirectionEffect {
private static FilterCreaturePermanent filter = new FilterCreaturePermanent();
public MartyrdomRedirectDamageTargetEffect(Duration duration, int amount) {
super(duration, amount, true);
staticText = "The next " + amount + " damage that would be dealt to target creature or player this turn is dealt to {this} instead";
}
public MartyrdomRedirectDamageTargetEffect(final MartyrdomRedirectDamageTargetEffect effect) {
super(effect);
}
@Override
public MartyrdomRedirectDamageTargetEffect copy() {
return new MartyrdomRedirectDamageTargetEffect(this);
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
Permanent permanent = game.getBattlefield().getPermanent(source.getSourceId());
if (permanent != null) {
if (filter.match(permanent, permanent.getId(), permanent.getControllerId(), game)) {
if (event.getTargetId().equals(getTargetPointer().getFirst(game, source))) {
if (event.getTargetId() != null) {
TargetCreatureOrPlayer target = new TargetCreatureOrPlayer();
target.add(source.getSourceId(), game);
redirectTarget = target;
return true;
}
}
}
}
return false;
}
}

View file

@ -0,0 +1,101 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.m;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.UUID;
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.game.permanent.Permanent;
import mage.players.Player;
/**
*
* @author TheElk801
*/
public class MartyrsCry extends CardImpl {
public MartyrsCry(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{W}{W}");
// Exile all white creatures. For each creature exiled this way, its controller draws a card.
this.getSpellAbility().addEffect(new MartyrsCryEffect());
}
public MartyrsCry(final MartyrsCry card) {
super(card);
}
@Override
public MartyrsCry copy() {
return new MartyrsCry(this);
}
}
class MartyrsCryEffect extends OneShotEffect {
MartyrsCryEffect() {
super(Outcome.Exile);
this.staticText = "Exile all white creatures. For each creature exiled this way, its controller draws a card.";
}
MartyrsCryEffect(final MartyrsCryEffect effect) {
super(effect);
}
@Override
public MartyrsCryEffect copy() {
return new MartyrsCryEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Map<UUID, Integer> playerCrtCount = new HashMap<>();
for (Iterator<Permanent> it = game.getBattlefield().getActivePermanents(source.getControllerId(), game).iterator(); it.hasNext();) {
Permanent perm = it.next();
if (perm != null && perm.isCreature() && perm.getColor(game).isWhite() && perm.moveToExile(null, null, source.getSourceId(), game)) {
playerCrtCount.putIfAbsent(perm.getControllerId(), 0);
playerCrtCount.compute(perm.getControllerId(), (p, amount) -> amount + 1);
}
}
for (UUID playerId : game.getPlayerList().toList()) {
Player player = game.getPlayer(playerId);
if (player != null) {
player.drawCards(playerCrtCount.getOrDefault(playerId, 0), game);
}
}
return true;
}
}

View file

@ -0,0 +1,311 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.m;
import java.util.*;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.common.CastOnlyDuringPhaseStepSourceAbility;
import mage.abilities.condition.common.BeforeAttackersAreDeclaredCondition;
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.RequirementEffect;
import mage.abilities.effects.RestrictionEffect;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.abilities.effects.common.combat.AttacksIfAbleTargetEffect;
import mage.abilities.effects.common.combat.CantAttackTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.common.FilterCreaturePermanent;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.Permanent;
import mage.game.stack.Spell;
import mage.players.Player;
import mage.target.Target;
import mage.target.common.TargetCreaturePermanent;
import mage.filter.predicate.permanent.ControllerPredicate;
import mage.target.targetpointer.FixedTarget;
import mage.watchers.Watcher;
import mage.watchers.common.ChooseBlockersRedundancyWatcher;
/**
*
* @author L_J
*/
public class MasterWarcraft extends CardImpl {
public MasterWarcraft(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{R/W}{R/W}");
// Cast Master Warcraft only before attackers are declared.
this.addAbility(new CastOnlyDuringPhaseStepSourceAbility(null, null, BeforeAttackersAreDeclaredCondition.instance, "Cast {this} only before attackers are declared"));
// You choose which creatures attack this turn.
this.getSpellAbility().addEffect(new MasterWarcraftChooseAttackersEffect());
// You choose which creatures block this turn and how those creatures block.
this.getSpellAbility().addEffect(new MasterWarcraftChooseBlockersEffect());
// (only the last resolved Master Warcraft spell's effects apply)
this.getSpellAbility().addWatcher(new MasterWarcraftCastWatcher());
this.getSpellAbility().addEffect(new MasterWarcraftCastWatcherIncrementEffect());
this.getSpellAbility().addWatcher(new ChooseBlockersRedundancyWatcher());
this.getSpellAbility().addEffect(new ChooseBlockersRedundancyWatcherIncrementEffect());
}
public MasterWarcraft(final MasterWarcraft card) {
super(card);
}
@Override
public MasterWarcraft copy() {
return new MasterWarcraft(this);
}
private class MasterWarcraftCastWatcherIncrementEffect extends OneShotEffect {
MasterWarcraftCastWatcherIncrementEffect() {
super(Outcome.Neutral);
}
MasterWarcraftCastWatcherIncrementEffect(final MasterWarcraftCastWatcherIncrementEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
MasterWarcraftCastWatcher watcher = (MasterWarcraftCastWatcher) game.getState().getWatchers().get(MasterWarcraftCastWatcher.class.getSimpleName());
if (watcher != null) {
watcher.increment();
return true;
}
return false;
}
@Override
public MasterWarcraftCastWatcherIncrementEffect copy() {
return new MasterWarcraftCastWatcherIncrementEffect(this);
}
}
private class ChooseBlockersRedundancyWatcherIncrementEffect extends OneShotEffect {
ChooseBlockersRedundancyWatcherIncrementEffect() {
super(Outcome.Neutral);
}
ChooseBlockersRedundancyWatcherIncrementEffect(final ChooseBlockersRedundancyWatcherIncrementEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
ChooseBlockersRedundancyWatcher watcher = (ChooseBlockersRedundancyWatcher) game.getState().getWatchers().get(ChooseBlockersRedundancyWatcher.class.getSimpleName());
if (watcher != null) {
watcher.increment();
return true;
}
return false;
}
@Override
public ChooseBlockersRedundancyWatcherIncrementEffect copy() {
return new ChooseBlockersRedundancyWatcherIncrementEffect(this);
}
}
}
class MasterWarcraftChooseAttackersEffect extends ContinuousRuleModifyingEffectImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures that will attack this combat (creatures not chosen won't attack this combat)");
static {
filter.add(new ControllerPredicate(TargetController.ACTIVE));
}
public MasterWarcraftChooseAttackersEffect() {
super(Duration.EndOfTurn, Outcome.Benefit, false, false);
staticText = "You choose which creatures attack this turn";
}
public MasterWarcraftChooseAttackersEffect(final MasterWarcraftChooseAttackersEffect effect) {
super(effect);
}
@Override
public MasterWarcraftChooseAttackersEffect copy() {
return new MasterWarcraftChooseAttackersEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
return true;
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DECLARING_ATTACKERS;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
MasterWarcraftCastWatcher watcher = (MasterWarcraftCastWatcher) game.getState().getWatchers().get(MasterWarcraftCastWatcher.class.getSimpleName());
watcher.decrement();
if (watcher.copyCountApply > 0) {
game.informPlayers(source.getSourceObject(game).getIdName() + " didn't apply");
return false;
}
watcher.copyCountApply = watcher.copyCount;
Player controller = game.getPlayer(source.getControllerId());
Player attackingPlayer = game.getPlayer(game.getCombat().getAttackingPlayerId());
if (controller != null && attackingPlayer != null && !attackingPlayer.getAvailableAttackers(game).isEmpty()) {
Target target = new TargetCreaturePermanent(0, Integer.MAX_VALUE, filter, true);
if (controller.chooseTarget(Outcome.Benefit, target, source, game)) {
for (Permanent permanent : game.getBattlefield().getActivePermanents(new FilterCreaturePermanent(), source.getControllerId(), source.getSourceId(), game)) {
// Choose creatures that will be attacking this combat
if (target.getTargets().contains(permanent.getId())) {
RequirementEffect effect = new AttacksIfAbleTargetEffect(Duration.EndOfCombat);
effect.setText("");
effect.setTargetPointer(new FixedTarget(permanent.getId()));
game.addEffect(effect, source);
game.informPlayers(controller.getLogName() + " has decided that " + permanent.getLogName() + " attacks this combat if able");
// All other creatures can't attack (unless they must attack)
} else {
boolean hasToAttack = false;
for (Map.Entry<RequirementEffect, Set<Ability>> entry : game.getContinuousEffects().getApplicableRequirementEffects(permanent, false, game).entrySet()) {
RequirementEffect effect2 = entry.getKey();
if (effect2.mustAttack(game)) {
hasToAttack = true;
}
}
if (!hasToAttack) {
RestrictionEffect effect = new CantAttackTargetEffect(Duration.EndOfCombat);
effect.setText("");
effect.setTargetPointer(new FixedTarget(permanent.getId()));
game.addEffect(effect, source);
}
}
}
}
}
return false; // the attack declaration resumes for the active player as normal
}
}
class MasterWarcraftChooseBlockersEffect extends ContinuousRuleModifyingEffectImpl {
public MasterWarcraftChooseBlockersEffect() {
super(Duration.EndOfTurn, Outcome.Benefit, false, false);
staticText = "You choose which creatures block this turn and how those creatures block";
}
public MasterWarcraftChooseBlockersEffect(final MasterWarcraftChooseBlockersEffect effect) {
super(effect);
}
@Override
public MasterWarcraftChooseBlockersEffect copy() {
return new MasterWarcraftChooseBlockersEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
return false;
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DECLARING_BLOCKERS;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
ChooseBlockersRedundancyWatcher watcher = (ChooseBlockersRedundancyWatcher) game.getState().getWatchers().get(ChooseBlockersRedundancyWatcher.class.getSimpleName());
watcher.decrement();
if (watcher.copyCountApply > 0) {
game.informPlayers(source.getSourceObject(game).getIdName() + " didn't apply");
return false;
}
watcher.copyCountApply = watcher.copyCount;
Player blockController = game.getPlayer(source.getControllerId());
if (blockController != null) {
game.getCombat().selectBlockers(blockController, game);
return true;
}
return false;
}
}
class MasterWarcraftCastWatcher extends Watcher {
public int copyCount = 0;
public int copyCountApply = 0;
public MasterWarcraftCastWatcher() {
super(MasterWarcraftCastWatcher.class.getSimpleName(), WatcherScope.GAME);
}
public MasterWarcraftCastWatcher(final MasterWarcraftCastWatcher watcher) {
super(watcher);
this.copyCount = watcher.copyCount;
this.copyCountApply = watcher.copyCountApply;
}
@Override
public void reset() {
copyCount = 0;
copyCountApply = 0;
}
@Override
public MasterWarcraftCastWatcher copy() {
return new MasterWarcraftCastWatcher(this);
}
@Override
public void watch(GameEvent event, Game game) {
}
public void increment() {
copyCount++;
copyCountApply = copyCount;
}
public void decrement() {
if (copyCountApply > 0) {
copyCountApply--;
}
}
}

View file

@ -0,0 +1,204 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.m;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.common.CastOnlyDuringPhaseStepSourceAbility;
import mage.abilities.condition.CompoundCondition;
import mage.abilities.condition.Condition;
import mage.abilities.condition.common.BeforeBlockersAreDeclaredCondition;
import mage.abilities.condition.common.IsPhaseCondition;
import mage.abilities.condition.common.MyTurnCondition;
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.abilities.effects.common.RemoveFromCombatTargetEffect;
import mage.abilities.effects.common.UntapTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.game.Game;
import mage.game.combat.CombatGroup;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.targetpointer.FixedTarget;
import mage.watchers.Watcher;
import mage.watchers.common.ChooseBlockersRedundancyWatcher;
/**
*
* @author L_J
*/
public class Melee extends CardImpl {
public Melee(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{4}{R}");
// Cast Melee only during your turn and only during combat before blockers are declared.
Condition condition = new CompoundCondition(BeforeBlockersAreDeclaredCondition.instance,
new IsPhaseCondition(TurnPhase.COMBAT),
MyTurnCondition.instance);
this.addAbility(new CastOnlyDuringPhaseStepSourceAbility(null, null, condition, "Cast {this} only during your turn and only during combat before blockers are declared"));
// You choose which creatures block this combat and how those creatures block.
// (only the last resolved Melee spell's blocking effect applies)
this.getSpellAbility().addEffect(new MeleeChooseBlockersEffect());
this.getSpellAbility().addWatcher(new ChooseBlockersRedundancyWatcher());
this.getSpellAbility().addEffect(new ChooseBlockersRedundancyWatcherIncrementEffect());
// Whenever a creature attacks and isn't blocked this combat, untap it and remove it from combat.
this.getSpellAbility().addEffect(new CreateDelayedTriggeredAbilityEffect(new MeleeTriggeredAbility()));
}
public Melee(final Melee card) {
super(card);
}
@Override
public Melee copy() {
return new Melee(this);
}
private class ChooseBlockersRedundancyWatcherIncrementEffect extends OneShotEffect {
ChooseBlockersRedundancyWatcherIncrementEffect() {
super(Outcome.Neutral);
}
ChooseBlockersRedundancyWatcherIncrementEffect(final ChooseBlockersRedundancyWatcherIncrementEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
ChooseBlockersRedundancyWatcher watcher = (ChooseBlockersRedundancyWatcher) game.getState().getWatchers().get(ChooseBlockersRedundancyWatcher.class.getSimpleName());
if (watcher != null) {
watcher.increment();
return true;
}
return false;
}
@Override
public ChooseBlockersRedundancyWatcherIncrementEffect copy() {
return new ChooseBlockersRedundancyWatcherIncrementEffect(this);
}
}
}
class MeleeChooseBlockersEffect extends ContinuousRuleModifyingEffectImpl {
public MeleeChooseBlockersEffect() {
super(Duration.EndOfCombat, Outcome.Benefit, false, false);
staticText = "You choose which creatures block this combat and how those creatures block";
}
public MeleeChooseBlockersEffect(final MeleeChooseBlockersEffect effect) {
super(effect);
}
@Override
public MeleeChooseBlockersEffect copy() {
return new MeleeChooseBlockersEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
return false;
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DECLARING_BLOCKERS;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
ChooseBlockersRedundancyWatcher watcher = (ChooseBlockersRedundancyWatcher) game.getState().getWatchers().get(ChooseBlockersRedundancyWatcher.class.getSimpleName());
watcher.decrement();
watcher.copyCount--;
if (watcher.copyCountApply > 0) {
game.informPlayers(source.getSourceObject(game).getIdName() + " didn't apply");
this.discard();
return false;
}
watcher.copyCountApply = watcher.copyCount;
Player blockController = game.getPlayer(source.getControllerId());
if (blockController != null) {
game.getCombat().selectBlockers(blockController, game);
return true;
}
this.discard();
return false;
}
}
class MeleeTriggeredAbility extends DelayedTriggeredAbility {
public MeleeTriggeredAbility() {
super(new UntapTargetEffect(), Duration.EndOfCombat, false);
this.addEffect(new RemoveFromCombatTargetEffect());
}
public MeleeTriggeredAbility(MeleeTriggeredAbility ability) {
super(ability);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.UNBLOCKED_ATTACKER;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Permanent permanent = game.getPermanent(event.getTargetId());
if (permanent != null) {
for (CombatGroup combatGroup : game.getCombat().getGroups()) {
if (combatGroup.getBlockers().isEmpty() && combatGroup.getAttackers().contains(event.getTargetId())) {
this.getEffects().setTargetPointer(new FixedTarget(permanent, game));
return true;
}
}
}
return false;
}
@Override
public MeleeTriggeredAbility copy() {
return new MeleeTriggeredAbility(this);
}
@Override
public String getRule() {
return "Whenever a creature attacks and isn't blocked this combat, untap it and remove it from combat.";
}
}

View file

@ -0,0 +1,100 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.m;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Layer;
import mage.constants.Outcome;
import mage.constants.SubLayer;
import mage.constants.SuperType;
import mage.constants.Zone;
import mage.filter.common.FilterLandPermanent;
import mage.game.Game;
import mage.game.permanent.Permanent;
/**
*
* @author TheElk801
*/
public class Melting extends CardImpl {
public Melting(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{R}");
// All lands are no longer snow.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new MeltingEffect()));
}
public Melting(final Melting card) {
super(card);
}
@Override
public Melting copy() {
return new Melting(this);
}
}
class MeltingEffect extends ContinuousEffectImpl {
private static final FilterLandPermanent filter = new FilterLandPermanent();
public MeltingEffect() {
super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Detriment);
}
public MeltingEffect(final MeltingEffect effect) {
super(effect);
}
@Override
public MeltingEffect copy() {
return new MeltingEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) {
permanent.getSuperType().remove(SuperType.SNOW);
}
return true;
}
@Override
public String getText(Mode mode) {
return "All lands are no longer snow";
}
}

View file

@ -0,0 +1,95 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.m;
import java.util.List;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.*;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.filter.FilterCard;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetCardInOpponentsGraveyard;
/**
*
* @author L_J
*/
public class Misinformation extends CardImpl {
public Misinformation(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{B}");
// Put up to three target cards from an opponent's graveyard on top of his or her library in any order.
this.getSpellAbility().addTarget(new TargetCardInOpponentsGraveyard(0, 3, new FilterCard("cards from an opponent's graveyard"), true));
this.getSpellAbility().addEffect(new MisinformationEffect());
}
public Misinformation(final Misinformation card) {
super(card);
}
@Override
public Misinformation copy() {
return new Misinformation(this);
}
}
class MisinformationEffect extends OneShotEffect {
MisinformationEffect() {
super(Outcome.Detriment);
this.staticText = "Put up to three target cards from an opponent's graveyard on top of his or her library in any order";
}
MisinformationEffect(final MisinformationEffect effect) {
super(effect);
}
@Override
public MisinformationEffect copy() {
return new MisinformationEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
List<UUID> targets = this.getTargetPointer().getTargets(game, source);
if (targets != null) {
Cards cards = new CardsImpl(targets);
controller.putCardsOnTopOfLibrary(cards, game, source, true);
return true;
}
}
return false;
}
}

View file

@ -27,8 +27,6 @@
*/ */
package mage.cards.m; package mage.cards.m;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID; import java.util.UUID;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
@ -96,23 +94,16 @@ class MistOfStagnationEffect extends OneShotEffect {
if (activePlayer != null) { if (activePlayer != null) {
int cardsInGrave = activePlayer.getGraveyard().size(); int cardsInGrave = activePlayer.getGraveyard().size();
if (cardsInGrave > 0) { if (cardsInGrave > 0) {
Set<TargetPermanent> targets = new HashSet<>(); TargetPermanent target = new TargetPermanent(cardsInGrave, cardsInGrave, new FilterPermanent("permanents to untap"), true);
for (int i = 1; 1 <= cardsInGrave; i++) { activePlayer.chooseTarget(outcome, target, source, game);
TargetPermanent target = new TargetPermanent(1, 1, new FilterPermanent(), true); for (UUID oneTarget : target.getTargets()) {
target.setTargetController(activePlayer.getId()); Permanent p = game.getPermanent(oneTarget);
target.setTargetController(activePlayer.getId());
if (target.canChoose(source.getSourceId(), activePlayer.getId(), game) && activePlayer.chooseTarget(Outcome.Untap, target, source, game)) {
targets.add(target);
}
}
for (TargetPermanent target : targets) {
Permanent p = game.getPermanent(target.getFirstTarget());
if (p != null) { if (p != null) {
p.untap(game); p.untap(game);
} }
} }
return true;
} }
return true;
} }
return false; return false;
} }

View file

@ -0,0 +1,148 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.m;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.effects.OneShotEffect;
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.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.Target;
import mage.target.common.TargetCreaturePermanent;
import mage.target.common.TargetOpponentsCreaturePermanent;
/**
*
* @author L_J
*/
public class MoggAssassin extends CardImpl {
private final UUID originalId;
public MoggAssassin(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{R}");
this.subtype.add(SubType.GOBLIN);
this.subtype.add(SubType.ASSASSIN);
this.power = new MageInt(2);
this.toughness = new MageInt(1);
//TODO: Make ability properly copiable
// {T}: You choose target creature an opponent controls, and that opponent chooses target creature. Flip a coin. If you win the flip, destroy the creature you chose. If you lose the flip, destroy the creature your opponent chose.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new MoggAssassinEffect(), new TapSourceCost());
ability.addTarget(new TargetOpponentsCreaturePermanent());
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability);
originalId = ability.getOriginalId();
}
@Override
public void adjustTargets(Ability ability, Game game) {
if (ability.getOriginalId().equals(originalId)) {
Player controller = game.getPlayer(ability.getControllerId());
if (controller != null) {
UUID opponentId = null;
if (game.getOpponents(controller.getId()).size() > 1) {
Target target = ability.getTargets().get(0);
if (controller.chooseTarget(Outcome.DestroyPermanent, target, ability, game)) {
Permanent permanent = game.getPermanent(target.getFirstTarget());
opponentId = permanent.getControllerId();
} else {
opponentId = game.getOpponents(controller.getId()).iterator().next();
}
} else {
opponentId = game.getOpponents(controller.getId()).iterator().next();
}
if (opponentId != null) {
ability.getTargets().get(1).setTargetController(opponentId);
}
}
}
}
public MoggAssassin(final MoggAssassin card) {
super(card);
this.originalId = card.originalId;
}
@Override
public MoggAssassin copy() {
return new MoggAssassin(this);
}
}
class MoggAssassinEffect extends OneShotEffect {
public MoggAssassinEffect() {
super(Outcome.DestroyPermanent);
this.staticText = "You choose target creature an opponent controls, and that opponent chooses target creature. Flip a coin. If you win the flip, destroy the creature you chose. If you lose the flip, destroy the creature your opponent chose";
}
public MoggAssassinEffect(final MoggAssassinEffect effect) {
super(effect);
}
@Override
public MoggAssassinEffect copy() {
return new MoggAssassinEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId());
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
Permanent chosenPermanent = game.getPermanent(source.getTargets().get(0).getFirstTarget());
Permanent opponentsPermanent = game.getPermanent(source.getTargets().get(1).getFirstTarget());
if (controller.flipCoin(game)) {
if (chosenPermanent != null) {
chosenPermanent.destroy(source.getSourceId(), game, false);
return true;
}
} else {
if (opponentsPermanent != null) {
opponentsPermanent.destroy(source.getSourceId(), game, false);
return true;
}
}
}
return false;
}
}

View file

@ -0,0 +1,83 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.m;
import java.util.UUID;
import mage.constants.SubType;
import mage.target.common.TargetCreaturePermanent;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.common.CountersSourceCount;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.continuous.BoostEnchantedEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.constants.Outcome;
import mage.target.TargetPermanent;
import mage.abilities.keyword.EnchantAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.TargetController;
import mage.constants.Zone;
import mage.counters.CounterType;
/**
*
* @author TheElk801
*/
public class Momentum extends CardImpl {
public Momentum(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}");
this.subtype.add(SubType.AURA);
// Enchant creature
TargetPermanent auraTarget = new TargetCreaturePermanent();
this.getSpellAbility().addTarget(auraTarget);
this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature));
Ability ability = new EnchantAbility(auraTarget.getTargetName());
this.addAbility(ability);
// At the beginning of your upkeep, you may put a growth counter on Momentum.
this.addAbility(new BeginningOfUpkeepTriggeredAbility(new AddCountersSourceEffect(CounterType.GROWTH.createInstance(), true), TargetController.YOU, true));
// Enchanted creature gets +1/+1 for each growth counter on Momentum.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEnchantedEffect(new CountersSourceCount(CounterType.GROWTH), new CountersSourceCount(CounterType.GROWTH))));
}
public Momentum(final Momentum card) {
super(card);
}
@Override
public Momentum copy() {
return new Momentum(this);
}
}

View file

@ -35,6 +35,7 @@ import mage.abilities.Ability;
import mage.abilities.SpellAbility; import mage.abilities.SpellAbility;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.continuous.BoostAllEffect; import mage.abilities.effects.common.continuous.BoostAllEffect;
import mage.abilities.keyword.special.JohanVigilanceAbility;
import mage.cards.Card; import mage.cards.Card;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
@ -91,7 +92,7 @@ class NoAbilityPredicate implements Predicate<MageObject> {
} }
if (isFaceDown) { if (isFaceDown) {
for (Ability ability : abilities) { for (Ability ability : abilities) {
if (!ability.getSourceId().equals(input.getId())) { if (!ability.getSourceId().equals(input.getId()) && !ability.getClass().equals(JohanVigilanceAbility.class)) {
return false; return false;
} }
} }
@ -99,8 +100,7 @@ class NoAbilityPredicate implements Predicate<MageObject> {
} }
for (Ability ability : abilities) { for (Ability ability : abilities) {
if (!Objects.equals(ability.getClass(), SpellAbility.class)) { if (!Objects.equals(ability.getClass(), SpellAbility.class) && !ability.getClass().equals(JohanVigilanceAbility.class)) {
return false; return false;
} }
} }

View file

@ -0,0 +1,112 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.m;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.ManaCosts;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.combat.CantAttackBlockUnlessPaysSourceEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.TargetController;
import mage.constants.Zone;
import mage.counters.CounterType;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
/**
*
* @author emerald000 & L_J
*/
public class MyrPrototype extends CardImpl {
public MyrPrototype(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{5}");
this.subtype.add(SubType.MYR);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// At the beginning of your upkeep, put a +1/+1 counter on Myr Prototype.
this.addAbility(new BeginningOfUpkeepTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance()), TargetController.YOU, false));
// Myr Prototype can't attack or block unless you pay {1} for each +1/+1 counter on it.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new MyrPrototypeCantAttackUnlessYouPayEffect()));
}
public MyrPrototype(final MyrPrototype card) {
super(card);
}
@Override
public MyrPrototype copy() {
return new MyrPrototype(this);
}
}
class MyrPrototypeCantAttackUnlessYouPayEffect extends CantAttackBlockUnlessPaysSourceEffect {
MyrPrototypeCantAttackUnlessYouPayEffect() {
super(new ManaCostsImpl("{0}"), RestrictType.ATTACK_AND_BLOCK);
staticText = "{this} can't attack or block unless you pay {1} for each +1/+1 counter on it";
}
MyrPrototypeCantAttackUnlessYouPayEffect(MyrPrototypeCantAttackUnlessYouPayEffect effect) {
super(effect);
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
return source.getSourceId().equals(event.getSourceId());
}
@Override
public ManaCosts getManaCostToPay(GameEvent event, Ability source, Game game) {
Permanent sourceObject = game.getPermanent(source.getSourceId());
if (sourceObject != null) {
int counter = sourceObject.getCounters(game).getCount(CounterType.P1P1);
if (counter > 0) {
return new ManaCostsImpl<>("{" + counter + '}');
}
}
return null;
}
@Override
public MyrPrototypeCantAttackUnlessYouPayEffect copy() {
return new MyrPrototypeCantAttackUnlessYouPayEffect(this);
}
}

View file

@ -30,13 +30,14 @@ package mage.cards.n;
import java.util.UUID; import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
import mage.abilities.condition.Condition; import mage.abilities.condition.Condition;
import mage.abilities.condition.InvertCondition; import mage.abilities.condition.InvertCondition;
import mage.abilities.condition.common.TargetAttackedThisTurnCondition; import mage.abilities.condition.common.TargetAttackedThisTurnCondition;
import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.decorator.ConditionalActivatedAbility; import mage.abilities.decorator.ConditionalActivatedAbility;
import mage.abilities.decorator.ConditionalOneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DestroyTargetAtBeginningOfNextEndStepEffect; import mage.abilities.effects.common.DestroyTargetEffect;
import mage.abilities.effects.common.combat.AttacksIfAbleTargetEffect; import mage.abilities.effects.common.combat.AttacksIfAbleTargetEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
@ -49,6 +50,7 @@ import mage.filter.predicate.permanent.ControllerPredicate;
import mage.game.Game; import mage.game.Game;
import mage.players.Player; import mage.players.Player;
import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetCreaturePermanent;
import mage.target.targetpointer.FixedTarget;
import mage.watchers.common.AttackedThisTurnWatcher; import mage.watchers.common.AttackedThisTurnWatcher;
/** /**
@ -66,7 +68,6 @@ public class NettlingImp extends CardImpl {
filter.setMessage("non-Wall creature the active player has controlled continuously since the beginning of the turn."); filter.setMessage("non-Wall creature the active player has controlled continuously since the beginning of the turn.");
} }
public NettlingImp(UUID ownerId, CardSetInfo setInfo) { public NettlingImp(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}"); super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}");
@ -74,9 +75,13 @@ public class NettlingImp extends CardImpl {
this.power = new MageInt(1); this.power = new MageInt(1);
this.toughness = new MageInt(1); this.toughness = new MageInt(1);
// {tap}: Choose target non-Wall creature the active player has controlled continuously since the beginning of the turn. That creature attacks this turn if able. If it doesn't, destroy it at the beginning of the next end step. Activate this ability only during an opponent's turn, before attackers are declared. // {T}: Choose target non-Wall creature the active player has controlled continuously since the beginning of the turn. That creature attacks this turn if able. If it doesn't, destroy it at the beginning of the next end step. Activate this ability only during an opponent's turn, before attackers are declared.
Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, new AttacksIfAbleTargetEffect(Duration.EndOfTurn), new TapSourceCost(), new NettlingImpTurnCondition(), "{T}: Choose target non-Wall creature the active player has controlled continuously since the beginning of the turn. That creature attacks this turn if able. If it doesn't, destroy it at the beginning of the next end step. Activate this ability only during an opponent's turn, before attackers are declared."); Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, new AttacksIfAbleTargetEffect(Duration.EndOfTurn),
ability.addEffect(new ConditionalOneShotEffect(new DestroyTargetAtBeginningOfNextEndStepEffect(), new InvertCondition(TargetAttackedThisTurnCondition.instance))); new TapSourceCost(), new NettlingImpTurnCondition(),
"{T}: Choose target non-Wall creature the active player has controlled continuously since the beginning of the turn. "
+ "That creature attacks this turn if able. If it doesn't, destroy it at the beginning of the next end step. "
+ "Activate this ability only during an opponent's turn, before attackers are declared.");
ability.addEffect(new NettlingImpDelayedDestroyEffect());
ability.addTarget(new TargetCreaturePermanent(filter)); ability.addTarget(new TargetCreaturePermanent(filter));
this.addAbility(ability, new AttackedThisTurnWatcher()); this.addAbility(ability, new AttackedThisTurnWatcher());
@ -105,3 +110,32 @@ class NettlingImpTurnCondition implements Condition {
return ""; return "";
} }
} }
class NettlingImpDelayedDestroyEffect extends OneShotEffect {
public NettlingImpDelayedDestroyEffect() {
super(Outcome.Detriment);
this.staticText = "If it doesn't, destroy it at the beginning of the next end step";
}
public NettlingImpDelayedDestroyEffect(final NettlingImpDelayedDestroyEffect effect) {
super(effect);
}
@Override
public NettlingImpDelayedDestroyEffect copy() {
return new NettlingImpDelayedDestroyEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
DestroyTargetEffect effect = new DestroyTargetEffect();
effect.setTargetPointer(new FixedTarget(source.getFirstTarget()));
AtTheBeginOfNextEndStepDelayedTriggeredAbility delayedAbility
= new AtTheBeginOfNextEndStepDelayedTriggeredAbility(Zone.ALL, effect, TargetController.ANY, new InvertCondition(TargetAttackedThisTurnCondition.instance));
delayedAbility.getDuration();
delayedAbility.getTargets().addAll(source.getTargets());
game.addDelayedTriggeredAbility(delayedAbility, source);
return true;
}
}

View file

@ -42,8 +42,7 @@ import mage.constants.SubType;
import mage.constants.SuperType; import mage.constants.SuperType;
import mage.constants.Zone; import mage.constants.Zone;
import mage.filter.FilterCard; import mage.filter.FilterCard;
import mage.filter.common.FilterCreaturePermanent; import mage.filter.StaticFilters;
import mage.filter.common.FilterLandPermanent;
import mage.filter.predicate.Predicates; import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.CardTypePredicate; import mage.filter.predicate.mageobject.CardTypePredicate;
import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetCreaturePermanent;
@ -55,6 +54,15 @@ import mage.target.common.TargetLandPermanent;
*/ */
public class NissaGenesisMage extends CardImpl { public class NissaGenesisMage extends CardImpl {
private static final FilterCard filter = new FilterCard("any number of creature and/or land cards");
static {
filter.add(Predicates.or(
new CardTypePredicate(CardType.CREATURE),
new CardTypePredicate(CardType.LAND)
));
}
public NissaGenesisMage(UUID ownerId, CardSetInfo setInfo) { public NissaGenesisMage(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{5}{G}{G}"); super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{5}{G}{G}");
this.addSuperType(SuperType.LEGENDARY); this.addSuperType(SuperType.LEGENDARY);
@ -64,8 +72,8 @@ public class NissaGenesisMage extends CardImpl {
//+2: Untap up to two target creatures and up to two target lands. //+2: Untap up to two target creatures and up to two target lands.
Ability ability = new LoyaltyAbility(new UntapTargetEffect(false).setText("Untap up to two target creatures and up to two target lands"), +2); Ability ability = new LoyaltyAbility(new UntapTargetEffect(false).setText("Untap up to two target creatures and up to two target lands"), +2);
ability.addTarget(new TargetCreaturePermanent(0, 2, new FilterCreaturePermanent("target creatures"), false)); ability.addTarget(new TargetCreaturePermanent(0, 2, StaticFilters.FILTER_PERMANENT_CREATURES, false));
ability.addTarget(new TargetLandPermanent(0, 2, new FilterLandPermanent("target land"), false)); ability.addTarget(new TargetLandPermanent(0, 2, StaticFilters.FILTER_LANDS, false));
this.addAbility(ability); this.addAbility(ability);
//-3: Target creature gets +5/+5 until end of turn. //-3: Target creature gets +5/+5 until end of turn.
@ -74,10 +82,8 @@ public class NissaGenesisMage extends CardImpl {
this.addAbility(ability); this.addAbility(ability);
//-10: Look at the top ten cards of your library. You may put any number of creature and/or land cards from among them onto the battlefield. Put the rest on the bottom of your library in a random order.); //-10: Look at the top ten cards of your library. You may put any number of creature and/or land cards from among them onto the battlefield. Put the rest on the bottom of your library in a random order.);
FilterCard filter = new FilterCard("creature and/or land cards");
filter.add(Predicates.or(new CardTypePredicate(CardType.CREATURE), new CardTypePredicate(CardType.LAND)));
this.addAbility(new LoyaltyAbility( this.addAbility(new LoyaltyAbility(
new LookLibraryAndPickControllerEffect(10, 10, filter, false, false, Zone.BATTLEFIELD, true).setBackInRandomOrder(true), new LookLibraryAndPickControllerEffect(10, 10, filter, false, true, Zone.BATTLEFIELD, false).setBackInRandomOrder(true),
-10)); -10));
} }

View file

@ -0,0 +1,141 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.n;
import java.util.UUID;
import mage.MageInt;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
import mage.abilities.condition.InvertCondition;
import mage.abilities.condition.common.BeforeAttackersAreDeclaredCondition;
import mage.abilities.condition.common.TargetAttackedThisTurnCondition;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.decorator.ConditionalActivatedAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.abilities.effects.common.UntapTargetEffect;
import mage.abilities.effects.common.combat.AttacksIfAbleTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.filter.predicate.permanent.ControlledFromStartOfControllerTurnPredicate;
import mage.filter.predicate.permanent.ControllerPredicate;
import mage.game.Game;
import mage.target.common.TargetCreaturePermanent;
import mage.target.targetpointer.FixedTarget;
import mage.watchers.common.AttackedThisTurnWatcher;
/**
*
* @author MTGfan & L_J
*/
public class Norritt extends CardImpl {
private static final FilterCreaturePermanent filterBlue = new FilterCreaturePermanent("blue creature");
static {
filterBlue.add(new ColorPredicate(ObjectColor.BLUE));
}
private static final FilterCreaturePermanent filterCreature = new FilterCreaturePermanent("non-Wall creature");
static {
filterCreature.add(Predicates.not(new SubtypePredicate(SubType.WALL)));
filterCreature.add(new ControlledFromStartOfControllerTurnPredicate());
filterCreature.add(new ControllerPredicate(TargetController.ACTIVE));
filterCreature.setMessage("non-Wall creature the active player has controlled continuously since the beginning of the turn.");
}
public Norritt(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}");
this.subtype.add(SubType.IMP);
this.power = new MageInt(1);
this.toughness = new MageInt(1);
// {T}: Untap target blue creature.
Ability ability1 = new SimpleActivatedAbility(Zone.BATTLEFIELD, new UntapTargetEffect(), new TapSourceCost());
ability1.addTarget(new TargetCreaturePermanent(filterBlue));
this.addAbility(ability1);
// {T}: Choose target non-Wall creature the active player has controlled continuously since the beginning of the turn. That creature attacks this turn if able. If it doesn't, destroy it at the beginning of the next end step. Activate this ability only before attackers are declared.
Ability ability2 = new ConditionalActivatedAbility(Zone.BATTLEFIELD, new AttacksIfAbleTargetEffect(Duration.EndOfTurn),
new TapSourceCost(), BeforeAttackersAreDeclaredCondition.instance,
"{T}: Choose target non-Wall creature the active player has controlled continuously since the beginning of the turn. "
+ "That creature attacks this turn if able. If it doesn't, destroy it at the beginning of the next end step. "
+ "Activate this ability only before attackers are declared.");
ability2.addEffect(new NorrittDelayedDestroyEffect());
ability2.addTarget(new TargetCreaturePermanent(filterCreature));
this.addAbility(ability2, new AttackedThisTurnWatcher());
}
public Norritt(final Norritt card) {
super(card);
}
@Override
public Norritt copy() {
return new Norritt(this);
}
}
class NorrittDelayedDestroyEffect extends OneShotEffect {
public NorrittDelayedDestroyEffect() {
super(Outcome.Detriment);
this.staticText = "If it doesn't, destroy it at the beginning of the next end step";
}
public NorrittDelayedDestroyEffect(final NorrittDelayedDestroyEffect effect) {
super(effect);
}
@Override
public NorrittDelayedDestroyEffect copy() {
return new NorrittDelayedDestroyEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
DestroyTargetEffect effect = new DestroyTargetEffect();
effect.setTargetPointer(new FixedTarget(source.getFirstTarget()));
AtTheBeginOfNextEndStepDelayedTriggeredAbility delayedAbility
= new AtTheBeginOfNextEndStepDelayedTriggeredAbility(Zone.ALL, effect, TargetController.ANY, new InvertCondition(TargetAttackedThisTurnCondition.instance));
delayedAbility.getDuration();
delayedAbility.getTargets().addAll(source.getTargets());
game.addDelayedTriggeredAbility(delayedAbility, source);
return true;
}
}

View file

@ -0,0 +1,129 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.n;
import java.util.UUID;
import mage.MageObject;
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.RedirectionEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.common.FilterCreaturePermanent;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.game.stack.Spell;
import mage.players.Player;
import mage.target.TargetSource;
import mage.target.common.TargetOpponentsChoicePermanent;
/**
*
* @author L_J
*/
public class NovaPentacle extends CardImpl {
public NovaPentacle(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{4}");
// {3}, {tap}: The next time a source of your choice would deal damage to you this turn, that damage is dealt to target creature of an opponent's choice instead
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new NovaPentacleEffect(), new GenericManaCost(3));
ability.addCost(new TapSourceCost());
ability.addTarget(new TargetOpponentsChoicePermanent(1, 1, new FilterCreaturePermanent(), false, true));
this.addAbility(ability);
}
public NovaPentacle(final NovaPentacle card) {
super(card);
}
@Override
public NovaPentacle copy() {
return new NovaPentacle(this);
}
}
class NovaPentacleEffect extends RedirectionEffect {
private final TargetSource damageSource;
public NovaPentacleEffect() {
super(Duration.EndOfTurn, Integer.MAX_VALUE, true);
staticText = "The next time a source of your choice would deal damage to you this turn, that damage is dealt to target creature of an opponent's choice instead";
this.damageSource = new TargetSource();
}
public NovaPentacleEffect(final NovaPentacleEffect effect) {
super(effect);
this.damageSource = effect.damageSource.copy();
}
@Override
public NovaPentacleEffect copy() {
return new NovaPentacleEffect(this);
}
@Override
public void init(Ability source, Game game) {
this.damageSource.choose(Outcome.PreventDamage, source.getControllerId(), source.getSourceId(), game);
super.init(source, game);
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
// check source
MageObject object = game.getObject(event.getSourceId());
if (object == null) {
game.informPlayers("Couldn't find source of damage");
return false;
}
if (!object.getId().equals(damageSource.getFirstTarget())
&& (!(object instanceof Spell) || !((Spell) object).getSourceId().equals(damageSource.getFirstTarget()))) {
return false;
}
this.redirectTarget = source.getTargets().get(0);
// check player
Player player = game.getPlayer(event.getTargetId());
if (player != null) {
if (player.getId().equals(source.getControllerId())) {
return true;
}
}
return false;
}
}

View file

@ -31,7 +31,8 @@ import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl; import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.ReplacementEffectImpl; import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.FirstStrikeAbility; import mage.abilities.keyword.FirstStrikeAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
@ -40,6 +41,7 @@ import mage.game.Game;
import mage.game.events.GameEvent; import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType; import mage.game.events.GameEvent.EventType;
import mage.players.Player; import mage.players.Player;
import mage.watchers.common.ChooseBlockersRedundancyWatcher;
/** /**
* @author noxx * @author noxx
@ -75,7 +77,9 @@ public class OdricMasterTactician extends CardImpl {
class OdricMasterTacticianTriggeredAbility extends TriggeredAbilityImpl { class OdricMasterTacticianTriggeredAbility extends TriggeredAbilityImpl {
public OdricMasterTacticianTriggeredAbility() { public OdricMasterTacticianTriggeredAbility() {
super(Zone.BATTLEFIELD, new OdricMasterTacticianEffect()); super(Zone.BATTLEFIELD, new OdricMasterTacticianChooseBlockersEffect());
this.addWatcher(new ChooseBlockersRedundancyWatcher());
this.addEffect(new ChooseBlockersRedundancyWatcherIncrementEffect());
} }
public OdricMasterTacticianTriggeredAbility(final OdricMasterTacticianTriggeredAbility ability) { public OdricMasterTacticianTriggeredAbility(final OdricMasterTacticianTriggeredAbility ability) {
@ -89,66 +93,59 @@ class OdricMasterTacticianTriggeredAbility extends TriggeredAbilityImpl {
@Override @Override
public boolean checkEventType(GameEvent event, Game game) { public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == EventType.DECLARED_ATTACKERS; return event.getType() == GameEvent.EventType.DECLARED_ATTACKERS;
} }
@Override @Override
public boolean checkTrigger(GameEvent event, Game game) { public boolean checkTrigger(GameEvent event, Game game) {
resetEffect(); return game.getCombat().getAttackers().size() >= 4 && game.getCombat().getAttackers().contains(this.sourceId);
if (game.getCombat().getAttackers().size() >= 4 && game.getCombat().getAttackers().contains(this.sourceId)) {
enableEffect();
return true;
}
return false;
} }
@Override private class ChooseBlockersRedundancyWatcherIncrementEffect extends OneShotEffect {
public void reset(Game game) {
resetEffect(); ChooseBlockersRedundancyWatcherIncrementEffect() {
super(Outcome.Neutral);
} }
private void resetEffect() { ChooseBlockersRedundancyWatcherIncrementEffect(final ChooseBlockersRedundancyWatcherIncrementEffect effect) {
getEffects().get(0).setValue("apply_" + sourceId, false);
}
private void enableEffect() {
getEffects().get(0).setValue("apply_" + sourceId, true);
}
@Override
public String getRule() {
return "Whenever {this} and at least three other creatures attack, you choose which creatures block this combat and how those creatures block.";
}
}
class OdricMasterTacticianEffect extends ReplacementEffectImpl {
public OdricMasterTacticianEffect() {
super(Duration.EndOfCombat, Outcome.Benefit);
}
public OdricMasterTacticianEffect(final OdricMasterTacticianEffect effect) {
super(effect); super(effect);
} }
@Override
public OdricMasterTacticianEffect copy() {
return new OdricMasterTacticianEffect(this);
}
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
ChooseBlockersRedundancyWatcher watcher = (ChooseBlockersRedundancyWatcher) game.getState().getWatchers().get(ChooseBlockersRedundancyWatcher.class.getSimpleName());
if (watcher != null) {
watcher.increment();
return true;
}
return false; return false;
} }
@Override @Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) { public ChooseBlockersRedundancyWatcherIncrementEffect copy() {
Player blockController = game.getPlayer(source.getControllerId()); return new ChooseBlockersRedundancyWatcherIncrementEffect(this);
if (blockController != null) {
game.getCombat().selectBlockers(blockController, game);
return true;
} }
}
}
class OdricMasterTacticianChooseBlockersEffect extends ContinuousRuleModifyingEffectImpl {
public OdricMasterTacticianChooseBlockersEffect() {
super(Duration.EndOfCombat, Outcome.Benefit, false, false);
staticText = "Whenever {this} and at least three other creatures attack, you choose which creatures block this combat and how those creatures block";
}
public OdricMasterTacticianChooseBlockersEffect(final OdricMasterTacticianChooseBlockersEffect effect) {
super(effect);
}
@Override
public OdricMasterTacticianChooseBlockersEffect copy() {
return new OdricMasterTacticianChooseBlockersEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
return false; return false;
} }
@ -159,12 +156,21 @@ class OdricMasterTacticianEffect extends ReplacementEffectImpl {
@Override @Override
public boolean applies(GameEvent event, Ability source, Game game) { public boolean applies(GameEvent event, Ability source, Game game) {
Object object = getValue("apply_" + source.getSourceId()); ChooseBlockersRedundancyWatcher watcher = (ChooseBlockersRedundancyWatcher) game.getState().getWatchers().get(ChooseBlockersRedundancyWatcher.class.getSimpleName());
if (object != null && object instanceof Boolean) { watcher.decrement();
if ((Boolean)object) { watcher.copyCount--;
return true; // replace event if (watcher.copyCountApply > 0) {
game.informPlayers(source.getSourceObject(game).getIdName() + " didn't apply");
this.discard();
return false;
} }
watcher.copyCountApply = watcher.copyCount;
Player blockController = game.getPlayer(source.getControllerId());
if (blockController != null) {
game.getCombat().selectBlockers(blockController, game);
return true;
} }
this.discard();
return false; return false;
} }
} }

View file

@ -69,9 +69,7 @@ public class OpalEyeKondasYojimbo extends CardImpl {
this.addAbility(new BushidoAbility(1)); this.addAbility(new BushidoAbility(1));
// {T}: The next time a source of your choice would deal damage this turn, that damage is dealt to Opal-Eye, Konda's Yojimbo instead. // {T}: The next time a source of your choice would deal damage this turn, that damage is dealt to Opal-Eye, Konda's Yojimbo instead.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new OpalEyeKondasYojimboRedirectionEffect(), new TapSourceCost()); this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new OpalEyeKondasYojimboRedirectionEffect(), new TapSourceCost()));
ability.addTarget(new TargetSource());
this.addAbility(ability);
// {1}{W}: Prevent the next 1 damage that would be dealt to Opal-Eye this turn. // {1}{W}: Prevent the next 1 damage that would be dealt to Opal-Eye this turn.
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new PreventDamageToSourceEffect(Duration.EndOfTurn, 1), new ManaCostsImpl("{1}{W}"))); this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new PreventDamageToSourceEffect(Duration.EndOfTurn, 1), new ManaCostsImpl("{1}{W}")));

View file

@ -29,27 +29,36 @@ package mage.cards.p;
import java.util.UUID; import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.ObjectColor;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.UntapSourceCost; import mage.abilities.costs.common.UntapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.ProtectionAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.choices.ChoiceColor; import mage.choices.ChoiceColor;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.SubType; import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Layer;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.constants.SubLayer;
import mage.constants.Zone; import mage.constants.Zone;
import mage.filter.FilterObject;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.players.Player; import mage.players.Player;
import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetCreaturePermanent;
import mage.target.targetpointer.FixedTarget;
/** /**
* *
* @author jeffwadsworth * @author jeffwadsworth & L_J
*
*/ */
public class PaleWayfarer extends CardImpl { public class PaleWayfarer extends CardImpl {
@ -92,7 +101,7 @@ class PaleWayfarerEffect extends OneShotEffect {
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
Permanent targetCreature = game.getPermanent(source.getFirstTarget()); Permanent targetCreature = game.getPermanent(getTargetPointer().getFirst(game, source));
if (targetCreature != null) { if (targetCreature != null) {
Player player = game.getPlayer(targetCreature.getControllerId()); Player player = game.getPlayer(targetCreature.getControllerId());
if (player != null) { if (player != null) {
@ -100,8 +109,16 @@ class PaleWayfarerEffect extends OneShotEffect {
if (player.choose(Outcome.Neutral, colorChoice, game)) { if (player.choose(Outcome.Neutral, colorChoice, game)) {
game.informPlayers(targetCreature.getName() + ": " + player.getLogName() + " has chosen " + colorChoice.getChoice()); game.informPlayers(targetCreature.getName() + ": " + player.getLogName() + " has chosen " + colorChoice.getChoice());
game.getState().setValue(targetCreature.getId() + "_color", colorChoice.getColor()); game.getState().setValue(targetCreature.getId() + "_color", colorChoice.getColor());
ObjectColor protectColor = (ObjectColor) game.getState().getValue(targetCreature.getId() + "_color");
if (protectColor != null) {
ContinuousEffect effect = new ProtectionChosenColorTargetEffect();
effect.setTargetPointer(new FixedTarget(targetCreature, game));
game.addEffect(effect, source);
} }
} }
return true;
}
} }
return false; return false;
} }
@ -111,3 +128,48 @@ class PaleWayfarerEffect extends OneShotEffect {
return new PaleWayfarerEffect(this); return new PaleWayfarerEffect(this);
} }
} }
class ProtectionChosenColorTargetEffect extends ContinuousEffectImpl {
protected ObjectColor chosenColor;
protected ProtectionAbility protectionAbility;
public ProtectionChosenColorTargetEffect() {
super(Duration.EndOfTurn, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility);
}
public ProtectionChosenColorTargetEffect(final ProtectionChosenColorTargetEffect effect) {
super(effect);
if (effect.chosenColor != null) {
this.chosenColor = effect.chosenColor.copy();
}
if (effect.protectionAbility != null) {
this.protectionAbility = effect.protectionAbility.copy();
}
}
@Override
public ProtectionChosenColorTargetEffect copy() {
return new ProtectionChosenColorTargetEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
if (permanent != null) {
ObjectColor color = (ObjectColor) game.getState().getValue(permanent.getId() + "_color");
if (color != null && (protectionAbility == null || !color.equals(chosenColor))) {
chosenColor = color;
FilterObject protectionFilter = new FilterObject(chosenColor.getDescription());
protectionFilter.add(new ColorPredicate(chosenColor));
protectionAbility = new ProtectionAbility(protectionFilter);
}
if (protectionAbility != null) {
permanent.addAbility(protectionAbility, source.getSourceId(), game);
return true;
}
}
return false;
}
}

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