forked from External/mage
Merge branch 'External-master'
All checks were successful
/ build_release (push) Successful in 27m57s
All checks were successful
/ build_release (push) Successful in 27m57s
This commit is contained in:
commit
d2c32ec53f
435 changed files with 12052 additions and 2085 deletions
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-root</artifactId>
|
||||
<version>1.4.56</version>
|
||||
<version>1.4.57</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-client</artifactId>
|
||||
|
|
|
|||
|
|
@ -2626,19 +2626,19 @@
|
|||
<Component class="javax.swing.JCheckBox" name="cbStopBlockWithAny">
|
||||
<Properties>
|
||||
<Property name="selected" type="boolean" value="true"/>
|
||||
<Property name="text" type="java.lang.String" value="STOP skips on declare blockers if ANY blockers are available"/>
|
||||
<Property name="text" type="java.lang.String" value="STOP skips when attacked and on declare blockers if ANY blockers are available"/>
|
||||
<Property name="actionCommand" type="java.lang.String" value=""/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="cbStopBlockWithZero">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="STOP skips on declare blockers if ZERO blockers are available"/>
|
||||
<Property name="text" type="java.lang.String" value="STOP skips when attacked if ZERO blockers are available"/>
|
||||
<Property name="actionCommand" type="java.lang.String" value=""/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="cbStopOnNewStackObjects">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Skip to STACK resolved (F10): stop on new objects added (on) or stop until empty (off)"/>
|
||||
<Property name="text" type="java.lang.String" value="Skip to STACK resolved (F10): stop on new objects added (on) or stop when stack empty (off)"/>
|
||||
<Property name="actionCommand" type="java.lang.String" value=""/>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[300, 25]"/>
|
||||
|
|
|
|||
|
|
@ -2403,15 +2403,15 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
phases_stopSettings.add(cbStopAttack);
|
||||
|
||||
cbStopBlockWithAny.setSelected(true);
|
||||
cbStopBlockWithAny.setText("STOP skips on declare blockers if ANY blockers are available");
|
||||
cbStopBlockWithAny.setText("STOP skips when attacked and on declare blockers if ANY blockers are available");
|
||||
cbStopBlockWithAny.setActionCommand("");
|
||||
phases_stopSettings.add(cbStopBlockWithAny);
|
||||
|
||||
cbStopBlockWithZero.setText("STOP skips on declare blockers if ZERO blockers are available");
|
||||
cbStopBlockWithZero.setText("STOP skips when attacked if ZERO blockers are available");
|
||||
cbStopBlockWithZero.setActionCommand("");
|
||||
phases_stopSettings.add(cbStopBlockWithZero);
|
||||
|
||||
cbStopOnNewStackObjects.setText("Skip to STACK resolved (F10): stop on new objects added (on) or stop until empty (off)");
|
||||
cbStopOnNewStackObjects.setText("Skip to STACK resolved (F10): stop on new objects added (on) or stop when stack empty (off)");
|
||||
cbStopOnNewStackObjects.setActionCommand("");
|
||||
cbStopOnNewStackObjects.setPreferredSize(new java.awt.Dimension(300, 25));
|
||||
phases_stopSettings.add(cbStopOnNewStackObjects);
|
||||
|
|
|
|||
|
|
@ -123,6 +123,7 @@ public class ModernCardRenderer extends CardRenderer {
|
|||
public static final Color ERROR_COLOR = new Color(255, 0, 255);
|
||||
|
||||
static String SUB_TYPE_ADVENTURE = "Adventure";
|
||||
static String SUB_TYPE_OMEN = "Omen";
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Layout metrics for modern border cards
|
||||
|
|
@ -168,8 +169,8 @@ public class ModernCardRenderer extends CardRenderer {
|
|||
// Processed mana cost string
|
||||
protected String manaCostString;
|
||||
|
||||
// Is an adventure
|
||||
protected boolean isAdventure = false;
|
||||
// Is an adventure or omen
|
||||
protected boolean isCardWithSpellOption = false;
|
||||
|
||||
public ModernCardRenderer(CardView card) {
|
||||
// Pass off to parent
|
||||
|
|
@ -179,12 +180,13 @@ public class ModernCardRenderer extends CardRenderer {
|
|||
manaCostString = ManaSymbols.getClearManaCost(cardView.getManaCostStr());
|
||||
|
||||
if (cardView.isSplitCard()) {
|
||||
isAdventure = cardView.getRightSplitTypeLine().contains(SUB_TYPE_ADVENTURE);
|
||||
isCardWithSpellOption = cardView.getRightSplitTypeLine().contains(SUB_TYPE_ADVENTURE)
|
||||
|| cardView.getRightSplitTypeLine().contains(SUB_TYPE_OMEN);
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isAdventure() {
|
||||
return isAdventure;
|
||||
protected boolean isCardWithSpellOption() {
|
||||
return isCardWithSpellOption;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -660,7 +662,7 @@ public class ModernCardRenderer extends CardRenderer {
|
|||
drawRulesText(g, textboxKeywords, textboxRules,
|
||||
contentWidth / 2 + totalContentInset + 4, totalContentInset + boxHeight + 2,
|
||||
contentWidth / 2 - 8, typeLineY - totalContentInset - boxHeight - 6, false);
|
||||
} else if (isAdventure) {
|
||||
} else if (isCardWithSpellOption) {
|
||||
drawRulesText(g, textboxKeywords, textboxRules,
|
||||
contentWidth / 2 + totalContentInset + 4, typeLineY + boxHeight + 2,
|
||||
contentWidth / 2 - 8, cardHeight - typeLineY - boxHeight - 4 - borderWidth * 3, false);
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ public class ModernSplitCardRenderer extends ModernCardRenderer {
|
|||
private boolean isAftermath = false;
|
||||
|
||||
private static String trimAdventure(String rule) {
|
||||
if (rule.startsWith("Adventure")) {
|
||||
if (rule.startsWith("Adventure") || rule.startsWith("Omen")) {
|
||||
return rule.substring(rule.lastIndexOf("—") + 8);
|
||||
}
|
||||
return rule;
|
||||
|
|
@ -71,7 +71,7 @@ public class ModernSplitCardRenderer extends ModernCardRenderer {
|
|||
rightHalf.color = new ObjectColor(cardView.getRightSplitCostsStr());
|
||||
leftHalf.color = new ObjectColor(cardView.getLeftSplitCostsStr());
|
||||
|
||||
if (isAdventure()) {
|
||||
if (isCardWithSpellOption()) {
|
||||
List<String> trimmedRules = new ArrayList<>();
|
||||
for (String rule : view.getRightSplitRules()) {
|
||||
trimmedRules.add(trimAdventure(rule));
|
||||
|
|
@ -95,7 +95,7 @@ public class ModernSplitCardRenderer extends ModernCardRenderer {
|
|||
// they "rotate" in opposite directions making consquence and normal split cards
|
||||
// have the "right" vs "left" as the top half.
|
||||
// Adventures are treated differently and not rotated at all.
|
||||
if (isAdventure()) {
|
||||
if (isCardWithSpellOption()) {
|
||||
manaCostString = leftHalf.manaCostString;
|
||||
textboxKeywords = leftHalf.keywords;
|
||||
textboxRules = leftHalf.rules;
|
||||
|
|
@ -159,7 +159,7 @@ public class ModernSplitCardRenderer extends ModernCardRenderer {
|
|||
protected void drawBackground(Graphics2D g) {
|
||||
if (cardView.isFaceDown()) {
|
||||
drawCardBackTexture(g);
|
||||
} if (isAdventure()) {
|
||||
} if (isCardWithSpellOption()) {
|
||||
super.drawBackground(g);
|
||||
} else {
|
||||
{ // Left half background (top of the card)
|
||||
|
|
@ -204,7 +204,7 @@ public class ModernSplitCardRenderer extends ModernCardRenderer {
|
|||
|
||||
@Override
|
||||
protected void drawArt(Graphics2D g) {
|
||||
if (isAdventure) {
|
||||
if (isCardWithSpellOption) {
|
||||
super.drawArt(g);
|
||||
} else if (artImage != null) {
|
||||
if (isAftermath()) {
|
||||
|
|
@ -318,7 +318,7 @@ public class ModernSplitCardRenderer extends ModernCardRenderer {
|
|||
|
||||
@Override
|
||||
protected void drawFrame(Graphics2D g, CardPanelAttributes attribs, BufferedImage image, boolean lessOpaqueRulesTextBox) {
|
||||
if (isAdventure()) {
|
||||
if (isCardWithSpellOption()) {
|
||||
super.drawFrame(g, attribs, image, lessOpaqueRulesTextBox);
|
||||
|
||||
CardPanelAttributes adventureAttribs = new CardPanelAttributes(
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ public class ScryfallApiCard {
|
|||
this.card_faces.forEach(ScryfallApiCardFace::prepareCompatibleData);
|
||||
}
|
||||
|
||||
// workaround for adventure card name fix:
|
||||
// workaround for adventure/omen card name fix:
|
||||
// - scryfall: Ondu Knotmaster // Throw a Line
|
||||
// - xmage: Ondu Knotmaster
|
||||
if (this.layout.equals("adventure")) {
|
||||
|
|
@ -100,12 +100,12 @@ public class ScryfallApiCard {
|
|||
}
|
||||
this.name = this.card_faces.get(0).name;
|
||||
} else if (this.card_faces.get(0).layout.equals("adventure")) {
|
||||
// adventure card
|
||||
// adventure/omen card
|
||||
// Bloomvine Regent // Claim Territory
|
||||
// https://scryfall.com/card/tdm/381/bloomvine-regent-claim-territory-bloomvine-regent
|
||||
this.name = this.card_faces.get(0).name;
|
||||
if (this.card_faces.get(0).name.equals(this.card_faces.get(1).name)) {
|
||||
throw new IllegalArgumentException("Scryfall: unsupported data type, adventure's reversible_card must have diff names in faces "
|
||||
throw new IllegalArgumentException("Scryfall: unsupported data type, adventure/omen's reversible_card must have diff names in faces "
|
||||
+ this.set + " - " + this.collector_number + " - " + this.name);
|
||||
}
|
||||
} else if (this.card_faces.get(0).layout.equals("token")) {
|
||||
|
|
|
|||
|
|
@ -2183,6 +2183,7 @@ public class ScryfallImageSupportTokens {
|
|||
// WHO
|
||||
put("WHO/Alien", "https://api.scryfall.com/cards/twho/2?format=image");
|
||||
put("WHO/Alien Insect", "https://api.scryfall.com/cards/twho/19/en?format=image");
|
||||
put("WHO/Alien Rhino", "https://api.scryfall.com/cards/twho/3/en?format=image");
|
||||
put("WHO/Alien Salamander", "https://api.scryfall.com/cards/twho/16?format=image");
|
||||
put("WHO/Alien Warrior", "https://api.scryfall.com/cards/twho/14?format=image");
|
||||
put("WHO/Beast", "https://api.scryfall.com/cards/twho/17?format=image");
|
||||
|
|
@ -2196,7 +2197,8 @@ public class ScryfallImageSupportTokens {
|
|||
put("WHO/Food/2", "https://api.scryfall.com/cards/twho/26?format=image");
|
||||
put("WHO/Food/3", "https://api.scryfall.com/cards/twho/27?format=image");
|
||||
put("WHO/Horse", "https://api.scryfall.com/cards/twho/4/en?format=image");
|
||||
put("WHO/Human", "https://api.scryfall.com/cards/twho/5?format=image");
|
||||
put("WHO/Human/1", "https://api.scryfall.com/cards/twho/6/en?format=image");
|
||||
put("WHO/Human/2", "https://api.scryfall.com/cards/twho/5/en?format=image");
|
||||
put("WHO/Human Noble", "https://api.scryfall.com/cards/twho/7/en?format=image");
|
||||
put("WHO/Mark of the Rani", "https://api.scryfall.com/cards/twho/15?format=image");
|
||||
put("WHO/Soldier", "https://api.scryfall.com/cards/twho/8?format=image");
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-root</artifactId>
|
||||
<version>1.4.56</version>
|
||||
<version>1.4.57</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-common</artifactId>
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@ public class MageVersion implements Serializable, Comparable<MageVersion> {
|
|||
// * launcher gives priority to 1.4.48 instead 1.4.48-any-text, so don't use empty release info
|
||||
public static final int MAGE_VERSION_MAJOR = 1;
|
||||
public static final int MAGE_VERSION_MINOR = 4;
|
||||
public static final int MAGE_VERSION_RELEASE = 56;
|
||||
public static final String MAGE_VERSION_RELEASE_INFO = "V3"; // V1, V1a, V1b for releases; V1-beta3, V1-beta4 for betas
|
||||
public static final int MAGE_VERSION_RELEASE = 57;
|
||||
public static final String MAGE_VERSION_RELEASE_INFO = "V1"; // V1, V1a, V1b for releases; V1-beta3, V1-beta4 for betas
|
||||
|
||||
// strict mode
|
||||
// Each update requires a strict version
|
||||
|
|
|
|||
|
|
@ -432,21 +432,21 @@ public class CardView extends SimpleCardView {
|
|||
fullCardName = mainCard.getLeftHalfCard().getName() + MockCard.MODAL_DOUBLE_FACES_NAME_SEPARATOR + mainCard.getRightHalfCard().getName();
|
||||
this.manaCostLeftStr = mainCard.getLeftHalfCard().getManaCostSymbols();
|
||||
this.manaCostRightStr = mainCard.getRightHalfCard().getManaCostSymbols();
|
||||
} else if (card instanceof AdventureCard) {
|
||||
} else if (card instanceof CardWithSpellOption) {
|
||||
this.isSplitCard = true;
|
||||
AdventureCard adventureCard = ((AdventureCard) card);
|
||||
leftSplitName = adventureCard.getName();
|
||||
leftSplitCostsStr = String.join("", adventureCard.getManaCostSymbols());
|
||||
leftSplitRules = adventureCard.getSharedRules(game);
|
||||
leftSplitTypeLine = getCardTypeLine(game, adventureCard);
|
||||
AdventureCardSpell adventureCardSpell = adventureCard.getSpellCard();
|
||||
rightSplitName = adventureCardSpell.getName();
|
||||
rightSplitCostsStr = String.join("", adventureCardSpell.getManaCostSymbols());
|
||||
rightSplitRules = adventureCardSpell.getRules(game);
|
||||
rightSplitTypeLine = getCardTypeLine(game, adventureCardSpell);
|
||||
fullCardName = adventureCard.getName() + MockCard.ADVENTURE_NAME_SEPARATOR + adventureCardSpell.getName();
|
||||
this.manaCostLeftStr = adventureCard.getManaCostSymbols();
|
||||
this.manaCostRightStr = adventureCardSpell.getManaCostSymbols();
|
||||
CardWithSpellOption mainCard = ((CardWithSpellOption) card);
|
||||
leftSplitName = mainCard.getName();
|
||||
leftSplitCostsStr = String.join("", mainCard.getManaCostSymbols());
|
||||
leftSplitRules = mainCard.getSharedRules(game);
|
||||
leftSplitTypeLine = getCardTypeLine(game, mainCard);
|
||||
SpellOptionCard splitCardSpell = mainCard.getSpellCard();
|
||||
rightSplitName = splitCardSpell.getName();
|
||||
rightSplitCostsStr = String.join("", splitCardSpell.getManaCostSymbols());
|
||||
rightSplitRules = splitCardSpell.getRules(game);
|
||||
rightSplitTypeLine = getCardTypeLine(game, splitCardSpell);
|
||||
fullCardName = mainCard.getName() + MockCard.CARD_WITH_SPELL_OPTION_NAME_SEPARATOR + splitCardSpell.getName();
|
||||
this.manaCostLeftStr = mainCard.getManaCostSymbols();
|
||||
this.manaCostRightStr = splitCardSpell.getManaCostSymbols();
|
||||
} else if (card instanceof MockCard) {
|
||||
// deck editor cards
|
||||
fullCardName = ((MockCard) card).getFullName(true);
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-plugins</artifactId>
|
||||
<version>1.4.56</version>
|
||||
<version>1.4.57</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-counter-plugin</artifactId>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-root</artifactId>
|
||||
<version>1.4.56</version>
|
||||
<version>1.4.57</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-plugins</artifactId>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-root</artifactId>
|
||||
<version>1.4.56</version>
|
||||
<version>1.4.57</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-reports</artifactId>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-root</artifactId>
|
||||
<version>1.4.56</version>
|
||||
<version>1.4.57</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-server-console</artifactId>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.56</version>
|
||||
<version>1.4.57</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-deck-constructed</artifactId>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.56</version>
|
||||
<version>1.4.57</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-deck-limited</artifactId>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.56</version>
|
||||
<version>1.4.57</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-game-brawlduel</artifactId>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.56</version>
|
||||
<version>1.4.57</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-game-brawlfreeforall</artifactId>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.56</version>
|
||||
<version>1.4.57</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-game-canadianhighlanderduel</artifactId>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.56</version>
|
||||
<version>1.4.57</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-game-commanderduel</artifactId>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.56</version>
|
||||
<version>1.4.57</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-game-commanderfreeforall</artifactId>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.56</version>
|
||||
<version>1.4.57</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-game-custompillaroftheparunsduel</artifactId>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.56</version>
|
||||
<version>1.4.57</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-game-freeforall</artifactId>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.56</version>
|
||||
<version>1.4.57</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-game-freeformcommanderduel</artifactId>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.56</version>
|
||||
<version>1.4.57</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-game-freeformcommanderfreeforall</artifactId>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.56</version>
|
||||
<version>1.4.57</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-game-freeformunlimitedcommander</artifactId>
|
||||
|
|
@ -23,7 +23,7 @@
|
|||
<dependency>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-game-freeformcommanderfreeforall</artifactId>
|
||||
<version>1.4.56</version>
|
||||
<version>1.4.57</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.56</version>
|
||||
<version>1.4.57</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-game-momirduel</artifactId>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.56</version>
|
||||
<version>1.4.57</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-game-momirfreeforall</artifactId>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.56</version>
|
||||
<version>1.4.57</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-game-oathbreakerduel</artifactId>
|
||||
|
|
@ -22,7 +22,7 @@
|
|||
<dependency>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-game-oathbreakerfreeforall</artifactId>
|
||||
<version>1.4.56</version>
|
||||
<version>1.4.57</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.56</version>
|
||||
<version>1.4.57</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-game-oathbreakerfreeforall</artifactId>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.56</version>
|
||||
<version>1.4.57</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-game-pennydreadfulcommanderfreeforall</artifactId>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.56</version>
|
||||
<version>1.4.57</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-game-tinyleadersduel</artifactId>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.56</version>
|
||||
<version>1.4.57</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-game-twoplayerduel</artifactId>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.56</version>
|
||||
<version>1.4.57</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-player-ai-draftbot</artifactId>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.56</version>
|
||||
<version>1.4.57</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-player-ai-ma</artifactId>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.56</version>
|
||||
<version>1.4.57</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-player-ai</artifactId>
|
||||
|
|
|
|||
|
|
@ -1863,8 +1863,11 @@ public class ComputerPlayer extends PlayerImpl {
|
|||
|
||||
@Override
|
||||
public int announceXMana(int min, int max, String message, Game game, Ability ability) {
|
||||
log.debug("announceXMana");
|
||||
//TODO: improve this
|
||||
// current logic - use max possible mana
|
||||
|
||||
// TODO: add good/bad effects support
|
||||
// TODO: add simple game simulations like declare blocker?
|
||||
|
||||
int numAvailable = getAvailableManaProducers(game).size() - ability.getManaCosts().manaValue();
|
||||
if (numAvailable < 0) {
|
||||
numAvailable = 0;
|
||||
|
|
@ -1881,12 +1884,17 @@ public class ComputerPlayer extends PlayerImpl {
|
|||
|
||||
@Override
|
||||
public int announceXCost(int min, int max, String message, Game game, Ability ability, VariableCost variablCost) {
|
||||
log.debug("announceXCost");
|
||||
// current logic - use random non-zero value
|
||||
|
||||
// TODO: add good/bad effects support
|
||||
// TODO: remove random logic
|
||||
|
||||
int value = RandomUtil.nextInt(CardUtil.overflowInc(max, 1));
|
||||
if (value < min) {
|
||||
value = min;
|
||||
}
|
||||
if (value < max) {
|
||||
// do not use zero values
|
||||
value++;
|
||||
}
|
||||
return value;
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.56</version>
|
||||
<version>1.4.57</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-player-ai-mcts</artifactId>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.56</version>
|
||||
<version>1.4.57</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-player-human</artifactId>
|
||||
|
|
|
|||
|
|
@ -380,9 +380,13 @@ public class HumanPlayer extends PlayerImpl {
|
|||
}
|
||||
}
|
||||
|
||||
private boolean canCallFeedback(Game game) {
|
||||
return !gameInCheckPlayableState(game) && !game.isSimulation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean chooseMulligan(Game game) {
|
||||
if (gameInCheckPlayableState(game)) {
|
||||
if (!canCallFeedback(game)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -509,7 +513,7 @@ public class HumanPlayer extends PlayerImpl {
|
|||
|
||||
@Override
|
||||
public int chooseReplacementEffect(Map<String, String> effectsMap, Map<String, MageObject> objectsMap, Game game) {
|
||||
if (gameInCheckPlayableState(game, true)) { // ignore warning logs until double call for TAPPED_FOR_MANA will be fix
|
||||
if (gameInCheckPlayableState(game, true) || game.isSimulation()) { // TODO: ignore warning logs until double call for TAPPED_FOR_MANA will be fix
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -615,7 +619,7 @@ public class HumanPlayer extends PlayerImpl {
|
|||
|
||||
@Override
|
||||
public boolean choose(Outcome outcome, Choice choice, Game game) {
|
||||
if (gameInCheckPlayableState(game)) {
|
||||
if (!canCallFeedback(game)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -678,7 +682,7 @@ public class HumanPlayer extends PlayerImpl {
|
|||
|
||||
@Override
|
||||
public boolean choose(Outcome outcome, Target target, Ability source, Game game, Map<String, Serializable> options) {
|
||||
if (gameInCheckPlayableState(game)) {
|
||||
if (!canCallFeedback(game)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -782,7 +786,7 @@ public class HumanPlayer extends PlayerImpl {
|
|||
|
||||
@Override
|
||||
public boolean chooseTarget(Outcome outcome, Target target, Ability source, Game game) {
|
||||
if (gameInCheckPlayableState(game)) {
|
||||
if (!canCallFeedback(game)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -862,7 +866,7 @@ public class HumanPlayer extends PlayerImpl {
|
|||
|
||||
@Override
|
||||
public boolean choose(Outcome outcome, Cards cards, TargetCard target, Ability source, Game game) {
|
||||
if (gameInCheckPlayableState(game)) {
|
||||
if (!canCallFeedback(game)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -944,7 +948,7 @@ public class HumanPlayer extends PlayerImpl {
|
|||
// choose one or multiple target cards
|
||||
@Override
|
||||
public boolean chooseTarget(Outcome outcome, Cards cards, TargetCard target, Ability source, Game game) {
|
||||
if (gameInCheckPlayableState(game)) {
|
||||
if (!canCallFeedback(game)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -1025,7 +1029,7 @@ public class HumanPlayer extends PlayerImpl {
|
|||
public boolean chooseTargetAmount(Outcome outcome, TargetAmount target, Ability source, Game game) {
|
||||
// choose amount
|
||||
// human can choose or un-choose MULTIPLE targets at once
|
||||
if (gameInCheckPlayableState(game)) {
|
||||
if (!canCallFeedback(game)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -1486,8 +1490,8 @@ public class HumanPlayer extends PlayerImpl {
|
|||
@Override
|
||||
public TriggeredAbility chooseTriggeredAbility(java.util.List<TriggeredAbility> abilities, Game game) {
|
||||
// choose triggered abilitity from list
|
||||
if (gameInCheckPlayableState(game)) {
|
||||
return null;
|
||||
if (!canCallFeedback(game)) {
|
||||
return abilities.isEmpty() ? null : abilities.get(0);
|
||||
}
|
||||
|
||||
// automatically order triggers with same ability, rules text, and targets
|
||||
|
|
@ -1615,7 +1619,7 @@ public class HumanPlayer extends PlayerImpl {
|
|||
|
||||
protected boolean playManaHandling(Ability abilityToCast, ManaCost unpaid, String promptText, Game game) {
|
||||
// choose mana to pay (from permanents or from pool)
|
||||
if (gameInCheckPlayableState(game)) {
|
||||
if (!canCallFeedback(game)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -1661,7 +1665,7 @@ public class HumanPlayer extends PlayerImpl {
|
|||
* @return
|
||||
*/
|
||||
public int announceRepetitions(Game game) {
|
||||
if (gameInCheckPlayableState(game)) {
|
||||
if (!canCallFeedback(game)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1694,8 +1698,8 @@ public class HumanPlayer extends PlayerImpl {
|
|||
*/
|
||||
@Override
|
||||
public int announceXMana(int min, int max, String message, Game game, Ability ability) {
|
||||
if (gameInCheckPlayableState(game)) {
|
||||
return 0;
|
||||
if (!canCallFeedback(game)) {
|
||||
return min;
|
||||
}
|
||||
|
||||
int xValue = 0;
|
||||
|
|
@ -1709,6 +1713,8 @@ public class HumanPlayer extends PlayerImpl {
|
|||
if (response.getInteger() != null) {
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO: add response verify here
|
||||
}
|
||||
|
||||
if (response.getInteger() != null) {
|
||||
|
|
@ -1719,8 +1725,8 @@ public class HumanPlayer extends PlayerImpl {
|
|||
|
||||
@Override
|
||||
public int announceXCost(int min, int max, String message, Game game, Ability ability, VariableCost variableCost) {
|
||||
if (gameInCheckPlayableState(game)) {
|
||||
return 0;
|
||||
if (!canCallFeedback(game)) {
|
||||
return min;
|
||||
}
|
||||
|
||||
int xValue = 0;
|
||||
|
|
@ -1792,7 +1798,7 @@ public class HumanPlayer extends PlayerImpl {
|
|||
|
||||
@Override
|
||||
public void selectAttackers(Game game, UUID attackingPlayerId) {
|
||||
if (gameInCheckPlayableState(game)) {
|
||||
if (!canCallFeedback(game)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -2062,7 +2068,7 @@ public class HumanPlayer extends PlayerImpl {
|
|||
|
||||
@Override
|
||||
public void selectBlockers(Ability source, Game game, UUID defendingPlayerId) {
|
||||
if (gameInCheckPlayableState(game)) {
|
||||
if (!canCallFeedback(game)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -2072,7 +2078,6 @@ public class HumanPlayer extends PlayerImpl {
|
|||
// stop skip on any/zero permanents available
|
||||
int possibleBlockersCount = game.getBattlefield().count(filter, playerId, source, game);
|
||||
boolean canStopOnAny = possibleBlockersCount != 0 && getControllingPlayersUserData(game).getUserSkipPrioritySteps().isStopOnDeclareBlockersWithAnyPermanents();
|
||||
boolean canStopOnZero = possibleBlockersCount == 0 && getControllingPlayersUserData(game).getUserSkipPrioritySteps().isStopOnDeclareBlockersWithZeroPermanents();
|
||||
|
||||
// skip declare blocker step
|
||||
// as opposed to declare attacker - it can be skipped by ANY skip button TODO: make same for declare attackers and rework skip buttons (normal and forced)
|
||||
|
|
@ -2081,9 +2086,11 @@ public class HumanPlayer extends PlayerImpl {
|
|||
|| passedTurn
|
||||
|| passedUntilEndOfTurn
|
||||
|| passedUntilNextMain;
|
||||
if (skipButtonActivated && !canStopOnAny && !canStopOnZero) {
|
||||
if (skipButtonActivated && !canStopOnAny) {
|
||||
return;
|
||||
}
|
||||
// Skip prompt to select blockers if player has none
|
||||
if (possibleBlockersCount == 0) return;
|
||||
|
||||
while (canRespond()) {
|
||||
prepareForResponse(game);
|
||||
|
|
@ -2123,7 +2130,7 @@ public class HumanPlayer extends PlayerImpl {
|
|||
}
|
||||
|
||||
protected void selectCombatGroup(UUID defenderId, UUID blockerId, Game game) {
|
||||
if (gameInCheckPlayableState(game)) {
|
||||
if (!canCallFeedback(game)) {
|
||||
return;
|
||||
}
|
||||
TargetAttackingCreature target = new TargetAttackingCreature();
|
||||
|
|
@ -2177,8 +2184,8 @@ public class HumanPlayer extends PlayerImpl {
|
|||
|
||||
@Override
|
||||
public int getAmount(int min, int max, String message, Game game) {
|
||||
if (gameInCheckPlayableState(game)) {
|
||||
return 0;
|
||||
if (!canCallFeedback(game)) {
|
||||
return min;
|
||||
}
|
||||
|
||||
while (canRespond()) {
|
||||
|
|
@ -2217,7 +2224,7 @@ public class HumanPlayer extends PlayerImpl {
|
|||
return defaultList;
|
||||
}
|
||||
|
||||
if (gameInCheckPlayableState(game)) {
|
||||
if (!canCallFeedback(game)) {
|
||||
return defaultList;
|
||||
}
|
||||
|
||||
|
|
@ -2285,7 +2292,7 @@ public class HumanPlayer extends PlayerImpl {
|
|||
* @param unpaidForManaAction - set unpaid for mana actions like convoke
|
||||
*/
|
||||
protected void activateSpecialAction(Game game, ManaCost unpaidForManaAction) {
|
||||
if (gameInCheckPlayableState(game)) {
|
||||
if (!canCallFeedback(game)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -2316,7 +2323,7 @@ public class HumanPlayer extends PlayerImpl {
|
|||
}
|
||||
|
||||
protected void activateAbility(Map<UUID, ? extends ActivatedAbility> abilities, MageObject object, Game game) {
|
||||
if (gameInCheckPlayableState(game)) {
|
||||
if (!canCallFeedback(game)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -2378,7 +2385,7 @@ public class HumanPlayer extends PlayerImpl {
|
|||
Card mainCard = game.getCard(CardUtil.getMainCardId(game, ability.getSourceId()));
|
||||
if (mainCard != null && !Zone.BATTLEFIELD.equals(game.getState().getZone(mainCard.getId()))) {
|
||||
if (mainCard instanceof SplitCard
|
||||
|| mainCard instanceof AdventureCard
|
||||
|| mainCard instanceof CardWithSpellOption
|
||||
|| mainCard instanceof ModalDoubleFacedCard) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -2401,7 +2408,7 @@ public class HumanPlayer extends PlayerImpl {
|
|||
|
||||
@Override
|
||||
public SpellAbility chooseAbilityForCast(Card card, Game game, boolean noMana) {
|
||||
if (gameInCheckPlayableState(game)) {
|
||||
if (!canCallFeedback(game)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
@ -2441,7 +2448,7 @@ public class HumanPlayer extends PlayerImpl {
|
|||
|
||||
@Override
|
||||
public ActivatedAbility chooseLandOrSpellAbility(Card card, Game game, boolean noMana) {
|
||||
if (gameInCheckPlayableState(game)) {
|
||||
if (!canCallFeedback(game)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
@ -2488,7 +2495,7 @@ public class HumanPlayer extends PlayerImpl {
|
|||
@Override
|
||||
public Mode chooseMode(Modes modes, Ability source, Game game) {
|
||||
// choose mode to activate
|
||||
if (gameInCheckPlayableState(game)) {
|
||||
if (!canCallFeedback(game)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
@ -2616,7 +2623,7 @@ public class HumanPlayer extends PlayerImpl {
|
|||
|
||||
@Override
|
||||
public boolean choosePile(Outcome outcome, String message, java.util.List<? extends Card> pile1, java.util.List<? extends Card> pile2, Game game) {
|
||||
if (gameInCheckPlayableState(game)) {
|
||||
if (!canCallFeedback(game)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.56</version>
|
||||
<version>1.4.57</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-tournament-boosterdraft</artifactId>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.56</version>
|
||||
<version>1.4.57</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-tournament-constructed</artifactId>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.56</version>
|
||||
<version>1.4.57</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-tournament-sealed</artifactId>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-root</artifactId>
|
||||
<version>1.4.56</version>
|
||||
<version>1.4.57</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-root</artifactId>
|
||||
<version>1.4.56</version>
|
||||
<version>1.4.57</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-server</artifactId>
|
||||
|
|
|
|||
|
|
@ -62,9 +62,6 @@ hand:Human:Angelic Edict:3
|
|||
battlefield:Computer:Grizzly Bears:2
|
||||
battlefield:Human:Grizzly Bears:2
|
||||
|
||||
// special command, see SystemUtil for more special commands list
|
||||
[@activate opponent ability]
|
||||
|
||||
[diff set codes example]
|
||||
battlefield:Human:XLN-Island:1
|
||||
battlefield:Human:UST-Island:1
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-root</artifactId>
|
||||
<version>1.4.56</version>
|
||||
<version>1.4.57</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-sets</artifactId>
|
||||
|
|
|
|||
|
|
@ -1,43 +1,30 @@
|
|||
package mage.cards.a;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.costs.CostAdjuster;
|
||||
import mage.abilities.costs.common.DiscardTargetCost;
|
||||
import mage.abilities.costs.costadjusters.DiscardXCardsCostAdjuster;
|
||||
import mage.abilities.dynamicvalue.common.GetXValue;
|
||||
import mage.abilities.effects.common.InfoEffect;
|
||||
import mage.abilities.effects.common.discard.LookTargetHandChooseDiscardEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.target.common.TargetCardInHand;
|
||||
import mage.target.common.TargetOpponent;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author fireshoes
|
||||
* @author fireshoes, JayDi85
|
||||
*/
|
||||
public final class AbandonHope extends CardImpl {
|
||||
|
||||
public AbandonHope(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{1}{B}");
|
||||
|
||||
// As an additional cost to cast Abandon Hope, discard X cards.
|
||||
Ability ability = new SimpleStaticAbility(
|
||||
Zone.ALL, new InfoEffect("As an additional cost to cast this spell, discard X cards")
|
||||
);
|
||||
ability.setRuleAtTheTop(true);
|
||||
this.addAbility(ability);
|
||||
// As an additional cost to cast this spell, discard X cards.
|
||||
DiscardXCardsCostAdjuster.addAdjusterAndMessage(this, StaticFilters.FILTER_CARD_CARDS);
|
||||
|
||||
// Look at target opponent's hand and choose X cards from it. That player discards those cards.
|
||||
this.getSpellAbility().addEffect(new LookTargetHandChooseDiscardEffect(false, GetXValue.instance, StaticFilters.FILTER_CARD_CARDS));
|
||||
this.getSpellAbility().addTarget(new TargetOpponent());
|
||||
this.getSpellAbility().setCostAdjuster(AbandonHopeAdjuster.instance);
|
||||
}
|
||||
|
||||
private AbandonHope(final AbandonHope card) {
|
||||
|
|
@ -49,15 +36,3 @@ public final class AbandonHope extends CardImpl {
|
|||
return new AbandonHope(this);
|
||||
}
|
||||
}
|
||||
|
||||
enum AbandonHopeAdjuster implements CostAdjuster {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public void adjustCosts(Ability ability, Game game) {
|
||||
int xValue = CardUtil.getSourceCostsTag(game, ability, "X", 0);
|
||||
if (xValue > 0) {
|
||||
ability.addCost(new DiscardTargetCost(new TargetCardInHand(xValue, xValue, StaticFilters.FILTER_CARD_CARDS)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,8 +9,6 @@ import mage.abilities.costs.mana.ManaCostsImpl;
|
|||
import mage.abilities.dynamicvalue.common.GreatestToughnessAmongControlledCreaturesValue;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect;
|
||||
import mage.abilities.hint.Hint;
|
||||
import mage.abilities.hint.ValueHint;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
|
|
@ -41,11 +39,6 @@ public final class AbzanMonument extends CardImpl {
|
|||
));
|
||||
}
|
||||
|
||||
private static final Hint hint = new ValueHint(
|
||||
"Greatest toughness among creatures you control",
|
||||
GreatestToughnessAmongControlledCreaturesValue.instance
|
||||
);
|
||||
|
||||
public AbzanMonument(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}");
|
||||
|
||||
|
|
@ -60,7 +53,7 @@ public final class AbzanMonument extends CardImpl {
|
|||
);
|
||||
ability.addCost(new TapSourceCost());
|
||||
ability.addCost(new SacrificeSourceCost());
|
||||
this.addAbility(ability.addHint(hint));
|
||||
this.addAbility(ability.addHint(GreatestToughnessAmongControlledCreaturesValue.ALL.getHint()));
|
||||
}
|
||||
|
||||
private AbzanMonument(final AbzanMonument card) {
|
||||
|
|
@ -93,9 +86,7 @@ class AbzanMonumentEffect extends OneShotEffect {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return new SpiritXXToken(
|
||||
GreatestToughnessAmongControlledCreaturesValue
|
||||
.instance
|
||||
.calculate(game, source, this)
|
||||
GreatestToughnessAmongControlledCreaturesValue.ALL.calculate(game, source, this)
|
||||
).putOntoBattlefield(1, game, source);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
50
Mage.Sets/src/mage/cards/a/AdaptiveTrainingPost.java
Normal file
50
Mage.Sets/src/mage/cards/a/AdaptiveTrainingPost.java
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
package mage.cards.a;
|
||||
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.common.SpellCastControllerTriggeredAbility;
|
||||
import mage.abilities.common.delayed.CopyNextSpellDelayedTriggeredAbility;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.abilities.condition.common.SourceHasCounterCondition;
|
||||
import mage.abilities.costs.common.RemoveCountersSourceCost;
|
||||
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
|
||||
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.counters.CounterType;
|
||||
import mage.filter.StaticFilters;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class AdaptiveTrainingPost extends CardImpl {
|
||||
|
||||
private static final Condition condition = new SourceHasCounterCondition(CounterType.CHARGE, 0, 2);
|
||||
|
||||
public AdaptiveTrainingPost(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}{U}");
|
||||
|
||||
// Whenever you cast an instant or sorcery spell, if this artifact has fewer than three charge counters on it, put a charge counter on it.
|
||||
this.addAbility(new SpellCastControllerTriggeredAbility(
|
||||
new AddCountersSourceEffect(CounterType.CHARGE.createInstance()),
|
||||
StaticFilters.FILTER_SPELL_AN_INSTANT_OR_SORCERY, false
|
||||
).withInterveningIf(condition));
|
||||
|
||||
// Remove three charge counters from this artifact: When you next cast an instant or sorcery spell this turn, copy it and you may choose new targets for the copy.
|
||||
this.addAbility(new SimpleActivatedAbility(
|
||||
new CreateDelayedTriggeredAbilityEffect(new CopyNextSpellDelayedTriggeredAbility()),
|
||||
new RemoveCountersSourceCost(CounterType.CHARGE.createInstance(3))
|
||||
));
|
||||
}
|
||||
|
||||
private AdaptiveTrainingPost(final AdaptiveTrainingPost card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AdaptiveTrainingPost copy() {
|
||||
return new AdaptiveTrainingPost(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -31,7 +31,7 @@ public final class AeonChronicler extends CardImpl {
|
|||
this.toughness = new MageInt(0);
|
||||
|
||||
// Aeon Chronicler's power and toughness are each equal to the number of cards in your hand.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetBasePowerToughnessSourceEffect(CardsInControllerHandCount.instance)));
|
||||
this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetBasePowerToughnessSourceEffect(CardsInControllerHandCount.ANY)));
|
||||
|
||||
// Suspend X-{X}{3}{U}. X can't be 0.
|
||||
this.addAbility(new SuspendAbility(Integer.MAX_VALUE, new ManaCostsImpl<>("{3}{U}"), this, true));
|
||||
|
|
|
|||
|
|
@ -1,27 +1,18 @@
|
|||
package mage.cards.a;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.costs.CostAdjuster;
|
||||
import mage.abilities.costs.common.DiscardTargetCost;
|
||||
import mage.abilities.costs.costadjusters.DiscardXCardsCostAdjuster;
|
||||
import mage.abilities.effects.Effect;
|
||||
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.Zone;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.target.common.TargetCardInHand;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
import mage.target.targetadjustment.XTargetsCountAdjuster;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jeffwadsworth
|
||||
*/
|
||||
public final class AetherTide extends CardImpl {
|
||||
|
|
@ -29,10 +20,8 @@ public final class AetherTide extends CardImpl {
|
|||
public AetherTide(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{U}");
|
||||
|
||||
// As an additional cost to cast Aether Tide, discard X creature cards.
|
||||
Ability ability = new SimpleStaticAbility(Zone.ALL, new InfoEffect("As an additional cost to cast this spell, discard X creature cards"));
|
||||
ability.setRuleAtTheTop(true);
|
||||
this.addAbility(ability);
|
||||
// As an additional cost to cast this spell, discard X creature cards.
|
||||
DiscardXCardsCostAdjuster.addAdjusterAndMessage(this, StaticFilters.FILTER_CARD_CREATURES);
|
||||
|
||||
// Return X target creatures to their owners' hands.
|
||||
Effect effect = new ReturnToHandTargetEffect();
|
||||
|
|
@ -40,8 +29,6 @@ public final class AetherTide extends CardImpl {
|
|||
this.getSpellAbility().addEffect(effect);
|
||||
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
|
||||
this.getSpellAbility().setTargetAdjuster(new XTargetsCountAdjuster());
|
||||
this.getSpellAbility().setCostAdjuster(AetherTideCostAdjuster.instance);
|
||||
|
||||
}
|
||||
|
||||
private AetherTide(final AetherTide card) {
|
||||
|
|
@ -53,15 +40,3 @@ public final class AetherTide extends CardImpl {
|
|||
return new AetherTide(this);
|
||||
}
|
||||
}
|
||||
|
||||
enum AetherTideCostAdjuster implements CostAdjuster {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public void adjustCosts(Ability ability, Game game) {
|
||||
int xValue = CardUtil.getSourceCostsTag(game, ability, "X", 0);
|
||||
if (xValue > 0) {
|
||||
ability.addCost(new DiscardTargetCost(new TargetCardInHand(xValue, xValue, StaticFilters.FILTER_CARD_CREATURES)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
47
Mage.Sets/src/mage/cards/a/AggressiveNegotiations.java
Normal file
47
Mage.Sets/src/mage/cards/a/AggressiveNegotiations.java
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
package mage.cards.a;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.common.ExileCardYouChooseTargetOpponentEffect;
|
||||
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.counters.CounterType;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.target.TargetPlayer;
|
||||
import mage.target.common.TargetControlledCreaturePermanent;
|
||||
import mage.target.targetpointer.SecondTargetPointer;
|
||||
|
||||
/**
|
||||
* Aggressive Negotiations implementation
|
||||
* Author: @mikejcunn
|
||||
*/
|
||||
public final class AggressiveNegotiations extends CardImpl {
|
||||
|
||||
public AggressiveNegotiations(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{B}");
|
||||
|
||||
// Target opponent reveals their hand. You choose a nonland card from it. That player exiles that card.
|
||||
Effect effect1 = new ExileCardYouChooseTargetOpponentEffect(StaticFilters.FILTER_CARD_A_NON_LAND);
|
||||
this.getSpellAbility().addEffect(effect1);
|
||||
this.getSpellAbility().addTarget(new TargetPlayer());
|
||||
|
||||
// Put a +1/+1 counter on target creature you control.
|
||||
this.getSpellAbility().addEffect(new AddCountersTargetEffect(
|
||||
CounterType.P1P1.createInstance()
|
||||
).setTargetPointer(new SecondTargetPointer()));
|
||||
this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent(0, 1));
|
||||
}
|
||||
|
||||
private AggressiveNegotiations(final AggressiveNegotiations card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AggressiveNegotiations copy() {
|
||||
return new AggressiveNegotiations(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -90,7 +90,7 @@ class AgrusKosEternalSoldierTriggeredAbility extends TriggeredAbilityImpl {
|
|||
if (!event.getTargetId().equals(getSourceId())) {
|
||||
return false;
|
||||
}
|
||||
StackObject targetingObject = CardUtil.getTargetingStackObject(event, game);
|
||||
StackObject targetingObject = CardUtil.getTargetingStackObject(this.getId().toString(), event, game);
|
||||
if (targetingObject == null || targetingObject instanceof Spell) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ package mage.cards.a;
|
|||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.CostAdjuster;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.costs.mana.VariableManaCost;
|
||||
import mage.abilities.effects.ReplacementEffectImpl;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
|
|
@ -36,12 +36,8 @@ public final class AladdinsLamp extends CardImpl {
|
|||
// {X}, {T}: The next time you would draw a card this turn, instead look at the top X cards of your library, put all but one of them on the bottom of your library in a random order, then draw a card. X can't be 0.
|
||||
Ability ability = new SimpleActivatedAbility(new AladdinsLampEffect(), new ManaCostsImpl<>("{X}"));
|
||||
ability.addCost(new TapSourceCost());
|
||||
for (Object cost : ability.getManaCosts()) {
|
||||
if (cost instanceof VariableManaCost) {
|
||||
((VariableManaCost) cost).setMinX(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
ability.setCostAdjuster(AladdinsLampCostAdjuster.instance);
|
||||
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
|
|
@ -101,3 +97,17 @@ class AladdinsLampEffect extends ReplacementEffectImpl {
|
|||
return source.isControlledBy(event.getPlayerId());
|
||||
}
|
||||
}
|
||||
|
||||
enum AladdinsLampCostAdjuster implements CostAdjuster {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public void prepareX(Ability ability, Game game) {
|
||||
Player controller = game.getPlayer(ability.getControllerId());
|
||||
if (controller == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
ability.setVariableCostsMinMax(1, Math.max(1, controller.getLibrary().size()));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,8 +47,8 @@ public final class AlandraSkyDreamer extends CardImpl {
|
|||
// Whenever you draw your fifth card each turn, Alandra, Sky Dreamer and Drakes you control each get +X/+X until end of turn, where X is the number of cards in your hand.
|
||||
DrawNthCardTriggeredAbility drawNthCardTriggeredAbility = new DrawNthCardTriggeredAbility(
|
||||
new BoostSourceEffect(
|
||||
CardsInControllerHandCount.instance,
|
||||
CardsInControllerHandCount.instance,
|
||||
CardsInControllerHandCount.ANY,
|
||||
CardsInControllerHandCount.ANY,
|
||||
Duration.EndOfTurn
|
||||
).setText("{this}"),
|
||||
false,
|
||||
|
|
@ -56,8 +56,8 @@ public final class AlandraSkyDreamer extends CardImpl {
|
|||
);
|
||||
drawNthCardTriggeredAbility.addEffect(
|
||||
new BoostControlledEffect(
|
||||
CardsInControllerHandCount.instance,
|
||||
CardsInControllerHandCount.instance,
|
||||
CardsInControllerHandCount.ANY,
|
||||
CardsInControllerHandCount.ANY,
|
||||
Duration.EndOfTurn,
|
||||
filter,
|
||||
false
|
||||
|
|
|
|||
42
Mage.Sets/src/mage/cards/a/AlignedHeart.java
Normal file
42
Mage.Sets/src/mage/cards/a/AlignedHeart.java
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
package mage.cards.a;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.FlurryAbility;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.dynamicvalue.common.CountersSourceCount;
|
||||
import mage.abilities.effects.common.CreateTokenEffect;
|
||||
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.counters.CounterType;
|
||||
import mage.game.permanent.token.MonasteryMentorToken;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class AlignedHeart extends CardImpl {
|
||||
|
||||
private static final DynamicValue xValue = new CountersSourceCount(CounterType.RALLY);
|
||||
|
||||
public AlignedHeart(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}");
|
||||
|
||||
// Flurry -- Whenever you cast your second spell each turn, put a rally counter on this enchantment. Then create a 1/1 white Monk creature token with prowess for each rally counter on it.
|
||||
Ability ability = new FlurryAbility(new AddCountersSourceEffect(CounterType.RALLY.createInstance()));
|
||||
ability.addEffect(new CreateTokenEffect(new MonasteryMentorToken(), xValue)
|
||||
.setText("then create a 1/1 white Monk creature token with prowess for each rally counter on it"));
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
private AlignedHeart(final AlignedHeart card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AlignedHeart copy() {
|
||||
return new AlignedHeart(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -61,7 +61,7 @@ class AncientExcavationEffect extends OneShotEffect {
|
|||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player != null) {
|
||||
DynamicValue numCards = CardsInControllerHandCount.instance;
|
||||
DynamicValue numCards = CardsInControllerHandCount.ANY;
|
||||
int amount = numCards.calculate(game, source, this);
|
||||
int cardsDrawn = player.drawCards(amount, source, game);
|
||||
player.discard(cardsDrawn, false, false, source, game);
|
||||
|
|
|
|||
48
Mage.Sets/src/mage/cards/a/ArborAdherent.java
Normal file
48
Mage.Sets/src/mage/cards/a/ArborAdherent.java
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
package mage.cards.a;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.Mana;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.dynamicvalue.common.GreatestToughnessAmongControlledCreaturesValue;
|
||||
import mage.abilities.mana.AnyColorManaAbility;
|
||||
import mage.abilities.mana.DynamicManaAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class ArborAdherent extends CardImpl {
|
||||
|
||||
public ArborAdherent(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}");
|
||||
|
||||
this.subtype.add(SubType.DOG);
|
||||
this.subtype.add(SubType.DRUID);
|
||||
this.power = new MageInt(2);
|
||||
this.toughness = new MageInt(4);
|
||||
|
||||
// {T}: Add one mana of any color.
|
||||
this.addAbility(new AnyColorManaAbility());
|
||||
|
||||
// {T}: Add X mana of any one color, where X is the greatest toughness among other creatures you control.
|
||||
this.addAbility(new DynamicManaAbility(
|
||||
Mana.AnyMana(1), GreatestToughnessAmongControlledCreaturesValue.OTHER,
|
||||
new TapSourceCost(), "add X mana of any one color, where X is the " +
|
||||
"greatest toughness among other creatures you control", true
|
||||
).addHint(GreatestToughnessAmongControlledCreaturesValue.OTHER.getHint()));
|
||||
}
|
||||
|
||||
private ArborAdherent(final ArborAdherent card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArborAdherent copy() {
|
||||
return new ArborAdherent(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
package mage.cards.a;
|
||||
|
||||
import java.util.UUID;
|
||||
|
|
@ -26,7 +25,7 @@ public final class Archivist extends CardImpl {
|
|||
this.power = new MageInt(1);
|
||||
this.toughness = new MageInt(1);
|
||||
|
||||
//{T}: Draw a card.
|
||||
// {T}: Draw a card.
|
||||
this.addAbility(new SimpleActivatedAbility(new DrawCardSourceControllerEffect(1), new TapSourceCost()));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ enum ArmMountedAnchorAdjuster implements CostAdjuster {
|
|||
instance;
|
||||
|
||||
@Override
|
||||
public void adjustCosts(Ability ability, Game game) {
|
||||
public void reduceCost(Ability ability, Game game) {
|
||||
// checking state
|
||||
if (HeckbentCondition.instance.apply(game, ability)) {
|
||||
CardUtil.reduceCost(ability, 2);
|
||||
|
|
|
|||
|
|
@ -1,11 +1,8 @@
|
|||
|
||||
package mage.cards.a;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldAbility;
|
||||
import mage.abilities.common.AsEntersBattlefieldAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.condition.common.ModeChoiceSourceCondition;
|
||||
import mage.abilities.effects.common.ChooseModeEffect;
|
||||
import mage.abilities.effects.common.PermanentsEnterBattlefieldTappedEffect;
|
||||
import mage.abilities.effects.common.continuous.GainAbilityAllEffect;
|
||||
|
|
@ -14,31 +11,44 @@ import mage.cards.CardImpl;
|
|||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Zone;
|
||||
import mage.constants.ModeChoice;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.predicate.ObjectSourcePlayer;
|
||||
import mage.filter.predicate.ObjectSourcePlayerPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.EntersTheBattlefieldEvent;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Eirkei
|
||||
*/
|
||||
public final class AshlingsPrerogative extends CardImpl {
|
||||
|
||||
private static final FilterPermanent filterMatch
|
||||
= new FilterCreaturePermanent("each creature with mana value of the chosen quality");
|
||||
private static final FilterPermanent filterNotMatch
|
||||
= new FilterCreaturePermanent("each creature without mana value of the chosen quality");
|
||||
|
||||
static {
|
||||
filterMatch.add(AshlingsPrerogativePredicate.WITH);
|
||||
filterNotMatch.add(AshlingsPrerogativePredicate.WITHOUT);
|
||||
}
|
||||
|
||||
public AshlingsPrerogative(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{R}");
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{R}");
|
||||
|
||||
// As Ashling's Prerogative enters the battlefield, choose odd or even.
|
||||
this.addAbility(new EntersBattlefieldAbility(new ChooseModeEffect("Odd or even?", "Odd", "Even"), null, "As {this} enters, choose odd or even. <i>(Zero is even.)</i>", ""));
|
||||
this.addAbility(new AsEntersBattlefieldAbility(new ChooseModeEffect(ModeChoice.ODD, ModeChoice.EVEN)));
|
||||
|
||||
// Each creature with converted mana cost of the chosen value has haste.
|
||||
this.addAbility(new SimpleStaticAbility(new AshlingsPrerogativeCorrectOddityEffect()));
|
||||
this.addAbility(new SimpleStaticAbility(new GainAbilityAllEffect(
|
||||
HasteAbility.getInstance(), Duration.WhileOnBattlefield, filterMatch
|
||||
)));
|
||||
|
||||
// Each creature without converted mana cost of the chosen value enters the battlefield tapped.
|
||||
this.addAbility(new SimpleStaticAbility(new AshlingsPrerogativeIncorrectOddityEffect()));
|
||||
|
||||
this.addAbility(new SimpleStaticAbility(new PermanentsEnterBattlefieldTappedEffect(filterNotMatch)));
|
||||
}
|
||||
|
||||
private AshlingsPrerogative(final AshlingsPrerogative card) {
|
||||
|
|
@ -51,67 +61,23 @@ public final class AshlingsPrerogative extends CardImpl {
|
|||
}
|
||||
}
|
||||
|
||||
class AshlingsPrerogativeIncorrectOddityEffect extends PermanentsEnterBattlefieldTappedEffect {
|
||||
enum AshlingsPrerogativePredicate implements ObjectSourcePlayerPredicate<Permanent> {
|
||||
WITH(true),
|
||||
WITHOUT(false);
|
||||
private final boolean match;
|
||||
|
||||
private static final FilterCreaturePermanent creaturefilter = new FilterCreaturePermanent("Each creature without mana value of the chosen quality");
|
||||
private static final ModeChoiceSourceCondition oddCondition = new ModeChoiceSourceCondition("Odd");
|
||||
|
||||
public AshlingsPrerogativeIncorrectOddityEffect() {
|
||||
super(creaturefilter);
|
||||
staticText = "Each creature without mana value of the chosen quality enters the battlefield tapped.";
|
||||
}
|
||||
|
||||
private AshlingsPrerogativeIncorrectOddityEffect(final AshlingsPrerogativeIncorrectOddityEffect effect) {
|
||||
super(effect);
|
||||
AshlingsPrerogativePredicate(boolean match) {
|
||||
this.match = match;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
int incorrectModResult;
|
||||
|
||||
if (oddCondition.apply(game, source)) {
|
||||
incorrectModResult = 0;
|
||||
public boolean apply(ObjectSourcePlayer<Permanent> input, Game game) {
|
||||
if (ModeChoice.ODD.checkMode(game, input.getSource())) {
|
||||
return (input.getObject().getManaValue() % 2 == 1) == match;
|
||||
} else if (ModeChoice.EVEN.checkMode(game, input.getSource())) {
|
||||
return (input.getObject().getManaValue() % 2 == 0) == match;
|
||||
} else {
|
||||
incorrectModResult = 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
Permanent permanent = ((EntersTheBattlefieldEvent) event).getTarget();
|
||||
|
||||
return permanent != null && creaturefilter.match(permanent, game) && permanent.getManaValue() % 2 == incorrectModResult;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AshlingsPrerogativeIncorrectOddityEffect copy() {
|
||||
return new AshlingsPrerogativeIncorrectOddityEffect(this);
|
||||
}
|
||||
}
|
||||
|
||||
class AshlingsPrerogativeCorrectOddityEffect extends GainAbilityAllEffect {
|
||||
|
||||
private static final FilterCreaturePermanent creaturefilter = new FilterCreaturePermanent("Each creature with mana value of the chosen quality");
|
||||
private static final ModeChoiceSourceCondition oddCondition = new ModeChoiceSourceCondition("Odd");
|
||||
|
||||
public AshlingsPrerogativeCorrectOddityEffect() {
|
||||
super(HasteAbility.getInstance(), Duration.WhileOnBattlefield, creaturefilter);
|
||||
staticText = "Each creature with mana value of the chosen quality has haste.";
|
||||
}
|
||||
private AshlingsPrerogativeCorrectOddityEffect(final AshlingsPrerogativeCorrectOddityEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean selectedByRuntimeData(Permanent permanent, Ability source, Game game) {
|
||||
int correctModResult;
|
||||
if (oddCondition.apply(game, source)) {
|
||||
correctModResult = 1;
|
||||
} else {
|
||||
correctModResult = 0;
|
||||
}
|
||||
return permanent != null && creaturefilter.match(permanent, game) && permanent.getManaValue() % 2 == correctModResult;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AshlingsPrerogativeCorrectOddityEffect copy() {
|
||||
return new AshlingsPrerogativeCorrectOddityEffect(this);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ public final class BaldinCenturyHerdmaster extends CardImpl {
|
|||
|
||||
// Whenever Baldin, Century Herdmaster attacks, up to one hundred target creatures each get +0/+X until end of turn, where X is the number of cards in your hand.
|
||||
Ability ability = new AttacksTriggeredAbility(new BoostTargetEffect(
|
||||
StaticValue.get(0), CardsInControllerHandCount.instance, Duration.EndOfTurn
|
||||
StaticValue.get(0), CardsInControllerHandCount.ANY, Duration.EndOfTurn
|
||||
).setText("up to one hundred target creatures each get +0/+X until end of turn, where X is the number of cards in your hand"));
|
||||
ability.addTarget(new TargetCreaturePermanent(0, 100));
|
||||
this.addAbility(ability);
|
||||
|
|
|
|||
|
|
@ -144,10 +144,9 @@ class BanditsTalentDiscardEffect extends OneShotEffect {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
enum BanditsTalentValue implements DynamicValue {
|
||||
instance;
|
||||
private static final Hint hint = new ValueHint("opponents who have one or fewer cards in hand", instance);
|
||||
private static final Hint hint = new ValueHint("Opponents who have one or fewer cards in hand", instance);
|
||||
|
||||
public static Hint getHint() {
|
||||
return hint;
|
||||
|
|
|
|||
|
|
@ -1,25 +1,28 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.CostAdjuster;
|
||||
import mage.abilities.costs.EarlyTargetCost;
|
||||
import mage.abilities.costs.VariableCostType;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.costs.mana.GenericManaCost;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.costs.mana.VariableManaCost;
|
||||
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
||||
import mage.abilities.effects.common.InfoEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.Target;
|
||||
import mage.target.common.TargetOpponent;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author awjackson
|
||||
* @author awjackson, JayDi85
|
||||
*/
|
||||
public final class BargainingTable extends CardImpl {
|
||||
|
||||
|
|
@ -27,13 +30,10 @@ public final class BargainingTable extends CardImpl {
|
|||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{5}");
|
||||
|
||||
// {X}, {T}: Draw a card. X is the number of cards in an opponent's hand.
|
||||
Ability ability = new SimpleActivatedAbility(new DrawCardSourceControllerEffect(1), new ManaCostsImpl<>("{X}"));
|
||||
Ability ability = new SimpleActivatedAbility(new DrawCardSourceControllerEffect(1), new BargainingTableXCost());
|
||||
ability.addCost(new TapSourceCost());
|
||||
ability.addEffect(new InfoEffect("X is the number of cards in an opponent's hand"));
|
||||
// You choose an opponent on announcement. This is not targeted, but a choice is still made.
|
||||
// This choice is made before determining the value for X that is used in the cost. (2004-10-04)
|
||||
ability.addTarget(new TargetOpponent(true));
|
||||
ability.setCostAdjuster(BargainingTableAdjuster.instance);
|
||||
ability.setCostAdjuster(BargainingTableCostAdjuster.instance);
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
|
|
@ -47,26 +47,70 @@ public final class BargainingTable extends CardImpl {
|
|||
}
|
||||
}
|
||||
|
||||
enum BargainingTableAdjuster implements CostAdjuster {
|
||||
class BargainingTableXCost extends VariableManaCost implements EarlyTargetCost {
|
||||
|
||||
// You choose an opponent on announcement. This is not targeted, but a choice is still made.
|
||||
// This choice is made before determining the value for X that is used in the cost.
|
||||
// (2004-10-04)
|
||||
|
||||
public BargainingTableXCost() {
|
||||
super(VariableCostType.NORMAL, 1);
|
||||
}
|
||||
|
||||
public BargainingTableXCost(final BargainingTableXCost cost) {
|
||||
super(cost);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void chooseTarget(Game game, Ability source, Player controller) {
|
||||
Target targetOpponent = new TargetOpponent(true);
|
||||
controller.choose(Outcome.Benefit, targetOpponent, source, game);
|
||||
addTarget(targetOpponent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BargainingTableXCost copy() {
|
||||
return new BargainingTableXCost(this);
|
||||
}
|
||||
}
|
||||
|
||||
enum BargainingTableCostAdjuster implements CostAdjuster {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public void adjustCosts(Ability ability, Game game) {
|
||||
int handSize = Integer.MAX_VALUE;
|
||||
if (game.inCheckPlayableState()) {
|
||||
for (UUID playerId : CardUtil.getAllPossibleTargets(ability, game)) {
|
||||
Player player = game.getPlayer(playerId);
|
||||
if (player != null) {
|
||||
handSize = Math.min(handSize, player.getHand().size());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Player player = game.getPlayer(ability.getFirstTarget());
|
||||
if (player != null) {
|
||||
handSize = player.getHand().size();
|
||||
}
|
||||
public void prepareX(Ability ability, Game game) {
|
||||
// make sure early target used
|
||||
BargainingTableXCost cost = ability.getManaCostsToPay().getVariableCosts().stream()
|
||||
.filter(c -> c instanceof BargainingTableXCost)
|
||||
.map(c -> (BargainingTableXCost) c)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (cost == null) {
|
||||
throw new IllegalArgumentException("Wrong code usage: cost item lost");
|
||||
}
|
||||
|
||||
if (game.inCheckPlayableState()) {
|
||||
// possible X
|
||||
int minHandSize = game.getOpponents(ability.getControllerId(), true).stream()
|
||||
.map(game::getPlayer)
|
||||
.filter(Objects::nonNull)
|
||||
.mapToInt(p -> p.getHand().size())
|
||||
.min()
|
||||
.orElse(0);
|
||||
int maxHandSize = game.getOpponents(ability.getControllerId(), true).stream()
|
||||
.map(game::getPlayer)
|
||||
.filter(Objects::nonNull)
|
||||
.mapToInt(p -> p.getHand().size())
|
||||
.max()
|
||||
.orElse(Integer.MAX_VALUE);
|
||||
ability.setVariableCostsMinMax(minHandSize, maxHandSize);
|
||||
} else {
|
||||
// real X
|
||||
Player opponent = game.getPlayer(cost.getTargets().getFirstTarget());
|
||||
if (opponent == null) {
|
||||
throw new IllegalStateException("Wrong code usage: cost target lost");
|
||||
}
|
||||
ability.setVariableCostsValue(opponent.getHand().size());
|
||||
}
|
||||
ability.clearManaCostsToPay();
|
||||
ability.addManaCostsToPay(new GenericManaCost(handSize));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,17 +1,17 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import mage.abilities.common.EntersBattlefieldAbility;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.abilities.common.AsEntersBattlefieldAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.condition.common.CreatureDiedControlledCondition;
|
||||
import mage.abilities.condition.common.ModeChoiceSourceCondition;
|
||||
import mage.abilities.decorator.ConditionalTriggeredAbility;
|
||||
import mage.abilities.effects.common.ChooseModeEffect;
|
||||
import mage.abilities.effects.common.SacrificeOpponentsEffect;
|
||||
import mage.abilities.effects.common.continuous.GainAnchorWordAbilitySourceEffect;
|
||||
import mage.abilities.effects.common.counter.AddCountersAllEffect;
|
||||
import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.ModeChoice;
|
||||
import mage.counters.CounterType;
|
||||
import mage.filter.StaticFilters;
|
||||
|
||||
|
|
@ -22,35 +22,25 @@ import java.util.UUID;
|
|||
*/
|
||||
public final class BarrensteppeSiege extends CardImpl {
|
||||
|
||||
private static final Condition condition1 = new ModeChoiceSourceCondition("Abzan");
|
||||
private static final String rule1 = "&bull Abzan — At the beginning of your end step, " +
|
||||
"put a +1/+1 counter on each creature you control.";
|
||||
private static final Condition condition2 = new ModeChoiceSourceCondition("Mardu");
|
||||
private static final String rule2 = "&bull Mardu — At the beginning of your end step, " +
|
||||
"if a creature died under your control this turn, each opponent sacrifices a creature of their choice.";
|
||||
|
||||
public BarrensteppeSiege(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}{B}");
|
||||
|
||||
// As this enchantment enters, choose Abzan or Mardu.
|
||||
this.addAbility(new EntersBattlefieldAbility(
|
||||
new ChooseModeEffect("Abzan or Mardu?", "Abzan", "Mardu"),
|
||||
null, "As {this} enters, choose Abzan or Mardu.", ""
|
||||
));
|
||||
this.addAbility(new AsEntersBattlefieldAbility(new ChooseModeEffect(ModeChoice.ABZAN, ModeChoice.MARDU)));
|
||||
|
||||
// * Abzan -- At the beginning of your end step, put a +1/+1 counter on each creature you control.
|
||||
this.addAbility(new ConditionalTriggeredAbility(
|
||||
this.addAbility(new SimpleStaticAbility(new GainAnchorWordAbilitySourceEffect(
|
||||
new BeginningOfEndStepTriggeredAbility(new AddCountersAllEffect(
|
||||
CounterType.P1P1.createInstance(), StaticFilters.FILTER_CONTROLLED_CREATURE
|
||||
)), condition1, rule1
|
||||
));
|
||||
)), ModeChoice.ABZAN
|
||||
)));
|
||||
|
||||
// * Mardu -- At the beginning of your end step, if a creature died under your control this turn, each opponent sacrifices a creature of their choice.
|
||||
this.addAbility(new ConditionalTriggeredAbility(
|
||||
this.addAbility(new SimpleStaticAbility(new GainAnchorWordAbilitySourceEffect(
|
||||
new BeginningOfEndStepTriggeredAbility(
|
||||
new SacrificeOpponentsEffect(StaticFilters.FILTER_PERMANENT_CREATURE)
|
||||
).withInterveningIf(CreatureDiedControlledCondition.instance), condition2, rule2
|
||||
));
|
||||
).withInterveningIf(CreatureDiedControlledCondition.instance), ModeChoice.MARDU
|
||||
)));
|
||||
}
|
||||
|
||||
private BarrensteppeSiege(final BarrensteppeSiege card) {
|
||||
|
|
|
|||
|
|
@ -19,10 +19,7 @@ import mage.abilities.hint.ValueHint;
|
|||
import mage.abilities.keyword.TrampleAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.constants.*;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.common.FilterControlledCreaturePermanent;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
|
|
@ -116,7 +113,7 @@ enum BaruWurmspeakerAdjuster implements CostAdjuster {
|
|||
instance;
|
||||
|
||||
@Override
|
||||
public void adjustCosts(Ability ability, Game game) {
|
||||
public void reduceCost(Ability ability, Game game) {
|
||||
int value = BaruWurmspeakerValue.instance.calculate(game, ability, null);
|
||||
if (value > 0) {
|
||||
CardUtil.reduceCost(ability, value);
|
||||
|
|
|
|||
|
|
@ -1,33 +1,35 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.AsEntersBattlefieldAbility;
|
||||
import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility;
|
||||
import mage.abilities.common.DiesCreatureTriggeredAbility;
|
||||
import mage.abilities.condition.common.ModeChoiceSourceCondition;
|
||||
import mage.abilities.decorator.ConditionalTriggeredAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.common.ChooseModeEffect;
|
||||
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldWithCounterTargetEffect;
|
||||
import mage.abilities.effects.common.continuous.GainAnchorWordAbilitySourceEffect;
|
||||
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
|
||||
import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.ComparisonType;
|
||||
import mage.constants.ModeChoice;
|
||||
import mage.counters.CounterType;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.filter.common.FilterCreatureCard;
|
||||
import mage.filter.predicate.mageobject.ManaValuePredicate;
|
||||
import mage.target.common.TargetCardInYourGraveyard;
|
||||
import mage.target.common.TargetControlledCreaturePermanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author Cguy7777
|
||||
*/
|
||||
public final class BattleOfHooverDam extends CardImpl {
|
||||
|
||||
private static final FilterCreatureCard filter = new FilterCreatureCard();
|
||||
private static final FilterCard filter = new FilterCreatureCard();
|
||||
|
||||
static {
|
||||
filter.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, 4));
|
||||
|
|
@ -37,32 +39,23 @@ public final class BattleOfHooverDam extends CardImpl {
|
|||
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{W}");
|
||||
|
||||
// As Battle of Hoover Dam enters the battlefield, choose NCR or Legion.
|
||||
this.addAbility(new AsEntersBattlefieldAbility(
|
||||
new ChooseModeEffect("NCR or Legion?", "NCR", "Legion")));
|
||||
this.addAbility(new AsEntersBattlefieldAbility(new ChooseModeEffect(ModeChoice.NCR, ModeChoice.LEGION)));
|
||||
|
||||
// * NCR -- At the beginning of your end step, return target creature card with mana value 3 or less
|
||||
// from your graveyard to the battlefield with a finality counter on it.
|
||||
Ability ncrAbility = new ConditionalTriggeredAbility(
|
||||
new BeginningOfEndStepTriggeredAbility(
|
||||
new ReturnFromGraveyardToBattlefieldWithCounterTargetEffect(CounterType.FINALITY.createInstance())
|
||||
),
|
||||
new ModeChoiceSourceCondition("NCR"),
|
||||
"&bull NCR — At the beginning of your end step, return target creature card with " +
|
||||
"mana value 3 or less from your graveyard to the battlefield with a finality counter on it.");
|
||||
ncrAbility.addTarget(new TargetCardInYourGraveyard(filter));
|
||||
this.addAbility(ncrAbility);
|
||||
Ability ability = new BeginningOfEndStepTriggeredAbility(
|
||||
new ReturnFromGraveyardToBattlefieldWithCounterTargetEffect(CounterType.FINALITY.createInstance())
|
||||
);
|
||||
ability.addTarget(new TargetCardInYourGraveyard(filter));
|
||||
this.addAbility(new SimpleStaticAbility(new GainAnchorWordAbilitySourceEffect(ability, ModeChoice.NCR)));
|
||||
|
||||
// * Legion -- Whenever a creature you control dies, put two +1/+1 counters on target creature you control.
|
||||
Ability legionAbility = new ConditionalTriggeredAbility(
|
||||
new DiesCreatureTriggeredAbility(
|
||||
new AddCountersTargetEffect(CounterType.P1P1.createInstance(2)),
|
||||
false,
|
||||
StaticFilters.FILTER_CONTROLLED_A_CREATURE),
|
||||
new ModeChoiceSourceCondition("Legion"),
|
||||
"&bull Legion — Whenever a creature you control dies, " +
|
||||
"put two +1/+1 counters on target creature you control.");
|
||||
legionAbility.addTarget(new TargetControlledCreaturePermanent());
|
||||
this.addAbility(legionAbility);
|
||||
ability = new DiesCreatureTriggeredAbility(
|
||||
new AddCountersTargetEffect(CounterType.P1P1.createInstance(2)),
|
||||
false, StaticFilters.FILTER_CONTROLLED_A_CREATURE
|
||||
);
|
||||
ability.addTarget(new TargetControlledCreaturePermanent());
|
||||
this.addAbility(new SimpleStaticAbility(new GainAnchorWordAbilitySourceEffect(ability, ModeChoice.LEGION)));
|
||||
}
|
||||
|
||||
private BattleOfHooverDam(final BattleOfHooverDam card) {
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ enum BattlefieldButcherAdjuster implements CostAdjuster {
|
|||
private static final Hint hint = new ValueHint("Creature cards in your graveyard", xValue);
|
||||
|
||||
@Override
|
||||
public void adjustCosts(Ability ability, Game game) {
|
||||
public void reduceCost(Ability ability, Game game) {
|
||||
CardUtil.reduceCost(ability, xValue.calculate(game, ability, null));
|
||||
}
|
||||
|
||||
|
|
|
|||
55
Mage.Sets/src/mage/cards/b/BecomeTheAvalanche.java
Normal file
55
Mage.Sets/src/mage/cards/b/BecomeTheAvalanche.java
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.dynamicvalue.common.CardsInControllerHandCount;
|
||||
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
|
||||
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
||||
import mage.abilities.effects.common.continuous.BoostControlledEffect;
|
||||
import mage.abilities.hint.Hint;
|
||||
import mage.abilities.hint.ValueHint;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.ComparisonType;
|
||||
import mage.constants.Duration;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.common.FilterControlledCreaturePermanent;
|
||||
import mage.filter.predicate.mageobject.PowerPredicate;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class BecomeTheAvalanche extends CardImpl {
|
||||
|
||||
private static final FilterPermanent filter
|
||||
= new FilterControlledCreaturePermanent("creature you control with power 4 or greater");
|
||||
|
||||
static {
|
||||
filter.add(new PowerPredicate(ComparisonType.MORE_THAN, 3));
|
||||
}
|
||||
|
||||
private static final DynamicValue xValue = new PermanentsOnBattlefieldCount(filter);
|
||||
private static final Hint hint = new ValueHint("Creatures you control with power 4 or greater", xValue);
|
||||
|
||||
public BecomeTheAvalanche(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{G}{G}");
|
||||
|
||||
// Draw a card for each creature you control with power 4 or greater. Then creatures you control get +X/+X until end of turn, where X is the number of cards in your hand.
|
||||
this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(xValue));
|
||||
this.getSpellAbility().addEffect(new BoostControlledEffect(
|
||||
CardsInControllerHandCount.ANY, CardsInControllerHandCount.ANY, Duration.EndOfTurn
|
||||
));
|
||||
this.getSpellAbility().addHint(hint);
|
||||
}
|
||||
|
||||
private BecomeTheAvalanche(final BecomeTheAvalanche card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BecomeTheAvalanche copy() {
|
||||
return new BecomeTheAvalanche(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -3,20 +3,21 @@ package mage.cards.b;
|
|||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.costs.CostAdjuster;
|
||||
import mage.abilities.costs.mana.GenericManaCost;
|
||||
import mage.abilities.effects.common.continuous.SetBasePowerToughnessEnchantedEffect;
|
||||
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.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.common.TargetControlledCreaturePermanent;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.costs.mana.GenericManaCost;
|
||||
import mage.constants.Outcome;
|
||||
import mage.target.common.TargetControlledCreaturePermanent;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
|
|
@ -35,7 +36,7 @@ public final class BeltOfGiantStrength extends CardImpl {
|
|||
// Equip {10}. This ability costs {X} less to activate where X is the power of the creature it targets.
|
||||
EquipAbility ability = new EquipAbility(Outcome.BoostCreature, new GenericManaCost(10), new TargetControlledCreaturePermanent(), false);
|
||||
ability.setCostReduceText("This ability costs {X} less to activate, where X is the power of the creature it targets.");
|
||||
ability.setCostAdjuster(BeltOfGiantStrengthAdjuster.instance);
|
||||
ability.setCostAdjuster(BeltOfGiantStrengthCostAdjuster.instance);
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
|
|
@ -49,33 +50,23 @@ public final class BeltOfGiantStrength extends CardImpl {
|
|||
}
|
||||
}
|
||||
|
||||
enum BeltOfGiantStrengthAdjuster implements CostAdjuster {
|
||||
enum BeltOfGiantStrengthCostAdjuster implements CostAdjuster {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public void adjustCosts(Ability ability, Game game) {
|
||||
public void reduceCost(Ability ability, Game game) {
|
||||
int power;
|
||||
if (game.inCheckPlayableState()) {
|
||||
int maxPower = 0;
|
||||
for (UUID permId : CardUtil.getAllPossibleTargets(ability, game)) {
|
||||
Permanent permanent = game.getPermanent(permId);
|
||||
if (permanent != null) {
|
||||
int power = permanent.getPower().getValue();
|
||||
if (power > maxPower) {
|
||||
maxPower = power;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (maxPower > 0) {
|
||||
CardUtil.reduceCost(ability, maxPower);
|
||||
}
|
||||
power = CardUtil.getAllPossibleTargets(ability, game).stream()
|
||||
.map(game::getPermanent)
|
||||
.filter(Objects::nonNull)
|
||||
.mapToInt(p -> p.getPower().getValue())
|
||||
.max().orElse(0);
|
||||
} else {
|
||||
Permanent permanent = game.getPermanent(ability.getFirstTarget());
|
||||
if (permanent != null) {
|
||||
int power = permanent.getPower().getValue();
|
||||
if (power > 0) {
|
||||
CardUtil.reduceCost(ability, power);
|
||||
}
|
||||
}
|
||||
power = Optional.ofNullable(game.getPermanent(ability.getFirstTarget()))
|
||||
.map(p -> p.getPower().getValue())
|
||||
.orElse(0);
|
||||
}
|
||||
CardUtil.reduceCost(ability, power);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
165
Mage.Sets/src/mage/cards/b/BetorKinToAll.java
Normal file
165
Mage.Sets/src/mage/cards/b/BetorKinToAll.java
Normal file
|
|
@ -0,0 +1,165 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
||||
import mage.abilities.hint.Hint;
|
||||
import mage.abilities.hint.ValueHint;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author androosss
|
||||
*/
|
||||
public final class BetorKinToAll extends CardImpl {
|
||||
|
||||
private static final Hint hint = new ValueHint(
|
||||
"Total toughness of creatures you control", ControlledCreaturesToughnessValue.instance);
|
||||
|
||||
public BetorKinToAll(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[] { CardType.CREATURE }, "{2}{W}{B}{G}");
|
||||
|
||||
this.supertype.add(SuperType.LEGENDARY);
|
||||
this.subtype.add(SubType.SPIRIT);
|
||||
this.subtype.add(SubType.DRAGON);
|
||||
this.power = new MageInt(5);
|
||||
this.toughness = new MageInt(7);
|
||||
|
||||
// Flying
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
|
||||
// At the beginning of your end step, if creatures you control have total
|
||||
// toughness 10 or greater, draw a card. Then if creatures you control have
|
||||
// total toughness 20 or greater, untap each creature you control. Then if
|
||||
// creatures you control have total toughness 40 or greater, each opponent loses
|
||||
// half their life, rounded up.
|
||||
Ability betorAbility = new BeginningOfEndStepTriggeredAbility(new DrawCardSourceControllerEffect(1))
|
||||
.withInterveningIf(BetorKinToAllCondition.instance).addHint(hint);
|
||||
betorAbility.addEffect(new BetorKinToAllEffect());
|
||||
this.addAbility(betorAbility);
|
||||
}
|
||||
|
||||
private BetorKinToAll(final BetorKinToAll card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BetorKinToAll copy() {
|
||||
return new BetorKinToAll(this);
|
||||
}
|
||||
}
|
||||
|
||||
enum BetorKinToAllCondition implements Condition {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return ControlledCreaturesToughnessValue.instance.calculate(game, source, null) >= 10;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class BetorKinToAllEffect extends OneShotEffect {
|
||||
|
||||
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent();
|
||||
|
||||
BetorKinToAllEffect() {
|
||||
super(Outcome.Benefit);
|
||||
this.staticText = "Then if creatures you control have total toughness 20 or greater, untap each creature you control. Then if creatures you control have total toughness 40 or greater, each opponent loses half their life, rounded up.";
|
||||
}
|
||||
|
||||
private BetorKinToAllEffect(final BetorKinToAllEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BetorKinToAllEffect copy() {
|
||||
return new BetorKinToAllEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int sumToughness = ControlledCreaturesToughnessValue.instance.calculate(game, source, null);
|
||||
|
||||
if (sumToughness < 20) {
|
||||
return true;
|
||||
}
|
||||
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, source.getControllerId(),
|
||||
game)) {
|
||||
permanent.untap(game);
|
||||
}
|
||||
|
||||
if (sumToughness < 40) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (UUID playerId : game.getOpponents(controller.getId())) {
|
||||
Player opponent = game.getPlayer(playerId);
|
||||
if (opponent == null) {
|
||||
continue;
|
||||
}
|
||||
int amount = (int) Math.ceil(opponent.getLife() / 2f);
|
||||
if (amount > 0) {
|
||||
opponent.loseLife(amount, game, source, false);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
enum ControlledCreaturesToughnessValue implements DynamicValue {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public int calculate(Game game, Ability sourceAbility, Effect effect) {
|
||||
return game
|
||||
.getBattlefield()
|
||||
.getActivePermanents(
|
||||
StaticFilters.FILTER_CONTROLLED_CREATURE,
|
||||
sourceAbility.getControllerId(), sourceAbility, game)
|
||||
.stream()
|
||||
.map(MageObject::getToughness)
|
||||
.mapToInt(MageInt::getValue)
|
||||
.sum();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ControlledCreaturesToughnessValue copy() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return "total toughness of creatures you control";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "X";
|
||||
}
|
||||
}
|
||||
|
|
@ -14,7 +14,6 @@ import mage.cards.CardImpl;
|
|||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
|
@ -42,8 +41,10 @@ public final class BighornerRancher extends CardImpl {
|
|||
|
||||
// Sacrifice Bighorner Rancher: You gain life equal to the greatest toughness among other creatures you control.
|
||||
this.addAbility(new SimpleActivatedAbility(
|
||||
new GainLifeEffect(GreatestToughnessAmongControlledCreaturesValue.instance).setText("You gain life equal to the greatest toughness among other creatures you control."),
|
||||
new SacrificeSourceCost()));
|
||||
new GainLifeEffect(GreatestToughnessAmongControlledCreaturesValue.OTHER)
|
||||
.setText("You gain life equal to the greatest toughness among other creatures you control."),
|
||||
new SacrificeSourceCost()
|
||||
).addHint(GreatestToughnessAmongControlledCreaturesValue.OTHER.getHint()));
|
||||
}
|
||||
|
||||
private BighornerRancher(final BighornerRancher card) {
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ enum BiteDownOnCrimeAdjuster implements CostAdjuster {
|
|||
private static final OptionalAdditionalCost collectEvidenceCost = CollectEvidenceAbility.makeCost(6);
|
||||
|
||||
@Override
|
||||
public void adjustCosts(Ability ability, Game game) {
|
||||
public void reduceCost(Ability ability, Game game) {
|
||||
if (CollectedEvidenceCondition.instance.apply(game, ability)
|
||||
|| (game.inCheckPlayableState() && collectEvidenceCost.canPay(ability, null, ability.getControllerId(), game))) {
|
||||
CardUtil.reduceCost(ability, 2);
|
||||
|
|
|
|||
68
Mage.Sets/src/mage/cards/b/BloomvineRegent.java
Normal file
68
Mage.Sets/src/mage/cards/b/BloomvineRegent.java
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.common.EntersBattlefieldThisOrAnotherTriggeredAbility;
|
||||
import mage.abilities.effects.common.GainLifeEffect;
|
||||
import mage.abilities.effects.common.search.SearchLibraryPutOntoBattlefieldTappedRestInHandEffect;
|
||||
import mage.cards.OmenCard;
|
||||
import mage.constants.SubType;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.common.FilterBasicLandCard;
|
||||
import mage.filter.common.FilterControlledCreaturePermanent;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.target.Target;
|
||||
import mage.target.common.TargetCardInLibrary;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Jmlundeen
|
||||
*/
|
||||
public final class BloomvineRegent extends OmenCard {
|
||||
|
||||
private static final FilterCard filter = new FilterCard("basic Forest cards");
|
||||
|
||||
static {
|
||||
filter.add(SubType.FOREST.getPredicate());
|
||||
filter.add(SuperType.BASIC.getPredicate());
|
||||
}
|
||||
|
||||
public BloomvineRegent(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, new CardType[]{CardType.SORCERY}, "{3}{G}{G}", "Claim Territory", "{2}{G}");
|
||||
|
||||
this.subtype.add(SubType.DRAGON);
|
||||
this.power = new MageInt(4);
|
||||
this.toughness = new MageInt(5);
|
||||
|
||||
// Flying
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
|
||||
// Whenever this creature or another Dragon you control enters, you gain 3 life.
|
||||
this.addAbility(new EntersBattlefieldThisOrAnotherTriggeredAbility(
|
||||
new GainLifeEffect(3),
|
||||
new FilterCreaturePermanent(SubType.DRAGON, "Dragon"),
|
||||
false,
|
||||
true
|
||||
));
|
||||
|
||||
// Claim Territory
|
||||
// Search your library for up to two basic Forest cards, reveal them, put one onto the battlefield tapped and the other into your hand, then shuffle. (Also shuffle this card.)
|
||||
TargetCardInLibrary target = new TargetCardInLibrary(0, 2, filter);
|
||||
this.getSpellCard().getSpellAbility().addEffect(new SearchLibraryPutOntoBattlefieldTappedRestInHandEffect(target, 1));
|
||||
this.finalizeOmen();
|
||||
}
|
||||
|
||||
private BloomvineRegent(final BloomvineRegent card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BloomvineRegent copy() {
|
||||
return new BloomvineRegent(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -33,7 +33,7 @@ public final class BodyOfKnowledge extends CardImpl {
|
|||
this.addAbility(new SimpleStaticAbility(
|
||||
Zone.ALL,
|
||||
new SetBasePowerToughnessSourceEffect(
|
||||
CardsInControllerHandCount.instance
|
||||
CardsInControllerHandCount.ANY
|
||||
)
|
||||
));
|
||||
|
||||
|
|
|
|||
63
Mage.Sets/src/mage/cards/b/BoneDevourer.java
Normal file
63
Mage.Sets/src/mage/cards/b/BoneDevourer.java
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.DiesSourceTriggeredAbility;
|
||||
import mage.abilities.common.EntersBattlefieldAbility;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.dynamicvalue.common.CountersSourceCount;
|
||||
import mage.abilities.dynamicvalue.common.CreaturesDiedThisTurnCount;
|
||||
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
||||
import mage.abilities.effects.common.LoseLifeSourceControllerEffect;
|
||||
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
||||
import mage.abilities.hint.common.CreaturesDiedThisTurnHint;
|
||||
import mage.abilities.keyword.FlashAbility;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.counters.CounterType;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class BoneDevourer extends CardImpl {
|
||||
|
||||
private static final DynamicValue xValue = new CountersSourceCount(null);
|
||||
|
||||
public BoneDevourer(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}");
|
||||
|
||||
this.subtype.add(SubType.DRAGON);
|
||||
this.power = new MageInt(2);
|
||||
this.toughness = new MageInt(2);
|
||||
|
||||
// Flash
|
||||
this.addAbility(FlashAbility.getInstance());
|
||||
|
||||
// Flying
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
|
||||
// This creature enters with a number of +1/+1 counters on it equal to the number of creatures that died this turn.
|
||||
this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(
|
||||
CounterType.P1P1.createInstance(), CreaturesDiedThisTurnCount.instance, false
|
||||
), "with a number of +1/+1 counters on it equal to the number of creatures that died this turn").addHint(CreaturesDiedThisTurnHint.instance));
|
||||
|
||||
// When this creature dies, you draw X cards and you lose X life, where X is the number of +1/+1 counters on it.
|
||||
Ability ability = new DiesSourceTriggeredAbility(new DrawCardSourceControllerEffect(xValue).setText("you draw X cards"));
|
||||
ability.addEffect(new LoseLifeSourceControllerEffect(xValue));
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
private BoneDevourer(final BoneDevourer card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BoneDevourer copy() {
|
||||
return new BoneDevourer(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -52,7 +52,7 @@ public final class BrightcapBadger extends AdventureCard {
|
|||
// Fungus Frolic
|
||||
// Create two 1/1 green Saproling creature tokens.
|
||||
this.getSpellCard().getSpellAbility().addEffect(new CreateTokenEffect(new SaprolingToken(), 2));
|
||||
this.getSpellCard().finalizeAdventure();
|
||||
this.finalizeAdventure();
|
||||
}
|
||||
|
||||
private BrightcapBadger(final BrightcapBadger card) {
|
||||
|
|
|
|||
76
Mage.Sets/src/mage/cards/b/BroodcallerScourge.java
Normal file
76
Mage.Sets/src/mage/cards/b/BroodcallerScourge.java
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.common.OneOrMoreDamagePlayerTriggeredAbility;
|
||||
import mage.abilities.effects.common.PutCardFromHandOntoBattlefieldEffect;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.common.FilterPermanentCard;
|
||||
import mage.filter.predicate.ObjectSourcePlayer;
|
||||
import mage.filter.predicate.ObjectSourcePlayerPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class BroodcallerScourge extends CardImpl {
|
||||
|
||||
private static final FilterCard filter
|
||||
= new FilterPermanentCard("a permanent card with mana value less than or equal to that damage");
|
||||
private static final FilterCreaturePermanent filter2 = new FilterCreaturePermanent(SubType.DRAGON, "Dragons");
|
||||
|
||||
static {
|
||||
filter.add(BroodcallerScourgePredicate.instance);
|
||||
}
|
||||
|
||||
public BroodcallerScourge(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{G}{G}");
|
||||
|
||||
this.subtype.add(SubType.DRAGON);
|
||||
this.power = new MageInt(5);
|
||||
this.toughness = new MageInt(7);
|
||||
|
||||
// Flying
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
|
||||
// Whenever one or more Dragons you control deal combat damage to a player, you may put a permanent card with mana value less than or equal to that damage from your hand onto the battlefield.
|
||||
this.addAbility(new OneOrMoreDamagePlayerTriggeredAbility(
|
||||
new PutCardFromHandOntoBattlefieldEffect(filter),
|
||||
filter2, true, true
|
||||
));
|
||||
}
|
||||
|
||||
private BroodcallerScourge(final BroodcallerScourge card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BroodcallerScourge copy() {
|
||||
return new BroodcallerScourge(this);
|
||||
}
|
||||
}
|
||||
|
||||
enum BroodcallerScourgePredicate implements ObjectSourcePlayerPredicate<Card> {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public boolean apply(ObjectSourcePlayer<Card> input, Game game) {
|
||||
return input
|
||||
.getObject()
|
||||
.getManaValue()
|
||||
<= CardUtil
|
||||
.getEffectValueFromAbility(
|
||||
input.getSource(), "damage",
|
||||
Integer.class, 0
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -59,7 +59,7 @@ enum CallerOfTheHuntAdjuster implements CostAdjuster {
|
|||
instance;
|
||||
|
||||
@Override
|
||||
public void adjustCosts(Ability ability, Game game) {
|
||||
public void prepareCost(Ability ability, Game game) {
|
||||
if (game.inCheckPlayableState()) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -103,6 +103,7 @@ enum CallerOfTheHuntAdjuster implements CostAdjuster {
|
|||
game.getState().setValue(sourceObject.getId() + "_type", maxSubType);
|
||||
} else {
|
||||
// human choose
|
||||
// TODO: need early target cost instead dialog here
|
||||
Effect effect = new ChooseCreatureTypeEffect(Outcome.Benefit);
|
||||
effect.apply(game, ability);
|
||||
}
|
||||
|
|
|
|||
83
Mage.Sets/src/mage/cards/c/CanopyGargantuan.java
Normal file
83
Mage.Sets/src/mage/cards/c/CanopyGargantuan.java
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
package mage.cards.c;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.abilities.keyword.WardAbility;
|
||||
import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.counters.CounterType;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class CanopyGargantuan extends CardImpl {
|
||||
|
||||
public CanopyGargantuan(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{G}{G}");
|
||||
|
||||
this.subtype.add(SubType.DRAGON);
|
||||
this.power = new MageInt(7);
|
||||
this.toughness = new MageInt(7);
|
||||
|
||||
// Flying
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
|
||||
// Ward {2}
|
||||
this.addAbility(new WardAbility(new ManaCostsImpl<>("{2}")));
|
||||
|
||||
// At the beginning of your upkeep, put a number of +1/+1 counters on each other creature you control equal to that creature's toughness.
|
||||
this.addAbility(new BeginningOfUpkeepTriggeredAbility(new CanopyGargantuanEffect()));
|
||||
}
|
||||
|
||||
private CanopyGargantuan(final CanopyGargantuan card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CanopyGargantuan copy() {
|
||||
return new CanopyGargantuan(this);
|
||||
}
|
||||
}
|
||||
|
||||
class CanopyGargantuanEffect extends OneShotEffect {
|
||||
|
||||
CanopyGargantuanEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "put a number of +1/+1 counters on each other creature you control equal to that creature's toughness";
|
||||
}
|
||||
|
||||
private CanopyGargantuanEffect(final CanopyGargantuanEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CanopyGargantuanEffect copy() {
|
||||
return new CanopyGargantuanEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
for (Permanent permanent : game.getBattlefield().getActivePermanents(
|
||||
StaticFilters.FILTER_OTHER_CONTROLLED_CREATURE,
|
||||
source.getControllerId(), source, game
|
||||
)) {
|
||||
int toughness = permanent.getToughness().getValue();
|
||||
if (toughness > 0) {
|
||||
permanent.addCounters(CounterType.P1P1.createInstance(toughness), source, game);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ import java.util.UUID;
|
|||
import mage.MageInt;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.CostImpl;
|
||||
import mage.abilities.triggers.BeginningOfCombatTriggeredAbility;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.Cost;
|
||||
|
|
@ -130,7 +131,7 @@ enum CaptainAmericaFirstAvengerValue implements DynamicValue {
|
|||
}
|
||||
}
|
||||
|
||||
class CaptainAmericaFirstAvengerUnattachCost extends EarlyTargetCost {
|
||||
class CaptainAmericaFirstAvengerUnattachCost extends CostImpl implements EarlyTargetCost {
|
||||
|
||||
private static final FilterPermanent filter = new FilterEquipmentPermanent("equipment attached to this creature");
|
||||
private static final FilterPermanent subfilter = new FilterControlledPermanent("{this}");
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ public final class CastleLocthwain extends CardImpl {
|
|||
Ability ability = new SimpleActivatedAbility(
|
||||
new DrawCardSourceControllerEffect(1).setText("draw a card,"), new ManaCostsImpl<>("{1}{B}{B}")
|
||||
);
|
||||
ability.addEffect(new LoseLifeSourceControllerEffect(CardsInControllerHandCount.instance)
|
||||
ability.addEffect(new LoseLifeSourceControllerEffect(CardsInControllerHandCount.ANY)
|
||||
.setText("then you lose life equal to the number of cards in your hand"));
|
||||
ability.addCost(new TapSourceCost());
|
||||
this.addAbility(ability);
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ public final class ChanneledForce extends CardImpl {
|
|||
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{U}{R}");
|
||||
|
||||
// As an additional cost to cast this spell, discard X cards.
|
||||
this.getSpellAbility().addCost(new DiscardXTargetCost(StaticFilters.FILTER_CARD_CARDS));
|
||||
this.getSpellAbility().addCost(new DiscardXTargetCost(StaticFilters.FILTER_CARD_CARDS, true));
|
||||
|
||||
// Target player draws X cards. Channeled Force deals X damage to up to one target creature or planeswalker.
|
||||
this.getSpellAbility().addEffect(new ChanneledForceEffect());
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ public final class ChitinGravestalker extends CardImpl {
|
|||
}
|
||||
|
||||
private static final DynamicValue xValue = new CardsInControllerGraveyardCount(filter);
|
||||
private static final Hint hint = new ValueHint("Instant and sorcery card in your graveyard", xValue);
|
||||
private static final Hint hint = new ValueHint("Artifact and/or creature cards in your graveyard", xValue);
|
||||
|
||||
public ChitinGravestalker(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{B}");
|
||||
|
|
|
|||
|
|
@ -1,23 +1,20 @@
|
|||
|
||||
package mage.cards.c;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.triggers.BeginningOfCombatTriggeredAbility;
|
||||
import mage.abilities.common.EntersBattlefieldAbility;
|
||||
import mage.abilities.condition.common.ModeChoiceSourceCondition;
|
||||
import mage.abilities.decorator.ConditionalTriggeredAbility;
|
||||
import mage.abilities.common.AsEntersBattlefieldAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.common.ChooseModeEffect;
|
||||
import mage.abilities.effects.common.TapTargetEffect;
|
||||
import mage.abilities.effects.common.continuous.GainAnchorWordAbilitySourceEffect;
|
||||
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
|
||||
import mage.abilities.triggers.BeginningOfCombatTriggeredAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.ModeChoice;
|
||||
import mage.constants.TargetController;
|
||||
import mage.counters.CounterType;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.predicate.Predicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.common.TargetControlledCreaturePermanent;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
|
||||
|
|
@ -28,36 +25,29 @@ import java.util.UUID;
|
|||
*/
|
||||
public final class CitadelSiege extends CardImpl {
|
||||
|
||||
private static final String ruleTrigger1 = "&bull Khans — At the beginning of combat on your turn, put two +1/+1 counters on target creature you control.";
|
||||
private static final String ruleTrigger2 = "&bull Dragons — At the beginning of combat on each opponent's turn, tap target creature that player controls.";
|
||||
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature controlled by the active player");
|
||||
|
||||
static {
|
||||
filter.add(CitadelSiegePredicate.instance);
|
||||
filter.add(TargetController.ACTIVE.getControllerPredicate());
|
||||
}
|
||||
|
||||
public CitadelSiege(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}{W}");
|
||||
|
||||
// As Citadel Siege enters the battlefield, choose Khans or Dragons.
|
||||
this.addAbility(new EntersBattlefieldAbility(new ChooseModeEffect("Khans or Dragons?", "Khans", "Dragons"), null,
|
||||
"As {this} enters, choose Khans or Dragons.", ""));
|
||||
this.addAbility(new AsEntersBattlefieldAbility(new ChooseModeEffect(ModeChoice.KHANS, ModeChoice.DRAGONS)));
|
||||
|
||||
// * Khans - At the beginning of combat on your turn, put two +1/+1 counters on target creature you control.
|
||||
Ability ability = new ConditionalTriggeredAbility(
|
||||
new BeginningOfCombatTriggeredAbility(new AddCountersTargetEffect(CounterType.P1P1.createInstance(2))),
|
||||
new ModeChoiceSourceCondition("Khans"),
|
||||
ruleTrigger1);
|
||||
Ability ability = new BeginningOfCombatTriggeredAbility(new AddCountersTargetEffect(CounterType.P1P1.createInstance(2)));
|
||||
ability.addTarget(new TargetControlledCreaturePermanent());
|
||||
this.addAbility(ability);
|
||||
this.addAbility(new SimpleStaticAbility(new GainAnchorWordAbilitySourceEffect(ability, ModeChoice.KHANS)));
|
||||
|
||||
// * Dragons - At the beginning of combat on each opponent's turn, tap target creature that player controls.
|
||||
ability = new ConditionalTriggeredAbility(
|
||||
new BeginningOfCombatTriggeredAbility(TargetController.OPPONENT, new TapTargetEffect(), false),
|
||||
new ModeChoiceSourceCondition("Dragons"),
|
||||
ruleTrigger2);
|
||||
ability = new BeginningOfCombatTriggeredAbility(
|
||||
TargetController.OPPONENT, new TapTargetEffect("tap target creature that player controls"), false
|
||||
);
|
||||
ability.addTarget(new TargetCreaturePermanent(filter));
|
||||
this.addAbility(ability);
|
||||
this.addAbility(new SimpleStaticAbility(new GainAnchorWordAbilitySourceEffect(ability, ModeChoice.DRAGONS)));
|
||||
}
|
||||
|
||||
private CitadelSiege(final CitadelSiege card) {
|
||||
|
|
@ -69,12 +59,3 @@ public final class CitadelSiege extends CardImpl {
|
|||
return new CitadelSiege(this);
|
||||
}
|
||||
}
|
||||
|
||||
enum CitadelSiegePredicate implements Predicate<Permanent> {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public boolean apply(Permanent input, Game game) {
|
||||
return input.getControllerId().equals(game.getActivePlayerId());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
72
Mage.Sets/src/mage/cards/c/ClarionConqueror.java
Normal file
72
Mage.Sets/src/mage/cards/c/ClarionConqueror.java
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
package mage.cards.c;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.RestrictionEffect;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.SubType;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class ClarionConqueror extends CardImpl {
|
||||
|
||||
public ClarionConqueror(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}");
|
||||
|
||||
this.subtype.add(SubType.DRAGON);
|
||||
this.power = new MageInt(3);
|
||||
this.toughness = new MageInt(3);
|
||||
|
||||
// Flying
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
|
||||
// Activated abilities of artifacts, creatures, and planeswalkers can't be activated.
|
||||
this.addAbility(new SimpleStaticAbility(new ClarionConquerorEffect()));
|
||||
}
|
||||
|
||||
private ClarionConqueror(final ClarionConqueror card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClarionConqueror copy() {
|
||||
return new ClarionConqueror(this);
|
||||
}
|
||||
}
|
||||
|
||||
class ClarionConquerorEffect extends RestrictionEffect {
|
||||
|
||||
ClarionConquerorEffect() {
|
||||
super(Duration.WhileOnBattlefield);
|
||||
staticText = "activated abilities of artifacts, creatures, and planeswalkers can't be activated";
|
||||
}
|
||||
|
||||
private ClarionConquerorEffect(final ClarionConquerorEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(Permanent permanent, Ability source, Game game) {
|
||||
return permanent.isArtifact(game) || permanent.isCreature(game) || permanent.isPlaneswalker(game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUseActivatedAbilities(Permanent permanent, Ability source, Game game, boolean canUseChooseDialogs) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClarionConquerorEffect copy() {
|
||||
return new ClarionConquerorEffect(this);
|
||||
}
|
||||
}
|
||||
164
Mage.Sets/src/mage/cards/c/ColossalGraveReaver.java
Normal file
164
Mage.Sets/src/mage/cards/c/ColossalGraveReaver.java
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
package mage.cards.c;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.BatchTriggeredAbility;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.common.EntersBattlefieldOrAttacksSourceTriggeredAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.MillCardsControllerEffect;
|
||||
import mage.cards.*;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.ZoneChangeBatchEvent;
|
||||
import mage.game.events.ZoneChangeEvent;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetCard;
|
||||
import mage.target.targetpointer.FixedTargets;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Grath
|
||||
*/
|
||||
public final class ColossalGraveReaver extends CardImpl {
|
||||
|
||||
public ColossalGraveReaver(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{6}{B}{G}");
|
||||
|
||||
this.subtype.add(SubType.DRAGON);
|
||||
this.power = new MageInt(7);
|
||||
this.toughness = new MageInt(6);
|
||||
|
||||
// Flying
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
|
||||
// Whenever this creature enters or attacks, mill three cards.
|
||||
this.addAbility(new EntersBattlefieldOrAttacksSourceTriggeredAbility(new MillCardsControllerEffect(3)));
|
||||
|
||||
// Whenever one or more creature cards are put into your graveyard from your library, put one of them onto the battlefield.
|
||||
this.addAbility(new ColossalGraveReaverTriggeredAbility());
|
||||
}
|
||||
|
||||
private ColossalGraveReaver(final ColossalGraveReaver card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ColossalGraveReaver copy() {
|
||||
return new ColossalGraveReaver(this);
|
||||
}
|
||||
}
|
||||
|
||||
class ColossalGraveReaverEffect extends OneShotEffect {
|
||||
|
||||
private static final FilterCard defaultFilter = new FilterCard("creature to return to battlefield");
|
||||
|
||||
public ColossalGraveReaverEffect() {
|
||||
super(Outcome.PutCreatureInPlay);
|
||||
staticText = "put one of them onto the battlefield";
|
||||
}
|
||||
|
||||
protected ColossalGraveReaverEffect(final ColossalGraveReaverEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ColossalGraveReaverEffect copy() {
|
||||
return new ColossalGraveReaverEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null) {
|
||||
Cards cardsToChooseFrom = new CardsImpl();
|
||||
for (UUID targetId : getTargetPointer().getTargets(game, source)) {
|
||||
Card card = game.getCard(targetId);
|
||||
if (card != null && game.getState().getZone(card.getId()) == Zone.GRAVEYARD) {
|
||||
cardsToChooseFrom.add(card);
|
||||
}
|
||||
}
|
||||
Set<Card> cardsToMove;
|
||||
switch (cardsToChooseFrom.size()) {
|
||||
case 0:
|
||||
return false;
|
||||
case 1:
|
||||
cardsToMove = new HashSet<>(cardsToChooseFrom.getCards(game));
|
||||
break;
|
||||
default:
|
||||
cardsToMove = new HashSet<>();
|
||||
TargetCard target = new TargetCard(1, 1, Zone.ALL, defaultFilter);
|
||||
target.withNotTarget(true);
|
||||
controller.choose(Outcome.PlayForFree, cardsToChooseFrom, target, source, game);
|
||||
cardsToMove.add(cardsToChooseFrom.get(target.getFirstTarget(), game));
|
||||
|
||||
}
|
||||
controller.moveCards(cardsToMove, Zone.BATTLEFIELD, source, game, false, false, false, null);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class ColossalGraveReaverTriggeredAbility extends TriggeredAbilityImpl implements BatchTriggeredAbility<ZoneChangeEvent> {
|
||||
|
||||
ColossalGraveReaverTriggeredAbility() {
|
||||
super(Zone.BATTLEFIELD, new ColossalGraveReaverEffect());
|
||||
}
|
||||
|
||||
private ColossalGraveReaverTriggeredAbility(final ColossalGraveReaverTriggeredAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ColossalGraveReaverTriggeredAbility copy() {
|
||||
return new ColossalGraveReaverTriggeredAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.ZONE_CHANGE_BATCH;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEvent(ZoneChangeEvent event, Game game) {
|
||||
if (event.getFromZone() != Zone.LIBRARY || event.getToZone() != Zone.GRAVEYARD) {
|
||||
return false;
|
||||
}
|
||||
Card card = game.getCard(event.getTargetId());
|
||||
return card != null && card.isCreature(game) && card.isOwnedBy(getControllerId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
Set<Card> set = getFilteredEvents((ZoneChangeBatchEvent) event, game)
|
||||
.stream()
|
||||
.map(ZoneChangeEvent::getTargetId)
|
||||
.map(game::getCard)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toSet());
|
||||
if (set.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
this.getEffects().setTargetPointer(new FixedTargets(set, game));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "Whenever one or more creature cards are put into your graveyard " +
|
||||
"from your library, put one of them onto the battlefield tapped.";
|
||||
}
|
||||
}
|
||||
|
|
@ -72,7 +72,7 @@ enum CrownOfGondorAdjuster implements CostAdjuster {
|
|||
instance;
|
||||
|
||||
@Override
|
||||
public void adjustCosts(Ability ability, Game game) {
|
||||
public void reduceCost(Ability ability, Game game) {
|
||||
if (MonarchIsSourceControllerCondition.instance.apply(game, ability)) {
|
||||
CardUtil.reduceCost(ability, 3);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ import mage.constants.CardType;
|
|||
import mage.constants.SubType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.constants.TargetController;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
|
||||
|
|
@ -59,7 +58,7 @@ public final class DamiaSageOfStone extends CardImpl {
|
|||
class DamiaSageOfStoneTriggeredAbility extends BeginningOfUpkeepTriggeredAbility {
|
||||
|
||||
DamiaSageOfStoneTriggeredAbility() {
|
||||
super(TargetController.YOU, new DrawCardSourceControllerEffect(new IntPlusDynamicValue(7, new MultipliedValue(CardsInControllerHandCount.instance, -1))), false);
|
||||
super(TargetController.YOU, new DrawCardSourceControllerEffect(new IntPlusDynamicValue(7, new MultipliedValue(CardsInControllerHandCount.ANY, -1))), false);
|
||||
}
|
||||
|
||||
private DamiaSageOfStoneTriggeredAbility(final DamiaSageOfStoneTriggeredAbility ability) {
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ enum IsBeingCastFromHandCondition implements Condition {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
MageObject object = game.getObject(source);
|
||||
if (object instanceof SplitCardHalf || object instanceof AdventureCardSpell || object instanceof ModalDoubleFacedCardHalf) {
|
||||
if (object instanceof SplitCardHalf || object instanceof SpellOptionCard || object instanceof ModalDoubleFacedCardHalf) {
|
||||
UUID mainCardId = ((Card) object).getMainCard().getId();
|
||||
object = game.getObject(mainCardId);
|
||||
}
|
||||
|
|
|
|||
83
Mage.Sets/src/mage/cards/d/DeathBegetsLife.java
Normal file
83
Mage.Sets/src/mage/cards/d/DeathBegetsLife.java
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
package mage.cards.d;
|
||||
|
||||
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.FilterPermanent;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author androosss
|
||||
*/
|
||||
public final class DeathBegetsLife extends CardImpl {
|
||||
|
||||
public DeathBegetsLife(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[] { CardType.SORCERY }, "{5}{B}{G}{U}");
|
||||
|
||||
// Destroy all creatures and enchantments. Draw a card for each permanent
|
||||
// destroyed this way.
|
||||
this.getSpellAbility().addEffect(new DeathBegetsLifeEffect());
|
||||
}
|
||||
|
||||
private DeathBegetsLife(final DeathBegetsLife card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeathBegetsLife copy() {
|
||||
return new DeathBegetsLife(this);
|
||||
}
|
||||
}
|
||||
|
||||
class DeathBegetsLifeEffect extends OneShotEffect {
|
||||
|
||||
private static final FilterPermanent filter = new FilterPermanent("creature or enchantment");
|
||||
static {
|
||||
filter.add(Predicates.or(
|
||||
CardType.CREATURE.getPredicate(),
|
||||
CardType.ENCHANTMENT.getPredicate()));
|
||||
}
|
||||
|
||||
DeathBegetsLifeEffect() {
|
||||
super(Outcome.DestroyPermanent);
|
||||
this.staticText = "Destroy all creatures and enchantments. Draw a card for each permanent destroyed this way";
|
||||
}
|
||||
|
||||
private DeathBegetsLifeEffect(final DeathBegetsLifeEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeathBegetsLifeEffect copy() {
|
||||
return new DeathBegetsLifeEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null) {
|
||||
int destroyedPermanent = 0;
|
||||
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter,
|
||||
controller.getId(), game)) {
|
||||
if (permanent.destroy(source, game)) {
|
||||
destroyedPermanent++;
|
||||
}
|
||||
}
|
||||
if (destroyedPermanent > 0) {
|
||||
game.processAction();
|
||||
controller.drawCards(destroyedPermanent, source, game);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
74
Mage.Sets/src/mage/cards/d/DeceptiveFrostkite.java
Normal file
74
Mage.Sets/src/mage/cards/d/DeceptiveFrostkite.java
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
package mage.cards.d;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.EntersBattlefieldEffect;
|
||||
import mage.abilities.effects.common.CopyPermanentEffect;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.ComparisonType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.common.FilterControlledCreaturePermanent;
|
||||
import mage.filter.predicate.mageobject.PowerPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.util.functions.CopyApplier;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class DeceptiveFrostkite extends CardImpl {
|
||||
|
||||
private static final FilterPermanent filter
|
||||
= new FilterControlledCreaturePermanent("a creature you control with power 4 or greater");
|
||||
|
||||
static {
|
||||
filter.add(new PowerPredicate(ComparisonType.MORE_THAN, 3));
|
||||
}
|
||||
|
||||
private static final CopyApplier applier = new CopyApplier() {
|
||||
@Override
|
||||
public boolean apply(Game game, MageObject blueprint, Ability source, UUID copyToObjectId) {
|
||||
blueprint.addSubType(SubType.DRAGON);
|
||||
blueprint.getAbilities().add(FlyingAbility.getInstance());
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
public DeceptiveFrostkite(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{U}{U}");
|
||||
|
||||
this.subtype.add(SubType.DRAGON);
|
||||
this.power = new MageInt(1);
|
||||
this.toughness = new MageInt(1);
|
||||
|
||||
// Flying
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
|
||||
// You may have this creature enter as a copy of a creature you control with power 4 or greater, except it's a Dragon in addition to its other types and it has flying.
|
||||
this.addAbility(new SimpleStaticAbility(
|
||||
Zone.ALL,
|
||||
new EntersBattlefieldEffect(
|
||||
new CopyPermanentEffect(filter, applier), "you may have this creature enter " +
|
||||
"as a copy of a creature you control with power 4 or greater, " +
|
||||
"except it's a Dragon in addition to its other types and it has flying", true
|
||||
)
|
||||
));
|
||||
}
|
||||
|
||||
private DeceptiveFrostkite(final DeceptiveFrostkite card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeceptiveFrostkite copy() {
|
||||
return new DeceptiveFrostkite(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -62,7 +62,7 @@ enum DeepwoodDenizenAdjuster implements CostAdjuster {
|
|||
instance;
|
||||
|
||||
@Override
|
||||
public void adjustCosts(Ability ability, Game game) {
|
||||
public void reduceCost(Ability ability, Game game) {
|
||||
CardUtil.reduceCost(ability, DeepwoodDenizenValue.instance.calculate(game, ability, null));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package mage.cards.d;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.PreventionEffectData;
|
||||
import mage.abilities.effects.PreventionEffectImpl;
|
||||
|
|
@ -11,8 +10,6 @@ import mage.constants.Duration;
|
|||
import mage.constants.Outcome;
|
||||
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;
|
||||
|
||||
|
|
@ -44,9 +41,11 @@ class DeflectingPalmEffect extends PreventionEffectImpl {
|
|||
|
||||
private final TargetSource target;
|
||||
|
||||
public DeflectingPalmEffect() {
|
||||
DeflectingPalmEffect() {
|
||||
super(Duration.EndOfTurn, Integer.MAX_VALUE, false, false);
|
||||
this.staticText = "The next time a source of your choice would deal damage to you this turn, prevent that damage. If damage is prevented this way, {this} deals that much damage to that source's controller";
|
||||
this.staticText = "the next time a source of your choice would deal damage to you this turn, " +
|
||||
"prevent that damage. If damage is prevented this way, " +
|
||||
"{this} deals that much damage to that source's controller";
|
||||
this.target = new TargetSource();
|
||||
}
|
||||
|
||||
|
|
@ -71,31 +70,23 @@ class DeflectingPalmEffect extends PreventionEffectImpl {
|
|||
PreventionEffectData preventionData = preventDamageAction(event, source, game);
|
||||
this.used = true;
|
||||
this.discard(); // only one use
|
||||
if (preventionData.getPreventedDamage() > 0) {
|
||||
MageObject damageDealingObject = game.getObject(target.getFirstTarget());
|
||||
UUID objectControllerId = null;
|
||||
if (damageDealingObject instanceof Permanent) {
|
||||
objectControllerId = ((Permanent) damageDealingObject).getControllerId();
|
||||
} else if (damageDealingObject instanceof Ability) {
|
||||
objectControllerId = ((Ability) damageDealingObject).getControllerId();
|
||||
} else if (damageDealingObject instanceof Spell) {
|
||||
objectControllerId = ((Spell) damageDealingObject).getControllerId();
|
||||
}
|
||||
if (objectControllerId != null) {
|
||||
Player objectController = game.getPlayer(objectControllerId);
|
||||
if (objectController != null) {
|
||||
objectController.damage(preventionData.getPreventedDamage(), source.getSourceId(), source, game);
|
||||
}
|
||||
}
|
||||
if (preventionData.getPreventedDamage() < 1) {
|
||||
return true;
|
||||
}
|
||||
UUID objectControllerId = game.getControllerId(target.getFirstTarget());
|
||||
Player objectController = game.getPlayer(objectControllerId);
|
||||
if (objectController == null) {
|
||||
return true;
|
||||
}
|
||||
objectController.damage(preventionData.getPreventedDamage(), source.getSourceId(), source, game);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if (!this.used && super.applies(event, source, game)) {
|
||||
return event.getTargetId().equals(source.getControllerId()) && event.getSourceId().equals(target.getFirstTarget());
|
||||
}
|
||||
return false;
|
||||
return !this.used
|
||||
&& super.applies(event, source, game)
|
||||
&& event.getTargetId().equals(source.getControllerId())
|
||||
&& event.getSourceId().equals(target.getFirstTarget());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ class DelayEffect extends OneShotEffect {
|
|||
if (controller != null && spell != null) {
|
||||
Effect effect = new CounterTargetWithReplacementEffect(PutCards.EXILED);
|
||||
effect.setTargetPointer(this.getTargetPointer().copy());
|
||||
Card card = game.getCard(spell.getSourceId());
|
||||
Card card = spell.getMainCard();
|
||||
if (card != null && effect.apply(game, source) && game.getState().getZone(card.getId()) == Zone.EXILED) {
|
||||
boolean hasSuspend = card.getAbilities(game).containsClass(SuspendAbility.class);
|
||||
UUID exileId = SuspendAbility.getSuspendExileId(controller.getId(), game);
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import java.util.UUID;
|
|||
*/
|
||||
public final class DemonicLore extends CardImpl {
|
||||
|
||||
private static final DynamicValue xValue = new MultipliedValue(CardsInControllerHandCount.instance, 2);
|
||||
private static final DynamicValue xValue = new MultipliedValue(CardsInControllerHandCount.ANY, 2);
|
||||
|
||||
public DemonicLore(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{B}");
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ import mage.cards.CardImpl;
|
|||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
@ -28,7 +27,7 @@ public final class DescendantOfSoramaro extends CardImpl {
|
|||
this.power = new MageInt(2);
|
||||
this.toughness = new MageInt(3);
|
||||
// {1}{U}: Look at the top X cards of your library, where X is the number of cards in your hand, then put them back in any order.
|
||||
Effect effect = new LookLibraryControllerEffect(CardsInControllerHandCount.instance);
|
||||
Effect effect = new LookLibraryControllerEffect(CardsInControllerHandCount.ANY);
|
||||
effect.setText("Look at the top X cards of your library, where X is the number of cards in your hand, then put them back in any order");
|
||||
this.addAbility(new SimpleActivatedAbility(
|
||||
effect, new ManaCostsImpl<>("{1}{U}")));
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ import mage.abilities.costs.Cost;
|
|||
import mage.abilities.costs.VariableCostImpl;
|
||||
import mage.abilities.costs.VariableCostType;
|
||||
import mage.abilities.costs.common.DiscardTargetCost;
|
||||
import mage.abilities.costs.common.DiscardXTargetCost;
|
||||
import mage.abilities.costs.costadjusters.DiscardXCardsCostAdjuster;
|
||||
import mage.abilities.dynamicvalue.common.GetXValue;
|
||||
import mage.abilities.effects.common.DamageAllEffect;
|
||||
import mage.abilities.effects.common.SacrificeAllEffect;
|
||||
|
|
@ -12,6 +14,7 @@ import mage.cards.CardImpl;
|
|||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.filter.common.FilterControlledLandPermanent;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.game.Game;
|
||||
|
|
@ -28,8 +31,8 @@ public final class DevastatingDreams extends CardImpl {
|
|||
public DevastatingDreams(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{R}{R}");
|
||||
|
||||
// As an additional cost to cast Devastating Dreams, discard X cards at random.
|
||||
this.getSpellAbility().addCost(new DevastatingDreamsAdditionalCost());
|
||||
// As an additional cost to cast this spell, discard X cards at random.
|
||||
this.getSpellAbility().addCost(new DiscardXTargetCost(StaticFilters.FILTER_CARD_CARDS, true).withRandom());
|
||||
|
||||
// Each player sacrifices X lands.
|
||||
this.getSpellAbility().addEffect(new SacrificeAllEffect(GetXValue.instance, new FilterControlledLandPermanent("lands")));
|
||||
|
|
|
|||
52
Mage.Sets/src/mage/cards/d/DirgurIslandDragon.java
Normal file
52
Mage.Sets/src/mage/cards/d/DirgurIslandDragon.java
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
package mage.cards.d;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
||||
import mage.abilities.effects.common.TapTargetEffect;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.abilities.keyword.WardAbility;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.cards.OmenCard;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Jmlundeen
|
||||
*/
|
||||
public final class DirgurIslandDragon extends OmenCard {
|
||||
|
||||
public DirgurIslandDragon(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, new CardType[]{CardType.INSTANT}, "{5}{U}", "Skimming Strike", "{1}{U}");
|
||||
|
||||
this.subtype.add(SubType.DRAGON);
|
||||
this.power = new MageInt(4);
|
||||
this.toughness = new MageInt(4);
|
||||
|
||||
// Flying
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
|
||||
// Ward {2}
|
||||
this.addAbility(new WardAbility(new ManaCostsImpl<>("{2}")));
|
||||
|
||||
// Skimming Strike
|
||||
// Tap up to one target creature. Draw a card.
|
||||
this.getSpellCard().getSpellAbility().addEffect(new TapTargetEffect());
|
||||
this.getSpellCard().getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1));
|
||||
this.getSpellCard().getSpellAbility().addTarget(new TargetCreaturePermanent(0, 1));
|
||||
this.finalizeOmen();
|
||||
}
|
||||
|
||||
private DirgurIslandDragon(final DirgurIslandDragon card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DirgurIslandDragon copy() {
|
||||
return new DirgurIslandDragon(this);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue